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.
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.
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
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
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.
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.
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 ********************************************************************************/
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
51 function commitMakeBackupFiles($rest_dir, $install_file, $unzip_dir, $zip_from_dir, $errors, $path='') {
53 // create restore file directory
54 mkdir_recursive($rest_dir);
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());
60 // keep this around for canceling
61 $_SESSION['uw_restore_dir'] = clean_path($rest_dir);
63 foreach ($newFiles as $file) {
64 if (strpos($file, 'md5'))
67 // get name of current file to place in restore directory
68 $cleanFile = str_replace(clean_path($unzip_dir . '/' . $zip_from_dir), '', $file);
70 // make sure the directory exists
71 $cleanDir = $rest_dir . '/' . dirname($cleanFile);
72 if (!is_dir($cleanDir)) {
73 mkdir_recursive($cleanDir);
76 $oldFile = clean_path(getcwd() . '/' . $cleanFile);
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}";
86 $backupFilesExist = true;
90 logThis('*** ERROR: directory not writable: ' . $rest_dir, $path);
91 $errors[] = "{$mod_strings['LBL_UW_BACKUP']}::{$mod_strings['ERR_UW_DIR_NOT_WRITABLE']}: {$oldFile}";
96 logThis('file backup done.', $path);
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
105 * @param string path Optional full path to alternate upgradeWizard log file.
106 * @return array Two element array containing to $copiedFiles and $skippedFiles.
111 function commitCopyNewFiles($unzip_dir, $zip_from_dir, $path='') {
112 logThis('Starting file copy process...', $path);
113 global $sugar_version;
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'))){
121 $files= findAllFiles(clean_path(getcwd().'/modules/'.$mod.'/.500'),$files);
122 if(sizeof($files) >0){
123 //backward compatibility is on
124 $backwardModules[] = $mod;
130 $newFiles = findAllFiles(clean_path($unzip_dir . '/' . $zip_from_dir), array());
131 $zipPath = clean_path($unzip_dir . '/' . $zip_from_dir);
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']);
140 $copiedFiles = array();
141 $skippedFiles = array();
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);
156 if(!is_dir(dirname($targetFile))) {
157 mkdir_recursive(dirname($targetFile)); // make sure the directory exists
160 if((!file_exists($targetFile)) || /* brand new file */
161 (!in_array($targetFile, $doNotOverwrite)) /* manual diff file */
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;
170 //logThis('Copying file to destination: ' . $targetFile, $path);
172 if(!copy($srcFile, $targetFile)) {
173 logThis('*** ERROR: could not copy file: ' . $targetFile, $path);
175 $copiedFiles[] = $targetFile;
178 //logThis('Skipping file: ' . $targetFile, $path);
179 $skippedFiles[] = $targetFile;
182 logThis('File copy done.', $path);
185 $ret['copiedFiles'] = $copiedFiles;
186 $ret['skippedFiles'] = $skippedFiles;
192 //On cancel put back the copied files from 500 to 451 state
193 function copyFilesOnCancel($step){
194 //place hoder for cancel action
199 function removeFileFromPath($file,$path, $deleteNot=array()){
201 $cur = $path . '/' . $file;
202 if(file_exists($cur)){
204 foreach($deleteNot as $dn){
214 if(!file_exists($path))return $removed;
216 while($e = $d->read()){
217 $next = $path . '/'. $e;
218 if(substr($e, 0, 1) != '.' && is_dir($next)){
219 $removed += removeFileFromPath($file, $next, $deleteNot);
226 * This function copies/overwrites between directories
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.
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) {
245 $targetFile = str_replace($from, $to, $srcFile);
247 if(!is_dir(dirname($targetFile))) {
248 mkdir_recursive(dirname($targetFile)); // make sure the directory exists
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;
258 //logThis('Copying file to destination: ' . $targetFile);
260 if(!copy($srcFile, $targetFile)) {
261 logThis('*** ERROR: could not copy file: ' . $targetFile);
263 //logThis('Copied file: ' . $targetFile);
264 //$copiedFiles[] = $targetFile;
272 function deleteDirectory($dirname,$only_empty=false) {
273 if (!is_dir($dirname))
275 $dscan = array(realpath($dirname));
277 while (!empty($dscan)) {
278 $dcur = array_pop($dscan);
280 if ($d=opendir($dcur)) {
281 while ($f=readdir($d)) {
282 if ($f=='.' || $f=='..')
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]);
299 logThis('Copy problem:Copying file to destination: ' . $darr[$i]);
301 return (($only_empty)? (count(scandir)<=2) : (!is_dir($dirname)));
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.
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();
318 foreach($newFiles as $file) {
319 $cleanFile = str_replace($zipPath, '', $file);
320 $srcFile = $zipPath . $cleanFile;
321 $targetFile = clean_path(getcwd() . '/' . $cleanFile);
323 if(!is_dir(dirname($targetFile))) {
324 mkdir_recursive(dirname($targetFile)); // make sure the directory exists
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;
335 //logThis('Copying file to destination: ' . $targetFile);
337 if(!copy($srcFile, $targetFile)) {
338 logThis('*** ERROR: could not copy file: ' . $targetFile);
340 $copiedFiles[] = $targetFile;
343 //logThis('Skipping file: ' . $targetFile);
344 $skippedFiles[] = $targetFile;
350 $ret['copiedFiles'] = $copiedFiles;
351 $ret['skippedFiles'] = $skippedFiles;
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);
360 // to use this function to empty a directory, write:
361 // recursive_remove_directory('path/to/full_directory');
363 function recursive_empty_or_remove_directory($directory, $exclude_dirs=null,$exclude_files=null,$empty=TRUE)
365 // if the path has a slash at the end we remove it here
366 if(substr($directory,-1) == '/')
368 $directory = substr($directory,0,-1);
371 // if the path is not valid or is not a directory ...
372 if(!file_exists($directory) || !is_dir($directory))
374 // ... we return false and exit the function
377 // ... if the path is not readable
378 }elseif(!is_readable($directory))
380 // ... we return false and exit the function
383 // ... else if the path is readable
386 // we open the directory
387 $handle = opendir($directory);
389 // and scan through the items inside
390 while (FALSE !== ($item = readdir($handle)))
392 // if the filepointer is not the current directory
393 // or the parent directory
394 if($item != '.' && $item != '..')
396 // we build the new path to delete
397 $path = $directory.'/'.$item;
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)){
404 else if(is_dir($path))
406 // we call this function with the new path
407 recursive_empty_or_remove_directory($path);
409 // if the new path is a file
411 // we remove the file
412 if($exclude_files != null && in_array($path,$exclude_files)){
421 // close the directory
424 // if the option to empty is not set to true
427 // try to delete the now empty directory
428 if(!rmdir($directory))
430 // return false if not possible
438 // ------------------------------------------------------------
443 function getAllCustomizedModules() {
445 require_once('files.md5');
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;
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;
476 return $return_array;
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.
484 function getAllModules() {
487 while($e = $d->read()){
488 if(substr($e, 0, 1) == '.' || !is_dir('modules/' . $e))continue;
494 //Remove files with the smae md5
496 function removeMd5MatchingFiles($deleteNot=array()){
498 $md5_string = array();
499 if(file_exists(clean_path(getcwd().'/files.md5'))){
500 require(clean_path(getcwd().'/files.md5'));
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]) {
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.
526 function commitHandleReminders($skippedFiles, $path='') {
528 global $current_user;
530 if(empty($mod_strings))
531 $mod_strings = return_module_language('en_us', 'UpgradeWizard');
533 if(empty($current_user->id)) {
534 $current_user->getSystemUser();
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";
543 foreach($skippedFiles as $file) {
544 $desc .= $file . "\n";
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;
553 if($_REQUEST['addTaskReminder'] == 'remind') {
554 logThis('Adding Task for admin for manual merge.', $path);
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;
570 if($_REQUEST['addEmailReminder'] == 'remind') {
571 logThis('Sending Reminder for admin for manual merge.', $path);
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;
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)
598 if(file_exists($file))
605 //Clean jsLanguage from cache
606 if(is_dir($GLOBALS['sugar_config']['cache_dir'].'jsLanguage')){
607 $allModFiles = array();
608 $allModFiles = findAllFiles($GLOBALS['sugar_config']['cache_dir'].'jsLanguage',$allModFiles);
609 foreach($allModFiles as $file){
610 if(file_exists($file)){
615 //Clean smarty from cache
616 if(is_dir($GLOBALS['sugar_config']['cache_dir'].'smarty')){
617 $allModFiles = array();
618 $allModFiles = findAllFiles($GLOBALS['sugar_config']['cache_dir'].'smarty',$allModFiles);
619 foreach($allModFiles as $file){
620 if(file_exists($file)){
625 //Rebuild dashlets cache
626 require_once('include/Dashlets/DashletCacheBuilder.php');
627 $dc = new DashletCacheBuilder();
631 function deleteChance(){
632 //Clean folder from cache
633 if(is_dir('include/SugarObjects/templates/chance')){
634 rmdir_recursive('include/SugarObjects/templates/chance');
636 if(is_dir('include/SugarObjects/templates/chance')){
637 if(!isset($_SESSION['chance'])){
638 $_SESSION['chance'] = '';
640 $_SESSION['chance'] = 'include/SugarObjects/templates/chance';
641 //rename('include/SugarObjects/templates/chance','include/SugarObjects/templates/chance_removeit');
648 * copies upgrade wizard files from new patch if that dir exists
649 * @param string file Path to uploaded zip file
651 function upgradeUWFiles($file) {
652 global $sugar_config;
653 // file = getcwd().'/'.$sugar_config['upload_dir'].$_FILES['upgrade_zip']['name'];
655 $cacheUploadUpgradesTemp = clean_path(mk_temp_dir("{$sugar_config['upload_dir']}upgrades/temp"));
657 unzip($file, $cacheUploadUpgradesTemp);
659 if(!file_exists(clean_path("{$cacheUploadUpgradesTemp}/manifest.php"))) {
660 logThis("*** ERROR: no manifest file detected while bootstraping upgrade wizard files!");
663 include(clean_path("{$cacheUploadUpgradesTemp}/manifest.php"));
668 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/modules/UpgradeWizard"))) {
669 $allFiles = findAllFiles(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/modules/UpgradeWizard"), $allFiles);
672 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/ModuleInstall"))) {
673 $allFiles = findAllFiles(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/ModuleInstall"), $allFiles);
675 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/javascript/yui"))) {
676 $allFiles = findAllFiles(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/javascript/yui"), $allFiles);
678 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/HandleAjaxCall.php"))) {
679 $allFiles[] = clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/HandleAjaxCall.php");
681 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/SugarTheme"))) {
682 $allFiles = findAllFiles(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/SugarTheme"), $allFiles);
684 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/SugarCache"))) {
685 $allFiles = findAllFiles(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/SugarCache"), $allFiles);
687 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/external_cache.php"))) {
688 $allFiles[] = clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/external_cache.php");
692 * /home/chris/workspace/maint450/cache/upload/upgrades/temp/DlNnqP/
693 * SugarEnt-Patch-4.5.0c/modules/Leads/ConvertLead.html
695 $cwd = clean_path(getcwd());
697 foreach($allFiles as $k => $file) {
698 $file = clean_path($file);
699 $destFile = str_replace(clean_path($cacheUploadUpgradesTemp.'/'.$manifest['copy_files']['from_dir']), $cwd, $file);
700 if(!is_dir(dirname($destFile))) {
701 mkdir_recursive(dirname($destFile)); // make sure the directory exists
703 if ( stristr($file,'uw_main.tpl') )
704 logThis('Skipping "'.$file.'" - file copy will during commit step.');
706 logThis('updating UpgradeWizard code: '.$destFile);
707 copy_recursive($file, $destFile);
710 logThis ('is sugar_file_util there '.file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/sugar_file_utils.php")));
711 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/sugar_file_utils.php"))) {
712 $file = clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/sugar_file_utils.php");
713 $destFile = str_replace(clean_path($cacheUploadUpgradesTemp.'/'.$manifest['copy_files']['from_dir']), $cwd, $file);
714 copy($file,$destFile);
721 * gets valid patch file names that exist in upload/upgrade/patch/
723 function getValidPatchName($returnFull = true) {
724 global $base_upgrade_dir;
727 global $sugar_version;
728 global $sugar_config;
729 $uh = new UpgradeHistory();
730 $base_upgrade_dir = $sugar_config['upload_dir'] . "upgrades";
733 // scan for new files (that are not installed)
734 logThis('finding new files for upgrade');
735 $upgrade_content = '';
736 $upgrade_contents = findAllFiles($base_upgrade_dir, array(), false, 'zip');
737 //other variations of zip file i.e. ZIP, zIp,zIP,Zip,ZIp,ZiP
738 $extns = array('ZIP','ZIp','ZiP','Zip','zIP','zIp','ziP');
739 foreach($extns as $extn){
740 $upgrade_contents = array_merge($upgrade_contents,findAllFiles( "$base_upgrade_dir", array() , false, $extn));
748 <b>{$mod_strings['LBL_ML_NAME']}</b>
751 <b>{$mod_strings['LBL_ML_TYPE']}</b>
754 <b>{$mod_strings['LBL_ML_VERSION']}</b>
757 <b>{$mod_strings['LBL_ML_PUBLISHED']}</b>
760 <b>{$mod_strings['LBL_ML_UNINSTALLABLE']}</b>
763 <b>{$mod_strings['LBL_ML_DESCRIPTION']}</b>
768 // assume old patches are there.
769 $upgradeToVersion = array(); // fill with valid patches - we will only use the latest qualified found patch
771 // cn: bug 10609 - notices for uninitialized variables
776 $published_date = '';
781 foreach($upgrade_contents as $upgrade_content) {
782 if(!preg_match("#.*\.zip\$#i", strtolower($upgrade_content))) {
786 $upgrade_content = clean_path($upgrade_content);
787 $the_base = basename($upgrade_content);
788 $the_md5 = md5_file($upgrade_content);
790 $md5_matches = $uh->findByMd5($the_md5);
792 /* If a patch is in the /patch dir AND has no record in the upgrade_history table we assume that it's the one we want.
793 * Edge-case: manual upgrade with a FTP of a patch; UH table has no entry for it. Assume nothing. :( */
794 if(0 == sizeof($md5_matches)) {
795 $target_manifest = remove_file_extension( $upgrade_content ) . '-manifest.php';
796 require_once($target_manifest);
798 if(empty($manifest['version'])) {
799 logThis("*** Potential error: patch found with no version [ {$upgrade_content} ]");
802 if(!isset($manifest['type']) || $manifest['type'] != 'patch') {
803 logThis("*** Potential error: patch found with either no 'type' or non-patch type [ {$upgrade_content} ]");
807 $upgradeToVersion[$manifest['version']] = urlencode($upgrade_content);
809 $name = empty($manifest['name']) ? $upgrade_content : $manifest['name'];
810 $version = empty($manifest['version']) ? '' : $manifest['version'];
811 $published_date = empty($manifest['published_date']) ? '' : $manifest['published_date'];
813 $description = empty($manifest['description']) ? 'None' : $manifest['description'];
814 $uninstallable = empty($manifest['is_uninstallable']) ? 'No' : 'Yes';
815 $type = getUITextForType( $manifest['type'] );
816 $manifest_type = $manifest['type'];
818 if(empty($manifest['icon'])) {
819 $icon = getImageForType( $manifest['type'] );
821 $path_parts = pathinfo( $manifest['icon'] );
822 $icon = "<img src=\"" . remove_file_extension( $upgrade_content ) . "-icon." . $path_parts['extension'] . "\">";
827 // cn: bug 10488 use the NEWEST upgrade/patch available when running upgrade wizard.
828 ksort($upgradeToVersion);
829 $upgradeToVersion = array_values($upgradeToVersion);
830 $newest = array_pop($upgradeToVersion);
831 $_SESSION['install_file'] = urldecode($newest); // in-case it was there from a prior.
832 logThis("*** UW using [ {$_SESSION['install_file']} ] as source for patch files.");
834 $cleanUpgradeContent = urlencode($_SESSION['install_file']);
836 // cn: 10606 - cannot upload a patch file since this returned always.
837 if(!empty($cleanUpgradeContent)) {
838 $ready .= "<tr><td>$icon</td><td>$name</td><td>$type</td><td>$version</td><td>$published_date</td><td>$uninstallable</td><td>$description</td>\n";
841 <form action="index.php" method="post">
842 <input type="hidden" name="module" value="UpgradeWizard">
843 <input type="hidden" name="action" value="index">
844 <input type="hidden" name="step" value="{$_REQUEST['step']}">
845 <input type="hidden" name="run" value="delete">
846 <input type=hidden name="install_file" value="{$cleanUpgradeContent}" />
847 <input type=submit value="{$mod_strings['LBL_BUTTON_DELETE']}" />
851 $disabled = "DISABLED";
856 if(empty($cleanUpgradeContent)){
857 $ready .= "<tr><td colspan='7'><i>None</i></td>\n";
858 $ready .= "</table>\n";
860 $ready .= "<br></ul>\n";
862 $return['ready'] = $ready;
863 $return['disabled'] = $disabled;
872 * finalizes upgrade by setting upgrade versions in DB (config table) and sugar_version.php
873 * @return bool true on success
875 function updateVersions($version) {
877 global $sugar_config;
880 logThis('At updateVersions()... updating config table and sugar_version.php.', $path);
883 if(isset($_SESSION['sugar_version_file']) && !empty($_SESSION['sugar_version_file'])) {
884 if(!copy($_SESSION['sugar_version_file'], clean_path(getcwd().'/sugar_version.php'))) {
885 logThis('*** ERROR: sugar_version.php could not be copied to destination! Cannot complete upgrade', $path);
888 logThis('sugar_version.php successfully updated!', $path);
891 logThis('*** ERROR: no sugar_version.php file location found! - cannot complete upgrade...', $path);
895 // handle config table
896 if($db->dbType == 'mysql') {
897 $q1 = "DELETE FROM `config` WHERE `category` = 'info' AND `name` = 'sugar_version'";
898 $q2 = "INSERT INTO `config` (`category`, `name`, `value`) VALUES ('info', 'sugar_version', '{$version}')";
899 } elseif($db->dbType == 'oci8' || $db->dbType == 'oracle') {
900 } elseif($db->dbType == 'mssql') {
901 $q1 = "DELETE FROM config WHERE category = 'info' AND name = 'sugar_version'";
902 $q2 = "INSERT INTO config (category, name, value) VALUES ('info', 'sugar_version', '{$version}')";
905 logThis('Deleting old DB version info from config table.', $path);
908 logThis('Inserting updated version info into config table.', $path);
911 logThis('updateVersions() complete.', $path);
918 * gets a module's lang pack - does not need to be a SugarModule
919 * @param lang string Language
920 * @param module string Path to language folder
921 * @return array mod_strings
923 function getModuleLanguagePack($lang, $module) {
924 $mod_strings = array();
926 if(!empty($lang) && !empty($module)) {
927 $langPack = clean_path(getcwd().'/'.$module.'/language/'.$lang.'.lang.php');
928 $langPackEn = clean_path(getcwd().'/'.$module.'/language/en_us.lang.php');
930 if(file_exists($langPack))
931 include_once($langPack);
932 elseif(file_exists($langPackEn))
933 include_once($langPackEn);
939 * checks system compliance for 4.5+ codebase
940 * @return array Mixed values
942 function checkSystemCompliance() {
943 global $sugar_config;
944 global $current_language;
948 if(!defined('SUGARCRM_MIN_MEM')) {
949 define('SUGARCRM_MIN_MEM', 40);
952 $installer_mod_strings = getModuleLanguagePack($current_language, './install');
954 $ret['error_found'] = false;
957 $php_version = constant('PHP_VERSION');
958 $check_php_version_result = check_php_version($php_version);
960 switch($check_php_version_result) {
962 $ret['phpVersion'] = "<b><span class=stop>{$installer_mod_strings['ERR_CHECKSYS_PHP_INVALID_VER']} {$php_version} )</span></b>";
963 $ret['error_found'] = true;
966 $ret['phpVersion'] = "<b><span class=go>{$installer_mod_strings['ERR_CHECKSYS_PHP_UNSUPPORTED']} {$php_version} )</span></b>";
969 $ret['phpVersion'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_PHP_OK']} {$php_version} )</span></b>";
973 // database and connect
974 switch($sugar_config['dbconfig']['db_type']){
977 $q = "SELECT version();";
979 $a = $db->fetchByAssoc($r);
980 if(version_compare($a['version()'], '4.1.2') < 0) {
981 $ret['error_found'] = true;
982 $ret['mysqlVersion'] = "<b><span class=stop>".$mod_strings['ERR_UW_MYSQL_VERSION'].$a['version()']."</span></b>";
996 if(function_exists('xml_parser_create')) {
997 $ret['xmlStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
999 $ret['xmlStatus'] = "<b><span class=stop>{$installer_mod_strings['LBL_CHECKSYS_NOT_AVAILABLE']}</span></b>";
1000 $ret['error_found'] = true;
1004 if(function_exists('curl_init')) {
1005 $ret['curlStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</font></b>";
1007 $ret['curlStatus'] = "<b><span class=go>{$installer_mod_strings['ERR_CHECKSYS_CURL']}</font></b>";
1008 $ret['error_found'] = false;
1012 if(function_exists('mb_strlen')) {
1013 $ret['mbstringStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</font></b>";
1015 $ret['mbstringStatus'] = "<b><span class=stop>{$installer_mod_strings['ERR_CHECKSYS_MBSTRING']}</font></b>";
1016 $ret['error_found'] = true;
1020 if(function_exists('imap_open')) {
1021 $ret['imapStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1023 $ret['imapStatus'] = "<b><span class=go>{$installer_mod_strings['ERR_CHECKSYS_IMAP']}</span></b>";
1024 $ret['error_found'] = false;
1029 if('1' == ini_get('safe_mode')) {
1030 $ret['safeModeStatus'] = "<b><span class=stop>{$installer_mod_strings['ERR_CHECKSYS_SAFE_MODE']}</span></b>";
1031 $ret['error_found'] = true;
1033 $ret['safeModeStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1037 // call time pass by ref
1038 if('1' == ini_get('allow_call_time_pass_reference')) {
1039 $ret['callTimeStatus'] = "<b><span class=stop>{$installer_mod_strings['ERR_CHECKSYS_CALL_TIME']}</span></b>";
1040 //continue upgrading
1042 $ret['callTimeStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1046 $ret['memory_msg'] = "";
1047 $memory_limit = "-1";//ini_get('memory_limit');
1048 $sugarMinMem = constant('SUGARCRM_MIN_MEM');
1049 // logic based on: http://us2.php.net/manual/en/ini.core.php#ini.memory-limit
1050 if( $memory_limit == "" ){ // memory_limit disabled at compile time, no memory limit
1051 $ret['memory_msg'] = "<b><span class=\"go\">{$installer_mod_strings['LBL_CHECKSYS_MEM_OK']}</span></b>";
1052 } elseif( $memory_limit == "-1" ){ // memory_limit enabled, but set to unlimited
1053 $ret['memory_msg'] = "<b><span class=\"go\">{$installer_mod_strings['LBL_CHECKSYS_MEM_UNLIMITED']}</span></b>";
1055 rtrim($memory_limit, 'M');
1056 $memory_limit_int = (int) $memory_limit;
1057 if( $memory_limit_int < constant('SUGARCRM_MIN_MEM') ){
1058 $ret['memory_msg'] = "<b><span class=\"stop\">{$installer_mod_strings['ERR_CHECKSYS_MEM_LIMIT_1']}" . constant('SUGARCRM_MIN_MEM') . "{$installer_mod_strings['ERR_CHECKSYS_MEM_LIMIT_2']}</span></b>";
1059 $ret['error_found'] = true;
1061 $ret['memory_msg'] = "<b><span class=\"go\">{$installer_mod_strings['LBL_CHECKSYS_OK']} ({$memory_limit})</span></b>";
1065 /* mbstring.func_overload
1066 $ret['mbstring.func_overload'] = '';
1067 $mb = ini_get('mbstring.func_overload');
1070 $ret['mbstring.func_overload'] = "<b><span class=\"stop\">{$mod_strings['ERR_UW_MBSTRING_FUNC_OVERLOAD']}</b>";
1071 $ret['error_found'] = true;
1079 function checkMysqlConnection(){
1080 global $sugar_config;
1081 $configOptions = $sugar_config['dbconfig'];
1082 if($sugar_config['dbconfig']['db_type'] == 'mysql'){
1083 @mysql_ping($GLOBALS['db']->database);
1088 * is a file that we blow away automagically
1090 function isAutoOverwriteFile($file) {
1091 $overwriteDirs = array(
1092 './sugar_version.php',
1093 './modules/UpgradeWizard/uw_main.tpl',
1095 $file = trim('.'.str_replace(clean_path(getcwd()), '', $file));
1097 if(in_array($file, $overwriteDirs)) {
1101 $fileExtension = substr(strrchr($file, "."), 1);
1102 if($fileExtension == 'tpl' || $fileExtension == 'html') {
1112 function logThis($entry, $path='') {
1113 global $mod_strings;
1114 if(file_exists('include/utils/sugar_file_utils.php')){
1115 require_once('include/utils/sugar_file_utils.php');
1117 $log = empty($path) ? clean_path(getcwd().'/upgradeWizard.log') : clean_path($path);
1119 // create if not exists
1120 if(!file_exists($log)) {
1121 if(function_exists('sugar_fopen')){
1122 $fp = @sugar_fopen($log, 'w+'); // attempts to create file
1125 $fp = fopen($log, 'w+'); // attempts to create file
1127 if(!is_resource($fp)) {
1128 $GLOBALS['log']->fatal('UpgradeWizard could not create the upgradeWizard.log file');
1129 die($mod_strings['ERR_UW_LOG_FILE_UNWRITABLE']);
1132 if(function_exists('sugar_fopen')){
1133 $fp = @sugar_fopen($log, 'a+'); // write pointer at end of file
1136 $fp = @fopen($log, 'a+'); // write pointer at end of file
1139 if(!is_resource($fp)) {
1140 $GLOBALS['log']->fatal('UpgradeWizard could not open/lock upgradeWizard.log file');
1141 die($mod_strings['ERR_UW_LOG_FILE_UNWRITABLE']);
1145 $line = date('r').' [UpgradeWizard] - '.$entry."\n";
1147 if(@fwrite($fp, $line) === false) {
1148 $GLOBALS['log']->fatal('UpgradeWizard could not write to upgradeWizard.log: '.$entry);
1149 die($mod_strings['ERR_UW_LOG_FILE_UNWRITABLE']);
1152 if(is_resource($fp)) {
1159 * tries to validate the query based on type
1160 * @param string query The query to verify
1161 * @param string dbType The DB type
1162 * @return string error Non-empty string on error
1164 function verifySqlStatement($query, $dbType, &$newTables) {
1166 logThis('verifying SQL statement');
1168 $table = getTableFromQuery($query);
1170 switch(strtoupper(substr($query, 0, 10))) {
1174 $error = testQueryAlter($table, $dbType, strtoupper($query), $newTables);
1178 $error = testQueryCreate($table, $dbType, $query, $newTables);
1182 $error = testQueryDelete($table, $dbType, $query);
1186 $error = testQueryDrop($table, $dbType, $query);
1190 $error = testQueryInsert($table, $dbType, $query);
1193 case (strtoupper(substr($query, 0, 6)) == 'UPDATE'):
1194 $error = testQueryUpdate($table, $dbType, $query);
1206 * @desc This function is to be used in the upgrade process to preserve changes/customaizations made to pre 5.1 quickcreate layout.
1207 * Prior to 5.1 we have been using editviewdefs as the base for quickcreatedefs. If a custom field was added to edit view layout, it
1208 * was automatically picked up by the quick create. [Addresses Bug 21469]
1209 * This function will check if customizations were made, and will create quickcreatedefs.php in the /cutom/working/$module_name directory.
1211 function updateQuickCreateDefs(){
1212 $d = dir('modules');
1213 $studio_modules = array();
1215 while($e = $d->read()){ //collect all studio modules.
1216 if(substr($e, 0, 1) == '.' || !is_dir('modules/' . $e))continue;
1217 if(file_exists('modules/' . $e . '/metadata/studio.php'))
1219 array_push($studio_modules, $e);
1223 foreach( $studio_modules as $modname ){ //for each studio enabled module
1224 //Check !exists modules/$modname/metadata/quickcreatedefs.php &&
1225 //exists custom/$modname/editviewdefs.php (module was customized) &&
1226 //!exists custom/$modname/quickcreateviewdefs.php
1228 $editviewdefs = "custom/working/modules/".$modname."/metadata/editviewdefs.php";
1229 $quickcreatedefs = "custom/working/modules/".$modname."/metadata/quickcreatedefs.php";
1231 if ( !file_exists("modules/".$modname."/metadata/quickcreatedefs.php") &&
1232 file_exists($editviewdefs) &&
1233 !file_exists($quickcreatedefs) ){
1234 //clone editviewdef and save it in custom/working/modules/metadata
1235 $GLOBALS['log']->debug("Copying editviewdefs.php as quickcreatedefs.php for the $modname module in custom/working/modules/$modname/metadata!");
1236 if(copy( $editviewdefs, $quickcreatedefs)){
1237 if(file_exists($quickcreatedefs) && is_readable($quickcreatedefs)){
1238 $file = file($quickcreatedefs);
1239 //replace 'EditView' with 'QuickCreate'
1240 $fp = fopen($quickcreatedefs,'w');
1241 foreach($file as &$line){
1242 if(preg_match('/^\s*\'EditView\'\s*=>\s*$/', $line) > 0){
1243 $line = "'QuickCreate' =>\n";
1251 $GLOBALS['log']->debug("Failed to replace 'EditView' with QuickCreate because $quickcreatedefs is either not readable or does not exist.");
1254 $GLOBALS['log']->debug("Failed to copy $editviewdefs to $quickcreatedefs!");
1261 function cleanQuery($query, $oci8=false) {
1271 $q = str_replace($bad, $good, $query);
1277 * test perms for CREATE queries
1279 function testPermsCreate($type, $out) {
1280 logThis('Checking CREATE TABLE permissions...');
1282 global $mod_strings;
1287 $db->query('CREATE TABLE temp (id varchar(36))');
1288 if($db->checkError()) {
1289 logThis('cannot CREATE TABLE!');
1290 $out['db']['dbNoCreate'] = true;
1291 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_CREATE']}</span></td></tr>";
1303 * test perms for INSERT
1305 function testPermsInsert($type, $out, $skip=false) {
1306 logThis('Checking INSERT INTO permissions...');
1308 global $mod_strings;
1314 $db->query("INSERT INTO temp (id) VALUES ('abcdef0123456789abcdef0123456789abcd')");
1315 if($db->checkError()) {
1316 logThis('cannot INSERT INTO!');
1317 $out['db']['dbNoInsert'] = true;
1318 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_INSERT']}</span></td></tr>";
1332 * test perms for UPDATE TABLE
1334 function testPermsUpdate($type, $out, $skip=false) {
1335 logThis('Checking UPDATE TABLE permissions...');
1337 global $mod_strings;
1343 $db->query("UPDATE temp SET id = '000000000000000000000000000000000000' WHERE id = 'abcdef0123456789abcdef0123456789abcd'");
1344 if($db->checkError()) {
1345 logThis('cannot UPDATE TABLE!');
1346 $out['db']['dbNoUpdate'] = true;
1347 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_UPDATE']}</span></td></tr>";
1361 * test perms for SELECT
1363 function testPermsSelect($type, $out, $skip=false) {
1364 logThis('Checking SELECT permissions...');
1366 global $mod_strings;
1371 $r = $db->query('SELECT id FROM temp');
1372 if($db->checkError()) {
1373 logThis('cannot SELECT!');
1374 $out['db']['dbNoSelect'] = true;
1375 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_SELECT']}</span></td></tr>";
1377 logThis('Checking validity of SELECT results');
1378 while($a = $db->fetchByAssoc($r)) {
1379 if($a['id'] != '000000000000000000000000000000000000') {
1380 logThis('results DO NOT MATCH! got: '.$a['id']);
1381 $out['db'][] = 'selectFailed';
1382 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_INSERT_FAILED']}</span></td></tr>";
1397 * test perms for DELETE
1399 function testPermsDelete($type, $out, $skip=false) {
1400 logThis('Checking DELETE FROM permissions...');
1402 global $mod_strings;
1407 $db->query("DELETE FROM temp WHERE id = '000000000000000000000000000000000000'");
1408 if($db->checkError()) {
1409 logThis('cannot DELETE FROM!');
1410 $out['db']['dbNoDelete'] = true;
1411 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_DELETE']}</span></td></tr>";
1424 * test perms for ALTER TABLE ADD COLUMN
1426 function testPermsAlterTableAdd($type, $out, $skip=false) {
1427 logThis('Checking ALTER TABLE ADD COLUMN permissions...');
1429 global $mod_strings;
1433 $db->query('ALTER TABLE temp ADD COLUMN test varchar(100)');
1434 if($db->checkError()) {
1435 logThis('cannot ADD COLUMN!');
1436 $out['db']['dbNoAddColumn'] = true;
1437 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_ADD_COLUMN']}</span></td></tr>";
1442 $db->query('ALTER TABLE [temp] ADD [test] [varchar] (100)');
1443 if($db->checkError()) {
1444 logThis('cannot ADD COLUMN!');
1445 $out['db']['dbNoAddColumn'] = true;
1446 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_ADD_COLUMN']}</span></td></tr>";
1461 * test perms for ALTER TABLE ADD COLUMN
1463 function testPermsAlterTableChange($type, $out, $skip=false) {
1464 logThis('Checking ALTER TABLE CHANGE COLUMN permissions...');
1466 global $mod_strings;
1470 $db->query('ALTER TABLE temp CHANGE COLUMN test test varchar(100)');
1471 if($db->checkError()) {
1472 logThis('cannot CHANGE COLUMN!');
1473 $out['db']['dbNoChangeColumn'] = true;
1474 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_CHANGE_COLUMN']}</span></td></tr>";
1479 $db->query('ALTER TABLE [temp] ALTER COLUMN [test] [varchar] (100)');
1480 if($db->checkError()) {
1481 logThis('cannot CHANGE COLUMN!');
1482 $out['db']['dbNoChangeColumn'] = true;
1483 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_CHANGE_COLUMN']}</span></td></tr>";
1497 * test perms for ALTER TABLE DROP COLUMN
1499 function testPermsAlterTableDrop($type, $out, $skip=false) {
1500 logThis('Checking ALTER TABLE DROP COLUMN permissions...');
1502 global $mod_strings;
1507 $db->query('ALTER TABLE temp DROP COLUMN test');
1508 if($db->checkError()) {
1509 logThis('cannot DROP COLUMN!');
1510 $out['db']['dbNoDropColumn'] = true;
1511 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_DROP_COLUMN']}</span></td></tr>";
1524 * test perms for DROP TABLE
1526 function testPermsDropTable($type, $out, $skip=false) {
1527 logThis('Checking DROP TABLE permissions...');
1529 global $mod_strings;
1534 $db->query('DROP TABLE temp');
1535 if($db->checkError()) {
1536 logThis('cannot DROP TABLE!');
1537 $out['db']['dbNoDropTable'] = true;
1538 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_DROP_TABLE']}</span></td></tr>";
1551 function createMSSQLTemp($table) {
1552 global $sugar_config;
1555 $qtest = "SELECT TABLE_NAME tn FROM information.tables WHERE TABLE_NAME = '{$table}__UW_TEMP'";
1556 $rtest = $db->query($qtest);
1557 $atest = $db->fetchByAssoc($rtest);
1560 $tempTable = "CREATE TABLE {$table}__UW_TEMP AS ".$db->limitQuerySql("SELECT * FROM {$table}",0,8);
1561 logThis("Creating temp table for {$table}: {$tempTable}");
1562 $db->query($tempTable);
1565 logThis("Found {$table}__UW_TEMP - skipping temp table creation.");
1570 * Tests an ALTER TABLE query
1571 * @param string table The table name to get DDL
1572 * @param string dbType MySQL, MSSQL, etc.
1573 * @param string query The query to test.
1574 * @return string Non-empty if error found
1576 function testQueryAlter($table, $dbType, $query, $newTables) {
1577 logThis('verifying ALTER statement...');
1579 global $sugar_config;
1582 $db = &DBManagerFactory::getInstance();
1585 // Skipping ALTER TABLE [table] DROP PRIMARY KEY because primary keys are not being copied
1586 // over to the temp tables
1587 if(strpos(strtoupper($query), 'DROP PRIMARY KEY') !== false) {
1588 logThis('Skipping DROP PRIMARY KEY verification');
1592 if ($dbType == 'mysql'){
1593 mysql_error(); // initialize errors
1597 if(!in_array($table, $newTables)) {
1601 logThis('creating temp table for ['.$table.']...');
1602 $q = "SHOW CREATE TABLE {$table}";
1603 $r = $db->query($q);
1604 $a = $db->fetchByAssoc($r);
1606 // rewrite DDL with _temp name
1607 $cleanQuery = cleanQuery($a['Create Table']);
1608 $tempTableQuery = str_replace("CREATE TABLE `{$table}`", "CREATE TABLE `{$table}__uw_temp`", $cleanQuery);
1609 $r2 = $db->query($tempTableQuery);
1611 // get sample data into the temp table to test for data/constraint conflicts
1612 logThis('inserting temp dataset...');
1613 $q3 = "INSERT INTO `{$table}__uw_temp` SELECT * FROM `{$table}` LIMIT 10";
1614 $r3 = $db->query($q3, false, "Preflight Failed for: {$query}");
1616 // test the query on the test table
1617 logThis('testing query: ['.$query.']');
1618 $tempTableTestQuery = str_replace("ALTER TABLE `{$table}`", "ALTER TABLE `{$table}__uw_temp`", $query);
1619 if (strpos($tempTableTestQuery, 'idx') === false) {
1620 if(isRunningAgainstTrueTable($tempTableTestQuery)) {
1621 $error = getFormattedError('Could not use a temp table to test query!', $query);
1625 logThis('testing query on temp table: ['.$tempTableTestQuery.']');
1626 $r4 = $db->query($tempTableTestQuery, false, "Preflight Failed for: {$query}");
1629 // test insertion of an index on a table
1630 $tempTableTestQuery_idx = str_replace("ADD INDEX `idx_", "ADD INDEX `temp_idx_", $tempTableTestQuery);
1631 logThis('testing query on temp table: ['.$tempTableTestQuery_idx.']');
1632 $r4 = $db->query($tempTableTestQuery_idx, false, "Preflight Failed for: {$query}");
1634 $mysqlError = mysql_error(); // empty on no-errors
1635 if(!empty($mysqlError)) {
1636 logThis('*** ERROR: query failed: '.$mysqlError);
1637 $error = getFormattedError($mysqlError, $query);
1641 // clean up moved to end of preflight
1645 logThis('mssql found: skipping test query - ['.$query.']');
1649 logThis('Oracle found: skipping test query - ['.$query.']');
1653 logThis($table . ' is a new table');
1656 logThis('verification done.');
1661 * Tests an CREATE TABLE query
1662 * @param string table The table name to get DDL
1663 * @param string dbType MySQL, MSSQL, etc.
1664 * @param string query The query to test.
1665 * @return string Non-empty if error found
1667 function testQueryCreate($table, $dbType, $query, &$newTables) {
1668 logThis('verifying CREATE statement...');
1671 $db = &DBManagerFactory::getInstance();
1677 // rewrite DDL with _temp name
1678 logThis('testing query: ['.$query.']');
1679 $tempTableQuery = str_replace("CREATE TABLE `{$table}`", "CREATE TABLE `{$table}__uw_temp`", $query);
1681 if(isRunningAgainstTrueTable($tempTableQuery)) {
1682 $error = getFormattedError('Could not use a temp table to test query!', $query);
1686 $r4 = $db->query($tempTableQuery, false, "Preflight Failed for: {$query}");
1688 $error = mysql_error(); // empty on no-errors
1689 if(!empty($error)) {
1690 logThis('*** ERROR: query failed.');
1691 $error = getFormattedError($error, $query);
1694 // check if table exists
1695 logThis('testing for table: '.$table);
1696 $q1 = "DESC `{$table}`";
1697 $r1 = $db->query($q1);
1699 $mysqlError = mysql_error();
1700 if(empty($mysqlError)) {
1701 logThis('*** ERROR: table already exists!: '.$table);
1702 $error = getFormattedError('table exists', $query);
1705 logThis('NEW TABLE: '.$query);
1706 $newTables[] = $table;
1711 logThis('mssql found: skipping test query - ['.$query.']');
1715 logThis('Oracle found: skipping test query - ['.$query.']');
1722 * Tests an DELETE FROM query
1723 * @param string table The table name to get DDL
1724 * @param string dbType MySQL, MSSQL, etc.
1725 * @param string query The query to test.
1726 * @return string Non-empty if error found
1728 function testQueryDelete($table, $dbType, $query) {
1729 logThis('verifying DELETE statements');
1732 $db = &DBManagerFactory::getInstance();
1740 logThis('creating temp table...');
1741 $q = "SHOW CREATE TABLE {$table}";
1742 $r = $db->query($q);
1743 $a = $db->fetchByAssoc($r);
1745 // rewrite DDL with _temp name
1746 $cleanQuery = cleanQuery($a['Create Table']);
1747 $tempTableQuery = str_replace("CREATE TABLE `{$table}`", "CREATE TABLE `{$table}__uw_temp`", $cleanQuery);
1748 $r2 = $db->query($tempTableQuery);
1750 // get sample data into the temp table to test for data/constraint conflicts
1751 logThis('inserting temp dataset...');
1752 $q3 = "INSERT INTO `{$table}__uw_temp` SELECT * FROM `{$table}` LIMIT 10";
1753 $r3 = $db->query($q3);
1755 // test the query on the test table
1756 logThis('testing query: ['.$query.']');
1757 $tempTableTestQuery = str_replace("DELETE FROM `{$table}`", "DELETE FROM `{$table}__uw_temp`", $query);
1759 if(isRunningAgainstTrueTable($tempTableTestQuery)) {
1760 $error = getFormattedError('Could not use a temp table to test query!', $tempTableTestQuery);
1764 $r4 = $db->query($tempTableTestQuery, false, "Preflight Failed for: {$query}");
1765 $error = mysql_error(); // empty on no-errors
1766 if(!empty($error)) {
1767 logThis('*** ERROR: query failed.');
1768 $error = getFormattedError($error, $query);
1773 logThis('mssql found: skipping test query - ['.$query.']');
1777 logThis('Oracle found: skipping test query - ['.$query.']');
1780 logThis('verification done.');
1785 * Tests a DROP TABLE query
1788 function testQueryDrop($table, $dbType, $query) {
1789 logThis('verifying DROP TABLE statement');
1792 $db = &DBManagerFactory::getInstance();
1800 logThis('creating temp table...');
1801 $q = "SHOW CREATE TABLE {$table}";
1802 $r = $db->query($q);
1803 $a = $db->fetchByAssoc($r);
1805 // rewrite DDL with _temp name
1806 $cleanQuery = cleanQuery($a['Create Table']);
1807 $tempTableQuery = str_replace("CREATE TABLE `{$table}`", "CREATE TABLE `{$table}__uw_temp`", $cleanQuery);
1808 $r2 = $db->query($tempTableQuery);
1810 // get sample data into the temp table to test for data/constraint conflicts
1811 logThis('inserting temp dataset...');
1812 $query = stripQuotesUW($query, $table);
1813 $q3 = "INSERT INTO `{$table}__uw_temp` SELECT * FROM `{$table}` LIMIT 10";
1814 $r3 = $db->query($q3);
1816 // test the query on the test table
1817 logThis('testing query: ['.$query.']');
1818 $tempTableTestQuery = str_replace("DROP TABLE `{$table}`", "DROP TABLE `{$table}__uw_temp`", $query);
1820 // make sure the test query is running against a temp table
1821 if(isRunningAgainstTrueTable($tempTableTestQuery)) {
1822 $error = getFormattedError('Could not use a temp table to test query!', $tempTableTestQuery);
1826 $r4 = $db->query($tempTableTestQuery, false, "Preflight Failed for: {$query}");
1827 $error = mysql_error(); // empty on no-errors
1828 if(!empty($error)) {
1829 logThis('*** ERROR: query failed.');
1830 $error = getFormattedError($error, $query);
1835 logThis('mssql found: skipping test query - ['.$query.']');
1839 logThis('Oracle found: skipping test query - ['.$query.']');
1842 logThis('verification done.');
1847 * Tests an INSERT INTO query
1848 * @param string table The table name to get DDL
1849 * @param string dbType MySQL, MSSQL, etc.
1850 * @param string query The query to test.
1851 * @return string Non-empty if error found
1853 function testQueryInsert($table, $dbType, $query) {
1854 logThis('verifying INSERT statement...');
1857 $db = &DBManagerFactory::getInstance();
1865 $q = "SHOW CREATE TABLE {$table}";
1866 $r = $db->query($q);
1867 $a = $db->fetchByAssoc($r);
1869 // rewrite DDL with _temp name
1870 $cleanQuery = cleanQuery($a['Create Table']);
1871 $tempTableQuery = str_replace("CREATE TABLE `{$table}`", "CREATE TABLE `{$table}__uw_temp`", $cleanQuery);
1872 $r2 = $db->query($tempTableQuery);
1874 // test the query on the test table
1875 logThis('testing query: ['.$query.']');
1876 $tempTableTestQuery = str_replace("INSERT INTO `{$table}`", "INSERT INTO `{$table}__uw_temp`", $query);
1878 // make sure the test query is running against a temp table
1879 if(isRunningAgainstTrueTable($tempTableTestQuery)) {
1880 $error = getFormattedError('Could not use a temp table to test query!', $tempTableTestQuery);
1884 $r4 = $db->query($tempTableTestQuery, false, "Preflight Failed for: {$query}");
1885 $error = mysql_error(); // empty on no-errors
1886 if(!empty($error)) {
1887 logThis('*** ERROR: query failed.');
1888 $error = getFormattedError($error, $query);
1893 logThis('mssql found: skipping test query - ['.$query.']');
1897 logThis('Oracle found: skipping test query - ['.$query.']');
1900 logThis('verification done.');
1906 * Tests an UPDATE TABLE query
1907 * @param string table The table name to get DDL
1908 * @param string dbType MySQL, MSSQL, etc.
1909 * @param string query The query to test.
1910 * @return string Non-empty if error found
1912 function testQueryUpdate($table, $dbType, $query) {
1913 logThis('verifying UPDATE TABLE statement...');
1916 $db = &DBManagerFactory::getInstance();
1924 $q = "SHOW CREATE TABLE {$table}";
1925 $r = $db->query($q);
1926 $a = $db->fetchByAssoc($r);
1928 // rewrite DDL with _temp name
1929 $cleanQuery = cleanQuery($a['Create Table']);
1930 $tempTableQuery = str_replace("CREATE TABLE `{$table}`", "CREATE TABLE `{$table}__uw_temp`", $cleanQuery);
1931 $r2 = $db->query($tempTableQuery);
1933 // get sample data into the temp table to test for data/constraint conflicts
1934 logThis('inserting temp dataset...');
1935 $q3 = "INSERT INTO `{$table}__uw_temp` SELECT * FROM `{$table}` LIMIT 10";
1936 $r3 = $db->query($q3, false, "Preflight Failed for: {$query}");
1938 // test the query on the test table
1939 logThis('testing query: ['.$query.']');
1940 $tempTableTestQuery = str_replace("UPDATE `{$table}`", "UPDATE `{$table}__uw_temp`", $query);
1942 // make sure the test query is running against a temp table
1943 if(isRunningAgainstTrueTable($tempTableTestQuery)) {
1944 $error = getFormattedError('Could not use a temp table to test query!', $tempTableTestQuery);
1948 $r4 = $db->query($tempTableTestQuery, false, "Preflight Failed for: {$query}");
1949 $error = mysql_error(); // empty on no-errors
1950 if(!empty($error)) {
1951 logThis('*** ERROR: query failed.');
1952 $error = getFormattedError($error, $query);
1960 logThis('Oracle found: skipping test query - ['.$query.']');
1963 logThis('verification done.');
1969 * strip queries of single and double quotes
1971 function stripQuotesUW($query, $table) {
1974 $start = strpos($query, $table);
1976 if(substr($query, ($start - 1), 1) != ' ') {
1977 $queryStrip = substr($query, 0, ($start-2));
1978 $queryStrip .= " {$table} ";
1979 $queryStrip .= substr($query, ($start + strlen($table) + 2), strlen($query));
1982 return (empty($queryStrip)) ? $query : $queryStrip;
1986 * ensures that a __UW_TEMP table test SQL is running against a temp table, not the real thing
1987 * @param string query
1988 * @return bool false if it is a good query
1990 function isRunningAgainstTrueTable($query) {
1991 $query = strtoupper($query);
1992 if(strpos($query, '__UW_TEMP') === false) {
1993 logThis('***ERROR: test query is NOT running against a temp table!!!! -> '.$query);
2008 * cleans up temp tables created during schema test phase
2010 function testCleanUp($dbType) {
2011 logThis('Cleaning up temporary tables...');
2015 $db = &DBManagerFactory::getInstance();
2021 $q = 'SHOW TABLES LIKE "%__uw_temp"';
2022 $r = $db->query($q, false, "Preflight Failed for: {$q}");
2024 // using raw mysql_command to use integer index
2025 while($a = $db->fetchByAssoc($r)) {
2026 logThis('Dropping table: '.$a[0]);
2027 $qClean = "DROP TABLE {$a[0]}";
2028 $rClean = $db->query($qClean);
2038 logThis('Done cleaning up temp tables.');
2043 function getFormattedError($error, $query) {
2044 $error = "<div><b>".$error;
2045 $error .= "</b>::{$query}</div>";
2053 * parses a query finding the table name
2054 * @param string query The query
2055 * @return string table The table
2057 function getTableFromQuery($query) {
2058 $standardQueries = array('ALTER TABLE', 'DROP TABLE', 'CREATE TABLE', 'INSERT INTO', 'UPDATE', 'DELETE FROM');
2059 $query = preg_replace("/[^A-Za-z0-9\_\s]/", "", $query);
2060 $query = trim(str_replace($standardQueries, '', $query));
2062 $firstSpc = strpos($query, " ");
2063 $end = ($firstSpc > 0) ? $firstSpc : strlen($query);
2064 $table = substr($query, 0, $end);
2071 function preLicenseCheck() {
2072 require_once('modules/UpgradeWizard/uw_files.php');
2074 global $sugar_config;
2075 global $mod_strings;
2076 global $sugar_version;
2078 if(!isset($sugar_version) || empty($sugar_version)) {
2079 require_once('./sugar_version.php');
2082 if(!isset($_SESSION['unzip_dir']) || empty($_SESSION['unzip_dir'])) {
2083 logThis('unzipping files in upgrade archive...');
2085 $base_upgrade_dir = $sugar_config['upload_dir'] . "/upgrades";
2086 $base_tmp_upgrade_dir = "$base_upgrade_dir/temp";
2088 //also come up with mechanism to read from upgrade-progress file
2089 if(!isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !is_file($_SESSION['install_file'])) {
2091 if ($handle = opendir(clean_path($sugar_config['upload_dir']))) {
2092 while (false !== ($file = readdir($handle))) {
2093 if($file !="." && $file !="..") {
2094 $far = explode(".",$file);
2095 if($far[sizeof($far)-1] == 'zip') {
2096 echo $sugar_config['upload_dir'].'/'.$file;
2097 $_SESSION['install_file'] = $sugar_config['upload_dir'].'/'.$file;
2103 if (file_exists(clean_path($base_tmp_upgrade_dir)) && $handle = opendir(clean_path($base_tmp_upgrade_dir))) {
2104 while (false !== ($file = readdir($handle))) {
2105 if($file !="." && $file !="..") {
2106 //echo $base_tmp_upgrade_dir."/".$file.'</br>';
2107 if(is_file($base_tmp_upgrade_dir."/".$file."/manifest.php")){
2108 require_once($base_tmp_upgrade_dir."/".$file."/manifest.php");
2109 $package_name= $manifest['copy_files']['from_dir'];
2110 //echo file_exists($base_tmp_upgrade_dir."/".$file."/".$package_name).'</br>';
2111 if(file_exists($base_tmp_upgrade_dir."/".$file."/".$package_name) && file_exists($base_tmp_upgrade_dir."/".$file."/scripts") && file_exists($base_tmp_upgrade_dir."/".$file."/manifest.php")){
2112 //echo 'Yeah this the directory '. $base_tmp_upgrade_dir."/".$file;
2113 $unzip_dir = $base_tmp_upgrade_dir."/".$file;
2114 if(file_exists($sugar_config['upload_dir'].'/upgrades/patch/'.$package_name.'.zip')){
2115 $_SESSION['install_file'] = $sugar_config['upload_dir'].'/upgrades/patch/'.$package_name.'.zip';
2124 if(!isset($_SESSION['install_file']) || empty($_SESSION['install_file'])){
2127 echo 'Upload File not found so redirecting to Upgrade Start ';
2128 $redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
2129 echo '<form name="redirect" action="' .$redirect_new_wizard. '" method="POST">';
2130 $upgrade_directories_not_found =<<<eoq
2131 <table cellpadding="3" cellspacing="0" border="0">
2133 <th colspan="2" align="left">
2134 <span class='error'><b>'Upload file missing or has been deleted. Refresh the page to go back to UpgradeWizard start'</b></span>
2139 $uwMain = $upgrade_directories_not_found;
2142 $install_file = urldecode( $_SESSION['install_file'] );
2144 if(empty($unzip_dir)){
2145 $unzip_dir = mk_temp_dir( $base_tmp_upgrade_dir );
2147 $zip_from_dir = ".";
2149 $zip_force_copy = array();
2152 logThis('Could not create a temporary directory using mk_temp_dir( $base_tmp_upgrade_dir )');
2153 die($mod_strings['ERR_UW_NO_CREATE_TMP_DIR']);
2156 //double check whether unzipped .
2157 if(file_exists($unzip_dir ."/scripts") && file_exists($unzip_dir."/manifest.php")){
2161 unzip( $install_file, $unzip_dir );
2164 // assumption -- already validated manifest.php at time of upload
2165 require_once( "$unzip_dir/manifest.php" );
2167 if( isset( $manifest['copy_files']['from_dir'] ) && $manifest['copy_files']['from_dir'] != "" ){
2168 $zip_from_dir = $manifest['copy_files']['from_dir'];
2170 if( isset( $manifest['copy_files']['to_dir'] ) && $manifest['copy_files']['to_dir'] != "" ){
2171 $zip_to_dir = $manifest['copy_files']['to_dir'];
2173 if( isset( $manifest['copy_files']['force_copy'] ) && $manifest['copy_files']['force_copy'] != "" ){
2174 $zip_force_copy = $manifest['copy_files']['force_copy'];
2176 if( isset( $manifest['version'] ) ){
2177 $version = $manifest['version'];
2179 if( !is_writable( "config.php" ) ){
2180 return $mod_strings['ERR_UW_CONFIG'];
2183 $_SESSION['unzip_dir'] = clean_path($unzip_dir);
2184 $_SESSION['zip_from_dir'] = clean_path($zip_from_dir);
2185 logThis('unzip done.');
2187 $unzip_dir = $_SESSION['unzip_dir'];
2188 $zip_from_dir = $_SESSION['zip_from_dir'];
2191 //check if $_SESSION['unzip_dir'] and $_SESSION['zip_from_dir'] exist
2192 if(!isset($_SESSION['unzip_dir']) || !file_exists($_SESSION['unzip_dir'])
2193 || !isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !file_exists($_SESSION['install_file'])){
2197 echo 'Upload File not found so redirecting to Upgrade Start ';
2198 $redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
2199 echo '<form name="redirect" action="' .$redirect_new_wizard. '" method="POST">';
2200 $upgrade_directories_not_found =<<<eoq
2201 <table cellpadding="3" cellspacing="0" border="0">
2203 <th colspan="2" align="left">
2204 <span class='error'><b>'Upload file missing or has been deleted. Refresh the page to go back to UpgradeWizard start'</b></span>
2209 $uwMain = $upgrade_directories_not_found;
2213 $parserFiles = array();
2215 if(file_exists(clean_path($unzip_dir.'/'.$zip_from_dir."/include/SugarFields"))) {
2216 $parserFiles = findAllFiles(clean_path($unzip_dir.'/'.$zip_from_dir."/include/SugarFields"), $parserFiles);
2219 $cwd = clean_path(getcwd());
2220 foreach($parserFiles as $file) {
2221 $srcFile = clean_path($file);
2222 //$targetFile = clean_path(getcwd() . '/' . $srcFile);
2223 if (strpos($srcFile,".svn") !== false) {
2227 $targetFile = str_replace(clean_path($unzip_dir.'/'.$zip_from_dir), $cwd, $srcFile);
2229 if(!is_dir(dirname($targetFile))) {
2230 mkdir_recursive(dirname($targetFile)); // make sure the directory exists
2233 if(!file_exists($targetFile))
2235 // handle sugar_version.php
2236 // C.L. - Added check for portal directory
2237 if(strpos($targetFile, 'sugar_version.php') !== false && !preg_match('/\/portal\/sugar_version\.php$/i', $targetFile)) {
2238 logThis('Skipping "sugar_version.php" - file copy will occur at end of successful upgrade', $path);
2239 $_SESSION['sugar_version_file'] = $srcFile;
2243 //logThis('Copying file to destination: ' . $targetFile);
2245 if(!copy($srcFile, $targetFile)) {
2246 logThis('*** ERROR: could not copy file: ' . $targetFile);
2248 $copiedFiles[] = $targetFile;
2251 //logThis('Skipping file: ' . $targetFile);
2252 //$skippedFiles[] = $targetFile;
2257 //Also copy the SugarMerge files
2258 if(file_exists(clean_path($unzip_dir.'/'.$zip_from_dir."/UpgradeWizard510Files"))) {
2259 $parserFiles = findAllFiles(clean_path($unzip_dir.'/'.$zip_from_dir."/UpgradeWizard510Files"), $parserFiles);
2260 foreach($parserFiles as $file) {
2261 $srcFile = clean_path($file);
2262 //$targetFile = clean_path(getcwd() . '/' . $srcFile);
2263 if (strpos($srcFile,".svn") !== false) {
2267 $targetFile = str_replace(clean_path($unzip_dir.'/'.$zip_from_dir."/UpgradeWizard510Files"), $cwd, $srcFile);
2268 if(!is_dir(dirname($targetFile))) {
2269 mkdir_recursive(dirname($targetFile)); // make sure the directory exists
2271 logThis('updating UpgradeWizard code: '.$targetFile);
2272 copy_recursive($file, $targetFile);
2276 logThis ('is SugarConfig there '.file_exists(clean_path($unzip_dir.'/'.$zip_from_dir."/include/SugarObjects/SugarConfig.php")));
2277 if(file_exists(clean_path($unzip_dir.'/'.$zip_from_dir."/include/SugarObjects/SugarConfig.php"))) {
2278 $file = clean_path($unzip_dir.'/'.$zip_from_dir."/include/SugarObjects/SugarConfig.php");
2279 $destFile = str_replace(clean_path($unzip_dir.'/'.$zip_from_dir), $cwd, $file);
2280 if(!is_dir(dirname($destFile))) {
2281 mkdir_recursive(dirname($destFile)); // make sure the directory exists
2283 copy($file,$destFile);
2284 //also copy include utils array utils
2285 $file = clean_path($unzip_dir.'/'.$zip_from_dir."/include/utils/array_utils.php");
2286 $destFile = str_replace(clean_path($unzip_dir.'/'.$zip_from_dir), $cwd, $file);
2287 if(!is_dir(dirname($destFile))) {
2288 mkdir_recursive(dirname($destFile)); // make sure the directory exists
2290 copy($file,$destFile);
2295 function preflightCheck() {
2296 require_once('modules/UpgradeWizard/uw_files.php');
2298 global $sugar_config;
2299 global $mod_strings;
2300 global $sugar_version;
2302 if(!isset($sugar_version) || empty($sugar_version)) {
2303 require_once('./sugar_version.php');
2306 unset($_SESSION['rebuild_relationships']);
2307 unset($_SESSION['rebuild_extensions']);
2309 // don't bother if are rechecking
2310 $manualDiff = array();
2311 if(!isset($_SESSION['unzip_dir']) || empty($_SESSION['unzip_dir'])) {
2312 logThis('unzipping files in upgrade archive...');
2314 $base_upgrade_dir = $sugar_config['upload_dir'] . "/upgrades";
2315 $base_tmp_upgrade_dir = "$base_upgrade_dir/temp";
2317 //Following is if User logged out unexpectedly and then logged into UpgradeWizard again.
2318 //also come up with mechanism to read from upgrade-progress file.
2319 if(!isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !is_file($_SESSION['install_file'])) {
2320 if (file_exists(clean_path($base_tmp_upgrade_dir)) && $handle = opendir(clean_path($base_tmp_upgrade_dir))) {
2321 while (false !== ($file = readdir($handle))) {
2322 if($file !="." && $file !="..") {
2323 //echo $base_tmp_upgrade_dir."/".$file.'</br>';
2324 if(is_file($base_tmp_upgrade_dir."/".$file."/manifest.php")){
2325 require_once($base_tmp_upgrade_dir."/".$file."/manifest.php");
2326 $package_name= $manifest['copy_files']['from_dir'];
2327 //echo file_exists($base_tmp_upgrade_dir."/".$file."/".$package_name).'</br>';
2328 if(file_exists($base_tmp_upgrade_dir."/".$file."/".$package_name) && file_exists($base_tmp_upgrade_dir."/".$file."/scripts") && file_exists($base_tmp_upgrade_dir."/".$file."/manifest.php")){
2329 //echo 'Yeah this the directory '. $base_tmp_upgrade_dir."/".$file;
2330 $unzip_dir = $base_tmp_upgrade_dir."/".$file;
2331 if(file_exists($sugar_config['upload_dir'].'/upgrades/patch/'.$package_name.'.zip')){
2332 $_SESSION['install_file'] = $sugar_config['upload_dir'].'/upgrades/patch/'.$package_name.'.zip';
2341 if(!isset($_SESSION['install_file']) || empty($_SESSION['install_file'])){
2344 echo 'Upload File not found so redirecting to Upgrade Start ';
2345 $redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
2346 echo '<form name="redirect" action="' .$redirect_new_wizard. '" method="POST">';
2347 $upgrade_directories_not_found =<<<eoq
2348 <table cellpadding="3" cellspacing="0" border="0">
2350 <th colspan="2" align="left">
2351 <span class='error'><b>'Upload file missing or has been deleted. Refresh the page to go back to UpgradeWizard start'</b></span>
2356 $uwMain = $upgrade_directories_not_found;
2360 $install_file = urldecode( $_SESSION['install_file'] );
2362 if(empty($unzip_dir)){
2363 $unzip_dir = mk_temp_dir( $base_tmp_upgrade_dir );
2365 $zip_from_dir = ".";
2367 $zip_force_copy = array();
2370 logThis('Could not create a temporary directory using mk_temp_dir( $base_tmp_upgrade_dir )');
2371 die($mod_strings['ERR_UW_NO_CREATE_TMP_DIR']);
2374 //double check whether unzipped .
2375 if(file_exists($unzip_dir ."/scripts") && file_exists($unzip_dir."/manifest.php")){
2379 unzip( $install_file, $unzip_dir );
2382 // assumption -- already validated manifest.php at time of upload
2383 require_once( "$unzip_dir/manifest.php" );
2385 if( isset( $manifest['copy_files']['from_dir'] ) && $manifest['copy_files']['from_dir'] != "" ){
2386 $zip_from_dir = $manifest['copy_files']['from_dir'];
2388 if( isset( $manifest['copy_files']['to_dir'] ) && $manifest['copy_files']['to_dir'] != "" ){
2389 $zip_to_dir = $manifest['copy_files']['to_dir'];
2391 if( isset( $manifest['copy_files']['force_copy'] ) && $manifest['copy_files']['force_copy'] != "" ){
2392 $zip_force_copy = $manifest['copy_files']['force_copy'];
2394 if( isset( $manifest['version'] ) ){
2395 $version = $manifest['version'];
2397 if( !is_writable( "config.php" ) ){
2398 return $mod_strings['ERR_UW_CONFIG'];
2401 $_SESSION['unzip_dir'] = clean_path($unzip_dir);
2402 $_SESSION['zip_from_dir'] = clean_path($zip_from_dir);
2404 //logThis('unzip done.');
2406 $unzip_dir = $_SESSION['unzip_dir'];
2407 $zip_from_dir = $_SESSION['zip_from_dir'];
2409 //check if $_SESSION['unzip_dir'] and $_SESSION['zip_from_dir'] exist
2410 if(!isset($_SESSION['unzip_dir']) || !file_exists($_SESSION['unzip_dir'])
2411 || !isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !file_exists($_SESSION['install_file'])){
2415 echo 'Upload File not found so redirecting to Upgrade Start ';
2416 $redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
2417 echo '<form name="redirect" action="' .$redirect_new_wizard. '" method="POST">';
2418 $upgrade_directories_not_found =<<<eoq
2419 <table cellpadding="3" cellspacing="0" border="0">
2421 <th colspan="2" align="left">
2422 <span class='error'><b>'Upload file missing or has been deleted. Refresh the page to go back to UpgradeWizard start'</b></span>
2427 $uwMain = $upgrade_directories_not_found;
2430 //copy minimum required files
2431 fileCopy('include/utils/sugar_file_utils.php');
2434 if(file_exists('include/utils/file_utils.php')){
2437 $upgradeFiles = findAllFiles(clean_path("$unzip_dir/$zip_from_dir"), array());
2438 $cache_html_files= array();
2439 if(is_dir("{$GLOBALS['sugar_config']['cache_dir']}layout")){
2440 //$cache_html_files = findAllFilesRelative( "cache/layout", array());
2444 $md5_string = array();
2445 if(file_exists(clean_path(getcwd().'/files.md5'))){
2446 require(clean_path(getcwd().'/files.md5'));
2449 // file preflight checks
2450 logThis('verifying md5 checksums for files...');
2451 foreach($upgradeFiles as $file) {
2452 if(in_array(str_replace(clean_path("$unzip_dir/$zip_from_dir") . "/", '', $file), $uw_files))
2453 continue; // skip already loaded files
2455 if(strpos($file, '.md5'))
2456 continue; // skip md5 file
2458 // normalize file paths
2459 $file = clean_path($file);
2461 // check that we can move/delete the upgraded file
2462 if(!is_writable($file)) {
2463 $errors[] = $mod_strings['ERR_UW_FILE_NOT_WRITABLE'].": ".$file;
2465 // check that destination files are writable
2466 $destFile = getcwd().str_replace(clean_path($unzip_dir.'/'.$zip_from_dir), '', $file);
2468 if(is_file($destFile)) { // of course it needs to exist first...
2469 if(!is_writable($destFile)) {
2470 $errors[] = $mod_strings['ERR_UW_FILE_NOT_WRITABLE'].": ".$destFile;
2474 ///////////////////////////////////////////////////////////////////////
2476 // compare md5s and build up a manual merge list
2477 $targetFile = clean_path(".".str_replace(getcwd(),'',$destFile));
2479 if(is_file($destFile)) {
2480 if(strpos($targetFile, '.php')) {
2481 // handle PHP files that were hit with the security regex
2483 if(function_exists('sugar_fopen')){
2484 $fp = sugar_fopen($destFile, 'r');
2487 $fp = fopen($destFile, 'r');
2489 $filesize = filesize($destFile);
2491 $fileContents = stream_get_contents($fp);
2492 $targetMd5 = md5($fileContents);
2495 $targetMd5 = md5_file($destFile);
2499 if(isset($md5_string[$targetFile]) && $md5_string[$targetFile] != $targetMd5) {
2500 logThis('found a file with a differing md5: ['.$targetFile.']');
2501 $manualDiff[] = $destFile;
2504 ///////////////////////////////////////////////////////////////////////
2506 logThis('md5 verification done.');
2507 $errors['manual'] = $manualDiff;
2512 function fileCopy($file_path){
2513 if(file_exists(clean_path($_SESSION['unzip_dir'].'/'.$_SESSION['zip_from_dir'].'/'.$file_path))) {
2514 $file = clean_path($_SESSION['unzip_dir'].'/'.$_SESSION['zip_from_dir'].'/'.$file_path);
2515 $destFile = str_replace(clean_path($_SESSION['unzip_dir'].'/'.$_SESSION['zip_from_dir']), clean_path(getcwd()), $file);
2516 if(!is_dir(dirname($destFile))) {
2517 mkdir_recursive(dirname($destFile)); // make sure the directory exists
2519 copy_recursive($file,$destFile);
2522 function getChecklist($steps, $step) {
2523 global $mod_strings;
2525 $skip = array('start', 'cancel', 'uninstall','end');
2528 $ret = '<table cellpadding="3" cellspacing="4" border="0">';
2529 $ret .= '<tr><th colspan="3" align="left">'.$mod_strings['LBL_UW_CHECKLIST'].':</th></tr>';
2530 foreach($steps['desc'] as $k => $desc) {
2531 if(in_array($steps['files'][$j], $skip)) {
2536 //$status = "<span class='error'>{$mod_strings['LBL_UW_INCOMPLETE']}</span>";
2538 $desc_mod_post = '';
2540 if(isset($_SESSION['step'][$steps['files'][$k]]) && $_SESSION['step'][$steps['files'][$k]] == 'success') {
2541 //$status = $mod_strings['LBL_UW_COMPLETE'];
2545 if($k == $_REQUEST['step']) {
2546 //$status = $mod_strings['LBL_UW_IN_PROGRESS'];
2547 $desc_mod_pre = "<font color=blue><i>";
2548 $desc_mod_post = "</i></font>";
2551 $ret .= "<tr><td> </td><td><b>{$i}: {$desc_mod_pre}{$desc}{$desc_mod_post}</b></td>";
2552 $ret .= "<td id={$steps['files'][$j]}><i></i></td></tr>";
2560 function prepSystemForUpgrade() {
2561 global $sugar_config;
2562 global $sugar_flavor;
2563 global $mod_strings;
2565 global $base_upgrade_dir;
2566 global $base_tmp_upgrade_dir;
2568 ///////////////////////////////////////////////////////////////////////////////
2569 //// Make sure variables exist
2570 if(!isset($base_upgrade_dir) || empty($base_upgrade_dir)){
2571 $base_upgrade_dir = getcwd().'/'.$sugar_config['upload_dir'] . "upgrades";
2573 if(!isset($base_tmp_upgrade_dir) || empty($base_tmp_upgrade_dir)){
2574 $base_tmp_upgrade_dir = "$base_upgrade_dir/temp";
2576 if(!isset($subdirs) || empty($subdirs)){
2577 $subdirs = array('full', 'langpack', 'module', 'patch', 'theme', 'temp');
2580 $upgrade_progress_dir = getcwd().'/'.$GLOBALS['sugar_config']['upload_dir'].'upgrades/temp';
2581 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
2582 if(file_exists($upgrade_progress_file)){
2583 if(function_exists('get_upgrade_progress') && function_exists('didThisStepRunBefore')){
2584 if(didThisStepRunBefore('end')){
2585 include($upgrade_progress_file);
2586 unset($upgrade_config);
2587 unlink($upgrade_progress_file);
2592 // increase the cuttoff time to 1 hour
2593 ini_set("max_execution_time", "3600");
2595 // make sure dirs exist
2596 if($subdirs != null){
2597 foreach($subdirs as $subdir) {
2598 mkdir_recursive("$base_upgrade_dir/$subdir");
2601 // array of special scripts that are executed during (un)installation-- key is type of script, value is filename
2602 if(!defined('SUGARCRM_PRE_INSTALL_FILE')) {
2603 define('SUGARCRM_PRE_INSTALL_FILE', 'scripts/pre_install.php');
2604 define('SUGARCRM_POST_INSTALL_FILE', 'scripts/post_install.php');
2605 define('SUGARCRM_PRE_UNINSTALL_FILE', 'scripts/pre_uninstall.php');
2606 define('SUGARCRM_POST_UNINSTALL_FILE', 'scripts/post_uninstall.php');
2609 $script_files = array(
2610 "pre-install" => constant('SUGARCRM_PRE_INSTALL_FILE'),
2611 "post-install" => constant('SUGARCRM_POST_INSTALL_FILE'),
2612 "pre-uninstall" => constant('SUGARCRM_PRE_UNINSTALL_FILE'),
2613 "post-uninstall" => constant('SUGARCRM_POST_UNINSTALL_FILE'),
2616 // check that the upload limit is set to 6M or greater
2617 define('SUGARCRM_MIN_UPLOAD_MAX_FILESIZE_BYTES', 6 * 1024 * 1024); // 6 Megabytes
2618 $upload_max_filesize = ini_get('upload_max_filesize');
2619 $upload_max_filesize_bytes = return_bytes($upload_max_filesize);
2621 if($upload_max_filesize_bytes < constant('SUGARCRM_MIN_UPLOAD_MAX_FILESIZE_BYTES')) {
2622 $GLOBALS['log']->debug("detected upload_max_filesize: $upload_max_filesize");
2624 echo '<p class="error">'.$mod_strings['MSG_INCREASE_UPLOAD_MAX_FILESIZE'].' '.get_cfg_var('cfg_file_path')."</p>\n";
2628 if ( !function_exists('extractFile') ) {
2629 function extractFile($zip_file, $file_in_zip) {
2630 global $base_tmp_upgrade_dir;
2633 $absolute_base_tmp_upgrade_dir = clean_path($base_tmp_upgrade_dir);
2634 $relative_base_tmp_upgrade_dir = clean_path(str_replace(clean_path(getcwd()), '', $absolute_base_tmp_upgrade_dir));
2636 // mk_temp_dir expects relative pathing
2637 $my_zip_dir = mk_temp_dir($relative_base_tmp_upgrade_dir);
2639 unzip_file($zip_file, $file_in_zip, $my_zip_dir);
2641 return("$my_zip_dir/$file_in_zip");
2645 if ( !function_exists('extractManifest') ) {
2646 function extractManifest($zip_file) {
2647 logThis('extracting manifest.');
2648 return(extractFile($zip_file, "manifest.php"));
2652 if ( !function_exists('getInstallType') ) {
2653 function getInstallType($type_string) {
2656 $subdirs = array('full', 'langpack', 'module', 'patch', 'theme', 'temp');
2657 foreach($subdirs as $subdir) {
2658 if(preg_match("#/$subdir/#", $type_string)) {
2662 // return empty if no match
2667 function getImageForType($type) {
2672 $icon = SugarThemeRegistry::current()->getImage("Upgrade", "");
2675 $icon = SugarThemeRegistry::current()->getImage("LanguagePacks", "");
2678 $icon = SugarThemeRegistry::current()->getImage("ModuleLoader", "");
2681 $icon = SugarThemeRegistry::current()->getImage("PatchUpgrades", "");
2684 $icon = SugarThemeRegistry::current()->getImage("Themes", "");
2692 if ( !function_exists('getLanguagePackName') ) {
2693 function getLanguagePackName($the_file) {
2694 require_once("$the_file");
2695 if(isset($app_list_strings["language_pack_name"])) {
2696 return($app_list_strings["language_pack_name"]);
2702 function getUITextForType($type) {
2703 if($type == "full") {
2704 return("Full Upgrade");
2706 if($type == "langpack") {
2707 return("Language Pack");
2709 if($type == "module") {
2712 if($type == "patch") {
2715 if($type == "theme") {
2722 * @todo this function doesn't seemed to be used anymore; trying kill this off
2724 function run_upgrade_wizard_sql($script) {
2726 global $sugar_config;
2728 $db_type = $sugar_config['dbconfig']['db_type'];
2729 $script = str_replace("%db_type%", $db_type, $script);
2730 if(!run_sql_file("$unzip_dir/$script")) {
2731 die("Error running sql file: $unzip_dir/$script");
2735 if ( !function_exists('validate_manifest') ) {
2737 * Verifies a manifest from a patch or module to be compatible with the current Sugar version and flavor
2738 * @param array manifest Standard manifest array
2739 * @return string Error message, blank on success
2741 function validate_manifest($manifest) {
2742 logThis('validating manifest.php file');
2743 // takes a manifest.php manifest array and validates contents
2745 global $sugar_version;
2746 global $sugar_flavor;
2747 global $mod_strings;
2749 if(!isset($manifest['type'])) {
2750 return $mod_strings['ERROR_MANIFEST_TYPE'];
2753 $type = $manifest['type'];
2755 if(getInstallType("/$type/") == "") {
2756 return $mod_strings['ERROR_PACKAGE_TYPE']. ": '" . $type . "'.";
2759 if(isset($manifest['acceptable_sugar_versions'])) {
2760 $version_ok = false;
2761 $matches_empty = true;
2762 if(isset($manifest['acceptable_sugar_versions']['exact_matches'])) {
2763 $matches_empty = false;
2764 foreach($manifest['acceptable_sugar_versions']['exact_matches'] as $match) {
2765 if($match == $sugar_version) {
2770 if(!$version_ok && isset($manifest['acceptable_sugar_versions']['regex_matches'])) {
2771 $matches_empty = false;
2772 foreach($manifest['acceptable_sugar_versions']['regex_matches'] as $match) {
2773 if(preg_match("/$match/", $sugar_version)) {
2779 if(!$matches_empty && !$version_ok) {
2780 return $mod_strings['ERROR_VERSION_INCOMPATIBLE']."<br />".
2781 $mod_strings['ERR_UW_VERSION'].$sugar_version;
2785 if(isset($manifest['acceptable_sugar_flavors']) && sizeof($manifest['acceptable_sugar_flavors']) > 0) {
2787 foreach($manifest['acceptable_sugar_flavors'] as $match) {
2788 if($match == $sugar_flavor) {
2793 return $mod_strings['ERROR_FLAVOR_INCOMPATIBLE']."<br />".
2794 $mod_strings['ERR_UW_FLAVOR'].$sugar_flavor."<br />".
2795 $mod_strings['ERR_UW_FLAVOR_2'].$manifest['acceptable_sugar_flavors'][0];
2803 function unlinkUploadFiles() {
2805 // logThis('at unlinkUploadFiles()');
2807 // if(isset($_SESSION['install_file']) && !empty($_SESSION['install_file'])) {
2808 // $upload = $_SESSION['install_file'];
2810 // if(is_file($upload)) {
2811 // logThis('unlinking ['.$upload.']');
2812 // @unlink($upload);
2817 if ( !function_exists('unlinkTempFiles') ) {
2819 * deletes files created by unzipping a package
2821 function unlinkTempFiles() {
2822 global $sugar_config;
2825 logThis('at unlinkTempFiles()');
2827 $sugar_config['upload_dir']='cache/upload/';
2828 //if(isset($sugar_config['upload_dir']) && $sugar_config['upload_dir'] != null && $sugar_config['upload_dir']=='cache/upload/'){
2829 $tempDir = clean_path(getcwd().'/'.$sugar_config['upload_dir'].'upgrades/temp');
2832 $uploadDir = getcwd()."/".'cache/upload/';
2833 $tempDir = clean_path(getcwd().'/'.$uploadDir.'upgrades/temp');
2835 if(file_exists($tempDir) && is_dir($tempDir)){
2836 $files = findAllFiles($tempDir, array(), false);
2838 foreach($files as $file) {
2839 if(!is_dir($file)) {
2840 //logThis('unlinking ['.$file.']', $path);
2845 $files = findAllFiles($tempDir, array(), true);
2846 foreach($files as $dir) {
2848 //logThis('removing dir ['.$dir.']', $path);
2852 $cacheFile = "modules/UpgradeWizard/_persistence.php";
2853 if(is_file($cacheFile)) {
2854 logThis("Unlinking Upgrade cache file: '_persistence.php'", $path);
2855 @unlink($cacheFile);
2858 logThis("finished!");
2863 * finds all files in the passed path, but skips select directories
2864 * @param string dir Relative path
2865 * @param array the_array Collections of found files/dirs
2866 * @param bool include_dir True if we want to include directories in the
2867 * returned collection
2869 function uwFindAllFiles($dir, $theArray, $includeDirs=false, $skipDirs=array(), $echo=false) {
2871 if (whetherNeedToSkipDir($dir, $skipDirs))
2876 if (!is_dir($dir)) { return $theArray; } // Bug # 46035, just checking for valid dir
2878 if ($d === false) { return $theArray; } // Bug # 46035, more checking
2880 while($f = $d->read()) {
2881 // bug 40793 Skip Directories array in upgradeWizard does not function correctly
2882 if($f == "." || $f == ".." || whetherNeedToSkipDir("$dir/$f", $skipDirs)) { // skip *nix self/parent
2886 // for AJAX length count
2892 if(is_dir("$dir/$f")) {
2893 if($includeDirs) { // add the directory if flagged
2894 $theArray[] = clean_path("$dir/$f");
2898 $theArray = uwFindAllFiles("$dir/$f/", $theArray, $includeDirs, $skipDirs, $echo);
2900 $theArray[] = clean_path("$dir/$f");
2912 * unset's UW's Session Vars
2914 function resetUwSession() {
2915 logThis('resetting $_SESSION');
2917 if(isset($_SESSION['committed']))
2918 unset($_SESSION['committed']);
2919 if(isset($_SESSION['sugar_version_file']))
2920 unset($_SESSION['sugar_version_file']);
2921 if(isset($_SESSION['upgrade_complete']))
2922 unset($_SESSION['upgrade_complete']);
2923 if(isset($_SESSION['allTables']))
2924 unset($_SESSION['allTables']);
2925 if(isset($_SESSION['alterCustomTableQueries']))
2926 unset($_SESSION['alterCustomTableQueries']);
2927 if(isset($_SESSION['skip_zip_upload']))
2928 unset($_SESSION['skip_zip_upload']);
2929 if(isset($_SESSION['sugar_version_file']))
2930 unset($_SESSION['sugar_version_file']);
2931 if(isset($_SESSION['install_file']))
2932 unset($_SESSION['install_file']);
2933 if(isset($_SESSION['unzip_dir']))
2934 unset($_SESSION['unzip_dir']);
2935 if(isset($_SESSION['zip_from_dir']))
2936 unset($_SESSION['zip_from_dir']);
2937 if(isset($_SESSION['overwrite_files']))
2938 unset($_SESSION['overwrite_files']);
2939 if(isset($_SESSION['schema_change']))
2940 unset($_SESSION['schema_change']);
2941 if(isset($_SESSION['uw_restore_dir']))
2942 unset($_SESSION['uw_restore_dir']);
2943 if(isset($_SESSION['step']))
2944 unset($_SESSION['step']);
2945 if(isset($_SESSION['files']))
2946 unset($_SESSION['files']);
2947 if(isset($_SESSION['Upgraded451Wizard'])){
2948 unset($_SESSION['Upgraded451Wizard']);
2950 if(isset($_SESSION['Initial_451to500_Step'])){
2951 unset($_SESSION['Initial_451to500_Step']);
2953 if(isset($_SESSION['license_shown']))
2954 unset($_SESSION['license_shown']);
2955 if(isset($_SESSION['sugarMergeRunResults']))
2956 unset($_SESSION['sugarMergeRunResults']);
2960 * runs rebuild scripts
2962 function UWrebuild() {
2966 //CCL - Comment this block out, it is called in end.php
2967 logThis('Rebuilding everything...', $path);
2968 require_once('modules/Administration/QuickRepairAndRebuild.php');
2969 $randc = new RepairAndClear();
2970 $randc->repairAndClearAll(array('clearAll'),array(translate('LBL_ALL_MODULES')), false, false);
2972 $query = "DELETE FROM versions WHERE name='Rebuild Extensions'";
2974 logThis('Registering rebuild record: '.$query, $path);
2975 logThis('Rebuild done.', $path);
2977 // insert a new database row to show the rebuild extensions is done
2978 $id = create_guid();
2979 $gmdate = gmdate('Y-m-d H:i:s');
2980 $date_entered = db_convert("'$gmdate'", 'datetime');
2981 $query = 'INSERT INTO versions (id, deleted, date_entered, date_modified, modified_user_id, created_by, name, file_version, db_version) '
2982 . "VALUES ('$id', '0', $date_entered, $date_entered, '1', '1', 'Rebuild Extensions', '4.0.0', '4.0.0')";
2984 logThis('Registering rebuild record in versions table: '.$query, $path);
2987 function getCustomTables($dbType) {
2990 $customTables = array();
2994 $query = "SHOW tables LIKE '%_cstm'";
2995 $result = $db->query($query);//, true, 'Error getting custom tables');
2996 while ($row = $db->fetchByAssoc($result)){
2997 $customTables[] = array_pop($row);
3001 return $customTables;
3004 function alterCustomTables($dbType, $customTables)
3009 while( $i < count($customTables) ) {
3010 $alterCustomTableSql[] = "ALTER TABLE " . $customTables[$i] . " CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci";
3017 return $alterCustomTableSql;
3020 function executeAlterCustomTablesSql($dbType, $queries) {
3023 foreach($queries as $query){
3025 logThis("Sending query: ".$query);
3026 if($db->dbType == 'oci8') {
3028 $query_result = $db->query($query);//.';', true, "An error has occured while performing db query. See log file for details.<br>");
3035 function getAllTables($dbType) {
3042 $query = "SHOW tables";
3043 $result = $db->query($query, true, 'Error getting custom tables');
3044 while ($row = $db->fetchByAssoc($result)){
3045 $tables[] = array_pop($row);
3052 function printAlterTableSql($tables)
3054 $alterTableSql = '';
3056 foreach($tables as $table)
3057 $alterTableSql .= "ALTER TABLE " . $table . " CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;" . "\n";
3059 return $alterTableSql;
3062 function executeConvertTablesSql($dbType, $tables) {
3065 foreach($tables as $table){
3066 $query = "ALTER TABLE " . $table . " CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci";
3068 logThis("Sending query: ".$query);
3069 if($db->dbType == 'oci8') {
3071 $query_result = $db->query($query);//.';', true, "An error has occured while performing db query. See log file for details.<br>");
3078 function testThis() {
3079 $files = uwFindAllFiles(getcwd().'/test', array());
3081 $out = "<table cellpadding='1' cellspacing='0' border='0'>\n";
3084 foreach($files as $file) {
3085 $relativeFile = clean_path(str_replace(getcwd().'/test', '', $file));
3086 $relativeFile = ($relativeFile{0} == '/') ? substr($relativeFile, 1, strlen($relativeFile)) : $relativeFile;
3088 $relativePath = dirname($relativeFile);
3090 if($relativePath == $priorPath) { // same dir, new file
3091 $out .= "<tr><td>".basename($relativeFile)."</td></tr>";
3092 $priorPath = $relativePath;
3106 function testThis2($dir, $id=0, $hide=false) {
3108 $dh = opendir($dir);
3111 $doHide = ($hide) ? 'none' : '';
3112 $out = "<div id='{$id}' style='display:{$doHide};'>";
3113 $out .= "<table cellpadding='1' cellspacing='0' border='0' style='border:0px solid #ccc'>\n";
3115 while($file = readdir($dh)) {
3116 if($file == '.' || $file == '..' || $file == 'CVS' || $file == '.cvsignore')
3119 if(is_dir($path.'/'.$file)) {
3120 $file = $path.'/'.$file;
3121 $newI = create_guid();
3122 $out .= "<tr><td valign='top'><a href='javascript:toggleNwFiles(\"{$newI}\");'><img border='0' src='".SugarThemeRegistry::current()->getImageURL('Workflow.gif')."'></a></td>\n";
3123 $out .= "<td valign='top'><b><a href='javascript:toggleNwFiles(\"{$newI}\");'>".basename($file)."</a></b></td></tr>";
3124 $out .= "<tr><td></td><td valign='top'>".testThis2($file, $newI, true)."</td></tr>";
3126 $out .= "<tr><td valign='top'> </td>\n";
3127 $out .= "<td valign='top'>".basename($file)."</td></tr>";
3131 $out .= "</tr></table>";
3142 function testThis3(&$files, $id, $hide, $previousPath = '') {
3143 if(!is_array($files) || empty($files))
3148 // expecting full path here
3149 foreach($files as $k => $file) {
3150 $file = str_replace(getcwd(), '', $file);
3151 $path = dirname($file);
3152 $fileName = basename($file);
3154 if($fileName == 'CVS' || $fileName == '.cvsignore')
3157 if($path == $previousPath) { // same directory
3158 // new row for each file
3159 $out .= "<tr><td valign='top' align='left'> </td>";
3160 $out .= "<td valign='top' align='left'>{$fileName}</td></tr>";
3161 } else { // new directory
3163 $out .= "<tr><td valign='top'><a href='javascript:toggleNwFiles(\"{$newI}\");'><img border='0' src='".SugarThemeRegistry::current()->getImageURL('Workflow.gif')."></a></td>\n";
3164 $out .= "<td valign='top'><b><a href='javascript:toggleNwFiles(\"{$newI}\");'>".$fileName."</a></b></td></tr>";
3165 $recurse = testThis3($files, $newI, true, $previousPath);
3166 $out .= "<tr><td></td><td valign='top'>".$recurse."</td></tr>";
3169 $previousPath = $path;
3171 $display = ($hide) ? 'none' : '';
3173 <div id="{$id}" style="display:{$display}">
3174 <table cellpadding='1' cellspacing='0' border='0' style='border:1px solid #ccc'>
3183 function testThis4($filePath, $fileNodes=array(), $fileName='') {
3184 $path = dirname($filePath);
3185 $file = basename($filePath);
3187 $exFile = explode('/', $path);
3189 foreach($exFile as $pathSegment) {
3190 if(is_array($fileNodes[$pathSegment])) { // path already processed
3192 } else { // newly found path
3193 $fileNodes[$pathSegment] = array();
3196 if($fileName != '') {
3197 $fileNodes[$pathSegment][] = $fileName;
3206 ///////////////////////////////////////////////////////////////////////////////
3207 //// SYSTEM CHECK FUNCTIONS
3209 * generates an array with all files in the SugarCRM root directory, skipping
3211 * @return array files Array of files with absolute paths
3213 function getFilesForPermsCheck() {
3214 global $sugar_config;
3216 logThis('Got JSON call to find all files...');
3217 $filesNotWritable = array();
3218 $filesNWPerms = array();
3220 // add directories here that should be skipped when doing file permissions checks (cache/upload is the nasty one)
3222 $sugar_config['upload_dir'],
3224 $files = uwFindAllFiles(getcwd(), array(), true, $skipDirs, true);
3229 * checks files for permissions
3230 * @param array files Array of files with absolute paths
3231 * @return string result of check
3233 function checkFiles($files, $echo=false) {
3234 global $mod_strings;
3235 $filesNotWritable = array();
3238 <a href='javascript:void(0); toggleNwFiles(\"filesNw\");'>{$mod_strings['LBL_UW_SHOW_NW_FILES']}</a>
3239 <div id='filesNw' style='display:none;'>
3240 <table cellpadding='3' cellspacing='0' border='0'>
3242 <th align='left'>{$mod_strings['LBL_UW_FILE']}</th>
3243 <th align='left'>{$mod_strings['LBL_UW_FILE_PERMS']}</th>
3244 <th align='left'>{$mod_strings['LBL_UW_FILE_OWNER']}</th>
3245 <th align='left'>{$mod_strings['LBL_UW_FILE_GROUP']}</th>
3248 $isWindows = is_windows();
3249 foreach($files as $file) {
3252 if(!is_writable_windows($file)) {
3253 logThis('WINDOWS: File ['.$file.'] not readable - saving for display');
3254 // don't warn yet - we're going to use this to check against replacement files
3255 // aw: commented out; it's a hack to allow upgrade wizard to continue on windows... will fix later
3256 /*$filesNotWritable[$i] = $file;
3257 $filesNWPerms[$i] = substr(sprintf('%o',fileperms($file)), -4);
3258 $filesOut .= "<tr>".
3259 "<td><span class='error'>{$file}</span></td>".
3260 "<td>{$filesNWPerms[$i]}</td>".
3261 "<td>".$mod_strings['ERR_UW_CANNOT_DETERMINE_USER']."</td>".
3262 "<td>".$mod_strings['ERR_UW_CANNOT_DETERMINE_GROUP']."</td>".
3266 if(!is_writable($file)) {
3267 logThis('File ['.$file.'] not writable - saving for display');
3268 // don't warn yet - we're going to use this to check against replacement files
3269 $filesNotWritable[$i] = $file;
3270 $filesNWPerms[$i] = substr(sprintf('%o',fileperms($file)), -4);
3271 $owner = posix_getpwuid(fileowner($file));
3272 $group = posix_getgrgid(filegroup($file));
3273 $filesOut .= "<tr>".
3274 "<td><span class='error'>{$file}</span></td>".
3275 "<td>{$filesNWPerms[$i]}</td>".
3276 "<td>".$owner['name']."</td>".
3277 "<td>".$group['name']."</td>".
3284 $filesOut .= '</table></div>';
3286 $errors['files']['filesNotWritable'] = (count($filesNotWritable) > 0) ? true : false;
3287 if(count($filesNotWritable) < 1) {
3288 $filesOut = "{$mod_strings['LBL_UW_FILE_NO_ERRORS']}";
3294 function deletePackageOnCancel(){
3295 global $mod_strings;
3296 global $sugar_config;
3297 logThis('running delete');
3298 if(!isset($_SESSION['install_file']) || ($_SESSION['install_file'] == "")) {
3299 logThis('ERROR: trying to delete non-existent file: ['.$_REQUEST['install_file'].']');
3300 $error = $mod_strings['ERR_UW_NO_FILE_UPLOADED'];
3302 // delete file in upgrades/patch
3303 $delete_me = urldecode( $_SESSION['install_file'] );
3304 if(@unlink($delete_me)) {
3305 //logThis('unlinking: '.$delete_me);
3306 $out = basename($delete_me).$mod_strings['LBL_UW_FILE_DELETED'];
3308 logThis('ERROR: could not delete ['.$delete_me.']');
3309 $error = $mod_strings['ERR_UW_FILE_NOT_DELETED'].$delete_me;
3312 // delete file in cache/upload
3313 $fileS = explode('/', $delete_me);
3315 $fileName = (isset($fileS[$c-1]) && !empty($fileS[$c-1])) ? $fileS[$c-1] : $fileS[$c-2];
3316 $deleteUpload = getcwd().'/'.$sugar_config['upload_dir'].$fileName;
3317 logThis('Trying to delete '.$deleteUpload);
3318 if(!@unlink($deleteUpload)) {
3319 logThis('ERROR: could not delete: ['.$deleteUpload.']');
3320 $error = $mod_strings['ERR_UW_FILE_NOT_DELETED'].$sugar_config['upload_dir'].$fileName;
3322 if(!empty($error)) {
3323 $out = "<b><span class='error'>{$error}</span></b><br />";
3328 function parseAndExecuteSqlFile($sqlScript,$forStepQuery='',$resumeFromQuery=''){
3329 global $sugar_config;
3330 $alterTableSchema = '';
3331 $sqlErrors = array();
3332 if(!isset($_SESSION['sqlSkippedQueries'])){
3333 $_SESSION['sqlSkippedQueries'] = array();
3335 $db = & DBManagerFactory::getInstance();
3337 if($sugar_config['dbconfig']['db_type'] == 'mysql') {
3340 if($sugar_config['dbconfig']['db_type'] == 'oci8'){
3341 $db->query("CREATE OR REPLACE FUNCTION blob_to_clob (blob_in IN BLOB)
3345 v_varchar VARCHAR2(32767);
3346 v_start PLS_INTEGER := 1;
3347 v_buffer PLS_INTEGER := 32767;
3349 DBMS_LOB.CREATETEMPORARY(v_clob, TRUE);
3351 FOR i IN 1..CEIL(DBMS_LOB.GETLENGTH(blob_in) / v_buffer)
3354 v_varchar := UTL_RAW.CAST_TO_VARCHAR2(DBMS_LOB.SUBSTR(blob_in, v_buffer, v_start));
3356 DBMS_LOB.WRITEAPPEND(v_clob, LENGTH(v_varchar), v_varchar);
3358 v_start := v_start + v_buffer;
3363 END blob_to_clob;");
3365 if(strpos($resumeFromQuery,",") != false){
3366 $resumeFromQuery = explode(",",$resumeFromQuery);
3367 if(is_array($resumeFromQuery)){
3368 //print_r('RES ARRAY '.$resumeFromQuery[0].'</br>');
3371 if(file_exists($sqlScript)) {
3372 $fp = fopen($sqlScript, 'r');
3373 $contents = stream_get_contents($fp);
3374 $anyScriptChanges =$contents;
3375 $resumeAfterFound = false;
3379 while($line = fgets($fp)) {
3380 if(strpos($line, '--') === false) {
3381 $completeLine .= " ".trim($line);
3382 if(strpos($line, ';') !== false) {
3384 $query = str_replace(';','',$completeLine);
3385 //if resume from query is not null then find out from where
3386 //it should start executing the query.
3388 if($query != null && $resumeFromQuery != null){
3389 if(!$resumeAfterFound){
3390 if(strpos($query,",") != false){
3391 $queArray = array();
3392 $queArray = explode(",",$query);
3393 for($i=0;$i<sizeof($resumeFromQuery);$i++){
3394 if(strcmp(strtolower(trim($resumeFromQuery[$i])),strtolower(trim($queArray[$i])))==0){
3395 //echo 'mat found '.$queArray[$i].'</br>';
3396 $resumeAfterFound = true;
3399 $resumeAfterFound = false;
3405 elseif(strcmp(strtolower(trim($resumeFromQuery)),strtolower(trim($query)))==0){
3406 $resumeAfterFound = true;
3409 if($resumeAfterFound){
3412 // if $count=1 means it is just found so skip the query. Run the next one
3413 if($query != null && $resumeAfterFound && $count >1){
3417 $tableName = getAlterTable($query);
3418 if(!empty($tableName))
3420 $db->query('ALTER TABLE '.$tableName.' DISABLE KEYS');
3424 if($db->checkError()){
3425 //put in the array to use later on
3426 $_SESSION['sqlSkippedQueries'][] = $query;
3428 if(!empty($tableName))
3430 $db->query('ALTER TABLE '.$tableName.' ENABLE KEYS');
3432 $progQuery[$forStepQuery]=$query;
3433 post_install_progress($progQuery,$action='set');
3436 elseif($query != null){
3440 $tableName = getAlterTable($query);
3441 if(!empty($tableName))
3443 $db->query('ALTER TABLE '.$tableName.' DISABLE KEYS');
3447 if(!empty($tableName))
3449 $db->query('ALTER TABLE '.$tableName.' ENABLE KEYS');
3451 $progQuery[$forStepQuery]=$query;
3452 post_install_progress($progQuery,$action='set');
3453 if($db->checkError()){
3454 //put in the array to use later on
3455 $_SESSION['sqlSkippedQueries'][] = $query;
3466 function getAlterTable($query){
3467 $query = strtolower($query);
3468 if (preg_match("/^\s*alter\s+table\s+/", $query)) {
3469 $sqlArray = explode(" ", $query);
3470 $key = array_search('table', $sqlArray);
3471 return $sqlArray[($key+1)];
3477 function set_upgrade_vars(){
3478 logThis('setting session variables...');
3479 $upgrade_progress_dir = getcwd().'/'.$GLOBALS['sugar_config']['upload_dir'].'upgrades/temp';
3480 if(!is_dir($upgrade_progress_dir)){
3481 mkdir_recursive($upgrade_progress_dir);
3483 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3484 if(file_exists($upgrade_progress_file)){
3485 include($upgrade_progress_file);
3488 fopen($upgrade_progress_file, 'w+');
3490 if(!isset($upgrade_config) || $upgrade_config == null){
3491 $upgrade_config = array();
3492 $upgrade_config[1]['upgrade_vars']=array();
3494 if(isset($upgrade_config[1]) && isset($upgrade_config[1]['upgrade_vars']) && !is_array($upgrade_config[1]['upgrade_vars'])){
3495 $upgrade_config[1]['upgrade_vars'] = array();
3498 if(!isset($upgrade_vars) || $upgrade_vars == NULL){
3499 $upgrade_vars = array();
3501 if(isset($_SESSION['unzip_dir']) && !empty($_SESSION['unzip_dir']) && file_exists($_SESSION['unzip_dir'])){
3502 $upgrade_vars['unzip_dir']=$_SESSION['unzip_dir'];
3504 if(isset($_SESSION['install_file']) && !empty($_SESSION['install_file']) && file_exists($_SESSION['install_file'])){
3505 $upgrade_vars['install_file']=$_SESSION['install_file'];
3507 if(isset($_SESSION['Upgraded451Wizard']) && !empty($_SESSION['Upgraded451Wizard'])){
3508 $upgrade_vars['Upgraded451Wizard']=$_SESSION['Upgraded451Wizard'];
3510 if(isset($_SESSION['license_shown']) && !empty($_SESSION['license_shown'])){
3511 $upgrade_vars['license_shown']=$_SESSION['license_shown'];
3513 if(isset($_SESSION['Initial_451to500_Step']) && !empty($_SESSION['Initial_451to500_Step'])){
3514 $upgrade_vars['Initial_451to500_Step']=$_SESSION['Initial_451to500_Step'];
3516 if(isset($_SESSION['zip_from_dir']) && !empty($_SESSION['zip_from_dir'])){
3517 $upgrade_vars['zip_from_dir']=$_SESSION['zip_from_dir'];
3519 //place into the upgrade_config array and rewrite config array only if new values are being inserted
3520 if(isset($upgrade_vars) && $upgrade_vars != null && sizeof($upgrade_vars) > 0){
3521 foreach($upgrade_vars as $key=>$val){
3522 if($key != null && $val != null){
3523 $upgrade_config[1]['upgrade_vars'][$key]=$upgrade_vars[$key];
3526 ksort($upgrade_config);
3527 if(is_writable($upgrade_progress_file) && write_array_to_file( "upgrade_config", $upgrade_config,
3528 $upgrade_progress_file)) {
3529 //writing to the file
3534 function initialize_session_vars(){
3535 $upgrade_progress_dir = getcwd().'/'.$GLOBALS['sugar_config']['upload_dir'].'upgrades/temp';
3536 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3537 if(file_exists($upgrade_progress_file)){
3538 include($upgrade_progress_file);
3539 if(isset($upgrade_config) && $upgrade_config != null && is_array($upgrade_config) && sizeof($upgrade_config) >0){
3540 $currVarsArray=$upgrade_config[1]['upgrade_vars'];
3541 //print_r($currVarsArray);
3542 if(isset($currVarsArray) && $currVarsArray != null && is_array($currVarsArray) && sizeof($currVarsArray)>0){
3543 foreach($currVarsArray as $key=>$val){
3544 if($key != null && $val !=null){
3545 //set session variables
3546 $_SESSION[$key]=$val;
3555 //track the upgrade progress on each step
3556 //track the upgrade progress on each step
3557 function set_upgrade_progress($currStep,$currState,$currStepSub='',$currStepSubState=''){
3559 $upgrade_progress_dir = getcwd().'/'.$GLOBALS['sugar_config']['upload_dir'].'upgrades/temp';
3560 if(!is_dir($upgrade_progress_dir)){
3561 mkdir_recursive($upgrade_progress_dir);
3563 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3564 if(file_exists($upgrade_progress_file)){
3565 include($upgrade_progress_file);
3568 if(function_exists('sugar_fopen')){
3569 sugar_fopen($upgrade_progress_file, 'w+');
3572 fopen($upgrade_progress_file, 'w+');
3575 if(!isset($upgrade_config) || $upgrade_config == null){
3576 $upgrade_config = array();
3577 $upgrade_config[1]['upgrade_vars']=array();
3579 if(!is_array($upgrade_config[1]['upgrade_vars'])){
3580 $upgrade_config[1]['upgrade_vars'] = array();
3582 if($currStep != null && $currState != null){
3583 if(sizeof($upgrade_config) > 0){
3584 if($currStepSub != null && $currStepSubState !=null){
3585 //check if new status to be set or update
3586 //get the latest in array. since it has sub components prepare an array
3587 if(!empty($upgrade_config[sizeof($upgrade_config)][$currStep]) && is_array($upgrade_config[sizeof($upgrade_config)][$currStep])){
3588 $latestStepSub = currSubStep($upgrade_config[sizeof($upgrade_config)][$currStep]);
3589 if($latestStepSub == $currStepSub){
3590 $upgrade_config[sizeof($upgrade_config)][$currStep][$latestStepSub]=$currStepSubState;
3591 $upgrade_config[sizeof($upgrade_config)][$currStep][$currStep] = $currState;
3594 $upgrade_config[sizeof($upgrade_config)][$currStep][$currStepSub]=$currStepSubState;
3595 $upgrade_config[sizeof($upgrade_config)][$currStep][$currStep] = $currState;
3599 $currArray = array();
3600 $currArray[$currStep] = $currState;
3601 $currArray[$currStepSub] = $currStepSubState;
3602 $upgrade_config[sizeof($upgrade_config)+1][$currStep] = $currArray;
3606 //get the current upgrade progress
3607 $latestStep = get_upgrade_progress();
3608 //set the upgrade progress
3609 //echo 'latest '.$latestStep;
3610 if($latestStep == $currStep){
3611 //update the current step with new progress status
3613 $upgrade_config[sizeof($upgrade_config)][$latestStep]=$currState;
3618 $upgrade_config[sizeof($upgrade_config)+1][$currStep]=$currState;
3620 // now check if there elements within array substeps
3624 //set the upgrade progress (just starting)
3625 $upgrade_config[sizeof($upgrade_config)+1][$currStep]= $currState;
3628 if(is_writable($upgrade_progress_file) && write_array_to_file( "upgrade_config", $upgrade_config,
3629 $upgrade_progress_file)) {
3630 //writing to the file
3636 function get_upgrade_progress(){
3637 $upgrade_progress_dir = getcwd().'/'.$GLOBALS['sugar_config']['upload_dir'].'upgrades/temp';
3638 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3640 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3642 if(file_exists($upgrade_progress_file)){
3643 include($upgrade_progress_file);
3644 //echo 'upconf '.$upgrade_config;
3645 if(!isset($upgrade_config) || $upgrade_config == null){
3646 $upgrade_config = array();
3648 if($upgrade_config != null && sizeof($upgrade_config) >1){
3649 $currArr = $upgrade_config[sizeof($upgrade_config)];
3650 //echo 'size of '.sizeof($upgrade_config);
3651 if(is_array($currArr)){
3652 foreach($currArr as $key=>$val){
3660 function currSubStep($currStep){
3662 if(is_array($currStep)){
3663 foreach($currStep as $key=>$val){
3671 function currUpgradeState($currState){
3673 if(is_array($currState)){
3674 foreach($currState as $key=>$val){
3676 foreach($val as $k=>$v){
3690 function didThisStepRunBefore($step,$SubStep=''){
3691 if($step == null) return;
3692 $upgrade_progress_dir = getcwd().'/'.$GLOBALS['sugar_config']['upload_dir'].'upgrades/temp';
3693 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3695 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3697 if(file_exists($upgrade_progress_file)){
3698 include($upgrade_progress_file);
3699 if(isset($upgrade_config) && $upgrade_config != null && is_array($upgrade_config) && sizeof($upgrade_config) >0){
3700 for($i=1;$i<=sizeof($upgrade_config);$i++){
3701 if(is_array($upgrade_config[$i])){
3702 foreach($upgrade_config[$i] as $key=>$val){
3704 if(is_array($upgrade_config[$i][$step])){
3706 foreach ($upgrade_config[$i][$step] as $k=>$v){
3708 foreach($v as $k1=>$v1){
3709 if($SubStep != null){
3710 if($SubStep ==$k1 && $v1=='done'){
3711 //echo 'Found Inside '.$k1;
3718 elseif($SubStep !=null){
3719 if($SubStep==$k && $v=='done'){
3720 //echo 'Found1 '.$k;
3725 elseif($step==$k && $v=='done'){
3726 //echo 'Found2 '.$k;
3732 elseif($val=='done'){
3733 //echo 'Foundmmmm '.$key;
3747 //get and set post install status
3748 function post_install_progress($progArray='',$action=''){
3749 if($action=='' || $action=='get'){
3750 //get the state of post install
3751 $upgrade_progress_dir = getcwd().'/'.$GLOBALS['sugar_config']['upload_dir'].'upgrades/temp';
3752 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3753 $currProg = array();
3754 if(file_exists($upgrade_progress_file)){
3755 include($upgrade_progress_file);
3756 if(is_array($upgrade_config[sizeof($upgrade_config)]['commit']['post_install']) && sizeof($upgrade_config[sizeof($upgrade_config)]['commit']['post_install'])>0){
3757 foreach($upgrade_config[sizeof($upgrade_config)]['commit']['post_install'] as $k=>$v){
3764 elseif($action=='set'){
3765 $upgrade_progress_dir = getcwd().'/'.$GLOBALS['sugar_config']['upload_dir'].'upgrades/temp';
3766 if(!is_dir($upgrade_progress_dir)){
3767 mkdir($upgrade_progress_dir);
3769 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3770 if(file_exists($upgrade_progress_file)){
3771 include($upgrade_progress_file);
3774 fopen($upgrade_progress_file, 'w+');
3776 if(!is_array($upgrade_config[sizeof($upgrade_config)]['commit']['post_install'])){
3777 $upgrade_config[sizeof($upgrade_config)]['commit']['post_install']=array();
3778 $upgrade_config[sizeof($upgrade_config)]['commit']['post_install']['post_install'] = 'in_progress';
3780 if($progArray != null && is_array($progArray)){
3781 foreach($progArray as $key=>$val){
3782 $upgrade_config[sizeof($upgrade_config)]['commit']['post_install'][$key]=$val;
3785 if(is_writable($upgrade_progress_file) && write_array_to_file( "upgrade_config", $upgrade_config,
3786 $upgrade_progress_file)) {
3787 //writing to the file
3793 // parse and run sql file
3794 function parseAndExecuteSqlFileExtended($sqlScript){
3795 global $sugar_config;
3796 $alterTableSchema = '';
3797 $db = & DBManagerFactory::getInstance();
3798 if(is_file($sqlScript)) {
3799 $fp = fopen($sqlScript, 'r');
3800 $contents = stream_get_contents($fp);
3801 $anyScriptChanges =$contents;
3805 while($line = fgets($fp)) {
3806 if(strpos($line, '--') === false) {
3807 $completeLine .= " ".trim($line);
3808 if(strpos($line, ';') !== false) {
3809 $completeLine = str_replace(';','',$completeLine);
3810 $currLine = explode(",",$completeLine);
3811 //check if multiple statements are clubbed
3812 if(sizeof($currLine) >1){
3813 $qarr = explode(" ",trim($currLine[0]));
3814 if(strtoupper(trim($qarr[0])) == 'CREATE' && strtoupper(trim($qarr[1])) == 'TABLE'){
3815 if(strtoupper(trim($qarr[2]) != null)){
3816 if($sugar_config['dbconfig']['db_type'] == 'oci8'){
3817 $query= "select table_name from user_tables where table_name=strtoupper(trim($qarr[2]))";
3818 $result = $db->query($query);
3819 $row = $db->fetchByAssociation($result);
3820 if($row['table_name'] != null){
3825 $query= $completeLine;
3834 $qType =trim($qarr[0])." ".trim($qarr[1])." ".trim($qarr[2]);
3835 echo trim($currLine[0])."<br />";
3836 for ($i = 1; $i <= sizeof($currLine)-1; $i++) {
3837 $query = $qType." ".trim($currLine[$i]);
3838 echo $query."<br />";
3844 echo trim($currLine[0]);
3848 //$q3 = $completeLine;
3849 //''$r3 = $GLOBALS['db']->query($q3, false, "Preflight Failed for:");
3850 //echo mysql_error();
3858 //$sqlErrors[] = $mod_strings['ERR_UW_FILE_NOT_READABLE'].'::'.$sqlScript;
3863 function repairDBForUpgrade($execute=false,$path=''){
3865 global $current_user, $beanFiles;
3867 set_time_limit(3600);
3869 $db = &DBManagerFactory::getInstance();
3871 VardefManager::clearVardef();
3872 require_once('include/ListView/ListView.php');
3873 foreach ($beanFiles as $bean => $file) {
3874 require_once ($file);
3875 $focus = new $bean ();
3876 $sql .= $db->repairTable($focus, $execute);
3880 $olddictionary = $dictionary;
3881 unset ($dictionary);
3882 include ('modules/TableDictionary.php');
3883 foreach ($dictionary as $meta) {
3884 $tablename = $meta['table'];
3885 $fielddefs = $meta['fields'];
3886 $indices = $meta['indices'];
3887 $sql .= $db->repairTableParams($tablename, $fielddefs, $indices, $execute);
3890 foreach (explode("\n", $sql) as $line) {
3891 if (!empty ($line) && substr($line, -2) != "*/") {
3894 $qry_str .= $line . "\n";
3905 preg_replace('#(/\*.+?\*/\n*)#', '', $qry_str)
3907 logThis("*******START EXECUTING DB UPGRADE QUERIES***************",$path);
3908 logThis($sql,$path);
3909 logThis("*******END EXECUTING DB UPGRADE QUERIES****************",$path);
3918 * upgradeUserPreferences
3919 * This method updates the user_preferences table and sets the pages/dashlets for users
3920 * which have ACL access to Trackers so that the Tracker dashlets are set in their user perferences
3923 function upgradeUserPreferences() {
3928 function add_custom_modules_favorites_search(){
3929 $module_directories = scandir('modules');
3931 foreach($module_directories as $module_dir){
3932 if($module_dir == '.' || $module_dir == '..' || !is_dir("modules/{$module_dir}")){
3937 preg_match('/^[a-z0-9]{1,5}_[a-z0-9_]+$/i' , $module_dir, $matches);
3939 // Make sure the module was created by module builder
3940 if(empty($matches)){
3944 $full_module_dir = "modules/{$module_dir}/";
3945 $read_searchdefs_from = "{$full_module_dir}/metadata/searchdefs.php";
3946 $read_SearchFields_from = "{$full_module_dir}/metadata/SearchFields.php";
3947 $read_custom_SearchFields_from = "custom/{$full_module_dir}/metadata/SearchFields.php";
3949 // Studio can possibly override this file, so we check for a custom version of it
3950 if(file_exists("custom/{$full_module_dir}/metadata/searchdefs.php")){
3951 $read_searchdefs_from = "custom/{$full_module_dir}/metadata/searchdefs.php";
3954 if(file_exists($read_searchdefs_from) && file_exists($read_SearchFields_from)){
3957 require($read_searchdefs_from);
3958 foreach($searchdefs[$module_dir]['layout']['basic_search'] as $sf_array){
3959 if(isset($sf_array['name']) && $sf_array['name'] == 'favorites_only'){
3964 require($read_SearchFields_from);
3965 if(isset($searchFields[$module_dir]['favorites_only'])){
3969 if(!$found_sf1 && !$found_sf2){
3970 $searchdefs[$module_dir]['layout']['basic_search']['favorites_only'] = array('name' => 'favorites_only','label' => 'LBL_FAVORITES_FILTER','type' => 'bool',);
3971 $searchdefs[$module_dir]['layout']['advanced_search']['favorites_only'] = array('name' => 'favorites_only','label' => 'LBL_FAVORITES_FILTER','type' => 'bool',);
3972 $searchFields[$module_dir]['favorites_only'] = array(
3973 'query_type'=>'format',
3974 'operator' => 'subquery',
3975 'subquery' => 'SELECT sugarfavorites.record_id FROM sugarfavorites
3976 WHERE sugarfavorites.deleted=0
3977 and sugarfavorites.module = \''.$module_dir.'\'
3978 and sugarfavorites.assigned_user_id = \'{0}\'',
3979 'db_field'=>array('id')
3982 if(!is_dir("custom/{$full_module_dir}/metadata")){
3983 mkdir_recursive("custom/{$full_module_dir}/metadata");
3985 $success_sf1 = write_array_to_file('searchdefs', $searchdefs, "custom/{$full_module_dir}/metadata/searchdefs.php");
3986 $success_sf2 = write_array_to_file('searchFields', $searchFields, "{$full_module_dir}/metadata/SearchFields.php");
3989 logThis("add_custom_modules_favorites_search failed for searchdefs.php for {$module_dir}");
3992 logThis("add_custom_modules_favorites_search failed for SearchFields.php for {$module_dir}");
3994 if($success_sf1 && $success_sf2){
3995 logThis("add_custom_modules_favorites_search successfully updated searchdefs and searchFields for {$module_dir}");
4004 * upgradeModulesForTeamsets
4006 * This method adds the team_set_id values to the module tables that have the new team_set_id column
4007 * added through the SugarCRM 5.5.x upgrade process. It also adds the values into the team_sets and
4008 * team_sets_teams tables.
4010 * @param filter Array of modules to process; empty by default
4012 function upgradeModulesForTeamsets($filter=array()) {
4013 require('include/modules.php');
4014 foreach($beanList as $moduleName=>$beanName) {
4015 if(!empty($filter) && array_search($moduleName, $filter) === false) {
4018 if($moduleName == 'TeamMemberships' || $moduleName == 'ForecastOpportunities'){
4021 $bean = loadBean($moduleName);
4023 empty($bean->table_name)) {
4027 $FieldArray = $GLOBALS['db']->helper->get_columns($bean->table_name);
4028 if(!isset($FieldArray['team_id'])) {
4032 upgradeTeamColumn($bean, 'team_id');
4036 //Upgrade users table
4037 $bean = loadBean('Users');
4038 upgradeTeamColumn($bean, 'default_team');
4039 $result = $GLOBALS['db']->query("SELECT id FROM teams where deleted=0");
4040 while($row = $GLOBALS['db']->fetchByAssoc($result)) {
4041 $teamset = new TeamSet();
4042 $teamset->addTeams($row['id']);
4049 * Helper function to create a team_set_id column and also set team_set_id column
4050 * to have the value of the $column_name parameter
4052 * @param $bean SugarBean which we are adding team_set_id column to
4053 * @param $column_name The name of the column containing the default team_set_id value
4055 function upgradeTeamColumn($bean, $column_name) {
4056 //first let's check to ensure that the team_set_id field is defined, if not it could be the case that this is an older
4057 //module that does not use the SugarObjects
4058 if(empty($bean->field_defs['team_set_id']) && $bean->module_dir != 'Trackers'){
4060 //at this point we could assume that since we have a team_id defined and not a team_set_id that we need to
4061 //add that field and the corresponding relationships
4062 $object = $bean->object_name;
4063 $module = $bean->module_dir;
4064 $object_name = $object;
4065 $_object_name = strtolower($object_name);
4067 if(!empty($GLOBALS['dictionary'][$object]['table'])){
4068 $table_name = $GLOBALS['dictionary'][$object]['table'];
4070 $table_name = strtolower($module);
4073 $path = 'include/SugarObjects/implements/team_security/vardefs.php';
4075 //go through each entry in the vardefs from team_security and unset anything that is already set in the core module
4076 //this will ensure we have the proper ordering.
4077 $fieldDiff = array_diff_assoc($vardefs['fields'], $GLOBALS['dictionary'][$bean->object_name]['fields']);
4079 $file = 'custom/Extension/modules/' . $bean->module_dir. '/Ext/Vardefs/teams.php';
4080 $contents = "<?php\n";
4081 if(!empty($fieldDiff)){
4082 foreach($fieldDiff as $key => $val){
4083 $contents .= "\n\$GLOBALS['dictionary']['". $object . "']['fields']['". $key . "']=" . var_export_helper($val) . ";";
4086 $relationshipDiff = array_diff_assoc($vardefs['relationships'], $GLOBALS['dictionary'][$bean->object_name]['relationships']);
4087 if(!empty($relationshipDiff)){
4088 foreach($relationshipDiff as $key => $val){
4089 $contents .= "\n\$GLOBALS['dictionary']['". $object . "']['relationships']['". $key . "']=" . var_export_helper($val) . ";";
4092 $indexDiff = array_diff_assoc($vardefs['indices'], $GLOBALS['dictionary'][$bean->object_name]['indices']);
4093 if(!empty($indexDiff)){
4094 foreach($indexDiff as $key => $val){
4095 $contents .= "\n\$GLOBALS['dictionary']['". $object . "']['indices']['". $key . "']=" . var_export_helper($val) . ";";
4098 if( $fh = @sugar_fopen( $file, 'wt' ) )
4100 fputs( $fh, $contents);
4105 //we have written out the teams.php into custom/Extension/modules/{$module_dir}/Ext/Vardefs/teams.php'
4106 //now let's merge back into vardefs.ext.php
4107 require_once('ModuleInstall/ModuleInstaller.php');
4108 $mi = new ModuleInstaller();
4109 $mi->merge_files('Ext/Vardefs/', 'vardefs.ext.php');
4110 VardefManager::loadVardef($bean->module_dir, $bean->object_name, true);
4111 $bean->field_defs = $GLOBALS['dictionary'][$bean->object_name]['fields'];
4114 if(isset($bean->field_defs['team_set_id'])) {
4115 //Create the team_set_id column
4116 $FieldArray = $GLOBALS['db']->helper->get_columns($bean->table_name);
4117 if(!isset($FieldArray['team_set_id'])) {
4118 $GLOBALS['db']->addColumn($bean->table_name, $bean->field_defs['team_set_id']);
4120 $indexArray = $GLOBALS['db']->helper->get_indices($bean->table_name);
4122 $indexName = getValidDBName('idx_'.strtolower($bean->table_name).'_tmst_id', true, 34);
4125 'name' => $indexName,
4127 'fields' => array('team_set_id')
4130 if(!isset($indexArray[$indexName])) {
4131 $GLOBALS['db']->addIndexes($bean->table_name, $indexDef);
4134 //Update the table's team_set_id column to have the same values as team_id
4135 $GLOBALS['db']->query("UPDATE {$bean->table_name} SET team_set_id = {$column_name}");
4140 * Update the folder subscription table which confirms to the team security mechanism but
4141 * the class SugarFolders does not extend SugarBean and is therefore never picked up by the
4142 * upgradeModulesForTeamsets function.
4144 function upgradeFolderSubscriptionsTeamSetId()
4146 logThis("In upgradeFolderSubscriptionsTeamSetId()");
4147 $query = "UPDATE folders SET team_set_id = team_id";
4148 $result = $GLOBALS['db']->query($query);
4149 logThis("Finished upgradeFolderSubscriptionsTeamSetId()");
4153 * upgradeModulesForTeam
4155 * This method update the associated_user_id, name, name_2 to the private team records on teams table
4156 * This function is used for upgrade process from 5.1.x and 5.2.x.
4159 function upgradeModulesForTeam() {
4160 logThis("In upgradeModulesForTeam()");
4161 $result = $GLOBALS['db']->query("SELECT id, user_name, first_name, last_name FROM users where deleted=0");
4163 while($row = $GLOBALS['db']->fetchByAssoc($result)) {
4164 $results2 = $GLOBALS['db']->query("SELECT id FROM teams WHERE name = '({$row['user_name']})'");
4166 if(!$assoc = $GLOBALS['db']->fetchByAssoc($results2)) {
4167 //if team does not exist, then lets create the team for this user
4170 $user->retrieve($row['id']);
4171 $team->new_user_created($user);
4172 $team_id = $team->id;
4174 $team_id =$assoc['id'];
4178 $name = is_null($row['first_name'])?'':$row['first_name'];
4179 $name_2 = is_null($row['last_name'])?'':$row['last_name'];
4180 $associated_user_id = $row['id'];
4183 //Ensure team->name is not empty by using team->name_2 if available
4184 if(empty($name) && !empty($name_2)) {
4189 $query = "UPDATE teams SET name = '{$name}', name_2 = '{$name_2}', associated_user_id = '{$associated_user_id}' WHERE id = '{$team_id}'";
4190 $GLOBALS['db']->query($query);
4193 //Update the team_set_id and default_team columns
4194 $ce_to_pro_or_ent = (isset($_SESSION['upgrade_from_flavor']) && ($_SESSION['upgrade_from_flavor'] == 'SugarCE to SugarPro' || $_SESSION['upgrade_from_flavor'] == 'SugarCE to SugarEnt' || $_SESSION['upgrade_from_flavor'] == 'SugarCE to SugarCorp' || $_SESSION['upgrade_from_flavor'] == 'SugarCE to SugarUlt'));
4196 //Update team_set_id
4197 if($ce_to_pro_or_ent) {
4198 $GLOBALS['db']->query("update users set team_set_id = (select teams.id from teams where teams.associated_user_id = users.id)");
4199 $GLOBALS['db']->query("update users set default_team = (select teams.id from teams where teams.associated_user_id = users.id)");
4205 function addNewSystemTabsFromUpgrade($from_dir){
4207 if(isset($_SESSION['upgrade_from_flavor'])){
4209 //check to see if there are any new files that need to be added to systems tab
4210 //retrieve old modules list
4211 logThis('check to see if new modules exist',$path);
4212 $oldModuleList = array();
4213 $newModuleList = array();
4214 include($from_dir.'/include/modules.php');
4215 $oldModuleList = $moduleList;
4216 include('include/modules.php');
4217 $newModuleList = $moduleList;
4219 //include tab controller
4220 require_once('modules/MySettings/TabController.php');
4221 $newTB = new TabController();
4223 //make sure new modules list has a key we can reference directly
4224 $newModuleList = $newTB->get_key_array($newModuleList);
4225 $oldModuleList = $newTB->get_key_array($oldModuleList);
4227 //iterate through list and remove commonalities to get new modules
4228 foreach ($newModuleList as $remove_mod){
4229 if(in_array($remove_mod, $oldModuleList)){
4230 unset($newModuleList[$remove_mod]);
4233 //new modules list now has left over modules which are new to this install, so lets add them to the system tabs
4234 logThis('new modules to add are '.var_export($newModuleList,true),$path);
4236 if(!empty($newModuleList))
4238 //grab the existing system tabs
4239 $tabs = $newTB->get_system_tabs();
4241 //add the new tabs to the array
4242 foreach($newModuleList as $nm ){
4246 $newTB->set_system_tabs($tabs);
4248 logThis('module tabs updated',$path);
4254 * This method attempts to fix dropdown lists that were incorrectly named.
4255 * There were versions of SugarCRM that did not enforce naming convention rules
4256 * for the dropdown list field name. This method attempts to resolve that by
4257 * fixing the language files that may have been affected and then updating the
4258 * fields_meta_data table accordingly. It also refreshes any vardefs that may
4259 * have been affected.
4262 function fix_dropdown_list() {
4263 if(file_exists('custom/include/language')) {
4265 $affected_modules = array();
4266 $affected_keys = array();
4268 getFiles($files, 'custom/include/language', '/\.php$/i');
4269 foreach($files as $file) {
4271 if(file_exists($file . '.bak')) {
4272 $bak_mod_time = filemtime($file . '.bak');
4273 $php_mod_time = filemtime($file);
4274 //We're saying if the .php file was modified 30 seconds no more than php.bak file then we
4275 //run these additional cleanup checks
4276 if($php_mod_time - $bak_mod_time < 30) {
4278 $app_list_strings = array();
4279 $GLOBALS['app_list_strings'] = array();
4280 require($file . '.bak');
4281 $bak_app_list_strings = array_merge($app_list_strings, $GLOBALS['app_list_strings']);
4283 $app_list_strings = array();
4284 $GLOBALS['app_list_strings'] = array();
4286 $php_app_list_strings = array_merge($app_list_strings, $GLOBALS['app_list_strings']);
4288 //Get the file contents
4289 $contents = file_get_contents($file);
4291 //Now simulate a fix for the file before we compare w/ the .php file
4292 //we also append to the $contents
4293 foreach($bak_app_list_strings as $key=>$entry) {
4294 if(preg_match('/([^A-Za-z_])/', $key, $matches) && is_array($entry)) {
4295 $new_key = preg_replace('/[^A-Za-z_]/', '_', $key);
4296 $bak_app_list_strings[$new_key] = $bak_app_list_strings[$key];
4297 unset($bak_app_list_strings[$key]);
4298 //Now if the entry doesn't exists in the .php file, then add to contents
4299 if(!isset($php_app_list_strings[$new_key])) {
4300 $contents .= "\n\$GLOBALS['app_list_strings']['{$new_key}'] = " . var_export_helper($bak_app_list_strings[$new_key]) . ";";
4305 //Now load the .php file to do the comparison
4306 foreach($php_app_list_strings as $key=>$entry) {
4307 if(isset($bak_app_list_strings[$key])) {
4308 $diff = array_diff($bak_app_list_strings[$key], $entry);
4310 //There is a difference, so copy the $bak_app_list_strings version into the .php file
4311 $contents .= "\n\$GLOBALS['app_list_strings']['{$key}'] = " . var_export_helper($bak_app_list_strings[$key]) . ";";
4316 //Now write out the file contents
4317 //Create backup just in case
4318 copy($file, $file . '.php_bak');
4319 $fp = @sugar_fopen($file, 'w');
4321 fwrite($fp, $contents);
4324 $GLOBALS['log']->error("Unable to update file contents in fix_dropdown_list for {$file}");
4329 unset($GLOBALS['app_strings']);
4330 unset($GLOBALS['app_list_strings']);
4331 $app_list_strings = array();
4334 $contents = file_get_contents($file);
4335 if ( !isset($GLOBALS['app_list_strings']) ) {
4336 $GLOBALS['app_list_strings'] = $app_list_strings;
4339 $GLOBALS['app_list_strings'] = array_merge($app_list_strings, $GLOBALS['app_list_strings']);
4342 if(isset($GLOBALS['app_list_strings']) && is_array($GLOBALS['app_list_strings'])) {
4343 foreach($GLOBALS['app_list_strings'] as $key=>$entry) {
4344 if(preg_match('/([^A-Za-z_])/', $key, $matches) && is_array($entry)) {
4345 $result = $GLOBALS['db']->query("SELECT custom_module FROM fields_meta_data WHERE ext1 = '{$key}'");
4346 if(!empty($result)) {
4347 while($row = $GLOBALS['db']->fetchByAssoc($result)) {
4348 $custom_module = $row['custom_module'];
4349 if(!empty($GLOBALS['beanList'][$custom_module])) {
4350 $affected_modules[$custom_module] = $GLOBALS['beanList'][$custom_module];
4355 //Replace all invalid characters with '_' character
4356 $new_key = preg_replace('/[^A-Za-z_]/', '_', $key);
4357 $affected_keys[$key] = $new_key;
4359 $GLOBALS['app_list_strings'][$new_key] = $GLOBALS['app_list_strings'][$key];
4360 unset($GLOBALS['app_list_strings'][$key]);
4362 $pattern_match = "/(\[\s*\'{$key}\'\s*\])/";
4363 $new_key = "['{$new_key}']";
4364 $out = preg_replace($pattern_match, $new_key, $contents);
4370 //This is a check for g => h instances where the file contents were incorrectly written
4371 //and also fixes the scenario where via a UI upgrade, the app_list_strings were incorrectly
4372 //merged with app_list_strings variables declared elsewhere
4374 if(preg_match('/\$GLOBALS\s*\[\s*[\"|\']app_list_strings[\"|\']\s*\]\s*=\s*array\s*\(/', $contents)) {
4375 //Now also remove all the non-custom labels that were added
4376 if(preg_match('/language\/([^\.]+)\.lang\.php$/', $file, $matches)) {
4377 $language = $matches[1];
4379 $app_list_strings = array();
4381 if(file_exists("include/language/$language.lang.php")) {
4382 include("include/language/$language.lang.php");
4384 if(file_exists("include/language/$language.lang.override.php")) {
4385 $app_list_strings = _mergeCustomAppListStrings("include/language/$language.lang.override.php" , $app_list_strings) ;
4387 if(file_exists("custom/application/Ext/Language/$language.ext.lang.php")) {
4388 $app_list_strings = _mergeCustomAppListStrings("custom/application/Ext/Language/$language.ext.lang.php" , $app_list_strings) ;
4390 if(file_exists("custom/application/Ext/Language/$language.lang.ext.php")) {
4391 $app_list_strings = _mergeCustomAppListStrings("custom/application/Ext/Language/$language.lang.ext.php" , $app_list_strings) ;
4394 $all_non_custom_include_language_strings = $app_strings;
4395 $all_non_custom_include_language_list_strings = $app_list_strings;
4397 $unset_keys = array();
4398 if(!empty($GLOBALS['app_list_strings'])) {
4399 foreach($GLOBALS['app_list_strings'] as $key=>$value) {
4401 if(isset($all_non_custom_include_language_list_strings[$key])) {
4402 $diff = array_diff($all_non_custom_include_language_list_strings[$key], $GLOBALS['app_list_strings'][$key]);
4405 if(!empty($all_non_custom_include_language_list_strings[$key]) && empty($diff)) {
4406 $unset_keys[] = $key;
4411 foreach($unset_keys as $key) {
4412 unset($GLOBALS['app_list_strings'][$key]);
4415 if(!empty($GLOBALS['app_strings'])) {
4416 foreach($GLOBALS['app_strings'] as $key=>$value) {
4417 if(!empty($all_non_custom_include_language_strings[$key])) {
4418 unset($GLOBALS['app_strings'][$key]);
4422 } //if(preg_match...)
4425 if(!empty($GLOBALS['app_strings'])) {
4426 foreach($GLOBALS['app_strings'] as $key=>$entry) {
4427 $out .= "\n\$GLOBALS['app_strings']['$key']=" . var_export_helper($entry) . ";";
4431 foreach($GLOBALS['app_list_strings'] as $key=>$entry) {
4432 $out .= "\n\$GLOBALS['app_list_strings']['$key']=" . var_export_helper($entry) . ";";
4436 } //if(preg_match...)
4440 //Create a backup just in case
4441 copy($file, $file . '.bak');
4442 $fp = @sugar_fopen($file, 'w');
4447 //If we can't update the file, just return
4448 $GLOBALS['log']->error("Unable to update file contents in fix_dropdown_list.");
4456 //Update db entries (the order matters here... need to process database changes first)
4457 if(!empty($affected_keys)) {
4458 foreach($affected_keys as $old_key=>$new_key) {
4459 $GLOBALS['db']->query("UPDATE fields_meta_data SET ext1 = '{$new_key}' WHERE ext1 = '{$old_key}'");
4463 //Update vardef files for affected modules
4464 if(!empty($affected_modules)) {
4465 foreach($affected_modules as $module=>$object) {
4466 VardefManager::refreshVardefs($module, $object);
4473 function update_iframe_dashlets(){
4474 require_once('cache/dashlets/dashlets.php');
4476 $db = DBManagerFactory::getInstance();
4477 $query = "SELECT id, contents, assigned_user_id FROM user_preferences WHERE deleted = 0 AND category = 'Home'";
4478 $result = $db->query($query, true, "Unable to update new default dashlets! ");
4479 while ($row = $db->fetchByAssoc($result)) {
4480 $content = unserialize(base64_decode($row['contents']));
4481 $assigned_user_id = $row['assigned_user_id'];
4482 $record_id = $row['id'];
4484 $current_user = new User();
4485 $current_user->retrieve($row['assigned_user_id']);
4487 if(!empty($content['dashlets']) && !empty($content['pages'])){
4488 $originalDashlets = $content['dashlets'];
4489 foreach($originalDashlets as $key => $ds){
4490 if(!empty($ds['options']['url']) && stristr($ds['options']['url'],'http://www.sugarcrm.com/crm/product/gopro')){
4491 unset($originalDashlets[$key]);
4494 $current_user->setPreference('dashlets', $originalDashlets, 0, 'Home');
4501 * convertImageToText
4502 * This method attempts to convert date type image to text on Microsoft SQL Server.
4503 * This method could NOT be used in any other type of datebases.
4505 function convertImageToText($table_name,$column_name){
4506 $set_lang = "SET LANGUAGE us_english";
4507 $GLOBALS['db']->query($set_lang);
4508 if($GLOBALS['db']->checkError()){
4509 logThis('An error occurred when performing this query-->'.$set_lang);
4511 $q="SELECT data_type
4512 FROM INFORMATION_SCHEMA.Tables T JOIN INFORMATION_SCHEMA.Columns C
4513 ON T.TABLE_NAME = C.TABLE_NAME where T.TABLE_NAME = '$table_name' and C.COLUMN_NAME = '$column_name'";
4514 $res= $GLOBALS['db']->query($q);
4515 if($GLOBALS['db']->checkError()){
4516 logThis('An error occurred when performing this query-->'.$q);
4518 $row= $GLOBALS['db']->fetchByAssoc($res);
4520 if(trim(strtolower($row['data_type'])) == 'image'){
4521 $addContent_temp = "alter table {$table_name} add {$column_name}_temp text null";
4522 $GLOBALS['db']->query($addContent_temp);
4523 if($GLOBALS['db']->checkError()){
4524 logThis('An error occurred when performing this query-->'.$addContent_temp);
4526 $qN = "select count=datalength({$column_name}), id, {$column_name} from {$table_name}";
4527 $result = $GLOBALS['db']->query($qN);
4528 while($row = $GLOBALS['db']->fetchByAssoc($result)){
4529 if($row['count'] >8000){
4530 $contentLength = $row['count'];
4533 $convertedContent = '';
4534 while($contentLength >0){
4535 $stepsQuery = "select cont=convert(varchar(max), convert(varbinary(8000), substring({$column_name},{$start},{$next}))) from {$table_name} where id= '{$row['id']}'";
4536 $steContQ = $GLOBALS['db']->query($stepsQuery);
4537 if($GLOBALS['db']->checkError()){
4538 logThis('An error occurred when performing this query-->'.$stepsQuery);
4540 $stepCont = $GLOBALS['db']->fetchByAssoc($steContQ);
4541 if(isset($stepCont['cont'])){
4542 $convertedContent = $convertedContent.$stepCont['cont'];
4544 $start = $start+$next;
4545 $contentLength = $contentLength - $next;
4547 $addContentDataText="update {$table_name} set {$column_name}_temp = '{$convertedContent}' where id= '{$row['id']}'";
4548 $GLOBALS['db']->query($addContentDataText);
4549 if($GLOBALS['db']->checkError()){
4550 logThis('An error occurred when performing this query-->'.$addContentDataText);
4554 $addContentDataText="update {$table_name} set {$column_name}_temp =
4555 convert(varchar(max), convert(varbinary(8000), {$column_name})) where id= '{$row['id']}'";
4556 $GLOBALS['db']->query($addContentDataText);
4557 if($GLOBALS['db']->checkError()){
4558 logThis('An error occurred when performing this query-->'.$addContentDataText);
4562 //drop the contents now and change contents_temp to contents
4563 $dropColumn = "alter table {$table_name} drop column {$column_name}";
4564 $GLOBALS['db']->query($dropColumn);
4565 if($GLOBALS['db']->checkError()){
4566 logThis('An error occurred when performing this query-->'.$dropColumn);
4568 $changeColumnName = "EXEC sp_rename '{$table_name}.[{$column_name}_temp]','{$column_name}','COLUMN'";
4569 $GLOBALS['db']->query($changeColumnName);
4570 if($GLOBALS['db']->checkError()){
4571 logThis('An error occurred when performing this query-->'.$changeColumnName);
4578 * This method attempts to delete all English inline help files.
4579 * This method was introduced by 5.5.0RC2.
4581 function clearHelpFiles(){
4582 $modulePath = clean_path(getcwd() . '/modules');
4583 $allHelpFiles = array();
4584 getFiles($allHelpFiles, $modulePath, "/en_us.help.*/");
4586 foreach( $allHelpFiles as $the_file ){
4587 if( is_file( $the_file ) ){
4588 unlink( $the_file );
4589 logThis("Deleted file: $the_file");
4597 * upgradeDateTimeFields
4599 * This method came from bug: 39757 where the date_end field is a date field and not a datetime field
4600 * which prevents you from performing timezone offset calculations once the data has been saved.
4602 * @param path String location to log file, empty by default
4604 function upgradeDateTimeFields($path=''){
4607 if($db->dbType == 'mysql')
4609 $meetingsSql = "UPDATE meetings SET date_end = date_add(date_start, INTERVAL + CONCAT(duration_hours, ':', duration_minutes) HOUR_MINUTE)";
4610 $callsSql = "UPDATE calls SET date_end = date_add(date_start, INTERVAL + CONCAT(duration_hours, ':', duration_minutes) HOUR_MINUTE)";
4611 } else if($db->dbType == 'mssql') {
4612 $meetingsSql = "UPDATE meetings set date_end = DATEADD(hh, duration_hours, DATEADD(mi, duration_minutes, date_start))";
4613 $callsSql = "UPDATE calls set date_end = DATEADD(hh, duration_hours, DATEADD(mi, duration_minutes, date_start))";
4614 } else if ($db->dbType == 'oci8') {
4615 $meetingsSql = "UPDATE meetings SET date_end = date_start + duration_hours/24 + duration_minutes/1440";
4616 $callsSql = "UPDATE calls SET date_end = date_start + duration_hours/24 + duration_minutes/1440";
4619 if(isset($meetingsSql) && isset($callsSql))
4621 logThis('upgradeDateTimeFields Meetings SQL:' . $meetingsSql, $path);
4622 $db->query($meetingsSql);
4624 logThis('upgradeDateTimeFields Calls SQL:' . $callsSql, $path);
4625 $db->query($callsSql);
4632 * upgradeDocumentTypeFields
4635 function upgradeDocumentTypeFields($path){
4639 $documentsSql = "UPDATE documents SET doc_type = 'Sugar' WHERE doc_type IS NULL";
4640 $meetingsSql = "UPDATE meetings SET type = 'Sugar' WHERE type IS NULL";
4642 logThis('upgradeDocumentTypeFields Documents SQL:' . $documentsSql, $path);
4643 $db->query($documentsSql);
4644 logThis('upgradeDocumentTypeFields Meetings SQL:' . $meetingsSql, $path);
4645 $db->query($meetingsSql);
4650 * merge_config_si_settings
4651 * This method checks for the presence of a config_si.php file and, if found, merges the configuration
4652 * settings from the config_si.php file into config.php. If a config_si_location parameter value is not
4653 * supplied it will attempt to discover the config_si.php file location from where the executing script
4656 * @param write_to_upgrade_log boolean optional value to write to the upgradeWizard.log file
4657 * @param config_location String optional value to config.php file location
4658 * @param config_si_location String optional value to config_si.php file location
4659 * @param path String file of the location of log file to write to
4660 * @return boolean value indicating whether or not a merge was attempted with config_si.php file
4662 function merge_config_si_settings($write_to_upgrade_log=false, $config_location='', $config_si_location='', $path='')
4664 if(!empty($config_location) && !file_exists($config_location))
4666 if($write_to_upgrade_log)
4668 logThis('config.php file specified in ' . $config_si_location . ' could not be found. Skip merging', $path);
4671 } else if(empty($config_location)) {
4673 //We are assuming this is from the silentUpgrade scripts so argv[3] will point to SugarCRM install location
4674 if(isset($argv[3]) && is_dir($argv[3]))
4676 $config_location = $argv[3] . DIRECTORY_SEPARATOR . 'config.php';
4680 //If config_location is still empty or if the file cannot be found, skip merging
4681 if(empty($config_location) || !file_exists($config_location))
4683 if($write_to_upgrade_log)
4685 logThis('config.php file at (' . $config_location . ') could not be found. Skip merging.', $path);
4689 if($write_to_upgrade_log)
4691 logThis('Loading config.php file at (' . $config_location . ') for merging.', $path);
4694 include($config_location);
4695 if(empty($sugar_config))
4697 if($write_to_upgrade_log)
4699 logThis('config.php contents are empty. Skip merging.', $path);
4705 if(!empty($config_si_location) && !file_exists($config_si_location))
4707 if($write_to_upgrade_log)
4709 logThis('config_si.php file specified in ' . $config_si_location . ' could not be found. Skip merging', $path);
4712 } else if(empty($config_si_location)) {
4713 if(isset($argv[0]) && is_file($argv[0]))
4715 $php_file = $argv[0];
4716 $p_info = pathinfo($php_file);
4717 $php_dir = (isset($p_info['dirname']) && $p_info['dirname'] != '.') ? $p_info['dirname'] . DIRECTORY_SEPARATOR : '';
4718 $config_si_location = $php_dir . 'config_si.php';
4722 //If config_si_location is still empty or if the file cannot be found, skip merging
4723 if(empty($config_si_location) || !file_exists($config_si_location))
4725 if($write_to_upgrade_log)
4727 logThis('config_si.php file at (' . $config_si_location . ') could not be found. Skip merging.', $path);
4731 if($write_to_upgrade_log)
4733 logThis('Loading config_si.php file at (' . $config_si_location . ') for merging.', $path);
4736 include($config_si_location);
4737 if(empty($sugar_config_si))
4739 if($write_to_upgrade_log)
4741 logThis('config_si.php contents are empty. Skip merging.', $path);
4747 //Now perform the merge operation
4749 foreach($sugar_config_si as $key=>$value)
4751 if(!preg_match('/^setup_/', $key) && !isset($sugar_config[$key]))
4753 if($write_to_upgrade_log)
4755 logThis('Merge key (' . $key . ') with value (' . $value . ')', $path);
4757 $sugar_config[$key] = $value;
4764 if($write_to_upgrade_log)
4766 logThis('Update config.php file with new values', $path);
4769 if(!write_array_to_file("sugar_config", $sugar_config, $config_location)) {
4770 if($write_to_upgrade_log)
4772 logThis('*** ERROR: could not write to config.php', $path);
4777 if($write_to_upgrade_log)
4779 logThis('config.php values are in sync with config_si.php values. Skipped merging.');
4784 if($write_to_upgrade_log)
4786 logThis('End merge_config_si_settings', $path);
4792 * upgrade_connectors
4793 * @param $path String variable for the log path
4795 function upgrade_connectors($path='') {
4796 logThis('Begin upgrade_connectors', $path);
4798 $filePath = 'custom/modules/Connectors/connectors/sources/ext/soap/hoovers/config.php';
4799 if(file_exists($filePath))
4801 logThis("{$filePath} file", $path);
4803 if(!is_null($config))
4806 if(isset($config['properties']['hoovers_endpoint']))
4808 $config['properties']['hoovers_endpoint'] = 'http://hapi.hoovers.com/HooversAPI-33';
4812 if(isset($config['properties']['hoovers_wsdl']))
4814 $config['properties']['hoovers_wsdl'] = 'http://hapi.hoovers.com/HooversAPI-33/hooversAPI/hooversAPI.wsdl';
4820 if(!write_array_to_file('config', $config, $filePath)) {
4821 logThis("Could not write new configuration to {$filePath} file", $path);
4823 logThis('Modified file successfully with new configuration entries', $path);
4829 $filePath = 'custom/modules/Connectors/connectors/sources/ext/soap/hoovers/vardefs.php';
4830 if(file_exists($filePath))
4832 logThis("Modifying {$filePath} file", $path);
4834 $fileContents = file_get_contents($filePath);
4835 $out = str_replace('bal.specialtyCriteria.companyKeyword', 'bal.specialtyCriteria.companyName', $fileContents);
4836 file_put_contents($filePath, $out);
4839 logThis('End upgrade_connectors', $path);
4843 * Enable the InsideView connector for the four default modules.
4845 function upgradeEnableInsideViewConnector($path='')
4847 logThis('Begin upgradeEnableInsideViewConnector', $path);
4849 // Load up the existing mapping and hand it to the InsideView connector to have it setup the correct logic hooks
4850 $mapFile = 'modules/Connectors/connectors/sources/ext/rest/insideview/mapping.php';
4851 if ( file_exists('custom/'.$mapFile) ) {
4852 logThis('Found CUSTOM mappings', $path);
4853 require('custom/'.$mapFile);
4855 logThis('Used default mapping', $path);
4859 require_once('include/connectors/sources/SourceFactory.php');
4860 $source = SourceFactory::getSource('ext_rest_insideview');
4862 // $mapping is brought in from the mapping.php file above
4863 $source->saveMappingHook($mapping);
4865 require_once('include/connectors/utils/ConnectorUtils.php');
4866 ConnectorUtils::installSource('ext_rest_insideview');
4868 // Now time to set the various modules to active, because this part ignores the default config
4869 require(CONNECTOR_DISPLAY_CONFIG_FILE);
4870 // $modules_sources come from that config file
4871 foreach ( $source->allowedModuleList as $module ) {
4872 $modules_sources[$module]['ext_rest_insideview'] = 'ext_rest_insideview';
4874 if(!write_array_to_file('modules_sources', $modules_sources, CONNECTOR_DISPLAY_CONFIG_FILE)) {
4875 //Log error and return empty array
4876 logThis("Cannot write \$modules_sources to " . CONNECTOR_DISPLAY_CONFIG_FILE,$path);
4879 logThis('End upgradeEnableInsideViewConnector', $path);
4883 function repair_long_relationship_names($path='')
4885 logThis("Begin repair_long_relationship_names", $path);
4886 require_once 'modules/ModuleBuilder/parsers/relationships/DeployedRelationships.php' ;
4887 $GLOBALS['mi_remove_tables'] = false;
4889 foreach($GLOBALS['moduleList'] as $module)
4891 $relationships = new DeployedRelationships ($module) ;
4892 foreach($relationships->getRelationshipList() as $rel_name)
4894 if (strlen($rel_name) > 27 && empty($touched[$rel_name]))
4896 logThis("Rebuilding relationship fields for $rel_name", $path);
4897 $touched[$rel_name] = true;
4898 $rel_obj = $relationships->get($rel_name);
4899 $rel_obj->setReadonly(false);
4900 $relationships->delete($rel_name);
4901 $relationships->save();
4902 $relationships->add($rel_obj);
4903 $relationships->save();
4904 $relationships->build () ;
4908 logThis("End repair_long_relationship_names", $path);
4911 function removeSilentUpgradeVarsCache(){
4912 global $silent_upgrade_vars_loaded;
4914 $cacheFileDir = "{$GLOBALS['sugar_config']['cache_dir']}/silentUpgrader";
4915 $cacheFile = "{$cacheFileDir}/silentUpgradeCache.php";
4917 if(file_exists($cacheFile)){
4921 $silent_upgrade_vars_loaded = array(); // Set to empty to reset it
4926 function loadSilentUpgradeVars(){
4927 global $silent_upgrade_vars_loaded;
4929 if(empty($silent_upgrade_vars_loaded)){
4930 $cacheFile = "{$GLOBALS['sugar_config']['cache_dir']}/silentUpgrader/silentUpgradeCache.php";
4931 // We have no pre existing vars
4932 if(!file_exists($cacheFile)){
4933 // Set the vars array so it's loaded
4934 $silent_upgrade_vars_loaded = array('vars' => array());
4937 require_once($cacheFile);
4938 $silent_upgrade_vars_loaded = $silent_upgrade_vars_cache;
4945 function writeSilentUpgradeVars(){
4946 global $silent_upgrade_vars_loaded;
4948 if(empty($silent_upgrade_vars_loaded)){
4949 return false; // You should have set some values before trying to write the silent upgrade vars
4952 $cacheFileDir = "{$GLOBALS['sugar_config']['cache_dir']}/silentUpgrader";
4953 $cacheFile = "{$cacheFileDir}/silentUpgradeCache.php";
4955 require_once('include/dir_inc.php');
4956 if(!mkdir_recursive($cacheFileDir)){
4959 require_once('include/utils/file_utils.php');
4960 if(!write_array_to_file('silent_upgrade_vars_cache', $silent_upgrade_vars_loaded, $cacheFile, 'w')){
4962 logThis("WARNING: writeSilentUpgradeVars could not write to {$cacheFile}", $path);
4969 function setSilentUpgradeVar($var, $value){
4970 if(!loadSilentUpgradeVars()){
4974 global $silent_upgrade_vars_loaded;
4976 $silent_upgrade_vars_loaded['vars'][$var] = $value;
4981 function getSilentUpgradeVar($var){
4982 if(!loadSilentUpgradeVars()){
4986 global $silent_upgrade_vars_loaded;
4988 if(!isset($silent_upgrade_vars_loaded['vars'][$var])){
4992 return $silent_upgrade_vars_loaded['vars'][$var];
4998 * add_unified_search_to_custom_modules_vardefs
5000 * This method calls the repair code to remove the unified_search_modules.php fiel
5003 function add_unified_search_to_custom_modules_vardefs()
5005 if(file_exists('cache/modules/unified_search_modules.php'))
5007 unlink('cache/modules/unified_search_modules.php');
5013 * change from using the older SugarCache in 6.1 and below to the new one in 6.2
5015 function upgradeSugarCache($file)
5017 global $sugar_config;
5018 // file = getcwd().'/'.$sugar_config['upload_dir'].$_FILES['upgrade_zip']['name'];
5020 $cacheUploadUpgradesTemp = clean_path(mk_temp_dir("{$sugar_config['upload_dir']}upgrades/temp"));
5022 unzip($file, $cacheUploadUpgradesTemp);
5024 if(!file_exists(clean_path("{$cacheUploadUpgradesTemp}/manifest.php"))) {
5025 logThis("*** ERROR: no manifest file detected while bootstraping upgrade wizard files!");
5028 include(clean_path("{$cacheUploadUpgradesTemp}/manifest.php"));
5031 $allFiles = array();
5032 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/database"))) {
5033 $allFiles = findAllFiles(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/database"), $allFiles);
5035 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/SugarCache"))) {
5036 $allFiles = findAllFiles(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/SugarCache"), $allFiles);
5038 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/external_cache.php"))) {
5039 $allFiles[] = clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/external_cache.php");
5041 $cwd = clean_path(getcwd());
5043 foreach($allFiles as $k => $file) {
5044 $file = clean_path($file);
5045 $destFile = str_replace(clean_path($cacheUploadUpgradesTemp.'/'.$manifest['copy_files']['from_dir']), $cwd, $file);
5046 if(!is_dir(dirname($destFile))) {
5047 mkdir_recursive(dirname($destFile)); // make sure the directory exists
5049 if ( stristr($file,'uw_main.tpl') )
5050 logThis('Skipping "'.$file.'" - file copy will during commit step.');
5052 logThis('updating UpgradeWizard code: '.$destFile);
5053 copy_recursive($file, $destFile);
5056 logThis ('is sugar_file_util there '.file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/sugar_file_utils.php")));
5057 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/sugar_file_utils.php"))) {
5058 $file = clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/sugar_file_utils.php");
5059 $destFile = str_replace(clean_path($cacheUploadUpgradesTemp.'/'.$manifest['copy_files']['from_dir']), $cwd, $file);
5060 copy($file,$destFile);
5066 * upgradeDisplayedTabsAndSubpanels
5068 * @param $version String value of current system version (pre upgrade)
5070 function upgradeDisplayedTabsAndSubpanels($version)
5072 if($version < '620')
5074 logThis('start upgrading system displayed tabs and subpanels');
5075 require_once('modules/MySettings/TabController.php');
5076 $tc = new TabController();
5078 //grab the existing system tabs
5079 $tabs = $tc->get_tabs_system();
5081 //add Calls, Meetings, Tasks, Notes, Prospects (Targets) and ProspectLists (Target Lists)
5082 //to displayed tabs unless explicitly set to hidden
5083 $modules_to_add = array('Calls', 'Meetings', 'Tasks', 'Notes', 'Prospects', 'ProspectLists');
5084 $added_tabs = array();
5086 foreach($modules_to_add as $module)
5088 $tabs[0][$module] = $module;
5089 $added_tabs[] = $module;
5092 logThis('calling set_system_tabs on TabController to add tabs: ' . var_export($added_tabs, true));
5093 $tc->set_system_tabs($tabs[0]);
5094 logThis('finish upgrading system displayed tabs and subpanels');
5100 * unlinkUpgradeFiles
5101 * This is a helper function to clean up
5103 * @param $version String value of current system version (pre upgrade)
5105 function unlinkUpgradeFiles($version)
5107 if(!isset($version))
5112 logThis('start unlinking files from previous upgrade');
5113 if($version < '620')
5115 //list of files to remove
5116 $files_to_remove = array('modules/Notifications/metadata/studio.php', 'modules/Help/Forms.php','themes/Sugar5/images/sugarColors.xml');
5118 foreach($files_to_remove as $f)
5122 logThis('removing file: ' . $f);
5127 logThis('end unlinking files from previous upgrade');
5129 if($version < '620')
5131 logThis('start upgrade for DocumentRevisions classic files (EditView.html, EditView.php, DetailView.html, DetailView.php, Save.php)');
5133 //Use a md5 comparison check to see if we can just remove the file where an exact match is found
5134 if($version < '610')
5137 'modules/DocumentRevisions/DetailView.html' => '17ad4d308ce66643fdeb6fdb3b0172d3',
5138 'modules/DocumentRevisions/DetailView.php' => 'd8606cdcd0281ae9443b2580a43eb5b3',
5139 'modules/DocumentRevisions/EditView.php' => 'c7a1c3ef2bb30e3f5a11d122b3c55ff1',
5140 'modules/DocumentRevisions/EditView.html' => '7d360ca703863c957f40b3719babe8c8',
5141 'modules/DocumentRevisions/Save.php' => 'd7e39293a5fb4d605ca2046e7d1fcf28',
5145 'modules/DocumentRevisions/DetailView.html' => 'a8356ff20cd995daffe6cb7f7b8b2340',
5146 'modules/DocumentRevisions/DetailView.php' => '20edf45dd785469c484fbddff1a3f8f2',
5147 'modules/DocumentRevisions/EditView.php' => 'fb31958496f04031b2851dcb4ce87d50',
5148 'modules/DocumentRevisions/EditView.html' => 'b8cada4fa6fada2b4e4928226d8b81ee',
5149 'modules/DocumentRevisions/Save.php' => '7fb62e4ebff879bafc07a08da62902aa',
5153 foreach($dr_files as $rev_file=>$hash)
5155 if(file_exists($rev_file))
5157 //It's a match here so let's just remove the file
5158 if (md5(file_get_contents($rev_file)) == $hash)
5160 logThis('removing file ' . $rev_file);
5163 if(!copy($rev_file, $rev_file . '.suback.bak'))
5165 logThis('error making backup for file ' . $rev_file);
5167 logThis('copied file ' . $rev_file . ' to ' . $rev_file . '.suback.bak');
5174 logThis('end upgrade for DocumentRevisions classic files');
5177 //First check if we even have the scripts_for_patch/files_to_remove directory
5178 require_once('modules/UpgradeWizard/UpgradeRemoval.php');
5181 if(empty($_SESSION['unzip_dir']))
5183 global $sugar_config;
5184 $base_upgrade_dir = $sugar_config['upload_dir'] . "/upgrades";
5185 $base_tmp_upgrade_dir = "$base_upgrade_dir/temp";
5186 $_SESSION['unzip_dir'] = mk_temp_dir( $base_tmp_upgrade_dir );
5190 if(isset($_SESSION['unzip_dir']) && file_exists($_SESSION['unzip_dir'].'/scripts/files_to_remove'))
5192 $files_to_remove = glob($_SESSION['unzip_dir'].'/scripts/files_to_remove/*.php');
5194 foreach($files_to_remove as $script)
5196 if(preg_match('/UpgradeRemoval(\d+)x\.php/', $script, $matches))
5198 $checkVersion = $matches[1] + 1; //Increment by one to check everything equal or below the target version
5199 $upgradeClass = 'UpgradeRemoval' . $matches[1] . 'x';
5200 require_once($_SESSION['unzip_dir'].'/scripts/files_to_remove/' . $upgradeClass . '.php');
5202 //Check to make sure we should load and run this UpgradeRemoval instance
5203 if($checkVersion <= $version && class_exists($upgradeClass))
5205 $upgradeInstance = new $upgradeClass();
5206 if($upgradeInstance instanceof UpgradeRemoval)
5208 logThis('Running UpgradeRemoval instance ' . $upgradeClass);
5209 logThis('Files will be backed up to custom/backup');
5210 $files = $upgradeInstance->getFilesToRemove($version);
5211 foreach($files as $file)
5215 $upgradeInstance->processFilesToRemove($files);
5222 //Check if we have a custom directory
5223 if(file_exists('custom/scripts/files_to_remove'))
5226 $files_to_remove = glob('custom/scripts/files_to_remove/*.php');
5228 foreach($files_to_remove as $script)
5230 if(preg_match('/\/files_to_remove\/(.*?)\.php$/', $script, $matches))
5232 require_once($script);
5233 $upgradeClass = $matches[1];
5235 if(!class_exists($upgradeClass))
5240 $upgradeInstance = new $upgradeClass();
5241 if($upgradeInstance instanceof UpgradeRemoval)
5243 logThis('Running Custom UpgradeRemoval instance ' . $upgradeClass);
5244 $files = $upgradeInstance->getFilesToRemove($version);
5245 foreach($files as $file)
5249 $upgradeInstance->processFilesToRemove($files);
5257 if (!function_exists("getValidDBName"))
5260 * Return a version of $proposed that can be used as a column name in any of our supported databases
5261 * 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)
5262 * @param string $name Proposed name for the column
5263 * @param string $ensureUnique
5264 * @return string Valid column name trimmed to right length and with invalid characters removed
5266 function getValidDBName ($name, $ensureUnique = false, $maxLen = 30)
5268 // first strip any invalid characters - all but alphanumerics and -
5269 $name = preg_replace ( '/[^\w-]+/i', '', $name ) ;
5270 $len = strlen ( $name ) ;
5274 $md5str = md5($name);
5275 $tail = substr ( $name, -11) ;
5276 $temp = substr($md5str , strlen($md5str)-4 );
5277 $result = substr ( $name, 0, 10) . $temp . $tail ;
5278 }else if ($len > ($maxLen - 5))
5280 $result = substr ( $name, 0, 11) . substr ( $name, 11 - $maxLen + 5);
5282 return strtolower ( $result ) ;
5289 * Whether directory exists within list of directories to skip
5290 * @param string $dir dir to be checked
5291 * @param array $skipDirs list with skipped dirs
5294 function whetherNeedToSkipDir($dir, $skipDirs)
5296 foreach($skipDirs as $skipMe) {
5297 if(strpos( clean_path($dir), $skipMe ) !== false) {