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