]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - modules/UpgradeWizard/uw_utils.php
Release 6.5.1
[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         } //while
3026 }
3027
3028
3029 /**
3030  * Checks if a locale name format is part of the default list, if not adds it to the config
3031  * @param $name_format string a local name format string such as 's f l'
3032  * @return bool true on successful write to config file, false on failure;
3033  */
3034 function upgradeLocaleNameFormat($name_format) {
3035     global $sugar_config, $sugar_version;
3036
3037     $localization = new Localization();
3038     $localeConfigDefaults = $localization->getLocaleConfigDefaults();
3039
3040     $uw_strings = return_module_language($GLOBALS['current_language'], 'UpgradeWizard');
3041     if(empty($sugar_config['name_formats'])) {
3042         $sugar_config['name_formats'] = $localeConfigDefaults['name_formats'];
3043         if(!rebuildConfigFile($sugar_config, $sugar_version)) {
3044             $errors[] = $uw_strings['ERR_UW_CONFIG_WRITE'];
3045         }
3046     }
3047     if (!in_array($name_format, $sugar_config['name_formats'])) {
3048         $new_config = sugarArrayMerge($sugar_config['name_formats'], array($name_format=>$name_format));
3049         $sugar_config['name_formats'] = $new_config;
3050         if(!rebuildConfigFile($sugar_config, $sugar_version)) {
3051             $errors[] = $uw_strings['ERR_UW_CONFIG_WRITE'];
3052             return false;
3053         }
3054     }
3055     return true;
3056 }
3057
3058
3059
3060 function add_custom_modules_favorites_search(){
3061     $module_directories = scandir('modules');
3062
3063         foreach($module_directories as $module_dir){
3064                 if($module_dir == '.' || $module_dir == '..' || !is_dir("modules/{$module_dir}")){
3065                         continue;
3066                 }
3067
3068                 $matches = array();
3069                 preg_match('/^[a-z0-9]{1,5}_[a-z0-9_]+$/i' , $module_dir, $matches);
3070
3071                 // Make sure the module was created by module builder
3072                 if(empty($matches)){
3073                         continue;
3074                 }
3075
3076                 $full_module_dir = "modules/{$module_dir}/";
3077                 $read_searchdefs_from = "{$full_module_dir}/metadata/searchdefs.php";
3078                 $read_SearchFields_from = "{$full_module_dir}/metadata/SearchFields.php";
3079                 $read_custom_SearchFields_from = "custom/{$full_module_dir}/metadata/SearchFields.php";
3080
3081                 // Studio can possibly override this file, so we check for a custom version of it
3082                 if(file_exists("custom/{$full_module_dir}/metadata/searchdefs.php")){
3083                         $read_searchdefs_from = "custom/{$full_module_dir}/metadata/searchdefs.php";
3084                 }
3085
3086                 if(file_exists($read_searchdefs_from) && file_exists($read_SearchFields_from)){
3087                         $found_sf1 = false;
3088                         $found_sf2 = false;
3089                         require($read_searchdefs_from);
3090                         foreach($searchdefs[$module_dir]['layout']['basic_search'] as $sf_array){
3091                                 if(isset($sf_array['name']) && $sf_array['name'] == 'favorites_only'){
3092                                         $found_sf1 = true;
3093                                 }
3094                         }
3095
3096                         require($read_SearchFields_from);
3097                         if(isset($searchFields[$module_dir]['favorites_only'])){
3098                                 $found_sf2 = true;
3099                         }
3100
3101                         if(!$found_sf1 && !$found_sf2){
3102                                 $searchdefs[$module_dir]['layout']['basic_search']['favorites_only'] = array('name' => 'favorites_only','label' => 'LBL_FAVORITES_FILTER','type' => 'bool',);
3103                                 $searchdefs[$module_dir]['layout']['advanced_search']['favorites_only'] = array('name' => 'favorites_only','label' => 'LBL_FAVORITES_FILTER','type' => 'bool',);
3104                                 $searchFields[$module_dir]['favorites_only'] = array(
3105                                         'query_type'=>'format',
3106                                         'operator' => 'subquery',
3107                                         'subquery' => 'SELECT sugarfavorites.record_id FROM sugarfavorites
3108                                                                 WHERE sugarfavorites.deleted=0
3109                                                                         and sugarfavorites.module = \''.$module_dir.'\'
3110                                                                         and sugarfavorites.assigned_user_id = \'{0}\'',
3111                                         'db_field'=>array('id')
3112                                 );
3113
3114                                 if(!is_dir("custom/{$full_module_dir}/metadata")){
3115                                         mkdir_recursive("custom/{$full_module_dir}/metadata");
3116                                 }
3117                                 $success_sf1 = write_array_to_file('searchdefs', $searchdefs, "custom/{$full_module_dir}/metadata/searchdefs.php");
3118                                 $success_sf2 = write_array_to_file('searchFields', $searchFields, "{$full_module_dir}/metadata/SearchFields.php");
3119
3120                                 if(!$success_sf1){
3121                                         logThis("add_custom_modules_favorites_search failed for searchdefs.php for {$module_dir}");
3122                                 }
3123                                 if(!$success_sf2){
3124                                         logThis("add_custom_modules_favorites_search failed for SearchFields.php for {$module_dir}");
3125                                 }
3126                                 if($success_sf1 && $success_sf2){
3127                                         logThis("add_custom_modules_favorites_search successfully updated searchdefs and searchFields for {$module_dir}");
3128                                 }
3129                         }
3130                 }
3131         }
3132 }
3133
3134
3135 /**
3136  * upgradeModulesForTeamsets
3137  *
3138  * This method adds the team_set_id values to the module tables that have the new team_set_id column
3139  * added through the SugarCRM 5.5.x upgrade process.  It also adds the values into the team_sets and
3140  * team_sets_teams tables.
3141  *
3142  * @param filter Array of modules to process; empty by default
3143  */
3144 function upgradeModulesForTeamsets($filter=array()) {
3145     require('include/modules.php');
3146         foreach($beanList as $moduleName=>$beanName) {
3147                     if(!empty($filter) && array_search($moduleName, $filter) === false) {
3148                        continue;
3149                     }
3150                 if($moduleName == 'TeamMemberships' || $moduleName == 'ForecastOpportunities'){
3151                 continue;
3152             }
3153                         $bean = loadBean($moduleName);
3154                         if(empty($bean) ||
3155                            empty($bean->table_name)) {
3156                            continue;
3157                         }
3158
3159                         $FieldArray = $GLOBALS['db']->helper->get_columns($bean->table_name);
3160                         if(!isset($FieldArray['team_id'])) {
3161                            continue;
3162                         }
3163
3164                         upgradeTeamColumn($bean, 'team_id');
3165
3166         } //foreach
3167
3168     //Upgrade users table
3169         $bean = loadBean('Users');
3170         upgradeTeamColumn($bean, 'default_team');
3171         $result = $GLOBALS['db']->query("SELECT id FROM teams where deleted=0");
3172         while($row = $GLOBALS['db']->fetchByAssoc($result)) {
3173               $teamset = new TeamSet();
3174               $teamset->addTeams($row['id']);
3175         }
3176 }
3177
3178
3179 /**
3180  * upgradeTeamColumn
3181  * Helper function to create a team_set_id column and also set team_set_id column
3182  * to have the value of the $column_name parameter
3183  *
3184  * @param $bean SugarBean which we are adding team_set_id column to
3185  * @param $column_name The name of the column containing the default team_set_id value
3186  */
3187 function upgradeTeamColumn($bean, $column_name) {
3188         //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
3189         //module that does not use the SugarObjects
3190         if(empty($bean->field_defs['team_set_id']) && $bean->module_dir != 'Trackers'){
3191
3192                 //at this point we could assume that since we have a team_id defined and not a team_set_id that we need to
3193                 //add that field and the corresponding relationships
3194                 $object = $bean->object_name;
3195                 $module = $bean->module_dir;
3196                 $object_name = $object;
3197                 $_object_name = strtolower($object_name);
3198
3199                 if(!empty($GLOBALS['dictionary'][$object]['table'])){
3200                         $table_name = $GLOBALS['dictionary'][$object]['table'];
3201                 }else{
3202                         $table_name = strtolower($module);
3203                 }
3204
3205                 $path = 'include/SugarObjects/implements/team_security/vardefs.php';
3206                 require($path);
3207                 //go through each entry in the vardefs from team_security and unset anything that is already set in the core module
3208                 //this will ensure we have the proper ordering.
3209                 $fieldDiff = array_diff_assoc($vardefs['fields'], $GLOBALS['dictionary'][$bean->object_name]['fields']);
3210
3211                 $file = 'custom/Extension/modules/' . $bean->module_dir. '/Ext/Vardefs/teams.php';
3212                 $contents = "<?php\n";
3213                 if(!empty($fieldDiff)){
3214                         foreach($fieldDiff as $key => $val){
3215                                 $contents .= "\n\$GLOBALS['dictionary']['". $object . "']['fields']['". $key . "']=" . var_export_helper($val) . ";";
3216                         }
3217                 }
3218                 $relationshipDiff = array_diff_assoc($vardefs['relationships'], $GLOBALS['dictionary'][$bean->object_name]['relationships']);
3219                 if(!empty($relationshipDiff)){
3220                         foreach($relationshipDiff as $key => $val){
3221                                 $contents .= "\n\$GLOBALS['dictionary']['". $object . "']['relationships']['". $key . "']=" . var_export_helper($val) . ";";
3222                         }
3223                 }
3224                 $indexDiff = array_diff_assoc($vardefs['indices'], $GLOBALS['dictionary'][$bean->object_name]['indices']);
3225                 if(!empty($indexDiff)){
3226                         foreach($indexDiff as $key => $val){
3227                                         $contents .= "\n\$GLOBALS['dictionary']['". $object . "']['indices']['". $key . "']=" . var_export_helper($val) . ";";
3228                         }
3229                 }
3230                 if( $fh = @sugar_fopen( $file, 'wt' ) )
3231             {
3232                 fputs( $fh, $contents);
3233                 fclose( $fh );
3234             }
3235
3236
3237                 //we have written out the teams.php into custom/Extension/modules/{$module_dir}/Ext/Vardefs/teams.php'
3238                 //now let's merge back into vardefs.ext.php
3239                 require_once('ModuleInstall/ModuleInstaller.php');
3240                 $mi = new ModuleInstaller();
3241                 $mi->merge_files('Ext/Vardefs/', 'vardefs.ext.php');
3242                 VardefManager::loadVardef($bean->module_dir, $bean->object_name, true);
3243                 $bean->field_defs = $GLOBALS['dictionary'][$bean->object_name]['fields'];
3244         }
3245
3246         if(isset($bean->field_defs['team_set_id'])) {
3247                 //Create the team_set_id column
3248                 $FieldArray = $GLOBALS['db']->helper->get_columns($bean->table_name);
3249                 if(!isset($FieldArray['team_set_id'])) {
3250                         $GLOBALS['db']->addColumn($bean->table_name, $bean->field_defs['team_set_id']);
3251                 }
3252                 $indexArray =  $GLOBALS['db']->helper->get_indices($bean->table_name);
3253
3254         $indexName = getValidDBName('idx_'.strtolower($bean->table_name).'_tmst_id', true, 34);
3255         $indexDef = array(
3256                                          array(
3257                                                 'name' => $indexName,
3258                                                 'type' => 'index',
3259                                                 'fields' => array('team_set_id')
3260                                          )
3261                                    );
3262                 if(!isset($indexArray[$indexName])) {
3263                         $GLOBALS['db']->addIndexes($bean->table_name, $indexDef);
3264                 }
3265
3266                 //Update the table's team_set_id column to have the same values as team_id
3267             $GLOBALS['db']->query("UPDATE {$bean->table_name} SET team_set_id = {$column_name}");
3268         }
3269 }
3270
3271 /**
3272  *  Update the folder subscription table which confirms to the team security mechanism but
3273  *  the class SugarFolders does not extend SugarBean and is therefore never picked up by the
3274  *  upgradeModulesForTeamsets function.
3275  */
3276 function upgradeFolderSubscriptionsTeamSetId()
3277 {
3278     logThis("In upgradeFolderSubscriptionsTeamSetId()");
3279     $query = "UPDATE folders SET team_set_id = team_id";
3280     $result = $GLOBALS['db']->query($query);
3281     logThis("Finished upgradeFolderSubscriptionsTeamSetId()");
3282 }
3283
3284 /**
3285  * upgradeModulesForTeam
3286  *
3287  * This method update the associated_user_id, name, name_2 to the private team records on teams table
3288  * This function is used for upgrade process from 5.1.x and 5.2.x.
3289  *
3290  */
3291 function upgradeModulesForTeam() {
3292     logThis("In upgradeModulesForTeam()");
3293     $result = $GLOBALS['db']->query("SELECT id, user_name, first_name, last_name FROM users where deleted=0");
3294
3295     while($row = $GLOBALS['db']->fetchByAssoc($result)) {
3296         $results2 = $GLOBALS['db']->query("SELECT id FROM teams WHERE name = '({$row['user_name']})'");
3297         $assoc = '';
3298                 if(!$assoc = $GLOBALS['db']->fetchByAssoc($results2)) {
3299                         //if team does not exist, then lets create the team for this user
3300                         $team = new Team();
3301                         $user = new User();
3302                         $user->retrieve($row['id']);
3303                         $team->new_user_created($user);
3304                         $team_id = $team->id;
3305                 }else{
3306                         $team_id =$assoc['id'];
3307                 }
3308
3309                         //upgrade the team
3310                         $name = is_null($row['first_name'])?'':$row['first_name'];
3311                         $name_2 = is_null($row['last_name'])?'':$row['last_name'];
3312                         $associated_user_id = $row['id'];
3313
3314                         //Bug 32914
3315                         //Ensure team->name is not empty by using team->name_2 if available
3316                         if(empty($name) && !empty($name_2)) {
3317                            $name = $name_2;
3318                            $name_2 = '';
3319                         }
3320
3321                         $query = "UPDATE teams SET name = '{$name}', name_2 = '{$name_2}', associated_user_id = '{$associated_user_id}' WHERE id = '{$team_id}'";
3322                         $GLOBALS['db']->query($query);
3323     } //while
3324
3325     //Update the team_set_id and default_team columns
3326     $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'));
3327
3328     //Update team_set_id
3329         if($ce_to_pro_or_ent) {
3330            $GLOBALS['db']->query("update users set team_set_id = (select teams.id from teams where teams.associated_user_id = users.id)");
3331            $GLOBALS['db']->query("update users set default_team = (select teams.id from teams where teams.associated_user_id = users.id)");
3332         }
3333
3334 }
3335
3336
3337     function addNewSystemTabsFromUpgrade($from_dir){
3338         global $path;
3339         if(isset($_SESSION['upgrade_from_flavor'])){
3340
3341             //check to see if there are any new files that need to be added to systems tab
3342             //retrieve old modules list
3343             logThis('check to see if new modules exist',$path);
3344             $oldModuleList = array();
3345             $newModuleList = array();
3346             include($from_dir.'/include/modules.php');
3347             $oldModuleList = $moduleList;
3348             include('include/modules.php');
3349             $newModuleList = $moduleList;
3350
3351             //include tab controller
3352             require_once('modules/MySettings/TabController.php');
3353             $newTB = new TabController();
3354
3355             //make sure new modules list has a key we can reference directly
3356             $newModuleList = $newTB->get_key_array($newModuleList);
3357             $oldModuleList = $newTB->get_key_array($oldModuleList);
3358
3359             //iterate through list and remove commonalities to get new modules
3360             foreach ($newModuleList as $remove_mod){
3361                 if(in_array($remove_mod, $oldModuleList)){
3362                     unset($newModuleList[$remove_mod]);
3363                 }
3364             }
3365             //new modules list now has left over modules which are new to this install, so lets add them to the system tabs
3366             logThis('new modules to add are '.var_export($newModuleList,true),$path);
3367
3368             if(!empty($newModuleList))
3369             {
3370                     //grab the existing system tabs
3371                     $tabs = $newTB->get_system_tabs();
3372
3373                     //add the new tabs to the array
3374                     foreach($newModuleList as $nm ){
3375                       $tabs[$nm] = $nm;
3376                     }
3377
3378                     $newTB->set_system_tabs($tabs);
3379             }
3380             logThis('module tabs updated',$path);
3381         }
3382     }
3383
3384     /**
3385      * fix_dropdown_list
3386      * This method attempts to fix dropdown lists that were incorrectly named.
3387      * There were versions of SugarCRM that did not enforce naming convention rules
3388      * for the dropdown list field name.  This method attempts to resolve that by
3389      * fixing the language files that may have been affected and then updating the
3390      * fields_meta_data table accordingly.  It also refreshes any vardefs that may
3391      * have been affected.
3392      *
3393      */
3394         function fix_dropdown_list() {
3395         if(file_exists('custom/include/language')) {
3396            $files = array();
3397            $affected_modules = array();
3398            $affected_keys = array();
3399
3400            getFiles($files, 'custom/include/language', '/\.php$/i');
3401            foreach($files as $file) {
3402
3403               if(file_exists($file . '.bak')) {
3404                  $bak_mod_time = filemtime($file . '.bak');
3405                  $php_mod_time = filemtime($file);
3406                  //We're saying if the .php file was modified 30 seconds no more than php.bak file then we
3407                  //run these additional cleanup checks
3408                  if($php_mod_time - $bak_mod_time < 30) {
3409
3410                         $app_list_strings = array();
3411                         $GLOBALS['app_list_strings'] = array();
3412                         require($file . '.bak');
3413                         $bak_app_list_strings = array_merge($app_list_strings, $GLOBALS['app_list_strings']);
3414
3415                         $app_list_strings = array();
3416                         $GLOBALS['app_list_strings'] = array();
3417                         require($file);
3418                         $php_app_list_strings = array_merge($app_list_strings, $GLOBALS['app_list_strings']);
3419
3420                         //Get the file contents
3421                         $contents = file_get_contents($file);
3422
3423                         //Now simulate a fix for the file before we compare w/ the .php file
3424                         //we also append to the $contents
3425                         foreach($bak_app_list_strings as $key=>$entry) {
3426                                                    if(preg_match('/([^A-Za-z_])/', $key, $matches) && is_array($entry)) {
3427                                                           $new_key = preg_replace('/[^A-Za-z_]/', '_', $key);
3428                                                           $bak_app_list_strings[$new_key] = $bak_app_list_strings[$key];
3429                                                           unset($bak_app_list_strings[$key]);
3430                                                           //Now if the entry doesn't exists in the .php file, then add to contents
3431                                                           if(!isset($php_app_list_strings[$new_key])) {
3432                                                                  $contents .= "\n\$GLOBALS['app_list_strings']['{$new_key}'] = " . var_export_helper($bak_app_list_strings[$new_key]) . ";";
3433                                                           }
3434                                                    } //if
3435                         } //foreach
3436
3437                         //Now load the .php file to do the comparison
3438                         foreach($php_app_list_strings as $key=>$entry) {
3439                                 if(isset($bak_app_list_strings[$key])) {
3440                                         $diff = array_diff($bak_app_list_strings[$key], $entry);
3441                                         if(!empty($diff)) {
3442                                            //There is a difference, so copy the $bak_app_list_strings version into the .php file
3443                                            $contents .= "\n\$GLOBALS['app_list_strings']['{$key}'] = " . var_export_helper($bak_app_list_strings[$key]) . ";";
3444                                         } //if
3445                                 } //if
3446                         } //foreach
3447
3448                         //Now write out the file contents
3449                         //Create backup just in case
3450                         copy($file, $file . '.php_bak');
3451                                         $fp = @sugar_fopen($file, 'w');
3452                         if($fp) {
3453                                fwrite($fp, $contents);
3454                                fclose($fp);
3455                         } else {
3456                            $GLOBALS['log']->error("Unable to update file contents in fix_dropdown_list for {$file}");
3457                         } //if-else
3458                  }
3459               }
3460
3461               unset($GLOBALS['app_strings']);
3462               unset($GLOBALS['app_list_strings']);
3463               $app_list_strings = array();
3464                   require($file);
3465                   $touched = false;
3466                   $contents = file_get_contents($file);
3467                   if ( !isset($GLOBALS['app_list_strings']) ) {
3468                       $GLOBALS['app_list_strings'] = $app_list_strings;
3469                   }
3470                   else {
3471                       $GLOBALS['app_list_strings'] = array_merge($app_list_strings, $GLOBALS['app_list_strings']);
3472                   }
3473
3474                   if(isset($GLOBALS['app_list_strings']) && is_array($GLOBALS['app_list_strings'])) {
3475                          foreach($GLOBALS['app_list_strings'] as $key=>$entry) {
3476                                 if(preg_match('/([^A-Za-z_])/', $key, $matches) && is_array($entry)) {
3477                                    $result = $GLOBALS['db']->query("SELECT custom_module FROM fields_meta_data WHERE ext1 = '{$key}'");
3478                                    if(!empty($result)) {
3479                                           while($row = $GLOBALS['db']->fetchByAssoc($result)) {
3480                                                     $custom_module = $row['custom_module'];
3481                                                     if(!empty($GLOBALS['beanList'][$custom_module])) {
3482                                                    $affected_modules[$custom_module] = $GLOBALS['beanList'][$custom_module];
3483                                                     }
3484                                           } //while
3485                                    }
3486
3487                                    //Replace all invalid characters with '_' character
3488                                    $new_key = preg_replace('/[^A-Za-z_]/', '_', $key);
3489                                    $affected_keys[$key] = $new_key;
3490
3491                                    $GLOBALS['app_list_strings'][$new_key] = $GLOBALS['app_list_strings'][$key];
3492                                    unset($GLOBALS['app_list_strings'][$key]);
3493
3494                                    $pattern_match = "/(\[\s*\'{$key}\'\s*\])/";
3495                                    $new_key = "['{$new_key}']";
3496                                    $out = preg_replace($pattern_match, $new_key, $contents);
3497                                    $contents = $out;
3498                                    $touched = true;
3499                                 } //if
3500                          } //foreach
3501
3502                  //This is a check for g => h instances where the file contents were incorrectly written
3503                  //and also fixes the scenario where via a UI upgrade, the app_list_strings were incorrectly
3504                  //merged with app_list_strings variables declared elsewhere
3505                          if(!$touched) {
3506                                    if(preg_match('/\$GLOBALS\s*\[\s*[\"|\']app_list_strings[\"|\']\s*\]\s*=\s*array\s*\(/', $contents)) {
3507                                           //Now also remove all the non-custom labels that were added
3508                                           if(preg_match('/language\/([^\.]+)\.lang\.php$/', $file, $matches)) {
3509                                                 $language = $matches[1];
3510
3511                                                 $app_list_strings = array();
3512
3513                                         if(file_exists("include/language/$language.lang.php")) {
3514                                                                    include("include/language/$language.lang.php");
3515                                                                 }
3516                                                                 if(file_exists("include/language/$language.lang.override.php")) {
3517                                                                    $app_list_strings =  _mergeCustomAppListStrings("include/language/$language.lang.override.php" , $app_list_strings) ;
3518                                                                 }
3519                                                                 if(file_exists("custom/application/Ext/Language/$language.ext.lang.php")) {
3520                                                                    $app_list_strings =  _mergeCustomAppListStrings("custom/application/Ext/Language/$language.ext.lang.php" , $app_list_strings) ;
3521                                                                 }
3522                                                                 if(file_exists("custom/application/Ext/Language/$language.lang.ext.php")) {
3523                                                                    $app_list_strings =  _mergeCustomAppListStrings("custom/application/Ext/Language/$language.lang.ext.php" , $app_list_strings) ;
3524                                                                 }
3525
3526                                                                 $all_non_custom_include_language_strings = $app_strings;
3527                                                                 $all_non_custom_include_language_list_strings = $app_list_strings;
3528
3529                                                                 $unset_keys = array();
3530                                                                 if(!empty($GLOBALS['app_list_strings'])) {
3531                                                                         foreach($GLOBALS['app_list_strings'] as $key=>$value) {
3532                                                                                 $diff = array();
3533                                                                                 if(isset($all_non_custom_include_language_list_strings[$key])) {
3534                                                                                         $diff = array_diff($all_non_custom_include_language_list_strings[$key], $GLOBALS['app_list_strings'][$key]);
3535                                                                                 }
3536
3537                                                                                 if(!empty($all_non_custom_include_language_list_strings[$key]) && empty($diff)) {
3538                                                                                         $unset_keys[] = $key;
3539                                                                                 }
3540                                                                         }
3541                                                                 }
3542
3543                                                                 foreach($unset_keys as $key) {
3544                                                                         unset($GLOBALS['app_list_strings'][$key]);
3545                                                                 }
3546
3547                                                                 if(!empty($GLOBALS['app_strings'])) {
3548                                                                 foreach($GLOBALS['app_strings'] as $key=>$value) {
3549                                                                                 if(!empty($all_non_custom_include_language_strings[$key])) {
3550                                                                                    unset($GLOBALS['app_strings'][$key]);
3551                                                                                 }
3552                                                                 }
3553                                                                 }
3554                                           } //if(preg_match...)
3555
3556                                       $out = "<?php \n";
3557                                       if(!empty($GLOBALS['app_strings'])) {
3558                                              foreach($GLOBALS['app_strings'] as $key=>$entry) {
3559                                                      $out .= "\n\$GLOBALS['app_strings']['$key']=" . var_export_helper($entry) . ";";
3560                                              }
3561                                       }
3562
3563                                                   foreach($GLOBALS['app_list_strings'] as $key=>$entry) {
3564                                                                   $out .= "\n\$GLOBALS['app_list_strings']['$key']=" . var_export_helper($entry) . ";";
3565                                                   } //foreach
3566
3567                                                   $touched = true;
3568                                    } //if(preg_match...)
3569                          } //if(!$touched)
3570
3571                          if($touched) {
3572                                  //Create a backup just in case
3573                                  copy($file, $file . '.bak');
3574                          $fp = @sugar_fopen($file, 'w');
3575                          if($fp) {
3576                                fwrite($fp, $out);
3577                                fclose($fp);
3578                          } else {
3579                            //If we can't update the file, just return
3580                            $GLOBALS['log']->error("Unable to update file contents in fix_dropdown_list.");
3581                            return;
3582                          }
3583                          } //if($touched)
3584                   } //if
3585
3586            } //foreach($files)
3587
3588            //Update db entries (the order matters here... need to process database changes first)
3589            if(!empty($affected_keys)) {
3590                   foreach($affected_keys as $old_key=>$new_key) {
3591                                   $GLOBALS['db']->query("UPDATE fields_meta_data SET ext1 = '{$new_key}' WHERE ext1 = '{$old_key}'");
3592                   }
3593            }
3594
3595            //Update vardef files for affected modules
3596            if(!empty($affected_modules)) {
3597                   foreach($affected_modules as $module=>$object) {
3598                           VardefManager::refreshVardefs($module, $object);
3599                   }
3600            }
3601         }
3602         }
3603
3604
3605         function update_iframe_dashlets(){
3606                 require_once(sugar_cached('dashlets/dashlets.php'));
3607
3608                 $db = DBManagerFactory::getInstance();
3609                 $query = "SELECT id, contents, assigned_user_id FROM user_preferences WHERE deleted = 0 AND category = 'Home'";
3610                 $result = $db->query($query, true, "Unable to update new default dashlets! ");
3611                 while ($row = $db->fetchByAssoc($result)) {
3612                         $content = unserialize(base64_decode($row['contents']));
3613                         $assigned_user_id = $row['assigned_user_id'];
3614                         $record_id = $row['id'];
3615
3616                         $current_user = new User();
3617                         $current_user->retrieve($row['assigned_user_id']);
3618
3619                         if(!empty($content['dashlets']) && !empty($content['pages'])){
3620                                 $originalDashlets = $content['dashlets'];
3621                                 foreach($originalDashlets as $key => $ds){
3622                                     if(!empty($ds['options']['url']) && stristr($ds['options']['url'],'http://www.sugarcrm.com/crm/product/gopro')){
3623                                                 unset($originalDashlets[$key]);
3624                                         }
3625                                 }
3626                                 $current_user->setPreference('dashlets', $originalDashlets, 0, 'Home');
3627                         }
3628                 }
3629         }
3630
3631
3632     /**
3633      * convertImageToText
3634      * @deprecated
3635      * This method attempts to convert date type image to text on Microsoft SQL Server.
3636      * This method could NOT be used in any other type of datebases.
3637      */
3638         function convertImageToText($table_name,$column_name){
3639                 $set_lang = "SET LANGUAGE us_english";
3640                 $GLOBALS['db']->query($set_lang);
3641             if($GLOBALS['db']->lastError()){
3642             logThis('An error occurred when performing this query-->'.$set_lang);
3643         }
3644        $q="SELECT data_type
3645         FROM INFORMATION_SCHEMA.Tables T JOIN INFORMATION_SCHEMA.Columns C
3646         ON T.TABLE_NAME = C.TABLE_NAME where T.TABLE_NAME = '$table_name' and C.COLUMN_NAME = '$column_name'";
3647        $res= $GLOBALS['db']->query($q);
3648        if($GLOBALS['db']->lastError()){
3649             logThis('An error occurred when performing this query-->'.$q);
3650         }
3651        $row= $GLOBALS['db']->fetchByAssoc($res);
3652
3653      if(trim(strtolower($row['data_type'])) == 'image'){
3654         $addContent_temp = "alter table {$table_name} add {$column_name}_temp text null";
3655         $GLOBALS['db']->query($addContent_temp);
3656         if($GLOBALS['db']->lastError()){
3657             logThis('An error occurred when performing this query-->'.$addContent_temp);
3658         }
3659         $qN = "select count=datalength({$column_name}), id, {$column_name} from {$table_name}";
3660         $result = $GLOBALS['db']->query($qN);
3661         while($row = $GLOBALS['db']->fetchByAssoc($result)){
3662            if($row['count'] >8000){
3663                 $contentLength = $row['count'];
3664                 $start = 1;
3665                 $next=8000;
3666                 $convertedContent = '';
3667                 while($contentLength >0){
3668                     $stepsQuery = "select cont=convert(varchar(max), convert(varbinary(8000), substring({$column_name},{$start},{$next}))) from {$table_name} where id= '{$row['id']}'";
3669                     $steContQ = $GLOBALS['db']->query($stepsQuery);
3670                     if($GLOBALS['db']->lastError()){
3671                         logThis('An error occurred when performing this query-->'.$stepsQuery);
3672                     }
3673                     $stepCont = $GLOBALS['db']->fetchByAssoc($steContQ);
3674                     if(isset($stepCont['cont'])){
3675                         $convertedContent = $convertedContent.$stepCont['cont'];
3676                     }
3677                     $start = $start+$next;
3678                     $contentLength = $contentLength - $next;
3679                 }
3680                 $addContentDataText="update {$table_name} set {$column_name}_temp = '{$convertedContent}' where id= '{$row['id']}'";
3681                 $GLOBALS['db']->query($addContentDataText);
3682                 if($GLOBALS['db']->lastError()){
3683                     logThis('An error occurred when performing this query-->'.$addContentDataText);
3684                 }
3685            }
3686            else{
3687                 $addContentDataText="update {$table_name} set {$column_name}_temp =
3688                 convert(varchar(max), convert(varbinary(8000), {$column_name})) where id= '{$row['id']}'";
3689                 $GLOBALS['db']->query($addContentDataText);
3690                 if($GLOBALS['db']->lastError()){
3691                     logThis('An error occurred when performing this query-->'.$addContentDataText);
3692                 }
3693            }
3694         }
3695         //drop the contents now and change contents_temp to contents
3696         $dropColumn = "alter table {$table_name} drop column {$column_name}";
3697         $GLOBALS['db']->query($dropColumn);
3698         if($GLOBALS['db']->lastError()){
3699             logThis('An error occurred when performing this query-->'.$dropColumn);
3700         }
3701         $changeColumnName = "EXEC sp_rename '{$table_name}.[{$column_name}_temp]','{$column_name}','COLUMN'";
3702         $GLOBALS['db']->query($changeColumnName);
3703         if($GLOBALS['db']->lastError()){
3704             logThis('An error occurred when performing this query-->'.$changeColumnName);
3705         }
3706      }
3707     }
3708
3709          /**
3710      * clearHelpFiles
3711      * This method attempts to delete all English inline help files.
3712      * This method was introduced by 5.5.0RC2.
3713      */
3714     function clearHelpFiles(){
3715                 $modulePath = clean_path(getcwd() . '/modules');
3716                 $allHelpFiles = array();
3717                 getFiles($allHelpFiles, $modulePath, "/en_us.help.*/");
3718
3719                 foreach( $allHelpFiles as $the_file ){
3720                 if( is_file( $the_file ) ){
3721                     unlink( $the_file );
3722                     logThis("Deleted file: $the_file");
3723                 }
3724             }
3725         }
3726
3727
3728
3729         /**
3730          * upgradeDateTimeFields
3731          *
3732          * This method came from bug: 39757 where the date_end field is a date field and not a datetime field
3733          * which prevents you from performing timezone offset calculations once the data has been saved.
3734          *
3735          * @param path String location to log file, empty by default
3736          */
3737         function upgradeDateTimeFields($path)
3738         {
3739                 //bug: 39757
3740                 global $db;
3741                 $meetingsSql = "UPDATE meetings SET date_end = ".$db->convert("date_start", 'add_time', array('duration_hours', 'duration_minutes'));
3742                 $callsSql = "UPDATE calls SET date_end = ".$db->convert("date_start", 'add_time', array('duration_hours', 'duration_minutes'));
3743         logThis('upgradeDateTimeFields Meetings SQL:' . $meetingsSql, $path);
3744                 $db->query($meetingsSql);
3745
3746                 logThis('upgradeDateTimeFields Calls SQL:' . $callsSql, $path);
3747                 $db->query($callsSql);
3748         }
3749
3750         /**
3751          * upgradeDocumentTypeFields
3752          *
3753          */
3754         function upgradeDocumentTypeFields($path){
3755                 //bug: 39757
3756                 global $db;
3757
3758                 $documentsSql = "UPDATE documents SET doc_type = 'Sugar' WHERE doc_type IS NULL";
3759                 $meetingsSql = "UPDATE meetings SET type = 'Sugar' WHERE type IS NULL";
3760
3761                 logThis('upgradeDocumentTypeFields Documents SQL:' . $documentsSql, $path);
3762                 $db->query($documentsSql);
3763                 logThis('upgradeDocumentTypeFields Meetings SQL:' . $meetingsSql, $path);
3764                 $db->query($meetingsSql);
3765         }
3766
3767
3768 /**
3769  * merge_config_si_settings
3770  * This method checks for the presence of a config_si.php file and, if found, merges the configuration
3771  * settings from the config_si.php file into config.php.  If a config_si_location parameter value is not
3772  * supplied it will attempt to discover the config_si.php file location from where the executing script
3773  * was invoked.
3774  *
3775  * @param write_to_upgrade_log boolean optional value to write to the upgradeWizard.log file
3776  * @param config_location String optional value to config.php file location
3777  * @param config_si_location String optional value to config_si.php file location
3778  * @param path String file of the location of log file to write to
3779  * @return boolean value indicating whether or not a merge was attempted with config_si.php file
3780  */
3781 function merge_config_si_settings($write_to_upgrade_log=false, $config_location='', $config_si_location='', $path='')
3782 {
3783         if(!empty($config_location) && !file_exists($config_location))
3784         {
3785                 if($write_to_upgrade_log)
3786                 {
3787                logThis('config.php file specified in ' . $config_si_location . ' could not be found.  Skip merging', $path);
3788                 }
3789             return false;
3790         } else if(empty($config_location)) {
3791                 global $argv;
3792                 //We are assuming this is from the silentUpgrade scripts so argv[3] will point to SugarCRM install location
3793                 if(isset($argv[3]) && is_dir($argv[3]))
3794                 {
3795                         $config_location = $argv[3] . DIRECTORY_SEPARATOR . 'config.php';
3796                 }
3797         }
3798
3799         //If config_location is still empty or if the file cannot be found, skip merging
3800         if(empty($config_location) || !file_exists($config_location))
3801         {
3802            if($write_to_upgrade_log)
3803            {
3804                   logThis('config.php file at (' . $config_location . ') could not be found.  Skip merging.', $path);
3805            }
3806            return false;
3807         } else {
3808            if($write_to_upgrade_log)
3809            {
3810               logThis('Loading config.php file at (' . $config_location . ') for merging.', $path);
3811            }
3812
3813            include($config_location);
3814            if(empty($sugar_config))
3815            {
3816                   if($write_to_upgrade_log)
3817                   {
3818                      logThis('config.php contents are empty.  Skip merging.', $path);
3819                   }
3820                   return false;
3821            }
3822         }
3823
3824         if(!empty($config_si_location) && !file_exists($config_si_location))
3825         {
3826                 if($write_to_upgrade_log)
3827                 {
3828                logThis('config_si.php file specified in ' . $config_si_location . ' could not be found.  Skip merging', $path);
3829                 }
3830             return false;
3831         } else if(empty($config_si_location)) {
3832                 if(isset($argv[0]) && is_file($argv[0]))
3833                 {
3834                         $php_file = $argv[0];
3835                         $p_info = pathinfo($php_file);
3836                         $php_dir = (isset($p_info['dirname']) && $p_info['dirname'] != '.') ?  $p_info['dirname'] . DIRECTORY_SEPARATOR : '';
3837                         $config_si_location = $php_dir . 'config_si.php';
3838                 }
3839         }
3840
3841         //If config_si_location is still empty or if the file cannot be found, skip merging
3842         if(empty($config_si_location) || !file_exists($config_si_location))
3843         {
3844            if($write_to_upgrade_log)
3845            {
3846               logThis('config_si.php file at (' . $config_si_location . ') could not be found.  Skip merging.', $path);
3847            }
3848            return false;
3849         } else {
3850            if($write_to_upgrade_log)
3851            {
3852               logThis('Loading config_si.php file at (' . $config_si_location . ') for merging.', $path);
3853            }
3854
3855            include($config_si_location);
3856            if(empty($sugar_config_si))
3857            {
3858               if($write_to_upgrade_log)
3859                   {
3860                      logThis('config_si.php contents are empty.  Skip merging.', $path);
3861                   }
3862                   return false;
3863            }
3864         }
3865
3866         //Now perform the merge operation
3867         $modified = false;
3868         foreach($sugar_config_si as $key=>$value)
3869         {
3870                 if(!preg_match('/^setup_/', $key) && !isset($sugar_config[$key]))
3871                 {
3872                    if($write_to_upgrade_log)
3873                    {
3874                       logThis('Merge key (' . $key . ') with value (' . $value . ')', $path);
3875                    }
3876                    $sugar_config[$key] = $value;
3877                    $modified = true;
3878                 }
3879         }
3880
3881         if($modified)
3882         {
3883                 if($write_to_upgrade_log)
3884                 {
3885                logThis('Update config.php file with new values', $path);
3886                 }
3887
3888             if(!write_array_to_file("sugar_config", $sugar_config, $config_location)) {
3889                if($write_to_upgrade_log)
3890                    {
3891                   logThis('*** ERROR: could not write to config.php', $path);
3892                    }
3893                    return false;
3894                 }
3895         } else {
3896            if($write_to_upgrade_log)
3897            {
3898               logThis('config.php values are in sync with config_si.php values.  Skipped merging.');
3899            }
3900            return false;
3901         }
3902
3903         if($write_to_upgrade_log)
3904         {
3905            logThis('End merge_config_si_settings', $path);
3906         }
3907         return true;
3908 }
3909
3910
3911 /**
3912  * upgrade_connectors
3913  *
3914  * This function handles support for upgrading connectors it is invoked from both end.php and silentUpgrade_step2.php
3915  *
3916  */
3917 function upgrade_connectors() {
3918     require_once('include/connectors/utils/ConnectorUtils.php');
3919     if(!ConnectorUtils::updateMetaDataFiles()) {
3920        $GLOBALS['log']->fatal('Cannot update metadata files for connectors');
3921     }
3922
3923     //Delete the custom connectors.php file if it exists so that it may be properly rebuilt
3924     if(file_exists('custom/modules/Connectors/metadata/connectors.php'))
3925     {
3926         unlink('custom/modules/Connectors/metadata/connectors.php');
3927     }
3928 }
3929
3930 /**
3931  * Enable the InsideView connector for the four default modules.
3932  */
3933 function upgradeEnableInsideViewConnector($path='')
3934 {
3935     logThis('Begin upgradeEnableInsideViewConnector', $path);
3936
3937     // Load up the existing mapping and hand it to the InsideView connector to have it setup the correct logic hooks
3938     $mapFile = 'modules/Connectors/connectors/sources/ext/rest/insideview/mapping.php';
3939     if ( file_exists('custom/'.$mapFile) ) {
3940         logThis('Found CUSTOM mappings', $path);
3941         require('custom/'.$mapFile);
3942     } else {
3943         logThis('Used default mapping', $path);
3944         require($mapFile);
3945     }
3946
3947     require_once('include/connectors/sources/SourceFactory.php');
3948     $source = SourceFactory::getSource('ext_rest_insideview');
3949
3950     // $mapping is brought in from the mapping.php file above
3951     $source->saveMappingHook($mapping);
3952
3953     require_once('include/connectors/utils/ConnectorUtils.php');
3954     ConnectorUtils::installSource('ext_rest_insideview');
3955
3956     // Now time to set the various modules to active, because this part ignores the default config
3957     require(CONNECTOR_DISPLAY_CONFIG_FILE);
3958     // $modules_sources come from that config file
3959     foreach ( $source->allowedModuleList as $module ) {
3960         $modules_sources[$module]['ext_rest_insideview'] = 'ext_rest_insideview';
3961     }
3962     if(!write_array_to_file('modules_sources', $modules_sources, CONNECTOR_DISPLAY_CONFIG_FILE)) {
3963         //Log error and return empty array
3964         logThis("Cannot write \$modules_sources to " . CONNECTOR_DISPLAY_CONFIG_FILE,$path);
3965     }
3966
3967     logThis('End upgradeEnableInsideViewConnector', $path);
3968
3969 }
3970
3971 function repair_long_relationship_names($path='')
3972 {
3973     logThis("Begin repair_long_relationship_names", $path);
3974     require_once 'modules/ModuleBuilder/parsers/relationships/DeployedRelationships.php' ;
3975     $GLOBALS['mi_remove_tables'] = false;
3976     $touched = array();
3977     foreach($GLOBALS['moduleList'] as $module)
3978     {
3979         $relationships = new DeployedRelationships ($module) ;
3980         foreach($relationships->getRelationshipList() as $rel_name)
3981         {
3982             if (strlen($rel_name) > 27 && empty($touched[$rel_name]))
3983             {
3984                 logThis("Rebuilding relationship fields for $rel_name", $path);
3985                 $touched[$rel_name] = true;
3986                 $rel_obj = $relationships->get($rel_name);
3987                 $rel_obj->setReadonly(false);
3988                 $relationships->delete($rel_name);
3989                 $relationships->save();
3990                 $relationships->add($rel_obj);
3991                 $relationships->save();
3992                 $relationships->build () ;
3993             }
3994         }
3995     }
3996     logThis("End repair_long_relationship_names", $path);
3997 }
3998
3999 function removeSilentUpgradeVarsCache(){
4000     global $silent_upgrade_vars_loaded;
4001
4002     $cacheFileDir = "{$GLOBALS['sugar_config']['cache_dir']}/silentUpgrader";
4003     $cacheFile = "{$cacheFileDir}/silentUpgradeCache.php";
4004
4005     if(file_exists($cacheFile)){
4006         unlink($cacheFile);
4007     }
4008
4009     $silent_upgrade_vars_loaded = array(); // Set to empty to reset it
4010
4011     return true;
4012 }
4013
4014 function loadSilentUpgradeVars(){
4015     global $silent_upgrade_vars_loaded;
4016
4017     if(empty($silent_upgrade_vars_loaded)){
4018         $cacheFile = "{$GLOBALS['sugar_config']['cache_dir']}/silentUpgrader/silentUpgradeCache.php";
4019         // We have no pre existing vars
4020         if(!file_exists($cacheFile)){
4021             // Set the vars array so it's loaded
4022             $silent_upgrade_vars_loaded = array('vars' => array());
4023         }
4024         else{
4025             require_once($cacheFile);
4026             $silent_upgrade_vars_loaded = $silent_upgrade_vars_cache;
4027         }
4028     }
4029
4030     return true;
4031 }
4032
4033 function writeSilentUpgradeVars(){
4034     global $silent_upgrade_vars_loaded;
4035
4036     if(empty($silent_upgrade_vars_loaded)){
4037         return false; // You should have set some values before trying to write the silent upgrade vars
4038     }
4039
4040     $cacheFileDir = "{$GLOBALS['sugar_config']['cache_dir']}/silentUpgrader";
4041     $cacheFile = "{$cacheFileDir}/silentUpgradeCache.php";
4042
4043     require_once('include/dir_inc.php');
4044     if(!mkdir_recursive($cacheFileDir)){
4045         return false;
4046     }
4047     require_once('include/utils/file_utils.php');
4048     if(!write_array_to_file('silent_upgrade_vars_cache', $silent_upgrade_vars_loaded, $cacheFile, 'w')){
4049         global $path;
4050         logThis("WARNING: writeSilentUpgradeVars could not write to {$cacheFile}", $path);
4051         return false;
4052     }
4053
4054     return true;
4055 }
4056
4057 function setSilentUpgradeVar($var, $value){
4058     if(!loadSilentUpgradeVars()){
4059         return false;
4060     }
4061
4062     global $silent_upgrade_vars_loaded;
4063
4064     $silent_upgrade_vars_loaded['vars'][$var] = $value;
4065
4066     return true;
4067 }
4068
4069 function getSilentUpgradeVar($var){
4070     if(!loadSilentUpgradeVars()){
4071         return false;
4072     }
4073
4074     global $silent_upgrade_vars_loaded;
4075
4076     if(!isset($silent_upgrade_vars_loaded['vars'][$var])){
4077         return null;
4078     }
4079     else{
4080         return $silent_upgrade_vars_loaded['vars'][$var];
4081     }
4082 }
4083
4084
4085 /**
4086  * add_unified_search_to_custom_modules_vardefs
4087  *
4088  * This method calls the repair code to remove the unified_search_modules.php fiel
4089  *
4090  */
4091 function add_unified_search_to_custom_modules_vardefs()
4092 {
4093         if(file_exists($cachefile = sugar_cached('modules/unified_search_modules.php')))
4094         {
4095            unlink($cachefile);
4096         }
4097
4098 }
4099
4100 /**
4101  * change from using the older SugarCache in 6.1 and below to the new one in 6.2
4102  */
4103 function upgradeSugarCache($file)
4104 {
4105         global $sugar_config;
4106         $cacheUploadUpgradesTemp = mk_temp_dir(sugar_cached('upgrades/temp'));
4107
4108         unzip($file, $cacheUploadUpgradesTemp);
4109
4110         if(!file_exists(clean_path("{$cacheUploadUpgradesTemp}/manifest.php"))) {
4111                 logThis("*** ERROR: no manifest file detected while bootstraping upgrade wizard files!");
4112                 return;
4113         } else {
4114                 include(clean_path("{$cacheUploadUpgradesTemp}/manifest.php"));
4115         }
4116
4117         $from_dir = "{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}";
4118         $allFiles = array();
4119         if(file_exists("$from_dir/include/SugarCache")) {
4120                 $allFiles = findAllFiles("$from_dir/include/SugarCache", $allFiles);
4121         }
4122         if(file_exists("$from_dir/include/database")) {
4123                 $allFiles = findAllFiles("$from_dir/include/database", $allFiles);
4124         }
4125         if(file_exists("$from_dir/include/utils/external_cache.php")) {
4126                 $allFiles[] = "$from_dir/include/utils/external_cache.php";
4127         }
4128         if(file_exists("$from_dir/include/utils/sugar_file_utils.php")) {
4129                 $allFiles[] = "$from_dir/include/utils/sugar_file_utils.php";
4130         }
4131         if(file_exists("$from_dir/include/utils/sugar_file_utils.php")) {
4132                 $allFiles[] = "$from_dir/include/utils/sugar_file_utils.php";
4133         }
4134
4135         foreach($allFiles as $k => $file) {
4136                 $destFile = str_replace($from_dir."/", "", $file);
4137        if(!is_dir(dirname($destFile))) {
4138                         mkdir_recursive(dirname($destFile)); // make sure the directory exists
4139                 }
4140                 if ( stristr($file,'uw_main.tpl') )
4141             logThis('Skipping "'.$file.'" - file copy will during commit step.');
4142         else {
4143             logThis('updating UpgradeWizard code: '.$destFile);
4144             copy_recursive($file, $destFile);
4145         }
4146         }
4147 }
4148
4149
4150 /**
4151  * upgradeDisplayedTabsAndSubpanels
4152  *
4153  * @param $version String value of current system version (pre upgrade)
4154  */
4155 function upgradeDisplayedTabsAndSubpanels($version)
4156 {
4157         if($version < '620')
4158         {
4159                 logThis('start upgrading system displayed tabs and subpanels');
4160             require_once('modules/MySettings/TabController.php');
4161             $tc = new TabController();
4162
4163             //grab the existing system tabs
4164             $tabs = $tc->get_tabs_system();
4165
4166             //add Calls, Meetings, Tasks, Notes, Prospects (Targets) and ProspectLists (Target Lists)
4167             //to displayed tabs unless explicitly set to hidden
4168             $modules_to_add = array('Calls', 'Meetings', 'Tasks', 'Notes', 'Prospects', 'ProspectLists');
4169             $added_tabs = array();
4170
4171             foreach($modules_to_add as $module)
4172             {
4173                        $tabs[0][$module] = $module;
4174                        $added_tabs[] = $module;
4175             }
4176
4177             logThis('calling set_system_tabs on TabController to add tabs: ' . var_export($added_tabs, true));
4178             $tc->set_system_tabs($tabs[0]);
4179             logThis('finish upgrading system displayed tabs and subpanels');
4180         }
4181 }
4182
4183
4184 /**
4185  * unlinkUpgradeFiles
4186  * This is a helper function to clean up
4187  *
4188  * @param $version String value of current system version (pre upgrade)
4189  */
4190 function unlinkUpgradeFiles($version)
4191 {
4192         if(!isset($version))
4193         {
4194            return;
4195         }
4196
4197     //First check if we even have the scripts_for_patch/files_to_remove directory
4198     require_once('modules/UpgradeWizard/UpgradeRemoval.php');
4199
4200     /*
4201     if(empty($_SESSION['unzip_dir']))
4202     {
4203         global $sugar_config;
4204         $base_upgrade_dir               = $sugar_config['upload_dir'] . "/upgrades";
4205         $base_tmp_upgrade_dir   = "$base_upgrade_dir/temp";
4206         $_SESSION['unzip_dir'] = mk_temp_dir( $base_tmp_upgrade_dir );
4207     }
4208     */
4209
4210     if(isset($_SESSION['unzip_dir']) && file_exists($_SESSION['unzip_dir'].'/scripts/files_to_remove'))
4211     {
4212        $files_to_remove = glob($_SESSION['unzip_dir'].'/scripts/files_to_remove/*.php');
4213
4214        foreach($files_to_remove as $script)
4215        {
4216                 if(preg_match('/UpgradeRemoval(\d+)x\.php/', $script, $matches))
4217                 {
4218                    $checkVersion = $matches[1] + 1; //Increment by one to check everything equal or below the target version
4219                    $upgradeClass = 'UpgradeRemoval' . $matches[1] . 'x';
4220                    require_once($_SESSION['unzip_dir'].'/scripts/files_to_remove/' . $upgradeClass . '.php');
4221
4222                    //Check to make sure we should load and run this UpgradeRemoval instance
4223                    if($checkVersion <= $version && class_exists($upgradeClass))
4224                    {
4225                           $upgradeInstance = new $upgradeClass();
4226                           if($upgradeInstance instanceof UpgradeRemoval)
4227                           {
4228                                   logThis('Running UpgradeRemoval instance ' . $upgradeClass);
4229                                   logThis('Files will be backed up to custom/backup');
4230                                   $files = $upgradeInstance->getFilesToRemove($version);
4231                                   foreach($files as $file)
4232                                   {
4233                                          logThis($file);
4234                                   }
4235                                   $upgradeInstance->processFilesToRemove($files);
4236                           }
4237                    }
4238             }
4239        }
4240     }
4241
4242     //Check if we have a custom directory
4243     if(file_exists('custom/scripts/files_to_remove'))
4244     {
4245        //Now find
4246        $files_to_remove = glob('custom/scripts/files_to_remove/*.php');
4247
4248        foreach($files_to_remove as $script)
4249        {
4250            if(preg_match('/\/files_to_remove\/(.*?)\.php$/', $script, $matches))
4251            {
4252                    require_once($script);
4253                    $upgradeClass  = $matches[1];
4254
4255                    if(!class_exists($upgradeClass))
4256                    {
4257                           continue;
4258                    }
4259
4260                    $upgradeInstance = new $upgradeClass();
4261                    if($upgradeInstance instanceof UpgradeRemoval)
4262                    {
4263                                   logThis('Running Custom UpgradeRemoval instance ' . $upgradeClass);
4264                                   $files = $upgradeInstance->getFilesToRemove($version);
4265                                   foreach($files as $file)
4266                                   {
4267                                          logThis($file);
4268                                   }
4269                                   $upgradeInstance->processFilesToRemove($files);
4270                    }
4271            }
4272        }
4273     }
4274
4275 }
4276
4277 if (!function_exists("getValidDBName"))
4278 {
4279     /*
4280      * Return a version of $proposed that can be used as a column name in any of our supported databases
4281      * 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)
4282      * @param string $name Proposed name for the column
4283      * @param string $ensureUnique
4284      * @return string Valid column name trimmed to right length and with invalid characters removed
4285      */
4286      function getValidDBName ($name, $ensureUnique = false, $maxLen = 30)
4287     {
4288         // first strip any invalid characters - all but alphanumerics and -
4289         $name = preg_replace ( '/[^\w-]+/i', '', $name ) ;
4290         $len = strlen ( $name ) ;
4291         $result = $name;
4292         if ($ensureUnique)
4293         {
4294             $md5str = md5($name);
4295             $tail = substr ( $name, -11) ;
4296             $temp = substr($md5str , strlen($md5str)-4 );
4297             $result = substr ( $name, 0, 10) . $temp . $tail ;
4298         }else if ($len > ($maxLen - 5))
4299         {
4300             $result = substr ( $name, 0, 11) . substr ( $name, 11 - $maxLen + 5);
4301         }
4302         return strtolower ( $result ) ;
4303     }
4304
4305
4306 }
4307
4308 /**
4309  * Get UW directories
4310  * Provides compatibility with both 6.3 and pre-6.3 setup
4311  */
4312 function getUWDirs()
4313 {
4314     if(!class_exists('UploadStream')) {
4315         // we're still running the old code
4316         global $sugar_config;
4317         return array($sugar_config['upload_dir'] . "/upgrades", $sugar_config['cache_dir'] . "upload/upgrades/temp");
4318     } else {
4319         if(!in_array("upload", stream_get_wrappers())) {
4320             UploadStream::register(); // just in case file was copied, but not run
4321         }
4322         return array("upload://upgrades", sugar_cached("upgrades/temp"));
4323     }
4324 }
4325
4326 /**
4327  * Whether directory exists within list of directories to skip
4328  * @param string $dir dir to be checked
4329  * @param array $skipDirs list with skipped dirs
4330  * @return boolean
4331  */
4332 function whetherNeedToSkipDir($dir, $skipDirs)
4333 {
4334     foreach($skipDirs as $skipMe) {
4335                 if(strpos( clean_path($dir), $skipMe ) !== false) {
4336                         return true;
4337                 }
4338         }
4339     return false;
4340 }
4341
4342
4343 /*
4344  * rebuildSprites
4345  * @param silentUpgrade boolean flag indicating whether or not we should treat running the SugarSpriteBuilder as an upgrade operation
4346  *
4347  */
4348 function rebuildSprites($fromUpgrade=true)
4349 {
4350     require_once('modules/Administration/SugarSpriteBuilder.php');
4351     $sb = new SugarSpriteBuilder();
4352     $sb->cssMinify = true;
4353     $sb->fromSilentUpgrade = $fromUpgrade;
4354     $sb->silentRun = $fromUpgrade;
4355
4356     // add common image directories
4357     $sb->addDirectory('default', 'include/images');
4358     $sb->addDirectory('default', 'themes/default/images');
4359     $sb->addDirectory('default', 'themes/default/images/SugarLogic');
4360
4361     // add all theme image directories
4362     if($dh = opendir('themes'))
4363     {
4364         while (($dir = readdir($dh)) !== false)
4365         {
4366             if ($dir != "." && $dir != ".." && $dir != 'default' && is_dir('themes/'.$dir)) {
4367                 $sb->addDirectory($dir, "themes/{$dir}/images");
4368             }
4369         }
4370         closedir($dh);
4371     }
4372
4373      // add all theme custom image directories
4374     $custom_themes_dir = "custom/themes";
4375     if (is_dir($custom_themes_dir)) {
4376          if($dh = opendir($custom_themes_dir))
4377          {
4378              while (($dir = readdir($dh)) !== false)
4379              {
4380                  //Since the custom theme directories don't require an images directory
4381                  // we check for it implicitly
4382                  if ($dir != "." && $dir != ".." && is_dir('custom/themes/'.$dir."/images")) {
4383                      $sb->addDirectory($dir, "custom/themes/{$dir}/images");
4384                  }
4385              }
4386              closedir($dh);
4387          }
4388     }
4389
4390     // generate the sprite goodies
4391     // everything is saved into cache/sprites
4392     $sb->createSprites();
4393 }
4394
4395
4396 /**
4397  * repairSearchFields
4398  *
4399  * This method goes through the list of SearchFields files based and calls TemplateRange::repairCustomSearchFields
4400  * method on the files in an attempt to ensure the range search attributes are properly set in SearchFields.php.
4401  *
4402  * @param $globString String value used for glob search defaults to searching for all SearchFields.php files in modules directory
4403  * @param $path String value used to point to log file should logging be required.  Defaults to empty.
4404  *
4405  */
4406 function repairSearchFields($globString='modules/*/metadata/SearchFields.php', $path='')
4407 {
4408         if(!empty($path))
4409         {
4410                 logThis('Begin repairSearchFields', $path);
4411         }
4412
4413         require_once('include/dir_inc.php');
4414         require_once('modules/DynamicFields/templates/Fields/TemplateRange.php');
4415         require('include/modules.php');
4416
4417         global $beanList;
4418         $searchFieldsFiles = glob($globString);
4419
4420         foreach($searchFieldsFiles as $file)
4421         {
4422                 if(preg_match('/modules\/(.*?)\/metadata\/SearchFields\.php/', $file, $matches) && isset($beanList[$matches[1]]))
4423                 {
4424                         $module = $matches[1];
4425                         $beanName = $beanList[$module];
4426                         VardefManager::loadVardef($module, $beanName);
4427                         if(isset($GLOBALS['dictionary'][$beanName]['fields']))
4428                         {
4429                                 if(!empty($path))
4430                                 {
4431                                         logThis('Calling TemplateRange::repairCustomSearchFields for module ' . $module, $path);
4432                                 }
4433                                 TemplateRange::repairCustomSearchFields($GLOBALS['dictionary'][$beanName]['fields'], $module);
4434                         }
4435                 }
4436         }
4437
4438         if(!empty($path))
4439         {
4440                 logThis('End repairSearchFields', $path);
4441         }
4442 }
4443
4444 /**
4445  * repairUpgradeHistoryTable
4446  *
4447  * This is a helper function used in the upgrade process to fix upgrade_history entries so that the filename column points
4448  * to the new upload directory location introduced in 6.4 versions
4449  */
4450 function repairUpgradeHistoryTable()
4451 {
4452     require_once('modules/Configurator/Configurator.php');
4453     new Configurator();
4454     global $sugar_config;
4455
4456     //Now upgrade the upgrade_history table entries
4457     $results = $GLOBALS['db']->query('SELECT id, filename FROM upgrade_history');
4458     $upload_dir = $sugar_config['cache_dir'].'upload/';
4459
4460     //Create regular expression string to
4461     $match = '/^' . str_replace('/', '\/', $upload_dir) . '(.*?)$/';
4462
4463     while(($row = $GLOBALS['db']->fetchByAssoc($results)))
4464     {
4465         $file = str_replace('//', '/', $row['filename']); //Strip out double-paths that may exist
4466
4467         if(!empty($file) && preg_match($match, $file, $matches))
4468         {
4469             //Update new file location to use the new $sugar_config['upload_dir'] value
4470             $new_file_location = $sugar_config['upload_dir'] . $matches[1];
4471             $GLOBALS['db']->query("UPDATE upgrade_history SET filename = '{$new_file_location}' WHERE id = '{$row['id']}'");
4472         }
4473     }
4474
4475 }