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