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