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