]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - modules/UpgradeWizard/uw_utils.php
Release 6.4.4
[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 $subdirs;
1798         global $base_upgrade_dir;
1799         global $base_tmp_upgrade_dir;
1800     list($p_base_upgrade_dir, $p_base_tmp_upgrade_dir) = getUWDirs();
1801         ///////////////////////////////////////////////////////////////////////////////
1802         ////    Make sure variables exist
1803         if(empty($base_upgrade_dir)){
1804                 $base_upgrade_dir       = $p_base_upgrade_dir;
1805         }
1806         if(empty($base_tmp_upgrade_dir)){
1807                 $base_tmp_upgrade_dir   = $p_base_tmp_upgrade_dir;
1808         }
1809         sugar_mkdir($base_tmp_upgrade_dir, 0775, true);
1810         if(!isset($subdirs) || empty($subdirs)){
1811                 $subdirs = array('full', 'langpack', 'module', 'patch', 'theme');
1812         }
1813
1814     $upgrade_progress_dir = $base_tmp_upgrade_dir;
1815     $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
1816     if(file_exists($upgrade_progress_file)){
1817         if(function_exists('get_upgrade_progress') && function_exists('didThisStepRunBefore')){
1818                 if(didThisStepRunBefore('end')){
1819                         include($upgrade_progress_file);
1820                         unset($upgrade_config);
1821                         unlink($upgrade_progress_file);
1822                 }
1823         }
1824     }
1825
1826     // increase the cuttoff time to 1 hour
1827         ini_set("max_execution_time", "3600");
1828
1829     // make sure dirs exist
1830         if($subdirs != null){
1831                 foreach($subdirs as $subdir) {
1832                     sugar_mkdir("$base_upgrade_dir/$subdir", 0775, true);
1833                 }
1834         }
1835         // array of special scripts that are executed during (un)installation-- key is type of script, value is filename
1836         if(!defined('SUGARCRM_PRE_INSTALL_FILE')) {
1837                 define('SUGARCRM_PRE_INSTALL_FILE', 'scripts/pre_install.php');
1838                 define('SUGARCRM_POST_INSTALL_FILE', 'scripts/post_install.php');
1839                 define('SUGARCRM_PRE_UNINSTALL_FILE', 'scripts/pre_uninstall.php');
1840                 define('SUGARCRM_POST_UNINSTALL_FILE', 'scripts/post_uninstall.php');
1841         }
1842
1843         $script_files = array(
1844                 "pre-install" => constant('SUGARCRM_PRE_INSTALL_FILE'),
1845                 "post-install" => constant('SUGARCRM_POST_INSTALL_FILE'),
1846                 "pre-uninstall" => constant('SUGARCRM_PRE_UNINSTALL_FILE'),
1847                 "post-uninstall" => constant('SUGARCRM_POST_UNINSTALL_FILE'),
1848         );
1849
1850         // check that the upload limit is set to 6M or greater
1851         define('SUGARCRM_MIN_UPLOAD_MAX_FILESIZE_BYTES', 6 * 1024 * 1024);  // 6 Megabytes
1852         $upload_max_filesize = ini_get('upload_max_filesize');
1853         $upload_max_filesize_bytes = return_bytes($upload_max_filesize);
1854
1855         if($upload_max_filesize_bytes < constant('SUGARCRM_MIN_UPLOAD_MAX_FILESIZE_BYTES')) {
1856                 $GLOBALS['log']->debug("detected upload_max_filesize: $upload_max_filesize");
1857
1858                 echo '<p class="error">'.$mod_strings['MSG_INCREASE_UPLOAD_MAX_FILESIZE'].' '.get_cfg_var('cfg_file_path')."</p>\n";
1859         }
1860 }
1861
1862 if ( !function_exists('extractFile') ) {
1863 function extractFile($zip_file, $file_in_zip) {
1864     global $base_tmp_upgrade_dir;
1865
1866         // strip cwd
1867         $absolute_base_tmp_upgrade_dir = clean_path($base_tmp_upgrade_dir);
1868         $relative_base_tmp_upgrade_dir = clean_path(str_replace(clean_path(getcwd()), '', $absolute_base_tmp_upgrade_dir));
1869
1870     // mk_temp_dir expects relative pathing
1871     $my_zip_dir = mk_temp_dir($relative_base_tmp_upgrade_dir);
1872
1873     unzip_file($zip_file, $file_in_zip, $my_zip_dir);
1874
1875     return("$my_zip_dir/$file_in_zip");
1876 }
1877 }
1878
1879 if ( !function_exists('extractManifest') ) {
1880 function extractManifest($zip_file) {
1881         logThis('extracting manifest.');
1882     return(extractFile($zip_file, "manifest.php"));
1883 }
1884 }
1885
1886 if ( !function_exists('getInstallType') ) {
1887 function getInstallType($type_string) {
1888     // detect file type
1889     global $subdirs;
1890         $subdirs = array('full', 'langpack', 'module', 'patch', 'theme', 'temp');
1891     foreach($subdirs as $subdir) {
1892         if(preg_match("#/$subdir/#", $type_string)) {
1893             return($subdir);
1894         }
1895     }
1896     // return empty if no match
1897     return("");
1898 }
1899 }
1900
1901 function getImageForType($type) {
1902     global $image_path;
1903     global $mod_strings;
1904
1905     $icon = "";
1906     switch($type) {
1907         case "full":
1908             $icon = SugarThemeRegistry::current()->getImage("Upgrade", "",null,null,'.gif',$mod_strings['LBL_UPGRADE']);
1909             break;
1910         case "langpack":
1911             $icon = SugarThemeRegistry::current()->getImage("LanguagePacks", "",null,null,'.gif',$mod_strings['LBL_LANGPACKS']);
1912             break;
1913         case "module":
1914             $icon = SugarThemeRegistry::current()->getImage("ModuleLoader", "",null,null,'.gif',$mod_strings['LBL_MODULELOADER']);
1915             break;
1916         case "patch":
1917             $icon = SugarThemeRegistry::current()->getImage("PatchUpgrades", "",null,null,'.gif',$mod_strings['LBL_PATCHUPGRADES']);
1918             break;
1919         case "theme":
1920             $icon = SugarThemeRegistry::current()->getImage("Themes", "",null,null,'.gif',$mod_strings['LBL_THEMES']);
1921             break;
1922         default:
1923             break;
1924     }
1925     return($icon);
1926 }
1927
1928 if ( !function_exists('getLanguagePackName') ) {
1929 function getLanguagePackName($the_file) {
1930     require_once("$the_file");
1931     if(isset($app_list_strings["language_pack_name"])) {
1932         return($app_list_strings["language_pack_name"]);
1933     }
1934     return("");
1935 }
1936 }
1937
1938 function getUITextForType($type) {
1939     if($type == "full") {
1940         return("Full Upgrade");
1941     }
1942     if($type == "langpack") {
1943         return("Language Pack");
1944     }
1945     if($type == "module") {
1946         return("Module");
1947     }
1948     if($type == "patch") {
1949         return("Patch");
1950     }
1951     if($type == "theme") {
1952         return("Theme");
1953     }
1954 }
1955
1956 if ( !function_exists('validate_manifest') ) {
1957 /**
1958  * Verifies a manifest from a patch or module to be compatible with the current Sugar version and flavor
1959  * @param array manifest Standard manifest array
1960  * @return string Error message, blank on success
1961  */
1962 function validate_manifest($manifest) {
1963         logThis('validating manifest.php file');
1964     // takes a manifest.php manifest array and validates contents
1965     global $subdirs;
1966     global $sugar_version;
1967     global $sugar_flavor;
1968         global $mod_strings;
1969
1970     if(!isset($manifest['type'])) {
1971         return $mod_strings['ERROR_MANIFEST_TYPE'];
1972     }
1973
1974     $type = $manifest['type'];
1975
1976     if(getInstallType("/$type/") == "") {
1977                 return $mod_strings['ERROR_PACKAGE_TYPE']. ": '" . $type . "'.";
1978     }
1979
1980     if(isset($manifest['acceptable_sugar_versions'])) {
1981         $version_ok = false;
1982         $matches_empty = true;
1983         if(isset($manifest['acceptable_sugar_versions']['exact_matches'])) {
1984             $matches_empty = false;
1985             foreach($manifest['acceptable_sugar_versions']['exact_matches'] as $match) {
1986                 if($match == $sugar_version) {
1987                     $version_ok = true;
1988                 }
1989             }
1990         }
1991         if(!$version_ok && isset($manifest['acceptable_sugar_versions']['regex_matches'])) {
1992             $matches_empty = false;
1993             foreach($manifest['acceptable_sugar_versions']['regex_matches'] as $match) {
1994                 if(preg_match("/$match/", $sugar_version)) {
1995                     $version_ok = true;
1996                 }
1997             }
1998         }
1999
2000         if(!$matches_empty && !$version_ok) {
2001             return $mod_strings['ERROR_VERSION_INCOMPATIBLE']."<br />".
2002             $mod_strings['ERR_UW_VERSION'].$sugar_version;
2003         }
2004     }
2005
2006     if(isset($manifest['acceptable_sugar_flavors']) && sizeof($manifest['acceptable_sugar_flavors']) > 0) {
2007         $flavor_ok = false;
2008         foreach($manifest['acceptable_sugar_flavors'] as $match) {
2009             if($match == $sugar_flavor) {
2010                 $flavor_ok = true;
2011             }
2012         }
2013         if(!$flavor_ok) {
2014             return $mod_strings['ERROR_FLAVOR_INCOMPATIBLE']."<br />".
2015             $mod_strings['ERR_UW_FLAVOR'].$sugar_flavor."<br />".
2016             $mod_strings['ERR_UW_FLAVOR_2'].$manifest['acceptable_sugar_flavors'][0];
2017         }
2018     }
2019
2020     return '';
2021 }
2022 }
2023
2024 function unlinkUploadFiles() {
2025         return;
2026 //      logThis('at unlinkUploadFiles()');
2027 //
2028 //      if(isset($_SESSION['install_file']) && !empty($_SESSION['install_file'])) {
2029 //              $upload = $_SESSION['install_file'];
2030 //
2031 //              if(is_file($upload)) {
2032 //                      logThis('unlinking ['.$upload.']');
2033 //                      @unlink($upload);
2034 //              }
2035 //      }
2036 }
2037
2038 /**
2039  * deletes files created by unzipping a package
2040  */
2041 function unlinkUWTempFiles() {
2042         global $sugar_config;
2043         global $path;
2044
2045         logThis('at unlinkUWTempFiles()');
2046         $tempDir='';
2047         list($upgDir, $tempDir) = getUWDirs();
2048
2049     if(file_exists($tempDir) && is_dir($tempDir)){
2050                 $files = findAllFiles($tempDir, array(), false);
2051                 rsort($files);
2052                 foreach($files as $file) {
2053                         if(!is_dir($file)) {
2054                                 //logThis('unlinking ['.$file.']', $path);
2055                                 @unlink($file);
2056                         }
2057                 }
2058                 // now do dirs
2059                 $files = findAllFiles($tempDir, array(), true);
2060                 foreach($files as $dir) {
2061                         if(is_dir($dir)) {
2062                                 //logThis('removing dir ['.$dir.']', $path);
2063                                 @rmdir($dir);
2064                         }
2065                 }
2066                 $cacheFile = sugar_cached("modules/UpgradeWizard/_persistence.php");
2067                 if(is_file($cacheFile)) {
2068                         logThis("Unlinking Upgrade cache file: '_persistence.php'", $path);
2069                         @unlink($cacheFile);
2070                 }
2071         }
2072         logThis("finished!");
2073 }
2074
2075 /**
2076  * finds all files in the passed path, but skips select directories
2077  * @param string dir Relative path
2078  * @param array the_array Collections of found files/dirs
2079  * @param bool include_dir True if we want to include directories in the
2080  * returned collection
2081  */
2082 function uwFindAllFiles($dir, $theArray, $includeDirs=false, $skipDirs=array(), $echo=false) {
2083         // check skips
2084     if (whetherNeedToSkipDir($dir, $skipDirs))
2085         {
2086             return $theArray;
2087         }
2088
2089     if (!is_dir($dir)) { return $theArray; }   // Bug # 46035, just checking for valid dir
2090         $d = dir($dir);
2091     if ($d === false)  { return $theArray; }   // Bug # 46035, more checking
2092
2093         while($f = $d->read()) {
2094                                         // bug 40793 Skip Directories array in upgradeWizard does not function correctly
2095             if($f == "." || $f == ".." || whetherNeedToSkipDir("$dir/$f", $skipDirs)) { // skip *nix self/parent
2096                 continue;
2097             }
2098
2099                 // for AJAX length count
2100         if($echo) {
2101                 echo '.';
2102                 ob_flush();
2103         }
2104
2105             if(is_dir("$dir/$f")) {
2106                         if($includeDirs) { // add the directory if flagged
2107                                 $theArray[] = clean_path("$dir/$f");
2108                         }
2109
2110                         // recurse in
2111                 $theArray = uwFindAllFiles("$dir/$f/", $theArray, $includeDirs, $skipDirs, $echo);
2112             } else {
2113                 $theArray[] = clean_path("$dir/$f");
2114             }
2115
2116
2117         }
2118         rsort($theArray);
2119         $d->close();
2120         return $theArray;
2121 }
2122
2123
2124
2125 /**
2126  * unset's UW's Session Vars
2127  */
2128 function resetUwSession() {
2129         logThis('resetting $_SESSION');
2130
2131         if(isset($_SESSION['committed']))
2132                 unset($_SESSION['committed']);
2133         if(isset($_SESSION['sugar_version_file']))
2134                 unset($_SESSION['sugar_version_file']);
2135         if(isset($_SESSION['upgrade_complete']))
2136                 unset($_SESSION['upgrade_complete']);
2137         if(isset($_SESSION['allTables']))
2138                 unset($_SESSION['allTables']);
2139         if(isset($_SESSION['alterCustomTableQueries']))
2140                 unset($_SESSION['alterCustomTableQueries']);
2141         if(isset($_SESSION['skip_zip_upload']))
2142                 unset($_SESSION['skip_zip_upload']);
2143         if(isset($_SESSION['sugar_version_file']))
2144                 unset($_SESSION['sugar_version_file']);
2145         if(isset($_SESSION['install_file']))
2146                 unset($_SESSION['install_file']);
2147         if(isset($_SESSION['unzip_dir']))
2148                 unset($_SESSION['unzip_dir']);
2149         if(isset($_SESSION['zip_from_dir']))
2150                 unset($_SESSION['zip_from_dir']);
2151         if(isset($_SESSION['overwrite_files']))
2152                 unset($_SESSION['overwrite_files']);
2153         if(isset($_SESSION['schema_change']))
2154                 unset($_SESSION['schema_change']);
2155         if(isset($_SESSION['uw_restore_dir']))
2156                 unset($_SESSION['uw_restore_dir']);
2157         if(isset($_SESSION['step']))
2158                 unset($_SESSION['step']);
2159         if(isset($_SESSION['files']))
2160                 unset($_SESSION['files']);
2161         if(isset($_SESSION['Upgraded451Wizard'])){
2162                 unset($_SESSION['Upgraded451Wizard']);
2163         }
2164         if(isset($_SESSION['Initial_451to500_Step'])){
2165                 unset($_SESSION['Initial_451to500_Step']);
2166         }
2167         if(isset($_SESSION['license_shown']))
2168                 unset($_SESSION['license_shown']);
2169     if(isset($_SESSION['sugarMergeRunResults']))
2170                 unset($_SESSION['sugarMergeRunResults']);
2171 }
2172
2173 /**
2174  * runs rebuild scripts
2175  */
2176 function UWrebuild() {
2177         global $db;
2178         global $path;
2179         /*
2180         //CCL - Comment this block out, it is called in end.php
2181         logThis('Rebuilding everything...', $path);
2182         require_once('modules/Administration/QuickRepairAndRebuild.php');
2183         $randc = new RepairAndClear();
2184     $randc->repairAndClearAll(array('clearAll'),array(translate('LBL_ALL_MODULES')), false, false);
2185     */
2186         $query = "DELETE FROM versions WHERE name='Rebuild Extensions'";
2187         $db->query($query);
2188         logThis('Registering rebuild record: '.$query, $path);
2189         logThis('Rebuild done.', $path);
2190
2191         // insert a new database row to show the rebuild extensions is done
2192         $id = create_guid();
2193         $gmdate = gmdate('Y-m-d H:i:s');
2194         $date_entered = db_convert("'$gmdate'", 'datetime');
2195         $query = 'INSERT INTO versions (id, deleted, date_entered, date_modified, modified_user_id, created_by, name, file_version, db_version) '
2196                 . "VALUES ('$id', '0', $date_entered, $date_entered, '1', '1', 'Rebuild Extensions', '4.0.0', '4.0.0')";
2197         $db->query($query);
2198         logThis('Registering rebuild record in versions table: '.$query, $path);
2199 }
2200
2201 function getCustomTables() {
2202         global $db;
2203
2204     return $db->tablesLike('%_cstm');
2205 }
2206
2207 function alterCustomTables($customTables)
2208 {
2209         return array();
2210 }
2211
2212 function getAllTables() {
2213         global $db;
2214     return $db->getTablesArray();
2215 }
2216
2217 function printAlterTableSql($tables)
2218 {
2219         $alterTableSql = '';
2220
2221         foreach($tables as $table)
2222                 $alterTableSql .= "ALTER TABLE " . $table . " CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;" . "\n";
2223
2224         return $alterTableSql;
2225 }
2226
2227 function executeConvertTablesSql($tables)
2228 {
2229         global $db;
2230
2231         foreach($tables as $table){
2232                 $query = "ALTER TABLE " . $table . " CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci";
2233                 if(!empty($table)){
2234                         logThis("Sending query: ".$query);
2235             $db->query($query);//, true, "An error has occured while performing db query.  See log file for details.<br>");
2236          }
2237         }
2238         return true;
2239 }
2240
2241 function testThis() {
2242         $files = uwFindAllFiles(getcwd().'/test', array());
2243
2244         $out = "<table cellpadding='1' cellspacing='0' border='0'>\n";
2245
2246         $priorPath = '';
2247         foreach($files as $file) {
2248                 $relativeFile = clean_path(str_replace(getcwd().'/test', '', $file));
2249                 $relativeFile = ($relativeFile{0} == '/') ? substr($relativeFile, 1, strlen($relativeFile)) : $relativeFile;
2250
2251                 $relativePath = dirname($relativeFile);
2252
2253                 if($relativePath == $priorPath) { // same dir, new file
2254                         $out .= "<tr><td>".basename($relativeFile)."</td></tr>";
2255                         $priorPath = $relativePath;
2256                 } else { // new dir
2257
2258                 }
2259         }
2260
2261         $out .= "</table>";
2262
2263         echo $out;
2264 }
2265
2266
2267
2268
2269 function testThis2($dir, $id=0, $hide=false) {
2270     global $mod_strings;
2271         $path = $dir;
2272         $dh = opendir($dir);
2273         rewinddir($dh);
2274
2275         $doHide = ($hide) ? 'none' : '';
2276         $out = "<div id='{$id}' style='display:{$doHide};'>";
2277         $out .= "<table cellpadding='1' cellspacing='0' style='border:0px solid #ccc'>\n";
2278
2279         while($file = readdir($dh)) {
2280                 if($file == '.' || $file == '..' || $file == 'CVS' || $file == '.cvsignore')
2281                         continue;
2282
2283                 if(is_dir($path.'/'.$file)) {
2284                         $file = $path.'/'.$file;
2285                         $newI = create_guid();
2286                         $out .= "<tr><td valign='top'><a href='javascript:toggleNwFiles(\"{$newI}\");'>".SugarThemeRegistry::current()->getImage("Workflow", "", null, null, ".gif", $mod_strings['LBL_WORKFLOW'])."</a></td>\n";
2287                         $out .= "<td valign='top'><b><a href='javascript:toggleNwFiles(\"{$newI}\");'>".basename($file)."</a></b></td></tr>";
2288                         $out .= "<tr><td></td><td valign='top'>".testThis2($file, $newI, true)."</td></tr>";
2289                 } else {
2290                         $out .= "<tr><td valign='top'>&nbsp;</td>\n";
2291                         $out .= "<td valign='top'>".basename($file)."</td></tr>";
2292                 }
2293         }
2294
2295         $out .= "</tr></table>";
2296         $out .= "</div>";
2297
2298         closedir($dh);
2299         return $out;
2300 }
2301
2302
2303
2304
2305
2306 function testThis3(&$files, $id, $hide, $previousPath = '') {
2307         if(!is_array($files) || empty($files))
2308                 return '';
2309
2310         $out = '';
2311
2312     global $mod_strings;
2313         // expecting full path here
2314         foreach($files as $k => $file) {
2315                 $file = str_replace(getcwd(), '', $file);
2316                 $path = dirname($file);
2317                 $fileName = basename($file);
2318
2319                 if($fileName == 'CVS' || $fileName == '.cvsignore')
2320                         continue;
2321
2322                 if($path == $previousPath) { // same directory
2323                         // new row for each file
2324                         $out .= "<tr><td valign='top' align='left'>&nbsp;</td>";
2325                         $out .= "<td valign='top' align='left'>{$fileName}</td></tr>";
2326                 } else { // new directory
2327                         $newI = $k;
2328                         $out .= "<tr><td valign='top'><a href='javascript:toggleNwFiles(\"{$newI}\");'>".SugarThemeRegistry::current()->getImage("Workflow", "", null, null, ".gif", $mod_strings['LBL_WORKFLOW'])."</a></td>\n";
2329                         $out .= "<td valign='top'><b><a href='javascript:toggleNwFiles(\"{$newI}\");'>".$fileName."</a></b></td></tr>";
2330                         $recurse = testThis3($files, $newI, true, $previousPath);
2331                         $out .= "<tr><td></td><td valign='top'>".$recurse."</td></tr>";
2332                 }
2333
2334                 $previousPath = $path;
2335         }
2336         $display = ($hide) ? 'none' : '';
2337         $ret = <<<eoq
2338         <div id="{$id}" style="display:{$display}">
2339         <table cellpadding='1' cellspacing='0' border='0' style='border:1px solid #ccc'>
2340                 {$out}
2341         </table>
2342         </div>
2343 eoq;
2344         return $ret;
2345 }
2346
2347
2348 function testThis4($filePath, $fileNodes=array(), $fileName='') {
2349         $path = dirname($filePath);
2350         $file = basename($filePath);
2351
2352         $exFile = explode('/', $path);
2353
2354         foreach($exFile as $pathSegment) {
2355                 if(is_array($fileNodes[$pathSegment])) { // path already processed
2356
2357                 } else { // newly found path
2358                         $fileNodes[$pathSegment] = array();
2359                 }
2360
2361                 if($fileName != '') {
2362                         $fileNodes[$pathSegment][] = $fileName;
2363                 }
2364         }
2365
2366         return $fileNodes;
2367 }
2368
2369
2370
2371 ///////////////////////////////////////////////////////////////////////////////
2372 ////    SYSTEM CHECK FUNCTIONS
2373 /**
2374  * generates an array with all files in the SugarCRM root directory, skipping
2375  * cache/
2376  * @return array files Array of files with absolute paths
2377  */
2378 function getFilesForPermsCheck() {
2379         global $sugar_config;
2380
2381         logThis('Got JSON call to find all files...');
2382         $filesNotWritable = array();
2383         $filesNWPerms = array();
2384
2385         // add directories here that should be skipped when doing file permissions checks (cache/upload is the nasty one)
2386         $skipDirs = array(
2387                 $sugar_config['upload_dir'],
2388         );
2389         $files = uwFindAllFiles(".", array(), true, $skipDirs, true);
2390         return $files;
2391 }
2392
2393 /**
2394  * checks files for permissions
2395  * @param array files Array of files with absolute paths
2396  * @return string result of check
2397  */
2398 function checkFiles($files, $echo=false) {
2399         global $mod_strings;
2400         $filesNotWritable = array();
2401         $i=0;
2402         $filesOut = "
2403                 <a href='javascript:void(0); toggleNwFiles(\"filesNw\");'>{$mod_strings['LBL_UW_SHOW_NW_FILES']}</a>
2404                 <div id='filesNw' style='display:none;'>
2405                 <table cellpadding='3' cellspacing='0' border='0'>
2406                 <tr>
2407                         <th align='left'>{$mod_strings['LBL_UW_FILE']}</th>
2408                         <th align='left'>{$mod_strings['LBL_UW_FILE_PERMS']}</th>
2409                         <th align='left'>{$mod_strings['LBL_UW_FILE_OWNER']}</th>
2410                         <th align='left'>{$mod_strings['LBL_UW_FILE_GROUP']}</th>
2411                 </tr>";
2412
2413         $isWindows = is_windows();
2414         foreach($files as $file) {
2415
2416                 if($isWindows) {
2417                         if(!is_writable_windows($file)) {
2418                                 logThis('WINDOWS: File ['.$file.'] not readable - saving for display');
2419                                 // don't warn yet - we're going to use this to check against replacement files
2420         // aw: commented out; it's a hack to allow upgrade wizard to continue on windows... will fix later
2421                                 /*$filesNotWritable[$i] = $file;
2422                                 $filesNWPerms[$i] = substr(sprintf('%o',fileperms($file)), -4);
2423                                 $filesOut .= "<tr>".
2424                                                                 "<td><span class='error'>{$file}</span></td>".
2425                                                                 "<td>{$filesNWPerms[$i]}</td>".
2426                                                                 "<td>".$mod_strings['ERR_UW_CANNOT_DETERMINE_USER']."</td>".
2427                                                                 "<td>".$mod_strings['ERR_UW_CANNOT_DETERMINE_GROUP']."</td>".
2428                                                           "</tr>";*/
2429                         }
2430                 } else {
2431                         if(!is_writable($file)) {
2432                                 logThis('File ['.$file.'] not writable - saving for display');
2433                                 // don't warn yet - we're going to use this to check against replacement files
2434                                 $filesNotWritable[$i] = $file;
2435                                 $filesNWPerms[$i] = substr(sprintf('%o',fileperms($file)), -4);
2436                                 $owner = posix_getpwuid(fileowner($file));
2437                                 $group = posix_getgrgid(filegroup($file));
2438                                 $filesOut .= "<tr>".
2439                                                                 "<td><span class='error'>{$file}</span></td>".
2440                                                                 "<td>{$filesNWPerms[$i]}</td>".
2441                                                                 "<td>".$owner['name']."</td>".
2442                                                                 "<td>".$group['name']."</td>".
2443                                                           "</tr>";
2444                         }
2445                 }
2446                 $i++;
2447         }
2448
2449         $filesOut .= '</table></div>';
2450         // not a stop error
2451         $errors['files']['filesNotWritable'] = (count($filesNotWritable) > 0) ? true : false;
2452         if(count($filesNotWritable) < 1) {
2453                 $filesOut = "{$mod_strings['LBL_UW_FILE_NO_ERRORS']}";
2454         }
2455
2456         return $filesOut;
2457 }
2458
2459 function deletePackageOnCancel(){
2460         global $mod_strings;
2461         global $sugar_config;
2462         list($base_upgrade_dir, $base_tmp_upgrade_dir) = getUWDirs();
2463         logThis('running delete');
2464     if(!isset($_SESSION['install_file']) || ($_SESSION['install_file'] == "")) {
2465         logThis('ERROR: trying to delete non-existent file: ['.$_REQUEST['install_file'].']');
2466         $error = $mod_strings['ERR_UW_NO_FILE_UPLOADED'];
2467     }
2468     // delete file in upgrades/patch
2469     $delete_me = "$base_upgrade_dir/patch/".basename(urldecode( $_REQUEST['install_file'] ));
2470     if(@unlink($delete_me)) {
2471         //logThis('unlinking: '.$delete_me);
2472         $out = basename($delete_me).$mod_strings['LBL_UW_FILE_DELETED'];
2473     } else {
2474         logThis('ERROR: could not delete ['.$delete_me.']');
2475                 $error = $mod_strings['ERR_UW_FILE_NOT_DELETED'].$delete_me;
2476     }
2477
2478     if(!empty($error)) {
2479                 $out = "<b><span class='error'>{$error}</span></b><br />";
2480     }
2481 }
2482
2483 function handleExecuteSqlKeys($db, $tableName, $disable)
2484 {
2485     if(empty($tableName)) return true;
2486     if(is_callable(array($db, "supports"))) {
2487         // new API
2488         return $disable?$db->disableKeys($tableName):$db->enableKeys($tableName);
2489     } else {
2490         // old api
2491         $op = $disable?"DISABLE":"ENABLE";
2492         return $db->query("ALTER TABLE $tableName $op KEYS");
2493     }
2494 }
2495
2496 function parseAndExecuteSqlFile($sqlScript,$forStepQuery='',$resumeFromQuery='')
2497 {
2498         global $sugar_config;
2499         $alterTableSchema = '';
2500         $sqlErrors = array();
2501         if(!isset($_SESSION['sqlSkippedQueries'])){
2502                 $_SESSION['sqlSkippedQueries'] = array();
2503         }
2504         $db = DBManagerFactory::getInstance();
2505         $disable_keys = ($db->dbType == "mysql"); // have to use old way for now for upgrades
2506         if(strpos($resumeFromQuery,",") != false){
2507                 $resumeFromQuery = explode(",",$resumeFromQuery);
2508         }
2509         if(file_exists($sqlScript)) {
2510                 $fp = fopen($sqlScript, 'r');
2511                 $contents = stream_get_contents($fp);
2512                 $anyScriptChanges =$contents;
2513                 $resumeAfterFound = false;
2514                 if(rewind($fp)) {
2515                         $completeLine = '';
2516                         $count = 0;
2517                         while($line = fgets($fp)) {
2518                                 if(strpos($line, '--') === false) {
2519                                         $completeLine .= " ".trim($line);
2520                                         if(strpos($line, ';') !== false) {
2521                                                 $query = '';
2522                                                 $query = str_replace(';','',$completeLine);
2523                                                 //if resume from query is not null then find out from where
2524                                                 //it should start executing the query.
2525
2526                                                 if($query != null && $resumeFromQuery != null){
2527                                                         if(!$resumeAfterFound){
2528                                                                 if(strpos($query,",") != false){
2529                                                                         $queArray = explode(",",$query);
2530                                                                         for($i=0;$i<sizeof($resumeFromQuery);$i++){
2531                                                                                 if(strcasecmp(trim($resumeFromQuery[$i]),trim($queArray[$i]))==0){
2532                                                                                         $resumeAfterFound = true;
2533                                                                                 } else {
2534                                                                                         $resumeAfterFound = false;
2535                                                                                         break;
2536                                                                                 }
2537                                                                         }//for
2538
2539                                                                 }
2540                                                                 elseif(strcasecmp(trim($resumeFromQuery),trim($query))==0){
2541                                                                         $resumeAfterFound = true;
2542                                                                 }
2543                                                         }
2544                                                         if($resumeAfterFound){
2545                                                                 $count++;
2546                                                         }
2547                                                         // if $count=1 means it is just found so skip the query. Run the next one
2548                                                         if($query != null && $resumeAfterFound && $count >1){
2549                                                         $tableName = getAlterTable($query);
2550                                                                 if($disable_keys)
2551                                                                 {
2552                                                                         handleExecuteSqlKeys($db, $tableName, true);
2553                                                                 }
2554                                                                 $db->query($query);
2555                                                                 if($db->checkError()){
2556                                                                         //put in the array to use later on
2557                                                                         $_SESSION['sqlSkippedQueries'][] = $query;
2558                                                                 }
2559                                                                 if($disable_keys)
2560                                                                 {
2561                                                                         handleExecuteSqlKeys($db, $tableName, false);
2562                                                                 }
2563                                                                 $progQuery[$forStepQuery]=$query;
2564                                                                 post_install_progress($progQuery,$action='set');
2565                                                         }//if
2566                                                 }
2567                                                 elseif($query != null){
2568                                                         $tableName = getAlterTable($query);
2569                                                         if($disable_keys)
2570                                                         {
2571                                                                 handleExecuteSqlKeys($db, $tableName, true);
2572                                                         }
2573                                                         $db->query($query);
2574                                                         if($disable_keys)
2575                                                         {
2576                                                                 handleExecuteSqlKeys($db, $tableName, false);
2577                                                         }
2578                                                         $progQuery[$forStepQuery]=$query;
2579                                                         post_install_progress($progQuery,$action='set');
2580                                                         if($db->checkError()){
2581                                                                 //put in the array to use later on
2582                                                                 $_SESSION['sqlSkippedQueries'][] = $query;
2583                                                         }
2584                                                 }
2585                                                 $completeLine = '';
2586                                         }
2587                                 }
2588                         }//while
2589                 }
2590         }
2591 }
2592
2593
2594 function getAlterTable($query){
2595         $query = strtolower($query);
2596         if (preg_match('/^\s*alter\s+table\s+/', $query)) {
2597                 $sqlArray = explode(" ", $query);
2598                 $key = array_search('table', $sqlArray);
2599                 return $sqlArray[($key+1)];
2600         }else {
2601                 return '';
2602         }
2603 }
2604
2605 function set_upgrade_vars(){
2606         logThis('setting session variables...');
2607         $upgrade_progress_dir = sugar_cached('upgrades/temp');
2608         if(!is_dir($upgrade_progress_dir)){
2609                 mkdir_recursive($upgrade_progress_dir);
2610         }
2611         $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
2612         if(file_exists($upgrade_progress_file)){
2613                 include($upgrade_progress_file);
2614         }
2615         else{
2616                 fopen($upgrade_progress_file, 'w+');
2617         }
2618         if(!isset($upgrade_config) || $upgrade_config == null){
2619                 $upgrade_config = array();
2620                 $upgrade_config[1]['upgrade_vars']=array();
2621         }
2622     if(isset($upgrade_config[1]) && isset($upgrade_config[1]['upgrade_vars']) && !is_array($upgrade_config[1]['upgrade_vars'])){
2623         $upgrade_config[1]['upgrade_vars'] = array();
2624     }
2625
2626         if(!isset($upgrade_vars) || $upgrade_vars == NULL){
2627                 $upgrade_vars = array();
2628         }
2629         if(isset($_SESSION['unzip_dir']) && !empty($_SESSION['unzip_dir']) && file_exists($_SESSION['unzip_dir'])){
2630                 $upgrade_vars['unzip_dir']=$_SESSION['unzip_dir'];
2631         }
2632         if(isset($_SESSION['install_file']) && !empty($_SESSION['install_file']) && file_exists($_SESSION['install_file'])){
2633                 $upgrade_vars['install_file']=$_SESSION['install_file'];
2634         }
2635         if(isset($_SESSION['Upgraded451Wizard']) && !empty($_SESSION['Upgraded451Wizard'])){
2636                 $upgrade_vars['Upgraded451Wizard']=$_SESSION['Upgraded451Wizard'];
2637         }
2638         if(isset($_SESSION['license_shown']) && !empty($_SESSION['license_shown'])){
2639                 $upgrade_vars['license_shown']=$_SESSION['license_shown'];
2640         }
2641         if(isset($_SESSION['Initial_451to500_Step']) && !empty($_SESSION['Initial_451to500_Step'])){
2642                 $upgrade_vars['Initial_451to500_Step']=$_SESSION['Initial_451to500_Step'];
2643         }
2644         if(isset($_SESSION['zip_from_dir']) && !empty($_SESSION['zip_from_dir'])){
2645                 $upgrade_vars['zip_from_dir']=$_SESSION['zip_from_dir'];
2646         }
2647         //place into the upgrade_config array and rewrite config array only if new values are being inserted
2648         if(isset($upgrade_vars) && $upgrade_vars != null && sizeof($upgrade_vars) > 0){
2649                 foreach($upgrade_vars as $key=>$val){
2650                         if($key != null && $val != null){
2651                                 $upgrade_config[1]['upgrade_vars'][$key]=$upgrade_vars[$key];
2652                         }
2653                 }
2654                 ksort($upgrade_config);
2655                 if(is_writable($upgrade_progress_file) && write_array_to_file( "upgrade_config", $upgrade_config,
2656                         $upgrade_progress_file)) {
2657                        //writing to the file
2658                 }
2659     }
2660 }
2661
2662 function initialize_session_vars(){
2663   $upgrade_progress_dir = sugar_cached('upgrades/temp');
2664   $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
2665   if(file_exists($upgrade_progress_file)){
2666         include($upgrade_progress_file);
2667         if(isset($upgrade_config) && $upgrade_config != null && is_array($upgrade_config) && sizeof($upgrade_config) >0){
2668                 $currVarsArray=$upgrade_config[1]['upgrade_vars'];
2669                 //print_r($currVarsArray);
2670                 if(isset($currVarsArray) && $currVarsArray != null && is_array($currVarsArray) && sizeof($currVarsArray)>0){
2671                         foreach($currVarsArray as $key=>$val){
2672                                 if($key != null && $val !=null){
2673                                         //set session variables
2674                                         $_SESSION[$key]=$val;
2675                                         //set varibales
2676                                         '$'.$key=$val;
2677                                 }
2678                         }
2679                 }
2680         }
2681   }
2682 }
2683 //track the upgrade progress on each step
2684 //track the upgrade progress on each step
2685 function set_upgrade_progress($currStep,$currState,$currStepSub='',$currStepSubState=''){
2686
2687         $upgrade_progress_dir = sugar_cached('upgrades/temp');
2688         if(!is_dir($upgrade_progress_dir)){
2689                 mkdir_recursive($upgrade_progress_dir);
2690         }
2691         $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
2692         if(file_exists($upgrade_progress_file)){
2693                 include($upgrade_progress_file);
2694         }
2695         else{
2696                 if(function_exists('sugar_fopen')){
2697                         sugar_fopen($upgrade_progress_file, 'w+');
2698                 }
2699                 else{
2700                         fopen($upgrade_progress_file, 'w+');
2701                 }
2702         }
2703         if(!isset($upgrade_config) || $upgrade_config == null){
2704                 $upgrade_config = array();
2705                 $upgrade_config[1]['upgrade_vars']=array();
2706         }
2707     if(!is_array($upgrade_config[1]['upgrade_vars'])){
2708         $upgrade_config[1]['upgrade_vars'] = array();
2709     }
2710         if($currStep != null && $currState != null){
2711                 if(sizeof($upgrade_config) > 0){
2712                         if($currStepSub != null && $currStepSubState !=null){
2713                                 //check if new status to be set or update
2714                                 //get the latest in array. since it has sub components prepare an array
2715                                 if(!empty($upgrade_config[sizeof($upgrade_config)][$currStep]) && is_array($upgrade_config[sizeof($upgrade_config)][$currStep])){
2716                                         $latestStepSub = currSubStep($upgrade_config[sizeof($upgrade_config)][$currStep]);
2717                                         if($latestStepSub == $currStepSub){
2718                                                 $upgrade_config[sizeof($upgrade_config)][$currStep][$latestStepSub]=$currStepSubState;
2719                                                 $upgrade_config[sizeof($upgrade_config)][$currStep][$currStep] = $currState;
2720                                         }
2721                                         else{
2722                                                 $upgrade_config[sizeof($upgrade_config)][$currStep][$currStepSub]=$currStepSubState;
2723                                                 $upgrade_config[sizeof($upgrade_config)][$currStep][$currStep] = $currState;
2724                                         }
2725                                 }
2726                                 else{
2727                                         $currArray = array();
2728                                         $currArray[$currStep] = $currState;
2729                                         $currArray[$currStepSub] = $currStepSubState;
2730                                         $upgrade_config[sizeof($upgrade_config)+1][$currStep] = $currArray;
2731                                 }
2732                         }
2733           else{
2734                                 //get the current upgrade progress
2735                                 $latestStep = get_upgrade_progress();
2736                                 //set the upgrade progress
2737                                 if($latestStep == $currStep){
2738                                         //update the current step with new progress status
2739                                         $upgrade_config[sizeof($upgrade_config)][$latestStep]=$currState;
2740                                 }
2741                                 else{
2742                                         //it's a new step
2743                                         $upgrade_config[sizeof($upgrade_config)+1][$currStep]=$currState;
2744                                 }
2745                     // now check if there elements within array substeps
2746           }
2747                 }
2748                 else{
2749                         //set the upgrade progress  (just starting)
2750                         $upgrade_config[sizeof($upgrade_config)+1][$currStep]= $currState;
2751                 }
2752
2753                 if(is_writable($upgrade_progress_file) && write_array_to_file( "upgrade_config", $upgrade_config,
2754                 $upgrade_progress_file)) {
2755                //writing to the file
2756                 }
2757
2758         }
2759 }
2760
2761 function get_upgrade_progress(){
2762         $upgrade_progress_dir = sugar_cached('upgrades/temp');
2763         $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
2764         $currState = '';
2765
2766         if(file_exists($upgrade_progress_file)){
2767                 include($upgrade_progress_file);
2768                 if(!isset($upgrade_config) || $upgrade_config == null){
2769                         $upgrade_config = array();
2770                 }
2771                 if($upgrade_config != null && sizeof($upgrade_config) >1){
2772                         $currArr = $upgrade_config[sizeof($upgrade_config)];
2773                         if(is_array($currArr)){
2774                            foreach($currArr as $key=>$val){
2775                                         $currState = $key;
2776                                 }
2777                         }
2778                 }
2779         }
2780         return $currState;
2781 }
2782 function currSubStep($currStep){
2783         $currSubStep = '';
2784         if(is_array($currStep)){
2785        foreach($currStep as $key=>$val){
2786                     if($key != null){
2787                         $currState = $key;
2788                         }
2789            }
2790         }
2791         return $currState;
2792 }
2793 function currUpgradeState($currState){
2794         $currState = '';
2795         if(is_array($currState)){
2796        foreach($currState as $key=>$val){
2797                         if(is_array($val)){
2798                                 foreach($val as $k=>$v){
2799                                         if($k != null){
2800                                                 $currState = $k;
2801                                         }
2802                                 }
2803                         }
2804                         else{
2805                                 $currState = $key;
2806                         }
2807                 }
2808         }
2809         return $currState;
2810 }
2811
2812 function didThisStepRunBefore($step,$SubStep=''){
2813         if($step == null) return;
2814         $upgrade_progress_dir = sugar_cached('upgrades/temp');
2815         $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
2816         $currState = '';
2817         $stepRan = false;
2818         if(file_exists($upgrade_progress_file)){
2819                 include($upgrade_progress_file);
2820                 if(isset($upgrade_config) && $upgrade_config != null && is_array($upgrade_config) && sizeof($upgrade_config) >0){
2821                         for($i=1;$i<=sizeof($upgrade_config);$i++){
2822                           if(is_array($upgrade_config[$i])){
2823                                         foreach($upgrade_config[$i] as $key=>$val){
2824                                                 if($key==$step){
2825                                                         if(is_array($upgrade_config[$i][$step])){
2826                                                                 //now process
2827                                                                 foreach ($upgrade_config[$i][$step] as $k=>$v){
2828                                                                         if(is_array($v)){
2829                                                                                 foreach($v as $k1=>$v1){
2830                                                                                         if($SubStep != null){
2831                                                                                                 if($SubStep ==$k1 && $v1=='done'){
2832                                                                                                         $stepRan = true;
2833                                                                                                         break;
2834                                                                                                 }
2835                                                                                         }
2836                                                                                 }//foreach
2837                                                                         }
2838                                                                         elseif($SubStep !=null){
2839                                                                                 if($SubStep==$k && $v=='done'){
2840                                                                                         $stepRan = true;
2841                                                                                         break;
2842                                                                                 }
2843                                                                         }
2844                                                                         elseif($step==$k && $v=='done'){
2845                                                                                 $stepRan = true;
2846                                                                                 break;
2847                                                                         }
2848                                                                 }//foreach
2849                                                         }
2850                                                         elseif($val=='done'){
2851                                                                 $stepRan = true;
2852                                                         }
2853                                                 }
2854                                         }//foreach
2855                                 }
2856                         }//for
2857                 }
2858         }
2859         return $stepRan;
2860 }
2861
2862
2863
2864 //get and set post install status
2865 function post_install_progress($progArray='',$action=''){
2866         $upgrade_progress_dir = sugar_cached('upgrades/temp');
2867         $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
2868     if($action=='' || $action=='get'){
2869                 //get the state of post install
2870         $currProg = array();
2871                 if(file_exists($upgrade_progress_file)){
2872                         include($upgrade_progress_file);
2873                         if(is_array($upgrade_config[sizeof($upgrade_config)]['commit']['post_install']) && sizeof($upgrade_config[sizeof($upgrade_config)]['commit']['post_install'])>0){
2874                                 foreach($upgrade_config[sizeof($upgrade_config)]['commit']['post_install'] as $k=>$v){
2875                                         $currProg[$k]=$v;
2876                                 }
2877                         }
2878                 }
2879                 return $currProg;
2880         }
2881         elseif($action=='set'){
2882                 if(!is_dir($upgrade_progress_dir)){
2883                         mkdir($upgrade_progress_dir);
2884                 }
2885                 if(file_exists($upgrade_progress_file)){
2886                         include($upgrade_progress_file);
2887                 }
2888                 else{
2889                         fopen($upgrade_progress_file, 'w+');
2890                 }
2891                 if(!is_array($upgrade_config[sizeof($upgrade_config)]['commit']['post_install'])){
2892                         $upgrade_config[sizeof($upgrade_config)]['commit']['post_install']=array();
2893                         $upgrade_config[sizeof($upgrade_config)]['commit']['post_install']['post_install'] = 'in_progress';
2894                 }
2895                 if($progArray != null && is_array($progArray)){
2896                         foreach($progArray as $key=>$val){
2897                                 $upgrade_config[sizeof($upgrade_config)]['commit']['post_install'][$key]=$val;
2898                         }
2899                 }
2900                 if(is_writable($upgrade_progress_file) && write_array_to_file( "upgrade_config", $upgrade_config,
2901                 $upgrade_progress_file)) {
2902                //writing to the file
2903                 }
2904         }
2905 }
2906
2907 function repairDBForUpgrade($execute=false,$path=''){
2908
2909         global $current_user, $beanFiles;
2910         global $dictionary;
2911         set_time_limit(3600);
2912
2913         $db = &DBManagerFactory::getInstance();
2914         $sql = '';
2915         VardefManager::clearVardef();
2916         require_once('include/ListView/ListView.php');
2917         foreach ($beanFiles as $bean => $file) {
2918                 require_once ($file);
2919                 $focus = new $bean ();
2920                 $sql .= $db->repairTable($focus, $execute);
2921
2922         }
2923         //echo $sql;
2924         $olddictionary = $dictionary;
2925         unset ($dictionary);
2926         include ('modules/TableDictionary.php');
2927         foreach ($dictionary as $meta) {
2928                 $tablename = $meta['table'];
2929                 $fielddefs = $meta['fields'];
2930                 $indices = $meta['indices'];
2931                 $sql .= $db->repairTableParams($tablename, $fielddefs, $indices, $execute);
2932         }
2933          $qry_str = "";
2934           foreach (explode("\n", $sql) as $line) {
2935                   if (!empty ($line) && substr($line, -2) != "*/") {
2936                         $line .= ";";
2937                   }
2938                   $qry_str .= $line . "\n";
2939            }
2940           $sql = str_replace(
2941           array(
2942                 "\n",
2943                 '&#039;',
2944            ),
2945           array(
2946                 '',
2947                 "'",
2948           ),
2949           preg_replace('#(/\*.+?\*/\n*)#', '', $qry_str)
2950           );
2951          logThis("*******START EXECUTING DB UPGRADE QUERIES***************",$path);
2952                 logThis($sql,$path);
2953          logThis("*******END EXECUTING DB UPGRADE QUERIES****************",$path);
2954          if(!$execute){
2955                 return $sql;
2956          }
2957 }
2958
2959
2960
2961 /**
2962  * upgradeUserPreferences
2963  * This method updates the user_preferences table and sets the pages/dashlets for users
2964  * which have ACL access to Trackers so that the Tracker dashlets are set in their user perferences
2965  *
2966  */
2967 function upgradeUserPreferences() {
2968     global $sugar_config, $sugar_version;
2969     $uw_strings = return_module_language($GLOBALS['current_language'], 'UpgradeWizard');
2970
2971     $localization = new Localization();
2972     $localeCoreDefaults = $localization->getLocaleConfigDefaults();
2973
2974     // check the current system wide default_locale_name_format and add it to the list if it's not there
2975     if(empty($sugar_config['name_formats'])) {
2976         $sugar_config['name_formats'] = $localeCoreDefaults['name_formats'];
2977         if(!rebuildConfigFile($sugar_config, $sugar_version)) {
2978             $errors[] = $uw_strings['ERR_UW_CONFIG_WRITE'];
2979         }
2980     }
2981
2982     $currentDefaultLocaleNameFormat = $sugar_config['default_locale_name_format'];
2983
2984     if ($localization->isAllowedNameFormat($currentDefaultLocaleNameFormat)) {
2985         upgradeLocaleNameFormat($currentDefaultLocaleNameFormat);
2986     } else {
2987         $sugar_config['default_locale_name_format'] = $localeCoreDefaults['default_locale_name_format'];
2988         if(!rebuildConfigFile($sugar_config, $sugar_version)) {
2989             $errors[] = $uw_strings['ERR_UW_CONFIG_WRITE'];
2990         }
2991         $localization->createInvalidLocaleNameFormatUpgradeNotice();
2992     }
2993
2994         $db = &DBManagerFactory::getInstance();
2995     $result = $db->query("SELECT id FROM users where deleted = '0'");
2996         while($row = $db->fetchByAssoc($result))
2997     {
2998         $current_user = new User();
2999         $current_user->retrieve($row['id']);
3000
3001         // 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
3002         $currentUserNameFormat = $current_user->getPreference('default_locale_name_format');
3003         if ($localization->isAllowedNameFormat($currentUserNameFormat)) {
3004             upgradeLocaleNameFormat($currentUserNameFormat);
3005         } else {
3006             $current_user->setPreference('default_locale_name_format', 's f l', 0, 'global');
3007             $current_user->savePreferencesToDB();
3008         }
3009
3010         } //while
3011 }
3012
3013
3014 /**
3015  * Checks if a locale name format is part of the default list, if not adds it to the config
3016  * @param $name_format string a local name format string such as 's f l'
3017  * @return bool true on successful write to config file, false on failure;
3018  */
3019 function upgradeLocaleNameFormat($name_format) {
3020     global $sugar_config, $sugar_version;
3021
3022     $localization = new Localization();
3023     $localeConfigDefaults = $localization->getLocaleConfigDefaults();
3024
3025     $uw_strings = return_module_language($GLOBALS['current_language'], 'UpgradeWizard');
3026     if(empty($sugar_config['name_formats'])) {
3027         $sugar_config['name_formats'] = $localeConfigDefaults['name_formats'];
3028         if(!rebuildConfigFile($sugar_config, $sugar_version)) {
3029             $errors[] = $uw_strings['ERR_UW_CONFIG_WRITE'];
3030         }
3031     }
3032     if (!in_array($name_format, $sugar_config['name_formats'])) {
3033         $new_config = sugarArrayMerge($sugar_config['name_formats'], array($name_format=>$name_format));
3034         $sugar_config['name_formats'] = $new_config;
3035         if(!rebuildConfigFile($sugar_config, $sugar_version)) {
3036             $errors[] = $uw_strings['ERR_UW_CONFIG_WRITE'];
3037             return false;
3038         }
3039     }
3040     return true;
3041 }
3042
3043
3044
3045 function add_custom_modules_favorites_search(){
3046     $module_directories = scandir('modules');
3047
3048         foreach($module_directories as $module_dir){
3049                 if($module_dir == '.' || $module_dir == '..' || !is_dir("modules/{$module_dir}")){
3050                         continue;
3051                 }
3052
3053                 $matches = array();
3054                 preg_match('/^[a-z0-9]{1,5}_[a-z0-9_]+$/i' , $module_dir, $matches);
3055
3056                 // Make sure the module was created by module builder
3057                 if(empty($matches)){
3058                         continue;
3059                 }
3060
3061                 $full_module_dir = "modules/{$module_dir}/";
3062                 $read_searchdefs_from = "{$full_module_dir}/metadata/searchdefs.php";
3063                 $read_SearchFields_from = "{$full_module_dir}/metadata/SearchFields.php";
3064                 $read_custom_SearchFields_from = "custom/{$full_module_dir}/metadata/SearchFields.php";
3065
3066                 // Studio can possibly override this file, so we check for a custom version of it
3067                 if(file_exists("custom/{$full_module_dir}/metadata/searchdefs.php")){
3068                         $read_searchdefs_from = "custom/{$full_module_dir}/metadata/searchdefs.php";
3069                 }
3070
3071                 if(file_exists($read_searchdefs_from) && file_exists($read_SearchFields_from)){
3072                         $found_sf1 = false;
3073                         $found_sf2 = false;
3074                         require($read_searchdefs_from);
3075                         foreach($searchdefs[$module_dir]['layout']['basic_search'] as $sf_array){
3076                                 if(isset($sf_array['name']) && $sf_array['name'] == 'favorites_only'){
3077                                         $found_sf1 = true;
3078                                 }
3079                         }
3080
3081                         require($read_SearchFields_from);
3082                         if(isset($searchFields[$module_dir]['favorites_only'])){
3083                                 $found_sf2 = true;
3084                         }
3085
3086                         if(!$found_sf1 && !$found_sf2){
3087                                 $searchdefs[$module_dir]['layout']['basic_search']['favorites_only'] = array('name' => 'favorites_only','label' => 'LBL_FAVORITES_FILTER','type' => 'bool',);
3088                                 $searchdefs[$module_dir]['layout']['advanced_search']['favorites_only'] = array('name' => 'favorites_only','label' => 'LBL_FAVORITES_FILTER','type' => 'bool',);
3089                                 $searchFields[$module_dir]['favorites_only'] = array(
3090                                         'query_type'=>'format',
3091                                         'operator' => 'subquery',
3092                                         'subquery' => 'SELECT sugarfavorites.record_id FROM sugarfavorites
3093                                                                 WHERE sugarfavorites.deleted=0
3094                                                                         and sugarfavorites.module = \''.$module_dir.'\'
3095                                                                         and sugarfavorites.assigned_user_id = \'{0}\'',
3096                                         'db_field'=>array('id')
3097                                 );
3098
3099                                 if(!is_dir("custom/{$full_module_dir}/metadata")){
3100                                         mkdir_recursive("custom/{$full_module_dir}/metadata");
3101                                 }
3102                                 $success_sf1 = write_array_to_file('searchdefs', $searchdefs, "custom/{$full_module_dir}/metadata/searchdefs.php");
3103                                 $success_sf2 = write_array_to_file('searchFields', $searchFields, "{$full_module_dir}/metadata/SearchFields.php");
3104
3105                                 if(!$success_sf1){
3106                                         logThis("add_custom_modules_favorites_search failed for searchdefs.php for {$module_dir}");
3107                                 }
3108                                 if(!$success_sf2){
3109                                         logThis("add_custom_modules_favorites_search failed for SearchFields.php for {$module_dir}");
3110                                 }
3111                                 if($success_sf1 && $success_sf2){
3112                                         logThis("add_custom_modules_favorites_search successfully updated searchdefs and searchFields for {$module_dir}");
3113                                 }
3114                         }
3115                 }
3116         }
3117 }
3118
3119
3120 /**
3121  * upgradeModulesForTeamsets
3122  *
3123  * This method adds the team_set_id values to the module tables that have the new team_set_id column
3124  * added through the SugarCRM 5.5.x upgrade process.  It also adds the values into the team_sets and
3125  * team_sets_teams tables.
3126  *
3127  * @param filter Array of modules to process; empty by default
3128  */
3129 function upgradeModulesForTeamsets($filter=array()) {
3130     require('include/modules.php');
3131         foreach($beanList as $moduleName=>$beanName) {
3132                     if(!empty($filter) && array_search($moduleName, $filter) === false) {
3133                        continue;
3134                     }
3135                 if($moduleName == 'TeamMemberships' || $moduleName == 'ForecastOpportunities'){
3136                 continue;
3137             }
3138                         $bean = loadBean($moduleName);
3139                         if(empty($bean) ||
3140                            empty($bean->table_name)) {
3141                            continue;
3142                         }
3143
3144                         $FieldArray = $GLOBALS['db']->helper->get_columns($bean->table_name);
3145                         if(!isset($FieldArray['team_id'])) {
3146                            continue;
3147                         }
3148
3149                         upgradeTeamColumn($bean, 'team_id');
3150
3151         } //foreach
3152
3153     //Upgrade users table
3154         $bean = loadBean('Users');
3155         upgradeTeamColumn($bean, 'default_team');
3156         $result = $GLOBALS['db']->query("SELECT id FROM teams where deleted=0");
3157         while($row = $GLOBALS['db']->fetchByAssoc($result)) {
3158               $teamset = new TeamSet();
3159               $teamset->addTeams($row['id']);
3160         }
3161 }
3162
3163
3164 /**
3165  * upgradeTeamColumn
3166  * Helper function to create a team_set_id column and also set team_set_id column
3167  * to have the value of the $column_name parameter
3168  *
3169  * @param $bean SugarBean which we are adding team_set_id column to
3170  * @param $column_name The name of the column containing the default team_set_id value
3171  */
3172 function upgradeTeamColumn($bean, $column_name) {
3173         //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
3174         //module that does not use the SugarObjects
3175         if(empty($bean->field_defs['team_set_id']) && $bean->module_dir != 'Trackers'){
3176
3177                 //at this point we could assume that since we have a team_id defined and not a team_set_id that we need to
3178                 //add that field and the corresponding relationships
3179                 $object = $bean->object_name;
3180                 $module = $bean->module_dir;
3181                 $object_name = $object;
3182                 $_object_name = strtolower($object_name);
3183
3184                 if(!empty($GLOBALS['dictionary'][$object]['table'])){
3185                         $table_name = $GLOBALS['dictionary'][$object]['table'];
3186                 }else{
3187                         $table_name = strtolower($module);
3188                 }
3189
3190                 $path = 'include/SugarObjects/implements/team_security/vardefs.php';
3191                 require($path);
3192                 //go through each entry in the vardefs from team_security and unset anything that is already set in the core module
3193                 //this will ensure we have the proper ordering.
3194                 $fieldDiff = array_diff_assoc($vardefs['fields'], $GLOBALS['dictionary'][$bean->object_name]['fields']);
3195
3196                 $file = 'custom/Extension/modules/' . $bean->module_dir. '/Ext/Vardefs/teams.php';
3197                 $contents = "<?php\n";
3198                 if(!empty($fieldDiff)){
3199                         foreach($fieldDiff as $key => $val){
3200                                 $contents .= "\n\$GLOBALS['dictionary']['". $object . "']['fields']['". $key . "']=" . var_export_helper($val) . ";";
3201                         }
3202                 }
3203                 $relationshipDiff = array_diff_assoc($vardefs['relationships'], $GLOBALS['dictionary'][$bean->object_name]['relationships']);
3204                 if(!empty($relationshipDiff)){
3205                         foreach($relationshipDiff as $key => $val){
3206                                 $contents .= "\n\$GLOBALS['dictionary']['". $object . "']['relationships']['". $key . "']=" . var_export_helper($val) . ";";
3207                         }
3208                 }
3209                 $indexDiff = array_diff_assoc($vardefs['indices'], $GLOBALS['dictionary'][$bean->object_name]['indices']);
3210                 if(!empty($indexDiff)){
3211                         foreach($indexDiff as $key => $val){
3212                                         $contents .= "\n\$GLOBALS['dictionary']['". $object . "']['indices']['". $key . "']=" . var_export_helper($val) . ";";
3213                         }
3214                 }
3215                 if( $fh = @sugar_fopen( $file, 'wt' ) )
3216             {
3217                 fputs( $fh, $contents);
3218                 fclose( $fh );
3219             }
3220
3221
3222                 //we have written out the teams.php into custom/Extension/modules/{$module_dir}/Ext/Vardefs/teams.php'
3223                 //now let's merge back into vardefs.ext.php
3224                 require_once('ModuleInstall/ModuleInstaller.php');
3225                 $mi = new ModuleInstaller();
3226                 $mi->merge_files('Ext/Vardefs/', 'vardefs.ext.php');
3227                 VardefManager::loadVardef($bean->module_dir, $bean->object_name, true);
3228                 $bean->field_defs = $GLOBALS['dictionary'][$bean->object_name]['fields'];
3229         }
3230
3231         if(isset($bean->field_defs['team_set_id'])) {
3232                 //Create the team_set_id column
3233                 $FieldArray = $GLOBALS['db']->helper->get_columns($bean->table_name);
3234                 if(!isset($FieldArray['team_set_id'])) {
3235                         $GLOBALS['db']->addColumn($bean->table_name, $bean->field_defs['team_set_id']);
3236                 }
3237                 $indexArray =  $GLOBALS['db']->helper->get_indices($bean->table_name);
3238
3239         $indexName = getValidDBName('idx_'.strtolower($bean->table_name).'_tmst_id', true, 34);
3240         $indexDef = array(
3241                                          array(
3242                                                 'name' => $indexName,
3243                                                 'type' => 'index',
3244                                                 'fields' => array('team_set_id')
3245                                          )
3246                                    );
3247                 if(!isset($indexArray[$indexName])) {
3248                         $GLOBALS['db']->addIndexes($bean->table_name, $indexDef);
3249                 }
3250
3251                 //Update the table's team_set_id column to have the same values as team_id
3252             $GLOBALS['db']->query("UPDATE {$bean->table_name} SET team_set_id = {$column_name}");
3253         }
3254 }
3255
3256 /**
3257  *  Update the folder subscription table which confirms to the team security mechanism but
3258  *  the class SugarFolders does not extend SugarBean and is therefore never picked up by the
3259  *  upgradeModulesForTeamsets function.
3260  */
3261 function upgradeFolderSubscriptionsTeamSetId()
3262 {
3263     logThis("In upgradeFolderSubscriptionsTeamSetId()");
3264     $query = "UPDATE folders SET team_set_id = team_id";
3265     $result = $GLOBALS['db']->query($query);
3266     logThis("Finished upgradeFolderSubscriptionsTeamSetId()");
3267 }
3268
3269 /**
3270  * upgradeModulesForTeam
3271  *
3272  * This method update the associated_user_id, name, name_2 to the private team records on teams table
3273  * This function is used for upgrade process from 5.1.x and 5.2.x.
3274  *
3275  */
3276 function upgradeModulesForTeam() {
3277     logThis("In upgradeModulesForTeam()");
3278     $result = $GLOBALS['db']->query("SELECT id, user_name, first_name, last_name FROM users where deleted=0");
3279
3280     while($row = $GLOBALS['db']->fetchByAssoc($result)) {
3281         $results2 = $GLOBALS['db']->query("SELECT id FROM teams WHERE name = '({$row['user_name']})'");
3282         $assoc = '';
3283                 if(!$assoc = $GLOBALS['db']->fetchByAssoc($results2)) {
3284                         //if team does not exist, then lets create the team for this user
3285                         $team = new Team();
3286                         $user = new User();
3287                         $user->retrieve($row['id']);
3288                         $team->new_user_created($user);
3289                         $team_id = $team->id;
3290                 }else{
3291                         $team_id =$assoc['id'];
3292                 }
3293
3294                         //upgrade the team
3295                         $name = is_null($row['first_name'])?'':$row['first_name'];
3296                         $name_2 = is_null($row['last_name'])?'':$row['last_name'];
3297                         $associated_user_id = $row['id'];
3298
3299                         //Bug 32914
3300                         //Ensure team->name is not empty by using team->name_2 if available
3301                         if(empty($name) && !empty($name_2)) {
3302                            $name = $name_2;
3303                            $name_2 = '';
3304                         }
3305
3306                         $query = "UPDATE teams SET name = '{$name}', name_2 = '{$name_2}', associated_user_id = '{$associated_user_id}' WHERE id = '{$team_id}'";
3307                         $GLOBALS['db']->query($query);
3308     } //while
3309
3310     //Update the team_set_id and default_team columns
3311     $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'));
3312
3313     //Update team_set_id
3314         if($ce_to_pro_or_ent) {
3315            $GLOBALS['db']->query("update users set team_set_id = (select teams.id from teams where teams.associated_user_id = users.id)");
3316            $GLOBALS['db']->query("update users set default_team = (select teams.id from teams where teams.associated_user_id = users.id)");
3317         }
3318
3319 }
3320
3321
3322     function addNewSystemTabsFromUpgrade($from_dir){
3323         global $path;
3324         if(isset($_SESSION['upgrade_from_flavor'])){
3325
3326             //check to see if there are any new files that need to be added to systems tab
3327             //retrieve old modules list
3328             logThis('check to see if new modules exist',$path);
3329             $oldModuleList = array();
3330             $newModuleList = array();
3331             include($from_dir.'/include/modules.php');
3332             $oldModuleList = $moduleList;
3333             include('include/modules.php');
3334             $newModuleList = $moduleList;
3335
3336             //include tab controller
3337             require_once('modules/MySettings/TabController.php');
3338             $newTB = new TabController();
3339
3340             //make sure new modules list has a key we can reference directly
3341             $newModuleList = $newTB->get_key_array($newModuleList);
3342             $oldModuleList = $newTB->get_key_array($oldModuleList);
3343
3344             //iterate through list and remove commonalities to get new modules
3345             foreach ($newModuleList as $remove_mod){
3346                 if(in_array($remove_mod, $oldModuleList)){
3347                     unset($newModuleList[$remove_mod]);
3348                 }
3349             }
3350             //new modules list now has left over modules which are new to this install, so lets add them to the system tabs
3351             logThis('new modules to add are '.var_export($newModuleList,true),$path);
3352
3353             if(!empty($newModuleList))
3354             {
3355                     //grab the existing system tabs
3356                     $tabs = $newTB->get_system_tabs();
3357
3358                     //add the new tabs to the array
3359                     foreach($newModuleList as $nm ){
3360                       $tabs[$nm] = $nm;
3361                     }
3362
3363                     $newTB->set_system_tabs($tabs);
3364             }
3365             logThis('module tabs updated',$path);
3366         }
3367     }
3368
3369     /**
3370      * fix_dropdown_list
3371      * This method attempts to fix dropdown lists that were incorrectly named.
3372      * There were versions of SugarCRM that did not enforce naming convention rules
3373      * for the dropdown list field name.  This method attempts to resolve that by
3374      * fixing the language files that may have been affected and then updating the
3375      * fields_meta_data table accordingly.  It also refreshes any vardefs that may
3376      * have been affected.
3377      *
3378      */
3379         function fix_dropdown_list() {
3380         if(file_exists('custom/include/language')) {
3381            $files = array();
3382            $affected_modules = array();
3383            $affected_keys = array();
3384
3385            getFiles($files, 'custom/include/language', '/\.php$/i');
3386            foreach($files as $file) {
3387
3388               if(file_exists($file . '.bak')) {
3389                  $bak_mod_time = filemtime($file . '.bak');
3390                  $php_mod_time = filemtime($file);
3391                  //We're saying if the .php file was modified 30 seconds no more than php.bak file then we
3392                  //run these additional cleanup checks
3393                  if($php_mod_time - $bak_mod_time < 30) {
3394
3395                         $app_list_strings = array();
3396                         $GLOBALS['app_list_strings'] = array();
3397                         require($file . '.bak');
3398                         $bak_app_list_strings = array_merge($app_list_strings, $GLOBALS['app_list_strings']);
3399
3400                         $app_list_strings = array();
3401                         $GLOBALS['app_list_strings'] = array();
3402                         require($file);
3403                         $php_app_list_strings = array_merge($app_list_strings, $GLOBALS['app_list_strings']);
3404
3405                         //Get the file contents
3406                         $contents = file_get_contents($file);
3407
3408                         //Now simulate a fix for the file before we compare w/ the .php file
3409                         //we also append to the $contents
3410                         foreach($bak_app_list_strings as $key=>$entry) {
3411                                                    if(preg_match('/([^A-Za-z_])/', $key, $matches) && is_array($entry)) {
3412                                                           $new_key = preg_replace('/[^A-Za-z_]/', '_', $key);
3413                                                           $bak_app_list_strings[$new_key] = $bak_app_list_strings[$key];
3414                                                           unset($bak_app_list_strings[$key]);
3415                                                           //Now if the entry doesn't exists in the .php file, then add to contents
3416                                                           if(!isset($php_app_list_strings[$new_key])) {
3417                                                                  $contents .= "\n\$GLOBALS['app_list_strings']['{$new_key}'] = " . var_export_helper($bak_app_list_strings[$new_key]) . ";";
3418                                                           }
3419                                                    } //if
3420                         } //foreach
3421
3422                         //Now load the .php file to do the comparison
3423                         foreach($php_app_list_strings as $key=>$entry) {
3424                                 if(isset($bak_app_list_strings[$key])) {
3425                                         $diff = array_diff($bak_app_list_strings[$key], $entry);
3426                                         if(!empty($diff)) {
3427                                            //There is a difference, so copy the $bak_app_list_strings version into the .php file
3428                                            $contents .= "\n\$GLOBALS['app_list_strings']['{$key}'] = " . var_export_helper($bak_app_list_strings[$key]) . ";";
3429                                         } //if
3430                                 } //if
3431                         } //foreach
3432
3433                         //Now write out the file contents
3434                         //Create backup just in case
3435                         copy($file, $file . '.php_bak');
3436                                         $fp = @sugar_fopen($file, 'w');
3437                         if($fp) {
3438                                fwrite($fp, $contents);
3439                                fclose($fp);
3440                         } else {
3441                            $GLOBALS['log']->error("Unable to update file contents in fix_dropdown_list for {$file}");
3442                         } //if-else
3443                  }
3444               }
3445
3446               unset($GLOBALS['app_strings']);
3447               unset($GLOBALS['app_list_strings']);
3448               $app_list_strings = array();
3449                   require($file);
3450                   $touched = false;
3451                   $contents = file_get_contents($file);
3452                   if ( !isset($GLOBALS['app_list_strings']) ) {
3453                       $GLOBALS['app_list_strings'] = $app_list_strings;
3454                   }
3455                   else {
3456                       $GLOBALS['app_list_strings'] = array_merge($app_list_strings, $GLOBALS['app_list_strings']);
3457                   }
3458
3459                   if(isset($GLOBALS['app_list_strings']) && is_array($GLOBALS['app_list_strings'])) {
3460                          foreach($GLOBALS['app_list_strings'] as $key=>$entry) {
3461                                 if(preg_match('/([^A-Za-z_])/', $key, $matches) && is_array($entry)) {
3462                                    $result = $GLOBALS['db']->query("SELECT custom_module FROM fields_meta_data WHERE ext1 = '{$key}'");
3463                                    if(!empty($result)) {
3464                                           while($row = $GLOBALS['db']->fetchByAssoc($result)) {
3465                                                     $custom_module = $row['custom_module'];
3466                                                     if(!empty($GLOBALS['beanList'][$custom_module])) {
3467                                                    $affected_modules[$custom_module] = $GLOBALS['beanList'][$custom_module];
3468                                                     }
3469                                           } //while
3470                                    }
3471
3472                                    //Replace all invalid characters with '_' character
3473                                    $new_key = preg_replace('/[^A-Za-z_]/', '_', $key);
3474                                    $affected_keys[$key] = $new_key;
3475
3476                                    $GLOBALS['app_list_strings'][$new_key] = $GLOBALS['app_list_strings'][$key];
3477                                    unset($GLOBALS['app_list_strings'][$key]);
3478
3479                                    $pattern_match = "/(\[\s*\'{$key}\'\s*\])/";
3480                                    $new_key = "['{$new_key}']";
3481                                    $out = preg_replace($pattern_match, $new_key, $contents);
3482                                    $contents = $out;
3483                                    $touched = true;
3484                                 } //if
3485                          } //foreach
3486
3487                  //This is a check for g => h instances where the file contents were incorrectly written
3488                  //and also fixes the scenario where via a UI upgrade, the app_list_strings were incorrectly
3489                  //merged with app_list_strings variables declared elsewhere
3490                          if(!$touched) {
3491                                    if(preg_match('/\$GLOBALS\s*\[\s*[\"|\']app_list_strings[\"|\']\s*\]\s*=\s*array\s*\(/', $contents)) {
3492                                           //Now also remove all the non-custom labels that were added
3493                                           if(preg_match('/language\/([^\.]+)\.lang\.php$/', $file, $matches)) {
3494                                                 $language = $matches[1];
3495
3496                                                 $app_list_strings = array();
3497
3498                                         if(file_exists("include/language/$language.lang.php")) {
3499                                                                    include("include/language/$language.lang.php");
3500                                                                 }
3501                                                                 if(file_exists("include/language/$language.lang.override.php")) {
3502                                                                    $app_list_strings =  _mergeCustomAppListStrings("include/language/$language.lang.override.php" , $app_list_strings) ;
3503                                                                 }
3504                                                                 if(file_exists("custom/application/Ext/Language/$language.ext.lang.php")) {
3505                                                                    $app_list_strings =  _mergeCustomAppListStrings("custom/application/Ext/Language/$language.ext.lang.php" , $app_list_strings) ;
3506                                                                 }
3507                                                                 if(file_exists("custom/application/Ext/Language/$language.lang.ext.php")) {
3508                                                                    $app_list_strings =  _mergeCustomAppListStrings("custom/application/Ext/Language/$language.lang.ext.php" , $app_list_strings) ;
3509                                                                 }
3510
3511                                                                 $all_non_custom_include_language_strings = $app_strings;
3512                                                                 $all_non_custom_include_language_list_strings = $app_list_strings;
3513
3514                                                                 $unset_keys = array();
3515                                                                 if(!empty($GLOBALS['app_list_strings'])) {
3516                                                                         foreach($GLOBALS['app_list_strings'] as $key=>$value) {
3517                                                                                 $diff = array();
3518                                                                                 if(isset($all_non_custom_include_language_list_strings[$key])) {
3519                                                                                         $diff = array_diff($all_non_custom_include_language_list_strings[$key], $GLOBALS['app_list_strings'][$key]);
3520                                                                                 }
3521
3522                                                                                 if(!empty($all_non_custom_include_language_list_strings[$key]) && empty($diff)) {
3523                                                                                         $unset_keys[] = $key;
3524                                                                                 }
3525                                                                         }
3526                                                                 }
3527
3528                                                                 foreach($unset_keys as $key) {
3529                                                                         unset($GLOBALS['app_list_strings'][$key]);
3530                                                                 }
3531
3532                                                                 if(!empty($GLOBALS['app_strings'])) {
3533                                                                 foreach($GLOBALS['app_strings'] as $key=>$value) {
3534                                                                                 if(!empty($all_non_custom_include_language_strings[$key])) {
3535                                                                                    unset($GLOBALS['app_strings'][$key]);
3536                                                                                 }
3537                                                                 }
3538                                                                 }
3539                                           } //if(preg_match...)
3540
3541                                       $out = "<?php \n";
3542                                       if(!empty($GLOBALS['app_strings'])) {
3543                                              foreach($GLOBALS['app_strings'] as $key=>$entry) {
3544                                                      $out .= "\n\$GLOBALS['app_strings']['$key']=" . var_export_helper($entry) . ";";
3545                                              }
3546                                       }
3547
3548                                                   foreach($GLOBALS['app_list_strings'] as $key=>$entry) {
3549                                                                   $out .= "\n\$GLOBALS['app_list_strings']['$key']=" . var_export_helper($entry) . ";";
3550                                                   } //foreach
3551
3552                                                   $touched = true;
3553                                    } //if(preg_match...)
3554                          } //if(!$touched)
3555
3556                          if($touched) {
3557                                  //Create a backup just in case
3558                                  copy($file, $file . '.bak');
3559                          $fp = @sugar_fopen($file, 'w');
3560                          if($fp) {
3561                                fwrite($fp, $out);
3562                                fclose($fp);
3563                          } else {
3564                            //If we can't update the file, just return
3565                            $GLOBALS['log']->error("Unable to update file contents in fix_dropdown_list.");
3566                            return;
3567                          }
3568                          } //if($touched)
3569                   } //if
3570
3571            } //foreach($files)
3572
3573            //Update db entries (the order matters here... need to process database changes first)
3574            if(!empty($affected_keys)) {
3575                   foreach($affected_keys as $old_key=>$new_key) {
3576                                   $GLOBALS['db']->query("UPDATE fields_meta_data SET ext1 = '{$new_key}' WHERE ext1 = '{$old_key}'");
3577                   }
3578            }
3579
3580            //Update vardef files for affected modules
3581            if(!empty($affected_modules)) {
3582                   foreach($affected_modules as $module=>$object) {
3583                           VardefManager::refreshVardefs($module, $object);
3584                   }
3585            }
3586         }
3587         }
3588
3589
3590         function update_iframe_dashlets(){
3591                 require_once(sugar_cached('dashlets/dashlets.php'));
3592
3593                 $db = DBManagerFactory::getInstance();
3594                 $query = "SELECT id, contents, assigned_user_id FROM user_preferences WHERE deleted = 0 AND category = 'Home'";
3595                 $result = $db->query($query, true, "Unable to update new default dashlets! ");
3596                 while ($row = $db->fetchByAssoc($result)) {
3597                         $content = unserialize(base64_decode($row['contents']));
3598                         $assigned_user_id = $row['assigned_user_id'];
3599                         $record_id = $row['id'];
3600
3601                         $current_user = new User();
3602                         $current_user->retrieve($row['assigned_user_id']);
3603
3604                         if(!empty($content['dashlets']) && !empty($content['pages'])){
3605                                 $originalDashlets = $content['dashlets'];
3606                                 foreach($originalDashlets as $key => $ds){
3607                                     if(!empty($ds['options']['url']) && stristr($ds['options']['url'],'http://www.sugarcrm.com/crm/product/gopro')){
3608                                                 unset($originalDashlets[$key]);
3609                                         }
3610                                 }
3611                                 $current_user->setPreference('dashlets', $originalDashlets, 0, 'Home');
3612                         }
3613                 }
3614         }
3615
3616
3617     /**
3618      * convertImageToText
3619      * @deprecated
3620      * This method attempts to convert date type image to text on Microsoft SQL Server.
3621      * This method could NOT be used in any other type of datebases.
3622      */
3623         function convertImageToText($table_name,$column_name){
3624                 $set_lang = "SET LANGUAGE us_english";
3625                 $GLOBALS['db']->query($set_lang);
3626             if($GLOBALS['db']->lastError()){
3627             logThis('An error occurred when performing this query-->'.$set_lang);
3628         }
3629        $q="SELECT data_type
3630         FROM INFORMATION_SCHEMA.Tables T JOIN INFORMATION_SCHEMA.Columns C
3631         ON T.TABLE_NAME = C.TABLE_NAME where T.TABLE_NAME = '$table_name' and C.COLUMN_NAME = '$column_name'";
3632        $res= $GLOBALS['db']->query($q);
3633        if($GLOBALS['db']->lastError()){
3634             logThis('An error occurred when performing this query-->'.$q);
3635         }
3636        $row= $GLOBALS['db']->fetchByAssoc($res);
3637
3638      if(trim(strtolower($row['data_type'])) == 'image'){
3639         $addContent_temp = "alter table {$table_name} add {$column_name}_temp text null";
3640         $GLOBALS['db']->query($addContent_temp);
3641         if($GLOBALS['db']->lastError()){
3642             logThis('An error occurred when performing this query-->'.$addContent_temp);
3643         }
3644         $qN = "select count=datalength({$column_name}), id, {$column_name} from {$table_name}";
3645         $result = $GLOBALS['db']->query($qN);
3646         while($row = $GLOBALS['db']->fetchByAssoc($result)){
3647            if($row['count'] >8000){
3648                 $contentLength = $row['count'];
3649                 $start = 1;
3650                 $next=8000;
3651                 $convertedContent = '';
3652                 while($contentLength >0){
3653                     $stepsQuery = "select cont=convert(varchar(max), convert(varbinary(8000), substring({$column_name},{$start},{$next}))) from {$table_name} where id= '{$row['id']}'";
3654                     $steContQ = $GLOBALS['db']->query($stepsQuery);
3655                     if($GLOBALS['db']->lastError()){
3656                         logThis('An error occurred when performing this query-->'.$stepsQuery);
3657                     }
3658                     $stepCont = $GLOBALS['db']->fetchByAssoc($steContQ);
3659                     if(isset($stepCont['cont'])){
3660                         $convertedContent = $convertedContent.$stepCont['cont'];
3661                     }
3662                     $start = $start+$next;
3663                     $contentLength = $contentLength - $next;
3664                 }
3665                 $addContentDataText="update {$table_name} set {$column_name}_temp = '{$convertedContent}' where id= '{$row['id']}'";
3666                 $GLOBALS['db']->query($addContentDataText);
3667                 if($GLOBALS['db']->lastError()){
3668                     logThis('An error occurred when performing this query-->'.$addContentDataText);
3669                 }
3670            }
3671            else{
3672                 $addContentDataText="update {$table_name} set {$column_name}_temp =
3673                 convert(varchar(max), convert(varbinary(8000), {$column_name})) where id= '{$row['id']}'";
3674                 $GLOBALS['db']->query($addContentDataText);
3675                 if($GLOBALS['db']->lastError()){
3676                     logThis('An error occurred when performing this query-->'.$addContentDataText);
3677                 }
3678            }
3679         }
3680         //drop the contents now and change contents_temp to contents
3681         $dropColumn = "alter table {$table_name} drop column {$column_name}";
3682         $GLOBALS['db']->query($dropColumn);
3683         if($GLOBALS['db']->lastError()){
3684             logThis('An error occurred when performing this query-->'.$dropColumn);
3685         }
3686         $changeColumnName = "EXEC sp_rename '{$table_name}.[{$column_name}_temp]','{$column_name}','COLUMN'";
3687         $GLOBALS['db']->query($changeColumnName);
3688         if($GLOBALS['db']->lastError()){
3689             logThis('An error occurred when performing this query-->'.$changeColumnName);
3690         }
3691      }
3692     }
3693
3694          /**
3695      * clearHelpFiles
3696      * This method attempts to delete all English inline help files.
3697      * This method was introduced by 5.5.0RC2.
3698      */
3699     function clearHelpFiles(){
3700                 $modulePath = clean_path(getcwd() . '/modules');
3701                 $allHelpFiles = array();
3702                 getFiles($allHelpFiles, $modulePath, "/en_us.help.*/");
3703
3704                 foreach( $allHelpFiles as $the_file ){
3705                 if( is_file( $the_file ) ){
3706                     unlink( $the_file );
3707                     logThis("Deleted file: $the_file");
3708                 }
3709             }
3710         }
3711
3712
3713
3714         /**
3715          * upgradeDateTimeFields
3716          *
3717          * This method came from bug: 39757 where the date_end field is a date field and not a datetime field
3718          * which prevents you from performing timezone offset calculations once the data has been saved.
3719          *
3720          * @param path String location to log file, empty by default
3721          */
3722         function upgradeDateTimeFields($path)
3723         {
3724                 //bug: 39757
3725                 global $db;
3726                 $meetingsSql = "UPDATE meetings SET date_end = ".$db->convert("date_start", 'add_time', array('duration_hours', 'duration_minutes'));
3727                 $callsSql = "UPDATE calls SET date_end = ".$db->convert("date_start", 'add_time', array('duration_hours', 'duration_minutes'));
3728         logThis('upgradeDateTimeFields Meetings SQL:' . $meetingsSql, $path);
3729                 $db->query($meetingsSql);
3730
3731                 logThis('upgradeDateTimeFields Calls SQL:' . $callsSql, $path);
3732                 $db->query($callsSql);
3733         }
3734
3735         /**
3736          * upgradeDocumentTypeFields
3737          *
3738          */
3739         function upgradeDocumentTypeFields($path){
3740                 //bug: 39757
3741                 global $db;
3742
3743                 $documentsSql = "UPDATE documents SET doc_type = 'Sugar' WHERE doc_type IS NULL";
3744                 $meetingsSql = "UPDATE meetings SET type = 'Sugar' WHERE type IS NULL";
3745
3746                 logThis('upgradeDocumentTypeFields Documents SQL:' . $documentsSql, $path);
3747                 $db->query($documentsSql);
3748                 logThis('upgradeDocumentTypeFields Meetings SQL:' . $meetingsSql, $path);
3749                 $db->query($meetingsSql);
3750         }
3751
3752
3753 /**
3754  * merge_config_si_settings
3755  * This method checks for the presence of a config_si.php file and, if found, merges the configuration
3756  * settings from the config_si.php file into config.php.  If a config_si_location parameter value is not
3757  * supplied it will attempt to discover the config_si.php file location from where the executing script
3758  * was invoked.
3759  *
3760  * @param write_to_upgrade_log boolean optional value to write to the upgradeWizard.log file
3761  * @param config_location String optional value to config.php file location
3762  * @param config_si_location String optional value to config_si.php file location
3763  * @param path String file of the location of log file to write to
3764  * @return boolean value indicating whether or not a merge was attempted with config_si.php file
3765  */
3766 function merge_config_si_settings($write_to_upgrade_log=false, $config_location='', $config_si_location='', $path='')
3767 {
3768         if(!empty($config_location) && !file_exists($config_location))
3769         {
3770                 if($write_to_upgrade_log)
3771                 {
3772                logThis('config.php file specified in ' . $config_si_location . ' could not be found.  Skip merging', $path);
3773                 }
3774             return false;
3775         } else if(empty($config_location)) {
3776                 global $argv;
3777                 //We are assuming this is from the silentUpgrade scripts so argv[3] will point to SugarCRM install location
3778                 if(isset($argv[3]) && is_dir($argv[3]))
3779                 {
3780                         $config_location = $argv[3] . DIRECTORY_SEPARATOR . 'config.php';
3781                 }
3782         }
3783
3784         //If config_location is still empty or if the file cannot be found, skip merging
3785         if(empty($config_location) || !file_exists($config_location))
3786         {
3787            if($write_to_upgrade_log)
3788            {
3789                   logThis('config.php file at (' . $config_location . ') could not be found.  Skip merging.', $path);
3790            }
3791            return false;
3792         } else {
3793            if($write_to_upgrade_log)
3794            {
3795               logThis('Loading config.php file at (' . $config_location . ') for merging.', $path);
3796            }
3797
3798            include($config_location);
3799            if(empty($sugar_config))
3800            {
3801                   if($write_to_upgrade_log)
3802                   {
3803                      logThis('config.php contents are empty.  Skip merging.', $path);
3804                   }
3805                   return false;
3806            }
3807         }
3808
3809         if(!empty($config_si_location) && !file_exists($config_si_location))
3810         {
3811                 if($write_to_upgrade_log)
3812                 {
3813                logThis('config_si.php file specified in ' . $config_si_location . ' could not be found.  Skip merging', $path);
3814                 }
3815             return false;
3816         } else if(empty($config_si_location)) {
3817                 if(isset($argv[0]) && is_file($argv[0]))
3818                 {
3819                         $php_file = $argv[0];
3820                         $p_info = pathinfo($php_file);
3821                         $php_dir = (isset($p_info['dirname']) && $p_info['dirname'] != '.') ?  $p_info['dirname'] . DIRECTORY_SEPARATOR : '';
3822                         $config_si_location = $php_dir . 'config_si.php';
3823                 }
3824         }
3825
3826         //If config_si_location is still empty or if the file cannot be found, skip merging
3827         if(empty($config_si_location) || !file_exists($config_si_location))
3828         {
3829            if($write_to_upgrade_log)
3830            {
3831               logThis('config_si.php file at (' . $config_si_location . ') could not be found.  Skip merging.', $path);
3832            }
3833            return false;
3834         } else {
3835            if($write_to_upgrade_log)
3836            {
3837               logThis('Loading config_si.php file at (' . $config_si_location . ') for merging.', $path);
3838            }
3839
3840            include($config_si_location);
3841            if(empty($sugar_config_si))
3842            {
3843               if($write_to_upgrade_log)
3844                   {
3845                      logThis('config_si.php contents are empty.  Skip merging.', $path);
3846                   }
3847                   return false;
3848            }
3849         }
3850
3851         //Now perform the merge operation
3852         $modified = false;
3853         foreach($sugar_config_si as $key=>$value)
3854         {
3855                 if(!preg_match('/^setup_/', $key) && !isset($sugar_config[$key]))
3856                 {
3857                    if($write_to_upgrade_log)
3858                    {
3859                       logThis('Merge key (' . $key . ') with value (' . $value . ')', $path);
3860                    }
3861                    $sugar_config[$key] = $value;
3862                    $modified = true;
3863                 }
3864         }
3865
3866         if($modified)
3867         {
3868                 if($write_to_upgrade_log)
3869                 {
3870                logThis('Update config.php file with new values', $path);
3871                 }
3872
3873             if(!write_array_to_file("sugar_config", $sugar_config, $config_location)) {
3874                if($write_to_upgrade_log)
3875                    {
3876                   logThis('*** ERROR: could not write to config.php', $path);
3877                    }
3878                    return false;
3879                 }
3880         } else {
3881            if($write_to_upgrade_log)
3882            {
3883               logThis('config.php values are in sync with config_si.php values.  Skipped merging.');
3884            }
3885            return false;
3886         }
3887
3888         if($write_to_upgrade_log)
3889         {
3890            logThis('End merge_config_si_settings', $path);
3891         }
3892         return true;
3893 }
3894
3895
3896 /**
3897  * upgrade_connectors
3898  *
3899  * This function handles support for upgrading connectors it is invoked from both end.php and silentUpgrade_step2.php
3900  *
3901  */
3902 function upgrade_connectors() {
3903     require_once('include/connectors/utils/ConnectorUtils.php');
3904     if(!ConnectorUtils::updateMetaDataFiles()) {
3905        $GLOBALS['log']->fatal('Cannot update metadata files for connectors');
3906     }
3907
3908     //Delete the custom connectors.php file if it exists so that it may be properly rebuilt
3909     if(file_exists('custom/modules/Connectors/metadata/connectors.php'))
3910     {
3911         unlink('custom/modules/Connectors/metadata/connectors.php');
3912     }
3913 }
3914
3915 /**
3916  * Enable the InsideView connector for the four default modules.
3917  */
3918 function upgradeEnableInsideViewConnector($path='')
3919 {
3920     logThis('Begin upgradeEnableInsideViewConnector', $path);
3921
3922     // Load up the existing mapping and hand it to the InsideView connector to have it setup the correct logic hooks
3923     $mapFile = 'modules/Connectors/connectors/sources/ext/rest/insideview/mapping.php';
3924     if ( file_exists('custom/'.$mapFile) ) {
3925         logThis('Found CUSTOM mappings', $path);
3926         require('custom/'.$mapFile);
3927     } else {
3928         logThis('Used default mapping', $path);
3929         require($mapFile);
3930     }
3931
3932     require_once('include/connectors/sources/SourceFactory.php');
3933     $source = SourceFactory::getSource('ext_rest_insideview');
3934
3935     // $mapping is brought in from the mapping.php file above
3936     $source->saveMappingHook($mapping);
3937
3938     require_once('include/connectors/utils/ConnectorUtils.php');
3939     ConnectorUtils::installSource('ext_rest_insideview');
3940
3941     // Now time to set the various modules to active, because this part ignores the default config
3942     require(CONNECTOR_DISPLAY_CONFIG_FILE);
3943     // $modules_sources come from that config file
3944     foreach ( $source->allowedModuleList as $module ) {
3945         $modules_sources[$module]['ext_rest_insideview'] = 'ext_rest_insideview';
3946     }
3947     if(!write_array_to_file('modules_sources', $modules_sources, CONNECTOR_DISPLAY_CONFIG_FILE)) {
3948         //Log error and return empty array
3949         logThis("Cannot write \$modules_sources to " . CONNECTOR_DISPLAY_CONFIG_FILE,$path);
3950     }
3951
3952     logThis('End upgradeEnableInsideViewConnector', $path);
3953
3954 }
3955
3956 function repair_long_relationship_names($path='')
3957 {
3958     logThis("Begin repair_long_relationship_names", $path);
3959     require_once 'modules/ModuleBuilder/parsers/relationships/DeployedRelationships.php' ;
3960     $GLOBALS['mi_remove_tables'] = false;
3961     $touched = array();
3962     foreach($GLOBALS['moduleList'] as $module)
3963     {
3964         $relationships = new DeployedRelationships ($module) ;
3965         foreach($relationships->getRelationshipList() as $rel_name)
3966         {
3967             if (strlen($rel_name) > 27 && empty($touched[$rel_name]))
3968             {
3969                 logThis("Rebuilding relationship fields for $rel_name", $path);
3970                 $touched[$rel_name] = true;
3971                 $rel_obj = $relationships->get($rel_name);
3972                 $rel_obj->setReadonly(false);
3973                 $relationships->delete($rel_name);
3974                 $relationships->save();
3975                 $relationships->add($rel_obj);
3976                 $relationships->save();
3977                 $relationships->build () ;
3978             }
3979         }
3980     }
3981     logThis("End repair_long_relationship_names", $path);
3982 }
3983
3984 function removeSilentUpgradeVarsCache(){
3985     global $silent_upgrade_vars_loaded;
3986
3987     $cacheFileDir = "{$GLOBALS['sugar_config']['cache_dir']}/silentUpgrader";
3988     $cacheFile = "{$cacheFileDir}/silentUpgradeCache.php";
3989
3990     if(file_exists($cacheFile)){
3991         unlink($cacheFile);
3992     }
3993
3994     $silent_upgrade_vars_loaded = array(); // Set to empty to reset it
3995
3996     return true;
3997 }
3998
3999 function loadSilentUpgradeVars(){
4000     global $silent_upgrade_vars_loaded;
4001
4002     if(empty($silent_upgrade_vars_loaded)){
4003         $cacheFile = "{$GLOBALS['sugar_config']['cache_dir']}/silentUpgrader/silentUpgradeCache.php";
4004         // We have no pre existing vars
4005         if(!file_exists($cacheFile)){
4006             // Set the vars array so it's loaded
4007             $silent_upgrade_vars_loaded = array('vars' => array());
4008         }
4009         else{
4010             require_once($cacheFile);
4011             $silent_upgrade_vars_loaded = $silent_upgrade_vars_cache;
4012         }
4013     }
4014
4015     return true;
4016 }
4017
4018 function writeSilentUpgradeVars(){
4019     global $silent_upgrade_vars_loaded;
4020
4021     if(empty($silent_upgrade_vars_loaded)){
4022         return false; // You should have set some values before trying to write the silent upgrade vars
4023     }
4024
4025     $cacheFileDir = "{$GLOBALS['sugar_config']['cache_dir']}/silentUpgrader";
4026     $cacheFile = "{$cacheFileDir}/silentUpgradeCache.php";
4027
4028     require_once('include/dir_inc.php');
4029     if(!mkdir_recursive($cacheFileDir)){
4030         return false;
4031     }
4032     require_once('include/utils/file_utils.php');
4033     if(!write_array_to_file('silent_upgrade_vars_cache', $silent_upgrade_vars_loaded, $cacheFile, 'w')){
4034         global $path;
4035         logThis("WARNING: writeSilentUpgradeVars could not write to {$cacheFile}", $path);
4036         return false;
4037     }
4038
4039     return true;
4040 }
4041
4042 function setSilentUpgradeVar($var, $value){
4043     if(!loadSilentUpgradeVars()){
4044         return false;
4045     }
4046
4047     global $silent_upgrade_vars_loaded;
4048
4049     $silent_upgrade_vars_loaded['vars'][$var] = $value;
4050
4051     return true;
4052 }
4053
4054 function getSilentUpgradeVar($var){
4055     if(!loadSilentUpgradeVars()){
4056         return false;
4057     }
4058
4059     global $silent_upgrade_vars_loaded;
4060
4061     if(!isset($silent_upgrade_vars_loaded['vars'][$var])){
4062         return null;
4063     }
4064     else{
4065         return $silent_upgrade_vars_loaded['vars'][$var];
4066     }
4067 }
4068
4069
4070 /**
4071  * add_unified_search_to_custom_modules_vardefs
4072  *
4073  * This method calls the repair code to remove the unified_search_modules.php fiel
4074  *
4075  */
4076 function add_unified_search_to_custom_modules_vardefs()
4077 {
4078         if(file_exists($cachefile = sugar_cached('modules/unified_search_modules.php')))
4079         {
4080            unlink($cachefile);
4081         }
4082
4083 }
4084
4085 /**
4086  * change from using the older SugarCache in 6.1 and below to the new one in 6.2
4087  */
4088 function upgradeSugarCache($file)
4089 {
4090         global $sugar_config;
4091         $cacheUploadUpgradesTemp = mk_temp_dir(sugar_cached('upgrades/temp'));
4092
4093         unzip($file, $cacheUploadUpgradesTemp);
4094
4095         if(!file_exists(clean_path("{$cacheUploadUpgradesTemp}/manifest.php"))) {
4096                 logThis("*** ERROR: no manifest file detected while bootstraping upgrade wizard files!");
4097                 return;
4098         } else {
4099                 include(clean_path("{$cacheUploadUpgradesTemp}/manifest.php"));
4100         }
4101
4102         $from_dir = "{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}";
4103         $allFiles = array();
4104         if(file_exists("$from_dir/include/SugarCache")) {
4105                 $allFiles = findAllFiles("$from_dir/include/SugarCache", $allFiles);
4106         }
4107         if(file_exists("$from_dir/include/database")) {
4108                 $allFiles = findAllFiles("$from_dir/include/database", $allFiles);
4109         }
4110         if(file_exists("$from_dir/include/utils/external_cache.php")) {
4111                 $allFiles[] = "$from_dir/include/utils/external_cache.php";
4112         }
4113         if(file_exists("$from_dir/include/utils/sugar_file_utils.php")) {
4114                 $allFiles[] = "$from_dir/include/utils/sugar_file_utils.php";
4115         }
4116         if(file_exists("$from_dir/include/utils/sugar_file_utils.php")) {
4117                 $allFiles[] = "$from_dir/include/utils/sugar_file_utils.php";
4118         }
4119
4120         foreach($allFiles as $k => $file) {
4121                 $destFile = str_replace($from_dir."/", "", $file);
4122        if(!is_dir(dirname($destFile))) {
4123                         mkdir_recursive(dirname($destFile)); // make sure the directory exists
4124                 }
4125                 if ( stristr($file,'uw_main.tpl') )
4126             logThis('Skipping "'.$file.'" - file copy will during commit step.');
4127         else {
4128             logThis('updating UpgradeWizard code: '.$destFile);
4129             copy_recursive($file, $destFile);
4130         }
4131         }
4132 }
4133
4134
4135 /**
4136  * upgradeDisplayedTabsAndSubpanels
4137  *
4138  * @param $version String value of current system version (pre upgrade)
4139  */
4140 function upgradeDisplayedTabsAndSubpanels($version)
4141 {
4142         if($version < '620')
4143         {
4144                 logThis('start upgrading system displayed tabs and subpanels');
4145             require_once('modules/MySettings/TabController.php');
4146             $tc = new TabController();
4147
4148             //grab the existing system tabs
4149             $tabs = $tc->get_tabs_system();
4150
4151             //add Calls, Meetings, Tasks, Notes, Prospects (Targets) and ProspectLists (Target Lists)
4152             //to displayed tabs unless explicitly set to hidden
4153             $modules_to_add = array('Calls', 'Meetings', 'Tasks', 'Notes', 'Prospects', 'ProspectLists');
4154             $added_tabs = array();
4155
4156             foreach($modules_to_add as $module)
4157             {
4158                        $tabs[0][$module] = $module;
4159                        $added_tabs[] = $module;
4160             }
4161
4162             logThis('calling set_system_tabs on TabController to add tabs: ' . var_export($added_tabs, true));
4163             $tc->set_system_tabs($tabs[0]);
4164             logThis('finish upgrading system displayed tabs and subpanels');
4165         }
4166 }
4167
4168
4169 /**
4170  * unlinkUpgradeFiles
4171  * This is a helper function to clean up
4172  *
4173  * @param $version String value of current system version (pre upgrade)
4174  */
4175 function unlinkUpgradeFiles($version)
4176 {
4177         if(!isset($version))
4178         {
4179            return;
4180         }
4181
4182     //First check if we even have the scripts_for_patch/files_to_remove directory
4183     require_once('modules/UpgradeWizard/UpgradeRemoval.php');
4184
4185     /*
4186     if(empty($_SESSION['unzip_dir']))
4187     {
4188         global $sugar_config;
4189         $base_upgrade_dir               = $sugar_config['upload_dir'] . "/upgrades";
4190         $base_tmp_upgrade_dir   = "$base_upgrade_dir/temp";
4191         $_SESSION['unzip_dir'] = mk_temp_dir( $base_tmp_upgrade_dir );
4192     }
4193     */
4194
4195     if(isset($_SESSION['unzip_dir']) && file_exists($_SESSION['unzip_dir'].'/scripts/files_to_remove'))
4196     {
4197        $files_to_remove = glob($_SESSION['unzip_dir'].'/scripts/files_to_remove/*.php');
4198
4199        foreach($files_to_remove as $script)
4200        {
4201                 if(preg_match('/UpgradeRemoval(\d+)x\.php/', $script, $matches))
4202                 {
4203                    $checkVersion = $matches[1] + 1; //Increment by one to check everything equal or below the target version
4204                    $upgradeClass = 'UpgradeRemoval' . $matches[1] . 'x';
4205                    require_once($_SESSION['unzip_dir'].'/scripts/files_to_remove/' . $upgradeClass . '.php');
4206
4207                    //Check to make sure we should load and run this UpgradeRemoval instance
4208                    if($checkVersion <= $version && class_exists($upgradeClass))
4209                    {
4210                           $upgradeInstance = new $upgradeClass();
4211                           if($upgradeInstance instanceof UpgradeRemoval)
4212                           {
4213                                   logThis('Running UpgradeRemoval instance ' . $upgradeClass);
4214                                   logThis('Files will be backed up to custom/backup');
4215                                   $files = $upgradeInstance->getFilesToRemove($version);
4216                                   foreach($files as $file)
4217                                   {
4218                                          logThis($file);
4219                                   }
4220                                   $upgradeInstance->processFilesToRemove($files);
4221                           }
4222                    }
4223             }
4224        }
4225     }
4226
4227     //Check if we have a custom directory
4228     if(file_exists('custom/scripts/files_to_remove'))
4229     {
4230        //Now find
4231        $files_to_remove = glob('custom/scripts/files_to_remove/*.php');
4232
4233        foreach($files_to_remove as $script)
4234        {
4235            if(preg_match('/\/files_to_remove\/(.*?)\.php$/', $script, $matches))
4236            {
4237                    require_once($script);
4238                    $upgradeClass  = $matches[1];
4239
4240                    if(!class_exists($upgradeClass))
4241                    {
4242                           continue;
4243                    }
4244
4245                    $upgradeInstance = new $upgradeClass();
4246                    if($upgradeInstance instanceof UpgradeRemoval)
4247                    {
4248                                   logThis('Running Custom UpgradeRemoval instance ' . $upgradeClass);
4249                                   $files = $upgradeInstance->getFilesToRemove($version);
4250                                   foreach($files as $file)
4251                                   {
4252                                          logThis($file);
4253                                   }
4254                                   $upgradeInstance->processFilesToRemove($files);
4255                    }
4256            }
4257        }
4258     }
4259
4260 }
4261
4262 if (!function_exists("getValidDBName"))
4263 {
4264     /*
4265      * Return a version of $proposed that can be used as a column name in any of our supported databases
4266      * 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)
4267      * @param string $name Proposed name for the column
4268      * @param string $ensureUnique
4269      * @return string Valid column name trimmed to right length and with invalid characters removed
4270      */
4271      function getValidDBName ($name, $ensureUnique = false, $maxLen = 30)
4272     {
4273         // first strip any invalid characters - all but alphanumerics and -
4274         $name = preg_replace ( '/[^\w-]+/i', '', $name ) ;
4275         $len = strlen ( $name ) ;
4276         $result = $name;
4277         if ($ensureUnique)
4278         {
4279             $md5str = md5($name);
4280             $tail = substr ( $name, -11) ;
4281             $temp = substr($md5str , strlen($md5str)-4 );
4282             $result = substr ( $name, 0, 10) . $temp . $tail ;
4283         }else if ($len > ($maxLen - 5))
4284         {
4285             $result = substr ( $name, 0, 11) . substr ( $name, 11 - $maxLen + 5);
4286         }
4287         return strtolower ( $result ) ;
4288     }
4289
4290
4291 }
4292
4293 /**
4294  * Get UW directories
4295  * Provides compatibility with both 6.3 and pre-6.3 setup
4296  */
4297 function getUWDirs()
4298 {
4299     if(!class_exists('UploadStream')) {
4300         // we're still running the old code
4301         global $sugar_config;
4302         return array($sugar_config['upload_dir'] . "/upgrades", $sugar_config['cache_dir'] . "upload/upgrades/temp");
4303     } else {
4304         if(!in_array("upload", stream_get_wrappers())) {
4305             UploadStream::register(); // just in case file was copied, but not run
4306         }
4307         return array("upload://upgrades", sugar_cached("upgrades/temp"));
4308     }
4309 }
4310
4311 /**
4312  * Whether directory exists within list of directories to skip
4313  * @param string $dir dir to be checked
4314  * @param array $skipDirs list with skipped dirs
4315  * @return boolean
4316  */
4317 function whetherNeedToSkipDir($dir, $skipDirs)
4318 {
4319     foreach($skipDirs as $skipMe) {
4320                 if(strpos( clean_path($dir), $skipMe ) !== false) {
4321                         return true;
4322                 }
4323         }
4324     return false;
4325 }
4326
4327
4328 /*
4329  * rebuildSprites
4330  * @param silentUpgrade boolean flag indicating whether or not we should treat running the SugarSpriteBuilder as an upgrade operation
4331  *
4332  */
4333 function rebuildSprites($fromUpgrade=true)
4334 {
4335     require_once('modules/Administration/SugarSpriteBuilder.php');
4336     $sb = new SugarSpriteBuilder();
4337     $sb->cssMinify = true;
4338     $sb->fromSilentUpgrade = $fromUpgrade;
4339     $sb->silentRun = $fromUpgrade;
4340
4341     // add common image directories
4342     $sb->addDirectory('default', 'include/images');
4343     $sb->addDirectory('default', 'themes/default/images');
4344     $sb->addDirectory('default', 'themes/default/images/SugarLogic');
4345
4346     // add all theme image directories
4347     if($dh = opendir('themes'))
4348     {
4349         while (($dir = readdir($dh)) !== false)
4350         {
4351             if ($dir != "." && $dir != ".." && $dir != 'default' && is_dir('themes/'.$dir)) {
4352                 $sb->addDirectory($dir, "themes/{$dir}/images");
4353             }
4354         }
4355         closedir($dh);
4356     }
4357
4358     // generate the sprite goodies
4359     // everything is saved into cache/sprites
4360     $sb->createSprites();
4361 }
4362
4363
4364 /**
4365  * repairSearchFields
4366  *
4367  * This method goes through the list of SearchFields files based and calls TemplateRange::repairCustomSearchFields
4368  * method on the files in an attempt to ensure the range search attributes are properly set in SearchFields.php.
4369  *
4370  * @param $globString String value used for glob search defaults to searching for all SearchFields.php files in modules directory
4371  * @param $path String value used to point to log file should logging be required.  Defaults to empty.
4372  *
4373  */
4374 function repairSearchFields($globString='modules/*/metadata/SearchFields.php', $path='')
4375 {
4376         if(!empty($path))
4377         {
4378                 logThis('Begin repairSearchFields', $path);
4379         }
4380
4381         require_once('include/dir_inc.php');
4382         require_once('modules/DynamicFields/templates/Fields/TemplateRange.php');
4383         require('include/modules.php');
4384
4385         global $beanList;
4386         $searchFieldsFiles = glob($globString);
4387
4388         foreach($searchFieldsFiles as $file)
4389         {
4390                 if(preg_match('/modules\/(.*?)\/metadata\/SearchFields\.php/', $file, $matches) && isset($beanList[$matches[1]]))
4391                 {
4392                         $module = $matches[1];
4393                         $beanName = $beanList[$module];
4394                         VardefManager::loadVardef($module, $beanName);
4395                         if(isset($GLOBALS['dictionary'][$beanName]['fields']))
4396                         {
4397                                 if(!empty($path))
4398                                 {
4399                                         logThis('Calling TemplateRange::repairCustomSearchFields for module ' . $module, $path);
4400                                 }
4401                                 TemplateRange::repairCustomSearchFields($GLOBALS['dictionary'][$beanName]['fields'], $module);
4402                         }
4403                 }
4404         }
4405
4406         if(!empty($path))
4407         {
4408                 logThis('End repairSearchFields', $path);
4409         }
4410 }
4411
4412 /**
4413  * repairUpgradeHistoryTable
4414  *
4415  * This is a helper function used in the upgrade process to fix upgrade_history entries so that the filename column points
4416  * to the new upload directory location introduced in 6.4 versions
4417  */
4418 function repairUpgradeHistoryTable()
4419 {
4420     require_once('modules/Configurator/Configurator.php');
4421     new Configurator();
4422     global $sugar_config;
4423
4424     //Now upgrade the upgrade_history table entries
4425     $results = $GLOBALS['db']->query('SELECT id, filename FROM upgrade_history');
4426     $upload_dir = $sugar_config['cache_dir'].'upload/';
4427
4428     //Create regular expression string to
4429     $match = '/^' . str_replace('/', '\/', $upload_dir) . '(.*?)$/';
4430
4431     while(($row = $GLOBALS['db']->fetchByAssoc($results)))
4432     {
4433         $file = str_replace('//', '/', $row['filename']); //Strip out double-paths that may exist
4434
4435         if(!empty($file) && preg_match($match, $file, $matches))
4436         {
4437             //Update new file location to use the new $sugar_config['upload_dir'] value
4438             $new_file_location = $sugar_config['upload_dir'] . $matches[1];
4439             $GLOBALS['db']->query("UPDATE upgrade_history SET filename = '{$new_file_location}' WHERE id = '{$row['id']}'");
4440         }
4441     }
4442
4443 }