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.

jssource/minify_utils.php (5 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
if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
3
/*********************************************************************************
4
 * SugarCRM Community Edition is a customer relationship management program developed by
5
 * SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
6
7
 * SuiteCRM is an extension to SugarCRM Community Edition developed by Salesagility Ltd.
8
 * Copyright (C) 2011 - 2014 Salesagility Ltd.
9
 *
10
 * This program is free software; you can redistribute it and/or modify it under
11
 * the terms of the GNU Affero General Public License version 3 as published by the
12
 * Free Software Foundation with the addition of the following permission added
13
 * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
14
 * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
15
 * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
16
 *
17
 * This program is distributed in the hope that it will be useful, but WITHOUT
18
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19
 * FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
20
 * details.
21
 *
22
 * You should have received a copy of the GNU Affero General Public License along with
23
 * this program; if not, see http://www.gnu.org/licenses or write to the Free
24
 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25
 * 02110-1301 USA.
26
 *
27
 * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
28
 * SW2-130, Cupertino, CA 95014, USA. or at email address [email protected].
29
 *
30
 * The interactive user interfaces in modified source and object code versions
31
 * of this program must display Appropriate Legal Notices, as required under
32
 * Section 5 of the GNU Affero General Public License version 3.
33
 *
34
 * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
35
 * these Appropriate Legal Notices must retain the display of the "Powered by
36
 * SugarCRM" logo and "Supercharged by SuiteCRM" logo. If the display of the logos is not
37
 * reasonably feasible for  technical reasons, the Appropriate Legal Notices must
38
 * display the words  "Powered by SugarCRM" and "Supercharged by SuiteCRM".
39
 ********************************************************************************/
40
41
42
43
44
    /**get_exclude_files
45
     *
46
     * This method returns a predefined array.
47
     * The array holds the location of files/folders to be excluded
48
     * if a prefix is passed in, then it is prepended to the key value in the array
49
     * @prefix string to be prepended to key value in array
50
     */
51
    function get_exclude_files($prefix = ''){
52
        //add slash to prefix if it is not empty
53
        if(!empty($prefix)){
54
            $prefix = $prefix . '/';
55
        }
56
      //add prefix to key if it was passed in
57
      $compress_exempt_files = array(
58
            $prefix.sugar_cached('')                => true,
59
            $prefix.'include/javascript/tiny_mce'   => true,
60
            $prefix.'include/javascript/yui'        => true,
61
            $prefix.'modules/Emails'                => true,
62
            $prefix.'jssource'                      => true,
63
            $prefix.'modules/ModuleBuilder'         => true,
64
            $prefix.'include/javascript/jquery'     => true,
65
            $prefix.'include/javascript/jquery/bootstrap'     => true,
66
            $prefix.'tests/PHPUnit/PHP/CodeCoverage/Report/HTML/Template' => true,
67
            $prefix.'tests/jssource/minify/expect'  => true,
68
            $prefix.'tests/jssource/minify/test'    => true,
69
        );
70
71
        return $compress_exempt_files;
72
73
}
74
75
76
77
    /**ConcatenateFiles($from_path)
78
     *
79
     * This method takes in a string value of the root directory to begin processing
80
     * it uses the predefined array of groupings to create a concatenated file for each grouping
81
     * and places the concatenated file in root directory
82
     * @from_path root directory where processing should take place
83
     */
84
    function ConcatenateFiles($from_path){
85
86
        // Minifying the group files takes a long time sometimes.
87
        @ini_set('max_execution_time', 300);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
88
        $js_groupings = array();
89
        if(isset($_REQUEST['root_directory'])){
90
            require('jssource/JSGroupings.php');
91
        }else{
92
            require('JSGroupings.php');
93
        }
94
        //get array with file sources to concatenate
95
        $file_groups = $js_groupings;//from JSGroupings.php;
96
        $files_opened = array();
97
        $currPerm = '';
98
99
        $excludedFiles = get_exclude_files($from_path);
100
        //for each item in array, concatenate the source files
101
        foreach($file_groups as $fg){
102
103
            //process each group array
104
            foreach($fg as $loc=>$trgt){
105
                $already_minified = FALSE;
106
                $minified_loc = str_replace('.js', '-min.js', $loc);
107
                if(is_file($minified_loc)) {
108
                    $loc = $minified_loc;
109
                    $already_minified = TRUE;
110
                }
111
                $relpath = $loc;
112
                $loc = $from_path.'/'.$loc;
113
114
                $trgt = sugar_cached($trgt);
115
                //check to see that source file is a file, and is readable.
116
                if(is_file($loc) && is_readable($loc)){
117
                    $currPerm = fileperms($loc);
118
                    //check to see if target exists, if it does then open file
119
                    if(file_exists($trgt)){
120
                        if(in_array($trgt, $files_opened)){
121
                            //open target file
122
                            if(function_exists('sugar_fopen')){
123
                                $trgt_handle = sugar_fopen($trgt, 'a');
124
                            }else{
125
                                $trgt_handle = fopen($trgt, 'a');
126
                            }
127
                        }else{
128
                            //open target file
129
                            if(function_exists('sugar_fopen')){
130
                                $trgt_handle = sugar_fopen($trgt, 'w');
131
                            }else{
132
                                $trgt_handle = fopen($trgt, 'w');
133
                            }
134
                        }
135
136
                    }else{
137
138
                        if(!function_exists('mkdir_recursive')) {
139
                            require_once('include/dir_inc.php');
140
                        }
141
142
                        mkdir_recursive(dirname($trgt));
143
                        //create and open target file
144
                        if(function_exists('sugar_fopen')){
145
                                $trgt_handle = @sugar_fopen($trgt, 'w');
146
                        }else{
147
                            $trgt_handle = @fopen($trgt, 'w');
148
                        }
149
150
                        // todo: make this failure more friendly.  Ideally, it will display a
151
                        //       warning to admin users and revert back to displaying all of the
152
                        //       Javascript files insted of displaying the minified versions.
153
                        if ($trgt_handle === false) {
154
                            $target_directory = dirname($trgt);
155
                            $base = dirname($target_directory);
156
                            while(!is_dir($base) && !empty($base) && $base != dirname($base)) {
157
                                $base = dirname($base);
158
                            }
159
                            sugar_die("Creating $target_directory failed: please make sure {$base} is writable\n");
160
                        }
161
162
                }
163
                $files_opened[] = $trgt;
164
165
                //make sure we have handles to both source and target file
166
                if ($trgt_handle) {
167
                        if($already_minified || isset($excludedFiles[dirname($loc)])) {
168
                            $buffer = file_get_contents($loc);
169
                        } else {
170
                            $buffer = SugarMin::minify(file_get_contents($loc));
171
                        }
172
173
                        $buffer .= "/* End of File $relpath */\n\n";
174
                        $num = fwrite($trgt_handle, $buffer);
175
176
                        if( $num=== false){
177
                         //log error, file did not get appended
178
                         echo "Error while concatenating file $loc to target file $trgt \n";
179
                        }
180
                    //close file opened.
181
                    fclose($trgt_handle);
182
                    }
183
184
                }
185
            }
186
187
            //set permissions on this file
188
            if(!empty($currPerm) && $currPerm !== false){
189
                //if we can retrieve permissions from target files, use same
190
                //permission on concatenated file
191
                if(function_exists('sugar_chmod')){
192
                    @sugar_chmod($trgt, $currPerm);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
193
                }else{
194
                    @chmod($trgt, $currPerm);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
195
                }
196
            }else{
197
                //no permissions could be retrieved, so set to 777
198
                if(function_exists('sugar_chmod')){
199
                    @sugar_chmod($trgt, 0777);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
200
                }else{
201
                    @chmod($trgt, 0777);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
202
                }
203
            }
204
        }
205
206
    }
207
208
    function create_backup_folder($bu_path){
209
        $bu_path = str_replace('\\', '/', $bu_path);
210
        //get path after root
211
        $jpos = strpos($bu_path,'jssource');
212
        if($jpos===false){
213
            $process_path = $bu_path;
214
        }else{
215
            $process_path = substr($bu_path, $jpos);
216
            $prefix_process_path = substr($bu_path, 0, $jpos-1);
217
        }
218
        //get rest of directories into array
219
        $bu_dir_arr = explode('/', $process_path);
220
221
        //iterate through each directory and create if needed
222
223
        foreach($bu_dir_arr as $bu_dir){
224
            if(!file_exists($prefix_process_path.'/'.$bu_dir)){
225
                if(function_exists('sugar_mkdir')){
226
                    sugar_mkdir($prefix_process_path.'/'.$bu_dir);
227
                }else{
228
                    mkdir($prefix_process_path.'/'.$bu_dir);
229
                }
230
            }
231
            $prefix_process_path = $prefix_process_path.'/'.$bu_dir;
232
        }
233
234
    }
235
236
237
238
239
    /**CompressFiles
240
     * This method will call jsmin libraries to minify passed in files
241
     * This method takes in 2 string values of the files to process
242
     * Processing will back up javascript files and then minify the original javascript.
243
     * Back up javascript files will have an added .src extension
244
     * @from_path file name and path to be processed
245
     * @to_path file name and path to be  used to place newly compressed contents
246
     */
247
    function CompressFiles($from_path,$to_path){
248
    if(!defined('JSMIN_AS_LIB')){
249
        define('JSMIN_AS_LIB', true);
250
    }
251
    //assumes jsmin.php is in same directory
252
    if(isset($_REQUEST['root_directory']) || defined('INSTANCE_PATH')){
253
        require_once('jssource/jsmin.php');
254
    }else{
255
        require_once('jsmin.php');
256
    }
257
    $nl='
258
 ';
259
260
        //check to make sure from path and to path are not empty
261
        if(isset($from_path) && !empty($from_path)&&isset($to_path) && !empty($to_path)){
262
            $lic_str = '';
263
            $ReadNextLine = true;
264
            // Output a minified version of example.js.
265
            if(file_exists($from_path) && is_file($from_path)){
266
                //read in license script
267
                if(function_exists('sugar_fopen')){
268
                    $file_handle = sugar_fopen($from_path, 'r');
269
                }else{
270
                    $file_handle = fopen($from_path, 'r');
271
                }
272
                if($file_handle){
273
                    $beg = false;
274
275
                    //Read the file until you hit a line with code.  This is meant to retrieve
276
                    //the initial license string found in the beginning comments of js code.
277
                    while (!feof($file_handle) && $ReadNextLine) {
278
                        $newLine = fgets($file_handle, 4096);
279
                        $newLine = trim($newLine);
280
                        //See if line contains open or closing comments
281
282
                        //if opening comments are found, set $beg to true
283
                        if(strpos($newLine, '/*')!== false){
284
                            $beg = true;
285
                        }
286
287
                        //if closing comments are found, set $beg to false
288
                        if(strpos($newLine, '*/')!== false){
289
                            $beg = false;
290
                        }
291
292
                        //if line is not empty (has code) set the boolean to false
293
                        if(! empty($newLine)){$ReadNextLine = false;}
294
                        //If we are in a comment block, then set boolean back to true
295
                        if($beg){
296
                            $ReadNextLine = true;
297
                            //add new line to license string
298
                            $lic_str .=trim($newLine).$nl;
299
                        }else{
300
                            //if we are here it means that uncommented and non blank line has been reached
301
                            //Check to see that ReadNextLine is true, if so then add the last line collected
302
                            //make sure the last line is either the end to a comment block, or starts with '//'
303
                            //else do not add as it is live code.
304
                            if(!empty($newLine) && ((strpos($newLine, '*/')!== false) || ($newLine{0}.$newLine{1}== '//'))){
305
                                //add new line to license string
306
                                $lic_str .=$newLine;
307
                            }
308
                            //set to false because $beg is false, which means the comment block has ended
309
                            $ReadNextLine = false;
310
311
                        }
312
                    }
313
314
                }
315
                if($file_handle){
316
                    fclose($file_handle);
317
                }
318
319
                //place license string into array for use with jsmin file.
320
                //this will preserve the license in the file
321
                $lic_arr = array($lic_str);
322
323
                //minify javascript
324
                //$jMin = new JSMin($from_path,$to_path,$lic_arr);
325
                $min_file = str_replace('.js', '-min.js', $from_path);
326
                if(strpos($from_path, '-min.js') !== FALSE) {
327
                    $min_file = $from_path;
328
                }
329
330
                if(is_file($min_file)) {
331
                    $out = file_get_contents($min_file);
332
                } else {
333
                    $out = $lic_str . SugarMin::minify(file_get_contents($from_path));
334
                }
335
336
            	if(function_exists('sugar_fopen') && $fh = @sugar_fopen( $to_path, 'w' ) )
337
			    {
338
			        fputs( $fh, $out);
339
			        fclose( $fh );
340
				} else {
341
				    file_put_contents($to_path, $out);
342
				}
343
344
            }else{
345
                 //log failure
346
                 echo"<B> COULD NOT COMPRESS $from_path, it is not a file \n";
347
            }
348
349
        }else{
350
         //log failure
351
         echo"<B> COULD NOT COMPRESS $from_path, missing variables \n";
352
        }
353
    }
354
355
    function reverseScripts($from_path,$to_path=''){
356
            $from_path = str_replace('\\', '/', $from_path);
357
            if(empty($to_path)){
358
                $to_path = $from_path;
359
            }
360
            $to_path = str_replace('\\', '/', $to_path);
361
362
            //check to see if provided paths are legit
363
364
            if (!file_exists($from_path))
365
            {
366
                //log error
367
                echo "JS Source directory at $from_path Does Not Exist<p>\n";
368
                return;
369
            }
370
371
            //get correct path for backup
372
            $bu_path = $to_path;
373
            $bu_path .= substr($from_path, strlen($to_path.'/jssource/src_files'));
374
375
            //if this is a directory, then read it and process files
376
            if(is_dir($from_path)){
377
                //grab file / directory and read it.
378
                $handle = opendir($from_path);
379
                //loop over the directory and go into each child directory
380
                while (false !== ($dir = readdir($handle))) {
381
382
                  //make sure you go into directory tree and not out of tree
383
                  if($dir!= '.' && $dir!= '..'){
384
                    //make recursive call to process this directory
385
                    reverseScripts($from_path.'/'.$dir, $to_path );
386
                  }
387
                }
388
            }
389
390
            //if this is not a directory, then
391
            //check if this is a javascript file, then process
392
            $path_parts = pathinfo($from_path);
393
            if(is_file("$from_path") && isset($path_parts['extension']) && $path_parts['extension'] =='js'){
394
395
                    //create backup directory if needed
396
                    $bu_dir = dirname($bu_path);
397
398
                    if(!file_exists($bu_dir)){
399
                        //directory does not exist, log it and return
400
                        echo" directory $bu_dir does not exist, could not restore $bu_path";
401
                        return;
402
                    }
403
404
                    //delete backup src file if it exists already
405
                    if(file_exists($bu_path)){
406
                        unlink($bu_path);
407
                    }
408
                      copy($from_path, $bu_path);
409
                }
410
411
412
    }
413
414
    /**BackUpAndCompressScriptFiles
415
     *
416
     * This method takes in a string value of the root directory to begin processing
417
     * it will process and iterate through all files and subdirectories
418
     * under the passed in directory, ignoring directories and files from the predefined exclude array.
419
     * Processing includes calling a method that will minify the javascript children files
420
     * @from_path root directory where processing should take place
421
     * @to_path root directory where processing should take place, this gets filled in dynamically
422
     */
423
    function BackUpAndCompressScriptFiles($from_path,$to_path = '', $backup = true){
424
            //check to see if provided paths are legit
425
            if (!file_exists($from_path))
426
            {
427
                //log error
428
                echo "The from directory, $from_path Does Not Exist<p>\n";
429
                return;
430
            }else{
431
                $from_path = str_replace('\\', '/', $from_path);
432
            }
433
434
            if(empty($to_path)){
435
                $to_path = $from_path;
436
            }elseif (!file_exists($to_path))
437
            {
438
                //log error
439
                echo "The to directory, $to_path Does Not Exist<p>\n";
440
                return;
441
            }
442
443
            //now grab list of files to exclude from minifying
444
            $exclude_files = get_exclude_files($to_path);
445
446
            //process only if file/directory is not in exclude list
447
            if(!isset($exclude_files[$from_path])){
448
449
                //get correct path for backup
450
                $bu_path = $to_path.'/jssource/src_files';
451
                $bu_path .= substr($from_path, strlen($to_path));
452
453
                //if this is a directory, then read it and process files
454
                if(is_dir("$from_path")){
455
                    //grab file / directory and read it.
456
                    $handle = opendir("$from_path");
457
                    //loop over the directory and go into each child directory
458
                    while (false !== ($dir = readdir($handle))) {
459
460
                      //make sure you go into directory tree and not out of tree
461
                      if($dir!= '.' && $dir!= '..'){
462
                        //make recursive call to process this directory
463
                        BackUpAndCompressScriptFiles($from_path.'/'.$dir, $to_path,$backup);
464
                      }
465
                    }
466
                }
467
468
469
                //if this is not a directory, then
470
                //check if this is a javascript file, then process
471
                // Also, check if there's a min counterpart, in which case, don't use this file.
472
                $path_parts = pathinfo($from_path);
473
                if(is_file("$from_path") && isset($path_parts['extension']) && $path_parts['extension'] =='js'){
474
                    /*$min_file_path = $path_parts['dirname'].'/'.$path_parts['filename'].'-min.'.$path_parts['extension'];
475
                    if(is_file($min_file_path)) {
476
                        $from_path = $min_file_path;
477
                    }*/
478
                    if($backup){
479
                        $bu_dir = dirname($bu_path);
480
                        if(!file_exists($bu_dir)){
481
                            create_backup_folder($bu_dir);
482
                        }
483
484
                        //delete backup src file if it exists already
485
                        if(file_exists($bu_path)){
486
                            unlink($bu_path);
487
                        }
488
                        //copy original file into a source file
489
                          rename($from_path, $bu_path);
490
                    }else{
491
                        //no need to backup, but remove file that is about to be copied
492
                        //if it exists in both backed up scripts and working directory
493
                        if(file_exists($from_path) && file_exists($bu_path)){unlink($from_path);}
494
                    }
495
496
                    //now make call to minify and overwrite the original file.
497
                    CompressFiles($bu_path, $from_path);
498
499
                }
500
            }
501
502
        }
503