Skip to content

Commit 17402a8

Browse files
author
John Mertic
committed
Release 6.3.0
1 parent 47ac7b4 commit 17402a8

File tree

650 files changed

+40726
-15608
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

650 files changed

+40726
-15608
lines changed

ModuleInstall/ModuleInstaller.php

Lines changed: 492 additions & 610 deletions
Large diffs are not rendered by default.

ModuleInstall/ModuleScanner.php

Lines changed: 97 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<?php
1+
<?php
22
if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
33
/*********************************************************************************
44
* SugarCRM Community Edition is a customer relationship management program developed by
@@ -53,11 +53,11 @@ class ModuleScanner{
5353
'install_languages'=>'language',
5454
'install_logichooks'=>'logic_hooks',
5555
'post_execute'=>'post_execute',
56-
56+
5757
);
58-
58+
5959
private $blackListExempt = array();
60-
60+
6161
private $validExt = array('png', 'gif', 'jpg', 'css', 'js', 'php', 'txt', 'html', 'htm', 'tpl', 'pdf', 'md5', 'xml');
6262
private $blackList = array(
6363
'popen',
@@ -120,9 +120,9 @@ class ModuleScanner{
120120
'exec',
121121
'system',
122122
'shell_exec',
123-
'passthru',
123+
'passthru',
124124
'chgrp',
125-
'chmod',
125+
'chmod',
126126
'chwown',
127127
'file_put_contents',
128128
'file',
@@ -133,7 +133,7 @@ class ModuleScanner{
133133
'filemtime',
134134
'fileowner',
135135
'fileperms',
136-
'fopen',
136+
'fopen',
137137
'is_executable',
138138
'is_writable',
139139
'is_writeable',
@@ -152,7 +152,7 @@ class ModuleScanner{
152152
'call_user_func',
153153
'call_user_func_array',
154154
'create_function',
155-
155+
156156

157157
//mutliple files per function call
158158
'copy',
@@ -182,14 +182,14 @@ public function printToWiki(){
182182
echo "'''Default Extensions'''<br>";
183183
foreach($this->validExt as $b){
184184
echo '#' . $b . '<br>';
185-
185+
186186
}
187187
echo "'''Default Black Listed Functions'''<br>";
188188
foreach($this->blackList as $b){
189189
echo '#' . $b . '<br>';
190-
190+
191191
}
192-
192+
193193
}
194194

195195
public function __construct(){
@@ -202,42 +202,42 @@ public function __construct(){
202202
if(!empty($GLOBALS['sugar_config']['moduleInstaller']['validExt'])){
203203
$this->validExt = array_merge($this->validExt, $GLOBALS['sugar_config']['moduleInstaller']['validExt']);
204204
}
205-
205+
206206
}
207207

208208
private $issues = array();
209209
private $pathToModule = '';
210-
210+
211211
/**
212212
*returns a list of issues
213213
*/
214214
public function getIssues(){
215215
return $this->issues;
216216
}
217-
217+
218218
/**
219219
*returns true or false if any issues were found
220220
*/
221221
public function hasIssues(){
222222
return !empty($this->issues);
223223
}
224-
224+
225225
/**
226226
*Ensures that a file has a valid extension
227227
*/
228228
private function isValidExtension($file){
229229
$file = strtolower($file);
230-
230+
231231
$extPos = strrpos($file, '.');
232232
//make sure they don't override the files.md5
233233
if($extPos === false || $file == 'files.md5')return false;
234234
$ext = substr($file, $extPos + 1);
235235
return in_array($ext, $this->validExt);
236-
236+
237237
}
238-
238+
239239
/**
240-
*Scans a directory and calls on scan file for each file
240+
*Scans a directory and calls on scan file for each file
241241
**/
242242
public function scanDir($path){
243243
static $startPath = '';
@@ -249,21 +249,40 @@ public function scanDir($path){
249249
if(is_dir($next)){
250250
if(substr($e, 0, 1) == '.')continue;
251251
$this->scanDir($next);
252-
}else{
252+
}else{
253253
$issues = $this->scanFile($next);
254-
255-
254+
255+
256256
}
257257
}
258258
return true;
259259
}
260-
261-
260+
261+
/**
262+
* Check if the file contents looks like PHP
263+
* @param string $contents File contents
264+
* @return boolean
265+
*/
266+
protected function isPHPFile($contents)
267+
{
268+
if(stripos($contents, '<?php') !== false) return true;
269+
for($tag=0;($tag = stripos($contents, '<?', $tag)) !== false;$tag++) {
270+
if(strncasecmp(substr($contents, $tag, 13), '<?xml version', 13)) {
271+
// <?xml version is OK, skip it
272+
$tag++;
273+
continue;
274+
}
275+
// found <?, it's PHP
276+
return true;
277+
}
278+
return false;
279+
}
280+
262281
/**
263-
* Given a file it will open it's contents and check if it is a PHP file (not safe to just rely on extensions) if it finds <?php tags it will use the tokenizer to scan the file
264-
* $var() and ` are always prevented then whatever is in the blacklist.
282+
* Given a file it will open it's contents and check if it is a PHP file (not safe to just rely on extensions) if it finds <?php tags it will use the tokenizer to scan the file
283+
* $var() and ` are always prevented then whatever is in the blacklist.
265284
* It will also ensure that all files are of valid extension types
266-
*
285+
*
267286
*/
268287
public function scanFile($file){
269288
$issues = array();
@@ -273,8 +292,8 @@ public function scanFile($file){
273292
return $issues;
274293
}
275294
$contents = file_get_contents($file);
276-
if(stripos($contents,'<?php') === false )return $issues;
277-
$tokens = token_get_all($contents);
295+
if(!$this->isPHPFile($contents)) return $issues;
296+
$tokens = @token_get_all($contents);
278297
$checkFunction = false;
279298
$possibleIssue = '';
280299
$lastToken = false;
@@ -285,7 +304,7 @@ public function scanFile($file){
285304
$issues['backtick'] = translate('ML_INVALID_FUNCTION') . " '`'";
286305
case '(':
287306
if($checkFunction)$issues[] = $possibleIssue;
288-
break;
307+
break;
289308
}
290309
$checkFunction = false;
291310
$possibleIssue = '';
@@ -301,16 +320,16 @@ public function scanFile($file){
301320
$token[1] = strtolower($token[1]);
302321
if(!in_array($token[1], $this->blackList))break;
303322
if(in_array($token[1], $this->blackListExempt))break;
304-
if ($lastToken !== false &&
305-
($lastToken[0] == T_NEW || $lastToken[0] == T_OBJECT_OPERATOR || $lastToken[0] == T_DOUBLE_COLON))
323+
if ($lastToken !== false &&
324+
($lastToken[0] == T_NEW || $lastToken[0] == T_OBJECT_OPERATOR || $lastToken[0] == T_DOUBLE_COLON))
306325
{
307326
break;
308327
}
309328
case T_VARIABLE:
310329
$checkFunction = true;
311330
$possibleIssue = translate('ML_INVALID_FUNCTION') . ' ' . $token[1] . '()';
312331
break;
313-
332+
314333
default:
315334
$checkFunction = false;
316335
$possibleIssue = '';
@@ -321,18 +340,18 @@ public function scanFile($file){
321340
$lastToken = $token;
322341
}
323342
}
324-
343+
325344
}
326345
if(!empty($issues)){
327346
$this->issues['file'][$file] = $issues;
328347
}
329-
330-
return $issues;
348+
349+
return $issues;
331350
}
332-
333-
351+
352+
334353
/*
335-
* checks files.md5 file to see if the file is from sugar
354+
* checks files.md5 file to see if the file is from sugar
336355
* ONLY WORKS ON FILES
337356
*/
338357
public function sugarFileExists($path){
@@ -343,11 +362,11 @@ public function sugarFileExists($path){
343362
$md5 = $md5_string;
344363
}
345364
if(isset($md5['./' . $path]))return true;
346-
347-
365+
366+
348367
}
349-
350-
368+
369+
351370
/**
352371
*This function will scan the Manifest for disabled actions specified in $GLOBALS['sugar_config']['moduleInstaller']['disableActions']
353372
*if $GLOBALS['sugar_config']['moduleInstaller']['disableRestrictedCopy'] is set to false or not set it will call on scanCopy to ensure that it is not overriding files
@@ -364,18 +383,18 @@ public function scanManifest($manifestPath){
364383
return $fileIssues;
365384
}
366385
include($manifestPath);
367-
368-
369-
//scan for disabled actions
386+
387+
388+
//scan for disabled actions
370389
if(isset($GLOBALS['sugar_config']['moduleInstaller']['disableActions'])){
371390
foreach($GLOBALS['sugar_config']['moduleInstaller']['disableActions'] as $action){
372391
if(isset($installdefs[$this->manifestMap[$action]])){
373392
$issues[] = translate('ML_INVALID_ACTION_IN_MANIFEST') . $this->manifestMap[$action];
374393
}
375394
}
376395
}
377-
378-
//now lets scan for files that will override our files
396+
397+
//now lets scan for files that will override our files
379398
if(empty($GLOBALS['sugar_config']['moduleInstaller']['disableRestrictedCopy']) && isset($installdefs['copy'])){
380399
foreach($installdefs['copy'] as $copy){
381400
$from = str_replace('<basepath>', $this->pathToModule, $copy['from']);
@@ -391,25 +410,25 @@ public function scanManifest($manifestPath){
391410
}
392411
while(substr_count($to, '//')){
393412
$to = str_replace('//', '/', $to);
394-
}
413+
}
395414
$this->scanCopy($from, $to);
396415
}
397416
}
398417
if(!empty($issues)){
399418
$this->issues['manifest'][$manifestPath] = $issues;
400419
}
401-
402-
403-
420+
421+
422+
404423
}
405-
406-
424+
425+
407426

408427
/**
409-
* Takes in where the file will is specified to be copied from and to
410-
* and ensures that there is no official sugar file there. If the file exists it will check
428+
* Takes in where the file will is specified to be copied from and to
429+
* and ensures that there is no official sugar file there. If the file exists it will check
411430
* against the MD5 file list to see if Sugar Created the file
412-
*
431+
*
413432
*/
414433
function scanCopy($from, $to){
415434
//if the file doesn't exist for the $to then it is not overriding anything
@@ -421,28 +440,28 @@ function scanCopy($from, $to){
421440
}
422441
$to .= '/'. basename($from);
423442
}
424-
//if the $to is a file and it is found in sugarFileExists then don't allow overriding it
443+
//if the $to is a file and it is found in sugarFileExists then don't allow overriding it
425444
if(is_file($to) && $this->sugarFileExists($to)){
426445
$this->issues['copy'][$from] = translate('ML_OVERRIDE_CORE_FILES') . '(' . $to . ')';
427446
}
428-
447+
429448
if(is_dir($from)){
430449
$d = dir($from);
431450
while($e = $d->read()){
432451
if($e == '.' || $e == '..')continue;
433-
$this->scanCopy($from .'/'. $e, $to .'/' . $e);
452+
$this->scanCopy($from .'/'. $e, $to .'/' . $e);
434453
}
435454
}
436-
437-
438-
439-
440-
455+
456+
457+
458+
459+
441460
}
442-
443-
461+
462+
444463
/**
445-
*Main external function that takes in a path to a package and then scans
464+
*Main external function that takes in a path to a package and then scans
446465
*that package's manifest for disabled actions and then it scans the PHP files
447466
*for restricted function calls
448467
*
@@ -454,22 +473,22 @@ public function scanPackage($path){
454473
$this->scanDir($path);
455474
}
456475
}
457-
476+
458477
/**
459-
*This function will take all issues of the current instance and print them to the screen
478+
*This function will take all issues of the current instance and print them to the screen
460479
**/
461480
public function displayIssues($package='Package'){
462-
echo '<h2>'.str_replace('{PACKAGE}' , $package ,translate('ML_PACKAGE_SCANNING')). '</h2><BR><h2 class="error">' . translate('ML_INSTALLATION_FAILED') . '</h2><br><p>' .str_replace('{PACKAGE}' , $package ,translate('ML_PACKAGE_NOT_CONFIRM')). '</p><ul><li>'. translate('ML_OBTAIN_NEW_PACKAGE') . '<li>' . translate('ML_RELAX_LOCAL').
481+
echo '<h2>'.str_replace('{PACKAGE}' , $package ,translate('ML_PACKAGE_SCANNING')). '</h2><BR><h2 class="error">' . translate('ML_INSTALLATION_FAILED') . '</h2><br><p>' .str_replace('{PACKAGE}' , $package ,translate('ML_PACKAGE_NOT_CONFIRM')). '</p><ul><li>'. translate('ML_OBTAIN_NEW_PACKAGE') . '<li>' . translate('ML_RELAX_LOCAL').
463482
'</ul></p><br>' . translate('ML_SUGAR_LOADING_POLICY') . ' <a href=" http://kb.sugarcrm.com/custom/module-loader-restrictions-for-sugar-open-cloud/">' . translate('ML_SUGAR_KB') . '</a>.'.
464483
'<br>' . translate('ML_AVAIL_RESTRICTION'). ' <a href=" http://developers.sugarcrm.com/wordpress/2009/08/14/module-loader-restrictions/">' . translate('ML_SUGAR_DZ') . '</a>.<br><br>';
465484

466-
485+
467486
foreach($this->issues as $type=>$issues){
468487
echo '<div class="error"><h2>'. ucfirst($type) .' ' . translate('ML_ISSUES') . '</h2> </div>';
469-
echo '<div id="details' . $type . '" >';
488+
echo '<div id="details' . $type . '" >';
470489
foreach($issues as $file=>$issue){
471490
$file = str_replace($this->pathToModule . '/', '', $file);
472-
echo '<div style="position:relative;left:10px"><b>' . $file . '</b></div><div style="position:relative;left:20px">';
491+
echo '<div style="position:relative;left:10px"><b>' . $file . '</b></div><div style="position:relative;left:20px">';
473492
if(is_array($issue)){
474493
foreach($issue as $i){
475494
echo "$i<br>";
@@ -480,13 +499,13 @@ public function displayIssues($package='Package'){
480499
echo "</div>";
481500
}
482501
echo '</div>';
483-
502+
484503
}
485504
echo "<br><input class='button' onclick='document.location.href=\"index.php?module=Administration&action=UpgradeWizard&view=module\"' type='button' value=\"" . translate('LBL_UW_BTN_BACK_TO_MOD_LOADER') . "\" />";
486-
505+
487506
}
488-
489-
507+
508+
490509
}
491510

492511

0 commit comments

Comments
 (0)