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