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