]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - modules/UpgradeWizard/uw_utils.php
Release 6.4.0beta3
[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         // upgradeWizard
677         if(file_exists("$from_dir/modules/UpgradeWizard")) {
678                 $allFiles[] = findAllFiles("$from_dir/modules/UpgradeWizard", $allFiles);
679         }
680         // moduleInstaller
681         if(file_exists("$from_dir/ModuleInstall")) {
682                 $allFiles[] = findAllFiles("$from_dir/ModuleInstall", $allFiles);
683         }
684         if(file_exists("$from_dir/include/javascript/yui")) {
685                 $allFiles[] = findAllFiles("$from_dir/include/javascript/yui", $allFiles);
686         }
687         if(file_exists("$from_dir/HandleAjaxCall.php")) {
688                 $allFiles[] = "$from_dir/HandleAjaxCall.php";
689         }
690         if(file_exists("$from_dir/include/SugarTheme")) {
691                 $allFiles[] = findAllFiles("$from_dir/include/SugarTheme", $allFiles);
692         }
693         if(file_exists("$from_dir/include/SugarCache")) {
694                 $allFiles[] = findAllFiles("$from_dir/include/SugarCache", $allFiles);
695         }
696         if(file_exists("$from_dir/include/utils/external_cache.php")) {
697                 $allFiles[] = "$from_dir/include/utils/external_cache.php";
698         }
699         if(file_exists("$from_dir/include/upload_file.php")) {
700                 $allFiles[] = "$from_dir/include/upload_file.php";
701         }
702         if(file_exists("$from_dir/include/file_utils.php")) {
703                 $allFiles[] = "$from_dir/include/file_utils.php";
704         }
705         if(file_exists("$from_dir/include/upload_file.php")) {
706                 $allFiles[] = "$from_dir/include/upload_file.php";
707         }
708         if(file_exists("$from_dir/include/utils/sugar_file_utils.php")) {
709                 $allFiles[] = "$from_dir/include/utils/sugar_file_utils.php";
710         }
711     // users
712     if(file_exists("$from_dir/modules/Users")) {
713         $allFiles[] = findAllFiles("$from_dir/modules/Users", $allFiles);
714     }
715
716     upgradeUWFilesCopy($allFiles, $from_dir);
717 }
718
719 /**
720  * upgradeUWFilesCopy
721  *
722  * This function recursively copies files from the upgradeUWFiles Array
723  * @see upgradeUWFiles
724  *
725  * @param array $allFiles Array of files to copy over after zip file has been uploaded
726  * @param string $from_dir Source directory
727  */
728 function upgradeUWFilesCopy($allFiles, $from_dir)
729 {
730    foreach($allFiles as $file)
731    {
732        if(is_array($file))
733        {
734            upgradeUWFilesCopy($file, $from_dir);
735        } else {
736            $destFile = str_replace($from_dir."/", "", $file);
737            if(!is_dir(dirname($destFile))) {
738               mkdir_recursive(dirname($destFile)); // make sure the directory exists
739            }
740
741            if(stristr($file,'uw_main.tpl'))
742               logThis('Skipping "'.$file.'" - file copy will during commit step.');
743            else {
744               logThis('updating UpgradeWizard code: '.$destFile);
745               copy_recursive($file, $destFile);
746            }
747        }
748    }
749 }
750
751
752
753 /**
754  * gets valid patch file names that exist in upload/upgrade/patch/
755  */
756 function getValidPatchName($returnFull = true) {
757         global $base_upgrade_dir;
758         global $mod_strings;
759         global $uh;
760         global $sugar_version;
761     global $sugar_config;
762     $uh = new UpgradeHistory();
763     list($base_upgrade_dir, $base_tmp_upgrade_dir) = getUWDirs();
764     $return = array();
765
766         // scan for new files (that are not installed)
767         logThis('finding new files for upgrade');
768         $upgrade_content = '';
769         $upgrade_contents = findAllFiles($base_upgrade_dir, array(), false, 'zip');
770         //other variations of zip file i.e. ZIP, zIp,zIP,Zip,ZIp,ZiP
771         $ready = "<ul>\n";
772         $ready .= "
773                 <table>
774                         <tr>
775                                 <td></td>
776                                 <td align=left>
777                                         <b>{$mod_strings['LBL_ML_NAME']}</b>
778                                 </td>
779                                 <td align=left>
780                                         <b>{$mod_strings['LBL_ML_TYPE']}</b>
781                                 </td>
782                                 <td align=left>
783                                         <b>{$mod_strings['LBL_ML_VERSION']}</b>
784                                 </td>
785                                 <td align=left>
786                                         <b>{$mod_strings['LBL_ML_PUBLISHED']}</b>
787                                 </td>
788                                 <td align=left>
789                                         <b>{$mod_strings['LBL_ML_UNINSTALLABLE']}</b>
790                                 </td>
791                                 <td align=left>
792                                         <b>{$mod_strings['LBL_ML_DESCRIPTION']}</b>
793                                 </td>
794                         </tr>";
795         $disabled = '';
796
797         // assume old patches are there.
798         $upgradeToVersion = array(); // fill with valid patches - we will only use the latest qualified found patch
799
800         // cn: bug 10609 - notices for uninitialized variables
801         $icon = '';
802         $name = '';
803         $type = '';
804         $version = '';
805         $published_date = '';
806         $uninstallable = '';
807         $description = '';
808         $disabled = '';
809
810         foreach($upgrade_contents as $upgrade_content) {
811                 if(!preg_match("#.*\.zip\$#i", $upgrade_content)) {
812                         continue;
813                 }
814
815                 $the_base = basename($upgrade_content);
816                 $the_md5 = md5_file($upgrade_content);
817
818                 $md5_matches = $uh->findByMd5($the_md5);
819
820                 /* 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.
821                  * Edge-case: manual upgrade with a FTP of a patch; UH table has no entry for it.  Assume nothing. :( */
822                 if(0 == sizeof($md5_matches)) {
823                         $target_manifest = remove_file_extension( $upgrade_content ) . '-manifest.php';
824                         require_once($target_manifest);
825
826                         if(empty($manifest['version'])) {
827                                 logThis("*** Potential error: patch found with no version [ {$upgrade_content} ]");
828                                 continue;
829                         }
830                         if(!isset($manifest['type']) || $manifest['type'] != 'patch') {
831                                 logThis("*** Potential error: patch found with either no 'type' or non-patch type [ {$upgrade_content} ]");
832                                 continue;
833                         }
834
835                         $upgradeToVersion[$manifest['version']] = urlencode($upgrade_content);
836
837                         $name = empty($manifest['name']) ? $upgrade_content : $manifest['name'];
838                         $version = empty($manifest['version']) ? '' : $manifest['version'];
839                         $published_date = empty($manifest['published_date']) ? '' : $manifest['published_date'];
840                         $icon = '';
841                         $description = empty($manifest['description']) ? 'None' : $manifest['description'];
842                         $uninstallable = empty($manifest['is_uninstallable']) ? 'No' : 'Yes';
843                         $type = getUITextForType( $manifest['type'] );
844                         $manifest_type = $manifest['type'];
845
846                         if(empty($manifest['icon'])) {
847                                 $icon = getImageForType( $manifest['type'] );
848                         } else {
849                                 $path_parts = pathinfo( $manifest['icon'] );
850                                 $icon = "<!--not_in_theme!--><img src=\"" . remove_file_extension( $upgrade_content ) . "-icon." . $path_parts['extension'] . "\">";
851                         }
852             }
853         }
854
855         // cn: bug 10488 use the NEWEST upgrade/patch available when running upgrade wizard.
856         ksort($upgradeToVersion);
857         $upgradeToVersion = array_values($upgradeToVersion);
858         $newest = array_pop($upgradeToVersion);
859         $_SESSION['install_file'] = urldecode($newest); // in-case it was there from a prior.
860         logThis("*** UW using [ {$_SESSION['install_file']} ] as source for patch files.");
861
862         $cleanUpgradeContent = urlencode($_SESSION['install_file']);
863
864         // cn: 10606 - cannot upload a patch file since this returned always.
865         if(!empty($cleanUpgradeContent)) {
866                 $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";
867                 $ready .=<<<eoq
868                 <td>
869                                 <form action="index.php" method="post">
870                                         <input type="hidden" name="module" value="UpgradeWizard">
871                                         <input type="hidden" name="action" value="index">
872                                         <input type="hidden" name="step" value="{$_REQUEST['step']}">
873                                         <input type="hidden" name="run" value="delete">
874                                 <input type=hidden name="install_file" value="{$cleanUpgradeContent}" />
875                                 <input type=submit value="{$mod_strings['LBL_BUTTON_DELETE']}" />
876                                 </form>
877                         </td></table>
878 eoq;
879                 $disabled = "DISABLED";
880         }
881
882
883
884         if(empty($cleanUpgradeContent)){
885             $ready .= "<tr><td colspan='7'><i>None</i></td>\n";
886                 $ready .= "</table>\n";
887         }
888         $ready .= "<br></ul>\n";
889
890         $return['ready'] = $ready;
891         $return['disabled'] = $disabled;
892
893         if($returnFull) {
894                 return $return;
895         }
896 }
897
898
899 /**
900  * finalizes upgrade by setting upgrade versions in DB (config table) and sugar_version.php
901  * @return bool true on success
902  */
903 function updateVersions($version) {
904         global $db;
905         global $sugar_config;
906         global $path;
907
908         logThis('At updateVersions()... updating config table and sugar_version.php.', $path);
909
910         // handle file copy
911         if(isset($_SESSION['sugar_version_file']) && !empty($_SESSION['sugar_version_file'])) {
912                 if(!copy($_SESSION['sugar_version_file'], clean_path(getcwd().'/sugar_version.php'))) {
913                         logThis('*** ERROR: sugar_version.php could not be copied to destination! Cannot complete upgrade', $path);
914                         return false;
915                 } else {
916                         logThis('sugar_version.php successfully updated!', $path);
917                 }
918         } else {
919                 logThis('*** ERROR: no sugar_version.php file location found! - cannot complete upgrade...', $path);
920                 return false;
921         }
922
923         $q1 = "DELETE FROM config WHERE category = 'info' AND name = 'sugar_version'";
924         $q2 = "INSERT INTO config (category, name, value) VALUES ('info', 'sugar_version', '{$version}')";
925
926         logThis('Deleting old DB version info from config table.', $path);
927         $db->query($q1);
928
929         logThis('Inserting updated version info into config table.', $path);
930         $db->query($q2);
931
932         logThis('updateVersions() complete.', $path);
933         return true;
934 }
935
936
937
938 /**
939  * gets a module's lang pack - does not need to be a SugarModule
940  * @param lang string Language
941  * @param module string Path to language folder
942  * @return array mod_strings
943  */
944 function getModuleLanguagePack($lang, $module) {
945         $mod_strings = array();
946
947         if(!empty($lang) && !empty($module)) {
948                 $langPack = clean_path(getcwd().'/'.$module.'/language/'.$lang.'.lang.php');
949                 $langPackEn = clean_path(getcwd().'/'.$module.'/language/en_us.lang.php');
950
951                 if(file_exists($langPack))
952                         include_once($langPack);
953                 elseif(file_exists($langPackEn))
954                         include_once($langPackEn);
955         }
956
957         return $mod_strings;
958 }
959 /**
960  * checks system compliance for 4.5+ codebase
961  * @return array Mixed values
962  */
963 function checkSystemCompliance() {
964         global $sugar_config;
965         global $current_language;
966         global $db;
967         global $mod_strings;
968
969         if(!defined('SUGARCRM_MIN_MEM')) {
970                 define('SUGARCRM_MIN_MEM', 40);
971         }
972
973         $installer_mod_strings = getModuleLanguagePack($current_language, './install');
974         $ret = array();
975         $ret['error_found'] = false;
976
977         // PHP version
978         $php_version = constant('PHP_VERSION');
979         $check_php_version_result = check_php_version($php_version);
980
981         switch($check_php_version_result) {
982                 case -1:
983                         $ret['phpVersion'] = "<b><span class=stop>{$installer_mod_strings['ERR_CHECKSYS_PHP_INVALID_VER']} {$php_version} )</span></b>";
984                         $ret['error_found'] = true;
985                         break;
986                 case 0:
987                         $ret['phpVersion'] = "<b><span class=go>{$installer_mod_strings['ERR_CHECKSYS_PHP_UNSUPPORTED']} {$php_version} )</span></b>";
988                         break;
989                 case 1:
990                         $ret['phpVersion'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_PHP_OK']} {$php_version} )</span></b>";
991                         break;
992         }
993
994         // database and connect
995     $v = $db->version();
996         if($db->dbType == 'mysql')
997     {
998         if(version_compare($v, '4.1.2') < 0) {
999                         $ret['error_found'] = true;
1000                         $ret['mysqlVersion'] = "<b><span class=stop>".$mod_strings['ERR_UW_MYSQL_VERSION'].$v."</span></b>";
1001             }
1002         } elseif($db->dbType == 'oci8') {
1003             if(!preg_match("/Oracle9i|Oracle Database 10g|11/i", $v)) {
1004                         $ret['error_found'] = true;
1005                         $ret['ociVersion'] = "<b><span class=stop>".$mod_strings['ERR_UW_OCI8_VERSION'].$v."</span></b>";
1006             }
1007         }
1008
1009
1010         // XML Parsing
1011         if(function_exists('xml_parser_create')) {
1012                 $ret['xmlStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1013         } else {
1014                 $ret['xmlStatus'] = "<b><span class=stop>{$installer_mod_strings['LBL_CHECKSYS_NOT_AVAILABLE']}</span></b>";
1015                 $ret['error_found'] = true;
1016         }
1017
1018         // cURL
1019         if(function_exists('curl_init')) {
1020                 $ret['curlStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1021         } else {
1022                 $ret['curlStatus'] = "<b><span class=go>{$installer_mod_strings['ERR_CHECKSYS_CURL']}</span></b>";
1023                 $ret['error_found'] = false;
1024         }
1025
1026         // mbstrings
1027         if(function_exists('mb_strlen')) {
1028                 $ret['mbstringStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1029         } else {
1030                 $ret['mbstringStatus'] = "<b><span class=stop>{$installer_mod_strings['ERR_CHECKSYS_MBSTRING']}</span></b>";
1031                 $ret['error_found'] = true;
1032         }
1033
1034         // imap
1035         if(function_exists('imap_open')) {
1036                 $ret['imapStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1037         } else {
1038                 $ret['imapStatus'] = "<b><span class=go>{$installer_mod_strings['ERR_CHECKSYS_IMAP']}</span></b>";
1039                 $ret['error_found'] = false;
1040         }
1041
1042
1043         // safe mode
1044         if('1' == ini_get('safe_mode')) {
1045                 $ret['safeModeStatus'] = "<b><span class=stop>{$installer_mod_strings['ERR_CHECKSYS_SAFE_MODE']}</span></b>";
1046                 $ret['error_found'] = true;
1047         } else {
1048                 $ret['safeModeStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1049         }
1050
1051
1052         // call time pass by ref
1053     if('1' == ini_get('allow_call_time_pass_reference')) {
1054                 $ret['callTimeStatus'] = "<b><span class=stop>{$installer_mod_strings['ERR_CHECKSYS_CALL_TIME']}</span></b>";
1055                 //continue upgrading
1056         } else {
1057                 $ret['callTimeStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1058         }
1059
1060         // memory limit
1061         $ret['memory_msg']     = "";
1062         $memory_limit   = "-1";//ini_get('memory_limit');
1063         $sugarMinMem = constant('SUGARCRM_MIN_MEM');
1064         // logic based on: http://us2.php.net/manual/en/ini.core.php#ini.memory-limit
1065         if( $memory_limit == "" ){          // memory_limit disabled at compile time, no memory limit
1066             $ret['memory_msg'] = "<b><span class=\"go\">{$installer_mod_strings['LBL_CHECKSYS_MEM_OK']}</span></b>";
1067         } elseif( $memory_limit == "-1" ){   // memory_limit enabled, but set to unlimited
1068             $ret['memory_msg'] = "<b><span class=\"go\">{$installer_mod_strings['LBL_CHECKSYS_MEM_UNLIMITED']}</span></b>";
1069         } else {
1070             rtrim($memory_limit, 'M');
1071             $memory_limit_int = (int) $memory_limit;
1072             if( $memory_limit_int < constant('SUGARCRM_MIN_MEM') ){
1073                 $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>";
1074                         $ret['error_found'] = true;
1075             } else {
1076                         $ret['memory_msg'] = "<b><span class=\"go\">{$installer_mod_strings['LBL_CHECKSYS_OK']} ({$memory_limit})</span></b>";
1077             }
1078         }
1079
1080         /* mbstring.func_overload
1081         $ret['mbstring.func_overload'] = '';
1082         $mb = ini_get('mbstring.func_overload');
1083
1084         if($mb > 1) {
1085                 $ret['mbstring.func_overload'] = "<b><span class=\"stop\">{$mod_strings['ERR_UW_MBSTRING_FUNC_OVERLOAD']}</b>";
1086                 $ret['error_found'] = true;
1087         }
1088         */
1089         return $ret;
1090 }
1091
1092
1093 /**
1094  * is a file that we blow away automagically
1095  */
1096 function isAutoOverwriteFile($file) {
1097         $overwriteDirs = array(
1098                 './sugar_version.php',
1099                 './modules/UpgradeWizard/uw_main.tpl',
1100         );
1101         $file = trim('.'.str_replace(clean_path(getcwd()), '', $file));
1102
1103         if(in_array($file, $overwriteDirs)) {
1104                 return true;
1105         }
1106
1107         $fileExtension = substr(strrchr($file, "."), 1);
1108         if($fileExtension == 'tpl' || $fileExtension == 'html') {
1109                 return false;
1110         }
1111
1112         return true;
1113 }
1114
1115 /**
1116  * flatfile logger
1117  */
1118 function logThis($entry, $path='') {
1119         global $mod_strings;
1120         if(file_exists('include/utils/sugar_file_utils.php')){
1121                 require_once('include/utils/sugar_file_utils.php');
1122         }
1123                 $log = empty($path) ? clean_path(getcwd().'/upgradeWizard.log') : clean_path($path);
1124
1125                 // create if not exists
1126                 if(!file_exists($log)) {
1127                         if(function_exists('sugar_fopen')){
1128                                 $fp = @sugar_fopen($log, 'w+'); // attempts to create file
1129                      }
1130                      else{
1131                                 $fp = fopen($log, 'w+'); // attempts to create file
1132                      }
1133                         if(!is_resource($fp)) {
1134                                 $GLOBALS['log']->fatal('UpgradeWizard could not create the upgradeWizard.log file');
1135                                 die($mod_strings['ERR_UW_LOG_FILE_UNWRITABLE']);
1136                         }
1137                 } else {
1138                         if(function_exists('sugar_fopen')){
1139                                 $fp = @sugar_fopen($log, 'a+'); // write pointer at end of file
1140                      }
1141                      else{
1142                                 $fp = @fopen($log, 'a+'); // write pointer at end of file
1143                      }
1144
1145                         if(!is_resource($fp)) {
1146                                 $GLOBALS['log']->fatal('UpgradeWizard could not open/lock upgradeWizard.log file');
1147                                 die($mod_strings['ERR_UW_LOG_FILE_UNWRITABLE']);
1148                         }
1149                 }
1150
1151                 $line = date('r').' [UpgradeWizard] - '.$entry."\n";
1152
1153                 if(@fwrite($fp, $line) === false) {
1154                         $GLOBALS['log']->fatal('UpgradeWizard could not write to upgradeWizard.log: '.$entry);
1155                         die($mod_strings['ERR_UW_LOG_FILE_UNWRITABLE']);
1156                 }
1157
1158                 if(is_resource($fp)) {
1159                         fclose($fp);
1160                 }
1161 }
1162
1163 /**
1164         *  @params : none
1165         *  @author: nsingh
1166         *  @desc This function is to be used in the upgrade process to preserve changes/customaizations made to pre 5.1 quickcreate layout.
1167         *  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
1168         *  was automatically picked up by the quick create. [Addresses Bug 21469]
1169         *  This function will check if customizations were made, and will create quickcreatedefs.php in the /cutom/working/$module_name directory.
1170         **/
1171 function updateQuickCreateDefs(){
1172         $d = dir('modules');
1173         $studio_modules = array();
1174
1175         while($e = $d->read()){ //collect all studio modules.
1176                 if(substr($e, 0, 1) == '.' || !is_dir('modules/' . $e))continue;
1177                 if(file_exists('modules/' . $e . '/metadata/studio.php'))
1178                 {
1179                         array_push($studio_modules, $e);
1180                 }
1181         }
1182
1183         foreach( $studio_modules as $modname ){ //for each studio enabled module
1184                 //Check !exists modules/$modname/metadata/quickcreatedefs.php &&
1185                 //exists custom/$modname/editviewdefs.php (module was customized) &&
1186                 //!exists custom/$modname/quickcreateviewdefs.php
1187
1188                 $editviewdefs = "custom/working/modules/".$modname."/metadata/editviewdefs.php";
1189                 $quickcreatedefs = "custom/working/modules/".$modname."/metadata/quickcreatedefs.php";
1190
1191                 if ( !file_exists("modules/".$modname."/metadata/quickcreatedefs.php") &&
1192                          file_exists($editviewdefs) &&
1193                          !file_exists($quickcreatedefs) ){
1194                                 //clone editviewdef and save it in custom/working/modules/metadata
1195                                 $GLOBALS['log']->debug("Copying editviewdefs.php as quickcreatedefs.php for the $modname module in custom/working/modules/$modname/metadata!");
1196                                 if(copy( $editviewdefs, $quickcreatedefs)){
1197                                         if(file_exists($quickcreatedefs) && is_readable($quickcreatedefs)){
1198                                                 $file = file($quickcreatedefs);
1199                                                 //replace 'EditView' with 'QuickCreate'
1200                                                 $fp = fopen($quickcreatedefs,'w');
1201                                                 foreach($file as &$line){
1202                                                         if(preg_match('/^\s*\'EditView\'\s*=>\s*$/', $line) > 0){
1203                                                                 $line = "'QuickCreate' =>\n";
1204                                                         }
1205                                                         fwrite($fp, $line);
1206                                                 }
1207                                                 //write back.
1208                                                 fclose($fp);
1209                                         }
1210                                         else{
1211                                                 $GLOBALS['log']->debug("Failed to replace 'EditView' with QuickCreate because $quickcreatedefs is either not readable or does not exist.");
1212                                         }
1213                                 }else{
1214                                         $GLOBALS['log']->debug("Failed to copy $editviewdefs to $quickcreatedefs!");
1215                                 }
1216                 }
1217         }
1218 }
1219
1220 /**
1221  * test perms for CREATE queries
1222  */
1223 function testPermsCreate($db, $out) {
1224         logThis('Checking CREATE TABLE permissions...');
1225         global $mod_strings;
1226
1227         if(!$db->checkPrivilege("CREATE TABLE")) {
1228         logThis('cannot CREATE TABLE!');
1229                 $out['db']['dbNoCreate'] = true;
1230                 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_CREATE']}</span></td></tr>";
1231         }
1232     return $out;
1233 }
1234
1235 /**
1236  * test perms for INSERT
1237  */
1238 function testPermsInsert($db, $out, $skip=false) {
1239         logThis('Checking INSERT INTO permissions...');
1240         global $mod_strings;
1241
1242         if(!$db->checkPrivilege("INSERT")) {
1243                 logThis('cannot INSERT INTO!');
1244                 $out['db']['dbNoInsert'] = true;
1245                 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_INSERT']}</span></td></tr>";
1246     }
1247     return $out;
1248 }
1249
1250
1251 /**
1252  * test perms for UPDATE TABLE
1253  */
1254 function testPermsUpdate($db, $out, $skip=false) {
1255         logThis('Checking UPDATE TABLE permissions...');
1256         global $mod_strings;
1257         if(!$db->checkPrivilege("UPDATE")) {
1258                                         logThis('cannot UPDATE TABLE!');
1259                                         $out['db']['dbNoUpdate'] = true;
1260                                         $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_UPDATE']}</span></td></tr>";
1261     }
1262     return $out;
1263 }
1264
1265
1266 /**
1267  * test perms for SELECT
1268  */
1269 function testPermsSelect($db, $out, $skip=false) {
1270         logThis('Checking SELECT permissions...');
1271         global $mod_strings;
1272         if(!$db->checkPrivilege("SELECT")) {
1273                                 logThis('cannot SELECT!');
1274                                 $out['db']['dbNoSelect'] = true;
1275                                 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_SELECT']}</span></td></tr>";
1276     }
1277     return $out;
1278 }
1279
1280 /**
1281  * test perms for DELETE
1282  */
1283 function testPermsDelete($db, $out, $skip=false) {
1284         logThis('Checking DELETE FROM permissions...');
1285         global $mod_strings;
1286         if(!$db->checkPrivilege("DELETE")) {
1287                                 logThis('cannot DELETE FROM!');
1288                                 $out['db']['dbNoDelete'] = true;
1289                                 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_DELETE']}</span></td></tr>";
1290     }
1291     return $out;
1292 }
1293
1294
1295 /**
1296  * test perms for ALTER TABLE ADD COLUMN
1297  */
1298 function testPermsAlterTableAdd($db, $out, $skip=false) {
1299         logThis('Checking ALTER TABLE ADD COLUMN permissions...');
1300         global $mod_strings;
1301         if(!$db->checkPrivilege("ADD COLUMN")) {
1302                                 logThis('cannot ADD COLUMN!');
1303                                 $out['db']['dbNoAddColumn'] = true;
1304                                 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_ADD_COLUMN']}</span></td></tr>";
1305     }
1306     return $out;
1307 }
1308
1309 /**
1310  * test perms for ALTER TABLE ADD COLUMN
1311  */
1312 function testPermsAlterTableChange($db, $out, $skip=false) {
1313         logThis('Checking ALTER TABLE CHANGE COLUMN permissions...');
1314         global $mod_strings;
1315         if(!$db->checkPrivilege("CHANGE COLUMN")) {
1316                                 logThis('cannot CHANGE COLUMN!');
1317                                 $out['db']['dbNoChangeColumn'] = true;
1318                                 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_CHANGE_COLUMN']}</span></td></tr>";
1319     }
1320     return $out;
1321 }
1322
1323 /**
1324  * test perms for ALTER TABLE DROP COLUMN
1325  */
1326 function testPermsAlterTableDrop($db, $out, $skip=false) {
1327         logThis('Checking ALTER TABLE DROP COLUMN permissions...');
1328         global $mod_strings;
1329         if(!$db->checkPrivilege("DROP COLUMN")) {
1330                                 logThis('cannot DROP COLUMN!');
1331                                 $out['db']['dbNoDropColumn'] = true;
1332                                 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_DROP_COLUMN']}</span></td></tr>";
1333     }
1334     return $out;
1335 }
1336
1337
1338 /**
1339  * test perms for DROP TABLE
1340  */
1341 function testPermsDropTable($db, $out, $skip=false) {
1342         logThis('Checking DROP TABLE permissions...');
1343         global $mod_strings;
1344         if(!$db->checkPrivilege("DROP TABLE")) {
1345                                 logThis('cannot DROP TABLE!');
1346                                 $out['db']['dbNoDropTable'] = true;
1347                                 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_DROP_TABLE']}</span></td></tr>";
1348     }
1349     return $out;
1350 }
1351
1352 function getFormattedError($error, $query) {
1353         $error = "<div><b>".$error;
1354         $error .= "</b>::{$query}</div>";
1355
1356         return $error;
1357 }
1358
1359 /**
1360  * parses a query finding the table name
1361  * @param string query The query
1362  * @return string table The table
1363  */
1364 function getTableFromQuery($query) {
1365         $standardQueries = array('ALTER TABLE', 'DROP TABLE', 'CREATE TABLE', 'INSERT INTO', 'UPDATE', 'DELETE FROM');
1366         $query = preg_replace("/[^A-Za-z0-9\_\s]/", "", $query);
1367         $query = trim(str_replace($standardQueries, '', $query));
1368
1369         $firstSpc = strpos($query, " ");
1370         $end = ($firstSpc > 0) ? $firstSpc : strlen($query);
1371         $table = substr($query, 0, $end);
1372
1373         return $table;
1374 }
1375
1376 //prelicense check
1377
1378 function preLicenseCheck() {
1379         require_once('modules/UpgradeWizard/uw_files.php');
1380
1381         global $sugar_config;
1382         global $mod_strings;
1383         global $sugar_version;
1384
1385         if(!isset($sugar_version) || empty($sugar_version)) {
1386                 require_once('./sugar_version.php');
1387         }
1388
1389 if(!isset($_SESSION['unzip_dir']) || empty($_SESSION['unzip_dir'])) {
1390                 logThis('unzipping files in upgrade archive...');
1391                 $errors                                 = array();
1392                 list($base_upgrade_dir, $base_tmp_upgrade_dir) = getUWDirs();
1393                 $unzip_dir = '';
1394                 //also come up with mechanism to read from upgrade-progress file
1395                 if(!isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !is_file($_SESSION['install_file'])) {
1396                         if (file_exists(clean_path($base_tmp_upgrade_dir)) && $handle = opendir(clean_path($base_tmp_upgrade_dir))) {
1397                                 while (false !== ($file = readdir($handle))) {
1398                                 if($file !="." && $file !="..") {
1399                                          if(is_file($base_tmp_upgrade_dir."/".$file."/manifest.php")){
1400                                                 require_once($base_tmp_upgrade_dir."/".$file."/manifest.php");
1401                                                 $package_name= $manifest['copy_files']['from_dir'];
1402                                                 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")){
1403                                                         $unzip_dir = $base_tmp_upgrade_dir."/".$file;
1404                                                         if(file_exists("$base_upgrade_dir/patch/".$package_name.'.zip')){
1405                                                                 $_SESSION['install_file'] = $package_name.".zip";
1406                                                                 break;
1407                                                         }
1408                                                 }
1409                                           }
1410                                 }
1411                         }
1412                         }
1413                 }
1414         if(empty($_SESSION['install_file'])){
1415                 unlinkUWTempFiles();
1416                 resetUwSession();
1417                 echo 'Upload File not found so redirecting to Upgrade Start ';
1418                 $redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
1419                 echo '<form name="redirect" action="' .$redirect_new_wizard. '"  method="POST">';
1420 $upgrade_directories_not_found =<<<eoq
1421         <table cellpadding="3" cellspacing="0" border="0">
1422                 <tr>
1423                         <th colspan="2" align="left">
1424                                 <span class='error'><b>'Upload file missing or has been deleted. Refresh the page to go back to UpgradeWizard start'</b></span>
1425                         </th>
1426                 </tr>
1427         </table>
1428 eoq;
1429 $uwMain = $upgrade_directories_not_found;
1430                                 return '';
1431         }
1432                 $install_file                   = "$base_upgrade_dir/patch/".basename(urldecode( $_SESSION['install_file'] ));
1433                 $show_files                             = true;
1434                 if(empty($unzip_dir)){
1435                         $unzip_dir                              = mk_temp_dir( $base_tmp_upgrade_dir );
1436                 }
1437                 $zip_from_dir                   = ".";
1438                 $zip_to_dir                             = ".";
1439                 $zip_force_copy                 = array();
1440
1441                 if(!$unzip_dir){
1442                         logThis('Could not create a temporary directory using mk_temp_dir( $base_tmp_upgrade_dir )');
1443                         die($mod_strings['ERR_UW_NO_CREATE_TMP_DIR']);
1444                 }
1445
1446                 //double check whether unzipped .
1447                 if(file_exists($unzip_dir ."/scripts") && file_exists($unzip_dir."/manifest.php")){
1448                 //already unzipped
1449                 }
1450                 else{
1451                         unzip( $install_file, $unzip_dir );
1452                 }
1453
1454                 // assumption -- already validated manifest.php at time of upload
1455                 require_once( "$unzip_dir/manifest.php" );
1456
1457                 if( isset( $manifest['copy_files']['from_dir'] ) && $manifest['copy_files']['from_dir'] != "" ){
1458                     $zip_from_dir   = $manifest['copy_files']['from_dir'];
1459                 }
1460                 if( isset( $manifest['copy_files']['to_dir'] ) && $manifest['copy_files']['to_dir'] != "" ){
1461                     $zip_to_dir     = $manifest['copy_files']['to_dir'];
1462                 }
1463                 if( isset( $manifest['copy_files']['force_copy'] ) && $manifest['copy_files']['force_copy'] != "" ){
1464                     $zip_force_copy     = $manifest['copy_files']['force_copy'];
1465                 }
1466                 if( isset( $manifest['version'] ) ){
1467                     $version    = $manifest['version'];
1468                 }
1469                 if( !is_writable( "config.php" ) ){
1470                         return $mod_strings['ERR_UW_CONFIG'];
1471                 }
1472
1473                 $_SESSION['unzip_dir'] = clean_path($unzip_dir);
1474                 $_SESSION['zip_from_dir'] = clean_path($zip_from_dir);
1475                 logThis('unzip done.');
1476         } else {
1477                 $unzip_dir = $_SESSION['unzip_dir'];
1478                 $zip_from_dir = $_SESSION['zip_from_dir'];
1479         }
1480
1481     //check if $_SESSION['unzip_dir'] and $_SESSION['zip_from_dir'] exist
1482         if(!isset($_SESSION['unzip_dir']) || !file_exists($_SESSION['unzip_dir'])
1483                 || !isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !file_exists($_SESSION['install_file'])){
1484                     //redirect to start
1485             unlinkUWTempFiles();
1486                 resetUwSession();
1487                 echo 'Upload File not found so redirecting to Upgrade Start ';
1488                 $redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
1489                 echo '<form name="redirect" action="' .$redirect_new_wizard. '"  method="POST">';
1490 $upgrade_directories_not_found =<<<eoq
1491         <table cellpadding="3" cellspacing="0" border="0">
1492                 <tr>
1493                         <th colspan="2" align="left">
1494                                 <span class='error'><b>'Upload file missing or has been deleted. Refresh the page to go back to UpgradeWizard start'</b></span>
1495                         </th>
1496                 </tr>
1497         </table>
1498 eoq;
1499 $uwMain = $upgrade_directories_not_found;
1500                                 return '';
1501         }
1502
1503         $parserFiles = array();
1504
1505         if(file_exists(clean_path($unzip_dir.'/'.$zip_from_dir."/include/SugarFields"))) {
1506                 $parserFiles = findAllFiles(clean_path($unzip_dir.'/'.$zip_from_dir."/include/SugarFields"), $parserFiles);
1507         }
1508
1509      $cwd = clean_path(getcwd());
1510         foreach($parserFiles as $file) {
1511                 $srcFile = clean_path($file);
1512                 //$targetFile = clean_path(getcwd() . '/' . $srcFile);
1513         if (strpos($srcFile,".svn") !== false) {
1514                   //do nothing
1515             }
1516             else{
1517             $targetFile = str_replace(clean_path($unzip_dir.'/'.$zip_from_dir), $cwd, $srcFile);
1518
1519                 if(!is_dir(dirname($targetFile))) {
1520                         mkdir_recursive(dirname($targetFile)); // make sure the directory exists
1521                 }
1522
1523                 if(!file_exists($targetFile))
1524                  {
1525                         // handle sugar_version.php
1526                         // C.L. - Added check for portal directory
1527                         if(strpos($targetFile, 'sugar_version.php') !== false && !preg_match('/\/portal\/sugar_version\.php$/i', $targetFile)) {
1528                                 logThis('Skipping "sugar_version.php" - file copy will occur at end of successful upgrade', $path);
1529                                 $_SESSION['sugar_version_file'] = $srcFile;
1530                                 continue;
1531                         }
1532
1533                         if(!copy($srcFile, $targetFile)) {
1534                                 logThis('*** ERROR: could not copy file: ' . $targetFile);
1535                         } else {
1536                                 $copiedFiles[] = $targetFile;
1537                         }
1538                 }
1539            }
1540          }
1541
1542     //Also copy the SugarMerge files
1543         if(file_exists(clean_path($unzip_dir.'/'.$zip_from_dir."/UpgradeWizard510Files"))) {
1544                 $parserFiles = findAllFiles(clean_path($unzip_dir.'/'.$zip_from_dir."/UpgradeWizard510Files"), $parserFiles);
1545                 foreach($parserFiles as $file) {
1546                         $srcFile = clean_path($file);
1547                 if (strpos($srcFile,".svn") !== false) {
1548                           //do nothing
1549                     } else {
1550                             $targetFile = str_replace(clean_path($unzip_dir.'/'.$zip_from_dir."/UpgradeWizard510Files"), $cwd, $srcFile);
1551                                 if(!is_dir(dirname($targetFile))) {
1552                                         mkdir_recursive(dirname($targetFile)); // make sure the directory exists
1553                                 }
1554                                 logThis('updating UpgradeWizard code: '.$targetFile);
1555                                 copy_recursive($file, $targetFile);
1556                     }
1557                 }
1558     }
1559     logThis ('is SugarConfig there '.file_exists(clean_path($unzip_dir.'/'.$zip_from_dir."/include/SugarObjects/SugarConfig.php")));
1560         if(file_exists(clean_path($unzip_dir.'/'.$zip_from_dir."/include/SugarObjects/SugarConfig.php"))) {
1561                 $file = clean_path($unzip_dir.'/'.$zip_from_dir."/include/SugarObjects/SugarConfig.php");
1562                 $destFile = str_replace(clean_path($unzip_dir.'/'.$zip_from_dir), $cwd, $file);
1563                 if(!is_dir(dirname($destFile))) {
1564                         mkdir_recursive(dirname($destFile)); // make sure the directory exists
1565                 }
1566         copy($file,$destFile);
1567         //also copy include utils array utils
1568         $file = clean_path($unzip_dir.'/'.$zip_from_dir."/include/utils/array_utils.php");
1569                 $destFile = str_replace(clean_path($unzip_dir.'/'.$zip_from_dir), $cwd, $file);
1570                 if(!is_dir(dirname($destFile))) {
1571                         mkdir_recursive(dirname($destFile)); // make sure the directory exists
1572                 }
1573         copy($file,$destFile);
1574         }
1575 }
1576
1577
1578 function preflightCheck() {
1579         require_once('modules/UpgradeWizard/uw_files.php');
1580
1581         global $sugar_config;
1582         global $mod_strings;
1583         global $sugar_version;
1584
1585         if(!isset($sugar_version) || empty($sugar_version)) {
1586                 require_once('./sugar_version.php');
1587         }
1588
1589         unset($_SESSION['rebuild_relationships']);
1590         unset($_SESSION['rebuild_extensions']);
1591
1592         // don't bother if are rechecking
1593         $manualDiff                     = array();
1594         if(!isset($_SESSION['unzip_dir']) || empty($_SESSION['unzip_dir'])) {
1595                 logThis('unzipping files in upgrade archive...');
1596                 $errors                                 = array();
1597                 list($base_upgrade_dir, $base_tmp_upgrade_dir) = getUWDirs();
1598                 $unzip_dir = '';
1599                 //Following is if User logged out unexpectedly and then logged into UpgradeWizard again.
1600                 //also come up with mechanism to read from upgrade-progress file.
1601                 if(!isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !is_file($_SESSION['install_file'])) {
1602                         if (file_exists($base_tmp_upgrade_dir) && $handle = opendir($base_tmp_upgrade_dir)) {
1603                         while (false !== ($file = readdir($handle))) {
1604                                 if($file !="." && $file !="..") {
1605                                          if(is_file($base_tmp_upgrade_dir."/".$file."/manifest.php")){
1606                                                 require_once($base_tmp_upgrade_dir."/".$file."/manifest.php");
1607                                                 $package_name= $manifest['copy_files']['from_dir'];
1608                                                 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")){
1609                                                         $unzip_dir = $base_tmp_upgrade_dir."/".$file;
1610                                                         if(file_exists("$base_upgrade_dir/patch/".$package_name.'.zip')){
1611                                                                 $_SESSION['install_file'] = $package_name.".zip";
1612                                                                 break;
1613                                                         }
1614                                                 }
1615                                           }
1616                                 }
1617                         }
1618                         }
1619                 }
1620         if(empty($_SESSION['install_file'])){
1621                 unlinkUWTempFiles();
1622                 resetUwSession();
1623                 echo 'Upload File not found so redirecting to Upgrade Start ';
1624                 $redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
1625                 echo '<form name="redirect" action="' .$redirect_new_wizard. '"  method="POST">';
1626 $upgrade_directories_not_found =<<<eoq
1627         <table cellpadding="3" cellspacing="0" border="0">
1628                 <tr>
1629                         <th colspan="2" align="left">
1630                                 <span class='error'><b>'Upload file missing or has been deleted. Refresh the page to go back to UpgradeWizard start'</b></span>
1631                         </th>
1632                 </tr>
1633         </table>
1634 eoq;
1635 $uwMain = $upgrade_directories_not_found;
1636                                 return '';
1637
1638         }
1639                 $install_file                   = "$base_upgrade_dir/patch/".basename(urldecode( $_SESSION['install_file'] ));
1640                 $show_files                             = true;
1641                 if(empty($unzip_dir)){
1642                         $unzip_dir                              = mk_temp_dir( $base_tmp_upgrade_dir );
1643                 }
1644                 $zip_from_dir                   = ".";
1645                 $zip_to_dir                             = ".";
1646                 $zip_force_copy                 = array();
1647
1648                 if(!$unzip_dir){
1649                         logThis('Could not create a temporary directory using mk_temp_dir( $base_tmp_upgrade_dir )');
1650                         die($mod_strings['ERR_UW_NO_CREATE_TMP_DIR']);
1651                 }
1652
1653                 //double check whether unzipped .
1654                 if(file_exists($unzip_dir ."/scripts") && file_exists($unzip_dir."/manifest.php")){
1655                 //already unzipped
1656                 }
1657                 else{
1658                         unzip( $install_file, $unzip_dir );
1659                 }
1660
1661                 // assumption -- already validated manifest.php at time of upload
1662                 require_once( "$unzip_dir/manifest.php" );
1663
1664                 if( isset( $manifest['copy_files']['from_dir'] ) && $manifest['copy_files']['from_dir'] != "" ){
1665                     $zip_from_dir   = $manifest['copy_files']['from_dir'];
1666                 }
1667                 if( isset( $manifest['copy_files']['to_dir'] ) && $manifest['copy_files']['to_dir'] != "" ){
1668                     $zip_to_dir     = $manifest['copy_files']['to_dir'];
1669                 }
1670                 if( isset( $manifest['copy_files']['force_copy'] ) && $manifest['copy_files']['force_copy'] != "" ){
1671                     $zip_force_copy     = $manifest['copy_files']['force_copy'];
1672                 }
1673                 if( isset( $manifest['version'] ) ){
1674                     $version    = $manifest['version'];
1675                 }
1676                 if( !is_writable( "config.php" ) ){
1677                         return $mod_strings['ERR_UW_CONFIG'];
1678                 }
1679
1680                 $_SESSION['unzip_dir'] = clean_path($unzip_dir);
1681                 $_SESSION['zip_from_dir'] = clean_path($zip_from_dir);
1682
1683          //logThis('unzip done.');
1684         } else {
1685                 $unzip_dir = $_SESSION['unzip_dir'];
1686                 $zip_from_dir = $_SESSION['zip_from_dir'];
1687         }
1688         //check if $_SESSION['unzip_dir'] and $_SESSION['zip_from_dir'] exist
1689         if(!isset($_SESSION['unzip_dir']) || !file_exists($_SESSION['unzip_dir'])
1690                 || !isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !file_exists($_SESSION['install_file'])){
1691                     //redirect to start
1692             unlinkUWTempFiles();
1693                 resetUwSession();
1694                 echo 'Upload File not found so redirecting to Upgrade Start ';
1695                 $redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
1696                 echo '<form name="redirect" action="' .$redirect_new_wizard. '"  method="POST">';
1697 $upgrade_directories_not_found =<<<eoq
1698         <table cellpadding="3" cellspacing="0" border="0">
1699                 <tr>
1700                         <th colspan="2" align="left">
1701                                 <span class='error'><b>'Upload file missing or has been deleted. Refresh the page to go back to UpgradeWizard start'</b></span>
1702                         </th>
1703                 </tr>
1704         </table>
1705 eoq;
1706 $uwMain = $upgrade_directories_not_found;
1707                                 return '';
1708         }
1709         //copy minimum required files
1710         fileCopy('include/utils/sugar_file_utils.php');
1711
1712         $upgradeFiles = findAllFiles(clean_path("$unzip_dir/$zip_from_dir"), array());
1713         $cache_html_files= array();
1714
1715         // get md5 sums
1716         $md5_string = array();
1717         if(file_exists(clean_path(getcwd().'/files.md5'))){
1718                 require(clean_path(getcwd().'/files.md5'));
1719         }
1720
1721         // file preflight checks
1722         logThis('verifying md5 checksums for files...');
1723         foreach($upgradeFiles as $file) {
1724                 if(in_array(str_replace(clean_path("$unzip_dir/$zip_from_dir") . "/", '', $file), $uw_files))
1725                         continue; // skip already loaded files
1726
1727                 if(strpos($file, '.md5'))
1728                         continue; // skip md5 file
1729
1730                 // normalize file paths
1731                 $file = clean_path($file);
1732
1733                 // check that we can move/delete the upgraded file
1734                 if(!is_writable($file)) {
1735                         $errors[] = $mod_strings['ERR_UW_FILE_NOT_WRITABLE'].": ".$file;
1736                 }
1737                 // check that destination files are writable
1738                 $destFile = getcwd().str_replace(clean_path($unzip_dir.'/'.$zip_from_dir), '', $file);
1739
1740                 if(is_file($destFile)) { // of course it needs to exist first...
1741                         if(!is_writable($destFile)) {
1742                                 $errors[] = $mod_strings['ERR_UW_FILE_NOT_WRITABLE'].": ".$destFile;
1743                         }
1744                 }
1745
1746                 ///////////////////////////////////////////////////////////////////////
1747                 ////    DIFFS
1748                 // compare md5s and build up a manual merge list
1749                 $targetFile = clean_path(".".str_replace(getcwd(),'',$destFile));
1750                 $targetMd5 = '0';
1751                 if(is_file($destFile)) {
1752                         if(strpos($targetFile, '.php')) {
1753                                 // handle PHP files that were hit with the security regex
1754                                 $fp = '';
1755                                 if(function_exists('sugar_fopen')){
1756                                         $fp = sugar_fopen($destFile, 'r');
1757                                 }
1758                                 else{
1759                                         $fp = fopen($destFile, 'r');
1760                                 }
1761                                 $filesize = filesize($destFile);
1762                                 if($filesize > 0) {
1763                                         $fileContents = stream_get_contents($fp);
1764                                         $targetMd5 = md5($fileContents);
1765                                 }
1766                         } else {
1767                                 $targetMd5 = md5_file($destFile);
1768                         }
1769                 }
1770
1771                 if(isset($md5_string[$targetFile]) && $md5_string[$targetFile] != $targetMd5) {
1772                         logThis('found a file with a differing md5: ['.$targetFile.']');
1773                         $manualDiff[] = $destFile;
1774                 }
1775                 ////    END DIFFS
1776                 ///////////////////////////////////////////////////////////////////////
1777         }
1778         logThis('md5 verification done.');
1779         $errors['manual'] = $manualDiff;
1780
1781         return $errors;
1782 }
1783
1784 function fileCopy($file_path){
1785         if(file_exists(clean_path($_SESSION['unzip_dir'].'/'.$_SESSION['zip_from_dir'].'/'.$file_path))) {
1786                 $file = clean_path($_SESSION['unzip_dir'].'/'.$_SESSION['zip_from_dir'].'/'.$file_path);
1787                 $destFile = str_replace(clean_path($_SESSION['unzip_dir'].'/'.$_SESSION['zip_from_dir']),  clean_path(getcwd()), $file);
1788         if(!is_dir(dirname($destFile))) {
1789                 mkdir_recursive(dirname($destFile)); // make sure the directory exists
1790                 }
1791                 copy_recursive($file,$destFile);
1792         }
1793 }
1794 function getChecklist($steps, $step) {
1795         global $mod_strings;
1796
1797         $skip = array('start', 'cancel', 'uninstall','end');
1798         $j=0;
1799         $i=1;
1800         $ret  = '<table cellpadding="3" cellspacing="4" border="0">';
1801         $ret .= '<tr><th colspan="3" align="left">'.$mod_strings['LBL_UW_CHECKLIST'].':</th></tr>';
1802         foreach($steps['desc'] as $k => $desc) {
1803                 if(in_array($steps['files'][$j], $skip)) {
1804                         $j++;
1805                         continue;
1806                 }
1807
1808                 //$status = "<span class='error'>{$mod_strings['LBL_UW_INCOMPLETE']}</span>";
1809                 $desc_mod_pre = '';
1810                 $desc_mod_post = '';
1811                 /*
1812                 if(isset($_SESSION['step'][$steps['files'][$k]]) && $_SESSION['step'][$steps['files'][$k]] == 'success') {
1813                         //$status = $mod_strings['LBL_UW_COMPLETE'];
1814                 }
1815                 */
1816
1817                 if($k == $_REQUEST['step']) {
1818                         //$status = $mod_strings['LBL_UW_IN_PROGRESS'];
1819                         $desc_mod_pre = "<font color=blue><i>";
1820                         $desc_mod_post = "</i></font>";
1821                 }
1822
1823                 $ret .= "<tr><td>&nbsp;</td><td><b>{$i}: {$desc_mod_pre}{$desc}{$desc_mod_post}</b></td>";
1824                 $ret .= "<td id={$steps['files'][$j]}><i></i></td></tr>";
1825                 $i++;
1826                 $j++;
1827         }
1828         $ret .= "</table>";
1829         return $ret;
1830 }
1831
1832 function prepSystemForUpgrade() {
1833         global $sugar_config;
1834         global $sugar_flavor;
1835         global $mod_strings;
1836         global $subdirs;
1837         global $base_upgrade_dir;
1838         global $base_tmp_upgrade_dir;
1839     list($p_base_upgrade_dir, $p_base_tmp_upgrade_dir) = getUWDirs();
1840         ///////////////////////////////////////////////////////////////////////////////
1841         ////    Make sure variables exist
1842         if(empty($base_upgrade_dir)){
1843                 $base_upgrade_dir       = $p_base_upgrade_dir;
1844         }
1845         if(empty($base_tmp_upgrade_dir)){
1846                 $base_tmp_upgrade_dir   = $p_base_tmp_upgrade_dir;
1847         }
1848         sugar_mkdir($base_tmp_upgrade_dir, 0775, true);
1849         if(!isset($subdirs) || empty($subdirs)){
1850                 $subdirs = array('full', 'langpack', 'module', 'patch', 'theme');
1851         }
1852
1853     $upgrade_progress_dir = $base_tmp_upgrade_dir;
1854     $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
1855     if(file_exists($upgrade_progress_file)){
1856         if(function_exists('get_upgrade_progress') && function_exists('didThisStepRunBefore')){
1857                 if(didThisStepRunBefore('end')){
1858                         include($upgrade_progress_file);
1859                         unset($upgrade_config);
1860                         unlink($upgrade_progress_file);
1861                 }
1862         }
1863     }
1864
1865     // increase the cuttoff time to 1 hour
1866         ini_set("max_execution_time", "3600");
1867
1868     // make sure dirs exist
1869         if($subdirs != null){
1870                 foreach($subdirs as $subdir) {
1871                     sugar_mkdir("$base_upgrade_dir/$subdir", 0775, true);
1872                 }
1873         }
1874         // array of special scripts that are executed during (un)installation-- key is type of script, value is filename
1875         if(!defined('SUGARCRM_PRE_INSTALL_FILE')) {
1876                 define('SUGARCRM_PRE_INSTALL_FILE', 'scripts/pre_install.php');
1877                 define('SUGARCRM_POST_INSTALL_FILE', 'scripts/post_install.php');
1878                 define('SUGARCRM_PRE_UNINSTALL_FILE', 'scripts/pre_uninstall.php');
1879                 define('SUGARCRM_POST_UNINSTALL_FILE', 'scripts/post_uninstall.php');
1880         }
1881
1882         $script_files = array(
1883                 "pre-install" => constant('SUGARCRM_PRE_INSTALL_FILE'),
1884                 "post-install" => constant('SUGARCRM_POST_INSTALL_FILE'),
1885                 "pre-uninstall" => constant('SUGARCRM_PRE_UNINSTALL_FILE'),
1886                 "post-uninstall" => constant('SUGARCRM_POST_UNINSTALL_FILE'),
1887         );
1888
1889         // check that the upload limit is set to 6M or greater
1890         define('SUGARCRM_MIN_UPLOAD_MAX_FILESIZE_BYTES', 6 * 1024 * 1024);  // 6 Megabytes
1891         $upload_max_filesize = ini_get('upload_max_filesize');
1892         $upload_max_filesize_bytes = return_bytes($upload_max_filesize);
1893
1894         if($upload_max_filesize_bytes < constant('SUGARCRM_MIN_UPLOAD_MAX_FILESIZE_BYTES')) {
1895                 $GLOBALS['log']->debug("detected upload_max_filesize: $upload_max_filesize");
1896
1897                 echo '<p class="error">'.$mod_strings['MSG_INCREASE_UPLOAD_MAX_FILESIZE'].' '.get_cfg_var('cfg_file_path')."</p>\n";
1898         }
1899 }
1900
1901 if ( !function_exists('extractFile') ) {
1902 function extractFile($zip_file, $file_in_zip) {
1903     global $base_tmp_upgrade_dir;
1904
1905         // strip cwd
1906         $absolute_base_tmp_upgrade_dir = clean_path($base_tmp_upgrade_dir);
1907         $relative_base_tmp_upgrade_dir = clean_path(str_replace(clean_path(getcwd()), '', $absolute_base_tmp_upgrade_dir));
1908
1909     // mk_temp_dir expects relative pathing
1910     $my_zip_dir = mk_temp_dir($relative_base_tmp_upgrade_dir);
1911
1912     unzip_file($zip_file, $file_in_zip, $my_zip_dir);
1913
1914     return("$my_zip_dir/$file_in_zip");
1915 }
1916 }
1917
1918 if ( !function_exists('extractManifest') ) {
1919 function extractManifest($zip_file) {
1920         logThis('extracting manifest.');
1921     return(extractFile($zip_file, "manifest.php"));
1922 }
1923 }
1924
1925 if ( !function_exists('getInstallType') ) {
1926 function getInstallType($type_string) {
1927     // detect file type
1928     global $subdirs;
1929         $subdirs = array('full', 'langpack', 'module', 'patch', 'theme', 'temp');
1930     foreach($subdirs as $subdir) {
1931         if(preg_match("#/$subdir/#", $type_string)) {
1932             return($subdir);
1933         }
1934     }
1935     // return empty if no match
1936     return("");
1937 }
1938 }
1939
1940 function getImageForType($type) {
1941     global $image_path;
1942     global $mod_strings;
1943
1944     $icon = "";
1945     switch($type) {
1946         case "full":
1947             $icon = SugarThemeRegistry::current()->getImage("Upgrade", "",null,null,'.gif',$mod_strings['LBL_UPGRADE']);
1948             break;
1949         case "langpack":
1950             $icon = SugarThemeRegistry::current()->getImage("LanguagePacks", "",null,null,'.gif',$mod_strings['LBL_LANGPACKS']);
1951             break;
1952         case "module":
1953             $icon = SugarThemeRegistry::current()->getImage("ModuleLoader", "",null,null,'.gif',$mod_strings['LBL_MODULELOADER']);
1954             break;
1955         case "patch":
1956             $icon = SugarThemeRegistry::current()->getImage("PatchUpgrades", "",null,null,'.gif',$mod_strings['LBL_PATCHUPGRADES']);
1957             break;
1958         case "theme":
1959             $icon = SugarThemeRegistry::current()->getImage("Themes", "",null,null,'.gif',$mod_strings['LBL_THEMES']);
1960             break;
1961         default:
1962             break;
1963     }
1964     return($icon);
1965 }
1966
1967 if ( !function_exists('getLanguagePackName') ) {
1968 function getLanguagePackName($the_file) {
1969     require_once("$the_file");
1970     if(isset($app_list_strings["language_pack_name"])) {
1971         return($app_list_strings["language_pack_name"]);
1972     }
1973     return("");
1974 }
1975 }
1976
1977 function getUITextForType($type) {
1978     if($type == "full") {
1979         return("Full Upgrade");
1980     }
1981     if($type == "langpack") {
1982         return("Language Pack");
1983     }
1984     if($type == "module") {
1985         return("Module");
1986     }
1987     if($type == "patch") {
1988         return("Patch");
1989     }
1990     if($type == "theme") {
1991         return("Theme");
1992     }
1993 }
1994
1995 if ( !function_exists('validate_manifest') ) {
1996 /**
1997  * Verifies a manifest from a patch or module to be compatible with the current Sugar version and flavor
1998  * @param array manifest Standard manifest array
1999  * @return string Error message, blank on success
2000  */
2001 function validate_manifest($manifest) {
2002         logThis('validating manifest.php file');
2003     // takes a manifest.php manifest array and validates contents
2004     global $subdirs;
2005     global $sugar_version;
2006     global $sugar_flavor;
2007         global $mod_strings;
2008
2009     if(!isset($manifest['type'])) {
2010         return $mod_strings['ERROR_MANIFEST_TYPE'];
2011     }
2012
2013     $type = $manifest['type'];
2014
2015     if(getInstallType("/$type/") == "") {
2016                 return $mod_strings['ERROR_PACKAGE_TYPE']. ": '" . $type . "'.";
2017     }
2018
2019     if(isset($manifest['acceptable_sugar_versions'])) {
2020         $version_ok = false;
2021         $matches_empty = true;
2022         if(isset($manifest['acceptable_sugar_versions']['exact_matches'])) {
2023             $matches_empty = false;
2024             foreach($manifest['acceptable_sugar_versions']['exact_matches'] as $match) {
2025                 if($match == $sugar_version) {
2026                     $version_ok = true;
2027                 }
2028             }
2029         }
2030         if(!$version_ok && isset($manifest['acceptable_sugar_versions']['regex_matches'])) {
2031             $matches_empty = false;
2032             foreach($manifest['acceptable_sugar_versions']['regex_matches'] as $match) {
2033                 if(preg_match("/$match/", $sugar_version)) {
2034                     $version_ok = true;
2035                 }
2036             }
2037         }
2038
2039         if(!$matches_empty && !$version_ok) {
2040             return $mod_strings['ERROR_VERSION_INCOMPATIBLE']."<br />".
2041             $mod_strings['ERR_UW_VERSION'].$sugar_version;
2042         }
2043     }
2044
2045     if(isset($manifest['acceptable_sugar_flavors']) && sizeof($manifest['acceptable_sugar_flavors']) > 0) {
2046         $flavor_ok = false;
2047         foreach($manifest['acceptable_sugar_flavors'] as $match) {
2048             if($match == $sugar_flavor) {
2049                 $flavor_ok = true;
2050             }
2051         }
2052         if(!$flavor_ok) {
2053             return $mod_strings['ERROR_FLAVOR_INCOMPATIBLE']."<br />".
2054             $mod_strings['ERR_UW_FLAVOR'].$sugar_flavor."<br />".
2055             $mod_strings['ERR_UW_FLAVOR_2'].$manifest['acceptable_sugar_flavors'][0];
2056         }
2057     }
2058
2059     return '';
2060 }
2061 }
2062
2063 function unlinkUploadFiles() {
2064         return;
2065 //      logThis('at unlinkUploadFiles()');
2066 //
2067 //      if(isset($_SESSION['install_file']) && !empty($_SESSION['install_file'])) {
2068 //              $upload = $_SESSION['install_file'];
2069 //
2070 //              if(is_file($upload)) {
2071 //                      logThis('unlinking ['.$upload.']');
2072 //                      @unlink($upload);
2073 //              }
2074 //      }
2075 }
2076
2077 /**
2078  * deletes files created by unzipping a package
2079  */
2080 function unlinkUWTempFiles() {
2081         global $sugar_config;
2082         global $path;
2083
2084         logThis('at unlinkUWTempFiles()');
2085         $tempDir='';
2086         list($upgDir, $tempDir) = getUWDirs();
2087
2088     if(file_exists($tempDir) && is_dir($tempDir)){
2089                 $files = findAllFiles($tempDir, array(), false);
2090                 rsort($files);
2091                 foreach($files as $file) {
2092                         if(!is_dir($file)) {
2093                                 //logThis('unlinking ['.$file.']', $path);
2094                                 @unlink($file);
2095                         }
2096                 }
2097                 // now do dirs
2098                 $files = findAllFiles($tempDir, array(), true);
2099                 foreach($files as $dir) {
2100                         if(is_dir($dir)) {
2101                                 //logThis('removing dir ['.$dir.']', $path);
2102                                 @rmdir($dir);
2103                         }
2104                 }
2105                 $cacheFile = sugar_cached("modules/UpgradeWizard/_persistence.php");
2106                 if(is_file($cacheFile)) {
2107                         logThis("Unlinking Upgrade cache file: '_persistence.php'", $path);
2108                         @unlink($cacheFile);
2109                 }
2110         }
2111         logThis("finished!");
2112 }
2113
2114 /**
2115  * finds all files in the passed path, but skips select directories
2116  * @param string dir Relative path
2117  * @param array the_array Collections of found files/dirs
2118  * @param bool include_dir True if we want to include directories in the
2119  * returned collection
2120  */
2121 function uwFindAllFiles($dir, $theArray, $includeDirs=false, $skipDirs=array(), $echo=false) {
2122         // check skips
2123     if (whetherNeedToSkipDir($dir, $skipDirs))
2124         {
2125             return $theArray;
2126         }
2127
2128     if (!is_dir($dir)) { return $theArray; }   // Bug # 46035, just checking for valid dir
2129         $d = dir($dir);
2130     if ($d === false)  { return $theArray; }   // Bug # 46035, more checking
2131
2132         while($f = $d->read()) {
2133                                         // bug 40793 Skip Directories array in upgradeWizard does not function correctly
2134             if($f == "." || $f == ".." || whetherNeedToSkipDir("$dir/$f", $skipDirs)) { // skip *nix self/parent
2135                 continue;
2136             }
2137
2138                 // for AJAX length count
2139         if($echo) {
2140                 echo '.';
2141                 ob_flush();
2142         }
2143
2144             if(is_dir("$dir/$f")) {
2145                         if($includeDirs) { // add the directory if flagged
2146                                 $theArray[] = clean_path("$dir/$f");
2147                         }
2148
2149                         // recurse in
2150                 $theArray = uwFindAllFiles("$dir/$f/", $theArray, $includeDirs, $skipDirs, $echo);
2151             } else {
2152                 $theArray[] = clean_path("$dir/$f");
2153             }
2154
2155
2156         }
2157         rsort($theArray);
2158         $d->close();
2159         return $theArray;
2160 }
2161
2162
2163
2164 /**
2165  * unset's UW's Session Vars
2166  */
2167 function resetUwSession() {
2168         logThis('resetting $_SESSION');
2169
2170         if(isset($_SESSION['committed']))
2171                 unset($_SESSION['committed']);
2172         if(isset($_SESSION['sugar_version_file']))
2173                 unset($_SESSION['sugar_version_file']);
2174         if(isset($_SESSION['upgrade_complete']))
2175                 unset($_SESSION['upgrade_complete']);
2176         if(isset($_SESSION['allTables']))
2177                 unset($_SESSION['allTables']);
2178         if(isset($_SESSION['alterCustomTableQueries']))
2179                 unset($_SESSION['alterCustomTableQueries']);
2180         if(isset($_SESSION['skip_zip_upload']))
2181                 unset($_SESSION['skip_zip_upload']);
2182         if(isset($_SESSION['sugar_version_file']))
2183                 unset($_SESSION['sugar_version_file']);
2184         if(isset($_SESSION['install_file']))
2185                 unset($_SESSION['install_file']);
2186         if(isset($_SESSION['unzip_dir']))
2187                 unset($_SESSION['unzip_dir']);
2188         if(isset($_SESSION['zip_from_dir']))
2189                 unset($_SESSION['zip_from_dir']);
2190         if(isset($_SESSION['overwrite_files']))
2191                 unset($_SESSION['overwrite_files']);
2192         if(isset($_SESSION['schema_change']))
2193                 unset($_SESSION['schema_change']);
2194         if(isset($_SESSION['uw_restore_dir']))
2195                 unset($_SESSION['uw_restore_dir']);
2196         if(isset($_SESSION['step']))
2197                 unset($_SESSION['step']);
2198         if(isset($_SESSION['files']))
2199                 unset($_SESSION['files']);
2200         if(isset($_SESSION['Upgraded451Wizard'])){
2201                 unset($_SESSION['Upgraded451Wizard']);
2202         }
2203         if(isset($_SESSION['Initial_451to500_Step'])){
2204                 unset($_SESSION['Initial_451to500_Step']);
2205         }
2206         if(isset($_SESSION['license_shown']))
2207                 unset($_SESSION['license_shown']);
2208     if(isset($_SESSION['sugarMergeRunResults']))
2209                 unset($_SESSION['sugarMergeRunResults']);
2210 }
2211
2212 /**
2213  * runs rebuild scripts
2214  */
2215 function UWrebuild() {
2216         global $db;
2217         global $path;
2218         /*
2219         //CCL - Comment this block out, it is called in end.php
2220         logThis('Rebuilding everything...', $path);
2221         require_once('modules/Administration/QuickRepairAndRebuild.php');
2222         $randc = new RepairAndClear();
2223     $randc->repairAndClearAll(array('clearAll'),array(translate('LBL_ALL_MODULES')), false, false);
2224     */
2225         $query = "DELETE FROM versions WHERE name='Rebuild Extensions'";
2226         $db->query($query);
2227         logThis('Registering rebuild record: '.$query, $path);
2228         logThis('Rebuild done.', $path);
2229
2230         // insert a new database row to show the rebuild extensions is done
2231         $id = create_guid();
2232         $gmdate = gmdate('Y-m-d H:i:s');
2233         $date_entered = db_convert("'$gmdate'", 'datetime');
2234         $query = 'INSERT INTO versions (id, deleted, date_entered, date_modified, modified_user_id, created_by, name, file_version, db_version) '
2235                 . "VALUES ('$id', '0', $date_entered, $date_entered, '1', '1', 'Rebuild Extensions', '4.0.0', '4.0.0')";
2236         $db->query($query);
2237         logThis('Registering rebuild record in versions table: '.$query, $path);
2238 }
2239
2240 function getCustomTables() {
2241         global $db;
2242
2243     return $db->tablesLike('%_cstm');
2244 }
2245
2246 function alterCustomTables($customTables)
2247 {
2248         return array();
2249 }
2250
2251 function getAllTables() {
2252         global $db;
2253     return $db->getTablesArray();
2254 }
2255
2256 function printAlterTableSql($tables)
2257 {
2258         $alterTableSql = '';
2259
2260         foreach($tables as $table)
2261                 $alterTableSql .= "ALTER TABLE " . $table . " CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;" . "\n";
2262
2263         return $alterTableSql;
2264 }
2265
2266 function executeConvertTablesSql($tables)
2267 {
2268         global $db;
2269
2270         foreach($tables as $table){
2271                 $query = "ALTER TABLE " . $table . " CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci";
2272                 if(!empty($table)){
2273                         logThis("Sending query: ".$query);
2274             $db->query($query);//, true, "An error has occured while performing db query.  See log file for details.<br>");
2275          }
2276         }
2277         return true;
2278 }
2279
2280 function testThis() {
2281         $files = uwFindAllFiles(getcwd().'/test', array());
2282
2283         $out = "<table cellpadding='1' cellspacing='0' border='0'>\n";
2284
2285         $priorPath = '';
2286         foreach($files as $file) {
2287                 $relativeFile = clean_path(str_replace(getcwd().'/test', '', $file));
2288                 $relativeFile = ($relativeFile{0} == '/') ? substr($relativeFile, 1, strlen($relativeFile)) : $relativeFile;
2289
2290                 $relativePath = dirname($relativeFile);
2291
2292                 if($relativePath == $priorPath) { // same dir, new file
2293                         $out .= "<tr><td>".basename($relativeFile)."</td></tr>";
2294                         $priorPath = $relativePath;
2295                 } else { // new dir
2296
2297                 }
2298         }
2299
2300         $out .= "</table>";
2301
2302         echo $out;
2303 }
2304
2305
2306
2307
2308 function testThis2($dir, $id=0, $hide=false) {
2309     global $mod_strings;
2310         $path = $dir;
2311         $dh = opendir($dir);
2312         rewinddir($dh);
2313
2314         $doHide = ($hide) ? 'none' : '';
2315         $out = "<div id='{$id}' style='display:{$doHide};'>";
2316         $out .= "<table cellpadding='1' cellspacing='0' border='0' style='border:0px solid #ccc'>\n";
2317
2318         while($file = readdir($dh)) {
2319                 if($file == '.' || $file == '..' || $file == 'CVS' || $file == '.cvsignore')
2320                         continue;
2321
2322                 if(is_dir($path.'/'.$file)) {
2323                         $file = $path.'/'.$file;
2324                         $newI = create_guid();
2325                         $out .= "<tr><td valign='top'><a href='javascript:toggleNwFiles(\"{$newI}\");'>".SugarThemeRegistry::current()->getImage("Workflow", "", null, null, ".gif", $mod_strings['LBL_WORKFLOW'])."</a></td>\n";
2326                         $out .= "<td valign='top'><b><a href='javascript:toggleNwFiles(\"{$newI}\");'>".basename($file)."</a></b></td></tr>";
2327                         $out .= "<tr><td></td><td valign='top'>".testThis2($file, $newI, true)."</td></tr>";
2328                 } else {
2329                         $out .= "<tr><td valign='top'>&nbsp;</td>\n";
2330                         $out .= "<td valign='top'>".basename($file)."</td></tr>";
2331                 }
2332         }
2333
2334         $out .= "</tr></table>";
2335         $out .= "</div>";
2336
2337         closedir($dh);
2338         return $out;
2339 }
2340
2341
2342
2343
2344
2345 function testThis3(&$files, $id, $hide, $previousPath = '') {
2346         if(!is_array($files) || empty($files))
2347                 return '';
2348
2349         $out = '';
2350
2351     global $mod_strings;
2352         // expecting full path here
2353         foreach($files as $k => $file) {
2354                 $file = str_replace(getcwd(), '', $file);
2355                 $path = dirname($file);
2356                 $fileName = basename($file);
2357
2358                 if($fileName == 'CVS' || $fileName == '.cvsignore')
2359                         continue;
2360
2361                 if($path == $previousPath) { // same directory
2362                         // new row for each file
2363                         $out .= "<tr><td valign='top' align='left'>&nbsp;</td>";
2364                         $out .= "<td valign='top' align='left'>{$fileName}</td></tr>";
2365                 } else { // new directory
2366                         $newI = $k;
2367                         $out .= "<tr><td valign='top'><a href='javascript:toggleNwFiles(\"{$newI}\");'>".SugarThemeRegistry::current()->getImage("Workflow", "", null, null, ".gif", $mod_strings['LBL_WORKFLOW'])."</a></td>\n";
2368                         $out .= "<td valign='top'><b><a href='javascript:toggleNwFiles(\"{$newI}\");'>".$fileName."</a></b></td></tr>";
2369                         $recurse = testThis3($files, $newI, true, $previousPath);
2370                         $out .= "<tr><td></td><td valign='top'>".$recurse."</td></tr>";
2371                 }
2372
2373                 $previousPath = $path;
2374         }
2375         $display = ($hide) ? 'none' : '';
2376         $ret = <<<eoq
2377         <div id="{$id}" style="display:{$display}">
2378         <table cellpadding='1' cellspacing='0' border='0' style='border:1px solid #ccc'>
2379                 {$out}
2380         </table>
2381         </div>
2382 eoq;
2383         return $ret;
2384 }
2385
2386
2387 function testThis4($filePath, $fileNodes=array(), $fileName='') {
2388         $path = dirname($filePath);
2389         $file = basename($filePath);
2390
2391         $exFile = explode('/', $path);
2392
2393         foreach($exFile as $pathSegment) {
2394                 if(is_array($fileNodes[$pathSegment])) { // path already processed
2395
2396                 } else { // newly found path
2397                         $fileNodes[$pathSegment] = array();
2398                 }
2399
2400                 if($fileName != '') {
2401                         $fileNodes[$pathSegment][] = $fileName;
2402                 }
2403         }
2404
2405         return $fileNodes;
2406 }
2407
2408
2409
2410 ///////////////////////////////////////////////////////////////////////////////
2411 ////    SYSTEM CHECK FUNCTIONS
2412 /**
2413  * generates an array with all files in the SugarCRM root directory, skipping
2414  * cache/
2415  * @return array files Array of files with absolute paths
2416  */
2417 function getFilesForPermsCheck() {
2418         global $sugar_config;
2419
2420         logThis('Got JSON call to find all files...');
2421         $filesNotWritable = array();
2422         $filesNWPerms = array();
2423
2424         // add directories here that should be skipped when doing file permissions checks (cache/upload is the nasty one)
2425         $skipDirs = array(
2426                 $sugar_config['upload_dir'],
2427         );
2428         $files = uwFindAllFiles(".", array(), true, $skipDirs, true);
2429         return $files;
2430 }
2431
2432 /**
2433  * checks files for permissions
2434  * @param array files Array of files with absolute paths
2435  * @return string result of check
2436  */
2437 function checkFiles($files, $echo=false) {
2438         global $mod_strings;
2439         $filesNotWritable = array();
2440         $i=0;
2441         $filesOut = "
2442                 <a href='javascript:void(0); toggleNwFiles(\"filesNw\");'>{$mod_strings['LBL_UW_SHOW_NW_FILES']}</a>
2443                 <div id='filesNw' style='display:none;'>
2444                 <table cellpadding='3' cellspacing='0' border='0'>
2445                 <tr>
2446                         <th align='left'>{$mod_strings['LBL_UW_FILE']}</th>
2447                         <th align='left'>{$mod_strings['LBL_UW_FILE_PERMS']}</th>
2448                         <th align='left'>{$mod_strings['LBL_UW_FILE_OWNER']}</th>
2449                         <th align='left'>{$mod_strings['LBL_UW_FILE_GROUP']}</th>
2450                 </tr>";
2451
2452         $isWindows = is_windows();
2453         foreach($files as $file) {
2454
2455                 if($isWindows) {
2456                         if(!is_writable_windows($file)) {
2457                                 logThis('WINDOWS: File ['.$file.'] not readable - saving for display');
2458                                 // don't warn yet - we're going to use this to check against replacement files
2459         // aw: commented out; it's a hack to allow upgrade wizard to continue on windows... will fix later
2460                                 /*$filesNotWritable[$i] = $file;
2461                                 $filesNWPerms[$i] = substr(sprintf('%o',fileperms($file)), -4);
2462                                 $filesOut .= "<tr>".
2463                                                                 "<td><span class='error'>{$file}</span></td>".
2464                                                                 "<td>{$filesNWPerms[$i]}</td>".
2465                                                                 "<td>".$mod_strings['ERR_UW_CANNOT_DETERMINE_USER']."</td>".
2466                                                                 "<td>".$mod_strings['ERR_UW_CANNOT_DETERMINE_GROUP']."</td>".
2467                                                           "</tr>";*/
2468                         }
2469                 } else {
2470                         if(!is_writable($file)) {
2471                                 logThis('File ['.$file.'] not writable - saving for display');
2472                                 // don't warn yet - we're going to use this to check against replacement files
2473                                 $filesNotWritable[$i] = $file;
2474                                 $filesNWPerms[$i] = substr(sprintf('%o',fileperms($file)), -4);
2475                                 $owner = posix_getpwuid(fileowner($file));
2476                                 $group = posix_getgrgid(filegroup($file));
2477                                 $filesOut .= "<tr>".
2478                                                                 "<td><span class='error'>{$file}</span></td>".
2479                                                                 "<td>{$filesNWPerms[$i]}</td>".
2480                                                                 "<td>".$owner['name']."</td>".
2481                                                                 "<td>".$group['name']."</td>".
2482                                                           "</tr>";
2483                         }
2484                 }
2485                 $i++;
2486         }
2487
2488         $filesOut .= '</table></div>';
2489         // not a stop error
2490         $errors['files']['filesNotWritable'] = (count($filesNotWritable) > 0) ? true : false;
2491         if(count($filesNotWritable) < 1) {
2492                 $filesOut = "{$mod_strings['LBL_UW_FILE_NO_ERRORS']}";
2493         }
2494
2495         return $filesOut;
2496 }
2497
2498 function deletePackageOnCancel(){
2499         global $mod_strings;
2500         global $sugar_config;
2501         list($base_upgrade_dir, $base_tmp_upgrade_dir) = getUWDirs();
2502         logThis('running delete');
2503     if(!isset($_SESSION['install_file']) || ($_SESSION['install_file'] == "")) {
2504         logThis('ERROR: trying to delete non-existent file: ['.$_REQUEST['install_file'].']');
2505         $error = $mod_strings['ERR_UW_NO_FILE_UPLOADED'];
2506     }
2507     // delete file in upgrades/patch
2508     $delete_me = "$base_upgrade_dir/patch/".basename(urldecode( $_REQUEST['install_file'] ));
2509     if(@unlink($delete_me)) {
2510         //logThis('unlinking: '.$delete_me);
2511         $out = basename($delete_me).$mod_strings['LBL_UW_FILE_DELETED'];
2512     } else {
2513         logThis('ERROR: could not delete ['.$delete_me.']');
2514                 $error = $mod_strings['ERR_UW_FILE_NOT_DELETED'].$delete_me;
2515     }
2516
2517     if(!empty($error)) {
2518                 $out = "<b><span class='error'>{$error}</span></b><br />";
2519     }
2520 }
2521
2522 function parseAndExecuteSqlFile($sqlScript,$forStepQuery='',$resumeFromQuery='')
2523 {
2524         global $sugar_config;
2525         $alterTableSchema = '';
2526         $sqlErrors = array();
2527         if(!isset($_SESSION['sqlSkippedQueries'])){
2528                 $_SESSION['sqlSkippedQueries'] = array();
2529         }
2530         $db = DBManagerFactory::getInstance();
2531         $disable_keys = $db->supports("disable_keys");
2532         if(strpos($resumeFromQuery,",") != false){
2533                 $resumeFromQuery = explode(",",$resumeFromQuery);
2534         }
2535         if(file_exists($sqlScript)) {
2536                 $fp = fopen($sqlScript, 'r');
2537                 $contents = stream_get_contents($fp);
2538                 $anyScriptChanges =$contents;
2539                 $resumeAfterFound = false;
2540                 if(rewind($fp)) {
2541                         $completeLine = '';
2542                         $count = 0;
2543                         while($line = fgets($fp)) {
2544                                 if(strpos($line, '--') === false) {
2545                                         $completeLine .= " ".trim($line);
2546                                         if(strpos($line, ';') !== false) {
2547                                                 $query = '';
2548                                                 $query = str_replace(';','',$completeLine);
2549                                                 //if resume from query is not null then find out from where
2550                                                 //it should start executing the query.
2551
2552                                                 if($query != null && $resumeFromQuery != null){
2553                                                         if(!$resumeAfterFound){
2554                                                                 if(strpos($query,",") != false){
2555                                                                         $queArray = explode(",",$query);
2556                                                                         for($i=0;$i<sizeof($resumeFromQuery);$i++){
2557                                                                                 if(strcasecmp(trim($resumeFromQuery[$i]),trim($queArray[$i]))==0){
2558                                                                                         $resumeAfterFound = true;
2559                                                                                 } else {
2560                                                                                         $resumeAfterFound = false;
2561                                                                                         break;
2562                                                                                 }
2563                                                                         }//for
2564
2565                                                                 }
2566                                                                 elseif(strcasecmp(trim($resumeFromQuery),trim($query))==0){
2567                                                                         $resumeAfterFound = true;
2568                                                                 }
2569                                                         }
2570                                                         if($resumeAfterFound){
2571                                                                 $count++;
2572                                                         }
2573                                                         // if $count=1 means it is just found so skip the query. Run the next one
2574                                                         if($query != null && $resumeAfterFound && $count >1){
2575                                                         $tableName = getAlterTable($query);
2576                                                                 if($disable_keys && !empty($tableName))
2577                                                                 {
2578                                                                         $db->disableKeys($tableName);
2579                                                                 }
2580                                                                 $db->query($query);
2581                                                                 if($db->checkError()){
2582                                                                         //put in the array to use later on
2583                                                                         $_SESSION['sqlSkippedQueries'][] = $query;
2584                                                                 }
2585                                                                 if($disable_keys && !empty($tableName))
2586                                                                 {
2587                                                                         $db->enableKeys($tableName);
2588                                                                 }
2589                                                                 $progQuery[$forStepQuery]=$query;
2590                                                                 post_install_progress($progQuery,$action='set');
2591                                                         }//if
2592                                                 }
2593                                                 elseif($query != null){
2594                                                         $tableName = getAlterTable($query);
2595                                                         if($disable_keys && !empty($tableName))
2596                                                         {
2597                                                                 $db->disableKeys($tableName);
2598                                                         }
2599                                                         $db->query($query);
2600                                                         if($disable_keys && !empty($tableName))
2601                                                         {
2602                                                                 $db->enableKeys($tableName);
2603                                                         }
2604                                                         $progQuery[$forStepQuery]=$query;
2605                                                         post_install_progress($progQuery,$action='set');
2606                                                         if($db->checkError()){
2607                                                                 //put in the array to use later on
2608                                                                 $_SESSION['sqlSkippedQueries'][] = $query;
2609                                                         }
2610                                                 }
2611                                                 $completeLine = '';
2612                                         }
2613                                 }
2614                         }//while
2615                 }
2616         }
2617 }
2618
2619
2620 function getAlterTable($query){
2621         $query = strtolower($query);
2622         if (preg_match('/^\s*alter\s+table\s+/', $query)) {
2623                 $sqlArray = explode(" ", $query);
2624                 $key = array_search('table', $sqlArray);
2625                 return $sqlArray[($key+1)];
2626         }else {
2627                 return '';
2628         }
2629 }
2630
2631 function set_upgrade_vars(){
2632         logThis('setting session variables...');
2633         $upgrade_progress_dir = sugar_cached('upgrades/temp');
2634         if(!is_dir($upgrade_progress_dir)){
2635                 mkdir_recursive($upgrade_progress_dir);
2636         }
2637         $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
2638         if(file_exists($upgrade_progress_file)){
2639                 include($upgrade_progress_file);
2640         }
2641         else{
2642                 fopen($upgrade_progress_file, 'w+');
2643         }
2644         if(!isset($upgrade_config) || $upgrade_config == null){
2645                 $upgrade_config = array();
2646                 $upgrade_config[1]['upgrade_vars']=array();
2647         }
2648     if(isset($upgrade_config[1]) && isset($upgrade_config[1]['upgrade_vars']) && !is_array($upgrade_config[1]['upgrade_vars'])){
2649         $upgrade_config[1]['upgrade_vars'] = array();
2650     }
2651
2652         if(!isset($upgrade_vars) || $upgrade_vars == NULL){
2653                 $upgrade_vars = array();
2654         }
2655         if(isset($_SESSION['unzip_dir']) && !empty($_SESSION['unzip_dir']) && file_exists($_SESSION['unzip_dir'])){
2656                 $upgrade_vars['unzip_dir']=$_SESSION['unzip_dir'];
2657         }
2658         if(isset($_SESSION['install_file']) && !empty($_SESSION['install_file']) && file_exists($_SESSION['install_file'])){
2659                 $upgrade_vars['install_file']=$_SESSION['install_file'];
2660         }
2661         if(isset($_SESSION['Upgraded451Wizard']) && !empty($_SESSION['Upgraded451Wizard'])){
2662                 $upgrade_vars['Upgraded451Wizard']=$_SESSION['Upgraded451Wizard'];
2663         }
2664         if(isset($_SESSION['license_shown']) && !empty($_SESSION['license_shown'])){
2665                 $upgrade_vars['license_shown']=$_SESSION['license_shown'];
2666         }
2667         if(isset($_SESSION['Initial_451to500_Step']) && !empty($_SESSION['Initial_451to500_Step'])){
2668                 $upgrade_vars['Initial_451to500_Step']=$_SESSION['Initial_451to500_Step'];
2669         }
2670         if(isset($_SESSION['zip_from_dir']) && !empty($_SESSION['zip_from_dir'])){
2671                 $upgrade_vars['zip_from_dir']=$_SESSION['zip_from_dir'];
2672         }
2673         //place into the upgrade_config array and rewrite config array only if new values are being inserted
2674         if(isset($upgrade_vars) && $upgrade_vars != null && sizeof($upgrade_vars) > 0){
2675                 foreach($upgrade_vars as $key=>$val){
2676                         if($key != null && $val != null){
2677                                 $upgrade_config[1]['upgrade_vars'][$key]=$upgrade_vars[$key];
2678                         }
2679                 }
2680                 ksort($upgrade_config);
2681                 if(is_writable($upgrade_progress_file) && write_array_to_file( "upgrade_config", $upgrade_config,
2682                         $upgrade_progress_file)) {
2683                        //writing to the file
2684                 }
2685     }
2686 }
2687
2688 function initialize_session_vars(){
2689   $upgrade_progress_dir = sugar_cached('upgrades/temp');
2690   $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
2691   if(file_exists($upgrade_progress_file)){
2692         include($upgrade_progress_file);
2693         if(isset($upgrade_config) && $upgrade_config != null && is_array($upgrade_config) && sizeof($upgrade_config) >0){
2694                 $currVarsArray=$upgrade_config[1]['upgrade_vars'];
2695                 //print_r($currVarsArray);
2696                 if(isset($currVarsArray) && $currVarsArray != null && is_array($currVarsArray) && sizeof($currVarsArray)>0){
2697                         foreach($currVarsArray as $key=>$val){
2698                                 if($key != null && $val !=null){
2699                                         //set session variables
2700                                         $_SESSION[$key]=$val;
2701                                         //set varibales
2702                                         '$'.$key=$val;
2703                                 }
2704                         }
2705                 }
2706         }
2707   }
2708 }
2709 //track the upgrade progress on each step
2710 //track the upgrade progress on each step
2711 function set_upgrade_progress($currStep,$currState,$currStepSub='',$currStepSubState=''){
2712
2713         $upgrade_progress_dir = sugar_cached('upgrades/temp');
2714         if(!is_dir($upgrade_progress_dir)){
2715                 mkdir_recursive($upgrade_progress_dir);
2716         }
2717         $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
2718         if(file_exists($upgrade_progress_file)){
2719                 include($upgrade_progress_file);
2720         }
2721         else{
2722                 if(function_exists('sugar_fopen')){
2723                         sugar_fopen($upgrade_progress_file, 'w+');
2724                 }
2725                 else{
2726                         fopen($upgrade_progress_file, 'w+');
2727                 }
2728         }
2729         if(!isset($upgrade_config) || $upgrade_config == null){
2730                 $upgrade_config = array();
2731                 $upgrade_config[1]['upgrade_vars']=array();
2732         }
2733     if(!is_array($upgrade_config[1]['upgrade_vars'])){
2734         $upgrade_config[1]['upgrade_vars'] = array();
2735     }
2736         if($currStep != null && $currState != null){
2737                 if(sizeof($upgrade_config) > 0){
2738                         if($currStepSub != null && $currStepSubState !=null){
2739                                 //check if new status to be set or update
2740                                 //get the latest in array. since it has sub components prepare an array
2741                                 if(!empty($upgrade_config[sizeof($upgrade_config)][$currStep]) && is_array($upgrade_config[sizeof($upgrade_config)][$currStep])){
2742                                         $latestStepSub = currSubStep($upgrade_config[sizeof($upgrade_config)][$currStep]);
2743                                         if($latestStepSub == $currStepSub){
2744                                                 $upgrade_config[sizeof($upgrade_config)][$currStep][$latestStepSub]=$currStepSubState;
2745                                                 $upgrade_config[sizeof($upgrade_config)][$currStep][$currStep] = $currState;
2746                                         }
2747                                         else{
2748                                                 $upgrade_config[sizeof($upgrade_config)][$currStep][$currStepSub]=$currStepSubState;
2749                                                 $upgrade_config[sizeof($upgrade_config)][$currStep][$currStep] = $currState;
2750                                         }
2751                                 }
2752                                 else{
2753                                         $currArray = array();
2754                                         $currArray[$currStep] = $currState;
2755                                         $currArray[$currStepSub] = $currStepSubState;
2756                                         $upgrade_config[sizeof($upgrade_config)+1][$currStep] = $currArray;
2757                                 }
2758                         }
2759           else{
2760                                 //get the current upgrade progress
2761                                 $latestStep = get_upgrade_progress();
2762                                 //set the upgrade progress
2763                                 if($latestStep == $currStep){
2764                                         //update the current step with new progress status
2765                                         $upgrade_config[sizeof($upgrade_config)][$latestStep]=$currState;
2766                                 }
2767                                 else{
2768                                         //it's a new step
2769                                         $upgrade_config[sizeof($upgrade_config)+1][$currStep]=$currState;
2770                                 }
2771                     // now check if there elements within array substeps
2772           }
2773                 }
2774                 else{
2775                         //set the upgrade progress  (just starting)
2776                         $upgrade_config[sizeof($upgrade_config)+1][$currStep]= $currState;
2777                 }
2778
2779                 if(is_writable($upgrade_progress_file) && write_array_to_file( "upgrade_config", $upgrade_config,
2780                 $upgrade_progress_file)) {
2781                //writing to the file
2782                 }
2783
2784         }
2785 }
2786
2787 function get_upgrade_progress(){
2788         $upgrade_progress_dir = sugar_cached('upgrades/temp');
2789         $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
2790         $currState = '';
2791
2792         if(file_exists($upgrade_progress_file)){
2793                 include($upgrade_progress_file);
2794                 if(!isset($upgrade_config) || $upgrade_config == null){
2795                         $upgrade_config = array();
2796                 }
2797                 if($upgrade_config != null && sizeof($upgrade_config) >1){
2798                         $currArr = $upgrade_config[sizeof($upgrade_config)];
2799                         if(is_array($currArr)){
2800                            foreach($currArr as $key=>$val){
2801                                         $currState = $key;
2802                                 }
2803                         }
2804                 }
2805         }
2806         return $currState;
2807 }
2808 function currSubStep($currStep){
2809         $currSubStep = '';
2810         if(is_array($currStep)){
2811        foreach($currStep as $key=>$val){
2812                     if($key != null){
2813                         $currState = $key;
2814                         }
2815            }
2816         }
2817         return $currState;
2818 }
2819 function currUpgradeState($currState){
2820         $currState = '';
2821         if(is_array($currState)){
2822        foreach($currState as $key=>$val){
2823                         if(is_array($val)){
2824                                 foreach($val as $k=>$v){
2825                                         if($k != null){
2826                                                 $currState = $k;
2827                                         }
2828                                 }
2829                         }
2830                         else{
2831                                 $currState = $key;
2832                         }
2833                 }
2834         }
2835         return $currState;
2836 }
2837
2838 function didThisStepRunBefore($step,$SubStep=''){
2839         if($step == null) return;
2840         $upgrade_progress_dir = sugar_cached('upgrades/temp');
2841         $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
2842         $currState = '';
2843         $stepRan = false;
2844         if(file_exists($upgrade_progress_file)){
2845                 include($upgrade_progress_file);
2846                 if(isset($upgrade_config) && $upgrade_config != null && is_array($upgrade_config) && sizeof($upgrade_config) >0){
2847                         for($i=1;$i<=sizeof($upgrade_config);$i++){
2848                           if(is_array($upgrade_config[$i])){
2849                                         foreach($upgrade_config[$i] as $key=>$val){
2850                                                 if($key==$step){
2851                                                         if(is_array($upgrade_config[$i][$step])){
2852                                                                 //now process
2853                                                                 foreach ($upgrade_config[$i][$step] as $k=>$v){
2854                                                                         if(is_array($v)){
2855                                                                                 foreach($v as $k1=>$v1){
2856                                                                                         if($SubStep != null){
2857                                                                                                 if($SubStep ==$k1 && $v1=='done'){
2858                                                                                                         $stepRan = true;
2859                                                                                                         break;
2860                                                                                                 }
2861                                                                                         }
2862                                                                                 }//foreach
2863                                                                         }
2864                                                                         elseif($SubStep !=null){
2865                                                                                 if($SubStep==$k && $v=='done'){
2866                                                                                         $stepRan = true;
2867                                                                                         break;
2868                                                                                 }
2869                                                                         }
2870                                                                         elseif($step==$k && $v=='done'){
2871                                                                                 $stepRan = true;
2872                                                                                 break;
2873                                                                         }
2874                                                                 }//foreach
2875                                                         }
2876                                                         elseif($val=='done'){
2877                                                                 $stepRan = true;
2878                                                         }
2879                                                 }
2880                                         }//foreach
2881                                 }
2882                         }//for
2883                 }
2884         }
2885         return $stepRan;
2886 }
2887
2888
2889
2890 //get and set post install status
2891 function post_install_progress($progArray='',$action=''){
2892         $upgrade_progress_dir = sugar_cached('upgrades/temp');
2893         $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
2894     if($action=='' || $action=='get'){
2895                 //get the state of post install
2896         $currProg = array();
2897                 if(file_exists($upgrade_progress_file)){
2898                         include($upgrade_progress_file);
2899                         if(is_array($upgrade_config[sizeof($upgrade_config)]['commit']['post_install']) && sizeof($upgrade_config[sizeof($upgrade_config)]['commit']['post_install'])>0){
2900                                 foreach($upgrade_config[sizeof($upgrade_config)]['commit']['post_install'] as $k=>$v){
2901                                         $currProg[$k]=$v;
2902                                 }
2903                         }
2904                 }
2905                 return $currProg;
2906         }
2907         elseif($action=='set'){
2908                 if(!is_dir($upgrade_progress_dir)){
2909                         mkdir($upgrade_progress_dir);
2910                 }
2911                 if(file_exists($upgrade_progress_file)){
2912                         include($upgrade_progress_file);
2913                 }
2914                 else{
2915                         fopen($upgrade_progress_file, 'w+');
2916                 }
2917                 if(!is_array($upgrade_config[sizeof($upgrade_config)]['commit']['post_install'])){
2918                         $upgrade_config[sizeof($upgrade_config)]['commit']['post_install']=array();
2919                         $upgrade_config[sizeof($upgrade_config)]['commit']['post_install']['post_install'] = 'in_progress';
2920                 }
2921                 if($progArray != null && is_array($progArray)){
2922                         foreach($progArray as $key=>$val){
2923                                 $upgrade_config[sizeof($upgrade_config)]['commit']['post_install'][$key]=$val;
2924                         }
2925                 }
2926                 if(is_writable($upgrade_progress_file) && write_array_to_file( "upgrade_config", $upgrade_config,
2927                 $upgrade_progress_file)) {
2928                //writing to the file
2929                 }
2930         }
2931 }
2932
2933 function repairDBForUpgrade($execute=false,$path=''){
2934
2935         global $current_user, $beanFiles;
2936         global $dictionary;
2937         set_time_limit(3600);
2938
2939         $db = &DBManagerFactory::getInstance();
2940         $sql = '';
2941         VardefManager::clearVardef();
2942         require_once('include/ListView/ListView.php');
2943         foreach ($beanFiles as $bean => $file) {
2944                 require_once ($file);
2945                 $focus = new $bean ();
2946                 $sql .= $db->repairTable($focus, $execute);
2947
2948         }
2949         //echo $sql;
2950         $olddictionary = $dictionary;
2951         unset ($dictionary);
2952         include ('modules/TableDictionary.php');
2953         foreach ($dictionary as $meta) {
2954                 $tablename = $meta['table'];
2955                 $fielddefs = $meta['fields'];
2956                 $indices = $meta['indices'];
2957                 $sql .= $db->repairTableParams($tablename, $fielddefs, $indices, $execute);
2958         }
2959          $qry_str = "";
2960           foreach (explode("\n", $sql) as $line) {
2961                   if (!empty ($line) && substr($line, -2) != "*/") {
2962                         $line .= ";";
2963                   }
2964                   $qry_str .= $line . "\n";
2965            }
2966           $sql = str_replace(
2967           array(
2968                 "\n",
2969                 '&#039;',
2970            ),
2971           array(
2972                 '',
2973                 "'",
2974           ),
2975           preg_replace('#(/\*.+?\*/\n*)#', '', $qry_str)
2976           );
2977          logThis("*******START EXECUTING DB UPGRADE QUERIES***************",$path);
2978                 logThis($sql,$path);
2979          logThis("*******END EXECUTING DB UPGRADE QUERIES****************",$path);
2980          if(!$execute){
2981                 return $sql;
2982          }
2983 }
2984
2985
2986
2987 /**
2988  * upgradeUserPreferences
2989  * This method updates the user_preferences table and sets the pages/dashlets for users
2990  * which have ACL access to Trackers so that the Tracker dashlets are set in their user perferences
2991  *
2992  */
2993 function upgradeUserPreferences() {
2994
2995     // check the current system wide default_locale_name_format and add it to the list if it's not there
2996     global $sugar_config;
2997     upgradeLocaleNameFormat($sugar_config['default_locale_name_format']);
2998
2999         $db = &DBManagerFactory::getInstance();
3000     $result = $db->query("SELECT id FROM users where deleted = '0'");
3001         while($row = $db->fetchByAssoc($result))
3002     {
3003         $current_user = new User();
3004         
3005         // 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
3006         upgradeLocaleNameFormat($current_user->getPreference('default_locale_name_format'));
3007
3008         } //while
3009 }
3010
3011 /**
3012  * Checks if a locale name format is part of the default list, if not adds it to the config
3013  * @param $name_format string a local name format string such as 's f l'
3014  * @return bool true on successful write to config file, false on failure;
3015  */
3016 function upgradeLocaleNameFormat($name_format) {
3017     global $sugar_config, $sugar_version, $mod_strings;
3018     if (!in_array($name_format, $sugar_config['name_formats'])) {
3019         $new_config = sugarArrayMerge($sugar_config['name_formats'], array($name_format=>$name_format));
3020         $sugar_config['name_formats'] = $new_config;
3021         if(!rebuildConfigFile($sugar_config, $sugar_version)) {
3022             logThis('*** ERROR: could not write config.php! - upgrade will fail!');
3023             $errors[] = $mod_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 }