]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - modules/UpgradeWizard/uw_utils.php
Release 6.5.6
[Github/sugarcrm.git] / modules / UpgradeWizard / uw_utils.php
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-2012 SugarCRM Inc.
6  * 
7  * This program is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU Affero General Public License version 3 as published by the
9  * Free Software Foundation with the addition of the following permission added
10  * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
11  * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
12  * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
13  * 
14  * This program is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16  * FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
17  * details.
18  * 
19  * You should have received a copy of the GNU Affero General Public License along with
20  * this program; if not, see http://www.gnu.org/licenses or write to the Free
21  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22  * 02110-1301 USA.
23  * 
24  * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
25  * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
26  * 
27  * The interactive user interfaces in modified source and object code versions
28  * of this program must display Appropriate Legal Notices, as required under
29  * Section 5 of the GNU Affero General Public License version 3.
30  * 
31  * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
32  * these Appropriate Legal Notices must retain the display of the "Powered by
33  * SugarCRM" logo. If the display of the logo is not reasonably feasible for
34  * technical reasons, the Appropriate Legal Notices must display the words
35  * "Powered by SugarCRM".
36  ********************************************************************************/
37
38
39
40
41 /**
42  * Helper function for upgrade - get path from upload:// name
43  * @param string $path
44  * return string
45  */
46 function getUploadRelativeName($path)
47 {
48     if(class_exists('UploadFile')) {
49         return UploadFile::realpath($path);
50     }
51     if(substr($path, 0, 9) == "upload://") {
52         $path = rtrim($GLOBALS['sugar_config']['upload_dir'], "/\\")."/".substr($path, 9);
53     }
54     return $path;
55 }
56
57 /**
58  * Backs-up files that are targeted for patch/upgrade to a restore directory
59  * @param string rest_dir Full path to the directory containing the original, replaced files.
60  * @param string install_file Full path to the uploaded patch/upgrade zip file
61  * @param string unzip_dir Full path to the unzipped files in a temporary directory
62  * @param string zip_from_dir Name of directory that the unzipped files containing the actuall replacement files
63  * @param array errors Collection of errors to be displayed at end of process
64  * @param string path Optional full path to the log file.
65  * @return array errors
66  */
67 function commitMakeBackupFiles($rest_dir, $install_file, $unzip_dir, $zip_from_dir, $errors, $path='') {
68         global $mod_strings;
69         // create restore file directory
70         sugar_mkdir($rest_dir, 0775, true);
71
72     if(file_exists($rest_dir) && is_dir($rest_dir)){
73                 logThis('backing up files to be overwritten...', $path);
74                 $newFiles = findAllFiles(clean_path($unzip_dir . '/' . $zip_from_dir), array());
75
76                 // keep this around for canceling
77                 $_SESSION['uw_restore_dir'] = getUploadRelativeName($rest_dir);
78
79                 foreach ($newFiles as $file) {
80                         if (strpos($file, 'md5'))
81                                 continue;
82
83                         // get name of current file to place in restore directory
84                         $cleanFile = str_replace(clean_path($unzip_dir . '/' . $zip_from_dir), '', $file);
85
86                         // make sure the directory exists
87                         $cleanDir = $rest_dir . '/' . dirname($cleanFile);
88                         sugar_mkdir($cleanDir, 0775, true);
89                         $oldFile = clean_path(getcwd() . '/' . $cleanFile);
90
91                         // only copy restore files for replacements - ignore new files from patch
92                         if (is_file($oldFile)) {
93                                 if (is_writable($rest_dir)) {
94                                         logThis('Backing up file: ' . $oldFile, $path);
95                                         if (!copy($oldFile, $rest_dir . '/' . $cleanFile)) {
96                                                 logThis('*** ERROR: could not backup file: ' . $oldFile, $path);
97                                                 $errors[] = "{$mod_strings['LBL_UW_BACKUP']}::{$mod_strings['ERR_UW_FILE_NOT_COPIED']}: {$oldFile}";
98                                         } else {
99                                                 $backupFilesExist = true;
100                                         }
101
102                                 } else {
103                                         logThis('*** ERROR: directory not writable: ' . $rest_dir, $path);
104                                         $errors[] = "{$mod_strings['LBL_UW_BACKUP']}::{$mod_strings['ERR_UW_DIR_NOT_WRITABLE']}: {$oldFile}";
105                                 }
106                         }
107                 }
108     }
109         logThis('file backup done.', $path);
110         return $errors;
111 }
112
113 /**
114  * Copies files from the unzipped patch to the destination.
115  * @param string unzip_dir Full path to the temporary directory created during unzip operation.
116  * @param string zip_from_dir Name of folder containing the unzipped files; usually the name of the Patch without the
117  * extension.
118  * @param string path Optional full path to alternate upgradeWizard log file.
119  * @return array Two element array containing to $copiedFiles and $skippedFiles.
120  */
121
122
123
124 function commitCopyNewFiles($unzip_dir, $zip_from_dir, $path='') {
125         logThis('Starting file copy process...', $path);
126         global $sugar_version;
127         $backwardModules='';
128     if(substr($sugar_version,0,1) >= 5){
129         $modules = getAllModules();
130                         $backwardModules = array();
131                         foreach($modules as $mod){
132                                 if(is_dir(clean_path(getcwd().'/modules/'.$mod.'/.500'))){
133                                         $files = array();
134                                 $files= findAllFiles(clean_path(getcwd().'/modules/'.$mod.'/.500'),$files);
135                                 if(sizeof($files) >0){
136                                         //backward compatibility is on
137                                                 $backwardModules[] = $mod;
138                                 }
139                            }
140                         }
141        }
142
143         $newFiles = findAllFiles(clean_path($unzip_dir . '/' . $zip_from_dir), array());
144         $zipPath = clean_path($unzip_dir . '/' . $zip_from_dir);
145
146         // handle special do-not-overwrite conditions
147         $doNotOverwrite = array();
148         $doNotOverwrite[] = '__stub';
149         if(isset($_REQUEST['overwrite_files_serial'])) {
150                 $doNotOverwrite = explode('::', $_REQUEST['overwrite_files_serial']);
151         }
152
153         $copiedFiles = array();
154         $skippedFiles = array();
155
156         foreach($newFiles as $file) {
157                 $cleanFile = str_replace($zipPath, '', $file);
158                 $srcFile = $zipPath . $cleanFile;
159                 $targetFile = clean_path(getcwd() . '/' . $cleanFile);
160                 if($backwardModules != null && sizeof($backwardModules) >0){
161                         foreach($backwardModules as $mod){
162                                 $splitPath = explode('/',trim($cleanFile));
163                                 if('modules' == trim($splitPath[1]) && $mod == trim($splitPath[2])){
164                                         $cleanFile = str_replace('/modules/'.$mod, '/modules/'.$mod.'/.500', $cleanFile);
165                                         $targetFile = clean_path(getcwd() . '/' . $cleanFile);
166                                 }
167                         }
168                 }
169                 if(!is_dir(dirname($targetFile))) {
170                         mkdir_recursive(dirname($targetFile)); // make sure the directory exists
171                 }
172
173                 if((!file_exists($targetFile)) || /* brand new file */
174                         (!in_array($targetFile, $doNotOverwrite)) /* manual diff file */
175                         ) {
176                         // handle sugar_version.php
177                         if(strpos($targetFile, 'sugar_version.php') !== false && !preg_match('/\/portal\/sugar_version\.php$/i', $targetFile)) {
178                                 logThis('Skipping "sugar_version.php" - file copy will occur at end of successful upgrade', $path);
179                                 $_SESSION['sugar_version_file'] = $srcFile;
180                                 continue;
181                         }
182
183                         //logThis('Copying file to destination: ' . $targetFile, $path);
184
185                         if(!copy($srcFile, $targetFile)) {
186                                 logThis('*** ERROR: could not copy file: ' . $targetFile, $path);
187                         } else {
188                                 $copiedFiles[] = $targetFile;
189                         }
190                 } else {
191                         //logThis('Skipping file: ' . $targetFile, $path);
192                         $skippedFiles[] = $targetFile;
193                 }
194         }
195         logThis('File copy done.', $path);
196
197         $ret = array();
198         $ret['copiedFiles'] = $copiedFiles;
199         $ret['skippedFiles'] = $skippedFiles;
200
201         return $ret;
202 }
203
204
205 //On cancel put back the copied files from 500 to 451 state
206 function copyFilesOnCancel($step){
207 //place hoder for cancel action
208
209 }
210
211
212 function removeFileFromPath($file,$path, $deleteNot=array()){
213                 $removed = 0;
214                 $cur = $path . '/' . $file;
215                 if(file_exists($cur)){
216                         $del = true;
217                         foreach($deleteNot as $dn){
218                                 if($cur == $dn){
219                                         $del = false;
220                                 }
221                         }
222                         if($del){
223                                 unlink($cur);
224                                 $removed++;
225                         }
226                 }
227                 if(!file_exists($path))return $removed;
228                 $d = dir($path);
229                 while(false !== ($e = $d->read())){  // Fixed bug. !== is required to literally match the type and value of false, so that a filename that could evaluate and cast to false, ie "false" or "0", still allows the while loop to continue.  From example at http://www.php.net/manual/en/function.dir.php
230                         $next = $path . '/'. $e;
231                         if(substr($e, 0, 1) != '.' && is_dir($next)){
232                                 $removed += removeFileFromPath($file, $next, $deleteNot);
233                         }
234                 }
235                 $d->close();  // from example at http://www.php.net/manual/en/function.dir.php
236                 return $removed;
237         }
238
239 /**
240  * This function copies/overwrites between directories
241  *
242  * @param string the directory name to remove
243  * @param boolean whether to just empty the given directory, without deleting the given directory.
244  * @return boolean True/False whether the directory was deleted.
245  */
246
247 function copyRecursiveBetweenDirectories($from,$to){
248         if(file_exists($from)){
249                 $modifiedFiles = array();
250                 $modifiedFiles = findAllFiles(clean_path($from), $modifiedFiles);
251                 $cwd = clean_path(getcwd());
252                 foreach($modifiedFiles as $file) {
253                         $srcFile = clean_path($file);
254             if (strpos($srcFile,".svn") === false) {
255                         $targetFile = str_replace($from, $to, $srcFile);
256
257                                 if(!is_dir(dirname($targetFile))) {
258                                         mkdir_recursive(dirname($targetFile)); // make sure the directory exists
259                                 }
260
261                                         // handle sugar_version.php
262                                         if(strpos($targetFile, 'sugar_version.php') !== false && !preg_match('/\/portal\/sugar_version\.php$/i', $targetFile)) {
263                                                 logThis('Skipping "sugar_version.php" - file copy will occur at end of successful upgrade', $targetFile);
264                                                 $_SESSION['sugar_version_file'] = $srcFile;
265                                                 continue;
266                                         }
267
268                                         if(!copy($srcFile, $targetFile)) {
269                                                 logThis("*** ERROR: could not copy file $srcFile to $targetFile");
270                                         }
271                 }
272                  }
273         }
274 }
275
276 function deleteDirectory($dirname,$only_empty=false) {
277     if (!is_dir($dirname))
278         return false;
279     $dscan = array(realpath($dirname));
280     $darr = array();
281     while (!empty($dscan)) {
282         $dcur = array_pop($dscan);
283         $darr[] = $dcur;
284         if ($d=opendir($dcur)) {
285             while ($f=readdir($d)) {
286                 if ($f=='.' || $f=='..')
287                     continue;
288                 $f=$dcur.'/'.$f;
289                 if (is_dir($f))
290                     $dscan[] = $f;
291                 else
292                     unlink($f);
293             }
294             closedir($d);
295         }
296     }
297     $i_until = ($only_empty)? 1 : 0;
298     for ($i=count($darr)-1; $i>=$i_until; $i--) {
299         if (rmdir($darr[$i]))
300             logThis('Success :Copying file to destination: ' . $darr[$i]);
301         else
302             logThis('Copy problem:Copying file to destination: ' . $darr[$i]);
303     }
304     return (($only_empty)? (count(scandir)<=2) : (!is_dir($dirname)));
305 }
306 /**
307  * Get all the customized modules. Compare the file md5s with the base md5s
308  * If a file has been modified then put the module in the list of customized
309  * modules. Show the list in the preflight check UI.
310  */
311
312 function deleteAndOverWriteSelectedFiles($unzip_dir, $zip_from_dir,$delete_dirs){
313         if($delete_dirs != null){
314                 foreach($delete_dirs as $del_dir){
315                         deleteDirectory($del_dir);
316                         $newFiles = findAllFiles(clean_path($unzip_dir . '/' . $zip_from_dir.'/'.$del_dir), array());
317                         $zipPath = clean_path($unzip_dir . '/' . $zip_from_dir.'/'.$del_dir);
318                         $copiedFiles = array();
319                         $skippedFiles = array();
320
321                         foreach($newFiles as $file) {
322                                 $cleanFile = str_replace($zipPath, '', $file);
323                                 $srcFile = $zipPath . $cleanFile;
324                                 $targetFile = clean_path(getcwd() . '/' . $cleanFile);
325
326                                 if(!is_dir(dirname($targetFile))) {
327                                         mkdir_recursive(dirname($targetFile)); // make sure the directory exists
328                                 }
329
330                                 if(!file_exists($targetFile)){
331                                         // handle sugar_version.php
332                                         if(strpos($targetFile, 'sugar_version.php') !== false) {
333                                                 logThis('Skipping sugar_version.php - file copy will occur at end of successful upgrade');
334                                                 $_SESSION['sugar_version_file'] = $srcFile;
335                                                 continue;
336                                         }
337
338                                         //logThis('Copying file to destination: ' . $targetFile);
339
340                                         if(!copy($srcFile, $targetFile)) {
341                                                 logThis('*** ERROR: could not copy file: ' . $targetFile);
342                                         } else {
343                                                 $copiedFiles[] = $targetFile;
344                                         }
345                                 } else {
346                                         //logThis('Skipping file: ' . $targetFile);
347                                         $skippedFiles[] = $targetFile;
348                                 }
349                           }
350                 }
351         }
352         $ret = array();
353         $ret['copiedFiles'] = $copiedFiles;
354         $ret['skippedFiles'] = $skippedFiles;
355
356         return $ret;
357 }
358
359 //Default is empty the directory. For removing set it to false
360 // to use this function to totally remove a directory, write:
361 // recursive_remove_directory('path/to/directory/to/delete',FALSE);
362
363 // to use this function to empty a directory, write:
364 // recursive_remove_directory('path/to/full_directory');
365
366 function recursive_empty_or_remove_directory($directory, $exclude_dirs=null,$exclude_files=null,$empty=TRUE)
367 {
368         // if the path has a slash at the end we remove it here
369         if(substr($directory,-1) == '/')
370         {
371                 $directory = substr($directory,0,-1);
372         }
373
374         // if the path is not valid or is not a directory ...
375         if(!file_exists($directory) || !is_dir($directory))
376         {
377                 // ... we return false and exit the function
378                 return FALSE;
379
380         // ... if the path is not readable
381         }elseif(!is_readable($directory))
382         {
383                 // ... we return false and exit the function
384                 return FALSE;
385
386         // ... else if the path is readable
387         }else{
388
389                 // we open the directory
390                 $handle = opendir($directory);
391
392                 // and scan through the items inside
393                 while (FALSE !== ($item = readdir($handle)))
394                 {
395                         // if the filepointer is not the current directory
396                         // or the parent directory
397                         if($item != '.' && $item != '..')
398                         {
399                                 // we build the new path to delete
400                                 $path = $directory.'/'.$item;
401
402                                 // if the new path is a directory
403                                 //add another check if the dir is in the list to exclude delete
404                                 if(is_dir($path) && $exclude_dirs != null && in_array($path,$exclude_dirs)){
405                                     //do nothing
406                                 }
407                                 else if(is_dir($path))
408                                 {
409                                         // we call this function with the new path
410                                         recursive_empty_or_remove_directory($path);
411                                 }
412                                 // if the new path is a file
413                                 else{
414                                         // we remove the file
415                                         if($exclude_files != null && in_array($path,$exclude_files)){
416                            //do nothing
417                                         }
418                                         else{
419                                                 unlink($path);
420                                     }
421                                 }
422                         }
423                 }
424                 // close the directory
425                 closedir($handle);
426
427                 // if the option to empty is not set to true
428                 if($empty == FALSE)
429                 {
430                         // try to delete the now empty directory
431                         if(!rmdir($directory))
432                         {
433                                 // return false if not possible
434                                 return FALSE;
435                         }
436                 }
437                 // return success
438                 return TRUE;
439         }
440 }
441 // ------------------------------------------------------------
442
443
444
445
446 function getAllCustomizedModules() {
447
448                 require_once('files.md5');
449
450             $return_array = array();
451             $modules = getAllModules();
452             foreach($modules as $mod) {
453                    //find all files in each module if the files have been modified
454                    //as compared to the base version then add the module to the
455                    //customized modules array
456                    $modFiles = findAllFiles(clean_path(getcwd())."/modules/$mod", array());
457                foreach($modFiles as $file){
458                   $fileContents = file_get_contents($file);
459                    $file = str_replace(clean_path(getcwd()),'',$file);
460                   if($md5_string['./' . $file]){
461                           if(md5($fileContents) != $md5_string['./' . $file]) {
462                              //A file has been customized in the module. Put the module into the
463                              // customized modules array.
464                              echo 'Changed File'.$file;
465                                   $return_array[$mod];
466                                   break;
467                           }
468                   }
469                   else{
470                         // This is a new file in user's version and indicates that module has been
471                         //customized. Put the module in the customized array.
472                        echo 'New File'.$file;
473                        $return_array[$mod];
474                        break;
475                   }
476                }
477             } //foreach
478
479                 return $return_array;
480         }
481
482     /**
483      * Array of all Modules in the version bein upgraded
484      * This method returns an Array of all modules
485      * @return $modules Array of modules.
486      */
487         function getAllModules() {
488                 $modules = array();
489                 $d = dir('modules');
490                 while($e = $d->read()){
491                         if(substr($e, 0, 1) == '.' || !is_dir('modules/' . $e))continue;
492                         $modules[] = $e;
493                 }
494                 return $modules;
495         }
496
497 //Remove files with the smae md5
498
499 function removeMd5MatchingFiles($deleteNot=array()){
500
501         $md5_string = array();
502         if(file_exists(clean_path(getcwd().'/files.md5'))){
503                 require(clean_path(getcwd().'/files.md5'));
504         }
505     $modulesAll = getAllModules();
506      foreach($modulesAll as $mod){
507               $allModFiles = array();
508               if(is_dir('modules/'.$mod)){
509               $allModFiles = findAllFiles('modules/'.$mod,$allModFiles);
510                foreach($allModFiles as $file){
511                         if(file_exists($file) && !in_array(basename($file),$deleteNot)){
512                                  if(isset($md5_string['./'.$file])) {
513                                   $fileContents = file_get_contents($file);
514                                   if(md5($fileContents) == $md5_string['./'.$file]) {
515                                         unlink($file);
516                                   }
517                               }
518                     }
519            }
520            }
521    }
522 }
523
524 /**
525  * Handles requirements for creating reminder Tasks and Emails
526  * @param array skippedFiles Array of files that were not overwriten and must be manually mereged.
527  * @param string path Optional full path to alternate upgradeWizard log.
528  */
529 function commitHandleReminders($skippedFiles, $path='') {
530         global $mod_strings;
531         global $current_user;
532
533         if(empty($mod_strings))
534                 $mod_strings = return_module_language('en_us', 'UpgradeWizard');
535
536         if(empty($current_user->id)) {
537                 $current_user->getSystemUser();
538         }
539
540         if(count($skippedFiles) > 0) {
541                 $desc = $mod_strings['LBL_UW_COMMIT_ADD_TASK_OVERVIEW'] . "\n\n";
542                 $desc .= $mod_strings['LBL_UW_COMMIT_ADD_TASK_DESC_1'];
543                 $desc .= $_SESSION['uw_restore_dir'] . "\n\n";
544                 $desc .= $mod_strings['LBL_UW_COMMIT_ADD_TASK_DESC_2'] . "\n\n";
545
546                 foreach($skippedFiles as $file) {
547                         $desc .= $file . "\n";
548                 }
549
550                 //MFH #13468
551                 /// Not using new TimeDate stuff here because it needs to be compatible with 6.0
552                 $nowDate = gmdate('Y-m-d');
553                 $nowTime = gmdate('H:i:s');
554                 $nowDateTime = $nowDate . ' ' . $nowTime;
555
556                 if($_REQUEST['addTaskReminder'] == 'remind') {
557                         logThis('Adding Task for admin for manual merge.', $path);
558
559                         $task = new Task();
560                         $task->name = $mod_strings['LBL_UW_COMMIT_ADD_TASK_NAME'];
561                         $task->description = $desc;
562                         $task->date_due = $nowDate;
563                         $task->time_due = $nowTime;
564                         $task->priority = 'High';
565                         $task->status = 'Not Started';
566                         $task->assigned_user_id = $current_user->id;
567                         $task->created_by = $current_user->id;
568                         $task->date_entered = $nowDateTime;
569                         $task->date_modified = $nowDateTime;
570                         $task->save();
571                 }
572
573                 if($_REQUEST['addEmailReminder'] == 'remind') {
574                         logThis('Sending Reminder for admin for manual merge.', $path);
575
576                         $email = new Email();
577                         $email->assigned_user_id = $current_user->id;
578                         $email->name = $mod_strings['LBL_UW_COMMIT_ADD_TASK_NAME'];
579                         $email->description = $desc;
580                         $email->description_html = nl2br($desc);
581                         $email->from_name = $current_user->full_name;
582                         $email->from_addr = $current_user->email1;
583                         $email->to_addrs_arr = $email->parse_addrs($current_user->email1, '', '', '');
584                         $email->cc_addrs_arr = array();
585                         $email->bcc_addrs_arr = array();
586                         $email->date_entered = $nowDateTime;
587                         $email->date_modified = $nowDateTime;
588                         $email->send();
589                         $email->save();
590                 }
591         }
592 }
593
594 function deleteCache(){
595         //Clean modules from cache
596         $cachedir = sugar_cached('modules');
597         if(is_dir($cachedir)){
598                 $allModFiles = array();
599                 $allModFiles = findAllFiles($cachedir,$allModFiles, true);
600                 foreach($allModFiles as $file) {
601                 if(file_exists($file)) {
602                         if(is_dir($file)) {
603                                   rmdir_recursive($file);
604                         } else {
605                           unlink($file);
606                }
607                 }
608             }
609
610         }
611
612         //Clean jsLanguage from cache
613         $cachedir = sugar_cached('jsLanguage');
614         if(is_dir($cachedir)){
615                 $allModFiles = array();
616                 $allModFiles = findAllFiles($cachedir,$allModFiles);
617            foreach($allModFiles as $file){
618                         if(file_exists($file)){
619                                 unlink($file);
620                         }
621                 }
622         }
623         //Clean smarty from cache
624         $cachedir = sugar_cached('smarty');
625         if(is_dir($cachedir)){
626                 $allModFiles = array();
627                 $allModFiles = findAllFiles($cachedir,$allModFiles);
628            foreach($allModFiles as $file){
629                 if(file_exists($file)){
630                                 unlink($file);
631                 }
632            }
633         }
634         //Rebuild dashlets cache
635         require_once('include/Dashlets/DashletCacheBuilder.php');
636         $dc = new DashletCacheBuilder();
637     $dc->buildCache();
638 }
639
640 function deleteChance(){
641         //Clean folder from cache
642         if(is_dir('include/SugarObjects/templates/chance')){
643                 rmdir_recursive('include/SugarObjects/templates/chance');
644          }
645         if(is_dir('include/SugarObjects/templates/chance')){
646                 if(!isset($_SESSION['chance'])){
647                         $_SESSION['chance'] = '';
648                 }
649                 $_SESSION['chance'] = 'include/SugarObjects/templates/chance';
650                 //rename('include/SugarObjects/templates/chance','include/SugarObjects/templates/chance_removeit');
651         }
652 }
653
654
655
656 /**
657  * upgradeUWFiles
658  * This function copies upgrade wizard files from new patch if that dir exists
659  *
660  * @param $file String path to uploaded zip file
661  */
662 function upgradeUWFiles($file) {
663     $cacheUploadUpgradesTemp = mk_temp_dir(sugar_cached("upgrades/temp"));
664
665         unzip($file, $cacheUploadUpgradesTemp);
666
667         if(!file_exists("$cacheUploadUpgradesTemp/manifest.php")) {
668                 logThis("*** ERROR: no manifest file detected while bootstraping upgrade wizard files!");
669                 return;
670         } else {
671                 include("$cacheUploadUpgradesTemp/manifest.php");
672         }
673
674         $allFiles = array();
675         $from_dir = "{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}";
676
677     // Localization
678     if(file_exists("$from_dir/include/Localization/Localization.php")) {
679         $allFiles[] = "$from_dir/include/Localization/Localization.php";
680     }
681     // upgradeWizard
682     if(file_exists("$from_dir/modules/UpgradeWizard")) {
683         $allFiles[] = findAllFiles("$from_dir/modules/UpgradeWizard", $allFiles);
684     }
685     // moduleInstaller
686     if(file_exists("$from_dir/ModuleInstall")) {
687         $allFiles[] = findAllFiles("$from_dir/ModuleInstall", $allFiles);
688     }
689     if(file_exists("$from_dir/include/javascript/yui")) {
690         $allFiles[] = findAllFiles("$from_dir/include/javascript/yui", $allFiles);
691     }
692     if(file_exists("$from_dir/HandleAjaxCall.php")) {
693         $allFiles[] = "$from_dir/HandleAjaxCall.php";
694     }
695     if(file_exists("$from_dir/include/SugarTheme")) {
696         $allFiles[] = findAllFiles("$from_dir/include/SugarTheme", $allFiles);
697     }
698     if(file_exists("$from_dir/include/SugarCache")) {
699         $allFiles[] = findAllFiles("$from_dir/include/SugarCache", $allFiles);
700     }
701     if(file_exists("$from_dir/include/utils/external_cache.php")) {
702         $allFiles[] = "$from_dir/include/utils/external_cache.php";
703     }
704     if(file_exists("$from_dir/include/upload_file.php")) {
705         $allFiles[] = "$from_dir/include/upload_file.php";
706     }
707     if(file_exists("$from_dir/include/file_utils.php")) {
708         $allFiles[] = "$from_dir/include/file_utils.php";
709     }
710     if(file_exists("$from_dir/include/upload_file.php")) {
711         $allFiles[] = "$from_dir/include/upload_file.php";
712     }
713     if(file_exists("$from_dir/include/utils/sugar_file_utils.php")) {
714         $allFiles[] = "$from_dir/include/utils/sugar_file_utils.php";
715     }
716     // users
717     if(file_exists("$from_dir/modules/Users")) {
718         $allFiles[] = findAllFiles("$from_dir/modules/Users", $allFiles);
719     }
720
721     upgradeUWFilesCopy($allFiles, $from_dir);
722 }
723
724 /**
725  * upgradeUWFilesCopy
726  *
727  * This function recursively copies files from the upgradeUWFiles Array
728  * @see upgradeUWFiles
729  *
730  * @param array $allFiles Array of files to copy over after zip file has been uploaded
731  * @param string $from_dir Source directory
732  */
733 function upgradeUWFilesCopy($allFiles, $from_dir)
734 {
735    foreach($allFiles as $file)
736    {
737        if(is_array($file))
738        {
739            upgradeUWFilesCopy($file, $from_dir);
740        } else {
741            $destFile = str_replace($from_dir."/", "", $file);
742            if(!is_dir(dirname($destFile))) {
743               mkdir_recursive(dirname($destFile)); // make sure the directory exists
744            }
745
746            if(stristr($file,'uw_main.tpl'))
747               logThis('Skipping "'.$file.'" - file copy will during commit step.');
748            else {
749               logThis('updating UpgradeWizard code: '.$destFile);
750               copy_recursive($file, $destFile);
751            }
752        }
753    }
754 }
755
756
757
758 /**
759  * gets valid patch file names that exist in upload/upgrade/patch/
760  */
761 function getValidPatchName($returnFull = true) {
762         global $base_upgrade_dir;
763         global $mod_strings;
764         global $uh;
765         global $sugar_version;
766     global $sugar_config;
767     $uh = new UpgradeHistory();
768     list($base_upgrade_dir, $base_tmp_upgrade_dir) = getUWDirs();
769     $return = array();
770
771         // scan for new files (that are not installed)
772         logThis('finding new files for upgrade');
773         $upgrade_content = '';
774         $upgrade_contents = findAllFiles($base_upgrade_dir, array(), false, 'zip');
775         //other variations of zip file i.e. ZIP, zIp,zIP,Zip,ZIp,ZiP
776         $ready = "<ul>\n";
777         $ready .= "
778                 <table>
779                         <tr>
780                                 <td></td>
781                                 <td align=left>
782                                         <b>{$mod_strings['LBL_ML_NAME']}</b>
783                                 </td>
784                                 <td align=left>
785                                         <b>{$mod_strings['LBL_ML_TYPE']}</b>
786                                 </td>
787                                 <td align=left>
788                                         <b>{$mod_strings['LBL_ML_VERSION']}</b>
789                                 </td>
790                                 <td align=left>
791                                         <b>{$mod_strings['LBL_ML_PUBLISHED']}</b>
792                                 </td>
793                                 <td align=left>
794                                         <b>{$mod_strings['LBL_ML_UNINSTALLABLE']}</b>
795                                 </td>
796                                 <td align=left>
797                                         <b>{$mod_strings['LBL_ML_DESCRIPTION']}</b>
798                                 </td>
799                         </tr>";
800         $disabled = '';
801
802         // assume old patches are there.
803         $upgradeToVersion = array(); // fill with valid patches - we will only use the latest qualified found patch
804
805         // cn: bug 10609 - notices for uninitialized variables
806         $icon = '';
807         $name = '';
808         $type = '';
809         $version = '';
810         $published_date = '';
811         $uninstallable = '';
812         $description = '';
813         $disabled = '';
814
815         foreach($upgrade_contents as $upgrade_content) {
816                 if(!preg_match("#.*\.zip\$#i", $upgrade_content)) {
817                         continue;
818                 }
819
820                 $the_base = basename($upgrade_content);
821                 $the_md5 = md5_file($upgrade_content);
822
823                 $md5_matches = $uh->findByMd5($the_md5);
824
825                 /* If a patch is in the /patch dir AND has no record in the upgrade_history table we assume that it's the one we want.
826                  * Edge-case: manual upgrade with a FTP of a patch; UH table has no entry for it.  Assume nothing. :( */
827                 if(0 == sizeof($md5_matches)) {
828                         $target_manifest = remove_file_extension( $upgrade_content ) . '-manifest.php';
829                         require_once($target_manifest);
830
831                         if(empty($manifest['version'])) {
832                                 logThis("*** Potential error: patch found with no version [ {$upgrade_content} ]");
833                                 continue;
834                         }
835                         if(!isset($manifest['type']) || $manifest['type'] != 'patch') {
836                                 logThis("*** Potential error: patch found with either no 'type' or non-patch type [ {$upgrade_content} ]");
837                                 continue;
838                         }
839
840                         $upgradeToVersion[$manifest['version']] = urlencode($upgrade_content);
841
842                         $name = empty($manifest['name']) ? $upgrade_content : $manifest['name'];
843                         $version = empty($manifest['version']) ? '' : $manifest['version'];
844                         $published_date = empty($manifest['published_date']) ? '' : $manifest['published_date'];
845                         $icon = '';
846                         $description = empty($manifest['description']) ? 'None' : $manifest['description'];
847                         $uninstallable = empty($manifest['is_uninstallable']) ? 'No' : 'Yes';
848                         $type = getUITextForType( $manifest['type'] );
849                         $manifest_type = $manifest['type'];
850
851                         if(empty($manifest['icon'])) {
852                                 $icon = getImageForType( $manifest['type'] );
853                         } else {
854                                 $path_parts = pathinfo( $manifest['icon'] );
855                                 $icon = "<!--not_in_theme!--><img src=\"" . remove_file_extension( $upgrade_content ) . "-icon." . $path_parts['extension'] . "\">";
856                         }
857             }
858         }
859
860         // cn: bug 10488 use the NEWEST upgrade/patch available when running upgrade wizard.
861         ksort($upgradeToVersion);
862         $upgradeToVersion = array_values($upgradeToVersion);
863         $newest = array_pop($upgradeToVersion);
864         $_SESSION['install_file'] = urldecode($newest); // in-case it was there from a prior.
865         logThis("*** UW using [ {$_SESSION['install_file']} ] as source for patch files.");
866
867         $cleanUpgradeContent = urlencode($_SESSION['install_file']);
868
869         // cn: 10606 - cannot upload a patch file since this returned always.
870         if(!empty($cleanUpgradeContent)) {
871                 $ready .= "<tr><td>$icon</td><td>$name</td><td>$type</td><td>$version</td><td>$published_date</td><td>$uninstallable</td><td>$description</td>\n";
872                 $ready .=<<<eoq
873                 <td>
874                                 <form action="index.php" method="post">
875                                         <input type="hidden" name="module" value="UpgradeWizard">
876                                         <input type="hidden" name="action" value="index">
877                                         <input type="hidden" name="step" value="{$_REQUEST['step']}">
878                                         <input type="hidden" name="run" value="delete">
879                                 <input type=hidden name="install_file" value="{$cleanUpgradeContent}" />
880                                 <input type=submit value="{$mod_strings['LBL_BUTTON_DELETE']}" />
881                                 </form>
882                         </td></table>
883 eoq;
884                 $disabled = "DISABLED";
885         }
886
887
888
889         if(empty($cleanUpgradeContent)){
890             $ready .= "<tr><td colspan='7'><i>None</i></td>\n";
891                 $ready .= "</table>\n";
892         }
893         $ready .= "<br></ul>\n";
894
895         $return['ready'] = $ready;
896         $return['disabled'] = $disabled;
897
898         if($returnFull) {
899                 return $return;
900         }
901 }
902
903
904 /**
905  * finalizes upgrade by setting upgrade versions in DB (config table) and sugar_version.php
906  * @return bool true on success
907  */
908 function updateVersions($version) {
909         global $db;
910         global $sugar_config;
911         global $path;
912
913         logThis('At updateVersions()... updating config table and sugar_version.php.', $path);
914
915         // handle file copy
916         if(isset($_SESSION['sugar_version_file']) && !empty($_SESSION['sugar_version_file'])) {
917                 if(!copy($_SESSION['sugar_version_file'], clean_path(getcwd().'/sugar_version.php'))) {
918                         logThis('*** ERROR: sugar_version.php could not be copied to destination! Cannot complete upgrade', $path);
919                         return false;
920                 } else {
921                         logThis('sugar_version.php successfully updated!', $path);
922                 }
923         } else {
924                 logThis('*** ERROR: no sugar_version.php file location found! - cannot complete upgrade...', $path);
925                 return false;
926         }
927
928         $q1 = "DELETE FROM config WHERE category = 'info' AND name = 'sugar_version'";
929         $q2 = "INSERT INTO config (category, name, value) VALUES ('info', 'sugar_version', '{$version}')";
930
931         logThis('Deleting old DB version info from config table.', $path);
932         $db->query($q1);
933
934         logThis('Inserting updated version info into config table.', $path);
935         $db->query($q2);
936
937         logThis('updateVersions() complete.', $path);
938         return true;
939 }
940
941
942
943 /**
944  * gets a module's lang pack - does not need to be a SugarModule
945  * @param lang string Language
946  * @param module string Path to language folder
947  * @return array mod_strings
948  */
949 function getModuleLanguagePack($lang, $module) {
950         $mod_strings = array();
951
952         if(!empty($lang) && !empty($module)) {
953                 $langPack = clean_path(getcwd().'/'.$module.'/language/'.$lang.'.lang.php');
954                 $langPackEn = clean_path(getcwd().'/'.$module.'/language/en_us.lang.php');
955
956         if (file_exists($langPack))
957         {
958             include($langPack);
959         }
960         elseif (file_exists($langPackEn))
961         {
962             include($langPackEn);
963         }
964         }
965
966         return $mod_strings;
967 }
968 /**
969  * checks system compliance for 4.5+ codebase
970  * @return array Mixed values
971  */
972 function checkSystemCompliance() {
973         global $sugar_config;
974         global $current_language;
975         global $db;
976         global $mod_strings;
977     global $app_strings;
978
979         if(!defined('SUGARCRM_MIN_MEM')) {
980                 define('SUGARCRM_MIN_MEM', 40);
981         }
982
983         $installer_mod_strings = getModuleLanguagePack($current_language, './install');
984         $ret = array();
985         $ret['error_found'] = false;
986
987         // PHP version
988         $php_version = constant('PHP_VERSION');
989         $check_php_version_result = check_php_version($php_version);
990
991         switch($check_php_version_result) {
992                 case -1:
993                         $ret['phpVersion'] = "<b><span class=stop>{$installer_mod_strings['ERR_CHECKSYS_PHP_INVALID_VER']} {$php_version} )</span></b>";
994                         $ret['error_found'] = true;
995                         break;
996                 case 0:
997                         $ret['phpVersion'] = "<b><span class=go>{$installer_mod_strings['ERR_CHECKSYS_PHP_UNSUPPORTED']} {$php_version} )</span></b>";
998                         break;
999                 case 1:
1000                         $ret['phpVersion'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_PHP_OK']} {$php_version} )</span></b>";
1001                         break;
1002         }
1003
1004         // database and connect
1005     $canInstall = $db->canInstall();
1006     if ($canInstall !== true)
1007     {
1008         $ret['error_found'] = true;
1009         if (count($canInstall) == 1)
1010         {
1011             $ret['dbVersion'] = "<b><span class=stop>" . $installer_mod_strings[$canInstall[0]] . "</span></b>";
1012         }
1013         else
1014         {
1015             $ret['dbVersion'] = "<b><span class=stop>" . sprintf($installer_mod_strings[$canInstall[0]], $canInstall[1]) . "</span></b>";
1016         }
1017     }
1018
1019         // XML Parsing
1020         if(function_exists('xml_parser_create')) {
1021                 $ret['xmlStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1022         } else {
1023                 $ret['xmlStatus'] = "<b><span class=stop>{$installer_mod_strings['LBL_CHECKSYS_NOT_AVAILABLE']}</span></b>";
1024                 $ret['error_found'] = true;
1025         }
1026
1027         // cURL
1028         if(function_exists('curl_init')) {
1029                 $ret['curlStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1030         } else {
1031                 $ret['curlStatus'] = "<b><span class=go>{$installer_mod_strings['ERR_CHECKSYS_CURL']}</span></b>";
1032                 $ret['error_found'] = false;
1033         }
1034
1035         // mbstrings
1036         if(function_exists('mb_strlen')) {
1037                 $ret['mbstringStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1038         } else {
1039                 $ret['mbstringStatus'] = "<b><span class=stop>{$installer_mod_strings['ERR_CHECKSYS_MBSTRING']}</span></b>";
1040                 $ret['error_found'] = true;
1041         }
1042
1043         // imap
1044         if(function_exists('imap_open')) {
1045                 $ret['imapStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1046         } else {
1047                 $ret['imapStatus'] = "<b><span class=go>{$installer_mod_strings['ERR_CHECKSYS_IMAP']}</span></b>";
1048                 $ret['error_found'] = false;
1049         }
1050
1051
1052         // safe mode
1053         if('1' == ini_get('safe_mode')) {
1054                 $ret['safeModeStatus'] = "<b><span class=stop>{$installer_mod_strings['ERR_CHECKSYS_SAFE_MODE']}</span></b>";
1055                 $ret['error_found'] = true;
1056         } else {
1057                 $ret['safeModeStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1058         }
1059
1060
1061         // call time pass by ref
1062     if('1' == ini_get('allow_call_time_pass_reference')) {
1063                 $ret['callTimeStatus'] = "<b><span class=stop>{$installer_mod_strings['ERR_CHECKSYS_CALL_TIME']}</span></b>";
1064                 //continue upgrading
1065         } else {
1066                 $ret['callTimeStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1067         }
1068
1069         // memory limit
1070         $ret['memory_msg']     = "";
1071         $memory_limit   = "-1";//ini_get('memory_limit');
1072         $sugarMinMem = constant('SUGARCRM_MIN_MEM');
1073         // logic based on: http://us2.php.net/manual/en/ini.core.php#ini.memory-limit
1074         if( $memory_limit == "" ){          // memory_limit disabled at compile time, no memory limit
1075             $ret['memory_msg'] = "<b><span class=\"go\">{$installer_mod_strings['LBL_CHECKSYS_MEM_OK']}</span></b>";
1076         } elseif( $memory_limit == "-1" ){   // memory_limit enabled, but set to unlimited
1077             $ret['memory_msg'] = "<b><span class=\"go\">{$installer_mod_strings['LBL_CHECKSYS_MEM_UNLIMITED']}</span></b>";
1078         } else {
1079             rtrim($memory_limit, 'M');
1080             $memory_limit_int = (int) $memory_limit;
1081             if( $memory_limit_int < constant('SUGARCRM_MIN_MEM') ){
1082                 $ret['memory_msg'] = "<b><span class=\"stop\">{$installer_mod_strings['ERR_CHECKSYS_MEM_LIMIT_1']}" . constant('SUGARCRM_MIN_MEM') . "{$installer_mod_strings['ERR_CHECKSYS_MEM_LIMIT_2']}</span></b>";
1083                         $ret['error_found'] = true;
1084             } else {
1085                         $ret['memory_msg'] = "<b><span class=\"go\">{$installer_mod_strings['LBL_CHECKSYS_OK']} ({$memory_limit})</span></b>";
1086             }
1087         }
1088         // zip support
1089     if (!class_exists("ZipArchive"))
1090     {
1091         $ret['ZipStatus'] = "<b><span class=stop>{$installer_mod_strings['ERR_CHECKSYS_ZIP']}</span></b>";
1092         $ret['error_found'] = true;
1093     } else {
1094         $ret['ZipStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1095     }
1096
1097
1098
1099     // Suhosin allow to use upload://
1100     $ret['stream_msg'] = '';
1101     if (UploadStream::getSuhosinStatus() == true)
1102     {
1103         $ret['stream_msg'] = "<b><span class=\"go\">{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1104     }
1105     else
1106     {
1107         $ret['stream_msg'] = "<b><span class=\"stop\">{$app_strings['ERR_SUHOSIN']}</span></b>";
1108         $ret['error_found'] = true;
1109     }
1110
1111         /* mbstring.func_overload
1112         $ret['mbstring.func_overload'] = '';
1113         $mb = ini_get('mbstring.func_overload');
1114
1115         if($mb > 1) {
1116                 $ret['mbstring.func_overload'] = "<b><span class=\"stop\">{$mod_strings['ERR_UW_MBSTRING_FUNC_OVERLOAD']}</b>";
1117                 $ret['error_found'] = true;
1118         }
1119         */
1120         return $ret;
1121 }
1122
1123
1124 /**
1125  * is a file that we blow away automagically
1126  */
1127 function isAutoOverwriteFile($file) {
1128         $overwriteDirs = array(
1129                 './sugar_version.php',
1130                 './modules/UpgradeWizard/uw_main.tpl',
1131         );
1132         $file = trim('.'.str_replace(clean_path(getcwd()), '', $file));
1133
1134         if(in_array($file, $overwriteDirs)) {
1135                 return true;
1136         }
1137
1138         $fileExtension = substr(strrchr($file, "."), 1);
1139         if($fileExtension == 'tpl' || $fileExtension == 'html') {
1140                 return false;
1141         }
1142
1143         return true;
1144 }
1145
1146 /**
1147  * flatfile logger
1148  */
1149 function logThis($entry, $path='') {
1150         global $mod_strings;
1151         if(file_exists('include/utils/sugar_file_utils.php')){
1152                 require_once('include/utils/sugar_file_utils.php');
1153         }
1154                 $log = empty($path) ? clean_path(getcwd().'/upgradeWizard.log') : clean_path($path);
1155
1156                 // create if not exists
1157                 if(!file_exists($log)) {
1158                         if(function_exists('sugar_fopen')){
1159                                 $fp = @sugar_fopen($log, 'w+'); // attempts to create file
1160                      }
1161                      else{
1162                                 $fp = fopen($log, 'w+'); // attempts to create file
1163                      }
1164                         if(!is_resource($fp)) {
1165                                 $GLOBALS['log']->fatal('UpgradeWizard could not create the upgradeWizard.log file');
1166                                 die($mod_strings['ERR_UW_LOG_FILE_UNWRITABLE']);
1167                         }
1168                 } else {
1169                         if(function_exists('sugar_fopen')){
1170                                 $fp = @sugar_fopen($log, 'a+'); // write pointer at end of file
1171                      }
1172                      else{
1173                                 $fp = @fopen($log, 'a+'); // write pointer at end of file
1174                      }
1175
1176                         if(!is_resource($fp)) {
1177                                 $GLOBALS['log']->fatal('UpgradeWizard could not open/lock upgradeWizard.log file');
1178                                 die($mod_strings['ERR_UW_LOG_FILE_UNWRITABLE']);
1179                         }
1180                 }
1181
1182                 $line = date('r').' [UpgradeWizard] - '.$entry."\n";
1183
1184                 if(@fwrite($fp, $line) === false) {
1185                         $GLOBALS['log']->fatal('UpgradeWizard could not write to upgradeWizard.log: '.$entry);
1186                         die($mod_strings['ERR_UW_LOG_FILE_UNWRITABLE']);
1187                 }
1188
1189                 if(is_resource($fp)) {
1190                         fclose($fp);
1191                 }
1192 }
1193
1194 /**
1195         *  @params : none
1196         *  @author: nsingh
1197         *  @desc This function is to be used in the upgrade process to preserve changes/customaizations made to pre 5.1 quickcreate layout.
1198         *  Prior to 5.1 we have been using editviewdefs as the base for quickcreatedefs. If a custom field was added to edit view layout, it
1199         *  was automatically picked up by the quick create. [Addresses Bug 21469]
1200         *  This function will check if customizations were made, and will create quickcreatedefs.php in the /cutom/working/$module_name directory.
1201         **/
1202 function updateQuickCreateDefs(){
1203         $d = dir('modules');
1204         $studio_modules = array();
1205
1206         while($e = $d->read()){ //collect all studio modules.
1207                 if(substr($e, 0, 1) == '.' || !is_dir('modules/' . $e))continue;
1208                 if(file_exists('modules/' . $e . '/metadata/studio.php'))
1209                 {
1210                         array_push($studio_modules, $e);
1211                 }
1212         }
1213
1214         foreach( $studio_modules as $modname ){ //for each studio enabled module
1215                 //Check !exists modules/$modname/metadata/quickcreatedefs.php &&
1216                 //exists custom/$modname/editviewdefs.php (module was customized) &&
1217                 //!exists custom/$modname/quickcreateviewdefs.php
1218
1219                 $editviewdefs = "custom/working/modules/".$modname."/metadata/editviewdefs.php";
1220                 $quickcreatedefs = "custom/working/modules/".$modname."/metadata/quickcreatedefs.php";
1221
1222                 if ( !file_exists("modules/".$modname."/metadata/quickcreatedefs.php") &&
1223                          file_exists($editviewdefs) &&
1224                          !file_exists($quickcreatedefs) ){
1225                                 //clone editviewdef and save it in custom/working/modules/metadata
1226                                 $GLOBALS['log']->debug("Copying editviewdefs.php as quickcreatedefs.php for the $modname module in custom/working/modules/$modname/metadata!");
1227                                 if(copy( $editviewdefs, $quickcreatedefs)){
1228                                         if(file_exists($quickcreatedefs) && is_readable($quickcreatedefs)){
1229                                                 $file = file($quickcreatedefs);
1230                                                 //replace 'EditView' with 'QuickCreate'
1231                                                 $fp = fopen($quickcreatedefs,'w');
1232                                                 foreach($file as &$line){
1233                                                         if(preg_match('/^\s*\'EditView\'\s*=>\s*$/', $line) > 0){
1234                                                                 $line = "'QuickCreate' =>\n";
1235                                                         }
1236                                                         fwrite($fp, $line);
1237                                                 }
1238                                                 //write back.
1239                                                 fclose($fp);
1240                                         }
1241                                         else{
1242                                                 $GLOBALS['log']->debug("Failed to replace 'EditView' with QuickCreate because $quickcreatedefs is either not readable or does not exist.");
1243                                         }
1244                                 }else{
1245                                         $GLOBALS['log']->debug("Failed to copy $editviewdefs to $quickcreatedefs!");
1246                                 }
1247                 }
1248         }
1249 }
1250
1251 /**
1252  * test perms for CREATE queries
1253  */
1254 function testPermsCreate($db, $out) {
1255         logThis('Checking CREATE TABLE permissions...');
1256         global $mod_strings;
1257
1258         if(!$db->checkPrivilege("CREATE TABLE")) {
1259         logThis('cannot CREATE TABLE!');
1260                 $out['db']['dbNoCreate'] = true;
1261                 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_CREATE']}</span></td></tr>";
1262         }
1263     return $out;
1264 }
1265
1266 /**
1267  * test perms for INSERT
1268  */
1269 function testPermsInsert($db, $out, $skip=false) {
1270         logThis('Checking INSERT INTO permissions...');
1271         global $mod_strings;
1272
1273         if(!$db->checkPrivilege("INSERT")) {
1274                 logThis('cannot INSERT INTO!');
1275                 $out['db']['dbNoInsert'] = true;
1276                 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_INSERT']}</span></td></tr>";
1277     }
1278     return $out;
1279 }
1280
1281
1282 /**
1283  * test perms for UPDATE TABLE
1284  */
1285 function testPermsUpdate($db, $out, $skip=false) {
1286         logThis('Checking UPDATE TABLE permissions...');
1287         global $mod_strings;
1288         if(!$db->checkPrivilege("UPDATE")) {
1289                                         logThis('cannot UPDATE TABLE!');
1290                                         $out['db']['dbNoUpdate'] = true;
1291                                         $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_UPDATE']}</span></td></tr>";
1292     }
1293     return $out;
1294 }
1295
1296
1297 /**
1298  * test perms for SELECT
1299  */
1300 function testPermsSelect($db, $out, $skip=false) {
1301         logThis('Checking SELECT permissions...');
1302         global $mod_strings;
1303         if(!$db->checkPrivilege("SELECT")) {
1304                                 logThis('cannot SELECT!');
1305                                 $out['db']['dbNoSelect'] = true;
1306                                 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_SELECT']}</span></td></tr>";
1307     }
1308     return $out;
1309 }
1310
1311 /**
1312  * test perms for DELETE
1313  */
1314 function testPermsDelete($db, $out, $skip=false) {
1315         logThis('Checking DELETE FROM permissions...');
1316         global $mod_strings;
1317         if(!$db->checkPrivilege("DELETE")) {
1318                                 logThis('cannot DELETE FROM!');
1319                                 $out['db']['dbNoDelete'] = true;
1320                                 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_DELETE']}</span></td></tr>";
1321     }
1322     return $out;
1323 }
1324
1325
1326 /**
1327  * test perms for ALTER TABLE ADD COLUMN
1328  */
1329 function testPermsAlterTableAdd($db, $out, $skip=false) {
1330         logThis('Checking ALTER TABLE ADD COLUMN permissions...');
1331         global $mod_strings;
1332         if(!$db->checkPrivilege("ADD COLUMN")) {
1333                                 logThis('cannot ADD COLUMN!');
1334                                 $out['db']['dbNoAddColumn'] = true;
1335                                 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_ADD_COLUMN']}</span></td></tr>";
1336     }
1337     return $out;
1338 }
1339
1340 /**
1341  * test perms for ALTER TABLE ADD COLUMN
1342  */
1343 function testPermsAlterTableChange($db, $out, $skip=false) {
1344         logThis('Checking ALTER TABLE CHANGE COLUMN permissions...');
1345         global $mod_strings;
1346         if(!$db->checkPrivilege("CHANGE COLUMN")) {
1347                                 logThis('cannot CHANGE COLUMN!');
1348                                 $out['db']['dbNoChangeColumn'] = true;
1349                                 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_CHANGE_COLUMN']}</span></td></tr>";
1350     }
1351     return $out;
1352 }
1353
1354 /**
1355  * test perms for ALTER TABLE DROP COLUMN
1356  */
1357 function testPermsAlterTableDrop($db, $out, $skip=false) {
1358         logThis('Checking ALTER TABLE DROP COLUMN permissions...');
1359         global $mod_strings;
1360         if(!$db->checkPrivilege("DROP COLUMN")) {
1361                                 logThis('cannot DROP COLUMN!');
1362                                 $out['db']['dbNoDropColumn'] = true;
1363                                 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_DROP_COLUMN']}</span></td></tr>";
1364     }
1365     return $out;
1366 }
1367
1368
1369 /**
1370  * test perms for DROP TABLE
1371  */
1372 function testPermsDropTable($db, $out, $skip=false) {
1373         logThis('Checking DROP TABLE permissions...');
1374         global $mod_strings;
1375         if(!$db->checkPrivilege("DROP TABLE")) {
1376                                 logThis('cannot DROP TABLE!');
1377                                 $out['db']['dbNoDropTable'] = true;
1378                                 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_DROP_TABLE']}</span></td></tr>";
1379     }
1380     return $out;
1381 }
1382
1383 function getFormattedError($error, $query) {
1384         $error = "<div><b>".$error;
1385         $error .= "</b>::{$query}</div>";
1386
1387         return $error;
1388 }
1389
1390 /**
1391  * parses a query finding the table name
1392  * @param string query The query
1393  * @return string table The table
1394  */
1395 function getTableFromQuery($query) {
1396         $standardQueries = array('ALTER TABLE', 'DROP TABLE', 'CREATE TABLE', 'INSERT INTO', 'UPDATE', 'DELETE FROM');
1397         $query = preg_replace("/[^A-Za-z0-9\_\s]/", "", $query);
1398         $query = trim(str_replace($standardQueries, '', $query));
1399
1400         $firstSpc = strpos($query, " ");
1401         $end = ($firstSpc > 0) ? $firstSpc : strlen($query);
1402         $table = substr($query, 0, $end);
1403
1404         return $table;
1405 }
1406
1407 //prelicense check
1408
1409 function preLicenseCheck() {
1410         require_once('modules/UpgradeWizard/uw_files.php');
1411
1412         global $sugar_config;
1413         global $mod_strings;
1414         global $sugar_version;
1415
1416         if(!isset($sugar_version) || empty($sugar_version)) {
1417                 require_once('./sugar_version.php');
1418         }
1419
1420 if(!isset($_SESSION['unzip_dir']) || empty($_SESSION['unzip_dir'])) {
1421                 logThis('unzipping files in upgrade archive...');
1422                 $errors                                 = array();
1423                 list($base_upgrade_dir, $base_tmp_upgrade_dir) = getUWDirs();
1424                 $unzip_dir = '';
1425                 //also come up with mechanism to read from upgrade-progress file
1426                 if(!isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !is_file($_SESSION['install_file'])) {
1427                         if (file_exists(clean_path($base_tmp_upgrade_dir)) && $handle = opendir(clean_path($base_tmp_upgrade_dir))) {
1428                                 while (false !== ($file = readdir($handle))) {
1429                                 if($file !="." && $file !="..") {
1430                                          if(is_file($base_tmp_upgrade_dir."/".$file."/manifest.php")){
1431                                                 require_once($base_tmp_upgrade_dir."/".$file."/manifest.php");
1432                                                 $package_name= $manifest['copy_files']['from_dir'];
1433                                                 if(file_exists($base_tmp_upgrade_dir."/".$file."/".$package_name) && file_exists($base_tmp_upgrade_dir."/".$file."/scripts") && file_exists($base_tmp_upgrade_dir."/".$file."/manifest.php")){
1434                                                         $unzip_dir = $base_tmp_upgrade_dir."/".$file;
1435                                                         if(file_exists("$base_upgrade_dir/patch/".$package_name.'.zip')){
1436                                                                 $_SESSION['install_file'] = $package_name.".zip";
1437                                                                 break;
1438                                                         }
1439                                                 }
1440                                           }
1441                                 }
1442                         }
1443                         }
1444                 }
1445         if(empty($_SESSION['install_file'])){
1446                 unlinkUWTempFiles();
1447                 resetUwSession();
1448                 echo 'Upload File not found so redirecting to Upgrade Start ';
1449                 $redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
1450                 echo '<form name="redirect" action="' .$redirect_new_wizard. '"  method="POST">';
1451 $upgrade_directories_not_found =<<<eoq
1452         <table cellpadding="3" cellspacing="0" border="0">
1453                 <tr>
1454                         <th colspan="2" align="left">
1455                                 <span class='error'><b>'Upload file missing or has been deleted. Refresh the page to go back to UpgradeWizard start'</b></span>
1456                         </th>
1457                 </tr>
1458         </table>
1459 eoq;
1460 $uwMain = $upgrade_directories_not_found;
1461                                 return '';
1462         }
1463                 $install_file                   = "$base_upgrade_dir/patch/".basename(urldecode( $_SESSION['install_file'] ));
1464                 $show_files                             = true;
1465                 if(empty($unzip_dir)){
1466                         $unzip_dir                              = mk_temp_dir( $base_tmp_upgrade_dir );
1467                 }
1468                 $zip_from_dir                   = ".";
1469                 $zip_to_dir                             = ".";
1470                 $zip_force_copy                 = array();
1471
1472                 if(!$unzip_dir){
1473                         logThis('Could not create a temporary directory using mk_temp_dir( $base_tmp_upgrade_dir )');
1474                         die($mod_strings['ERR_UW_NO_CREATE_TMP_DIR']);
1475                 }
1476
1477                 //double check whether unzipped .
1478                 if(file_exists($unzip_dir ."/scripts") && file_exists($unzip_dir."/manifest.php")){
1479                 //already unzipped
1480                 }
1481                 else{
1482                         unzip( $install_file, $unzip_dir );
1483                 }
1484
1485                 // assumption -- already validated manifest.php at time of upload
1486                 require_once( "$unzip_dir/manifest.php" );
1487
1488                 if( isset( $manifest['copy_files']['from_dir'] ) && $manifest['copy_files']['from_dir'] != "" ){
1489                     $zip_from_dir   = $manifest['copy_files']['from_dir'];
1490                 }
1491                 if( isset( $manifest['copy_files']['to_dir'] ) && $manifest['copy_files']['to_dir'] != "" ){
1492                     $zip_to_dir     = $manifest['copy_files']['to_dir'];
1493                 }
1494                 if( isset( $manifest['copy_files']['force_copy'] ) && $manifest['copy_files']['force_copy'] != "" ){
1495                     $zip_force_copy     = $manifest['copy_files']['force_copy'];
1496                 }
1497                 if( isset( $manifest['version'] ) ){
1498                     $version    = $manifest['version'];
1499                 }
1500                 if( !is_writable( "config.php" ) ){
1501                         return $mod_strings['ERR_UW_CONFIG'];
1502                 }
1503
1504                 $_SESSION['unzip_dir'] = clean_path($unzip_dir);
1505                 $_SESSION['zip_from_dir'] = clean_path($zip_from_dir);
1506                 logThis('unzip done.');
1507         } else {
1508                 $unzip_dir = $_SESSION['unzip_dir'];
1509                 $zip_from_dir = $_SESSION['zip_from_dir'];
1510         }
1511
1512     //check if $_SESSION['unzip_dir'] and $_SESSION['zip_from_dir'] exist
1513         if(!isset($_SESSION['unzip_dir']) || !file_exists($_SESSION['unzip_dir'])
1514                 || !isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !file_exists($_SESSION['install_file'])){
1515                     //redirect to start
1516             unlinkUWTempFiles();
1517                 resetUwSession();
1518                 echo 'Upload File not found so redirecting to Upgrade Start ';
1519                 $redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
1520                 echo '<form name="redirect" action="' .$redirect_new_wizard. '"  method="POST">';
1521 $upgrade_directories_not_found =<<<eoq
1522         <table cellpadding="3" cellspacing="0" border="0">
1523                 <tr>
1524                         <th colspan="2" align="left">
1525                                 <span class='error'><b>'Upload file missing or has been deleted. Refresh the page to go back to UpgradeWizard start'</b></span>
1526                         </th>
1527                 </tr>
1528         </table>
1529 eoq;
1530 $uwMain = $upgrade_directories_not_found;
1531                                 return '';
1532         }
1533
1534     logThis ('is SugarConfig there '.file_exists(clean_path($unzip_dir.'/'.$zip_from_dir."/include/SugarObjects/SugarConfig.php")));
1535         if(file_exists(clean_path($unzip_dir.'/'.$zip_from_dir."/include/SugarObjects/SugarConfig.php"))) {
1536                 $file = clean_path($unzip_dir.'/'.$zip_from_dir."/include/SugarObjects/SugarConfig.php");
1537                 $destFile = str_replace(clean_path($unzip_dir.'/'.$zip_from_dir), $cwd, $file);
1538                 if(!is_dir(dirname($destFile))) {
1539                         mkdir_recursive(dirname($destFile)); // make sure the directory exists
1540                 }
1541         copy($file,$destFile);
1542         //also copy include utils array utils
1543         $file = clean_path($unzip_dir.'/'.$zip_from_dir."/include/utils/array_utils.php");
1544                 $destFile = str_replace(clean_path($unzip_dir.'/'.$zip_from_dir), $cwd, $file);
1545                 if(!is_dir(dirname($destFile))) {
1546                         mkdir_recursive(dirname($destFile)); // make sure the directory exists
1547                 }
1548         copy($file,$destFile);
1549         }
1550 }
1551
1552
1553 function preflightCheck() {
1554         require_once('modules/UpgradeWizard/uw_files.php');
1555
1556         global $sugar_config;
1557         global $mod_strings;
1558         global $sugar_version;
1559
1560         if(!isset($sugar_version) || empty($sugar_version)) {
1561                 require_once('./sugar_version.php');
1562         }
1563
1564         unset($_SESSION['rebuild_relationships']);
1565         unset($_SESSION['rebuild_extensions']);
1566
1567         // don't bother if are rechecking
1568         $manualDiff                     = array();
1569         if(!isset($_SESSION['unzip_dir']) || empty($_SESSION['unzip_dir'])) {
1570                 logThis('unzipping files in upgrade archive...');
1571                 $errors                                 = array();
1572                 list($base_upgrade_dir, $base_tmp_upgrade_dir) = getUWDirs();
1573                 $unzip_dir = '';
1574                 //Following is if User logged out unexpectedly and then logged into UpgradeWizard again.
1575                 //also come up with mechanism to read from upgrade-progress file.
1576                 if(!isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !is_file($_SESSION['install_file'])) {
1577                         if (file_exists($base_tmp_upgrade_dir) && $handle = opendir($base_tmp_upgrade_dir)) {
1578                         while (false !== ($file = readdir($handle))) {
1579                                 if($file !="." && $file !="..") {
1580                                          if(is_file($base_tmp_upgrade_dir."/".$file."/manifest.php")){
1581                                                 require_once($base_tmp_upgrade_dir."/".$file."/manifest.php");
1582                                                 $package_name= $manifest['copy_files']['from_dir'];
1583                                                 if(file_exists($base_tmp_upgrade_dir."/".$file."/".$package_name) && file_exists($base_tmp_upgrade_dir."/".$file."/scripts") && file_exists($base_tmp_upgrade_dir."/".$file."/manifest.php")){
1584                                                         $unzip_dir = $base_tmp_upgrade_dir."/".$file;
1585                                                         if(file_exists("$base_upgrade_dir/patch/".$package_name.'.zip')){
1586                                                                 $_SESSION['install_file'] = $package_name.".zip";
1587                                                                 break;
1588                                                         }
1589                                                 }
1590                                           }
1591                                 }
1592                         }
1593                         }
1594                 }
1595         if(empty($_SESSION['install_file'])){
1596                 unlinkUWTempFiles();
1597                 resetUwSession();
1598                 echo 'Upload File not found so redirecting to Upgrade Start ';
1599                 $redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
1600                 echo '<form name="redirect" action="' .$redirect_new_wizard. '"  method="POST">';
1601 $upgrade_directories_not_found =<<<eoq
1602         <table cellpadding="3" cellspacing="0" border="0">
1603                 <tr>
1604                         <th colspan="2" align="left">
1605                                 <span class='error'><b>'Upload file missing or has been deleted. Refresh the page to go back to UpgradeWizard start'</b></span>
1606                         </th>
1607                 </tr>
1608         </table>
1609 eoq;
1610 $uwMain = $upgrade_directories_not_found;
1611                                 return '';
1612
1613         }
1614                 $install_file                   = "$base_upgrade_dir/patch/".basename(urldecode( $_SESSION['install_file'] ));
1615                 $show_files                             = true;
1616                 if(empty($unzip_dir)){
1617                         $unzip_dir                              = mk_temp_dir( $base_tmp_upgrade_dir );
1618                 }
1619                 $zip_from_dir                   = ".";
1620                 $zip_to_dir                             = ".";
1621                 $zip_force_copy                 = array();
1622
1623                 if(!$unzip_dir){
1624                         logThis('Could not create a temporary directory using mk_temp_dir( $base_tmp_upgrade_dir )');
1625                         die($mod_strings['ERR_UW_NO_CREATE_TMP_DIR']);
1626                 }
1627
1628                 //double check whether unzipped .
1629                 if(file_exists($unzip_dir ."/scripts") && file_exists($unzip_dir."/manifest.php")){
1630                 //already unzipped
1631                 }
1632                 else{
1633                         unzip( $install_file, $unzip_dir );
1634                 }
1635
1636                 // assumption -- already validated manifest.php at time of upload
1637                 require_once( "$unzip_dir/manifest.php" );
1638
1639                 if( isset( $manifest['copy_files']['from_dir'] ) && $manifest['copy_files']['from_dir'] != "" ){
1640                     $zip_from_dir   = $manifest['copy_files']['from_dir'];
1641                 }
1642                 if( isset( $manifest['copy_files']['to_dir'] ) && $manifest['copy_files']['to_dir'] != "" ){
1643                     $zip_to_dir     = $manifest['copy_files']['to_dir'];
1644                 }
1645                 if( isset( $manifest['copy_files']['force_copy'] ) && $manifest['copy_files']['force_copy'] != "" ){
1646                     $zip_force_copy     = $manifest['copy_files']['force_copy'];
1647                 }
1648                 if( isset( $manifest['version'] ) ){
1649                     $version    = $manifest['version'];
1650                 }
1651                 if( !is_writable( "config.php" ) ){
1652                         return $mod_strings['ERR_UW_CONFIG'];
1653                 }
1654
1655                 $_SESSION['unzip_dir'] = clean_path($unzip_dir);
1656                 $_SESSION['zip_from_dir'] = clean_path($zip_from_dir);
1657
1658          //logThis('unzip done.');
1659         } else {
1660                 $unzip_dir = $_SESSION['unzip_dir'];
1661                 $zip_from_dir = $_SESSION['zip_from_dir'];
1662         }
1663         //check if $_SESSION['unzip_dir'] and $_SESSION['zip_from_dir'] exist
1664         if(!isset($_SESSION['unzip_dir']) || !file_exists($_SESSION['unzip_dir'])
1665                 || !isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !file_exists($_SESSION['install_file'])){
1666                     //redirect to start
1667             unlinkUWTempFiles();
1668                 resetUwSession();
1669                 echo 'Upload File not found so redirecting to Upgrade Start ';
1670                 $redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
1671                 echo '<form name="redirect" action="' .$redirect_new_wizard. '"  method="POST">';
1672 $upgrade_directories_not_found =<<<eoq
1673         <table cellpadding="3" cellspacing="0" border="0">
1674                 <tr>
1675                         <th colspan="2" align="left">
1676                                 <span class='error'><b>'Upload file missing or has been deleted. Refresh the page to go back to UpgradeWizard start'</b></span>
1677                         </th>
1678                 </tr>
1679         </table>
1680 eoq;
1681 $uwMain = $upgrade_directories_not_found;
1682                                 return '';
1683         }
1684         //copy minimum required files
1685         fileCopy('include/utils/sugar_file_utils.php');
1686
1687         $upgradeFiles = findAllFiles(clean_path("$unzip_dir/$zip_from_dir"), array());
1688         $cache_html_files= array();
1689
1690         // get md5 sums
1691         $md5_string = array();
1692         if(file_exists(clean_path(getcwd().'/files.md5'))){
1693                 require(clean_path(getcwd().'/files.md5'));
1694         }
1695
1696         // file preflight checks
1697         logThis('verifying md5 checksums for files...');
1698         foreach($upgradeFiles as $file) {
1699                 if(in_array(str_replace(clean_path("$unzip_dir/$zip_from_dir") . "/", '', $file), $uw_files))
1700                         continue; // skip already loaded files
1701
1702                 if(strpos($file, '.md5'))
1703                         continue; // skip md5 file
1704
1705                 // normalize file paths
1706                 $file = clean_path($file);
1707
1708                 // check that we can move/delete the upgraded file
1709                 if(!is_writable($file)) {
1710                         $errors[] = $mod_strings['ERR_UW_FILE_NOT_WRITABLE'].": ".$file;
1711                 }
1712                 // check that destination files are writable
1713                 $destFile = getcwd().str_replace(clean_path($unzip_dir.'/'.$zip_from_dir), '', $file);
1714
1715                 if(is_file($destFile)) { // of course it needs to exist first...
1716                         if(!is_writable($destFile)) {
1717                                 $errors[] = $mod_strings['ERR_UW_FILE_NOT_WRITABLE'].": ".$destFile;
1718                         }
1719                 }
1720
1721                 ///////////////////////////////////////////////////////////////////////
1722                 ////    DIFFS
1723                 // compare md5s and build up a manual merge list
1724                 $targetFile = clean_path(".".str_replace(getcwd(),'',$destFile));
1725                 $targetMd5 = '0';
1726                 if(is_file($destFile)) {
1727                         if(strpos($targetFile, '.php')) {
1728                                 // handle PHP files that were hit with the security regex
1729                                 $fp = '';
1730                                 if(function_exists('sugar_fopen')){
1731                                         $fp = sugar_fopen($destFile, 'r');
1732                                 }
1733                                 else{
1734                                         $fp = fopen($destFile, 'r');
1735                                 }
1736                                 $filesize = filesize($destFile);
1737                                 if($filesize > 0) {
1738                                         $fileContents = stream_get_contents($fp);
1739                                         $targetMd5 = md5($fileContents);
1740                                 }
1741                         } else {
1742                                 $targetMd5 = md5_file($destFile);
1743                         }
1744                 }
1745
1746                 if(isset($md5_string[$targetFile]) && $md5_string[$targetFile] != $targetMd5) {
1747                         logThis('found a file with a differing md5: ['.$targetFile.']');
1748                         $manualDiff[] = $destFile;
1749                 }
1750                 ////    END DIFFS
1751                 ///////////////////////////////////////////////////////////////////////
1752         }
1753         logThis('md5 verification done.');
1754         $errors['manual'] = $manualDiff;
1755
1756         return $errors;
1757 }
1758
1759 function fileCopy($file_path){
1760         if(file_exists(clean_path($_SESSION['unzip_dir'].'/'.$_SESSION['zip_from_dir'].'/'.$file_path))) {
1761                 $file = clean_path($_SESSION['unzip_dir'].'/'.$_SESSION['zip_from_dir'].'/'.$file_path);
1762                 $destFile = str_replace(clean_path($_SESSION['unzip_dir'].'/'.$_SESSION['zip_from_dir']),  clean_path(getcwd()), $file);
1763         if(!is_dir(dirname($destFile))) {
1764                 mkdir_recursive(dirname($destFile)); // make sure the directory exists
1765                 }
1766                 copy_recursive($file,$destFile);
1767         }
1768 }
1769 function getChecklist($steps, $step) {
1770         global $mod_strings;
1771
1772         $skip = array('start', 'cancel', 'uninstall','end');
1773         $j=0;
1774         $i=1;
1775         $ret  = '<table cellpadding="3" cellspacing="4" border="0">';
1776         $ret .= '<tr><th colspan="3" align="left">'.$mod_strings['LBL_UW_CHECKLIST'].':</th></tr>';
1777         foreach($steps['desc'] as $k => $desc) {
1778                 if(in_array($steps['files'][$j], $skip)) {
1779                         $j++;
1780                         continue;
1781                 }
1782
1783                 //$status = "<span class='error'>{$mod_strings['LBL_UW_INCOMPLETE']}</span>";
1784                 $desc_mod_pre = '';
1785                 $desc_mod_post = '';
1786                 /*
1787                 if(isset($_SESSION['step'][$steps['files'][$k]]) && $_SESSION['step'][$steps['files'][$k]] == 'success') {
1788                         //$status = $mod_strings['LBL_UW_COMPLETE'];
1789                 }
1790                 */
1791
1792                 if($k == $_REQUEST['step']) {
1793                         //$status = $mod_strings['LBL_UW_IN_PROGRESS'];
1794                         $desc_mod_pre = "<font color=blue><i>";
1795                         $desc_mod_post = "</i></font>";
1796                 }
1797
1798                 $ret .= "<tr><td>&nbsp;</td><td><b>{$i}: {$desc_mod_pre}{$desc}{$desc_mod_post}</b></td>";
1799                 $ret .= "<td id={$steps['files'][$j]}><i></i></td></tr>";
1800                 $i++;
1801                 $j++;
1802         }
1803         $ret .= "</table>";
1804         return $ret;
1805 }
1806
1807 function prepSystemForUpgrade() {
1808         global $sugar_config;
1809         global $sugar_flavor;
1810         global $mod_strings;
1811     global $current_language;
1812         global $subdirs;
1813         global $base_upgrade_dir;
1814         global $base_tmp_upgrade_dir;
1815     list($p_base_upgrade_dir, $p_base_tmp_upgrade_dir) = getUWDirs();
1816         ///////////////////////////////////////////////////////////////////////////////
1817         ////    Make sure variables exist
1818         if(empty($base_upgrade_dir)){
1819                 $base_upgrade_dir       = $p_base_upgrade_dir;
1820         }
1821         if(empty($base_tmp_upgrade_dir)){
1822                 $base_tmp_upgrade_dir   = $p_base_tmp_upgrade_dir;
1823         }
1824         sugar_mkdir($base_tmp_upgrade_dir, 0775, true);
1825         if(!isset($subdirs) || empty($subdirs)){
1826                 $subdirs = array('full', 'langpack', 'module', 'patch', 'theme');
1827         }
1828
1829     $upgrade_progress_dir = $base_tmp_upgrade_dir;
1830     $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
1831     if(file_exists($upgrade_progress_file)){
1832         if(function_exists('get_upgrade_progress') && function_exists('didThisStepRunBefore')){
1833                 if(didThisStepRunBefore('end')){
1834                         include($upgrade_progress_file);
1835                         unset($upgrade_config);
1836                         unlink($upgrade_progress_file);
1837                 }
1838         }
1839     }
1840
1841     // increase the cuttoff time to 1 hour
1842         ini_set("max_execution_time", "3600");
1843
1844     // make sure dirs exist
1845         if($subdirs != null){
1846                 foreach($subdirs as $subdir) {
1847                     sugar_mkdir("$base_upgrade_dir/$subdir", 0775, true);
1848                 }
1849         }
1850         // array of special scripts that are executed during (un)installation-- key is type of script, value is filename
1851         if(!defined('SUGARCRM_PRE_INSTALL_FILE')) {
1852                 define('SUGARCRM_PRE_INSTALL_FILE', 'scripts/pre_install.php');
1853                 define('SUGARCRM_POST_INSTALL_FILE', 'scripts/post_install.php');
1854                 define('SUGARCRM_PRE_UNINSTALL_FILE', 'scripts/pre_uninstall.php');
1855                 define('SUGARCRM_POST_UNINSTALL_FILE', 'scripts/post_uninstall.php');
1856         }
1857
1858         $script_files = array(
1859                 "pre-install" => constant('SUGARCRM_PRE_INSTALL_FILE'),
1860                 "post-install" => constant('SUGARCRM_POST_INSTALL_FILE'),
1861                 "pre-uninstall" => constant('SUGARCRM_PRE_UNINSTALL_FILE'),
1862                 "post-uninstall" => constant('SUGARCRM_POST_UNINSTALL_FILE'),
1863         );
1864
1865         // check that the upload limit is set to 6M or greater
1866         define('SUGARCRM_MIN_UPLOAD_MAX_FILESIZE_BYTES', 6 * 1024 * 1024);  // 6 Megabytes
1867         $upload_max_filesize = ini_get('upload_max_filesize');
1868         $upload_max_filesize_bytes = return_bytes($upload_max_filesize);
1869
1870         if($upload_max_filesize_bytes < constant('SUGARCRM_MIN_UPLOAD_MAX_FILESIZE_BYTES')) {
1871                 $GLOBALS['log']->debug("detected upload_max_filesize: $upload_max_filesize");
1872         $admin_strings = return_module_language($current_language, 'Administration');
1873                 echo '<p class="error">'.$admin_strings['MSG_INCREASE_UPLOAD_MAX_FILESIZE'].' '.get_cfg_var('cfg_file_path')."</p>\n";
1874         }
1875 }
1876
1877 if ( !function_exists('extractFile') ) {
1878 function extractFile($zip_file, $file_in_zip) {
1879     global $base_tmp_upgrade_dir;
1880
1881         // strip cwd
1882         $absolute_base_tmp_upgrade_dir = clean_path($base_tmp_upgrade_dir);
1883         $relative_base_tmp_upgrade_dir = clean_path(str_replace(clean_path(getcwd()), '', $absolute_base_tmp_upgrade_dir));
1884
1885     // mk_temp_dir expects relative pathing
1886     $my_zip_dir = mk_temp_dir($relative_base_tmp_upgrade_dir);
1887
1888     unzip_file($zip_file, $file_in_zip, $my_zip_dir);
1889
1890     return("$my_zip_dir/$file_in_zip");
1891 }
1892 }
1893
1894 if ( !function_exists('extractManifest') ) {
1895 function extractManifest($zip_file) {
1896         logThis('extracting manifest.');
1897     return(extractFile($zip_file, "manifest.php"));
1898 }
1899 }
1900
1901 if ( !function_exists('getInstallType') ) {
1902 function getInstallType($type_string) {
1903     // detect file type
1904     global $subdirs;
1905         $subdirs = array('full', 'langpack', 'module', 'patch', 'theme', 'temp');
1906     foreach($subdirs as $subdir) {
1907         if(preg_match("#/$subdir/#", $type_string)) {
1908             return($subdir);
1909         }
1910     }
1911     // return empty if no match
1912     return("");
1913 }
1914 }
1915
1916 function getImageForType($type) {
1917     global $image_path;
1918     global $mod_strings;
1919
1920     $icon = "";
1921     switch($type) {
1922         case "full":
1923             $icon = SugarThemeRegistry::current()->getImage("Upgrade", "",null,null,'.gif',$mod_strings['LBL_UPGRADE']);
1924             break;
1925         case "langpack":
1926             $icon = SugarThemeRegistry::current()->getImage("LanguagePacks", "",null,null,'.gif',$mod_strings['LBL_LANGPACKS']);
1927             break;
1928         case "module":
1929             $icon = SugarThemeRegistry::current()->getImage("ModuleLoader", "",null,null,'.gif',$mod_strings['LBL_MODULELOADER']);
1930             break;
1931         case "patch":
1932             $icon = SugarThemeRegistry::current()->getImage("PatchUpgrades", "",null,null,'.gif',$mod_strings['LBL_PATCHUPGRADES']);
1933             break;
1934         case "theme":
1935             $icon = SugarThemeRegistry::current()->getImage("Themes", "",null,null,'.gif',$mod_strings['LBL_THEMES']);
1936             break;
1937         default:
1938             break;
1939     }
1940     return($icon);
1941 }
1942
1943 if ( !function_exists('getLanguagePackName') ) {
1944 function getLanguagePackName($the_file) {
1945     require_once("$the_file");
1946     if(isset($app_list_strings["language_pack_name"])) {
1947         return($app_list_strings["language_pack_name"]);
1948     }
1949     return("");
1950 }
1951 }
1952
1953 function getUITextForType($type) {
1954     if($type == "full") {
1955         return("Full Upgrade");
1956     }
1957     if($type == "langpack") {
1958         return("Language Pack");
1959     }
1960     if($type == "module") {
1961         return("Module");
1962     }
1963     if($type == "patch") {
1964         return("Patch");
1965     }
1966     if($type == "theme") {
1967         return("Theme");
1968     }
1969 }
1970
1971 if ( !function_exists('validate_manifest') ) {
1972 /**
1973  * Verifies a manifest from a patch or module to be compatible with the current Sugar version and flavor
1974  * @param array manifest Standard manifest array
1975  * @return string Error message, blank on success
1976  */
1977 function validate_manifest($manifest) {
1978         logThis('validating manifest.php file');
1979     // takes a manifest.php manifest array and validates contents
1980     global $subdirs;
1981     global $sugar_version;
1982     global $sugar_flavor;
1983         global $mod_strings;
1984
1985     if(!isset($manifest['type'])) {
1986         return $mod_strings['ERROR_MANIFEST_TYPE'];
1987     }
1988
1989     $type = $manifest['type'];
1990
1991     if(getInstallType("/$type/") == "") {
1992                 return $mod_strings['ERROR_PACKAGE_TYPE']. ": '" . $type . "'.";
1993     }
1994
1995     if(isset($manifest['acceptable_sugar_versions'])) {
1996         $version_ok = false;
1997         $matches_empty = true;
1998         if(isset($manifest['acceptable_sugar_versions']['exact_matches'])) {
1999             $matches_empty = false;
2000             foreach($manifest['acceptable_sugar_versions']['exact_matches'] as $match) {
2001                 if($match == $sugar_version) {
2002                     $version_ok = true;
2003                 }
2004             }
2005         }
2006         if(!$version_ok && isset($manifest['acceptable_sugar_versions']['regex_matches'])) {
2007             $matches_empty = false;
2008             foreach($manifest['acceptable_sugar_versions']['regex_matches'] as $match) {
2009                 if(preg_match("/$match/", $sugar_version)) {
2010                     $version_ok = true;
2011                 }
2012             }
2013         }
2014
2015         if(!$matches_empty && !$version_ok) {
2016             return $mod_strings['ERROR_VERSION_INCOMPATIBLE']."<br />".
2017             $mod_strings['ERR_UW_VERSION'].$sugar_version;
2018         }
2019     }
2020
2021     if(isset($manifest['acceptable_sugar_flavors']) && sizeof($manifest['acceptable_sugar_flavors']) > 0) {
2022         $flavor_ok = false;
2023         foreach($manifest['acceptable_sugar_flavors'] as $match) {
2024             if($match == $sugar_flavor) {
2025                 $flavor_ok = true;
2026             }
2027         }
2028         if(!$flavor_ok) {
2029             return $mod_strings['ERROR_FLAVOR_INCOMPATIBLE']."<br />".
2030             $mod_strings['ERR_UW_FLAVOR'].$sugar_flavor."<br />".
2031             $mod_strings['ERR_UW_FLAVOR_2'].$manifest['acceptable_sugar_flavors'][0];
2032         }
2033     }
2034
2035     return '';
2036 }
2037 }
2038
2039 function unlinkUploadFiles() {
2040         return;
2041 //      logThis('at unlinkUploadFiles()');
2042 //
2043 //      if(isset($_SESSION['install_file']) && !empty($_SESSION['install_file'])) {
2044 //              $upload = $_SESSION['install_file'];
2045 //
2046 //              if(is_file($upload)) {
2047 //                      logThis('unlinking ['.$upload.']');
2048 //                      @unlink($upload);
2049 //              }
2050 //      }
2051 }
2052
2053 /**
2054  * deletes files created by unzipping a package
2055  */
2056 function unlinkUWTempFiles() {
2057         global $sugar_config;
2058         global $path;
2059
2060         logThis('at unlinkUWTempFiles()');
2061         $tempDir='';
2062         list($upgDir, $tempDir) = getUWDirs();
2063
2064     if(file_exists($tempDir) && is_dir($tempDir)){
2065                 $files = findAllFiles($tempDir, array(), false);
2066                 rsort($files);
2067                 foreach($files as $file) {
2068                         if(!is_dir($file)) {
2069                                 //logThis('unlinking ['.$file.']', $path);
2070                                 @unlink($file);
2071                         }
2072                 }
2073                 // now do dirs
2074                 $files = findAllFiles($tempDir, array(), true);
2075                 foreach($files as $dir) {
2076                         if(is_dir($dir)) {
2077                                 //logThis('removing dir ['.$dir.']', $path);
2078                                 @rmdir($dir);
2079                         }
2080                 }
2081                 $cacheFile = sugar_cached("modules/UpgradeWizard/_persistence.php");
2082                 if(is_file($cacheFile)) {
2083                         logThis("Unlinking Upgrade cache file: '_persistence.php'", $path);
2084                         @unlink($cacheFile);
2085                 }
2086         }
2087         logThis("finished!");
2088 }
2089
2090 /**
2091  * finds all files in the passed path, but skips select directories
2092  * @param string dir Relative path
2093  * @param array the_array Collections of found files/dirs
2094  * @param bool include_dir True if we want to include directories in the
2095  * returned collection
2096  */
2097 function uwFindAllFiles($dir, $theArray, $includeDirs=false, $skipDirs=array(), $echo=false) {
2098         // check skips
2099     if (whetherNeedToSkipDir($dir, $skipDirs))
2100         {
2101             return $theArray;
2102         }
2103
2104     if (!is_dir($dir)) { return $theArray; }   // Bug # 46035, just checking for valid dir
2105         $d = dir($dir);
2106     if ($d === false)  { return $theArray; }   // Bug # 46035, more checking
2107
2108         while($f = $d->read()) {
2109                                         // bug 40793 Skip Directories array in upgradeWizard does not function correctly
2110             if($f == "." || $f == ".." || whetherNeedToSkipDir("$dir/$f", $skipDirs)) { // skip *nix self/parent
2111                 continue;
2112             }
2113
2114                 // for AJAX length count
2115         if($echo) {
2116                 echo '.';
2117                 ob_flush();
2118         }
2119
2120             if(is_dir("$dir/$f")) {
2121                         if($includeDirs) { // add the directory if flagged
2122                                 $theArray[] = clean_path("$dir/$f");
2123                         }
2124
2125                         // recurse in
2126                 $theArray = uwFindAllFiles("$dir/$f/", $theArray, $includeDirs, $skipDirs, $echo);
2127             } else {
2128                 $theArray[] = clean_path("$dir/$f");
2129             }
2130
2131
2132         }
2133         rsort($theArray);
2134         $d->close();
2135         return $theArray;
2136 }
2137
2138
2139
2140 /**
2141  * unset's UW's Session Vars
2142  */
2143 function resetUwSession() {
2144         logThis('resetting $_SESSION');
2145
2146         if(isset($_SESSION['committed']))
2147                 unset($_SESSION['committed']);
2148         if(isset($_SESSION['sugar_version_file']))
2149                 unset($_SESSION['sugar_version_file']);
2150         if(isset($_SESSION['upgrade_complete']))
2151                 unset($_SESSION['upgrade_complete']);
2152         if(isset($_SESSION['allTables']))
2153                 unset($_SESSION['allTables']);
2154         if(isset($_SESSION['alterCustomTableQueries']))
2155                 unset($_SESSION['alterCustomTableQueries']);
2156         if(isset($_SESSION['skip_zip_upload']))
2157                 unset($_SESSION['skip_zip_upload']);
2158         if(isset($_SESSION['sugar_version_file']))
2159                 unset($_SESSION['sugar_version_file']);
2160         if(isset($_SESSION['install_file']))
2161                 unset($_SESSION['install_file']);
2162         if(isset($_SESSION['unzip_dir']))
2163                 unset($_SESSION['unzip_dir']);
2164         if(isset($_SESSION['zip_from_dir']))
2165                 unset($_SESSION['zip_from_dir']);
2166         if(isset($_SESSION['overwrite_files']))
2167                 unset($_SESSION['overwrite_files']);
2168         if(isset($_SESSION['schema_change']))
2169                 unset($_SESSION['schema_change']);
2170         if(isset($_SESSION['uw_restore_dir']))
2171                 unset($_SESSION['uw_restore_dir']);
2172         if(isset($_SESSION['step']))
2173                 unset($_SESSION['step']);
2174         if(isset($_SESSION['files']))
2175                 unset($_SESSION['files']);
2176         if(isset($_SESSION['Upgraded451Wizard'])){
2177                 unset($_SESSION['Upgraded451Wizard']);
2178         }
2179         if(isset($_SESSION['Initial_451to500_Step'])){
2180                 unset($_SESSION['Initial_451to500_Step']);
2181         }
2182         if(isset($_SESSION['license_shown']))
2183                 unset($_SESSION['license_shown']);
2184     if(isset($_SESSION['sugarMergeRunResults']))
2185                 unset($_SESSION['sugarMergeRunResults']);
2186 }
2187
2188 /**
2189  * runs rebuild scripts
2190  */
2191 function UWrebuild() {
2192         global $db;
2193         global $path;
2194         /*
2195         //CCL - Comment this block out, it is called in end.php
2196         logThis('Rebuilding everything...', $path);
2197         require_once('modules/Administration/QuickRepairAndRebuild.php');
2198         $randc = new RepairAndClear();
2199     $randc->repairAndClearAll(array('clearAll'),array(translate('LBL_ALL_MODULES')), false, false);
2200     */
2201         $query = "DELETE FROM versions WHERE name='Rebuild Extensions'";
2202         $db->query($query);
2203         logThis('Registering rebuild record: '.$query, $path);
2204         logThis('Rebuild done.', $path);
2205
2206         // insert a new database row to show the rebuild extensions is done
2207         $id = create_guid();
2208         $gmdate = gmdate('Y-m-d H:i:s');
2209         $date_entered = db_convert("'$gmdate'", 'datetime');
2210         $query = 'INSERT INTO versions (id, deleted, date_entered, date_modified, modified_user_id, created_by, name, file_version, db_version) '
2211                 . "VALUES ('$id', '0', $date_entered, $date_entered, '1', '1', 'Rebuild Extensions', '4.0.0', '4.0.0')";
2212         $db->query($query);
2213         logThis('Registering rebuild record in versions table: '.$query, $path);
2214 }
2215
2216 function getCustomTables() {
2217         global $db;
2218
2219     return $db->tablesLike('%_cstm');
2220 }
2221
2222 function alterCustomTables($customTables)
2223 {
2224         return array();
2225 }
2226
2227 function getAllTables() {
2228         global $db;
2229     return $db->getTablesArray();
2230 }
2231
2232 function printAlterTableSql($tables)
2233 {
2234         $alterTableSql = '';
2235
2236         foreach($tables as $table)
2237                 $alterTableSql .= "ALTER TABLE " . $table . " CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;" . "\n";
2238
2239         return $alterTableSql;
2240 }
2241
2242 function executeConvertTablesSql($tables)
2243 {
2244         global $db;
2245
2246         foreach($tables as $table){
2247                 $query = "ALTER TABLE " . $table . " CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci";
2248                 if(!empty($table)){
2249                         logThis("Sending query: ".$query);
2250             $db->query($query);//, true, "An error has occured while performing db query.  See log file for details.<br>");
2251          }
2252         }
2253         return true;
2254 }
2255
2256 function testThis() {
2257         $files = uwFindAllFiles(getcwd().'/test', array());
2258
2259         $out = "<table cellpadding='1' cellspacing='0' border='0'>\n";
2260
2261         $priorPath = '';
2262         foreach($files as $file) {
2263                 $relativeFile = clean_path(str_replace(getcwd().'/test', '', $file));
2264                 $relativeFile = ($relativeFile{0} == '/') ? substr($relativeFile, 1, strlen($relativeFile)) : $relativeFile;
2265
2266                 $relativePath = dirname($relativeFile);
2267
2268                 if($relativePath == $priorPath) { // same dir, new file
2269                         $out .= "<tr><td>".basename($relativeFile)."</td></tr>";
2270                         $priorPath = $relativePath;
2271                 } else { // new dir
2272
2273                 }
2274         }
2275
2276         $out .= "</table>";
2277
2278         echo $out;
2279 }
2280
2281
2282
2283
2284 function testThis2($dir, $id=0, $hide=false) {
2285     global $mod_strings;
2286         $path = $dir;
2287         $dh = opendir($dir);
2288         rewinddir($dh);
2289
2290         $doHide = ($hide) ? 'none' : '';
2291         $out = "<div id='{$id}' style='display:{$doHide};'>";
2292         $out .= "<table cellpadding='1' cellspacing='0' style='border:0px solid #ccc'>\n";
2293
2294         while($file = readdir($dh)) {
2295                 if($file == '.' || $file == '..' || $file == 'CVS' || $file == '.cvsignore')
2296                         continue;
2297
2298                 if(is_dir($path.'/'.$file)) {
2299                         $file = $path.'/'.$file;
2300                         $newI = create_guid();
2301                         $out .= "<tr><td valign='top'><a href='javascript:toggleNwFiles(\"{$newI}\");'>".SugarThemeRegistry::current()->getImage("Workflow", "", null, null, ".gif", $mod_strings['LBL_WORKFLOW'])."</a></td>\n";
2302                         $out .= "<td valign='top'><b><a href='javascript:toggleNwFiles(\"{$newI}\");'>".basename($file)."</a></b></td></tr>";
2303                         $out .= "<tr><td></td><td valign='top'>".testThis2($file, $newI, true)."</td></tr>";
2304                 } else {
2305                         $out .= "<tr><td valign='top'>&nbsp;</td>\n";
2306                         $out .= "<td valign='top'>".basename($file)."</td></tr>";
2307                 }
2308         }
2309
2310         $out .= "</tr></table>";
2311         $out .= "</div>";
2312
2313         closedir($dh);
2314         return $out;
2315 }
2316
2317
2318
2319
2320
2321 function testThis3(&$files, $id, $hide, $previousPath = '') {
2322         if(!is_array($files) || empty($files))
2323                 return '';
2324
2325         $out = '';
2326
2327     global $mod_strings;
2328         // expecting full path here
2329         foreach($files as $k => $file) {
2330                 $file = str_replace(getcwd(), '', $file);
2331                 $path = dirname($file);
2332                 $fileName = basename($file);
2333
2334                 if($fileName == 'CVS' || $fileName == '.cvsignore')
2335                         continue;
2336
2337                 if($path == $previousPath) { // same directory
2338                         // new row for each file
2339                         $out .= "<tr><td valign='top' align='left'>&nbsp;</td>";
2340                         $out .= "<td valign='top' align='left'>{$fileName}</td></tr>";
2341                 } else { // new directory
2342                         $newI = $k;
2343                         $out .= "<tr><td valign='top'><a href='javascript:toggleNwFiles(\"{$newI}\");'>".SugarThemeRegistry::current()->getImage("Workflow", "", null, null, ".gif", $mod_strings['LBL_WORKFLOW'])."</a></td>\n";
2344                         $out .= "<td valign='top'><b><a href='javascript:toggleNwFiles(\"{$newI}\");'>".$fileName."</a></b></td></tr>";
2345                         $recurse = testThis3($files, $newI, true, $previousPath);
2346                         $out .= "<tr><td></td><td valign='top'>".$recurse."</td></tr>";
2347                 }
2348
2349                 $previousPath = $path;
2350         }
2351         $display = ($hide) ? 'none' : '';
2352         $ret = <<<eoq
2353         <div id="{$id}" style="display:{$display}">
2354         <table cellpadding='1' cellspacing='0' border='0' style='border:1px solid #ccc'>
2355                 {$out}
2356         </table>
2357         </div>
2358 eoq;
2359         return $ret;
2360 }
2361
2362
2363 function testThis4($filePath, $fileNodes=array(), $fileName='') {
2364         $path = dirname($filePath);
2365         $file = basename($filePath);
2366
2367         $exFile = explode('/', $path);
2368
2369         foreach($exFile as $pathSegment) {
2370                 if(is_array($fileNodes[$pathSegment])) { // path already processed
2371
2372                 } else { // newly found path
2373                         $fileNodes[$pathSegment] = array();
2374                 }
2375
2376                 if($fileName != '') {
2377                         $fileNodes[$pathSegment][] = $fileName;
2378                 }
2379         }
2380
2381         return $fileNodes;
2382 }
2383
2384
2385
2386 ///////////////////////////////////////////////////////////////////////////////
2387 ////    SYSTEM CHECK FUNCTIONS
2388 /**
2389  * generates an array with all files in the SugarCRM root directory, skipping
2390  * cache/
2391  * @return array files Array of files with absolute paths
2392  */
2393 function getFilesForPermsCheck() {
2394         global $sugar_config;
2395
2396         logThis('Got JSON call to find all files...');
2397         $filesNotWritable = array();
2398         $filesNWPerms = array();
2399
2400         // add directories here that should be skipped when doing file permissions checks (cache/upload is the nasty one)
2401         $skipDirs = array(
2402                 $sugar_config['upload_dir'],
2403         );
2404         $files = uwFindAllFiles(".", array(), true, $skipDirs, true);
2405         return $files;
2406 }
2407
2408 /**
2409  * checks files for permissions
2410  * @param array files Array of files with absolute paths
2411  * @return string result of check
2412  */
2413 function checkFiles($files, $echo=false) {
2414         global $mod_strings;
2415         $filesNotWritable = array();
2416         $i=0;
2417         $filesOut = "
2418                 <a href='javascript:void(0); toggleNwFiles(\"filesNw\");'>{$mod_strings['LBL_UW_SHOW_NW_FILES']}</a>
2419                 <div id='filesNw' style='display:none;'>
2420                 <table cellpadding='3' cellspacing='0' border='0'>
2421                 <tr>
2422                         <th align='left'>{$mod_strings['LBL_UW_FILE']}</th>
2423                         <th align='left'>{$mod_strings['LBL_UW_FILE_PERMS']}</th>
2424                         <th align='left'>{$mod_strings['LBL_UW_FILE_OWNER']}</th>
2425                         <th align='left'>{$mod_strings['LBL_UW_FILE_GROUP']}</th>
2426                 </tr>";
2427
2428         $isWindows = is_windows();
2429         foreach($files as $file) {
2430
2431                 if($isWindows) {
2432                         if(!is_writable_windows($file)) {
2433                                 logThis('WINDOWS: File ['.$file.'] not readable - saving for display');
2434                                 // don't warn yet - we're going to use this to check against replacement files
2435         // aw: commented out; it's a hack to allow upgrade wizard to continue on windows... will fix later
2436                                 /*$filesNotWritable[$i] = $file;
2437                                 $filesNWPerms[$i] = substr(sprintf('%o',fileperms($file)), -4);
2438                                 $filesOut .= "<tr>".
2439                                                                 "<td><span class='error'>{$file}</span></td>".
2440                                                                 "<td>{$filesNWPerms[$i]}</td>".
2441                                                                 "<td>".$mod_strings['ERR_UW_CANNOT_DETERMINE_USER']."</td>".
2442                                                                 "<td>".$mod_strings['ERR_UW_CANNOT_DETERMINE_GROUP']."</td>".
2443                                                           "</tr>";*/
2444                         }
2445                 } else {
2446                         if(!is_writable($file)) {
2447                                 logThis('File ['.$file.'] not writable - saving for display');
2448                                 // don't warn yet - we're going to use this to check against replacement files
2449                                 $filesNotWritable[$i] = $file;
2450                                 $filesNWPerms[$i] = substr(sprintf('%o',fileperms($file)), -4);
2451                                 $owner = posix_getpwuid(fileowner($file));
2452                                 $group = posix_getgrgid(filegroup($file));
2453                                 $filesOut .= "<tr>".
2454                                                                 "<td><span class='error'>{$file}</span></td>".
2455                                                                 "<td>{$filesNWPerms[$i]}</td>".
2456                                                                 "<td>".$owner['name']."</td>".
2457                                                                 "<td>".$group['name']."</td>".
2458                                                           "</tr>";
2459                         }
2460                 }
2461                 $i++;
2462         }
2463
2464         $filesOut .= '</table></div>';
2465         // not a stop error
2466         $errors['files']['filesNotWritable'] = (count($filesNotWritable) > 0) ? true : false;
2467         if(count($filesNotWritable) < 1) {
2468                 $filesOut = "{$mod_strings['LBL_UW_FILE_NO_ERRORS']}";
2469         }
2470
2471         return $filesOut;
2472 }
2473
2474 function deletePackageOnCancel(){
2475         global $mod_strings;
2476         global $sugar_config;
2477         list($base_upgrade_dir, $base_tmp_upgrade_dir) = getUWDirs();
2478         logThis('running delete');
2479     if(!isset($_SESSION['install_file']) || ($_SESSION['install_file'] == "")) {
2480         logThis('ERROR: trying to delete non-existent file: ['.$_REQUEST['install_file'].']');
2481         $error = $mod_strings['ERR_UW_NO_FILE_UPLOADED'];
2482     }
2483     // delete file in upgrades/patch
2484     $delete_me = "$base_upgrade_dir/patch/".basename(urldecode( $_REQUEST['install_file'] ));
2485     if(@unlink($delete_me)) {
2486         //logThis('unlinking: '.$delete_me);
2487         $out = basename($delete_me).$mod_strings['LBL_UW_FILE_DELETED'];
2488     } else {
2489         logThis('ERROR: could not delete ['.$delete_me.']');
2490                 $error = $mod_strings['ERR_UW_FILE_NOT_DELETED'].$delete_me;
2491     }
2492
2493     if(!empty($error)) {
2494                 $out = "<b><span class='error'>{$error}</span></b><br />";
2495     }
2496 }
2497
2498 function handleExecuteSqlKeys($db, $tableName, $disable)
2499 {
2500     if(empty($tableName)) return true;
2501     if(is_callable(array($db, "supports"))) {
2502         // new API
2503         return $disable?$db->disableKeys($tableName):$db->enableKeys($tableName);
2504     } else {
2505         // old api
2506         $op = $disable?"DISABLE":"ENABLE";
2507         return $db->query("ALTER TABLE $tableName $op KEYS");
2508     }
2509 }
2510
2511 function parseAndExecuteSqlFile($sqlScript,$forStepQuery='',$resumeFromQuery='')
2512 {
2513         global $sugar_config;
2514         $alterTableSchema = '';
2515         $sqlErrors = array();
2516         if(!isset($_SESSION['sqlSkippedQueries'])){
2517                 $_SESSION['sqlSkippedQueries'] = array();
2518         }
2519         $db = DBManagerFactory::getInstance();
2520         $disable_keys = ($db->dbType == "mysql"); // have to use old way for now for upgrades
2521         if(strpos($resumeFromQuery,",") != false){
2522                 $resumeFromQuery = explode(",",$resumeFromQuery);
2523         }
2524         if(file_exists($sqlScript)) {
2525                 $fp = fopen($sqlScript, 'r');
2526                 $contents = stream_get_contents($fp);
2527                 $anyScriptChanges =$contents;
2528                 $resumeAfterFound = false;
2529                 if(rewind($fp)) {
2530                         $completeLine = '';
2531                         $count = 0;
2532                         while($line = fgets($fp)) {
2533                                 if(strpos($line, '--') === false) {
2534                                         $completeLine .= " ".trim($line);
2535                                         if(strpos($line, ';') !== false) {
2536                                                 $query = '';
2537                                                 $query = str_replace(';','',$completeLine);
2538                                                 //if resume from query is not null then find out from where
2539                                                 //it should start executing the query.
2540
2541                                                 if($query != null && $resumeFromQuery != null){
2542                                                         if(!$resumeAfterFound){
2543                                                                 if(strpos($query,",") != false){
2544                                                                         $queArray = explode(",",$query);
2545                                                                         for($i=0;$i<sizeof($resumeFromQuery);$i++){
2546                                                                                 if(strcasecmp(trim($resumeFromQuery[$i]),trim($queArray[$i]))==0){
2547                                                                                         $resumeAfterFound = true;
2548                                                                                 } else {
2549                                                                                         $resumeAfterFound = false;
2550                                                                                         break;
2551                                                                                 }
2552                                                                         }//for
2553
2554                                                                 }
2555                                                                 elseif(strcasecmp(trim($resumeFromQuery),trim($query))==0){
2556                                                                         $resumeAfterFound = true;
2557                                                                 }
2558                                                         }
2559                                                         if($resumeAfterFound){
2560                                                                 $count++;
2561                                                         }
2562                                                         // if $count=1 means it is just found so skip the query. Run the next one
2563                                                         if($query != null && $resumeAfterFound && $count >1){
2564                                                         $tableName = getAlterTable($query);
2565                                                                 if($disable_keys)
2566                                                                 {
2567                                                                         handleExecuteSqlKeys($db, $tableName, true);
2568                                                                 }
2569                                                                 $db->query($query);
2570                                                                 if($db->checkError()){
2571                                                                         //put in the array to use later on
2572                                                                         $_SESSION['sqlSkippedQueries'][] = $query;
2573                                                                 }
2574                                                                 if($disable_keys)
2575                                                                 {
2576                                                                         handleExecuteSqlKeys($db, $tableName, false);
2577                                                                 }
2578                                                                 $progQuery[$forStepQuery]=$query;
2579                                                                 post_install_progress($progQuery,$action='set');
2580                                                         }//if
2581                                                 }
2582                                                 elseif($query != null){
2583                                                         $tableName = getAlterTable($query);
2584                                                         if($disable_keys)
2585                                                         {
2586                                                                 handleExecuteSqlKeys($db, $tableName, true);
2587                                                         }
2588                                                         $db->query($query);
2589                                                         if($disable_keys)
2590                                                         {
2591                                                                 handleExecuteSqlKeys($db, $tableName, false);
2592                                                         }
2593                                                         $progQuery[$forStepQuery]=$query;
2594                                                         post_install_progress($progQuery,$action='set');
2595                                                         if($db->checkError()){
2596                                                                 //put in the array to use later on
2597                                                                 $_SESSION['sqlSkippedQueries'][] = $query;
2598                                                         }
2599                                                 }
2600                                                 $completeLine = '';
2601                                         }
2602                                 }
2603                         }//while
2604                 }
2605         }
2606 }
2607
2608
2609 function getAlterTable($query){
2610         $query = strtolower($query);
2611         if (preg_match('/^\s*alter\s+table\s+/', $query)) {
2612                 $sqlArray = explode(" ", $query);
2613                 $key = array_search('table', $sqlArray);
2614                 return $sqlArray[($key+1)];
2615         }else {
2616                 return '';
2617         }
2618 }
2619
2620 function set_upgrade_vars(){
2621         logThis('setting session variables...');
2622         $upgrade_progress_dir = sugar_cached('upgrades/temp');
2623         if(!is_dir($upgrade_progress_dir)){
2624                 mkdir_recursive($upgrade_progress_dir);
2625         }
2626         $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
2627         if(file_exists($upgrade_progress_file)){
2628                 include($upgrade_progress_file);
2629         }
2630         else{
2631                 fopen($upgrade_progress_file, 'w+');
2632         }
2633         if(!isset($upgrade_config) || $upgrade_config == null){
2634                 $upgrade_config = array();
2635                 $upgrade_config[1]['upgrade_vars']=array();
2636         }
2637     if(isset($upgrade_config[1]) && isset($upgrade_config[1]['upgrade_vars']) && !is_array($upgrade_config[1]['upgrade_vars'])){
2638         $upgrade_config[1]['upgrade_vars'] = array();
2639     }
2640
2641         if(!isset($upgrade_vars) || $upgrade_vars == NULL){
2642                 $upgrade_vars = array();
2643         }
2644         if(isset($_SESSION['unzip_dir']) && !empty($_SESSION['unzip_dir']) && file_exists($_SESSION['unzip_dir'])){
2645                 $upgrade_vars['unzip_dir']=$_SESSION['unzip_dir'];
2646         }
2647         if(isset($_SESSION['install_file']) && !empty($_SESSION['install_file']) && file_exists($_SESSION['install_file'])){
2648                 $upgrade_vars['install_file']=$_SESSION['install_file'];
2649         }
2650         if(isset($_SESSION['Upgraded451Wizard']) && !empty($_SESSION['Upgraded451Wizard'])){
2651                 $upgrade_vars['Upgraded451Wizard']=$_SESSION['Upgraded451Wizard'];
2652         }
2653         if(isset($_SESSION['license_shown']) && !empty($_SESSION['license_shown'])){
2654                 $upgrade_vars['license_shown']=$_SESSION['license_shown'];
2655         }
2656         if(isset($_SESSION['Initial_451to500_Step']) && !empty($_SESSION['Initial_451to500_Step'])){
2657                 $upgrade_vars['Initial_451to500_Step']=$_SESSION['Initial_451to500_Step'];
2658         }
2659         if(isset($_SESSION['zip_from_dir']) && !empty($_SESSION['zip_from_dir'])){
2660                 $upgrade_vars['zip_from_dir']=$_SESSION['zip_from_dir'];
2661         }
2662         //place into the upgrade_config array and rewrite config array only if new values are being inserted
2663         if(isset($upgrade_vars) && $upgrade_vars != null && sizeof($upgrade_vars) > 0){
2664                 foreach($upgrade_vars as $key=>$val){
2665                         if($key != null && $val != null){
2666                                 $upgrade_config[1]['upgrade_vars'][$key]=$upgrade_vars[$key];
2667                         }
2668                 }
2669                 ksort($upgrade_config);
2670                 if(is_writable($upgrade_progress_file) && write_array_to_file( "upgrade_config", $upgrade_config,
2671                         $upgrade_progress_file)) {
2672                        //writing to the file
2673                 }
2674     }
2675 }
2676
2677 function initialize_session_vars(){
2678   $upgrade_progress_dir = sugar_cached('upgrades/temp');
2679   $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
2680   if(file_exists($upgrade_progress_file)){
2681         include($upgrade_progress_file);
2682         if(isset($upgrade_config) && $upgrade_config != null && is_array($upgrade_config) && sizeof($upgrade_config) >0){
2683                 $currVarsArray=$upgrade_config[1]['upgrade_vars'];
2684                 //print_r($currVarsArray);
2685                 if(isset($currVarsArray) && $currVarsArray != null && is_array($currVarsArray) && sizeof($currVarsArray)>0){
2686                         foreach($currVarsArray as $key=>$val){
2687                                 if($key != null && $val !=null){
2688                                         //set session variables
2689                                         $_SESSION[$key]=$val;
2690                                         //set varibales
2691                                         '$'.$key=$val;
2692                                 }
2693                         }
2694                 }
2695         }
2696   }
2697 }
2698 //track the upgrade progress on each step
2699 //track the upgrade progress on each step
2700 function set_upgrade_progress($currStep,$currState,$currStepSub='',$currStepSubState=''){
2701
2702         $upgrade_progress_dir = sugar_cached('upgrades/temp');
2703         if(!is_dir($upgrade_progress_dir)){
2704                 mkdir_recursive($upgrade_progress_dir);
2705         }
2706         $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
2707         if(file_exists($upgrade_progress_file)){
2708                 include($upgrade_progress_file);
2709         }
2710         else{
2711                 if(function_exists('sugar_fopen')){
2712                         sugar_fopen($upgrade_progress_file, 'w+');
2713                 }
2714                 else{
2715                         fopen($upgrade_progress_file, 'w+');
2716                 }
2717         }
2718         if(!isset($upgrade_config) || $upgrade_config == null){
2719                 $upgrade_config = array();
2720                 $upgrade_config[1]['upgrade_vars']=array();
2721         }
2722     if(!is_array($upgrade_config[1]['upgrade_vars'])){
2723         $upgrade_config[1]['upgrade_vars'] = array();
2724     }
2725         if($currStep != null && $currState != null){
2726                 if(sizeof($upgrade_config) > 0){
2727                         if($currStepSub != null && $currStepSubState !=null){
2728                                 //check if new status to be set or update
2729                                 //get the latest in array. since it has sub components prepare an array
2730                                 if(!empty($upgrade_config[sizeof($upgrade_config)][$currStep]) && is_array($upgrade_config[sizeof($upgrade_config)][$currStep])){
2731                                         $latestStepSub = currSubStep($upgrade_config[sizeof($upgrade_config)][$currStep]);
2732                                         if($latestStepSub == $currStepSub){
2733                                                 $upgrade_config[sizeof($upgrade_config)][$currStep][$latestStepSub]=$currStepSubState;
2734                                                 $upgrade_config[sizeof($upgrade_config)][$currStep][$currStep] = $currState;
2735                                         }
2736                                         else{
2737                                                 $upgrade_config[sizeof($upgrade_config)][$currStep][$currStepSub]=$currStepSubState;
2738                                                 $upgrade_config[sizeof($upgrade_config)][$currStep][$currStep] = $currState;
2739                                         }
2740                                 }
2741                                 else{
2742                                         $currArray = array();
2743                                         $currArray[$currStep] = $currState;
2744                                         $currArray[$currStepSub] = $currStepSubState;
2745                                         $upgrade_config[sizeof($upgrade_config)+1][$currStep] = $currArray;
2746                                 }
2747                         }
2748           else{
2749                                 //get the current upgrade progress
2750                                 $latestStep = get_upgrade_progress();
2751                                 //set the upgrade progress
2752                                 if($latestStep == $currStep){
2753                                         //update the current step with new progress status
2754                                         $upgrade_config[sizeof($upgrade_config)][$latestStep]=$currState;
2755                                 }
2756                                 else{
2757                                         //it's a new step
2758                                         $upgrade_config[sizeof($upgrade_config)+1][$currStep]=$currState;
2759                                 }
2760                     // now check if there elements within array substeps
2761           }
2762                 }
2763                 else{
2764                         //set the upgrade progress  (just starting)
2765                         $upgrade_config[sizeof($upgrade_config)+1][$currStep]= $currState;
2766                 }
2767
2768                 if(is_writable($upgrade_progress_file) && write_array_to_file( "upgrade_config", $upgrade_config,
2769                 $upgrade_progress_file)) {
2770                //writing to the file
2771                 }
2772
2773         }
2774 }
2775
2776 function get_upgrade_progress(){
2777         $upgrade_progress_dir = sugar_cached('upgrades/temp');
2778         $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
2779         $currState = '';
2780
2781         if(file_exists($upgrade_progress_file)){
2782                 include($upgrade_progress_file);
2783                 if(!isset($upgrade_config) || $upgrade_config == null){
2784                         $upgrade_config = array();
2785                 }
2786                 if($upgrade_config != null && sizeof($upgrade_config) >1){
2787                         $currArr = $upgrade_config[sizeof($upgrade_config)];
2788                         if(is_array($currArr)){
2789                            foreach($currArr as $key=>$val){
2790                                         $currState = $key;
2791                                 }
2792                         }
2793                 }
2794         }
2795         return $currState;
2796 }
2797 function currSubStep($currStep){
2798         $currSubStep = '';
2799         if(is_array($currStep)){
2800        foreach($currStep as $key=>$val){
2801                     if($key != null){
2802                         $currState = $key;
2803                         }
2804            }
2805         }
2806         return $currState;
2807 }
2808 function currUpgradeState($currState){
2809         $currState = '';
2810         if(is_array($currState)){
2811        foreach($currState as $key=>$val){
2812                         if(is_array($val)){
2813                                 foreach($val as $k=>$v){
2814                                         if($k != null){
2815                                                 $currState = $k;
2816                                         }
2817                                 }
2818                         }
2819                         else{
2820                                 $currState = $key;
2821                         }
2822                 }
2823         }
2824         return $currState;
2825 }
2826
2827 function didThisStepRunBefore($step,$SubStep=''){
2828         if($step == null) return;
2829         $upgrade_progress_dir = sugar_cached('upgrades/temp');
2830         $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
2831         $currState = '';
2832         $stepRan = false;
2833         if(file_exists($upgrade_progress_file)){
2834                 include($upgrade_progress_file);
2835                 if(isset($upgrade_config) && $upgrade_config != null && is_array($upgrade_config) && sizeof($upgrade_config) >0){
2836                         for($i=1;$i<=sizeof($upgrade_config);$i++){
2837                           if(is_array($upgrade_config[$i])){
2838                                         foreach($upgrade_config[$i] as $key=>$val){
2839                                                 if($key==$step){
2840                                                         if(is_array($upgrade_config[$i][$step])){
2841                                                                 //now process
2842                                                                 foreach ($upgrade_config[$i][$step] as $k=>$v){
2843                                                                         if(is_array($v)){
2844                                                                                 foreach($v as $k1=>$v1){
2845                                                                                         if($SubStep != null){
2846                                                                                                 if($SubStep ==$k1 && $v1=='done'){
2847                                                                                                         $stepRan = true;
2848                                                                                                         break;
2849                                                                                                 }
2850                                                                                         }
2851                                                                                 }//foreach
2852                                                                         }
2853                                                                         elseif($SubStep !=null){
2854                                                                                 if($SubStep==$k && $v=='done'){
2855                                                                                         $stepRan = true;
2856                                                                                         break;
2857                                                                                 }
2858                                                                         }
2859                                                                         elseif($step==$k && $v=='done'){
2860                                                                                 $stepRan = true;
2861                                                                                 break;
2862                                                                         }
2863                                                                 }//foreach
2864                                                         }
2865                                                         elseif($val=='done'){
2866                                                                 $stepRan = true;
2867                                                         }
2868                                                 }
2869                                         }//foreach
2870                                 }
2871                         }//for
2872                 }
2873         }
2874         return $stepRan;
2875 }
2876
2877
2878
2879 //get and set post install status
2880 function post_install_progress($progArray='',$action=''){
2881         $upgrade_progress_dir = sugar_cached('upgrades/temp');
2882         $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
2883     if($action=='' || $action=='get'){
2884                 //get the state of post install
2885         $currProg = array();
2886                 if(file_exists($upgrade_progress_file)){
2887                         include($upgrade_progress_file);
2888                         if(is_array($upgrade_config[sizeof($upgrade_config)]['commit']['post_install']) && sizeof($upgrade_config[sizeof($upgrade_config)]['commit']['post_install'])>0){
2889                                 foreach($upgrade_config[sizeof($upgrade_config)]['commit']['post_install'] as $k=>$v){
2890                                         $currProg[$k]=$v;
2891                                 }
2892                         }
2893                 }
2894                 return $currProg;
2895         }
2896         elseif($action=='set'){
2897                 if(!is_dir($upgrade_progress_dir)){
2898                         mkdir($upgrade_progress_dir);
2899                 }
2900                 if(file_exists($upgrade_progress_file)){
2901                         include($upgrade_progress_file);
2902                 }
2903                 else{
2904                         fopen($upgrade_progress_file, 'w+');
2905                 }
2906                 if(!is_array($upgrade_config[sizeof($upgrade_config)]['commit']['post_install'])){
2907                         $upgrade_config[sizeof($upgrade_config)]['commit']['post_install']=array();
2908                         $upgrade_config[sizeof($upgrade_config)]['commit']['post_install']['post_install'] = 'in_progress';
2909                 }
2910                 if($progArray != null && is_array($progArray)){
2911                         foreach($progArray as $key=>$val){
2912                                 $upgrade_config[sizeof($upgrade_config)]['commit']['post_install'][$key]=$val;
2913                         }
2914                 }
2915                 if(is_writable($upgrade_progress_file) && write_array_to_file( "upgrade_config", $upgrade_config,
2916                 $upgrade_progress_file)) {
2917                //writing to the file
2918                 }
2919         }
2920 }
2921
2922 function repairDBForUpgrade($execute=false,$path=''){
2923
2924         global $current_user, $beanFiles;
2925         global $dictionary;
2926         set_time_limit(3600);
2927
2928         $db = &DBManagerFactory::getInstance();
2929         $sql = '';
2930         VardefManager::clearVardef();
2931         require_once('include/ListView/ListView.php');
2932         foreach ($beanFiles as $bean => $file) {
2933                 require_once ($file);
2934                 $focus = new $bean ();
2935                 $sql .= $db->repairTable($focus, $execute);
2936
2937         }
2938         //echo $sql;
2939         $olddictionary = $dictionary;
2940         unset ($dictionary);
2941         include ('modules/TableDictionary.php');
2942         foreach ($dictionary as $meta) {
2943                 $tablename = $meta['table'];
2944                 $fielddefs = $meta['fields'];
2945                 $indices = $meta['indices'];
2946                 $sql .= $db->repairTableParams($tablename, $fielddefs, $indices, $execute);
2947         }
2948          $qry_str = "";
2949           foreach (explode("\n", $sql) as $line) {
2950                   if (!empty ($line) && substr($line, -2) != "*/") {
2951                         $line .= ";";
2952                   }
2953                   $qry_str .= $line . "\n";
2954            }
2955           $sql = str_replace(
2956           array(
2957                 "\n",
2958                 '&#039;',
2959            ),
2960           array(
2961                 '',
2962                 "'",
2963           ),
2964           preg_replace('#(/\*.+?\*/\n*)#', '', $qry_str)
2965           );
2966          logThis("*******START EXECUTING DB UPGRADE QUERIES***************",$path);
2967                 logThis($sql,$path);
2968          logThis("*******END EXECUTING DB UPGRADE QUERIES****************",$path);
2969          if(!$execute){
2970                 return $sql;
2971          }
2972 }
2973
2974
2975
2976 /**
2977  * upgradeUserPreferences
2978  * This method updates the user_preferences table and sets the pages/dashlets for users
2979  * which have ACL access to Trackers so that the Tracker dashlets are set in their user perferences
2980  *
2981  */
2982 function upgradeUserPreferences() {
2983     global $sugar_config, $sugar_version;
2984     $uw_strings = return_module_language($GLOBALS['current_language'], 'UpgradeWizard');
2985
2986     $localization = new Localization();
2987     $localeCoreDefaults = $localization->getLocaleConfigDefaults();
2988
2989     // check the current system wide default_locale_name_format and add it to the list if it's not there
2990     if(empty($sugar_config['name_formats'])) {
2991         $sugar_config['name_formats'] = $localeCoreDefaults['name_formats'];
2992         if(!rebuildConfigFile($sugar_config, $sugar_version)) {
2993             $errors[] = $uw_strings['ERR_UW_CONFIG_WRITE'];
2994         }
2995     }
2996
2997     $currentDefaultLocaleNameFormat = $sugar_config['default_locale_name_format'];
2998
2999     if ($localization->isAllowedNameFormat($currentDefaultLocaleNameFormat)) {
3000         upgradeLocaleNameFormat($currentDefaultLocaleNameFormat);
3001     } else {
3002         $sugar_config['default_locale_name_format'] = $localeCoreDefaults['default_locale_name_format'];
3003         if(!rebuildConfigFile($sugar_config, $sugar_version)) {
3004             $errors[] = $uw_strings['ERR_UW_CONFIG_WRITE'];
3005         }
3006         $localization->createInvalidLocaleNameFormatUpgradeNotice();
3007     }
3008
3009         $db = &DBManagerFactory::getInstance();
3010     $result = $db->query("SELECT id FROM users where deleted = '0'");
3011         while($row = $db->fetchByAssoc($result))
3012     {
3013         $current_user = new User();
3014         $current_user->retrieve($row['id']);
3015
3016         // get the user's name locale format, check if it's in our list, add it if it's not, keep it as user's default
3017         $currentUserNameFormat = $current_user->getPreference('default_locale_name_format');
3018         if ($localization->isAllowedNameFormat($currentUserNameFormat)) {
3019             upgradeLocaleNameFormat($currentUserNameFormat);
3020         } else {
3021             $current_user->setPreference('default_locale_name_format', 's f l', 0, 'global');
3022             $current_user->savePreferencesToDB();
3023         }
3024
3025         $changed = false;
3026         if(!$current_user->getPreference('calendar_publish_key')) {
3027                 // set publish key if not set already
3028                 $current_user->setPreference('calendar_publish_key', create_guid());
3029                 $changed = true;
3030         }
3031
3032
3033         // we need to force save the changes to disk, otherwise we lose them.
3034         if($changed)
3035         {
3036             $current_user->savePreferencesToDB();
3037         }
3038
3039         } //while
3040 }
3041
3042
3043 /**
3044  * Checks if a locale name format is part of the default list, if not adds it to the config
3045  * @param $name_format string a local name format string such as 's f l'
3046  * @return bool true on successful write to config file, false on failure;
3047  */
3048 function upgradeLocaleNameFormat($name_format) {
3049     global $sugar_config, $sugar_version;
3050
3051     $localization = new Localization();
3052     $localeConfigDefaults = $localization->getLocaleConfigDefaults();
3053
3054     $uw_strings = return_module_language($GLOBALS['current_language'], 'UpgradeWizard');
3055     if(empty($sugar_config['name_formats'])) {
3056         $sugar_config['name_formats'] = $localeConfigDefaults['name_formats'];
3057         if(!rebuildConfigFile($sugar_config, $sugar_version)) {
3058             $errors[] = $uw_strings['ERR_UW_CONFIG_WRITE'];
3059         }
3060     }
3061     if (!in_array($name_format, $sugar_config['name_formats'])) {
3062         $new_config = sugarArrayMerge($sugar_config['name_formats'], array($name_format=>$name_format));
3063         $sugar_config['name_formats'] = $new_config;
3064         if(!rebuildConfigFile($sugar_config, $sugar_version)) {
3065             $errors[] = $uw_strings['ERR_UW_CONFIG_WRITE'];
3066             return false;
3067         }
3068     }
3069     return true;
3070 }
3071
3072
3073
3074 function add_custom_modules_favorites_search(){
3075     $module_directories = scandir('modules');
3076
3077         foreach($module_directories as $module_dir){
3078                 if($module_dir == '.' || $module_dir == '..' || !is_dir("modules/{$module_dir}")){
3079                         continue;
3080                 }
3081
3082                 $matches = array();
3083                 preg_match('/^[a-z0-9]{1,5}_[a-z0-9_]+$/i' , $module_dir, $matches);
3084
3085                 // Make sure the module was created by module builder
3086                 if(empty($matches)){
3087                         continue;
3088                 }
3089
3090                 $full_module_dir = "modules/{$module_dir}/";
3091                 $read_searchdefs_from = "{$full_module_dir}/metadata/searchdefs.php";
3092                 $read_SearchFields_from = "{$full_module_dir}/metadata/SearchFields.php";
3093                 $read_custom_SearchFields_from = "custom/{$full_module_dir}/metadata/SearchFields.php";
3094
3095                 // Studio can possibly override this file, so we check for a custom version of it
3096                 if(file_exists("custom/{$full_module_dir}/metadata/searchdefs.php")){
3097                         $read_searchdefs_from = "custom/{$full_module_dir}/metadata/searchdefs.php";
3098                 }
3099
3100                 if(file_exists($read_searchdefs_from) && file_exists($read_SearchFields_from)){
3101                         $found_sf1 = false;
3102                         $found_sf2 = false;
3103                         require($read_searchdefs_from);
3104                         foreach($searchdefs[$module_dir]['layout']['basic_search'] as $sf_array){
3105                                 if(isset($sf_array['name']) && $sf_array['name'] == 'favorites_only'){
3106                                         $found_sf1 = true;
3107                                 }
3108                         }
3109
3110                         require($read_SearchFields_from);
3111                         if(isset($searchFields[$module_dir]['favorites_only'])){
3112                                 $found_sf2 = true;
3113                         }
3114
3115                         if(!$found_sf1 && !$found_sf2){
3116                                 $searchdefs[$module_dir]['layout']['basic_search']['favorites_only'] = array('name' => 'favorites_only','label' => 'LBL_FAVORITES_FILTER','type' => 'bool',);
3117                                 $searchdefs[$module_dir]['layout']['advanced_search']['favorites_only'] = array('name' => 'favorites_only','label' => 'LBL_FAVORITES_FILTER','type' => 'bool',);
3118                                 $searchFields[$module_dir]['favorites_only'] = array(
3119                                         'query_type'=>'format',
3120                                         'operator' => 'subquery',
3121                                         'subquery' => 'SELECT sugarfavorites.record_id FROM sugarfavorites
3122                                                                 WHERE sugarfavorites.deleted=0
3123                                                                         and sugarfavorites.module = \''.$module_dir.'\'
3124                                                                         and sugarfavorites.assigned_user_id = \'{0}\'',
3125                                         'db_field'=>array('id')
3126                                 );
3127
3128                                 if(!is_dir("custom/{$full_module_dir}/metadata")){
3129                                         mkdir_recursive("custom/{$full_module_dir}/metadata");
3130                                 }
3131                                 $success_sf1 = write_array_to_file('searchdefs', $searchdefs, "custom/{$full_module_dir}/metadata/searchdefs.php");
3132                                 $success_sf2 = write_array_to_file('searchFields', $searchFields, "{$full_module_dir}/metadata/SearchFields.php");
3133
3134                                 if(!$success_sf1){
3135                                         logThis("add_custom_modules_favorites_search failed for searchdefs.php for {$module_dir}");
3136                                 }
3137                                 if(!$success_sf2){
3138                                         logThis("add_custom_modules_favorites_search failed for SearchFields.php for {$module_dir}");
3139                                 }
3140                                 if($success_sf1 && $success_sf2){
3141                                         logThis("add_custom_modules_favorites_search successfully updated searchdefs and searchFields for {$module_dir}");
3142                                 }
3143                         }
3144                 }
3145         }
3146 }
3147
3148
3149 /**
3150  * upgradeModulesForTeamsets
3151  *
3152  * This method adds the team_set_id values to the module tables that have the new team_set_id column
3153  * added through the SugarCRM 5.5.x upgrade process.  It also adds the values into the team_sets and
3154  * team_sets_teams tables.
3155  *
3156  * @param filter Array of modules to process; empty by default
3157  */
3158 function upgradeModulesForTeamsets($filter=array()) {
3159     require('include/modules.php');
3160         foreach($beanList as $moduleName=>$beanName) {
3161                     if(!empty($filter) && array_search($moduleName, $filter) === false) {
3162                        continue;
3163                     }
3164                 if($moduleName == 'TeamMemberships' || $moduleName == 'ForecastOpportunities'){
3165                 continue;
3166             }
3167                         $bean = loadBean($moduleName);
3168                         if(empty($bean) ||
3169                            empty($bean->table_name)) {
3170                            continue;
3171                         }
3172
3173                         $FieldArray = $GLOBALS['db']->helper->get_columns($bean->table_name);
3174                         if(!isset($FieldArray['team_id'])) {
3175                            continue;
3176                         }
3177
3178                         upgradeTeamColumn($bean, 'team_id');
3179
3180         } //foreach
3181
3182     //Upgrade users table
3183         $bean = loadBean('Users');
3184         upgradeTeamColumn($bean, 'default_team');
3185         $result = $GLOBALS['db']->query("SELECT id FROM teams where deleted=0");
3186         while($row = $GLOBALS['db']->fetchByAssoc($result)) {
3187               $teamset = new TeamSet();
3188               $teamset->addTeams($row['id']);
3189         }
3190 }
3191
3192
3193 /**
3194  * upgradeTeamColumn
3195  * Helper function to create a team_set_id column and also set team_set_id column
3196  * to have the value of the $column_name parameter
3197  *
3198  * @param $bean SugarBean which we are adding team_set_id column to
3199  * @param $column_name The name of the column containing the default team_set_id value
3200  */
3201 function upgradeTeamColumn($bean, $column_name) {
3202         //first let's check to ensure that the team_set_id field is defined, if not it could be the case that this is an older
3203         //module that does not use the SugarObjects
3204         if(empty($bean->field_defs['team_set_id']) && $bean->module_dir != 'Trackers'){
3205
3206                 //at this point we could assume that since we have a team_id defined and not a team_set_id that we need to
3207                 //add that field and the corresponding relationships
3208                 $object = $bean->object_name;
3209                 $module = $bean->module_dir;
3210                 $object_name = $object;
3211                 $_object_name = strtolower($object_name);
3212
3213                 if(!empty($GLOBALS['dictionary'][$object]['table'])){
3214                         $table_name = $GLOBALS['dictionary'][$object]['table'];
3215                 }else{
3216                         $table_name = strtolower($module);
3217                 }
3218
3219                 $path = 'include/SugarObjects/implements/team_security/vardefs.php';
3220                 require($path);
3221                 //go through each entry in the vardefs from team_security and unset anything that is already set in the core module
3222                 //this will ensure we have the proper ordering.
3223                 $fieldDiff = array_diff_assoc($vardefs['fields'], $GLOBALS['dictionary'][$bean->object_name]['fields']);
3224
3225                 $file = 'custom/Extension/modules/' . $bean->module_dir. '/Ext/Vardefs/teams.php';
3226                 $contents = "<?php\n";
3227                 if(!empty($fieldDiff)){
3228                         foreach($fieldDiff as $key => $val){
3229                                 $contents .= "\n\$GLOBALS['dictionary']['". $object . "']['fields']['". $key . "']=" . var_export_helper($val) . ";";
3230                         }
3231                 }
3232                 $relationshipDiff = array_diff_assoc($vardefs['relationships'], $GLOBALS['dictionary'][$bean->object_name]['relationships']);
3233                 if(!empty($relationshipDiff)){
3234                         foreach($relationshipDiff as $key => $val){
3235                                 $contents .= "\n\$GLOBALS['dictionary']['". $object . "']['relationships']['". $key . "']=" . var_export_helper($val) . ";";
3236                         }
3237                 }
3238                 $indexDiff = array_diff_assoc($vardefs['indices'], $GLOBALS['dictionary'][$bean->object_name]['indices']);
3239                 if(!empty($indexDiff)){
3240                         foreach($indexDiff as $key => $val){
3241                                         $contents .= "\n\$GLOBALS['dictionary']['". $object . "']['indices']['". $key . "']=" . var_export_helper($val) . ";";
3242                         }
3243                 }
3244                 if( $fh = @sugar_fopen( $file, 'wt' ) )
3245             {
3246                 fputs( $fh, $contents);
3247                 fclose( $fh );
3248             }
3249
3250
3251                 //we have written out the teams.php into custom/Extension/modules/{$module_dir}/Ext/Vardefs/teams.php'
3252                 //now let's merge back into vardefs.ext.php
3253                 require_once('ModuleInstall/ModuleInstaller.php');
3254                 $mi = new ModuleInstaller();
3255                 $mi->merge_files('Ext/Vardefs/', 'vardefs.ext.php');
3256                 VardefManager::loadVardef($bean->module_dir, $bean->object_name, true);
3257                 $bean->field_defs = $GLOBALS['dictionary'][$bean->object_name]['fields'];
3258         }
3259
3260         if(isset($bean->field_defs['team_set_id'])) {
3261                 //Create the team_set_id column
3262                 $FieldArray = $GLOBALS['db']->helper->get_columns($bean->table_name);
3263                 if(!isset($FieldArray['team_set_id'])) {
3264                         $GLOBALS['db']->addColumn($bean->table_name, $bean->field_defs['team_set_id']);
3265                 }
3266                 $indexArray =  $GLOBALS['db']->helper->get_indices($bean->table_name);
3267
3268         $indexName = getValidDBName('idx_'.strtolower($bean->table_name).'_tmst_id', true, 34);
3269         $indexDef = array(
3270                                          array(
3271                                                 'name' => $indexName,
3272                                                 'type' => 'index',
3273                                                 'fields' => array('team_set_id')
3274                                          )
3275                                    );
3276                 if(!isset($indexArray[$indexName])) {
3277                         $GLOBALS['db']->addIndexes($bean->table_name, $indexDef);
3278                 }
3279
3280                 //Update the table's team_set_id column to have the same values as team_id
3281             $GLOBALS['db']->query("UPDATE {$bean->table_name} SET team_set_id = {$column_name}");
3282         }
3283 }
3284
3285 /**
3286  *  Update the folder subscription table which confirms to the team security mechanism but
3287  *  the class SugarFolders does not extend SugarBean and is therefore never picked up by the
3288  *  upgradeModulesForTeamsets function.
3289  */
3290 function upgradeFolderSubscriptionsTeamSetId()
3291 {
3292     logThis("In upgradeFolderSubscriptionsTeamSetId()");
3293     $query = "UPDATE folders SET team_set_id = team_id";
3294     $result = $GLOBALS['db']->query($query);
3295     logThis("Finished upgradeFolderSubscriptionsTeamSetId()");
3296 }
3297
3298 /**
3299  * upgradeModulesForTeam
3300  *
3301  * This method update the associated_user_id, name, name_2 to the private team records on teams table
3302  * This function is used for upgrade process from 5.1.x and 5.2.x.
3303  *
3304  */
3305 function upgradeModulesForTeam() {
3306     logThis("In upgradeModulesForTeam()");
3307     $result = $GLOBALS['db']->query("SELECT id, user_name, first_name, last_name FROM users where deleted=0");
3308
3309     while($row = $GLOBALS['db']->fetchByAssoc($result)) {
3310         $results2 = $GLOBALS['db']->query("SELECT id FROM teams WHERE name = '({$row['user_name']})'");
3311         $assoc = '';
3312                 if(!$assoc = $GLOBALS['db']->fetchByAssoc($results2)) {
3313                         //if team does not exist, then lets create the team for this user
3314                         $team = new Team();
3315                         $user = new User();
3316                         $user->retrieve($row['id']);
3317                         $team->new_user_created($user);
3318                         $team_id = $team->id;
3319                 }else{
3320                         $team_id =$assoc['id'];
3321                 }
3322
3323                         //upgrade the team
3324                         $name = is_null($row['first_name'])?'':$row['first_name'];
3325                         $name_2 = is_null($row['last_name'])?'':$row['last_name'];
3326                         $associated_user_id = $row['id'];
3327
3328                         //Bug 32914
3329                         //Ensure team->name is not empty by using team->name_2 if available
3330                         if(empty($name) && !empty($name_2)) {
3331                            $name = $name_2;
3332                            $name_2 = '';
3333                         }
3334
3335                         $query = "UPDATE teams SET name = '{$name}', name_2 = '{$name_2}', associated_user_id = '{$associated_user_id}' WHERE id = '{$team_id}'";
3336                         $GLOBALS['db']->query($query);
3337     } //while
3338
3339     //Update the team_set_id and default_team columns
3340     $ce_to_pro_or_ent = (isset($_SESSION['upgrade_from_flavor']) && ($_SESSION['upgrade_from_flavor'] == 'SugarCE to SugarPro' || $_SESSION['upgrade_from_flavor'] == 'SugarCE to SugarEnt' || $_SESSION['upgrade_from_flavor'] == 'SugarCE to SugarCorp' || $_SESSION['upgrade_from_flavor'] == 'SugarCE to SugarUlt'));
3341
3342     //Update team_set_id
3343         if($ce_to_pro_or_ent) {
3344            $GLOBALS['db']->query("update users set team_set_id = (select teams.id from teams where teams.associated_user_id = users.id)");
3345            $GLOBALS['db']->query("update users set default_team = (select teams.id from teams where teams.associated_user_id = users.id)");
3346         }
3347
3348 }
3349
3350
3351     function addNewSystemTabsFromUpgrade($from_dir){
3352         global $path;
3353         if(isset($_SESSION['upgrade_from_flavor'])){
3354
3355             //check to see if there are any new files that need to be added to systems tab
3356             //retrieve old modules list
3357             logThis('check to see if new modules exist',$path);
3358             $oldModuleList = array();
3359             $newModuleList = array();
3360             include($from_dir.'/include/modules.php');
3361             $oldModuleList = $moduleList;
3362             include('include/modules.php');
3363             $newModuleList = $moduleList;
3364
3365             //include tab controller
3366             require_once('modules/MySettings/TabController.php');
3367             $newTB = new TabController();
3368
3369             //make sure new modules list has a key we can reference directly
3370             $newModuleList = $newTB->get_key_array($newModuleList);
3371             $oldModuleList = $newTB->get_key_array($oldModuleList);
3372
3373             //iterate through list and remove commonalities to get new modules
3374             foreach ($newModuleList as $remove_mod){
3375                 if(in_array($remove_mod, $oldModuleList)){
3376                     unset($newModuleList[$remove_mod]);
3377                 }
3378             }
3379             //new modules list now has left over modules which are new to this install, so lets add them to the system tabs
3380             logThis('new modules to add are '.var_export($newModuleList,true),$path);
3381
3382             if(!empty($newModuleList))
3383             {
3384                     //grab the existing system tabs
3385                     $tabs = $newTB->get_system_tabs();
3386
3387                     //add the new tabs to the array
3388                     foreach($newModuleList as $nm ){
3389                       $tabs[$nm] = $nm;
3390                     }
3391
3392                     $newTB->set_system_tabs($tabs);
3393             }
3394             logThis('module tabs updated',$path);
3395         }
3396     }
3397
3398     /**
3399      * fix_dropdown_list
3400      * This method attempts to fix dropdown lists that were incorrectly named.
3401      * There were versions of SugarCRM that did not enforce naming convention rules
3402      * for the dropdown list field name.  This method attempts to resolve that by
3403      * fixing the language files that may have been affected and then updating the
3404      * fields_meta_data table accordingly.  It also refreshes any vardefs that may
3405      * have been affected.
3406      *
3407      */
3408         function fix_dropdown_list() {
3409         if(file_exists('custom/include/language')) {
3410            $files = array();
3411            $affected_modules = array();
3412            $affected_keys = array();
3413
3414            getFiles($files, 'custom/include/language', '/\.php$/i');
3415            foreach($files as $file) {
3416
3417               if(file_exists($file . '.bak')) {
3418                  $bak_mod_time = filemtime($file . '.bak');
3419                  $php_mod_time = filemtime($file);
3420                  //We're saying if the .php file was modified 30 seconds no more than php.bak file then we
3421                  //run these additional cleanup checks
3422                  if($php_mod_time - $bak_mod_time < 30) {
3423
3424                         $app_list_strings = array();
3425                         $GLOBALS['app_list_strings'] = array();
3426                         require($file . '.bak');
3427                         $bak_app_list_strings = array_merge($app_list_strings, $GLOBALS['app_list_strings']);
3428
3429                         $app_list_strings = array();
3430                         $GLOBALS['app_list_strings'] = array();
3431                         require($file);
3432                         $php_app_list_strings = array_merge($app_list_strings, $GLOBALS['app_list_strings']);
3433
3434                         //Get the file contents
3435                         $contents = file_get_contents($file);
3436
3437                         //Now simulate a fix for the file before we compare w/ the .php file
3438                         //we also append to the $contents
3439                         foreach($bak_app_list_strings as $key=>$entry) {
3440                                                    if(preg_match('/([^A-Za-z_])/', $key, $matches) && is_array($entry)) {
3441                                                           $new_key = preg_replace('/[^A-Za-z_]/', '_', $key);
3442                                                           $bak_app_list_strings[$new_key] = $bak_app_list_strings[$key];
3443                                                           unset($bak_app_list_strings[$key]);
3444                                                           //Now if the entry doesn't exists in the .php file, then add to contents
3445                                                           if(!isset($php_app_list_strings[$new_key])) {
3446                                                                  $contents .= "\n\$GLOBALS['app_list_strings']['{$new_key}'] = " . var_export_helper($bak_app_list_strings[$new_key]) . ";";
3447                                                           }
3448                                                    } //if
3449                         } //foreach
3450
3451                         //Now load the .php file to do the comparison
3452                         foreach($php_app_list_strings as $key=>$entry) {
3453                                 if(isset($bak_app_list_strings[$key])) {
3454                                         $diff = array_diff($bak_app_list_strings[$key], $entry);
3455                                         if(!empty($diff)) {
3456                                            //There is a difference, so copy the $bak_app_list_strings version into the .php file
3457                                            $contents .= "\n\$GLOBALS['app_list_strings']['{$key}'] = " . var_export_helper($bak_app_list_strings[$key]) . ";";
3458                                         } //if
3459                                 } //if
3460                         } //foreach
3461
3462                         //Now write out the file contents
3463                         //Create backup just in case
3464                         copy($file, $file . '.php_bak');
3465                                         $fp = @sugar_fopen($file, 'w');
3466                         if($fp) {
3467                                fwrite($fp, $contents);
3468                                fclose($fp);
3469                         } else {
3470                            $GLOBALS['log']->error("Unable to update file contents in fix_dropdown_list for {$file}");
3471                         } //if-else
3472                  }
3473               }
3474
3475               unset($GLOBALS['app_strings']);
3476               unset($GLOBALS['app_list_strings']);
3477               $app_list_strings = array();
3478                   require($file);
3479                   $touched = false;
3480                   $contents = file_get_contents($file);
3481                   if ( !isset($GLOBALS['app_list_strings']) ) {
3482                       $GLOBALS['app_list_strings'] = $app_list_strings;
3483                   }
3484                   else {
3485                       $GLOBALS['app_list_strings'] = array_merge($app_list_strings, $GLOBALS['app_list_strings']);
3486                   }
3487
3488                   if(isset($GLOBALS['app_list_strings']) && is_array($GLOBALS['app_list_strings'])) {
3489                          foreach($GLOBALS['app_list_strings'] as $key=>$entry) {
3490                                 if(preg_match('/([^A-Za-z_])/', $key, $matches) && is_array($entry)) {
3491                                    $result = $GLOBALS['db']->query("SELECT custom_module FROM fields_meta_data WHERE ext1 = '{$key}'");
3492                                    if(!empty($result)) {
3493                                           while($row = $GLOBALS['db']->fetchByAssoc($result)) {
3494                                                     $custom_module = $row['custom_module'];
3495                                                     if(!empty($GLOBALS['beanList'][$custom_module])) {
3496                                                    $affected_modules[$custom_module] = $GLOBALS['beanList'][$custom_module];
3497                                                     }
3498                                           } //while
3499                                    }
3500
3501                                    //Replace all invalid characters with '_' character
3502                                    $new_key = preg_replace('/[^A-Za-z_]/', '_', $key);
3503                                    $affected_keys[$key] = $new_key;
3504
3505                                    $GLOBALS['app_list_strings'][$new_key] = $GLOBALS['app_list_strings'][$key];
3506                                    unset($GLOBALS['app_list_strings'][$key]);
3507
3508                                    $pattern_match = "/(\[\s*\'{$key}\'\s*\])/";
3509                                    $new_key = "['{$new_key}']";
3510                                    $out = preg_replace($pattern_match, $new_key, $contents);
3511                                    $contents = $out;
3512                                    $touched = true;
3513                                 } //if
3514                          } //foreach
3515
3516                  //This is a check for g => h instances where the file contents were incorrectly written
3517                  //and also fixes the scenario where via a UI upgrade, the app_list_strings were incorrectly
3518                  //merged with app_list_strings variables declared elsewhere
3519                          if(!$touched) {
3520                                    if(preg_match('/\$GLOBALS\s*\[\s*[\"|\']app_list_strings[\"|\']\s*\]\s*=\s*array\s*\(/', $contents)) {
3521                                           //Now also remove all the non-custom labels that were added
3522                                           if(preg_match('/language\/([^\.]+)\.lang\.php$/', $file, $matches)) {
3523                                                 $language = $matches[1];
3524
3525                                                 $app_list_strings = array();
3526
3527                                         if(file_exists("include/language/$language.lang.php")) {
3528                                                                    include("include/language/$language.lang.php");
3529                                                                 }
3530                                                                 if(file_exists("include/language/$language.lang.override.php")) {
3531                                                                    $app_list_strings =  _mergeCustomAppListStrings("include/language/$language.lang.override.php" , $app_list_strings) ;
3532                                                                 }
3533                                                                 if(file_exists("custom/application/Ext/Language/$language.ext.lang.php")) {
3534                                                                    $app_list_strings =  _mergeCustomAppListStrings("custom/application/Ext/Language/$language.ext.lang.php" , $app_list_strings) ;
3535                                                                 }
3536                                                                 if(file_exists("custom/application/Ext/Language/$language.lang.ext.php")) {
3537                                                                    $app_list_strings =  _mergeCustomAppListStrings("custom/application/Ext/Language/$language.lang.ext.php" , $app_list_strings) ;
3538                                                                 }
3539
3540                                                                 $all_non_custom_include_language_strings = $app_strings;
3541                                                                 $all_non_custom_include_language_list_strings = $app_list_strings;
3542
3543                                                                 $unset_keys = array();
3544                                                                 if(!empty($GLOBALS['app_list_strings'])) {
3545                                                                         foreach($GLOBALS['app_list_strings'] as $key=>$value) {
3546                                                                                 $diff = array();
3547                                                                                 if(isset($all_non_custom_include_language_list_strings[$key])) {
3548                                                                                         $diff = array_diff($all_non_custom_include_language_list_strings[$key], $GLOBALS['app_list_strings'][$key]);
3549                                                                                 }
3550
3551                                                                                 if(!empty($all_non_custom_include_language_list_strings[$key]) && empty($diff)) {
3552                                                                                         $unset_keys[] = $key;
3553                                                                                 }
3554                                                                         }
3555                                                                 }
3556
3557                                                                 foreach($unset_keys as $key) {
3558                                                                         unset($GLOBALS['app_list_strings'][$key]);
3559                                                                 }
3560
3561                                                                 if(!empty($GLOBALS['app_strings'])) {
3562                                                                 foreach($GLOBALS['app_strings'] as $key=>$value) {
3563                                                                                 if(!empty($all_non_custom_include_language_strings[$key])) {
3564                                                                                    unset($GLOBALS['app_strings'][$key]);
3565                                                                                 }
3566                                                                 }
3567                                                                 }
3568                                           } //if(preg_match...)
3569
3570                                       $out = "<?php \n";
3571                                       if(!empty($GLOBALS['app_strings'])) {
3572                                              foreach($GLOBALS['app_strings'] as $key=>$entry) {
3573                                                      $out .= "\n\$GLOBALS['app_strings']['$key']=" . var_export_helper($entry) . ";";
3574                                              }
3575                                       }
3576
3577                                                   foreach($GLOBALS['app_list_strings'] as $key=>$entry) {
3578                                                                   $out .= "\n\$GLOBALS['app_list_strings']['$key']=" . var_export_helper($entry) . ";";
3579                                                   } //foreach
3580
3581                                                   $touched = true;
3582                                    } //if(preg_match...)
3583                          } //if(!$touched)
3584
3585                          if($touched) {
3586                                  //Create a backup just in case
3587                                  copy($file, $file . '.bak');
3588                          $fp = @sugar_fopen($file, 'w');
3589                          if($fp) {
3590                                fwrite($fp, $out);
3591                                fclose($fp);
3592                          } else {
3593                            //If we can't update the file, just return
3594                            $GLOBALS['log']->error("Unable to update file contents in fix_dropdown_list.");
3595                            return;
3596                          }
3597                          } //if($touched)
3598                   } //if
3599
3600            } //foreach($files)
3601
3602            //Update db entries (the order matters here... need to process database changes first)
3603            if(!empty($affected_keys)) {
3604                   foreach($affected_keys as $old_key=>$new_key) {
3605                                   $GLOBALS['db']->query("UPDATE fields_meta_data SET ext1 = '{$new_key}' WHERE ext1 = '{$old_key}'");
3606                   }
3607            }
3608
3609            //Update vardef files for affected modules
3610            if(!empty($affected_modules)) {
3611                   foreach($affected_modules as $module=>$object) {
3612                           VardefManager::refreshVardefs($module, $object);
3613                   }
3614            }
3615         }
3616         }
3617
3618
3619         function update_iframe_dashlets(){
3620                 require_once(sugar_cached('dashlets/dashlets.php'));
3621
3622                 $db = DBManagerFactory::getInstance();
3623                 $query = "SELECT id, contents, assigned_user_id FROM user_preferences WHERE deleted = 0 AND category = 'Home'";
3624                 $result = $db->query($query, true, "Unable to update new default dashlets! ");
3625                 while ($row = $db->fetchByAssoc($result)) {
3626                         $content = unserialize(base64_decode($row['contents']));
3627                         $assigned_user_id = $row['assigned_user_id'];
3628                         $record_id = $row['id'];
3629
3630                         $current_user = new User();
3631                         $current_user->retrieve($row['assigned_user_id']);
3632
3633                         if(!empty($content['dashlets']) && !empty($content['pages'])){
3634                                 $originalDashlets = $content['dashlets'];
3635                                 foreach($originalDashlets as $key => $ds){
3636                                     if(!empty($ds['options']['url']) && stristr($ds['options']['url'],'http://www.sugarcrm.com/crm/product/gopro')){
3637                                                 unset($originalDashlets[$key]);
3638                                         }
3639                                 }
3640                                 $current_user->setPreference('dashlets', $originalDashlets, 0, 'Home');
3641                         }
3642                 }
3643         }
3644
3645
3646     /**
3647      * convertImageToText
3648      * @deprecated
3649      * This method attempts to convert date type image to text on Microsoft SQL Server.
3650      * This method could NOT be used in any other type of datebases.
3651      */
3652         function convertImageToText($table_name,$column_name){
3653                 $set_lang = "SET LANGUAGE us_english";
3654                 $GLOBALS['db']->query($set_lang);
3655             if($GLOBALS['db']->lastError()){
3656             logThis('An error occurred when performing this query-->'.$set_lang);
3657         }
3658        $q="SELECT data_type
3659         FROM INFORMATION_SCHEMA.Tables T JOIN INFORMATION_SCHEMA.Columns C
3660         ON T.TABLE_NAME = C.TABLE_NAME where T.TABLE_NAME = '$table_name' and C.COLUMN_NAME = '$column_name'";
3661        $res= $GLOBALS['db']->query($q);
3662        if($GLOBALS['db']->lastError()){
3663             logThis('An error occurred when performing this query-->'.$q);
3664         }
3665        $row= $GLOBALS['db']->fetchByAssoc($res);
3666
3667      if(trim(strtolower($row['data_type'])) == 'image'){
3668         $addContent_temp = "alter table {$table_name} add {$column_name}_temp text null";
3669         $GLOBALS['db']->query($addContent_temp);
3670         if($GLOBALS['db']->lastError()){
3671             logThis('An error occurred when performing this query-->'.$addContent_temp);
3672         }
3673         $qN = "select count=datalength({$column_name}), id, {$column_name} from {$table_name}";
3674         $result = $GLOBALS['db']->query($qN);
3675         while($row = $GLOBALS['db']->fetchByAssoc($result)){
3676            if($row['count'] >8000){
3677                 $contentLength = $row['count'];
3678                 $start = 1;
3679                 $next=8000;
3680                 $convertedContent = '';
3681                 while($contentLength >0){
3682                     $stepsQuery = "select cont=convert(varchar(max), convert(varbinary(8000), substring({$column_name},{$start},{$next}))) from {$table_name} where id= '{$row['id']}'";
3683                     $steContQ = $GLOBALS['db']->query($stepsQuery);
3684                     if($GLOBALS['db']->lastError()){
3685                         logThis('An error occurred when performing this query-->'.$stepsQuery);
3686                     }
3687                     $stepCont = $GLOBALS['db']->fetchByAssoc($steContQ);
3688                     if(isset($stepCont['cont'])){
3689                         $convertedContent = $convertedContent.$stepCont['cont'];
3690                     }
3691                     $start = $start+$next;
3692                     $contentLength = $contentLength - $next;
3693                 }
3694                 $addContentDataText="update {$table_name} set {$column_name}_temp = '{$convertedContent}' where id= '{$row['id']}'";
3695                 $GLOBALS['db']->query($addContentDataText);
3696                 if($GLOBALS['db']->lastError()){
3697                     logThis('An error occurred when performing this query-->'.$addContentDataText);
3698                 }
3699            }
3700            else{
3701                 $addContentDataText="update {$table_name} set {$column_name}_temp =
3702                 convert(varchar(max), convert(varbinary(8000), {$column_name})) where id= '{$row['id']}'";
3703                 $GLOBALS['db']->query($addContentDataText);
3704                 if($GLOBALS['db']->lastError()){
3705                     logThis('An error occurred when performing this query-->'.$addContentDataText);
3706                 }
3707            }
3708         }
3709         //drop the contents now and change contents_temp to contents
3710         $dropColumn = "alter table {$table_name} drop column {$column_name}";
3711         $GLOBALS['db']->query($dropColumn);
3712         if($GLOBALS['db']->lastError()){
3713             logThis('An error occurred when performing this query-->'.$dropColumn);
3714         }
3715         $changeColumnName = "EXEC sp_rename '{$table_name}.[{$column_name}_temp]','{$column_name}','COLUMN'";
3716         $GLOBALS['db']->query($changeColumnName);
3717         if($GLOBALS['db']->lastError()){
3718             logThis('An error occurred when performing this query-->'.$changeColumnName);
3719         }
3720      }
3721     }
3722
3723          /**
3724      * clearHelpFiles
3725      * This method attempts to delete all English inline help files.
3726      * This method was introduced by 5.5.0RC2.
3727      */
3728     function clearHelpFiles(){
3729                 $modulePath = clean_path(getcwd() . '/modules');
3730                 $allHelpFiles = array();
3731                 getFiles($allHelpFiles, $modulePath, "/en_us.help.*/");
3732
3733                 foreach( $allHelpFiles as $the_file ){
3734                 if( is_file( $the_file ) ){
3735                     unlink( $the_file );
3736                     logThis("Deleted file: $the_file");
3737                 }
3738             }
3739         }
3740
3741
3742
3743         /**
3744          * upgradeDateTimeFields
3745          *
3746          * This method came from bug: 39757 where the date_end field is a date field and not a datetime field
3747          * which prevents you from performing timezone offset calculations once the data has been saved.
3748          *
3749          * @param path String location to log file, empty by default
3750          */
3751         function upgradeDateTimeFields($path)
3752         {
3753                 //bug: 39757
3754                 global $db;
3755                 $meetingsSql = "UPDATE meetings SET date_end = ".$db->convert("date_start", 'add_time', array('duration_hours', 'duration_minutes'));
3756                 $callsSql = "UPDATE calls SET date_end = ".$db->convert("date_start", 'add_time', array('duration_hours', 'duration_minutes'));
3757         logThis('upgradeDateTimeFields Meetings SQL:' . $meetingsSql, $path);
3758                 $db->query($meetingsSql);
3759
3760                 logThis('upgradeDateTimeFields Calls SQL:' . $callsSql, $path);
3761                 $db->query($callsSql);
3762         }
3763
3764         /**
3765          * upgradeDocumentTypeFields
3766          *
3767          */
3768         function upgradeDocumentTypeFields($path){
3769                 //bug: 39757
3770                 global $db;
3771
3772                 $documentsSql = "UPDATE documents SET doc_type = 'Sugar' WHERE doc_type IS NULL";
3773                 $meetingsSql = "UPDATE meetings SET type = 'Sugar' WHERE type IS NULL";
3774
3775                 logThis('upgradeDocumentTypeFields Documents SQL:' . $documentsSql, $path);
3776                 $db->query($documentsSql);
3777                 logThis('upgradeDocumentTypeFields Meetings SQL:' . $meetingsSql, $path);
3778                 $db->query($meetingsSql);
3779         }
3780
3781
3782 /**
3783  * merge_config_si_settings
3784  * This method checks for the presence of a config_si.php file and, if found, merges the configuration
3785  * settings from the config_si.php file into config.php.  If a config_si_location parameter value is not
3786  * supplied it will attempt to discover the config_si.php file location from where the executing script
3787  * was invoked.
3788  *
3789  * @param write_to_upgrade_log boolean optional value to write to the upgradeWizard.log file
3790  * @param config_location String optional value to config.php file location
3791  * @param config_si_location String optional value to config_si.php file location
3792  * @param path String file of the location of log file to write to
3793  * @return boolean value indicating whether or not a merge was attempted with config_si.php file
3794  */
3795 function merge_config_si_settings($write_to_upgrade_log=false, $config_location='', $config_si_location='', $path='')
3796 {
3797         if(!empty($config_location) && !file_exists($config_location))
3798         {
3799                 if($write_to_upgrade_log)
3800                 {
3801                logThis('config.php file specified in ' . $config_si_location . ' could not be found.  Skip merging', $path);
3802                 }
3803             return false;
3804         } else if(empty($config_location)) {
3805                 global $argv;
3806                 //We are assuming this is from the silentUpgrade scripts so argv[3] will point to SugarCRM install location
3807                 if(isset($argv[3]) && is_dir($argv[3]))
3808                 {
3809                         $config_location = $argv[3] . DIRECTORY_SEPARATOR . 'config.php';
3810                 }
3811         }
3812
3813         //If config_location is still empty or if the file cannot be found, skip merging
3814         if(empty($config_location) || !file_exists($config_location))
3815         {
3816            if($write_to_upgrade_log)
3817            {
3818                   logThis('config.php file at (' . $config_location . ') could not be found.  Skip merging.', $path);
3819            }
3820            return false;
3821         } else {
3822            if($write_to_upgrade_log)
3823            {
3824               logThis('Loading config.php file at (' . $config_location . ') for merging.', $path);
3825            }
3826
3827            include($config_location);
3828            if(empty($sugar_config))
3829            {
3830                   if($write_to_upgrade_log)
3831                   {
3832                      logThis('config.php contents are empty.  Skip merging.', $path);
3833                   }
3834                   return false;
3835            }
3836         }
3837
3838         if(!empty($config_si_location) && !file_exists($config_si_location))
3839         {
3840                 if($write_to_upgrade_log)
3841                 {
3842                logThis('config_si.php file specified in ' . $config_si_location . ' could not be found.  Skip merging', $path);
3843                 }
3844             return false;
3845         } else if(empty($config_si_location)) {
3846                 if(isset($argv[0]) && is_file($argv[0]))
3847                 {
3848                         $php_file = $argv[0];
3849                         $p_info = pathinfo($php_file);
3850                         $php_dir = (isset($p_info['dirname']) && $p_info['dirname'] != '.') ?  $p_info['dirname'] . DIRECTORY_SEPARATOR : '';
3851                         $config_si_location = $php_dir . 'config_si.php';
3852                 }
3853         }
3854
3855         //If config_si_location is still empty or if the file cannot be found, skip merging
3856         if(empty($config_si_location) || !file_exists($config_si_location))
3857         {
3858            if($write_to_upgrade_log)
3859            {
3860               logThis('config_si.php file at (' . $config_si_location . ') could not be found.  Skip merging.', $path);
3861            }
3862            return false;
3863         } else {
3864            if($write_to_upgrade_log)
3865            {
3866               logThis('Loading config_si.php file at (' . $config_si_location . ') for merging.', $path);
3867            }
3868
3869            include($config_si_location);
3870            if(empty($sugar_config_si))
3871            {
3872               if($write_to_upgrade_log)
3873                   {
3874                      logThis('config_si.php contents are empty.  Skip merging.', $path);
3875                   }
3876                   return false;
3877            }
3878         }
3879
3880         //Now perform the merge operation
3881         $modified = false;
3882         foreach($sugar_config_si as $key=>$value)
3883         {
3884                 if(!preg_match('/^setup_/', $key) && !isset($sugar_config[$key]))
3885                 {
3886                    if($write_to_upgrade_log)
3887                    {
3888                       logThis('Merge key (' . $key . ') with value (' . $value . ')', $path);
3889                    }
3890                    $sugar_config[$key] = $value;
3891                    $modified = true;
3892                 }
3893         }
3894
3895         if($modified)
3896         {
3897                 if($write_to_upgrade_log)
3898                 {
3899                logThis('Update config.php file with new values', $path);
3900                 }
3901
3902             if(!write_array_to_file("sugar_config", $sugar_config, $config_location)) {
3903                if($write_to_upgrade_log)
3904                    {
3905                   logThis('*** ERROR: could not write to config.php', $path);
3906                    }
3907                    return false;
3908                 }
3909         } else {
3910            if($write_to_upgrade_log)
3911            {
3912               logThis('config.php values are in sync with config_si.php values.  Skipped merging.');
3913            }
3914            return false;
3915         }
3916
3917         if($write_to_upgrade_log)
3918         {
3919            logThis('End merge_config_si_settings', $path);
3920         }
3921         return true;
3922 }
3923
3924
3925 /**
3926  * upgrade_connectors
3927  *
3928  * This function handles support for upgrading connectors it is invoked from both end.php and silentUpgrade_step2.php
3929  *
3930  */
3931 function upgrade_connectors() {
3932     require_once('include/connectors/utils/ConnectorUtils.php');
3933     if(!ConnectorUtils::updateMetaDataFiles()) {
3934        $GLOBALS['log']->fatal('Cannot update metadata files for connectors');
3935     }
3936
3937     //Delete the custom connectors.php file if it exists so that it may be properly rebuilt
3938     if(file_exists('custom/modules/Connectors/metadata/connectors.php'))
3939     {
3940         unlink('custom/modules/Connectors/metadata/connectors.php');
3941     }
3942 }
3943
3944 /**
3945  * Enable the InsideView connector for the four default modules.
3946  */
3947 function upgradeEnableInsideViewConnector($path='')
3948 {
3949     logThis('Begin upgradeEnableInsideViewConnector', $path);
3950
3951     // Load up the existing mapping and hand it to the InsideView connector to have it setup the correct logic hooks
3952     $mapFile = 'modules/Connectors/connectors/sources/ext/rest/insideview/mapping.php';
3953     if ( file_exists('custom/'.$mapFile) ) {
3954         logThis('Found CUSTOM mappings', $path);
3955         require('custom/'.$mapFile);
3956     } else {
3957         logThis('Used default mapping', $path);
3958         require($mapFile);
3959     }
3960
3961     require_once('include/connectors/sources/SourceFactory.php');
3962     $source = SourceFactory::getSource('ext_rest_insideview');
3963
3964     // $mapping is brought in from the mapping.php file above
3965     $source->saveMappingHook($mapping);
3966
3967     require_once('include/connectors/utils/ConnectorUtils.php');
3968     ConnectorUtils::installSource('ext_rest_insideview');
3969
3970     // Now time to set the various modules to active, because this part ignores the default config
3971     require(CONNECTOR_DISPLAY_CONFIG_FILE);
3972     // $modules_sources come from that config file
3973     foreach ( $source->allowedModuleList as $module ) {
3974         $modules_sources[$module]['ext_rest_insideview'] = 'ext_rest_insideview';
3975     }
3976     if(!write_array_to_file('modules_sources', $modules_sources, CONNECTOR_DISPLAY_CONFIG_FILE)) {
3977         //Log error and return empty array
3978         logThis("Cannot write \$modules_sources to " . CONNECTOR_DISPLAY_CONFIG_FILE,$path);
3979     }
3980
3981     logThis('End upgradeEnableInsideViewConnector', $path);
3982
3983 }
3984
3985 function repair_long_relationship_names($path='')
3986 {
3987     logThis("Begin repair_long_relationship_names", $path);
3988     require_once 'modules/ModuleBuilder/parsers/relationships/DeployedRelationships.php' ;
3989     $GLOBALS['mi_remove_tables'] = false;
3990     $touched = array();
3991     foreach($GLOBALS['moduleList'] as $module)
3992     {
3993         $relationships = new DeployedRelationships ($module) ;
3994         foreach($relationships->getRelationshipList() as $rel_name)
3995         {
3996             if (strlen($rel_name) > 27 && empty($touched[$rel_name]))
3997             {
3998                 logThis("Rebuilding relationship fields for $rel_name", $path);
3999                 $touched[$rel_name] = true;
4000                 $rel_obj = $relationships->get($rel_name);
4001                 $rel_obj->setReadonly(false);
4002                 $relationships->delete($rel_name);
4003                 $relationships->save();
4004                 $relationships->add($rel_obj);
4005                 $relationships->save();
4006                 $relationships->build () ;
4007             }
4008         }
4009     }
4010     logThis("End repair_long_relationship_names", $path);
4011 }
4012
4013 function removeSilentUpgradeVarsCache(){
4014     global $silent_upgrade_vars_loaded;
4015
4016     $cacheFileDir = "{$GLOBALS['sugar_config']['cache_dir']}/silentUpgrader";
4017     $cacheFile = "{$cacheFileDir}/silentUpgradeCache.php";
4018
4019     if(file_exists($cacheFile)){
4020         unlink($cacheFile);
4021     }
4022
4023     $silent_upgrade_vars_loaded = array(); // Set to empty to reset it
4024
4025     return true;
4026 }
4027
4028 function loadSilentUpgradeVars(){
4029     global $silent_upgrade_vars_loaded;
4030
4031     if(empty($silent_upgrade_vars_loaded)){
4032         $cacheFile = "{$GLOBALS['sugar_config']['cache_dir']}/silentUpgrader/silentUpgradeCache.php";
4033         // We have no pre existing vars
4034         if(!file_exists($cacheFile)){
4035             // Set the vars array so it's loaded
4036             $silent_upgrade_vars_loaded = array('vars' => array());
4037         }
4038         else{
4039             require_once($cacheFile);
4040             $silent_upgrade_vars_loaded = $silent_upgrade_vars_cache;
4041         }
4042     }
4043
4044     return true;
4045 }
4046
4047 function writeSilentUpgradeVars(){
4048     global $silent_upgrade_vars_loaded;
4049
4050     if(empty($silent_upgrade_vars_loaded)){
4051         return false; // You should have set some values before trying to write the silent upgrade vars
4052     }
4053
4054     $cacheFileDir = "{$GLOBALS['sugar_config']['cache_dir']}/silentUpgrader";
4055     $cacheFile = "{$cacheFileDir}/silentUpgradeCache.php";
4056
4057     require_once('include/dir_inc.php');
4058     if(!mkdir_recursive($cacheFileDir)){
4059         return false;
4060     }
4061     require_once('include/utils/file_utils.php');
4062     if(!write_array_to_file('silent_upgrade_vars_cache', $silent_upgrade_vars_loaded, $cacheFile, 'w')){
4063         global $path;
4064         logThis("WARNING: writeSilentUpgradeVars could not write to {$cacheFile}", $path);
4065         return false;
4066     }
4067
4068     return true;
4069 }
4070
4071 function setSilentUpgradeVar($var, $value){
4072     if(!loadSilentUpgradeVars()){
4073         return false;
4074     }
4075
4076     global $silent_upgrade_vars_loaded;
4077
4078     $silent_upgrade_vars_loaded['vars'][$var] = $value;
4079
4080     return true;
4081 }
4082
4083 function getSilentUpgradeVar($var){
4084     if(!loadSilentUpgradeVars()){
4085         return false;
4086     }
4087
4088     global $silent_upgrade_vars_loaded;
4089
4090     if(!isset($silent_upgrade_vars_loaded['vars'][$var])){
4091         return null;
4092     }
4093     else{
4094         return $silent_upgrade_vars_loaded['vars'][$var];
4095     }
4096 }
4097
4098
4099 /**
4100  * add_unified_search_to_custom_modules_vardefs
4101  *
4102  * This method calls the repair code to remove the unified_search_modules.php fiel
4103  *
4104  */
4105 function add_unified_search_to_custom_modules_vardefs()
4106 {
4107         if(file_exists($cachefile = sugar_cached('modules/unified_search_modules.php')))
4108         {
4109            unlink($cachefile);
4110         }
4111
4112 }
4113
4114 /**
4115  * change from using the older SugarCache in 6.1 and below to the new one in 6.2
4116  */
4117 function upgradeSugarCache($file)
4118 {
4119         global $sugar_config;
4120         $cacheUploadUpgradesTemp = mk_temp_dir(sugar_cached('upgrades/temp'));
4121
4122         unzip($file, $cacheUploadUpgradesTemp);
4123
4124         if(!file_exists(clean_path("{$cacheUploadUpgradesTemp}/manifest.php"))) {
4125                 logThis("*** ERROR: no manifest file detected while bootstraping upgrade wizard files!");
4126                 return;
4127         } else {
4128                 include(clean_path("{$cacheUploadUpgradesTemp}/manifest.php"));
4129         }
4130
4131         $from_dir = "{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}";
4132         $allFiles = array();
4133         if(file_exists("$from_dir/include/SugarCache")) {
4134                 $allFiles = findAllFiles("$from_dir/include/SugarCache", $allFiles);
4135         }
4136         if(file_exists("$from_dir/include/database")) {
4137                 $allFiles = findAllFiles("$from_dir/include/database", $allFiles);
4138         }
4139         if(file_exists("$from_dir/include/utils/external_cache.php")) {
4140                 $allFiles[] = "$from_dir/include/utils/external_cache.php";
4141         }
4142         if(file_exists("$from_dir/include/utils/sugar_file_utils.php")) {
4143                 $allFiles[] = "$from_dir/include/utils/sugar_file_utils.php";
4144         }
4145         if(file_exists("$from_dir/include/utils/sugar_file_utils.php")) {
4146                 $allFiles[] = "$from_dir/include/utils/sugar_file_utils.php";
4147         }
4148
4149         foreach($allFiles as $k => $file) {
4150                 $destFile = str_replace($from_dir."/", "", $file);
4151        if(!is_dir(dirname($destFile))) {
4152                         mkdir_recursive(dirname($destFile)); // make sure the directory exists
4153                 }
4154                 if ( stristr($file,'uw_main.tpl') )
4155             logThis('Skipping "'.$file.'" - file copy will during commit step.');
4156         else {
4157             logThis('updating UpgradeWizard code: '.$destFile);
4158             copy_recursive($file, $destFile);
4159         }
4160         }
4161 }
4162
4163
4164 /**
4165  * upgradeDisplayedTabsAndSubpanels
4166  *
4167  * @param $version String value of current system version (pre upgrade)
4168  */
4169 function upgradeDisplayedTabsAndSubpanels($version)
4170 {
4171         if($version < '620')
4172         {
4173                 logThis('start upgrading system displayed tabs and subpanels');
4174             require_once('modules/MySettings/TabController.php');
4175             $tc = new TabController();
4176
4177             //grab the existing system tabs
4178             $tabs = $tc->get_tabs_system();
4179
4180             //add Calls, Meetings, Tasks, Notes, Prospects (Targets) and ProspectLists (Target Lists)
4181             //to displayed tabs unless explicitly set to hidden
4182             $modules_to_add = array('Calls', 'Meetings', 'Tasks', 'Notes', 'Prospects', 'ProspectLists');
4183             $added_tabs = array();
4184
4185             foreach($modules_to_add as $module)
4186             {
4187                        $tabs[0][$module] = $module;
4188                        $added_tabs[] = $module;
4189             }
4190
4191             logThis('calling set_system_tabs on TabController to add tabs: ' . var_export($added_tabs, true));
4192             $tc->set_system_tabs($tabs[0]);
4193             logThis('finish upgrading system displayed tabs and subpanels');
4194         }
4195 }
4196
4197
4198 /**
4199  * unlinkUpgradeFiles
4200  * This is a helper function to clean up
4201  *
4202  * @param $version String value of current system version (pre upgrade)
4203  */
4204 function unlinkUpgradeFiles($version)
4205 {
4206         if(!isset($version))
4207         {
4208            return;
4209         }
4210
4211     //First check if we even have the scripts_for_patch/files_to_remove directory
4212     require_once('modules/UpgradeWizard/UpgradeRemoval.php');
4213
4214     /*
4215     if(empty($_SESSION['unzip_dir']))
4216     {
4217         global $sugar_config;
4218         $base_upgrade_dir               = $sugar_config['upload_dir'] . "/upgrades";
4219         $base_tmp_upgrade_dir   = "$base_upgrade_dir/temp";
4220         $_SESSION['unzip_dir'] = mk_temp_dir( $base_tmp_upgrade_dir );
4221     }
4222     */
4223
4224     if(isset($_SESSION['unzip_dir']) && file_exists($_SESSION['unzip_dir'].'/scripts/files_to_remove'))
4225     {
4226        $files_to_remove = glob($_SESSION['unzip_dir'].'/scripts/files_to_remove/*.php');
4227
4228        foreach($files_to_remove as $script)
4229        {
4230                 if(preg_match('/UpgradeRemoval(\d+)x\.php/', $script, $matches))
4231                 {
4232                    $checkVersion = $matches[1] + 1; //Increment by one to check everything equal or below the target version
4233                    $upgradeClass = 'UpgradeRemoval' . $matches[1] . 'x';
4234                    require_once($_SESSION['unzip_dir'].'/scripts/files_to_remove/' . $upgradeClass . '.php');
4235
4236                    //Check to make sure we should load and run this UpgradeRemoval instance
4237                    if($checkVersion <= $version && class_exists($upgradeClass))
4238                    {
4239                           $upgradeInstance = new $upgradeClass();
4240                           if($upgradeInstance instanceof UpgradeRemoval)
4241                           {
4242                                   logThis('Running UpgradeRemoval instance ' . $upgradeClass);
4243                                   logThis('Files will be backed up to custom/backup');
4244                                   $files = $upgradeInstance->getFilesToRemove($version);
4245                                   foreach($files as $file)
4246                                   {
4247                                          logThis($file);
4248                                   }
4249                                   $upgradeInstance->processFilesToRemove($files);
4250                           }
4251                    }
4252             }
4253        }
4254     }
4255
4256     //Check if we have a custom directory
4257     if(file_exists('custom/scripts/files_to_remove'))
4258     {
4259        //Now find
4260        $files_to_remove = glob('custom/scripts/files_to_remove/*.php');
4261
4262        foreach($files_to_remove as $script)
4263        {
4264            if(preg_match('/\/files_to_remove\/(.*?)\.php$/', $script, $matches))
4265            {
4266                    require_once($script);
4267                    $upgradeClass  = $matches[1];
4268
4269                    if(!class_exists($upgradeClass))
4270                    {
4271                           continue;
4272                    }
4273
4274                    $upgradeInstance = new $upgradeClass();
4275                    if($upgradeInstance instanceof UpgradeRemoval)
4276                    {
4277                                   logThis('Running Custom UpgradeRemoval instance ' . $upgradeClass);
4278                                   $files = $upgradeInstance->getFilesToRemove($version);
4279                                   foreach($files as $file)
4280                                   {
4281                                          logThis($file);
4282                                   }
4283                                   $upgradeInstance->processFilesToRemove($files);
4284                    }
4285            }
4286        }
4287     }
4288
4289 }
4290
4291 if (!function_exists("getValidDBName"))
4292 {
4293     /*
4294      * Return a version of $proposed that can be used as a column name in any of our supported databases
4295      * Practically this means no longer than 25 characters as the smallest identifier length for our supported DBs is 30 chars for Oracle plus we add on at least four characters in some places (for indicies for example)
4296      * @param string $name Proposed name for the column
4297      * @param string $ensureUnique
4298      * @return string Valid column name trimmed to right length and with invalid characters removed
4299      */
4300      function getValidDBName ($name, $ensureUnique = false, $maxLen = 30)
4301     {
4302         // first strip any invalid characters - all but alphanumerics and -
4303         $name = preg_replace ( '/[^\w-]+/i', '', $name ) ;
4304         $len = strlen ( $name ) ;
4305         $result = $name;
4306         if ($ensureUnique)
4307         {
4308             $md5str = md5($name);
4309             $tail = substr ( $name, -11) ;
4310             $temp = substr($md5str , strlen($md5str)-4 );
4311             $result = substr ( $name, 0, 10) . $temp . $tail ;
4312         }else if ($len > ($maxLen - 5))
4313         {
4314             $result = substr ( $name, 0, 11) . substr ( $name, 11 - $maxLen + 5);
4315         }
4316         return strtolower ( $result ) ;
4317     }
4318
4319
4320 }
4321
4322 /**
4323  * Get UW directories
4324  * Provides compatibility with both 6.3 and pre-6.3 setup
4325  */
4326 function getUWDirs()
4327 {
4328     if(!class_exists('UploadStream')) {
4329         // we're still running the old code
4330         global $sugar_config;
4331         return array($sugar_config['upload_dir'] . "/upgrades", $sugar_config['cache_dir'] . "upload/upgrades/temp");
4332     } else {
4333         if(!in_array("upload", stream_get_wrappers())) {
4334             UploadStream::register(); // just in case file was copied, but not run
4335         }
4336         return array("upload://upgrades", sugar_cached("upgrades/temp"));
4337     }
4338 }
4339
4340 /**
4341  * Whether directory exists within list of directories to skip
4342  * @param string $dir dir to be checked
4343  * @param array $skipDirs list with skipped dirs
4344  * @return boolean
4345  */
4346 function whetherNeedToSkipDir($dir, $skipDirs)
4347 {
4348     foreach($skipDirs as $skipMe) {
4349                 if(strpos( clean_path($dir), $skipMe ) !== false) {
4350                         return true;
4351                 }
4352         }
4353     return false;
4354 }
4355
4356
4357 /*
4358  * rebuildSprites
4359  * @param silentUpgrade boolean flag indicating whether or not we should treat running the SugarSpriteBuilder as an upgrade operation
4360  *
4361  */
4362 function rebuildSprites($fromUpgrade=true)
4363 {
4364     require_once('modules/Administration/SugarSpriteBuilder.php');
4365     $sb = new SugarSpriteBuilder();
4366     $sb->cssMinify = true;
4367     $sb->fromSilentUpgrade = $fromUpgrade;
4368     $sb->silentRun = $fromUpgrade;
4369
4370     // add common image directories
4371     $sb->addDirectory('default', 'include/images');
4372     $sb->addDirectory('default', 'themes/default/images');
4373     $sb->addDirectory('default', 'themes/default/images/SugarLogic');
4374
4375     // add all theme image directories
4376     if($dh = opendir('themes'))
4377     {
4378         while (($dir = readdir($dh)) !== false)
4379         {
4380             if ($dir != "." && $dir != ".." && $dir != 'default' && is_dir('themes/'.$dir)) {
4381                 $sb->addDirectory($dir, "themes/{$dir}/images");
4382             }
4383         }
4384         closedir($dh);
4385     }
4386
4387      // add all theme custom image directories
4388     $custom_themes_dir = "custom/themes";
4389     if (is_dir($custom_themes_dir)) {
4390          if($dh = opendir($custom_themes_dir))
4391          {
4392              while (($dir = readdir($dh)) !== false)
4393              {
4394                  //Since the custom theme directories don't require an images directory
4395                  // we check for it implicitly
4396                  if ($dir != "." && $dir != ".." && is_dir('custom/themes/'.$dir."/images")) {
4397                      $sb->addDirectory($dir, "custom/themes/{$dir}/images");
4398                  }
4399              }
4400              closedir($dh);
4401          }
4402     }
4403
4404     // generate the sprite goodies
4405     // everything is saved into cache/sprites
4406     $sb->createSprites();
4407 }
4408
4409
4410 /**
4411  * repairSearchFields
4412  *
4413  * This method goes through the list of SearchFields files based and calls TemplateRange::repairCustomSearchFields
4414  * method on the files in an attempt to ensure the range search attributes are properly set in SearchFields.php.
4415  *
4416  * @param $globString String value used for glob search defaults to searching for all SearchFields.php files in modules directory
4417  * @param $path String value used to point to log file should logging be required.  Defaults to empty.
4418  *
4419  */
4420 function repairSearchFields($globString='modules/*/metadata/SearchFields.php', $path='')
4421 {
4422         if(!empty($path))
4423         {
4424                 logThis('Begin repairSearchFields', $path);
4425         }
4426
4427         require_once('include/dir_inc.php');
4428         require_once('modules/DynamicFields/templates/Fields/TemplateRange.php');
4429         require('include/modules.php');
4430
4431         global $beanList;
4432         $searchFieldsFiles = glob($globString);
4433
4434         foreach($searchFieldsFiles as $file)
4435         {
4436                 if(preg_match('/modules\/(.*?)\/metadata\/SearchFields\.php/', $file, $matches) && isset($beanList[$matches[1]]))
4437                 {
4438                         $module = $matches[1];
4439                         $beanName = $beanList[$module];
4440                         VardefManager::loadVardef($module, $beanName);
4441                         if(isset($GLOBALS['dictionary'][$beanName]['fields']))
4442                         {
4443                                 if(!empty($path))
4444                                 {
4445                                         logThis('Calling TemplateRange::repairCustomSearchFields for module ' . $module, $path);
4446                                 }
4447                                 TemplateRange::repairCustomSearchFields($GLOBALS['dictionary'][$beanName]['fields'], $module);
4448                         }
4449                 }
4450         }
4451
4452         if(!empty($path))
4453         {
4454                 logThis('End repairSearchFields', $path);
4455         }
4456 }
4457
4458 /**
4459  * repairUpgradeHistoryTable
4460  *
4461  * This is a helper function used in the upgrade process to fix upgrade_history entries so that the filename column points
4462  * to the new upload directory location introduced in 6.4 versions
4463  */
4464 function repairUpgradeHistoryTable()
4465 {
4466     require_once('modules/Configurator/Configurator.php');
4467     new Configurator();
4468     global $sugar_config;
4469
4470     //Now upgrade the upgrade_history table entries
4471     $results = $GLOBALS['db']->query('SELECT id, filename FROM upgrade_history');
4472     $upload_dir = $sugar_config['cache_dir'].'upload/';
4473
4474     //Create regular expression string to
4475     $match = '/^' . str_replace('/', '\/', $upload_dir) . '(.*?)$/';
4476
4477     while(($row = $GLOBALS['db']->fetchByAssoc($results)))
4478     {
4479         $file = str_replace('//', '/', $row['filename']); //Strip out double-paths that may exist
4480
4481         if(!empty($file) && preg_match($match, $file, $matches))
4482         {
4483             //Update new file location to use the new $sugar_config['upload_dir'] value
4484             $new_file_location = $sugar_config['upload_dir'] . $matches[1];
4485             $GLOBALS['db']->query("UPDATE upgrade_history SET filename = '{$new_file_location}' WHERE id = '{$row['id']}'");
4486         }
4487     }
4488
4489 }