]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - modules/UpgradeWizard/uw_utils.php
Release 6.2.3
[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, $theArray, $includeDirs=false, $skipDirs=array(), $echo=false) {
2870         // check skips
2871     if (whetherNeedToSkipDir($dir, $skipDirs))
2872         {
2873             return $theArray;
2874         }
2875
2876     if (!is_dir($dir)) { return $theArray; }   // Bug # 46035, just checking for valid dir
2877         $d = dir($dir);
2878     if ($d === false)  { return $theArray; }   // Bug # 46035, more checking
2879
2880         while($f = $d->read()) {
2881                                         // bug 40793 Skip Directories array in upgradeWizard does not function correctly
2882             if($f == "." || $f == ".." || whetherNeedToSkipDir("$dir/$f", $skipDirs)) { // skip *nix self/parent
2883                 continue;
2884             }
2885
2886                 // for AJAX length count
2887         if($echo) {
2888                 echo '.';
2889                 ob_flush();
2890         }
2891
2892             if(is_dir("$dir/$f")) {
2893                         if($includeDirs) { // add the directory if flagged
2894                                 $theArray[] = clean_path("$dir/$f");
2895                         }
2896
2897                         // recurse in
2898                 $theArray = uwFindAllFiles("$dir/$f/", $theArray, $includeDirs, $skipDirs, $echo);
2899             } else {
2900                 $theArray[] = clean_path("$dir/$f");
2901             }
2902
2903
2904         }
2905         rsort($theArray);
2906         return $theArray;
2907 }
2908
2909
2910
2911 /**
2912  * unset's UW's Session Vars
2913  */
2914 function resetUwSession() {
2915         logThis('resetting $_SESSION');
2916
2917         if(isset($_SESSION['committed']))
2918                 unset($_SESSION['committed']);
2919         if(isset($_SESSION['sugar_version_file']))
2920                 unset($_SESSION['sugar_version_file']);
2921         if(isset($_SESSION['upgrade_complete']))
2922                 unset($_SESSION['upgrade_complete']);
2923         if(isset($_SESSION['allTables']))
2924                 unset($_SESSION['allTables']);
2925         if(isset($_SESSION['alterCustomTableQueries']))
2926                 unset($_SESSION['alterCustomTableQueries']);
2927         if(isset($_SESSION['skip_zip_upload']))
2928                 unset($_SESSION['skip_zip_upload']);
2929         if(isset($_SESSION['sugar_version_file']))
2930                 unset($_SESSION['sugar_version_file']);
2931         if(isset($_SESSION['install_file']))
2932                 unset($_SESSION['install_file']);
2933         if(isset($_SESSION['unzip_dir']))
2934                 unset($_SESSION['unzip_dir']);
2935         if(isset($_SESSION['zip_from_dir']))
2936                 unset($_SESSION['zip_from_dir']);
2937         if(isset($_SESSION['overwrite_files']))
2938                 unset($_SESSION['overwrite_files']);
2939         if(isset($_SESSION['schema_change']))
2940                 unset($_SESSION['schema_change']);
2941         if(isset($_SESSION['uw_restore_dir']))
2942                 unset($_SESSION['uw_restore_dir']);
2943         if(isset($_SESSION['step']))
2944                 unset($_SESSION['step']);
2945         if(isset($_SESSION['files']))
2946                 unset($_SESSION['files']);
2947         if(isset($_SESSION['Upgraded451Wizard'])){
2948                 unset($_SESSION['Upgraded451Wizard']);
2949         }
2950         if(isset($_SESSION['Initial_451to500_Step'])){
2951                 unset($_SESSION['Initial_451to500_Step']);
2952         }
2953         if(isset($_SESSION['license_shown']))
2954                 unset($_SESSION['license_shown']);
2955     if(isset($_SESSION['sugarMergeRunResults']))
2956                 unset($_SESSION['sugarMergeRunResults']);
2957 }
2958
2959 /**
2960  * runs rebuild scripts
2961  */
2962 function UWrebuild() {
2963         global $db;
2964         global $path;
2965         /*
2966         //CCL - Comment this block out, it is called in end.php
2967         logThis('Rebuilding everything...', $path);
2968         require_once('modules/Administration/QuickRepairAndRebuild.php');
2969         $randc = new RepairAndClear();
2970     $randc->repairAndClearAll(array('clearAll'),array(translate('LBL_ALL_MODULES')), false, false);
2971     */
2972         $query = "DELETE FROM versions WHERE name='Rebuild Extensions'";
2973         $db->query($query);
2974         logThis('Registering rebuild record: '.$query, $path);
2975         logThis('Rebuild done.', $path);
2976
2977         // insert a new database row to show the rebuild extensions is done
2978         $id = create_guid();
2979         $gmdate = gmdate('Y-m-d H:i:s');
2980         $date_entered = db_convert("'$gmdate'", 'datetime');
2981         $query = 'INSERT INTO versions (id, deleted, date_entered, date_modified, modified_user_id, created_by, name, file_version, db_version) '
2982                 . "VALUES ('$id', '0', $date_entered, $date_entered, '1', '1', 'Rebuild Extensions', '4.0.0', '4.0.0')";
2983         $db->query($query);
2984         logThis('Registering rebuild record in versions table: '.$query, $path);
2985 }
2986
2987 function getCustomTables($dbType) {
2988         global $db;
2989
2990         $customTables = array();
2991
2992     switch($dbType) {
2993                 case 'mysql':
2994                 $query = "SHOW tables LIKE '%_cstm'";
2995                 $result = $db->query($query);//, true, 'Error getting custom tables');
2996             while ($row = $db->fetchByAssoc($result)){
2997                 $customTables[] = array_pop($row);
2998             }
2999             break;
3000         }
3001     return $customTables;
3002 }
3003
3004 function alterCustomTables($dbType, $customTables)
3005 {
3006         switch($dbType) {
3007                 case 'mysql':
3008                         $i = 0;
3009                         while( $i < count($customTables) ) {
3010                                 $alterCustomTableSql[] = "ALTER TABLE " . $customTables[$i] . " CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci";
3011                                 $i++;
3012                         }
3013                         break;
3014                 case 'oci8':
3015                         break;
3016         }
3017         return $alterCustomTableSql;
3018 }
3019
3020 function executeAlterCustomTablesSql($dbType, $queries) {
3021         global $db;
3022
3023         foreach($queries as $query){
3024                 if(!empty($query)){
3025                         logThis("Sending query: ".$query);
3026                     if($db->dbType == 'oci8') {
3027                 } else {
3028                     $query_result = $db->query($query);//.';', true, "An error has occured while performing db query.  See log file for details.<br>");
3029                 }
3030          }
3031         }
3032         return true;
3033 }
3034
3035 function getAllTables($dbType) {
3036         global $db;
3037
3038         $tables = array();
3039
3040     switch($dbType) {
3041                 case 'mysql':
3042                 $query = "SHOW tables";
3043                 $result = $db->query($query, true, 'Error getting custom tables');
3044             while ($row = $db->fetchByAssoc($result)){
3045                 $tables[] = array_pop($row);
3046             }
3047             break;
3048         }
3049     return $tables;
3050 }
3051
3052 function printAlterTableSql($tables)
3053 {
3054         $alterTableSql = '';
3055
3056         foreach($tables as $table)
3057                 $alterTableSql .= "ALTER TABLE " . $table . " CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;" . "\n";
3058
3059         return $alterTableSql;
3060 }
3061
3062 function executeConvertTablesSql($dbType, $tables) {
3063         global $db;
3064
3065         foreach($tables as $table){
3066                 $query = "ALTER TABLE " . $table . " CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci";
3067                 if(!empty($table)){
3068                         logThis("Sending query: ".$query);
3069                     if($db->dbType == 'oci8') {
3070                 } else {
3071                     $query_result = $db->query($query);//.';', true, "An error has occured while performing db query.  See log file for details.<br>");
3072                 }
3073          }
3074         }
3075         return true;
3076 }
3077
3078 function testThis() {
3079         $files = uwFindAllFiles(getcwd().'/test', array());
3080
3081         $out = "<table cellpadding='1' cellspacing='0' border='0'>\n";
3082
3083         $priorPath = '';
3084         foreach($files as $file) {
3085                 $relativeFile = clean_path(str_replace(getcwd().'/test', '', $file));
3086                 $relativeFile = ($relativeFile{0} == '/') ? substr($relativeFile, 1, strlen($relativeFile)) : $relativeFile;
3087
3088                 $relativePath = dirname($relativeFile);
3089
3090                 if($relativePath == $priorPath) { // same dir, new file
3091                         $out .= "<tr><td>".basename($relativeFile)."</td></tr>";
3092                         $priorPath = $relativePath;
3093                 } else { // new dir
3094
3095                 }
3096         }
3097
3098         $out .= "</table>";
3099
3100         echo $out;
3101 }
3102
3103
3104
3105
3106 function testThis2($dir, $id=0, $hide=false) {
3107         $path = $dir;
3108         $dh = opendir($dir);
3109         rewinddir($dh);
3110
3111         $doHide = ($hide) ? 'none' : '';
3112         $out = "<div id='{$id}' style='display:{$doHide};'>";
3113         $out .= "<table cellpadding='1' cellspacing='0' border='0' style='border:0px solid #ccc'>\n";
3114
3115         while($file = readdir($dh)) {
3116                 if($file == '.' || $file == '..' || $file == 'CVS' || $file == '.cvsignore')
3117                         continue;
3118
3119                 if(is_dir($path.'/'.$file)) {
3120                         $file = $path.'/'.$file;
3121                         $newI = create_guid();
3122                         $out .= "<tr><td valign='top'><a href='javascript:toggleNwFiles(\"{$newI}\");'><img border='0' src='".SugarThemeRegistry::current()->getImageURL('Workflow.gif')."'></a></td>\n";
3123                         $out .= "<td valign='top'><b><a href='javascript:toggleNwFiles(\"{$newI}\");'>".basename($file)."</a></b></td></tr>";
3124                         $out .= "<tr><td></td><td valign='top'>".testThis2($file, $newI, true)."</td></tr>";
3125                 } else {
3126                         $out .= "<tr><td valign='top'>&nbsp;</td>\n";
3127                         $out .= "<td valign='top'>".basename($file)."</td></tr>";
3128                 }
3129         }
3130
3131         $out .= "</tr></table>";
3132         $out .= "</div>";
3133
3134         closedir($dh);
3135         return $out;
3136 }
3137
3138
3139
3140
3141
3142 function testThis3(&$files, $id, $hide, $previousPath = '') {
3143         if(!is_array($files) || empty($files))
3144                 return '';
3145
3146         $out = '';
3147
3148         // expecting full path here
3149         foreach($files as $k => $file) {
3150                 $file = str_replace(getcwd(), '', $file);
3151                 $path = dirname($file);
3152                 $fileName = basename($file);
3153
3154                 if($fileName == 'CVS' || $fileName == '.cvsignore')
3155                         continue;
3156
3157                 if($path == $previousPath) { // same directory
3158                         // new row for each file
3159                         $out .= "<tr><td valign='top' align='left'>&nbsp;</td>";
3160                         $out .= "<td valign='top' align='left'>{$fileName}</td></tr>";
3161                 } else { // new directory
3162                         $newI = $k;
3163                         $out .= "<tr><td valign='top'><a href='javascript:toggleNwFiles(\"{$newI}\");'><img border='0' src='".SugarThemeRegistry::current()->getImageURL('Workflow.gif')."></a></td>\n";
3164                         $out .= "<td valign='top'><b><a href='javascript:toggleNwFiles(\"{$newI}\");'>".$fileName."</a></b></td></tr>";
3165                         $recurse = testThis3($files, $newI, true, $previousPath);
3166                         $out .= "<tr><td></td><td valign='top'>".$recurse."</td></tr>";
3167                 }
3168
3169                 $previousPath = $path;
3170         }
3171         $display = ($hide) ? 'none' : '';
3172         $ret = <<<eoq
3173         <div id="{$id}" style="display:{$display}">
3174         <table cellpadding='1' cellspacing='0' border='0' style='border:1px solid #ccc'>
3175                 {$out}
3176         </table>
3177         </div>
3178 eoq;
3179         return $ret;
3180 }
3181
3182
3183 function testThis4($filePath, $fileNodes=array(), $fileName='') {
3184         $path = dirname($filePath);
3185         $file = basename($filePath);
3186
3187         $exFile = explode('/', $path);
3188
3189         foreach($exFile as $pathSegment) {
3190                 if(is_array($fileNodes[$pathSegment])) { // path already processed
3191
3192                 } else { // newly found path
3193                         $fileNodes[$pathSegment] = array();
3194                 }
3195
3196                 if($fileName != '') {
3197                         $fileNodes[$pathSegment][] = $fileName;
3198                 }
3199         }
3200
3201         return $fileNodes;
3202 }
3203
3204
3205
3206 ///////////////////////////////////////////////////////////////////////////////
3207 ////    SYSTEM CHECK FUNCTIONS
3208 /**
3209  * generates an array with all files in the SugarCRM root directory, skipping
3210  * cache/
3211  * @return array files Array of files with absolute paths
3212  */
3213 function getFilesForPermsCheck() {
3214         global $sugar_config;
3215
3216         logThis('Got JSON call to find all files...');
3217         $filesNotWritable = array();
3218         $filesNWPerms = array();
3219
3220         // add directories here that should be skipped when doing file permissions checks (cache/upload is the nasty one)
3221         $skipDirs = array(
3222                 $sugar_config['upload_dir'],
3223         );
3224         $files = uwFindAllFiles(getcwd(), array(), true, $skipDirs, true);
3225         return $files;
3226 }
3227
3228 /**
3229  * checks files for permissions
3230  * @param array files Array of files with absolute paths
3231  * @return string result of check
3232  */
3233 function checkFiles($files, $echo=false) {
3234         global $mod_strings;
3235         $filesNotWritable = array();
3236         $i=0;
3237         $filesOut = "
3238                 <a href='javascript:void(0); toggleNwFiles(\"filesNw\");'>{$mod_strings['LBL_UW_SHOW_NW_FILES']}</a>
3239                 <div id='filesNw' style='display:none;'>
3240                 <table cellpadding='3' cellspacing='0' border='0'>
3241                 <tr>
3242                         <th align='left'>{$mod_strings['LBL_UW_FILE']}</th>
3243                         <th align='left'>{$mod_strings['LBL_UW_FILE_PERMS']}</th>
3244                         <th align='left'>{$mod_strings['LBL_UW_FILE_OWNER']}</th>
3245                         <th align='left'>{$mod_strings['LBL_UW_FILE_GROUP']}</th>
3246                 </tr>";
3247
3248         $isWindows = is_windows();
3249         foreach($files as $file) {
3250
3251                 if($isWindows) {
3252                         if(!is_writable_windows($file)) {
3253                                 logThis('WINDOWS: File ['.$file.'] not readable - saving for display');
3254                                 // don't warn yet - we're going to use this to check against replacement files
3255         // aw: commented out; it's a hack to allow upgrade wizard to continue on windows... will fix later
3256                                 /*$filesNotWritable[$i] = $file;
3257                                 $filesNWPerms[$i] = substr(sprintf('%o',fileperms($file)), -4);
3258                                 $filesOut .= "<tr>".
3259                                                                 "<td><span class='error'>{$file}</span></td>".
3260                                                                 "<td>{$filesNWPerms[$i]}</td>".
3261                                                                 "<td>".$mod_strings['ERR_UW_CANNOT_DETERMINE_USER']."</td>".
3262                                                                 "<td>".$mod_strings['ERR_UW_CANNOT_DETERMINE_GROUP']."</td>".
3263                                                           "</tr>";*/
3264                         }
3265                 } else {
3266                         if(!is_writable($file)) {
3267                                 logThis('File ['.$file.'] not writable - saving for display');
3268                                 // don't warn yet - we're going to use this to check against replacement files
3269                                 $filesNotWritable[$i] = $file;
3270                                 $filesNWPerms[$i] = substr(sprintf('%o',fileperms($file)), -4);
3271                                 $owner = posix_getpwuid(fileowner($file));
3272                                 $group = posix_getgrgid(filegroup($file));
3273                                 $filesOut .= "<tr>".
3274                                                                 "<td><span class='error'>{$file}</span></td>".
3275                                                                 "<td>{$filesNWPerms[$i]}</td>".
3276                                                                 "<td>".$owner['name']."</td>".
3277                                                                 "<td>".$group['name']."</td>".
3278                                                           "</tr>";
3279                         }
3280                 }
3281                 $i++;
3282         }
3283
3284         $filesOut .= '</table></div>';
3285         // not a stop error
3286         $errors['files']['filesNotWritable'] = (count($filesNotWritable) > 0) ? true : false;
3287         if(count($filesNotWritable) < 1) {
3288                 $filesOut = "{$mod_strings['LBL_UW_FILE_NO_ERRORS']}";
3289         }
3290
3291         return $filesOut;
3292 }
3293
3294 function deletePackageOnCancel(){
3295         global $mod_strings;
3296         global $sugar_config;
3297         logThis('running delete');
3298     if(!isset($_SESSION['install_file']) || ($_SESSION['install_file'] == "")) {
3299         logThis('ERROR: trying to delete non-existent file: ['.$_REQUEST['install_file'].']');
3300         $error = $mod_strings['ERR_UW_NO_FILE_UPLOADED'];
3301     }
3302     // delete file in upgrades/patch
3303     $delete_me = urldecode( $_SESSION['install_file'] );
3304     if(@unlink($delete_me)) {
3305         //logThis('unlinking: '.$delete_me);
3306         $out = basename($delete_me).$mod_strings['LBL_UW_FILE_DELETED'];
3307     } else {
3308         logThis('ERROR: could not delete ['.$delete_me.']');
3309                 $error = $mod_strings['ERR_UW_FILE_NOT_DELETED'].$delete_me;
3310     }
3311
3312     // delete file in cache/upload
3313     $fileS = explode('/', $delete_me);
3314     $c = count($fileS);
3315     $fileName = (isset($fileS[$c-1]) && !empty($fileS[$c-1])) ? $fileS[$c-1] : $fileS[$c-2];
3316     $deleteUpload = getcwd().'/'.$sugar_config['upload_dir'].$fileName;
3317     logThis('Trying to delete '.$deleteUpload);
3318     if(!@unlink($deleteUpload)) {
3319         logThis('ERROR: could not delete: ['.$deleteUpload.']');
3320         $error = $mod_strings['ERR_UW_FILE_NOT_DELETED'].$sugar_config['upload_dir'].$fileName;
3321     }
3322     if(!empty($error)) {
3323                 $out = "<b><span class='error'>{$error}</span></b><br />";
3324     }
3325 }
3326
3327
3328 function parseAndExecuteSqlFile($sqlScript,$forStepQuery='',$resumeFromQuery=''){
3329         global $sugar_config;
3330         $alterTableSchema = '';
3331         $sqlErrors = array();
3332         if(!isset($_SESSION['sqlSkippedQueries'])){
3333                 $_SESSION['sqlSkippedQueries'] = array();
3334          }
3335         $db = & DBManagerFactory::getInstance();
3336         $is_mysql = false;
3337         if($sugar_config['dbconfig']['db_type'] == 'mysql') {
3338            $is_mysql = true;
3339         }
3340     if($sugar_config['dbconfig']['db_type'] == 'oci8'){
3341         $db->query("CREATE OR REPLACE FUNCTION blob_to_clob (blob_in IN BLOB)
3342                                         RETURN CLOB
3343                                         AS
3344                                           v_clob    CLOB;
3345                                           v_varchar VARCHAR2(32767);
3346                                           v_start   PLS_INTEGER := 1;
3347                                           v_buffer  PLS_INTEGER := 32767;
3348                                         BEGIN
3349                                           DBMS_LOB.CREATETEMPORARY(v_clob, TRUE);
3350
3351                                           FOR i IN 1..CEIL(DBMS_LOB.GETLENGTH(blob_in) / v_buffer)
3352                                           LOOP
3353
3354                                              v_varchar := UTL_RAW.CAST_TO_VARCHAR2(DBMS_LOB.SUBSTR(blob_in, v_buffer, v_start));
3355
3356                                                    DBMS_LOB.WRITEAPPEND(v_clob, LENGTH(v_varchar), v_varchar);
3357
3358                                                 v_start := v_start + v_buffer;
3359                                             END LOOP;
3360
3361                                            RETURN v_clob;
3362
3363                                         END blob_to_clob;");
3364     }
3365     if(strpos($resumeFromQuery,",") != false){
3366         $resumeFromQuery = explode(",",$resumeFromQuery);
3367         if(is_array($resumeFromQuery)){
3368                 //print_r('RES ARRAY '.$resumeFromQuery[0].'</br>');
3369         }
3370     }
3371         if(file_exists($sqlScript)) {
3372                 $fp = fopen($sqlScript, 'r');
3373                 $contents = stream_get_contents($fp);
3374             $anyScriptChanges =$contents;
3375             $resumeAfterFound = false;
3376                 if(rewind($fp)) {
3377                         $completeLine = '';
3378                         $count = 0;
3379                         while($line = fgets($fp)) {
3380                                 if(strpos($line, '--') === false) {
3381                                         $completeLine .= " ".trim($line);
3382                                         if(strpos($line, ';') !== false) {
3383                                                 $query = '';
3384                                                 $query = str_replace(';','',$completeLine);
3385                                                 //if resume from query is not null then find out from where
3386                                                 //it should start executing the query.
3387
3388                                                 if($query != null && $resumeFromQuery != null){
3389                                                         if(!$resumeAfterFound){
3390                                                                 if(strpos($query,",") != false){
3391                                                                         $queArray = array();
3392                                                                         $queArray = explode(",",$query);
3393                                                                         for($i=0;$i<sizeof($resumeFromQuery);$i++){
3394                                                                                 if(strcmp(strtolower(trim($resumeFromQuery[$i])),strtolower(trim($queArray[$i])))==0){
3395                                                                                         //echo 'mat found '.$queArray[$i].'</br>';
3396                                                                                         $resumeAfterFound = true;
3397                                                                                 }
3398                                                                                 else{
3399                                                                                         $resumeAfterFound = false;
3400                                                                                         break;
3401                                                                                 }
3402                                                                         }//for
3403
3404                                                                 }
3405                                                                 elseif(strcmp(strtolower(trim($resumeFromQuery)),strtolower(trim($query)))==0){
3406                                                                         $resumeAfterFound = true;
3407                                                                 }
3408                                                         }
3409                                                         if($resumeAfterFound){
3410                                                                 $count++;
3411                                                         }
3412                                                         // if $count=1 means it is just found so skip the query. Run the next one
3413                                 if($query != null && $resumeAfterFound && $count >1){
3414                                         $tableName = '';
3415                                         if($is_mysql)
3416                                         {
3417                                                 $tableName = getAlterTable($query);
3418                                                 if(!empty($tableName))
3419                                                 {
3420                                                         $db->query('ALTER TABLE '.$tableName.' DISABLE KEYS');
3421                                                 }
3422                                         }
3423                                         $db->query($query);
3424                                         if($db->checkError()){
3425                                             //put in the array to use later on
3426                                             $_SESSION['sqlSkippedQueries'][] = $query;
3427                                         }
3428                                     if(!empty($tableName))
3429                                 {
3430                                     $db->query('ALTER TABLE '.$tableName.' ENABLE KEYS');
3431                                 }
3432                                         $progQuery[$forStepQuery]=$query;
3433                                         post_install_progress($progQuery,$action='set');
3434                                 }//if
3435                                                 }
3436                                                 elseif($query != null){
3437                                                         $tableName = '';
3438                                 if($is_mysql)
3439                                 {
3440                                     $tableName = getAlterTable($query);
3441                                     if(!empty($tableName))
3442                                     {
3443                                         $db->query('ALTER TABLE '.$tableName.' DISABLE KEYS');
3444                                     }
3445                                 }
3446                                         $db->query($query);
3447                                                         if(!empty($tableName))
3448                                 {
3449                                     $db->query('ALTER TABLE '.$tableName.' ENABLE KEYS');
3450                                 }
3451                                         $progQuery[$forStepQuery]=$query;
3452                                         post_install_progress($progQuery,$action='set');
3453                                         if($db->checkError()){
3454                                             //put in the array to use later on
3455                                             $_SESSION['sqlSkippedQueries'][] = $query;
3456                                         }
3457                                 }
3458                                 $completeLine = '';
3459                                         }
3460                                 }
3461                         }//while
3462                 }
3463         }
3464 }
3465
3466 function getAlterTable($query){
3467         $query = strtolower($query);
3468         if (preg_match("/^\s*alter\s+table\s+/", $query)) {
3469                 $sqlArray = explode(" ", $query);
3470                 $key = array_search('table', $sqlArray);
3471                 return $sqlArray[($key+1)];
3472         }else {
3473                 return '';
3474         }
3475 }
3476
3477 function set_upgrade_vars(){
3478         logThis('setting session variables...');
3479         $upgrade_progress_dir = getcwd().'/'.$GLOBALS['sugar_config']['upload_dir'].'upgrades/temp';
3480         if(!is_dir($upgrade_progress_dir)){
3481                 mkdir_recursive($upgrade_progress_dir);
3482         }
3483         $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3484         if(file_exists($upgrade_progress_file)){
3485                 include($upgrade_progress_file);
3486         }
3487         else{
3488                 fopen($upgrade_progress_file, 'w+');
3489         }
3490         if(!isset($upgrade_config) || $upgrade_config == null){
3491                 $upgrade_config = array();
3492                 $upgrade_config[1]['upgrade_vars']=array();
3493         }
3494     if(isset($upgrade_config[1]) && isset($upgrade_config[1]['upgrade_vars']) && !is_array($upgrade_config[1]['upgrade_vars'])){
3495         $upgrade_config[1]['upgrade_vars'] = array();
3496     }
3497
3498         if(!isset($upgrade_vars) || $upgrade_vars == NULL){
3499                 $upgrade_vars = array();
3500         }
3501         if(isset($_SESSION['unzip_dir']) && !empty($_SESSION['unzip_dir']) && file_exists($_SESSION['unzip_dir'])){
3502                 $upgrade_vars['unzip_dir']=$_SESSION['unzip_dir'];
3503         }
3504         if(isset($_SESSION['install_file']) && !empty($_SESSION['install_file']) && file_exists($_SESSION['install_file'])){
3505                 $upgrade_vars['install_file']=$_SESSION['install_file'];
3506         }
3507         if(isset($_SESSION['Upgraded451Wizard']) && !empty($_SESSION['Upgraded451Wizard'])){
3508                 $upgrade_vars['Upgraded451Wizard']=$_SESSION['Upgraded451Wizard'];
3509         }
3510         if(isset($_SESSION['license_shown']) && !empty($_SESSION['license_shown'])){
3511                 $upgrade_vars['license_shown']=$_SESSION['license_shown'];
3512         }
3513         if(isset($_SESSION['Initial_451to500_Step']) && !empty($_SESSION['Initial_451to500_Step'])){
3514                 $upgrade_vars['Initial_451to500_Step']=$_SESSION['Initial_451to500_Step'];
3515         }
3516         if(isset($_SESSION['zip_from_dir']) && !empty($_SESSION['zip_from_dir'])){
3517                 $upgrade_vars['zip_from_dir']=$_SESSION['zip_from_dir'];
3518         }
3519         //place into the upgrade_config array and rewrite config array only if new values are being inserted
3520         if(isset($upgrade_vars) && $upgrade_vars != null && sizeof($upgrade_vars) > 0){
3521                 foreach($upgrade_vars as $key=>$val){
3522                         if($key != null && $val != null){
3523                                 $upgrade_config[1]['upgrade_vars'][$key]=$upgrade_vars[$key];
3524                         }
3525                 }
3526                 ksort($upgrade_config);
3527                 if(is_writable($upgrade_progress_file) && write_array_to_file( "upgrade_config", $upgrade_config,
3528                         $upgrade_progress_file)) {
3529                        //writing to the file
3530                 }
3531     }
3532 }
3533
3534 function initialize_session_vars(){
3535   $upgrade_progress_dir = getcwd().'/'.$GLOBALS['sugar_config']['upload_dir'].'upgrades/temp';
3536   $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3537   if(file_exists($upgrade_progress_file)){
3538         include($upgrade_progress_file);
3539         if(isset($upgrade_config) && $upgrade_config != null && is_array($upgrade_config) && sizeof($upgrade_config) >0){
3540                 $currVarsArray=$upgrade_config[1]['upgrade_vars'];
3541                 //print_r($currVarsArray);
3542                 if(isset($currVarsArray) && $currVarsArray != null && is_array($currVarsArray) && sizeof($currVarsArray)>0){
3543                         foreach($currVarsArray as $key=>$val){
3544                                 if($key != null && $val !=null){
3545                                         //set session variables
3546                                         $_SESSION[$key]=$val;
3547                                         //set varibales
3548                                         '$'.$key=$val;
3549                                 }
3550                         }
3551                 }
3552         }
3553   }
3554 }
3555 //track the upgrade progress on each step
3556 //track the upgrade progress on each step
3557 function set_upgrade_progress($currStep,$currState,$currStepSub='',$currStepSubState=''){
3558
3559         $upgrade_progress_dir = getcwd().'/'.$GLOBALS['sugar_config']['upload_dir'].'upgrades/temp';
3560         if(!is_dir($upgrade_progress_dir)){
3561                 mkdir_recursive($upgrade_progress_dir);
3562         }
3563         $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3564         if(file_exists($upgrade_progress_file)){
3565                 include($upgrade_progress_file);
3566         }
3567         else{
3568                 if(function_exists('sugar_fopen')){
3569                         sugar_fopen($upgrade_progress_file, 'w+');
3570                 }
3571                 else{
3572                         fopen($upgrade_progress_file, 'w+');
3573                 }
3574         }
3575         if(!isset($upgrade_config) || $upgrade_config == null){
3576                 $upgrade_config = array();
3577                 $upgrade_config[1]['upgrade_vars']=array();
3578         }
3579     if(!is_array($upgrade_config[1]['upgrade_vars'])){
3580         $upgrade_config[1]['upgrade_vars'] = array();
3581     }
3582         if($currStep != null && $currState != null){
3583                 if(sizeof($upgrade_config) > 0){
3584                         if($currStepSub != null && $currStepSubState !=null){
3585                                 //check if new status to be set or update
3586                                 //get the latest in array. since it has sub components prepare an array
3587                                 if(!empty($upgrade_config[sizeof($upgrade_config)][$currStep]) && is_array($upgrade_config[sizeof($upgrade_config)][$currStep])){
3588                                         $latestStepSub = currSubStep($upgrade_config[sizeof($upgrade_config)][$currStep]);
3589                                         if($latestStepSub == $currStepSub){
3590                                                 $upgrade_config[sizeof($upgrade_config)][$currStep][$latestStepSub]=$currStepSubState;
3591                                                 $upgrade_config[sizeof($upgrade_config)][$currStep][$currStep] = $currState;
3592                                         }
3593                                         else{
3594                                                 $upgrade_config[sizeof($upgrade_config)][$currStep][$currStepSub]=$currStepSubState;
3595                                                 $upgrade_config[sizeof($upgrade_config)][$currStep][$currStep] = $currState;
3596                                         }
3597                                 }
3598                                 else{
3599                                         $currArray = array();
3600                                         $currArray[$currStep] = $currState;
3601                                         $currArray[$currStepSub] = $currStepSubState;
3602                                         $upgrade_config[sizeof($upgrade_config)+1][$currStep] = $currArray;
3603                                 }
3604                         }
3605           else{
3606                                 //get the current upgrade progress
3607                                 $latestStep = get_upgrade_progress();
3608                                 //set the upgrade progress
3609                                 //echo 'latest '.$latestStep;
3610                                 if($latestStep == $currStep){
3611                                         //update the current step with new progress status
3612                                         //echo 'update it';
3613                                         $upgrade_config[sizeof($upgrade_config)][$latestStep]=$currState;
3614                                 }
3615                                 else{
3616                                         //it's a new step
3617                                         //echo 'new it';
3618                                         $upgrade_config[sizeof($upgrade_config)+1][$currStep]=$currState;
3619                                 }
3620                     // now check if there elements within array substeps
3621           }
3622                 }
3623                 else{
3624                         //set the upgrade progress  (just starting)
3625                         $upgrade_config[sizeof($upgrade_config)+1][$currStep]= $currState;
3626                 }
3627
3628                 if(is_writable($upgrade_progress_file) && write_array_to_file( "upgrade_config", $upgrade_config,
3629                 $upgrade_progress_file)) {
3630                //writing to the file
3631                 }
3632
3633         }
3634 }
3635
3636 function get_upgrade_progress(){
3637         $upgrade_progress_dir = getcwd().'/'.$GLOBALS['sugar_config']['upload_dir'].'upgrades/temp';
3638         $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3639         $currState = '';
3640         $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3641
3642         if(file_exists($upgrade_progress_file)){
3643                 include($upgrade_progress_file);
3644                 //echo  'upconf '.$upgrade_config;
3645                 if(!isset($upgrade_config) || $upgrade_config == null){
3646                         $upgrade_config = array();
3647                 }
3648                 if($upgrade_config != null && sizeof($upgrade_config) >1){
3649                         $currArr = $upgrade_config[sizeof($upgrade_config)];
3650                                 //echo 'size of '.sizeof($upgrade_config);
3651                         if(is_array($currArr)){
3652                            foreach($currArr as $key=>$val){
3653                                         $currState = $key;
3654                                 }
3655                         }
3656                 }
3657         }
3658         return $currState;
3659 }
3660 function currSubStep($currStep){
3661         $currSubStep = '';
3662         if(is_array($currStep)){
3663        foreach($currStep as $key=>$val){
3664                     if($key != null){
3665                         $currState = $key;
3666                         }
3667            }
3668         }
3669         return $currState;
3670 }
3671 function currUpgradeState($currState){
3672         $currState = '';
3673         if(is_array($currState)){
3674        foreach($currState as $key=>$val){
3675                         if(is_array($val)){
3676                                 foreach($val as $k=>$v){
3677                                         if($k != null){
3678                                                 $currState = $k;
3679                                         }
3680                                 }
3681                         }
3682                         else{
3683                                 $currState = $key;
3684                         }
3685                 }
3686         }
3687         return $currState;
3688 }
3689
3690 function didThisStepRunBefore($step,$SubStep=''){
3691         if($step == null) return;
3692         $upgrade_progress_dir = getcwd().'/'.$GLOBALS['sugar_config']['upload_dir'].'upgrades/temp';
3693         $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3694         $currState = '';
3695         $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3696         $stepRan = false;
3697         if(file_exists($upgrade_progress_file)){
3698                 include($upgrade_progress_file);
3699                 if(isset($upgrade_config) && $upgrade_config != null && is_array($upgrade_config) && sizeof($upgrade_config) >0){
3700                         for($i=1;$i<=sizeof($upgrade_config);$i++){
3701                           if(is_array($upgrade_config[$i])){
3702                                         foreach($upgrade_config[$i] as $key=>$val){
3703                                                 if($key==$step){
3704                                                         if(is_array($upgrade_config[$i][$step])){
3705                                                                 //now process
3706                                                                 foreach ($upgrade_config[$i][$step] as $k=>$v){
3707                                                                         if(is_array($v)){
3708                                                                                 foreach($v as $k1=>$v1){
3709                                                                                         if($SubStep != null){
3710                                                                                                 if($SubStep ==$k1 && $v1=='done'){
3711                                                                                                         //echo 'Found Inside '.$k1;
3712                                                                                                         $stepRan = true;
3713                                                                                                         break;
3714                                                                                                 }
3715                                                                                         }
3716                                                                                 }//foreach
3717                                                                         }
3718                                                                         elseif($SubStep !=null){
3719                                                                                 if($SubStep==$k && $v=='done'){
3720                                                                                         //echo 'Found1 '.$k;
3721                                                                                         $stepRan = true;
3722                                                                                         break;
3723                                                                                 }
3724                                                                         }
3725                                                                         elseif($step==$k && $v=='done'){
3726                                                                                 //echo 'Found2 '.$k;
3727                                                                                 $stepRan = true;
3728                                                                                 break;
3729                                                                         }
3730                                                                 }//foreach
3731                                                         }
3732                                                         elseif($val=='done'){
3733                                                                 //echo 'Foundmmmm '.$key;
3734                                                                 $stepRan = true;
3735                                                         }
3736                                                 }
3737                                         }//foreach
3738                                 }
3739                         }//for
3740                 }
3741         }
3742         return $stepRan;
3743 }
3744
3745
3746
3747 //get and set post install status
3748 function post_install_progress($progArray='',$action=''){
3749         if($action=='' || $action=='get'){
3750                 //get the state of post install
3751                 $upgrade_progress_dir = getcwd().'/'.$GLOBALS['sugar_config']['upload_dir'].'upgrades/temp';
3752                 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3753         $currProg = array();
3754                 if(file_exists($upgrade_progress_file)){
3755                         include($upgrade_progress_file);
3756                         if(is_array($upgrade_config[sizeof($upgrade_config)]['commit']['post_install']) && sizeof($upgrade_config[sizeof($upgrade_config)]['commit']['post_install'])>0){
3757                                 foreach($upgrade_config[sizeof($upgrade_config)]['commit']['post_install'] as $k=>$v){
3758                                         $currProg[$k]=$v;
3759                                 }
3760                         }
3761                 }
3762                 return $currProg;
3763         }
3764         elseif($action=='set'){
3765                 $upgrade_progress_dir = getcwd().'/'.$GLOBALS['sugar_config']['upload_dir'].'upgrades/temp';
3766                 if(!is_dir($upgrade_progress_dir)){
3767                         mkdir($upgrade_progress_dir);
3768                 }
3769                 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3770                 if(file_exists($upgrade_progress_file)){
3771                         include($upgrade_progress_file);
3772                 }
3773                 else{
3774                         fopen($upgrade_progress_file, 'w+');
3775                 }
3776                 if(!is_array($upgrade_config[sizeof($upgrade_config)]['commit']['post_install'])){
3777                         $upgrade_config[sizeof($upgrade_config)]['commit']['post_install']=array();
3778                         $upgrade_config[sizeof($upgrade_config)]['commit']['post_install']['post_install'] = 'in_progress';
3779                 }
3780                 if($progArray != null && is_array($progArray)){
3781                         foreach($progArray as $key=>$val){
3782                                 $upgrade_config[sizeof($upgrade_config)]['commit']['post_install'][$key]=$val;
3783                         }
3784                 }
3785                 if(is_writable($upgrade_progress_file) && write_array_to_file( "upgrade_config", $upgrade_config,
3786                 $upgrade_progress_file)) {
3787                //writing to the file
3788                 }
3789         }
3790 }
3791
3792
3793 // parse and run sql file
3794 function parseAndExecuteSqlFileExtended($sqlScript){
3795         global $sugar_config;
3796         $alterTableSchema = '';
3797         $db = & DBManagerFactory::getInstance();
3798         if(is_file($sqlScript)) {
3799                 $fp = fopen($sqlScript, 'r');
3800                 $contents = stream_get_contents($fp);
3801             $anyScriptChanges =$contents;
3802                 if(rewind($fp)) {
3803                         $completeLine = '';
3804                         $count = 0;
3805                         while($line = fgets($fp)) {
3806                                 if(strpos($line, '--') === false) {
3807                                         $completeLine .= " ".trim($line);
3808                                         if(strpos($line, ';') !== false) {
3809                                                 $completeLine = str_replace(';','',$completeLine);
3810                             $currLine = explode(",",$completeLine);
3811                             //check if multiple statements are clubbed
3812                             if(sizeof($currLine) >1){
3813                                 $qarr = explode(" ",trim($currLine[0]));
3814                                 if(strtoupper(trim($qarr[0])) == 'CREATE' && strtoupper(trim($qarr[1])) == 'TABLE'){
3815                                     if(strtoupper(trim($qarr[2]) != null)){
3816                                         if($sugar_config['dbconfig']['db_type'] == 'oci8'){
3817                                                 $query= "select table_name from user_tables where table_name=strtoupper(trim($qarr[2]))";
3818                                                                                 $result = $db->query($query);
3819                                                                                 $row = $db->fetchByAssociation($result);
3820                                                                                 if($row['table_name'] != null){
3821                                                                                         //already exists
3822                                                                                 }
3823                                                                                 else{
3824                                                                                         //create table
3825                                                                                         $query= $completeLine;
3826                                                                                         $db->query($query);
3827                                                                                 }
3828                                         }
3829
3830                                     }
3831
3832                                 }
3833                                 else{
3834                                         $qType =trim($qarr[0])." ".trim($qarr[1])." ".trim($qarr[2]);
3835                                         echo trim($currLine[0])."<br />";
3836                                     for ($i = 1; $i <= sizeof($currLine)-1; $i++) {
3837                                                                    $query = $qType." ".trim($currLine[$i]);
3838                                                                    echo $query."<br />";
3839                                                                 }
3840                                 }
3841
3842                             }
3843                             else{
3844                                 echo  trim($currLine[0]);
3845                             }
3846
3847
3848                         //$q3 = $completeLine;
3849                                                 //''$r3 = $GLOBALS['db']->query($q3, false, "Preflight Failed for:");
3850                         //echo mysql_error();
3851                                                 $completeLine = '';
3852                                                 //break;
3853                                         }
3854                                 }
3855                         }
3856                 } else {
3857
3858                         //$sqlErrors[] = $mod_strings['ERR_UW_FILE_NOT_READABLE'].'::'.$sqlScript;
3859                 }
3860         }
3861 }
3862
3863 function repairDBForUpgrade($execute=false,$path=''){
3864
3865         global $current_user, $beanFiles;
3866         global $dictionary;
3867         set_time_limit(3600);
3868
3869         $db = &DBManagerFactory::getInstance();
3870         $sql = '';
3871         VardefManager::clearVardef();
3872         require_once('include/ListView/ListView.php');
3873         foreach ($beanFiles as $bean => $file) {
3874                 require_once ($file);
3875                 $focus = new $bean ();
3876                 $sql .= $db->repairTable($focus, $execute);
3877
3878         }
3879         //echo $sql;
3880         $olddictionary = $dictionary;
3881         unset ($dictionary);
3882         include ('modules/TableDictionary.php');
3883         foreach ($dictionary as $meta) {
3884                 $tablename = $meta['table'];
3885                 $fielddefs = $meta['fields'];
3886                 $indices = $meta['indices'];
3887                 $sql .= $db->repairTableParams($tablename, $fielddefs, $indices, $execute);
3888         }
3889          $qry_str = "";
3890           foreach (explode("\n", $sql) as $line) {
3891                   if (!empty ($line) && substr($line, -2) != "*/") {
3892                         $line .= ";";
3893                   }
3894                   $qry_str .= $line . "\n";
3895            }
3896           $sql = str_replace(
3897           array(
3898                 "\n",
3899                 '&#039;',
3900            ),
3901           array(
3902                 '',
3903                 "'",
3904           ),
3905           preg_replace('#(/\*.+?\*/\n*)#', '', $qry_str)
3906           );
3907          logThis("*******START EXECUTING DB UPGRADE QUERIES***************",$path);
3908                 logThis($sql,$path);
3909          logThis("*******END EXECUTING DB UPGRADE QUERIES****************",$path);
3910          if(!$execute){
3911                 return $sql;
3912          }
3913 }
3914
3915
3916
3917 /**
3918  * upgradeUserPreferences
3919  * This method updates the user_preferences table and sets the pages/dashlets for users
3920  * which have ACL access to Trackers so that the Tracker dashlets are set in their user perferences
3921  *
3922  */
3923 function upgradeUserPreferences() {
3924
3925 }
3926
3927
3928 function add_custom_modules_favorites_search(){
3929     $module_directories = scandir('modules');
3930
3931         foreach($module_directories as $module_dir){
3932                 if($module_dir == '.' || $module_dir == '..' || !is_dir("modules/{$module_dir}")){
3933                         continue;
3934                 }
3935
3936                 $matches = array();
3937                 preg_match('/^[a-z0-9]{1,5}_[a-z0-9_]+$/i' , $module_dir, $matches);
3938
3939                 // Make sure the module was created by module builder
3940                 if(empty($matches)){
3941                         continue;
3942                 }
3943
3944                 $full_module_dir = "modules/{$module_dir}/";
3945                 $read_searchdefs_from = "{$full_module_dir}/metadata/searchdefs.php";
3946                 $read_SearchFields_from = "{$full_module_dir}/metadata/SearchFields.php";
3947                 $read_custom_SearchFields_from = "custom/{$full_module_dir}/metadata/SearchFields.php";
3948
3949                 // Studio can possibly override this file, so we check for a custom version of it
3950                 if(file_exists("custom/{$full_module_dir}/metadata/searchdefs.php")){
3951                         $read_searchdefs_from = "custom/{$full_module_dir}/metadata/searchdefs.php";
3952                 }
3953
3954                 if(file_exists($read_searchdefs_from) && file_exists($read_SearchFields_from)){
3955                         $found_sf1 = false;
3956                         $found_sf2 = false;
3957                         require($read_searchdefs_from);
3958                         foreach($searchdefs[$module_dir]['layout']['basic_search'] as $sf_array){
3959                                 if(isset($sf_array['name']) && $sf_array['name'] == 'favorites_only'){
3960                                         $found_sf1 = true;
3961                                 }
3962                         }
3963
3964                         require($read_SearchFields_from);
3965                         if(isset($searchFields[$module_dir]['favorites_only'])){
3966                                 $found_sf2 = true;
3967                         }
3968
3969                         if(!$found_sf1 && !$found_sf2){
3970                                 $searchdefs[$module_dir]['layout']['basic_search']['favorites_only'] = array('name' => 'favorites_only','label' => 'LBL_FAVORITES_FILTER','type' => 'bool',);
3971                                 $searchdefs[$module_dir]['layout']['advanced_search']['favorites_only'] = array('name' => 'favorites_only','label' => 'LBL_FAVORITES_FILTER','type' => 'bool',);
3972                                 $searchFields[$module_dir]['favorites_only'] = array(
3973                                         'query_type'=>'format',
3974                                         'operator' => 'subquery',
3975                                         'subquery' => 'SELECT sugarfavorites.record_id FROM sugarfavorites
3976                                                                 WHERE sugarfavorites.deleted=0
3977                                                                         and sugarfavorites.module = \''.$module_dir.'\'
3978                                                                         and sugarfavorites.assigned_user_id = \'{0}\'',
3979                                         'db_field'=>array('id')
3980                                 );
3981
3982                                 if(!is_dir("custom/{$full_module_dir}/metadata")){
3983                                         mkdir_recursive("custom/{$full_module_dir}/metadata");
3984                                 }
3985                                 $success_sf1 = write_array_to_file('searchdefs', $searchdefs, "custom/{$full_module_dir}/metadata/searchdefs.php");
3986                                 $success_sf2 = write_array_to_file('searchFields', $searchFields, "{$full_module_dir}/metadata/SearchFields.php");
3987
3988                                 if(!$success_sf1){
3989                                         logThis("add_custom_modules_favorites_search failed for searchdefs.php for {$module_dir}");
3990                                 }
3991                                 if(!$success_sf2){
3992                                         logThis("add_custom_modules_favorites_search failed for SearchFields.php for {$module_dir}");
3993                                 }
3994                                 if($success_sf1 && $success_sf2){
3995                                         logThis("add_custom_modules_favorites_search successfully updated searchdefs and searchFields for {$module_dir}");
3996                                 }
3997                         }
3998                 }
3999         }
4000 }
4001
4002
4003 /**
4004  * upgradeModulesForTeamsets
4005  *
4006  * This method adds the team_set_id values to the module tables that have the new team_set_id column
4007  * added through the SugarCRM 5.5.x upgrade process.  It also adds the values into the team_sets and
4008  * team_sets_teams tables.
4009  *
4010  * @param filter Array of modules to process; empty by default
4011  */
4012 function upgradeModulesForTeamsets($filter=array()) {
4013     require('include/modules.php');
4014         foreach($beanList as $moduleName=>$beanName) {
4015                     if(!empty($filter) && array_search($moduleName, $filter) === false) {
4016                        continue;
4017                     }
4018                 if($moduleName == 'TeamMemberships' || $moduleName == 'ForecastOpportunities'){
4019                 continue;
4020             }
4021                         $bean = loadBean($moduleName);
4022                         if(empty($bean) ||
4023                            empty($bean->table_name)) {
4024                            continue;
4025                         }
4026
4027                         $FieldArray = $GLOBALS['db']->helper->get_columns($bean->table_name);
4028                         if(!isset($FieldArray['team_id'])) {
4029                            continue;
4030                         }
4031
4032                         upgradeTeamColumn($bean, 'team_id');
4033
4034         } //foreach
4035
4036     //Upgrade users table
4037         $bean = loadBean('Users');
4038         upgradeTeamColumn($bean, 'default_team');
4039         $result = $GLOBALS['db']->query("SELECT id FROM teams where deleted=0");
4040         while($row = $GLOBALS['db']->fetchByAssoc($result)) {
4041               $teamset = new TeamSet();
4042               $teamset->addTeams($row['id']);
4043         }
4044 }
4045
4046
4047 /**
4048  * upgradeTeamColumn
4049  * Helper function to create a team_set_id column and also set team_set_id column
4050  * to have the value of the $column_name parameter
4051  *
4052  * @param $bean SugarBean which we are adding team_set_id column to
4053  * @param $column_name The name of the column containing the default team_set_id value
4054  */
4055 function upgradeTeamColumn($bean, $column_name) {
4056         //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
4057         //module that does not use the SugarObjects
4058         if(empty($bean->field_defs['team_set_id']) && $bean->module_dir != 'Trackers'){
4059
4060                 //at this point we could assume that since we have a team_id defined and not a team_set_id that we need to
4061                 //add that field and the corresponding relationships
4062                 $object = $bean->object_name;
4063                 $module = $bean->module_dir;
4064                 $object_name = $object;
4065                 $_object_name = strtolower($object_name);
4066
4067                 if(!empty($GLOBALS['dictionary'][$object]['table'])){
4068                         $table_name = $GLOBALS['dictionary'][$object]['table'];
4069                 }else{
4070                         $table_name = strtolower($module);
4071                 }
4072
4073                 $path = 'include/SugarObjects/implements/team_security/vardefs.php';
4074                 require($path);
4075                 //go through each entry in the vardefs from team_security and unset anything that is already set in the core module
4076                 //this will ensure we have the proper ordering.
4077                 $fieldDiff = array_diff_assoc($vardefs['fields'], $GLOBALS['dictionary'][$bean->object_name]['fields']);
4078
4079                 $file = 'custom/Extension/modules/' . $bean->module_dir. '/Ext/Vardefs/teams.php';
4080                 $contents = "<?php\n";
4081                 if(!empty($fieldDiff)){
4082                         foreach($fieldDiff as $key => $val){
4083                                 $contents .= "\n\$GLOBALS['dictionary']['". $object . "']['fields']['". $key . "']=" . var_export_helper($val) . ";";
4084                         }
4085                 }
4086                 $relationshipDiff = array_diff_assoc($vardefs['relationships'], $GLOBALS['dictionary'][$bean->object_name]['relationships']);
4087                 if(!empty($relationshipDiff)){
4088                         foreach($relationshipDiff as $key => $val){
4089                                 $contents .= "\n\$GLOBALS['dictionary']['". $object . "']['relationships']['". $key . "']=" . var_export_helper($val) . ";";
4090                         }
4091                 }
4092                 $indexDiff = array_diff_assoc($vardefs['indices'], $GLOBALS['dictionary'][$bean->object_name]['indices']);
4093                 if(!empty($indexDiff)){
4094                         foreach($indexDiff as $key => $val){
4095                                         $contents .= "\n\$GLOBALS['dictionary']['". $object . "']['indices']['". $key . "']=" . var_export_helper($val) . ";";
4096                         }
4097                 }
4098                 if( $fh = @sugar_fopen( $file, 'wt' ) )
4099             {
4100                 fputs( $fh, $contents);
4101                 fclose( $fh );
4102             }
4103
4104
4105                 //we have written out the teams.php into custom/Extension/modules/{$module_dir}/Ext/Vardefs/teams.php'
4106                 //now let's merge back into vardefs.ext.php
4107                 require_once('ModuleInstall/ModuleInstaller.php');
4108                 $mi = new ModuleInstaller();
4109                 $mi->merge_files('Ext/Vardefs/', 'vardefs.ext.php');
4110                 VardefManager::loadVardef($bean->module_dir, $bean->object_name, true);
4111                 $bean->field_defs = $GLOBALS['dictionary'][$bean->object_name]['fields'];
4112         }
4113
4114         if(isset($bean->field_defs['team_set_id'])) {
4115                 //Create the team_set_id column
4116                 $FieldArray = $GLOBALS['db']->helper->get_columns($bean->table_name);
4117                 if(!isset($FieldArray['team_set_id'])) {
4118                         $GLOBALS['db']->addColumn($bean->table_name, $bean->field_defs['team_set_id']);
4119                 }
4120                 $indexArray =  $GLOBALS['db']->helper->get_indices($bean->table_name);
4121                 
4122         $indexName = getValidDBName('idx_'.strtolower($bean->table_name).'_tmst_id', true, 34);
4123         $indexDef = array(
4124                                          array(
4125                                                 'name' => $indexName,
4126                                                 'type' => 'index',
4127                                                 'fields' => array('team_set_id')
4128                                          )
4129                                    );
4130                 if(!isset($indexArray[$indexName])) {
4131                         $GLOBALS['db']->addIndexes($bean->table_name, $indexDef);
4132                 }
4133
4134                 //Update the table's team_set_id column to have the same values as team_id
4135             $GLOBALS['db']->query("UPDATE {$bean->table_name} SET team_set_id = {$column_name}");
4136         }
4137 }
4138
4139 /**
4140  *  Update the folder subscription table which confirms to the team security mechanism but
4141  *  the class SugarFolders does not extend SugarBean and is therefore never picked up by the
4142  *  upgradeModulesForTeamsets function.
4143  */
4144 function upgradeFolderSubscriptionsTeamSetId()
4145 {
4146     logThis("In upgradeFolderSubscriptionsTeamSetId()");
4147     $query = "UPDATE folders SET team_set_id = team_id";
4148     $result = $GLOBALS['db']->query($query);
4149     logThis("Finished upgradeFolderSubscriptionsTeamSetId()");
4150 }
4151
4152 /**
4153  * upgradeModulesForTeam
4154  *
4155  * This method update the associated_user_id, name, name_2 to the private team records on teams table
4156  * This function is used for upgrade process from 5.1.x and 5.2.x.
4157  *
4158  */
4159 function upgradeModulesForTeam() {
4160     logThis("In upgradeModulesForTeam()");
4161     $result = $GLOBALS['db']->query("SELECT id, user_name, first_name, last_name FROM users where deleted=0");
4162
4163     while($row = $GLOBALS['db']->fetchByAssoc($result)) {
4164         $results2 = $GLOBALS['db']->query("SELECT id FROM teams WHERE name = '({$row['user_name']})'");
4165         $assoc = '';
4166                 if(!$assoc = $GLOBALS['db']->fetchByAssoc($results2)) {
4167                         //if team does not exist, then lets create the team for this user
4168                         $team = new Team();
4169                         $user = new User();
4170                         $user->retrieve($row['id']);
4171                         $team->new_user_created($user);
4172                         $team_id = $team->id;
4173                 }else{
4174                         $team_id =$assoc['id'];
4175                 }
4176
4177                         //upgrade the team
4178                         $name = is_null($row['first_name'])?'':$row['first_name'];
4179                         $name_2 = is_null($row['last_name'])?'':$row['last_name'];
4180                         $associated_user_id = $row['id'];
4181
4182                         //Bug 32914
4183                         //Ensure team->name is not empty by using team->name_2 if available
4184                         if(empty($name) && !empty($name_2)) {
4185                            $name = $name_2;
4186                            $name_2 = '';
4187                         }
4188
4189                         $query = "UPDATE teams SET name = '{$name}', name_2 = '{$name_2}', associated_user_id = '{$associated_user_id}' WHERE id = '{$team_id}'";
4190                         $GLOBALS['db']->query($query);
4191     } //while
4192
4193     //Update the team_set_id and default_team columns
4194     $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'));
4195
4196     //Update team_set_id
4197         if($ce_to_pro_or_ent) {
4198            $GLOBALS['db']->query("update users set team_set_id = (select teams.id from teams where teams.associated_user_id = users.id)");
4199            $GLOBALS['db']->query("update users set default_team = (select teams.id from teams where teams.associated_user_id = users.id)");
4200         }
4201
4202 }
4203
4204
4205     function addNewSystemTabsFromUpgrade($from_dir){
4206         global $path;
4207         if(isset($_SESSION['upgrade_from_flavor'])){
4208
4209             //check to see if there are any new files that need to be added to systems tab
4210             //retrieve old modules list
4211             logThis('check to see if new modules exist',$path);
4212             $oldModuleList = array();
4213             $newModuleList = array();
4214             include($from_dir.'/include/modules.php');
4215             $oldModuleList = $moduleList;
4216             include('include/modules.php');
4217             $newModuleList = $moduleList;
4218
4219             //include tab controller
4220             require_once('modules/MySettings/TabController.php');
4221             $newTB = new TabController();
4222
4223             //make sure new modules list has a key we can reference directly
4224             $newModuleList = $newTB->get_key_array($newModuleList);
4225             $oldModuleList = $newTB->get_key_array($oldModuleList);
4226
4227             //iterate through list and remove commonalities to get new modules
4228             foreach ($newModuleList as $remove_mod){
4229                 if(in_array($remove_mod, $oldModuleList)){
4230                     unset($newModuleList[$remove_mod]);
4231                 }
4232             }
4233             //new modules list now has left over modules which are new to this install, so lets add them to the system tabs
4234             logThis('new modules to add are '.var_export($newModuleList,true),$path);
4235
4236             if(!empty($newModuleList))
4237             {
4238                     //grab the existing system tabs
4239                     $tabs = $newTB->get_system_tabs();
4240         
4241                     //add the new tabs to the array
4242                     foreach($newModuleList as $nm ){
4243                       $tabs[$nm] = $nm;
4244                     }
4245         
4246                     $newTB->set_system_tabs($tabs);
4247             }
4248             logThis('module tabs updated',$path);
4249         }
4250     }
4251
4252     /**
4253      * fix_dropdown_list
4254      * This method attempts to fix dropdown lists that were incorrectly named.
4255      * There were versions of SugarCRM that did not enforce naming convention rules
4256      * for the dropdown list field name.  This method attempts to resolve that by
4257      * fixing the language files that may have been affected and then updating the
4258      * fields_meta_data table accordingly.  It also refreshes any vardefs that may
4259      * have been affected.
4260      *
4261      */
4262         function fix_dropdown_list() {
4263         if(file_exists('custom/include/language')) {
4264            $files = array();
4265            $affected_modules = array();
4266            $affected_keys = array();
4267
4268            getFiles($files, 'custom/include/language', '/\.php$/i');
4269            foreach($files as $file) {
4270
4271               if(file_exists($file . '.bak')) {
4272                  $bak_mod_time = filemtime($file . '.bak');
4273                  $php_mod_time = filemtime($file);
4274                  //We're saying if the .php file was modified 30 seconds no more than php.bak file then we
4275                  //run these additional cleanup checks
4276                  if($php_mod_time - $bak_mod_time < 30) {
4277
4278                         $app_list_strings = array();
4279                         $GLOBALS['app_list_strings'] = array();
4280                         require($file . '.bak');
4281                         $bak_app_list_strings = array_merge($app_list_strings, $GLOBALS['app_list_strings']);
4282
4283                         $app_list_strings = array();
4284                         $GLOBALS['app_list_strings'] = array();
4285                         require($file);
4286                         $php_app_list_strings = array_merge($app_list_strings, $GLOBALS['app_list_strings']);
4287
4288                         //Get the file contents
4289                         $contents = file_get_contents($file);
4290
4291                         //Now simulate a fix for the file before we compare w/ the .php file
4292                         //we also append to the $contents
4293                         foreach($bak_app_list_strings as $key=>$entry) {
4294                                                    if(preg_match('/([^A-Za-z_])/', $key, $matches) && is_array($entry)) {
4295                                                           $new_key = preg_replace('/[^A-Za-z_]/', '_', $key);
4296                                                           $bak_app_list_strings[$new_key] = $bak_app_list_strings[$key];
4297                                                           unset($bak_app_list_strings[$key]);
4298                                                           //Now if the entry doesn't exists in the .php file, then add to contents
4299                                                           if(!isset($php_app_list_strings[$new_key])) {
4300                                                                  $contents .= "\n\$GLOBALS['app_list_strings']['{$new_key}'] = " . var_export_helper($bak_app_list_strings[$new_key]) . ";";
4301                                                           }
4302                                                    } //if
4303                         } //foreach
4304
4305                         //Now load the .php file to do the comparison
4306                         foreach($php_app_list_strings as $key=>$entry) {
4307                                 if(isset($bak_app_list_strings[$key])) {
4308                                         $diff = array_diff($bak_app_list_strings[$key], $entry);
4309                                         if(!empty($diff)) {
4310                                            //There is a difference, so copy the $bak_app_list_strings version into the .php file
4311                                            $contents .= "\n\$GLOBALS['app_list_strings']['{$key}'] = " . var_export_helper($bak_app_list_strings[$key]) . ";";
4312                                         } //if
4313                                 } //if
4314                         } //foreach
4315
4316                         //Now write out the file contents
4317                         //Create backup just in case
4318                         copy($file, $file . '.php_bak');
4319                                         $fp = @sugar_fopen($file, 'w');
4320                         if($fp) {
4321                                fwrite($fp, $contents);
4322                                fclose($fp);
4323                         } else {
4324                            $GLOBALS['log']->error("Unable to update file contents in fix_dropdown_list for {$file}");
4325                         } //if-else
4326                  }
4327               }
4328
4329               unset($GLOBALS['app_strings']);
4330               unset($GLOBALS['app_list_strings']);
4331               $app_list_strings = array();
4332                   require($file);
4333                   $touched = false;
4334                   $contents = file_get_contents($file);
4335                   if ( !isset($GLOBALS['app_list_strings']) ) {
4336                       $GLOBALS['app_list_strings'] = $app_list_strings;
4337                   }
4338                   else {
4339                       $GLOBALS['app_list_strings'] = array_merge($app_list_strings, $GLOBALS['app_list_strings']);
4340                   }
4341
4342                   if(isset($GLOBALS['app_list_strings']) && is_array($GLOBALS['app_list_strings'])) {
4343                          foreach($GLOBALS['app_list_strings'] as $key=>$entry) {
4344                                 if(preg_match('/([^A-Za-z_])/', $key, $matches) && is_array($entry)) {
4345                                    $result = $GLOBALS['db']->query("SELECT custom_module FROM fields_meta_data WHERE ext1 = '{$key}'");
4346                                    if(!empty($result)) {
4347                                           while($row = $GLOBALS['db']->fetchByAssoc($result)) {
4348                                                     $custom_module = $row['custom_module'];
4349                                                     if(!empty($GLOBALS['beanList'][$custom_module])) {
4350                                                    $affected_modules[$custom_module] = $GLOBALS['beanList'][$custom_module];
4351                                                     }
4352                                           } //while
4353                                    }
4354
4355                                    //Replace all invalid characters with '_' character
4356                                    $new_key = preg_replace('/[^A-Za-z_]/', '_', $key);
4357                                    $affected_keys[$key] = $new_key;
4358
4359                                    $GLOBALS['app_list_strings'][$new_key] = $GLOBALS['app_list_strings'][$key];
4360                                    unset($GLOBALS['app_list_strings'][$key]);
4361
4362                                    $pattern_match = "/(\[\s*\'{$key}\'\s*\])/";
4363                                    $new_key = "['{$new_key}']";
4364                                    $out = preg_replace($pattern_match, $new_key, $contents);
4365                                    $contents = $out;
4366                                    $touched = true;
4367                                 } //if
4368                          } //foreach
4369
4370                  //This is a check for g => h instances where the file contents were incorrectly written
4371                  //and also fixes the scenario where via a UI upgrade, the app_list_strings were incorrectly
4372                  //merged with app_list_strings variables declared elsewhere
4373                          if(!$touched) {
4374                                    if(preg_match('/\$GLOBALS\s*\[\s*[\"|\']app_list_strings[\"|\']\s*\]\s*=\s*array\s*\(/', $contents)) {
4375                                           //Now also remove all the non-custom labels that were added
4376                                           if(preg_match('/language\/([^\.]+)\.lang\.php$/', $file, $matches)) {
4377                                                 $language = $matches[1];
4378
4379                                                 $app_list_strings = array();
4380
4381                                         if(file_exists("include/language/$language.lang.php")) {
4382                                                                    include("include/language/$language.lang.php");
4383                                                                 }
4384                                                                 if(file_exists("include/language/$language.lang.override.php")) {
4385                                                                    $app_list_strings =  _mergeCustomAppListStrings("include/language/$language.lang.override.php" , $app_list_strings) ;
4386                                                                 }
4387                                                                 if(file_exists("custom/application/Ext/Language/$language.ext.lang.php")) {
4388                                                                    $app_list_strings =  _mergeCustomAppListStrings("custom/application/Ext/Language/$language.ext.lang.php" , $app_list_strings) ;
4389                                                                 }
4390                                                                 if(file_exists("custom/application/Ext/Language/$language.lang.ext.php")) {
4391                                                                    $app_list_strings =  _mergeCustomAppListStrings("custom/application/Ext/Language/$language.lang.ext.php" , $app_list_strings) ;
4392                                                                 }
4393
4394                                                                 $all_non_custom_include_language_strings = $app_strings;
4395                                                                 $all_non_custom_include_language_list_strings = $app_list_strings;
4396
4397                                                                 $unset_keys = array();
4398                                                                 if(!empty($GLOBALS['app_list_strings'])) {
4399                                                                         foreach($GLOBALS['app_list_strings'] as $key=>$value) {
4400                                                                                 $diff = array();
4401                                                                                 if(isset($all_non_custom_include_language_list_strings[$key])) {
4402                                                                                         $diff = array_diff($all_non_custom_include_language_list_strings[$key], $GLOBALS['app_list_strings'][$key]);
4403                                                                                 }
4404
4405                                                                                 if(!empty($all_non_custom_include_language_list_strings[$key]) && empty($diff)) {
4406                                                                                         $unset_keys[] = $key;
4407                                                                                 }
4408                                                                         }
4409                                                                 }
4410
4411                                                                 foreach($unset_keys as $key) {
4412                                                                         unset($GLOBALS['app_list_strings'][$key]);
4413                                                                 }
4414
4415                                                                 if(!empty($GLOBALS['app_strings'])) {
4416                                                                 foreach($GLOBALS['app_strings'] as $key=>$value) {
4417                                                                                 if(!empty($all_non_custom_include_language_strings[$key])) {
4418                                                                                    unset($GLOBALS['app_strings'][$key]);
4419                                                                                 }
4420                                                                 }
4421                                                                 }
4422                                           } //if(preg_match...)
4423
4424                                       $out = "<?php \n";
4425                                       if(!empty($GLOBALS['app_strings'])) {
4426                                              foreach($GLOBALS['app_strings'] as $key=>$entry) {
4427                                                      $out .= "\n\$GLOBALS['app_strings']['$key']=" . var_export_helper($entry) . ";";
4428                                              }
4429                                       }
4430
4431                                                   foreach($GLOBALS['app_list_strings'] as $key=>$entry) {
4432                                                                   $out .= "\n\$GLOBALS['app_list_strings']['$key']=" . var_export_helper($entry) . ";";
4433                                                   } //foreach
4434
4435                                                   $touched = true;
4436                                    } //if(preg_match...)
4437                          } //if(!$touched)
4438
4439                          if($touched) {
4440                                  //Create a backup just in case
4441                                  copy($file, $file . '.bak');
4442                          $fp = @sugar_fopen($file, 'w');
4443                          if($fp) {
4444                                fwrite($fp, $out);
4445                                fclose($fp);
4446                          } else {
4447                            //If we can't update the file, just return
4448                            $GLOBALS['log']->error("Unable to update file contents in fix_dropdown_list.");
4449                            return;
4450                          }
4451                          } //if($touched)
4452                   } //if
4453
4454            } //foreach($files)
4455
4456            //Update db entries (the order matters here... need to process database changes first)
4457            if(!empty($affected_keys)) {
4458                   foreach($affected_keys as $old_key=>$new_key) {
4459                                   $GLOBALS['db']->query("UPDATE fields_meta_data SET ext1 = '{$new_key}' WHERE ext1 = '{$old_key}'");
4460                   }
4461            }
4462
4463            //Update vardef files for affected modules
4464            if(!empty($affected_modules)) {
4465                   foreach($affected_modules as $module=>$object) {
4466                           VardefManager::refreshVardefs($module, $object);
4467                   }
4468            }
4469         }
4470         }
4471
4472
4473         function update_iframe_dashlets(){
4474                 require_once('cache/dashlets/dashlets.php');
4475
4476                 $db = DBManagerFactory::getInstance();
4477                 $query = "SELECT id, contents, assigned_user_id FROM user_preferences WHERE deleted = 0 AND category = 'Home'";
4478                 $result = $db->query($query, true, "Unable to update new default dashlets! ");
4479                 while ($row = $db->fetchByAssoc($result)) {
4480                         $content = unserialize(base64_decode($row['contents']));
4481                         $assigned_user_id = $row['assigned_user_id'];
4482                         $record_id = $row['id'];
4483
4484                         $current_user = new User();
4485                         $current_user->retrieve($row['assigned_user_id']);
4486
4487                         if(!empty($content['dashlets']) && !empty($content['pages'])){
4488                                 $originalDashlets = $content['dashlets'];
4489                                 foreach($originalDashlets as $key => $ds){
4490                                     if(!empty($ds['options']['url']) && stristr($ds['options']['url'],'http://www.sugarcrm.com/crm/product/gopro')){
4491                                                 unset($originalDashlets[$key]);
4492                                         }
4493                                 }
4494                                 $current_user->setPreference('dashlets', $originalDashlets, 0, 'Home');
4495                         }
4496                 }
4497         }
4498
4499
4500     /**
4501      * convertImageToText
4502      * This method attempts to convert date type image to text on Microsoft SQL Server.
4503      * This method could NOT be used in any other type of datebases.
4504      */
4505         function convertImageToText($table_name,$column_name){
4506                 $set_lang = "SET LANGUAGE us_english";
4507                 $GLOBALS['db']->query($set_lang);
4508             if($GLOBALS['db']->checkError()){
4509             logThis('An error occurred when performing this query-->'.$set_lang);
4510         }
4511        $q="SELECT data_type
4512         FROM INFORMATION_SCHEMA.Tables T JOIN INFORMATION_SCHEMA.Columns C
4513         ON T.TABLE_NAME = C.TABLE_NAME where T.TABLE_NAME = '$table_name' and C.COLUMN_NAME = '$column_name'";
4514        $res= $GLOBALS['db']->query($q);
4515        if($GLOBALS['db']->checkError()){
4516             logThis('An error occurred when performing this query-->'.$q);
4517         }
4518        $row= $GLOBALS['db']->fetchByAssoc($res);
4519
4520      if(trim(strtolower($row['data_type'])) == 'image'){
4521         $addContent_temp = "alter table {$table_name} add {$column_name}_temp text null";
4522         $GLOBALS['db']->query($addContent_temp);
4523         if($GLOBALS['db']->checkError()){
4524             logThis('An error occurred when performing this query-->'.$addContent_temp);
4525         }
4526         $qN = "select count=datalength({$column_name}), id, {$column_name} from {$table_name}";
4527         $result = $GLOBALS['db']->query($qN);
4528         while($row = $GLOBALS['db']->fetchByAssoc($result)){
4529            if($row['count'] >8000){
4530                 $contentLength = $row['count'];
4531                 $start = 1;
4532                 $next=8000;
4533                 $convertedContent = '';
4534                 while($contentLength >0){
4535                     $stepsQuery = "select cont=convert(varchar(max), convert(varbinary(8000), substring({$column_name},{$start},{$next}))) from {$table_name} where id= '{$row['id']}'";
4536                     $steContQ = $GLOBALS['db']->query($stepsQuery);
4537                     if($GLOBALS['db']->checkError()){
4538                         logThis('An error occurred when performing this query-->'.$stepsQuery);
4539                     }
4540                     $stepCont = $GLOBALS['db']->fetchByAssoc($steContQ);
4541                     if(isset($stepCont['cont'])){
4542                         $convertedContent = $convertedContent.$stepCont['cont'];
4543                     }
4544                     $start = $start+$next;
4545                     $contentLength = $contentLength - $next;
4546                 }
4547                 $addContentDataText="update {$table_name} set {$column_name}_temp = '{$convertedContent}' where id= '{$row['id']}'";
4548                 $GLOBALS['db']->query($addContentDataText);
4549                 if($GLOBALS['db']->checkError()){
4550                     logThis('An error occurred when performing this query-->'.$addContentDataText);
4551                 }
4552            }
4553            else{
4554                 $addContentDataText="update {$table_name} set {$column_name}_temp =
4555                 convert(varchar(max), convert(varbinary(8000), {$column_name})) where id= '{$row['id']}'";
4556                 $GLOBALS['db']->query($addContentDataText);
4557                 if($GLOBALS['db']->checkError()){
4558                     logThis('An error occurred when performing this query-->'.$addContentDataText);
4559                 }
4560            }
4561         }
4562         //drop the contents now and change contents_temp to contents
4563         $dropColumn = "alter table {$table_name} drop column {$column_name}";
4564         $GLOBALS['db']->query($dropColumn);
4565         if($GLOBALS['db']->checkError()){
4566             logThis('An error occurred when performing this query-->'.$dropColumn);
4567         }
4568         $changeColumnName = "EXEC sp_rename '{$table_name}.[{$column_name}_temp]','{$column_name}','COLUMN'";
4569         $GLOBALS['db']->query($changeColumnName);
4570         if($GLOBALS['db']->checkError()){
4571             logThis('An error occurred when performing this query-->'.$changeColumnName);
4572         }
4573      }
4574     }
4575
4576          /**
4577      * clearHelpFiles
4578      * This method attempts to delete all English inline help files.
4579      * This method was introduced by 5.5.0RC2.
4580      */
4581     function clearHelpFiles(){
4582                 $modulePath = clean_path(getcwd() . '/modules');
4583                 $allHelpFiles = array();
4584                 getFiles($allHelpFiles, $modulePath, "/en_us.help.*/");
4585
4586                 foreach( $allHelpFiles as $the_file ){
4587                 if( is_file( $the_file ) ){
4588                     unlink( $the_file );
4589                     logThis("Deleted file: $the_file");
4590                 }
4591             }
4592         }
4593
4594
4595
4596         /**
4597          * upgradeDateTimeFields
4598          *
4599          * This method came from bug: 39757 where the date_end field is a date field and not a datetime field
4600          * which prevents you from performing timezone offset calculations once the data has been saved.
4601          *
4602          * @param path String location to log file, empty by default
4603          */
4604         function upgradeDateTimeFields($path=''){
4605                 //bug: 39757
4606                 global $db;
4607                 if($db->dbType == 'mysql')
4608                 {
4609                         $meetingsSql = "UPDATE meetings SET date_end = date_add(date_start, INTERVAL + CONCAT(duration_hours, ':', duration_minutes) HOUR_MINUTE)";
4610                         $callsSql = "UPDATE calls SET date_end = date_add(date_start, INTERVAL + CONCAT(duration_hours, ':', duration_minutes) HOUR_MINUTE)";
4611                 } else if($db->dbType == 'mssql') {
4612                         $meetingsSql = "UPDATE meetings set date_end = DATEADD(hh, duration_hours, DATEADD(mi, duration_minutes, date_start))";
4613                         $callsSql = "UPDATE calls set date_end = DATEADD(hh, duration_hours, DATEADD(mi, duration_minutes, date_start))";
4614                 } else if ($db->dbType == 'oci8') {
4615                         $meetingsSql = "UPDATE meetings SET date_end = date_start + duration_hours/24 + duration_minutes/1440";
4616                         $callsSql = "UPDATE calls SET date_end = date_start + duration_hours/24 + duration_minutes/1440";
4617                 }
4618
4619                 if(isset($meetingsSql) && isset($callsSql))
4620                 {
4621                         logThis('upgradeDateTimeFields Meetings SQL:' . $meetingsSql, $path);
4622                         $db->query($meetingsSql);
4623
4624                         logThis('upgradeDateTimeFields Calls SQL:' . $callsSql, $path);
4625                         $db->query($callsSql);
4626                 }
4627         }
4628
4629
4630
4631         /**
4632          * upgradeDocumentTypeFields
4633          *
4634          */
4635         function upgradeDocumentTypeFields($path){
4636                 //bug: 39757
4637                 global $db;
4638
4639                 $documentsSql = "UPDATE documents SET doc_type = 'Sugar' WHERE doc_type IS NULL";
4640                 $meetingsSql = "UPDATE meetings SET type = 'Sugar' WHERE type IS NULL";
4641
4642                 logThis('upgradeDocumentTypeFields Documents SQL:' . $documentsSql, $path);
4643                 $db->query($documentsSql);
4644                 logThis('upgradeDocumentTypeFields Meetings SQL:' . $meetingsSql, $path);
4645                 $db->query($meetingsSql);
4646         }
4647
4648
4649 /**
4650  * merge_config_si_settings
4651  * This method checks for the presence of a config_si.php file and, if found, merges the configuration
4652  * settings from the config_si.php file into config.php.  If a config_si_location parameter value is not
4653  * supplied it will attempt to discover the config_si.php file location from where the executing script
4654  * was invoked.
4655  *
4656  * @param write_to_upgrade_log boolean optional value to write to the upgradeWizard.log file
4657  * @param config_location String optional value to config.php file location
4658  * @param config_si_location String optional value to config_si.php file location
4659  * @param path String file of the location of log file to write to
4660  * @return boolean value indicating whether or not a merge was attempted with config_si.php file
4661  */
4662 function merge_config_si_settings($write_to_upgrade_log=false, $config_location='', $config_si_location='', $path='')
4663 {
4664         if(!empty($config_location) && !file_exists($config_location))
4665         {
4666                 if($write_to_upgrade_log)
4667                 {
4668                logThis('config.php file specified in ' . $config_si_location . ' could not be found.  Skip merging', $path);
4669                 }
4670             return false;
4671         } else if(empty($config_location)) {
4672                 global $argv;
4673                 //We are assuming this is from the silentUpgrade scripts so argv[3] will point to SugarCRM install location
4674                 if(isset($argv[3]) && is_dir($argv[3]))
4675                 {
4676                         $config_location = $argv[3] . DIRECTORY_SEPARATOR . 'config.php';
4677                 }
4678         }
4679
4680         //If config_location is still empty or if the file cannot be found, skip merging
4681         if(empty($config_location) || !file_exists($config_location))
4682         {
4683            if($write_to_upgrade_log)
4684            {
4685                   logThis('config.php file at (' . $config_location . ') could not be found.  Skip merging.', $path);
4686            }
4687            return false;
4688         } else {
4689            if($write_to_upgrade_log)
4690            {
4691               logThis('Loading config.php file at (' . $config_location . ') for merging.', $path);
4692            }
4693
4694            include($config_location);
4695            if(empty($sugar_config))
4696            {
4697                   if($write_to_upgrade_log)
4698                   {
4699                      logThis('config.php contents are empty.  Skip merging.', $path);
4700                   }
4701                   return false;
4702            }
4703         }
4704
4705         if(!empty($config_si_location) && !file_exists($config_si_location))
4706         {
4707                 if($write_to_upgrade_log)
4708                 {
4709                logThis('config_si.php file specified in ' . $config_si_location . ' could not be found.  Skip merging', $path);
4710                 }
4711             return false;
4712         } else if(empty($config_si_location)) {
4713                 if(isset($argv[0]) && is_file($argv[0]))
4714                 {
4715                         $php_file = $argv[0];
4716                         $p_info = pathinfo($php_file);
4717                         $php_dir = (isset($p_info['dirname']) && $p_info['dirname'] != '.') ?  $p_info['dirname'] . DIRECTORY_SEPARATOR : '';
4718                         $config_si_location = $php_dir . 'config_si.php';
4719                 }
4720         }
4721
4722         //If config_si_location is still empty or if the file cannot be found, skip merging
4723         if(empty($config_si_location) || !file_exists($config_si_location))
4724         {
4725            if($write_to_upgrade_log)
4726            {
4727               logThis('config_si.php file at (' . $config_si_location . ') could not be found.  Skip merging.', $path);
4728            }
4729            return false;
4730         } else {
4731            if($write_to_upgrade_log)
4732            {
4733               logThis('Loading config_si.php file at (' . $config_si_location . ') for merging.', $path);
4734            }
4735
4736            include($config_si_location);
4737            if(empty($sugar_config_si))
4738            {
4739               if($write_to_upgrade_log)
4740                   {
4741                      logThis('config_si.php contents are empty.  Skip merging.', $path);
4742                   }
4743                   return false;
4744            }
4745         }
4746
4747         //Now perform the merge operation
4748         $modified = false;
4749         foreach($sugar_config_si as $key=>$value)
4750         {
4751                 if(!preg_match('/^setup_/', $key) && !isset($sugar_config[$key]))
4752                 {
4753                    if($write_to_upgrade_log)
4754                    {
4755                       logThis('Merge key (' . $key . ') with value (' . $value . ')', $path);
4756                    }
4757                    $sugar_config[$key] = $value;
4758                    $modified = true;
4759                 }
4760         }
4761
4762         if($modified)
4763         {
4764                 if($write_to_upgrade_log)
4765                 {
4766                logThis('Update config.php file with new values', $path);
4767                 }
4768
4769             if(!write_array_to_file("sugar_config", $sugar_config, $config_location)) {
4770                if($write_to_upgrade_log)
4771                    {
4772                   logThis('*** ERROR: could not write to config.php', $path);
4773                    }
4774                    return false;
4775                 }
4776         } else {
4777            if($write_to_upgrade_log)
4778            {
4779               logThis('config.php values are in sync with config_si.php values.  Skipped merging.');
4780            }
4781            return false;
4782         }
4783
4784         if($write_to_upgrade_log)
4785         {
4786            logThis('End merge_config_si_settings', $path);
4787         }
4788         return true;
4789 }
4790
4791 /**
4792  * upgrade_connectors
4793  * @param $path String variable for the log path
4794  */
4795 function upgrade_connectors($path='') {
4796     logThis('Begin upgrade_connectors', $path);
4797
4798     $filePath = 'custom/modules/Connectors/connectors/sources/ext/soap/hoovers/config.php';
4799     if(file_exists($filePath))
4800     {
4801        logThis("{$filePath} file", $path);
4802        require($filePath);
4803        if(!is_null($config))
4804        {
4805           $modified = false;
4806           if(isset($config['properties']['hoovers_endpoint']))
4807           {
4808              $config['properties']['hoovers_endpoint'] = 'http://hapi.hoovers.com/HooversAPI-33';
4809              $modified = true;
4810           }
4811
4812           if(isset($config['properties']['hoovers_wsdl']))
4813           {
4814              $config['properties']['hoovers_wsdl'] = 'http://hapi.hoovers.com/HooversAPI-33/hooversAPI/hooversAPI.wsdl';
4815              $modified = true;
4816           }
4817
4818           if($modified)
4819           {
4820               if(!write_array_to_file('config', $config, $filePath)) {
4821                  logThis("Could not write new configuration to {$filePath} file", $path);
4822               } else {
4823                  logThis('Modified file successfully with new configuration entries', $path);
4824               }
4825           }
4826        }
4827     }
4828
4829     $filePath = 'custom/modules/Connectors/connectors/sources/ext/soap/hoovers/vardefs.php';
4830     if(file_exists($filePath))
4831     {
4832        logThis("Modifying {$filePath} file", $path);
4833        require($filePath);
4834        $fileContents = file_get_contents($filePath);
4835        $out = str_replace('bal.specialtyCriteria.companyKeyword', 'bal.specialtyCriteria.companyName', $fileContents);
4836        file_put_contents($filePath, $out);
4837     }
4838
4839     logThis('End upgrade_connectors', $path);
4840 }
4841
4842 /**
4843  * Enable the InsideView connector for the four default modules.
4844  */
4845 function upgradeEnableInsideViewConnector($path='')
4846 {
4847     logThis('Begin upgradeEnableInsideViewConnector', $path);
4848
4849     // Load up the existing mapping and hand it to the InsideView connector to have it setup the correct logic hooks
4850     $mapFile = 'modules/Connectors/connectors/sources/ext/rest/insideview/mapping.php';
4851     if ( file_exists('custom/'.$mapFile) ) {
4852         logThis('Found CUSTOM mappings', $path);
4853         require('custom/'.$mapFile);
4854     } else {
4855         logThis('Used default mapping', $path);
4856         require($mapFile);
4857     }
4858  
4859     require_once('include/connectors/sources/SourceFactory.php');
4860     $source = SourceFactory::getSource('ext_rest_insideview');
4861
4862     // $mapping is brought in from the mapping.php file above
4863     $source->saveMappingHook($mapping);
4864
4865     require_once('include/connectors/utils/ConnectorUtils.php');
4866     ConnectorUtils::installSource('ext_rest_insideview');
4867
4868     // Now time to set the various modules to active, because this part ignores the default config
4869     require(CONNECTOR_DISPLAY_CONFIG_FILE);
4870     // $modules_sources come from that config file
4871     foreach ( $source->allowedModuleList as $module ) {
4872         $modules_sources[$module]['ext_rest_insideview'] = 'ext_rest_insideview';
4873     }
4874     if(!write_array_to_file('modules_sources', $modules_sources, CONNECTOR_DISPLAY_CONFIG_FILE)) {
4875         //Log error and return empty array
4876         logThis("Cannot write \$modules_sources to " . CONNECTOR_DISPLAY_CONFIG_FILE,$path);
4877     }
4878
4879     logThis('End upgradeEnableInsideViewConnector', $path);
4880
4881 }
4882
4883 function repair_long_relationship_names($path='')
4884 {
4885     logThis("Begin repair_long_relationship_names", $path);
4886     require_once 'modules/ModuleBuilder/parsers/relationships/DeployedRelationships.php' ;
4887     $GLOBALS['mi_remove_tables'] = false;
4888     $touched = array();
4889     foreach($GLOBALS['moduleList'] as $module)
4890     {
4891         $relationships = new DeployedRelationships ($module) ;
4892         foreach($relationships->getRelationshipList() as $rel_name)
4893         {
4894             if (strlen($rel_name) > 27 && empty($touched[$rel_name]))
4895             {
4896                 logThis("Rebuilding relationship fields for $rel_name", $path);
4897                 $touched[$rel_name] = true;
4898                 $rel_obj = $relationships->get($rel_name);
4899                 $rel_obj->setReadonly(false);
4900                 $relationships->delete($rel_name);
4901                 $relationships->save();
4902                 $relationships->add($rel_obj);
4903                 $relationships->save();
4904                 $relationships->build () ;
4905             }
4906         }
4907     }
4908     logThis("End repair_long_relationship_names", $path);
4909 }
4910
4911 function removeSilentUpgradeVarsCache(){
4912     global $silent_upgrade_vars_loaded;
4913
4914     $cacheFileDir = "{$GLOBALS['sugar_config']['cache_dir']}/silentUpgrader";
4915     $cacheFile = "{$cacheFileDir}/silentUpgradeCache.php";
4916
4917     if(file_exists($cacheFile)){
4918         unlink($cacheFile);
4919     }
4920
4921     $silent_upgrade_vars_loaded = array(); // Set to empty to reset it
4922
4923     return true;
4924 }
4925
4926 function loadSilentUpgradeVars(){
4927     global $silent_upgrade_vars_loaded;
4928
4929     if(empty($silent_upgrade_vars_loaded)){
4930         $cacheFile = "{$GLOBALS['sugar_config']['cache_dir']}/silentUpgrader/silentUpgradeCache.php";
4931         // We have no pre existing vars
4932         if(!file_exists($cacheFile)){
4933             // Set the vars array so it's loaded
4934             $silent_upgrade_vars_loaded = array('vars' => array());
4935         }
4936         else{
4937             require_once($cacheFile);
4938             $silent_upgrade_vars_loaded = $silent_upgrade_vars_cache;
4939         }
4940     }
4941
4942     return true;
4943 }
4944
4945 function writeSilentUpgradeVars(){
4946     global $silent_upgrade_vars_loaded;
4947
4948     if(empty($silent_upgrade_vars_loaded)){
4949         return false; // You should have set some values before trying to write the silent upgrade vars
4950     }
4951
4952     $cacheFileDir = "{$GLOBALS['sugar_config']['cache_dir']}/silentUpgrader";
4953     $cacheFile = "{$cacheFileDir}/silentUpgradeCache.php";
4954
4955     require_once('include/dir_inc.php');
4956     if(!mkdir_recursive($cacheFileDir)){
4957         return false;
4958     }
4959     require_once('include/utils/file_utils.php');
4960     if(!write_array_to_file('silent_upgrade_vars_cache', $silent_upgrade_vars_loaded, $cacheFile, 'w')){
4961         global $path;
4962         logThis("WARNING: writeSilentUpgradeVars could not write to {$cacheFile}", $path);
4963         return false;
4964     }
4965
4966     return true;
4967 }
4968
4969 function setSilentUpgradeVar($var, $value){
4970     if(!loadSilentUpgradeVars()){
4971         return false;
4972     }
4973
4974     global $silent_upgrade_vars_loaded;
4975
4976     $silent_upgrade_vars_loaded['vars'][$var] = $value;
4977
4978     return true;
4979 }
4980
4981 function getSilentUpgradeVar($var){
4982     if(!loadSilentUpgradeVars()){
4983         return false;
4984     }
4985
4986     global $silent_upgrade_vars_loaded;
4987
4988     if(!isset($silent_upgrade_vars_loaded['vars'][$var])){
4989         return null;
4990     }
4991     else{
4992         return $silent_upgrade_vars_loaded['vars'][$var];
4993     }
4994 }
4995
4996
4997 /**
4998  * add_unified_search_to_custom_modules_vardefs
4999  *
5000  * This method calls the repair code to remove the unified_search_modules.php fiel
5001  *
5002  */
5003 function add_unified_search_to_custom_modules_vardefs()
5004 {
5005         if(file_exists('cache/modules/unified_search_modules.php'))
5006         {
5007            unlink('cache/modules/unified_search_modules.php');
5008         }
5009
5010 }
5011
5012 /**
5013  * change from using the older SugarCache in 6.1 and below to the new one in 6.2
5014  */
5015 function upgradeSugarCache($file)
5016 {
5017         global $sugar_config;
5018         // file = getcwd().'/'.$sugar_config['upload_dir'].$_FILES['upgrade_zip']['name'];
5019
5020         $cacheUploadUpgradesTemp = clean_path(mk_temp_dir("{$sugar_config['upload_dir']}upgrades/temp"));
5021
5022         unzip($file, $cacheUploadUpgradesTemp);
5023
5024         if(!file_exists(clean_path("{$cacheUploadUpgradesTemp}/manifest.php"))) {
5025                 logThis("*** ERROR: no manifest file detected while bootstraping upgrade wizard files!");
5026                 return;
5027         } else {
5028                 include(clean_path("{$cacheUploadUpgradesTemp}/manifest.php"));
5029         }
5030
5031         $allFiles = array();
5032         if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/database"))) {
5033                 $allFiles = findAllFiles(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/database"), $allFiles);
5034         }       
5035         if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/SugarCache"))) {
5036                 $allFiles = findAllFiles(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/SugarCache"), $allFiles);
5037         }
5038         if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/external_cache.php"))) {
5039                 $allFiles[] = clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/external_cache.php");
5040         }
5041         $cwd = clean_path(getcwd());
5042
5043         foreach($allFiles as $k => $file) {
5044                 $file = clean_path($file);
5045                 $destFile = str_replace(clean_path($cacheUploadUpgradesTemp.'/'.$manifest['copy_files']['from_dir']), $cwd, $file);
5046        if(!is_dir(dirname($destFile))) {
5047                         mkdir_recursive(dirname($destFile)); // make sure the directory exists
5048                 }
5049                 if ( stristr($file,'uw_main.tpl') )
5050             logThis('Skipping "'.$file.'" - file copy will during commit step.');
5051         else {
5052             logThis('updating UpgradeWizard code: '.$destFile);
5053             copy_recursive($file, $destFile);
5054         }
5055         }
5056         logThis ('is sugar_file_util there '.file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/sugar_file_utils.php")));
5057         if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/sugar_file_utils.php"))) {
5058                 $file = clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/sugar_file_utils.php");
5059                 $destFile = str_replace(clean_path($cacheUploadUpgradesTemp.'/'.$manifest['copy_files']['from_dir']), $cwd, $file);
5060         copy($file,$destFile);
5061         }
5062 }
5063
5064
5065 /**
5066  * upgradeDisplayedTabsAndSubpanels
5067  * 
5068  * @param $version String value of current system version (pre upgrade)
5069  */
5070 function upgradeDisplayedTabsAndSubpanels($version)
5071 {
5072         if($version < '620')
5073         {
5074                 logThis('start upgrading system displayed tabs and subpanels');
5075             require_once('modules/MySettings/TabController.php');
5076             $tc = new TabController();  
5077             
5078             //grab the existing system tabs
5079             $tabs = $tc->get_tabs_system();  
5080
5081             //add Calls, Meetings, Tasks, Notes, Prospects (Targets) and ProspectLists (Target Lists) 
5082             //to displayed tabs unless explicitly set to hidden
5083             $modules_to_add = array('Calls', 'Meetings', 'Tasks', 'Notes', 'Prospects', 'ProspectLists');
5084             $added_tabs = array();
5085             
5086             foreach($modules_to_add as $module)
5087             {
5088                        $tabs[0][$module] = $module;
5089                        $added_tabs[] = $module;
5090             }
5091             
5092             logThis('calling set_system_tabs on TabController to add tabs: ' . var_export($added_tabs, true));
5093             $tc->set_system_tabs($tabs[0]);    
5094             logThis('finish upgrading system displayed tabs and subpanels'); 
5095         }
5096 }
5097
5098
5099 /**
5100  * unlinkUpgradeFiles
5101  * This is a helper function to clean up 
5102  * 
5103  * @param $version String value of current system version (pre upgrade)
5104  */
5105 function unlinkUpgradeFiles($version)
5106 {
5107         if(!isset($version))
5108         {
5109            return;
5110         }
5111         
5112         logThis('start unlinking files from previous upgrade');
5113         if($version < '620')
5114         {
5115            //list of files to remove
5116            $files_to_remove = array('modules/Notifications/metadata/studio.php', 'modules/Help/Forms.php','themes/Sugar5/images/sugarColors.xml');
5117            
5118            foreach($files_to_remove as $f)
5119            {
5120                    if(file_exists($f))
5121                    {
5122                           logThis('removing file: ' . $f);
5123                           unlink($f);
5124                    }  
5125            }
5126         }
5127         logThis('end unlinking files from previous upgrade');
5128         
5129         if($version < '620')
5130         {
5131                 logThis('start upgrade for DocumentRevisions classic files (EditView.html, EditView.php, DetailView.html, DetailView.php, Save.php)');
5132
5133                 //Use a md5 comparison check to see if we can just remove the file where an exact match is found
5134                 if($version < '610')
5135                 {
5136                         $dr_files = array(
5137                  'modules/DocumentRevisions/DetailView.html' => '17ad4d308ce66643fdeb6fdb3b0172d3',
5138                          'modules/DocumentRevisions/DetailView.php' => 'd8606cdcd0281ae9443b2580a43eb5b3',
5139                  'modules/DocumentRevisions/EditView.php' => 'c7a1c3ef2bb30e3f5a11d122b3c55ff1',
5140                  'modules/DocumentRevisions/EditView.html' => '7d360ca703863c957f40b3719babe8c8',
5141                          'modules/DocumentRevisions/Save.php' => 'd7e39293a5fb4d605ca2046e7d1fcf28',
5142                 );              
5143                 } else {
5144                         $dr_files = array(
5145                  'modules/DocumentRevisions/DetailView.html' => 'a8356ff20cd995daffe6cb7f7b8b2340',
5146                          'modules/DocumentRevisions/DetailView.php' => '20edf45dd785469c484fbddff1a3f8f2',
5147                  'modules/DocumentRevisions/EditView.php' => 'fb31958496f04031b2851dcb4ce87d50',
5148                  'modules/DocumentRevisions/EditView.html' => 'b8cada4fa6fada2b4e4928226d8b81ee',
5149                          'modules/DocumentRevisions/Save.php' => '7fb62e4ebff879bafc07a08da62902aa',
5150                 );
5151                 }
5152         
5153                 foreach($dr_files as $rev_file=>$hash)
5154                 {
5155                         if(file_exists($rev_file))
5156                         {
5157                                 //It's a match here so let's just remove the file
5158                                 if (md5(file_get_contents($rev_file)) == $hash) 
5159                                 {
5160                                         logThis('removing file ' . $rev_file);
5161                                         unlink($rev_file);
5162                                 } else {
5163                                         if(!copy($rev_file, $rev_file . '.suback.bak')) 
5164                                         {
5165                                           logThis('error making backup for file ' . $rev_file);
5166                                         } else {
5167                                           logThis('copied file ' . $rev_file . ' to ' . $rev_file . '.suback.bak');
5168                                           unlink($rev_file);
5169                                         }
5170                                 } 
5171                         }
5172                 }
5173                 
5174                 logThis('end upgrade for DocumentRevisions classic files');
5175         }       
5176
5177     //First check if we even have the scripts_for_patch/files_to_remove directory
5178     require_once('modules/UpgradeWizard/UpgradeRemoval.php');
5179     
5180     if(file_exists($_SESSION['unzip_dir'].'/scripts/files_to_remove'))
5181     {
5182        $files_to_remove = glob($_SESSION['unzip_dir'].'/scripts/files_to_remove/*.php');
5183       
5184        foreach($files_to_remove as $script)
5185        {
5186                 if(preg_match('/UpgradeRemoval(\d+)x\.php/', $script, $matches))
5187                 {
5188                    $checkVersion = $matches[1] + 1; //Increment by one to check everything equal or below the target version
5189                    $upgradeClass = 'UpgradeRemoval' . $matches[1] . 'x';
5190                    require_once($_SESSION['unzip_dir'].'/scripts/files_to_remove/' . $upgradeClass . '.php');                      
5191
5192                    //Check to make sure we should load and run this UpgradeRemoval instance
5193                    if($checkVersion <= $version && class_exists($upgradeClass))
5194                    {
5195                           $upgradeInstance = new $upgradeClass();
5196                           if($upgradeInstance instanceof UpgradeRemoval)
5197                           {
5198                                   logThis('Running UpgradeRemoval instance ' . $upgradeClass);
5199                                   logThis('Files will be backed up to custom/backup');
5200                                   $files = $upgradeInstance->getFilesToRemove($version);
5201                                   foreach($files as $file)
5202                                   {
5203                                          logThis($file);
5204                                   }
5205                                   $upgradeInstance->processFilesToRemove($files);
5206                           }
5207                    }
5208             }
5209        }
5210     }   
5211     
5212     //Check if we have a custom directory
5213     if(file_exists('custom/scripts/files_to_remove'))
5214     {
5215        //Now find
5216        $files_to_remove = glob('custom/scripts/files_to_remove/*.php');
5217        
5218        foreach($files_to_remove as $script)
5219        {
5220            if(preg_match('/\/files_to_remove\/(.*?)\.php$/', $script, $matches))
5221            {
5222                    require_once($script);
5223                    $upgradeClass  = $matches[1];
5224                                            
5225                    if(!class_exists($upgradeClass))
5226                    {
5227                           continue;
5228                    }
5229
5230                    $upgradeInstance = new $upgradeClass();
5231                    if($upgradeInstance instanceof UpgradeRemoval)
5232                    {
5233                                   logThis('Running Custom UpgradeRemoval instance ' . $upgradeClass);
5234                                   $files = $upgradeInstance->getFilesToRemove($version);
5235                                   foreach($files as $file)
5236                                   {
5237                                          logThis($file);
5238                                   }
5239                                   $upgradeInstance->processFilesToRemove($files);
5240                    }                    
5241            }
5242        }
5243     }   
5244         
5245 }
5246
5247 if (!function_exists("getValidDBName"))
5248 {
5249     /*
5250      * Return a version of $proposed that can be used as a column name in any of our supported databases
5251      * 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)
5252      * @param string $name Proposed name for the column
5253      * @param string $ensureUnique
5254      * @return string Valid column name trimmed to right length and with invalid characters removed
5255      */
5256      function getValidDBName ($name, $ensureUnique = false, $maxLen = 30)
5257     {
5258         // first strip any invalid characters - all but alphanumerics and -
5259         $name = preg_replace ( '/[^\w-]+/i', '', $name ) ;
5260         $len = strlen ( $name ) ;
5261         $result = $name;
5262         if ($ensureUnique)
5263         {
5264             $md5str = md5($name);
5265             $tail = substr ( $name, -8) ;
5266             $temp = substr($md5str , strlen($md5str)-4 );
5267             $result = substr ( $name, 0, 7) . $temp . $tail ;
5268         }else if ($len > ($maxLen - 5))
5269         {
5270             $result = substr ( $name, 0, 8) . substr ( $name, 8 - $maxLen + 5);
5271         }
5272         return strtolower ( $result ) ;
5273     }
5274     
5275
5276 }
5277
5278 /**
5279  * Whether directory exists within list of directories to skip
5280  * @param string $dir dir to be checked
5281  * @param array $skipDirs list with skipped dirs
5282  * @return boolean
5283  */
5284 function whetherNeedToSkipDir($dir, $skipDirs) 
5285 {
5286     foreach($skipDirs as $skipMe) {
5287                 if(strpos( clean_path($dir), $skipMe ) !== false) {
5288                         return true;
5289                 }
5290         }
5291     return false;
5292 }