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