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-2012 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 * Helper function for upgrade - get path from upload:// name
46 function getUploadRelativeName($path)
48 if(class_exists('UploadFile')) {
49 return UploadFile::realpath($path);
51 if(substr($path, 0, 9) == "upload://") {
52 $path = rtrim($GLOBALS['sugar_config']['upload_dir'], "/\\")."/".substr($path, 9);
58 * Backs-up files that are targeted for patch/upgrade to a restore directory
59 * @param string rest_dir Full path to the directory containing the original, replaced files.
60 * @param string install_file Full path to the uploaded patch/upgrade zip file
61 * @param string unzip_dir Full path to the unzipped files in a temporary directory
62 * @param string zip_from_dir Name of directory that the unzipped files containing the actuall replacement files
63 * @param array errors Collection of errors to be displayed at end of process
64 * @param string path Optional full path to the log file.
65 * @return array errors
67 function commitMakeBackupFiles($rest_dir, $install_file, $unzip_dir, $zip_from_dir, $errors, $path='') {
69 // create restore file directory
70 sugar_mkdir($rest_dir, 0775, true);
72 if(file_exists($rest_dir) && is_dir($rest_dir)){
73 logThis('backing up files to be overwritten...', $path);
74 $newFiles = findAllFiles(clean_path($unzip_dir . '/' . $zip_from_dir), array());
76 // keep this around for canceling
77 $_SESSION['uw_restore_dir'] = getUploadRelativeName($rest_dir);
79 foreach ($newFiles as $file) {
80 if (strpos($file, 'md5'))
83 // get name of current file to place in restore directory
84 $cleanFile = str_replace(clean_path($unzip_dir . '/' . $zip_from_dir), '', $file);
86 // make sure the directory exists
87 $cleanDir = $rest_dir . '/' . dirname($cleanFile);
88 sugar_mkdir($cleanDir, 0775, true);
89 $oldFile = clean_path(getcwd() . '/' . $cleanFile);
91 // only copy restore files for replacements - ignore new files from patch
92 if (is_file($oldFile)) {
93 if (is_writable($rest_dir)) {
94 logThis('Backing up file: ' . $oldFile, $path);
95 if (!copy($oldFile, $rest_dir . '/' . $cleanFile)) {
96 logThis('*** ERROR: could not backup file: ' . $oldFile, $path);
97 $errors[] = "{$mod_strings['LBL_UW_BACKUP']}::{$mod_strings['ERR_UW_FILE_NOT_COPIED']}: {$oldFile}";
99 $backupFilesExist = true;
103 logThis('*** ERROR: directory not writable: ' . $rest_dir, $path);
104 $errors[] = "{$mod_strings['LBL_UW_BACKUP']}::{$mod_strings['ERR_UW_DIR_NOT_WRITABLE']}: {$oldFile}";
109 logThis('file backup done.', $path);
114 * Copies files from the unzipped patch to the destination.
115 * @param string unzip_dir Full path to the temporary directory created during unzip operation.
116 * @param string zip_from_dir Name of folder containing the unzipped files; usually the name of the Patch without the
118 * @param string path Optional full path to alternate upgradeWizard log file.
119 * @return array Two element array containing to $copiedFiles and $skippedFiles.
124 function commitCopyNewFiles($unzip_dir, $zip_from_dir, $path='') {
125 logThis('Starting file copy process...', $path);
126 global $sugar_version;
128 if(substr($sugar_version,0,1) >= 5){
129 $modules = getAllModules();
130 $backwardModules = array();
131 foreach($modules as $mod){
132 if(is_dir(clean_path(getcwd().'/modules/'.$mod.'/.500'))){
134 $files= findAllFiles(clean_path(getcwd().'/modules/'.$mod.'/.500'),$files);
135 if(sizeof($files) >0){
136 //backward compatibility is on
137 $backwardModules[] = $mod;
143 $newFiles = findAllFiles(clean_path($unzip_dir . '/' . $zip_from_dir), array());
144 $zipPath = clean_path($unzip_dir . '/' . $zip_from_dir);
146 // handle special do-not-overwrite conditions
147 $doNotOverwrite = array();
148 $doNotOverwrite[] = '__stub';
149 if(isset($_REQUEST['overwrite_files_serial'])) {
150 $doNotOverwrite = explode('::', $_REQUEST['overwrite_files_serial']);
153 $copiedFiles = array();
154 $skippedFiles = array();
156 foreach($newFiles as $file) {
157 $cleanFile = str_replace($zipPath, '', $file);
158 $srcFile = $zipPath . $cleanFile;
159 $targetFile = clean_path(getcwd() . '/' . $cleanFile);
160 if($backwardModules != null && sizeof($backwardModules) >0){
161 foreach($backwardModules as $mod){
162 $splitPath = explode('/',trim($cleanFile));
163 if('modules' == trim($splitPath[1]) && $mod == trim($splitPath[2])){
164 $cleanFile = str_replace('/modules/'.$mod, '/modules/'.$mod.'/.500', $cleanFile);
165 $targetFile = clean_path(getcwd() . '/' . $cleanFile);
169 if(!is_dir(dirname($targetFile))) {
170 mkdir_recursive(dirname($targetFile)); // make sure the directory exists
173 if((!file_exists($targetFile)) || /* brand new file */
174 (!in_array($targetFile, $doNotOverwrite)) /* manual diff file */
176 // handle sugar_version.php
177 if(strpos($targetFile, 'sugar_version.php') !== false && !preg_match('/\/portal\/sugar_version\.php$/i', $targetFile)) {
178 logThis('Skipping "sugar_version.php" - file copy will occur at end of successful upgrade', $path);
179 $_SESSION['sugar_version_file'] = $srcFile;
183 //logThis('Copying file to destination: ' . $targetFile, $path);
185 if(!copy($srcFile, $targetFile)) {
186 logThis('*** ERROR: could not copy file: ' . $targetFile, $path);
188 $copiedFiles[] = $targetFile;
191 //logThis('Skipping file: ' . $targetFile, $path);
192 $skippedFiles[] = $targetFile;
195 logThis('File copy done.', $path);
198 $ret['copiedFiles'] = $copiedFiles;
199 $ret['skippedFiles'] = $skippedFiles;
205 //On cancel put back the copied files from 500 to 451 state
206 function copyFilesOnCancel($step){
207 //place hoder for cancel action
212 function removeFileFromPath($file,$path, $deleteNot=array()){
214 $cur = $path . '/' . $file;
215 if(file_exists($cur)){
217 foreach($deleteNot as $dn){
227 if(!file_exists($path))return $removed;
229 while($e = $d->read()){
230 $next = $path . '/'. $e;
231 if(substr($e, 0, 1) != '.' && is_dir($next)){
232 $removed += removeFileFromPath($file, $next, $deleteNot);
239 * This function copies/overwrites between directories
241 * @param string the directory name to remove
242 * @param boolean whether to just empty the given directory, without deleting the given directory.
243 * @return boolean True/False whether the directory was deleted.
246 function copyRecursiveBetweenDirectories($from,$to){
247 if(file_exists($from)){
248 $modifiedFiles = array();
249 $modifiedFiles = findAllFiles(clean_path($from), $modifiedFiles);
250 $cwd = clean_path(getcwd());
251 foreach($modifiedFiles as $file) {
252 $srcFile = clean_path($file);
253 if (strpos($srcFile,".svn") === false) {
254 $targetFile = str_replace($from, $to, $srcFile);
256 if(!is_dir(dirname($targetFile))) {
257 mkdir_recursive(dirname($targetFile)); // make sure the directory exists
260 // handle sugar_version.php
261 if(strpos($targetFile, 'sugar_version.php') !== false && !preg_match('/\/portal\/sugar_version\.php$/i', $targetFile)) {
262 logThis('Skipping "sugar_version.php" - file copy will occur at end of successful upgrade', $targetFile);
263 $_SESSION['sugar_version_file'] = $srcFile;
267 if(!copy($srcFile, $targetFile)) {
268 logThis("*** ERROR: could not copy file $srcFile to $targetFile");
275 function deleteDirectory($dirname,$only_empty=false) {
276 if (!is_dir($dirname))
278 $dscan = array(realpath($dirname));
280 while (!empty($dscan)) {
281 $dcur = array_pop($dscan);
283 if ($d=opendir($dcur)) {
284 while ($f=readdir($d)) {
285 if ($f=='.' || $f=='..')
296 $i_until = ($only_empty)? 1 : 0;
297 for ($i=count($darr)-1; $i>=$i_until; $i--) {
298 if (rmdir($darr[$i]))
299 logThis('Success :Copying file to destination: ' . $darr[$i]);
301 logThis('Copy problem:Copying file to destination: ' . $darr[$i]);
303 return (($only_empty)? (count(scandir)<=2) : (!is_dir($dirname)));
306 * Get all the customized modules. Compare the file md5s with the base md5s
307 * If a file has been modified then put the module in the list of customized
308 * modules. Show the list in the preflight check UI.
311 function deleteAndOverWriteSelectedFiles($unzip_dir, $zip_from_dir,$delete_dirs){
312 if($delete_dirs != null){
313 foreach($delete_dirs as $del_dir){
314 deleteDirectory($del_dir);
315 $newFiles = findAllFiles(clean_path($unzip_dir . '/' . $zip_from_dir.'/'.$del_dir), array());
316 $zipPath = clean_path($unzip_dir . '/' . $zip_from_dir.'/'.$del_dir);
317 $copiedFiles = array();
318 $skippedFiles = array();
320 foreach($newFiles as $file) {
321 $cleanFile = str_replace($zipPath, '', $file);
322 $srcFile = $zipPath . $cleanFile;
323 $targetFile = clean_path(getcwd() . '/' . $cleanFile);
325 if(!is_dir(dirname($targetFile))) {
326 mkdir_recursive(dirname($targetFile)); // make sure the directory exists
329 if(!file_exists($targetFile)){
330 // handle sugar_version.php
331 if(strpos($targetFile, 'sugar_version.php') !== false) {
332 logThis('Skipping sugar_version.php - file copy will occur at end of successful upgrade');
333 $_SESSION['sugar_version_file'] = $srcFile;
337 //logThis('Copying file to destination: ' . $targetFile);
339 if(!copy($srcFile, $targetFile)) {
340 logThis('*** ERROR: could not copy file: ' . $targetFile);
342 $copiedFiles[] = $targetFile;
345 //logThis('Skipping file: ' . $targetFile);
346 $skippedFiles[] = $targetFile;
352 $ret['copiedFiles'] = $copiedFiles;
353 $ret['skippedFiles'] = $skippedFiles;
358 //Default is empty the directory. For removing set it to false
359 // to use this function to totally remove a directory, write:
360 // recursive_remove_directory('path/to/directory/to/delete',FALSE);
362 // to use this function to empty a directory, write:
363 // recursive_remove_directory('path/to/full_directory');
365 function recursive_empty_or_remove_directory($directory, $exclude_dirs=null,$exclude_files=null,$empty=TRUE)
367 // if the path has a slash at the end we remove it here
368 if(substr($directory,-1) == '/')
370 $directory = substr($directory,0,-1);
373 // if the path is not valid or is not a directory ...
374 if(!file_exists($directory) || !is_dir($directory))
376 // ... we return false and exit the function
379 // ... if the path is not readable
380 }elseif(!is_readable($directory))
382 // ... we return false and exit the function
385 // ... else if the path is readable
388 // we open the directory
389 $handle = opendir($directory);
391 // and scan through the items inside
392 while (FALSE !== ($item = readdir($handle)))
394 // if the filepointer is not the current directory
395 // or the parent directory
396 if($item != '.' && $item != '..')
398 // we build the new path to delete
399 $path = $directory.'/'.$item;
401 // if the new path is a directory
402 //add another check if the dir is in the list to exclude delete
403 if(is_dir($path) && $exclude_dirs != null && in_array($path,$exclude_dirs)){
406 else if(is_dir($path))
408 // we call this function with the new path
409 recursive_empty_or_remove_directory($path);
411 // if the new path is a file
413 // we remove the file
414 if($exclude_files != null && in_array($path,$exclude_files)){
423 // close the directory
426 // if the option to empty is not set to true
429 // try to delete the now empty directory
430 if(!rmdir($directory))
432 // return false if not possible
440 // ------------------------------------------------------------
445 function getAllCustomizedModules() {
447 require_once('files.md5');
449 $return_array = array();
450 $modules = getAllModules();
451 foreach($modules as $mod) {
452 //find all files in each module if the files have been modified
453 //as compared to the base version then add the module to the
454 //customized modules array
455 $modFiles = findAllFiles(clean_path(getcwd())."/modules/$mod", array());
456 foreach($modFiles as $file){
457 $fileContents = file_get_contents($file);
458 $file = str_replace(clean_path(getcwd()),'',$file);
459 if($md5_string['./' . $file]){
460 if(md5($fileContents) != $md5_string['./' . $file]) {
461 //A file has been customized in the module. Put the module into the
462 // customized modules array.
463 echo 'Changed File'.$file;
469 // This is a new file in user's version and indicates that module has been
470 //customized. Put the module in the customized array.
471 echo 'New File'.$file;
478 return $return_array;
482 * Array of all Modules in the version bein upgraded
483 * This method returns an Array of all modules
484 * @return $modules Array of modules.
486 function getAllModules() {
489 while($e = $d->read()){
490 if(substr($e, 0, 1) == '.' || !is_dir('modules/' . $e))continue;
496 //Remove files with the smae md5
498 function removeMd5MatchingFiles($deleteNot=array()){
500 $md5_string = array();
501 if(file_exists(clean_path(getcwd().'/files.md5'))){
502 require(clean_path(getcwd().'/files.md5'));
504 $modulesAll = getAllModules();
505 foreach($modulesAll as $mod){
506 $allModFiles = array();
507 if(is_dir('modules/'.$mod)){
508 $allModFiles = findAllFiles('modules/'.$mod,$allModFiles);
509 foreach($allModFiles as $file){
510 if(file_exists($file) && !in_array(basename($file),$deleteNot)){
511 if(isset($md5_string['./'.$file])) {
512 $fileContents = file_get_contents($file);
513 if(md5($fileContents) == $md5_string['./'.$file]) {
524 * Handles requirements for creating reminder Tasks and Emails
525 * @param array skippedFiles Array of files that were not overwriten and must be manually mereged.
526 * @param string path Optional full path to alternate upgradeWizard log.
528 function commitHandleReminders($skippedFiles, $path='') {
530 global $current_user;
532 if(empty($mod_strings))
533 $mod_strings = return_module_language('en_us', 'UpgradeWizard');
535 if(empty($current_user->id)) {
536 $current_user->getSystemUser();
539 if(count($skippedFiles) > 0) {
540 $desc = $mod_strings['LBL_UW_COMMIT_ADD_TASK_OVERVIEW'] . "\n\n";
541 $desc .= $mod_strings['LBL_UW_COMMIT_ADD_TASK_DESC_1'];
542 $desc .= $_SESSION['uw_restore_dir'] . "\n\n";
543 $desc .= $mod_strings['LBL_UW_COMMIT_ADD_TASK_DESC_2'] . "\n\n";
545 foreach($skippedFiles as $file) {
546 $desc .= $file . "\n";
550 /// Not using new TimeDate stuff here because it needs to be compatible with 6.0
551 $nowDate = gmdate('Y-m-d');
552 $nowTime = gmdate('H:i:s');
553 $nowDateTime = $nowDate . ' ' . $nowTime;
555 if($_REQUEST['addTaskReminder'] == 'remind') {
556 logThis('Adding Task for admin for manual merge.', $path);
559 $task->name = $mod_strings['LBL_UW_COMMIT_ADD_TASK_NAME'];
560 $task->description = $desc;
561 $task->date_due = $nowDate;
562 $task->time_due = $nowTime;
563 $task->priority = 'High';
564 $task->status = 'Not Started';
565 $task->assigned_user_id = $current_user->id;
566 $task->created_by = $current_user->id;
567 $task->date_entered = $nowDateTime;
568 $task->date_modified = $nowDateTime;
572 if($_REQUEST['addEmailReminder'] == 'remind') {
573 logThis('Sending Reminder for admin for manual merge.', $path);
575 $email = new Email();
576 $email->assigned_user_id = $current_user->id;
577 $email->name = $mod_strings['LBL_UW_COMMIT_ADD_TASK_NAME'];
578 $email->description = $desc;
579 $email->description_html = nl2br($desc);
580 $email->from_name = $current_user->full_name;
581 $email->from_addr = $current_user->email1;
582 $email->to_addrs_arr = $email->parse_addrs($current_user->email1, '', '', '');
583 $email->cc_addrs_arr = array();
584 $email->bcc_addrs_arr = array();
585 $email->date_entered = $nowDateTime;
586 $email->date_modified = $nowDateTime;
593 function deleteCache(){
594 //Clean modules from cache
595 $cachedir = sugar_cached('modules');
596 if(is_dir($cachedir)){
597 $allModFiles = array();
598 $allModFiles = findAllFiles($cachedir,$allModFiles, true);
599 foreach($allModFiles as $file) {
600 if(file_exists($file)) {
602 rmdir_recursive($file);
611 //Clean jsLanguage from cache
612 $cachedir = sugar_cached('jsLanguage');
613 if(is_dir($cachedir)){
614 $allModFiles = array();
615 $allModFiles = findAllFiles($cachedir,$allModFiles);
616 foreach($allModFiles as $file){
617 if(file_exists($file)){
622 //Clean smarty from cache
623 $cachedir = sugar_cached('smarty');
624 if(is_dir($cachedir)){
625 $allModFiles = array();
626 $allModFiles = findAllFiles($cachedir,$allModFiles);
627 foreach($allModFiles as $file){
628 if(file_exists($file)){
633 //Rebuild dashlets cache
634 require_once('include/Dashlets/DashletCacheBuilder.php');
635 $dc = new DashletCacheBuilder();
639 function deleteChance(){
640 //Clean folder from cache
641 if(is_dir('include/SugarObjects/templates/chance')){
642 rmdir_recursive('include/SugarObjects/templates/chance');
644 if(is_dir('include/SugarObjects/templates/chance')){
645 if(!isset($_SESSION['chance'])){
646 $_SESSION['chance'] = '';
648 $_SESSION['chance'] = 'include/SugarObjects/templates/chance';
649 //rename('include/SugarObjects/templates/chance','include/SugarObjects/templates/chance_removeit');
657 * This function copies upgrade wizard files from new patch if that dir exists
659 * @param $file String path to uploaded zip file
661 function upgradeUWFiles($file) {
662 $cacheUploadUpgradesTemp = mk_temp_dir(sugar_cached("upgrades/temp"));
664 unzip($file, $cacheUploadUpgradesTemp);
666 if(!file_exists("$cacheUploadUpgradesTemp/manifest.php")) {
667 logThis("*** ERROR: no manifest file detected while bootstraping upgrade wizard files!");
670 include("$cacheUploadUpgradesTemp/manifest.php");
674 $from_dir = "{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}";
677 if(file_exists("$from_dir/include/Localization/Localization.php")) {
678 $allFiles[] = "$from_dir/include/Localization/Localization.php";
681 if(file_exists("$from_dir/modules/UpgradeWizard")) {
682 $allFiles[] = findAllFiles("$from_dir/modules/UpgradeWizard", $allFiles);
685 if(file_exists("$from_dir/ModuleInstall")) {
686 $allFiles[] = findAllFiles("$from_dir/ModuleInstall", $allFiles);
688 if(file_exists("$from_dir/include/javascript/yui")) {
689 $allFiles[] = findAllFiles("$from_dir/include/javascript/yui", $allFiles);
691 if(file_exists("$from_dir/HandleAjaxCall.php")) {
692 $allFiles[] = "$from_dir/HandleAjaxCall.php";
694 if(file_exists("$from_dir/include/SugarTheme")) {
695 $allFiles[] = findAllFiles("$from_dir/include/SugarTheme", $allFiles);
697 if(file_exists("$from_dir/include/SugarCache")) {
698 $allFiles[] = findAllFiles("$from_dir/include/SugarCache", $allFiles);
700 if(file_exists("$from_dir/include/utils/external_cache.php")) {
701 $allFiles[] = "$from_dir/include/utils/external_cache.php";
703 if(file_exists("$from_dir/include/upload_file.php")) {
704 $allFiles[] = "$from_dir/include/upload_file.php";
706 if(file_exists("$from_dir/include/file_utils.php")) {
707 $allFiles[] = "$from_dir/include/file_utils.php";
709 if(file_exists("$from_dir/include/upload_file.php")) {
710 $allFiles[] = "$from_dir/include/upload_file.php";
712 if(file_exists("$from_dir/include/utils/sugar_file_utils.php")) {
713 $allFiles[] = "$from_dir/include/utils/sugar_file_utils.php";
716 if(file_exists("$from_dir/modules/Users")) {
717 $allFiles[] = findAllFiles("$from_dir/modules/Users", $allFiles);
720 upgradeUWFilesCopy($allFiles, $from_dir);
726 * This function recursively copies files from the upgradeUWFiles Array
727 * @see upgradeUWFiles
729 * @param array $allFiles Array of files to copy over after zip file has been uploaded
730 * @param string $from_dir Source directory
732 function upgradeUWFilesCopy($allFiles, $from_dir)
734 foreach($allFiles as $file)
738 upgradeUWFilesCopy($file, $from_dir);
740 $destFile = str_replace($from_dir."/", "", $file);
741 if(!is_dir(dirname($destFile))) {
742 mkdir_recursive(dirname($destFile)); // make sure the directory exists
745 if(stristr($file,'uw_main.tpl'))
746 logThis('Skipping "'.$file.'" - file copy will during commit step.');
748 logThis('updating UpgradeWizard code: '.$destFile);
749 copy_recursive($file, $destFile);
758 * gets valid patch file names that exist in upload/upgrade/patch/
760 function getValidPatchName($returnFull = true) {
761 global $base_upgrade_dir;
764 global $sugar_version;
765 global $sugar_config;
766 $uh = new UpgradeHistory();
767 list($base_upgrade_dir, $base_tmp_upgrade_dir) = getUWDirs();
770 // scan for new files (that are not installed)
771 logThis('finding new files for upgrade');
772 $upgrade_content = '';
773 $upgrade_contents = findAllFiles($base_upgrade_dir, array(), false, 'zip');
774 //other variations of zip file i.e. ZIP, zIp,zIP,Zip,ZIp,ZiP
781 <b>{$mod_strings['LBL_ML_NAME']}</b>
784 <b>{$mod_strings['LBL_ML_TYPE']}</b>
787 <b>{$mod_strings['LBL_ML_VERSION']}</b>
790 <b>{$mod_strings['LBL_ML_PUBLISHED']}</b>
793 <b>{$mod_strings['LBL_ML_UNINSTALLABLE']}</b>
796 <b>{$mod_strings['LBL_ML_DESCRIPTION']}</b>
801 // assume old patches are there.
802 $upgradeToVersion = array(); // fill with valid patches - we will only use the latest qualified found patch
804 // cn: bug 10609 - notices for uninitialized variables
809 $published_date = '';
814 foreach($upgrade_contents as $upgrade_content) {
815 if(!preg_match("#.*\.zip\$#i", $upgrade_content)) {
819 $the_base = basename($upgrade_content);
820 $the_md5 = md5_file($upgrade_content);
822 $md5_matches = $uh->findByMd5($the_md5);
824 /* 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.
825 * Edge-case: manual upgrade with a FTP of a patch; UH table has no entry for it. Assume nothing. :( */
826 if(0 == sizeof($md5_matches)) {
827 $target_manifest = remove_file_extension( $upgrade_content ) . '-manifest.php';
828 require_once($target_manifest);
830 if(empty($manifest['version'])) {
831 logThis("*** Potential error: patch found with no version [ {$upgrade_content} ]");
834 if(!isset($manifest['type']) || $manifest['type'] != 'patch') {
835 logThis("*** Potential error: patch found with either no 'type' or non-patch type [ {$upgrade_content} ]");
839 $upgradeToVersion[$manifest['version']] = urlencode($upgrade_content);
841 $name = empty($manifest['name']) ? $upgrade_content : $manifest['name'];
842 $version = empty($manifest['version']) ? '' : $manifest['version'];
843 $published_date = empty($manifest['published_date']) ? '' : $manifest['published_date'];
845 $description = empty($manifest['description']) ? 'None' : $manifest['description'];
846 $uninstallable = empty($manifest['is_uninstallable']) ? 'No' : 'Yes';
847 $type = getUITextForType( $manifest['type'] );
848 $manifest_type = $manifest['type'];
850 if(empty($manifest['icon'])) {
851 $icon = getImageForType( $manifest['type'] );
853 $path_parts = pathinfo( $manifest['icon'] );
854 $icon = "<!--not_in_theme!--><img src=\"" . remove_file_extension( $upgrade_content ) . "-icon." . $path_parts['extension'] . "\">";
859 // cn: bug 10488 use the NEWEST upgrade/patch available when running upgrade wizard.
860 ksort($upgradeToVersion);
861 $upgradeToVersion = array_values($upgradeToVersion);
862 $newest = array_pop($upgradeToVersion);
863 $_SESSION['install_file'] = urldecode($newest); // in-case it was there from a prior.
864 logThis("*** UW using [ {$_SESSION['install_file']} ] as source for patch files.");
866 $cleanUpgradeContent = urlencode($_SESSION['install_file']);
868 // cn: 10606 - cannot upload a patch file since this returned always.
869 if(!empty($cleanUpgradeContent)) {
870 $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";
873 <form action="index.php" method="post">
874 <input type="hidden" name="module" value="UpgradeWizard">
875 <input type="hidden" name="action" value="index">
876 <input type="hidden" name="step" value="{$_REQUEST['step']}">
877 <input type="hidden" name="run" value="delete">
878 <input type=hidden name="install_file" value="{$cleanUpgradeContent}" />
879 <input type=submit value="{$mod_strings['LBL_BUTTON_DELETE']}" />
883 $disabled = "DISABLED";
888 if(empty($cleanUpgradeContent)){
889 $ready .= "<tr><td colspan='7'><i>None</i></td>\n";
890 $ready .= "</table>\n";
892 $ready .= "<br></ul>\n";
894 $return['ready'] = $ready;
895 $return['disabled'] = $disabled;
904 * finalizes upgrade by setting upgrade versions in DB (config table) and sugar_version.php
905 * @return bool true on success
907 function updateVersions($version) {
909 global $sugar_config;
912 logThis('At updateVersions()... updating config table and sugar_version.php.', $path);
915 if(isset($_SESSION['sugar_version_file']) && !empty($_SESSION['sugar_version_file'])) {
916 if(!copy($_SESSION['sugar_version_file'], clean_path(getcwd().'/sugar_version.php'))) {
917 logThis('*** ERROR: sugar_version.php could not be copied to destination! Cannot complete upgrade', $path);
920 logThis('sugar_version.php successfully updated!', $path);
923 logThis('*** ERROR: no sugar_version.php file location found! - cannot complete upgrade...', $path);
927 $q1 = "DELETE FROM config WHERE category = 'info' AND name = 'sugar_version'";
928 $q2 = "INSERT INTO config (category, name, value) VALUES ('info', 'sugar_version', '{$version}')";
930 logThis('Deleting old DB version info from config table.', $path);
933 logThis('Inserting updated version info into config table.', $path);
936 logThis('updateVersions() complete.', $path);
943 * gets a module's lang pack - does not need to be a SugarModule
944 * @param lang string Language
945 * @param module string Path to language folder
946 * @return array mod_strings
948 function getModuleLanguagePack($lang, $module) {
949 $mod_strings = array();
951 if(!empty($lang) && !empty($module)) {
952 $langPack = clean_path(getcwd().'/'.$module.'/language/'.$lang.'.lang.php');
953 $langPackEn = clean_path(getcwd().'/'.$module.'/language/en_us.lang.php');
955 if (file_exists($langPack))
959 elseif (file_exists($langPackEn))
961 include($langPackEn);
968 * checks system compliance for 4.5+ codebase
969 * @return array Mixed values
971 function checkSystemCompliance() {
972 global $sugar_config;
973 global $current_language;
977 if(!defined('SUGARCRM_MIN_MEM')) {
978 define('SUGARCRM_MIN_MEM', 40);
981 $installer_mod_strings = getModuleLanguagePack($current_language, './install');
983 $ret['error_found'] = false;
986 $php_version = constant('PHP_VERSION');
987 $check_php_version_result = check_php_version($php_version);
989 switch($check_php_version_result) {
991 $ret['phpVersion'] = "<b><span class=stop>{$installer_mod_strings['ERR_CHECKSYS_PHP_INVALID_VER']} {$php_version} )</span></b>";
992 $ret['error_found'] = true;
995 $ret['phpVersion'] = "<b><span class=go>{$installer_mod_strings['ERR_CHECKSYS_PHP_UNSUPPORTED']} {$php_version} )</span></b>";
998 $ret['phpVersion'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_PHP_OK']} {$php_version} )</span></b>";
1002 // database and connect
1003 $canInstall = $db->canInstall();
1004 if ($canInstall !== true)
1006 $ret['error_found'] = true;
1007 if (count($canInstall) == 1)
1009 $ret['dbVersion'] = "<b><span class=stop>" . $installer_mod_strings[$canInstall[0]] . "</span></b>";
1013 $ret['dbVersion'] = "<b><span class=stop>" . sprintf($installer_mod_strings[$canInstall[0]], $canInstall[1]) . "</span></b>";
1018 if(function_exists('xml_parser_create')) {
1019 $ret['xmlStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1021 $ret['xmlStatus'] = "<b><span class=stop>{$installer_mod_strings['LBL_CHECKSYS_NOT_AVAILABLE']}</span></b>";
1022 $ret['error_found'] = true;
1026 if(function_exists('curl_init')) {
1027 $ret['curlStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1029 $ret['curlStatus'] = "<b><span class=go>{$installer_mod_strings['ERR_CHECKSYS_CURL']}</span></b>";
1030 $ret['error_found'] = false;
1034 if(function_exists('mb_strlen')) {
1035 $ret['mbstringStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1037 $ret['mbstringStatus'] = "<b><span class=stop>{$installer_mod_strings['ERR_CHECKSYS_MBSTRING']}</span></b>";
1038 $ret['error_found'] = true;
1042 if(function_exists('imap_open')) {
1043 $ret['imapStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1045 $ret['imapStatus'] = "<b><span class=go>{$installer_mod_strings['ERR_CHECKSYS_IMAP']}</span></b>";
1046 $ret['error_found'] = false;
1051 if('1' == ini_get('safe_mode')) {
1052 $ret['safeModeStatus'] = "<b><span class=stop>{$installer_mod_strings['ERR_CHECKSYS_SAFE_MODE']}</span></b>";
1053 $ret['error_found'] = true;
1055 $ret['safeModeStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1059 // call time pass by ref
1060 if('1' == ini_get('allow_call_time_pass_reference')) {
1061 $ret['callTimeStatus'] = "<b><span class=stop>{$installer_mod_strings['ERR_CHECKSYS_CALL_TIME']}</span></b>";
1062 //continue upgrading
1064 $ret['callTimeStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1068 $ret['memory_msg'] = "";
1069 $memory_limit = "-1";//ini_get('memory_limit');
1070 $sugarMinMem = constant('SUGARCRM_MIN_MEM');
1071 // logic based on: http://us2.php.net/manual/en/ini.core.php#ini.memory-limit
1072 if( $memory_limit == "" ){ // memory_limit disabled at compile time, no memory limit
1073 $ret['memory_msg'] = "<b><span class=\"go\">{$installer_mod_strings['LBL_CHECKSYS_MEM_OK']}</span></b>";
1074 } elseif( $memory_limit == "-1" ){ // memory_limit enabled, but set to unlimited
1075 $ret['memory_msg'] = "<b><span class=\"go\">{$installer_mod_strings['LBL_CHECKSYS_MEM_UNLIMITED']}</span></b>";
1077 rtrim($memory_limit, 'M');
1078 $memory_limit_int = (int) $memory_limit;
1079 if( $memory_limit_int < constant('SUGARCRM_MIN_MEM') ){
1080 $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>";
1081 $ret['error_found'] = true;
1083 $ret['memory_msg'] = "<b><span class=\"go\">{$installer_mod_strings['LBL_CHECKSYS_OK']} ({$memory_limit})</span></b>";
1087 if (!class_exists("ZipArchive"))
1089 $ret['ZipStatus'] = "<b><span class=stop>{$installer_mod_strings['ERR_CHECKSYS_ZIP']}</span></b>";
1090 $ret['error_found'] = true;
1092 $ret['ZipStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1097 /* mbstring.func_overload
1098 $ret['mbstring.func_overload'] = '';
1099 $mb = ini_get('mbstring.func_overload');
1102 $ret['mbstring.func_overload'] = "<b><span class=\"stop\">{$mod_strings['ERR_UW_MBSTRING_FUNC_OVERLOAD']}</b>";
1103 $ret['error_found'] = true;
1111 * is a file that we blow away automagically
1113 function isAutoOverwriteFile($file) {
1114 $overwriteDirs = array(
1115 './sugar_version.php',
1116 './modules/UpgradeWizard/uw_main.tpl',
1118 $file = trim('.'.str_replace(clean_path(getcwd()), '', $file));
1120 if(in_array($file, $overwriteDirs)) {
1124 $fileExtension = substr(strrchr($file, "."), 1);
1125 if($fileExtension == 'tpl' || $fileExtension == 'html') {
1135 function logThis($entry, $path='') {
1136 global $mod_strings;
1137 if(file_exists('include/utils/sugar_file_utils.php')){
1138 require_once('include/utils/sugar_file_utils.php');
1140 $log = empty($path) ? clean_path(getcwd().'/upgradeWizard.log') : clean_path($path);
1142 // create if not exists
1143 if(!file_exists($log)) {
1144 if(function_exists('sugar_fopen')){
1145 $fp = @sugar_fopen($log, 'w+'); // attempts to create file
1148 $fp = fopen($log, 'w+'); // attempts to create file
1150 if(!is_resource($fp)) {
1151 $GLOBALS['log']->fatal('UpgradeWizard could not create the upgradeWizard.log file');
1152 die($mod_strings['ERR_UW_LOG_FILE_UNWRITABLE']);
1155 if(function_exists('sugar_fopen')){
1156 $fp = @sugar_fopen($log, 'a+'); // write pointer at end of file
1159 $fp = @fopen($log, 'a+'); // write pointer at end of file
1162 if(!is_resource($fp)) {
1163 $GLOBALS['log']->fatal('UpgradeWizard could not open/lock upgradeWizard.log file');
1164 die($mod_strings['ERR_UW_LOG_FILE_UNWRITABLE']);
1168 $line = date('r').' [UpgradeWizard] - '.$entry."\n";
1170 if(@fwrite($fp, $line) === false) {
1171 $GLOBALS['log']->fatal('UpgradeWizard could not write to upgradeWizard.log: '.$entry);
1172 die($mod_strings['ERR_UW_LOG_FILE_UNWRITABLE']);
1175 if(is_resource($fp)) {
1183 * @desc This function is to be used in the upgrade process to preserve changes/customaizations made to pre 5.1 quickcreate layout.
1184 * 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
1185 * was automatically picked up by the quick create. [Addresses Bug 21469]
1186 * This function will check if customizations were made, and will create quickcreatedefs.php in the /cutom/working/$module_name directory.
1188 function updateQuickCreateDefs(){
1189 $d = dir('modules');
1190 $studio_modules = array();
1192 while($e = $d->read()){ //collect all studio modules.
1193 if(substr($e, 0, 1) == '.' || !is_dir('modules/' . $e))continue;
1194 if(file_exists('modules/' . $e . '/metadata/studio.php'))
1196 array_push($studio_modules, $e);
1200 foreach( $studio_modules as $modname ){ //for each studio enabled module
1201 //Check !exists modules/$modname/metadata/quickcreatedefs.php &&
1202 //exists custom/$modname/editviewdefs.php (module was customized) &&
1203 //!exists custom/$modname/quickcreateviewdefs.php
1205 $editviewdefs = "custom/working/modules/".$modname."/metadata/editviewdefs.php";
1206 $quickcreatedefs = "custom/working/modules/".$modname."/metadata/quickcreatedefs.php";
1208 if ( !file_exists("modules/".$modname."/metadata/quickcreatedefs.php") &&
1209 file_exists($editviewdefs) &&
1210 !file_exists($quickcreatedefs) ){
1211 //clone editviewdef and save it in custom/working/modules/metadata
1212 $GLOBALS['log']->debug("Copying editviewdefs.php as quickcreatedefs.php for the $modname module in custom/working/modules/$modname/metadata!");
1213 if(copy( $editviewdefs, $quickcreatedefs)){
1214 if(file_exists($quickcreatedefs) && is_readable($quickcreatedefs)){
1215 $file = file($quickcreatedefs);
1216 //replace 'EditView' with 'QuickCreate'
1217 $fp = fopen($quickcreatedefs,'w');
1218 foreach($file as &$line){
1219 if(preg_match('/^\s*\'EditView\'\s*=>\s*$/', $line) > 0){
1220 $line = "'QuickCreate' =>\n";
1228 $GLOBALS['log']->debug("Failed to replace 'EditView' with QuickCreate because $quickcreatedefs is either not readable or does not exist.");
1231 $GLOBALS['log']->debug("Failed to copy $editviewdefs to $quickcreatedefs!");
1238 * test perms for CREATE queries
1240 function testPermsCreate($db, $out) {
1241 logThis('Checking CREATE TABLE permissions...');
1242 global $mod_strings;
1244 if(!$db->checkPrivilege("CREATE TABLE")) {
1245 logThis('cannot CREATE TABLE!');
1246 $out['db']['dbNoCreate'] = true;
1247 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_CREATE']}</span></td></tr>";
1253 * test perms for INSERT
1255 function testPermsInsert($db, $out, $skip=false) {
1256 logThis('Checking INSERT INTO permissions...');
1257 global $mod_strings;
1259 if(!$db->checkPrivilege("INSERT")) {
1260 logThis('cannot INSERT INTO!');
1261 $out['db']['dbNoInsert'] = true;
1262 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_INSERT']}</span></td></tr>";
1269 * test perms for UPDATE TABLE
1271 function testPermsUpdate($db, $out, $skip=false) {
1272 logThis('Checking UPDATE TABLE permissions...');
1273 global $mod_strings;
1274 if(!$db->checkPrivilege("UPDATE")) {
1275 logThis('cannot UPDATE TABLE!');
1276 $out['db']['dbNoUpdate'] = true;
1277 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_UPDATE']}</span></td></tr>";
1284 * test perms for SELECT
1286 function testPermsSelect($db, $out, $skip=false) {
1287 logThis('Checking SELECT permissions...');
1288 global $mod_strings;
1289 if(!$db->checkPrivilege("SELECT")) {
1290 logThis('cannot SELECT!');
1291 $out['db']['dbNoSelect'] = true;
1292 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_SELECT']}</span></td></tr>";
1298 * test perms for DELETE
1300 function testPermsDelete($db, $out, $skip=false) {
1301 logThis('Checking DELETE FROM permissions...');
1302 global $mod_strings;
1303 if(!$db->checkPrivilege("DELETE")) {
1304 logThis('cannot DELETE FROM!');
1305 $out['db']['dbNoDelete'] = true;
1306 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_DELETE']}</span></td></tr>";
1313 * test perms for ALTER TABLE ADD COLUMN
1315 function testPermsAlterTableAdd($db, $out, $skip=false) {
1316 logThis('Checking ALTER TABLE ADD COLUMN permissions...');
1317 global $mod_strings;
1318 if(!$db->checkPrivilege("ADD COLUMN")) {
1319 logThis('cannot ADD COLUMN!');
1320 $out['db']['dbNoAddColumn'] = true;
1321 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_ADD_COLUMN']}</span></td></tr>";
1327 * test perms for ALTER TABLE ADD COLUMN
1329 function testPermsAlterTableChange($db, $out, $skip=false) {
1330 logThis('Checking ALTER TABLE CHANGE COLUMN permissions...');
1331 global $mod_strings;
1332 if(!$db->checkPrivilege("CHANGE COLUMN")) {
1333 logThis('cannot CHANGE COLUMN!');
1334 $out['db']['dbNoChangeColumn'] = true;
1335 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_CHANGE_COLUMN']}</span></td></tr>";
1341 * test perms for ALTER TABLE DROP COLUMN
1343 function testPermsAlterTableDrop($db, $out, $skip=false) {
1344 logThis('Checking ALTER TABLE DROP COLUMN permissions...');
1345 global $mod_strings;
1346 if(!$db->checkPrivilege("DROP COLUMN")) {
1347 logThis('cannot DROP COLUMN!');
1348 $out['db']['dbNoDropColumn'] = true;
1349 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_DROP_COLUMN']}</span></td></tr>";
1356 * test perms for DROP TABLE
1358 function testPermsDropTable($db, $out, $skip=false) {
1359 logThis('Checking DROP TABLE permissions...');
1360 global $mod_strings;
1361 if(!$db->checkPrivilege("DROP TABLE")) {
1362 logThis('cannot DROP TABLE!');
1363 $out['db']['dbNoDropTable'] = true;
1364 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_DROP_TABLE']}</span></td></tr>";
1369 function getFormattedError($error, $query) {
1370 $error = "<div><b>".$error;
1371 $error .= "</b>::{$query}</div>";
1377 * parses a query finding the table name
1378 * @param string query The query
1379 * @return string table The table
1381 function getTableFromQuery($query) {
1382 $standardQueries = array('ALTER TABLE', 'DROP TABLE', 'CREATE TABLE', 'INSERT INTO', 'UPDATE', 'DELETE FROM');
1383 $query = preg_replace("/[^A-Za-z0-9\_\s]/", "", $query);
1384 $query = trim(str_replace($standardQueries, '', $query));
1386 $firstSpc = strpos($query, " ");
1387 $end = ($firstSpc > 0) ? $firstSpc : strlen($query);
1388 $table = substr($query, 0, $end);
1395 function preLicenseCheck() {
1396 require_once('modules/UpgradeWizard/uw_files.php');
1398 global $sugar_config;
1399 global $mod_strings;
1400 global $sugar_version;
1402 if(!isset($sugar_version) || empty($sugar_version)) {
1403 require_once('./sugar_version.php');
1406 if(!isset($_SESSION['unzip_dir']) || empty($_SESSION['unzip_dir'])) {
1407 logThis('unzipping files in upgrade archive...');
1409 list($base_upgrade_dir, $base_tmp_upgrade_dir) = getUWDirs();
1411 //also come up with mechanism to read from upgrade-progress file
1412 if(!isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !is_file($_SESSION['install_file'])) {
1413 if (file_exists(clean_path($base_tmp_upgrade_dir)) && $handle = opendir(clean_path($base_tmp_upgrade_dir))) {
1414 while (false !== ($file = readdir($handle))) {
1415 if($file !="." && $file !="..") {
1416 if(is_file($base_tmp_upgrade_dir."/".$file."/manifest.php")){
1417 require_once($base_tmp_upgrade_dir."/".$file."/manifest.php");
1418 $package_name= $manifest['copy_files']['from_dir'];
1419 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")){
1420 $unzip_dir = $base_tmp_upgrade_dir."/".$file;
1421 if(file_exists("$base_upgrade_dir/patch/".$package_name.'.zip')){
1422 $_SESSION['install_file'] = $package_name.".zip";
1431 if(empty($_SESSION['install_file'])){
1432 unlinkUWTempFiles();
1434 echo 'Upload File not found so redirecting to Upgrade Start ';
1435 $redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
1436 echo '<form name="redirect" action="' .$redirect_new_wizard. '" method="POST">';
1437 $upgrade_directories_not_found =<<<eoq
1438 <table cellpadding="3" cellspacing="0" border="0">
1440 <th colspan="2" align="left">
1441 <span class='error'><b>'Upload file missing or has been deleted. Refresh the page to go back to UpgradeWizard start'</b></span>
1446 $uwMain = $upgrade_directories_not_found;
1449 $install_file = "$base_upgrade_dir/patch/".basename(urldecode( $_SESSION['install_file'] ));
1451 if(empty($unzip_dir)){
1452 $unzip_dir = mk_temp_dir( $base_tmp_upgrade_dir );
1454 $zip_from_dir = ".";
1456 $zip_force_copy = array();
1459 logThis('Could not create a temporary directory using mk_temp_dir( $base_tmp_upgrade_dir )');
1460 die($mod_strings['ERR_UW_NO_CREATE_TMP_DIR']);
1463 //double check whether unzipped .
1464 if(file_exists($unzip_dir ."/scripts") && file_exists($unzip_dir."/manifest.php")){
1468 unzip( $install_file, $unzip_dir );
1471 // assumption -- already validated manifest.php at time of upload
1472 require_once( "$unzip_dir/manifest.php" );
1474 if( isset( $manifest['copy_files']['from_dir'] ) && $manifest['copy_files']['from_dir'] != "" ){
1475 $zip_from_dir = $manifest['copy_files']['from_dir'];
1477 if( isset( $manifest['copy_files']['to_dir'] ) && $manifest['copy_files']['to_dir'] != "" ){
1478 $zip_to_dir = $manifest['copy_files']['to_dir'];
1480 if( isset( $manifest['copy_files']['force_copy'] ) && $manifest['copy_files']['force_copy'] != "" ){
1481 $zip_force_copy = $manifest['copy_files']['force_copy'];
1483 if( isset( $manifest['version'] ) ){
1484 $version = $manifest['version'];
1486 if( !is_writable( "config.php" ) ){
1487 return $mod_strings['ERR_UW_CONFIG'];
1490 $_SESSION['unzip_dir'] = clean_path($unzip_dir);
1491 $_SESSION['zip_from_dir'] = clean_path($zip_from_dir);
1492 logThis('unzip done.');
1494 $unzip_dir = $_SESSION['unzip_dir'];
1495 $zip_from_dir = $_SESSION['zip_from_dir'];
1498 //check if $_SESSION['unzip_dir'] and $_SESSION['zip_from_dir'] exist
1499 if(!isset($_SESSION['unzip_dir']) || !file_exists($_SESSION['unzip_dir'])
1500 || !isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !file_exists($_SESSION['install_file'])){
1502 unlinkUWTempFiles();
1504 echo 'Upload File not found so redirecting to Upgrade Start ';
1505 $redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
1506 echo '<form name="redirect" action="' .$redirect_new_wizard. '" method="POST">';
1507 $upgrade_directories_not_found =<<<eoq
1508 <table cellpadding="3" cellspacing="0" border="0">
1510 <th colspan="2" align="left">
1511 <span class='error'><b>'Upload file missing or has been deleted. Refresh the page to go back to UpgradeWizard start'</b></span>
1516 $uwMain = $upgrade_directories_not_found;
1520 logThis ('is SugarConfig there '.file_exists(clean_path($unzip_dir.'/'.$zip_from_dir."/include/SugarObjects/SugarConfig.php")));
1521 if(file_exists(clean_path($unzip_dir.'/'.$zip_from_dir."/include/SugarObjects/SugarConfig.php"))) {
1522 $file = clean_path($unzip_dir.'/'.$zip_from_dir."/include/SugarObjects/SugarConfig.php");
1523 $destFile = str_replace(clean_path($unzip_dir.'/'.$zip_from_dir), $cwd, $file);
1524 if(!is_dir(dirname($destFile))) {
1525 mkdir_recursive(dirname($destFile)); // make sure the directory exists
1527 copy($file,$destFile);
1528 //also copy include utils array utils
1529 $file = clean_path($unzip_dir.'/'.$zip_from_dir."/include/utils/array_utils.php");
1530 $destFile = str_replace(clean_path($unzip_dir.'/'.$zip_from_dir), $cwd, $file);
1531 if(!is_dir(dirname($destFile))) {
1532 mkdir_recursive(dirname($destFile)); // make sure the directory exists
1534 copy($file,$destFile);
1539 function preflightCheck() {
1540 require_once('modules/UpgradeWizard/uw_files.php');
1542 global $sugar_config;
1543 global $mod_strings;
1544 global $sugar_version;
1546 if(!isset($sugar_version) || empty($sugar_version)) {
1547 require_once('./sugar_version.php');
1550 unset($_SESSION['rebuild_relationships']);
1551 unset($_SESSION['rebuild_extensions']);
1553 // don't bother if are rechecking
1554 $manualDiff = array();
1555 if(!isset($_SESSION['unzip_dir']) || empty($_SESSION['unzip_dir'])) {
1556 logThis('unzipping files in upgrade archive...');
1558 list($base_upgrade_dir, $base_tmp_upgrade_dir) = getUWDirs();
1560 //Following is if User logged out unexpectedly and then logged into UpgradeWizard again.
1561 //also come up with mechanism to read from upgrade-progress file.
1562 if(!isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !is_file($_SESSION['install_file'])) {
1563 if (file_exists($base_tmp_upgrade_dir) && $handle = opendir($base_tmp_upgrade_dir)) {
1564 while (false !== ($file = readdir($handle))) {
1565 if($file !="." && $file !="..") {
1566 if(is_file($base_tmp_upgrade_dir."/".$file."/manifest.php")){
1567 require_once($base_tmp_upgrade_dir."/".$file."/manifest.php");
1568 $package_name= $manifest['copy_files']['from_dir'];
1569 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")){
1570 $unzip_dir = $base_tmp_upgrade_dir."/".$file;
1571 if(file_exists("$base_upgrade_dir/patch/".$package_name.'.zip')){
1572 $_SESSION['install_file'] = $package_name.".zip";
1581 if(empty($_SESSION['install_file'])){
1582 unlinkUWTempFiles();
1584 echo 'Upload File not found so redirecting to Upgrade Start ';
1585 $redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
1586 echo '<form name="redirect" action="' .$redirect_new_wizard. '" method="POST">';
1587 $upgrade_directories_not_found =<<<eoq
1588 <table cellpadding="3" cellspacing="0" border="0">
1590 <th colspan="2" align="left">
1591 <span class='error'><b>'Upload file missing or has been deleted. Refresh the page to go back to UpgradeWizard start'</b></span>
1596 $uwMain = $upgrade_directories_not_found;
1600 $install_file = "$base_upgrade_dir/patch/".basename(urldecode( $_SESSION['install_file'] ));
1602 if(empty($unzip_dir)){
1603 $unzip_dir = mk_temp_dir( $base_tmp_upgrade_dir );
1605 $zip_from_dir = ".";
1607 $zip_force_copy = array();
1610 logThis('Could not create a temporary directory using mk_temp_dir( $base_tmp_upgrade_dir )');
1611 die($mod_strings['ERR_UW_NO_CREATE_TMP_DIR']);
1614 //double check whether unzipped .
1615 if(file_exists($unzip_dir ."/scripts") && file_exists($unzip_dir."/manifest.php")){
1619 unzip( $install_file, $unzip_dir );
1622 // assumption -- already validated manifest.php at time of upload
1623 require_once( "$unzip_dir/manifest.php" );
1625 if( isset( $manifest['copy_files']['from_dir'] ) && $manifest['copy_files']['from_dir'] != "" ){
1626 $zip_from_dir = $manifest['copy_files']['from_dir'];
1628 if( isset( $manifest['copy_files']['to_dir'] ) && $manifest['copy_files']['to_dir'] != "" ){
1629 $zip_to_dir = $manifest['copy_files']['to_dir'];
1631 if( isset( $manifest['copy_files']['force_copy'] ) && $manifest['copy_files']['force_copy'] != "" ){
1632 $zip_force_copy = $manifest['copy_files']['force_copy'];
1634 if( isset( $manifest['version'] ) ){
1635 $version = $manifest['version'];
1637 if( !is_writable( "config.php" ) ){
1638 return $mod_strings['ERR_UW_CONFIG'];
1641 $_SESSION['unzip_dir'] = clean_path($unzip_dir);
1642 $_SESSION['zip_from_dir'] = clean_path($zip_from_dir);
1644 //logThis('unzip done.');
1646 $unzip_dir = $_SESSION['unzip_dir'];
1647 $zip_from_dir = $_SESSION['zip_from_dir'];
1649 //check if $_SESSION['unzip_dir'] and $_SESSION['zip_from_dir'] exist
1650 if(!isset($_SESSION['unzip_dir']) || !file_exists($_SESSION['unzip_dir'])
1651 || !isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !file_exists($_SESSION['install_file'])){
1653 unlinkUWTempFiles();
1655 echo 'Upload File not found so redirecting to Upgrade Start ';
1656 $redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
1657 echo '<form name="redirect" action="' .$redirect_new_wizard. '" method="POST">';
1658 $upgrade_directories_not_found =<<<eoq
1659 <table cellpadding="3" cellspacing="0" border="0">
1661 <th colspan="2" align="left">
1662 <span class='error'><b>'Upload file missing or has been deleted. Refresh the page to go back to UpgradeWizard start'</b></span>
1667 $uwMain = $upgrade_directories_not_found;
1670 //copy minimum required files
1671 fileCopy('include/utils/sugar_file_utils.php');
1673 $upgradeFiles = findAllFiles(clean_path("$unzip_dir/$zip_from_dir"), array());
1674 $cache_html_files= array();
1677 $md5_string = array();
1678 if(file_exists(clean_path(getcwd().'/files.md5'))){
1679 require(clean_path(getcwd().'/files.md5'));
1682 // file preflight checks
1683 logThis('verifying md5 checksums for files...');
1684 foreach($upgradeFiles as $file) {
1685 if(in_array(str_replace(clean_path("$unzip_dir/$zip_from_dir") . "/", '', $file), $uw_files))
1686 continue; // skip already loaded files
1688 if(strpos($file, '.md5'))
1689 continue; // skip md5 file
1691 // normalize file paths
1692 $file = clean_path($file);
1694 // check that we can move/delete the upgraded file
1695 if(!is_writable($file)) {
1696 $errors[] = $mod_strings['ERR_UW_FILE_NOT_WRITABLE'].": ".$file;
1698 // check that destination files are writable
1699 $destFile = getcwd().str_replace(clean_path($unzip_dir.'/'.$zip_from_dir), '', $file);
1701 if(is_file($destFile)) { // of course it needs to exist first...
1702 if(!is_writable($destFile)) {
1703 $errors[] = $mod_strings['ERR_UW_FILE_NOT_WRITABLE'].": ".$destFile;
1707 ///////////////////////////////////////////////////////////////////////
1709 // compare md5s and build up a manual merge list
1710 $targetFile = clean_path(".".str_replace(getcwd(),'',$destFile));
1712 if(is_file($destFile)) {
1713 if(strpos($targetFile, '.php')) {
1714 // handle PHP files that were hit with the security regex
1716 if(function_exists('sugar_fopen')){
1717 $fp = sugar_fopen($destFile, 'r');
1720 $fp = fopen($destFile, 'r');
1722 $filesize = filesize($destFile);
1724 $fileContents = stream_get_contents($fp);
1725 $targetMd5 = md5($fileContents);
1728 $targetMd5 = md5_file($destFile);
1732 if(isset($md5_string[$targetFile]) && $md5_string[$targetFile] != $targetMd5) {
1733 logThis('found a file with a differing md5: ['.$targetFile.']');
1734 $manualDiff[] = $destFile;
1737 ///////////////////////////////////////////////////////////////////////
1739 logThis('md5 verification done.');
1740 $errors['manual'] = $manualDiff;
1745 function fileCopy($file_path){
1746 if(file_exists(clean_path($_SESSION['unzip_dir'].'/'.$_SESSION['zip_from_dir'].'/'.$file_path))) {
1747 $file = clean_path($_SESSION['unzip_dir'].'/'.$_SESSION['zip_from_dir'].'/'.$file_path);
1748 $destFile = str_replace(clean_path($_SESSION['unzip_dir'].'/'.$_SESSION['zip_from_dir']), clean_path(getcwd()), $file);
1749 if(!is_dir(dirname($destFile))) {
1750 mkdir_recursive(dirname($destFile)); // make sure the directory exists
1752 copy_recursive($file,$destFile);
1755 function getChecklist($steps, $step) {
1756 global $mod_strings;
1758 $skip = array('start', 'cancel', 'uninstall','end');
1761 $ret = '<table cellpadding="3" cellspacing="4" border="0">';
1762 $ret .= '<tr><th colspan="3" align="left">'.$mod_strings['LBL_UW_CHECKLIST'].':</th></tr>';
1763 foreach($steps['desc'] as $k => $desc) {
1764 if(in_array($steps['files'][$j], $skip)) {
1769 //$status = "<span class='error'>{$mod_strings['LBL_UW_INCOMPLETE']}</span>";
1771 $desc_mod_post = '';
1773 if(isset($_SESSION['step'][$steps['files'][$k]]) && $_SESSION['step'][$steps['files'][$k]] == 'success') {
1774 //$status = $mod_strings['LBL_UW_COMPLETE'];
1778 if($k == $_REQUEST['step']) {
1779 //$status = $mod_strings['LBL_UW_IN_PROGRESS'];
1780 $desc_mod_pre = "<font color=blue><i>";
1781 $desc_mod_post = "</i></font>";
1784 $ret .= "<tr><td> </td><td><b>{$i}: {$desc_mod_pre}{$desc}{$desc_mod_post}</b></td>";
1785 $ret .= "<td id={$steps['files'][$j]}><i></i></td></tr>";
1793 function prepSystemForUpgrade() {
1794 global $sugar_config;
1795 global $sugar_flavor;
1796 global $mod_strings;
1798 global $base_upgrade_dir;
1799 global $base_tmp_upgrade_dir;
1800 list($p_base_upgrade_dir, $p_base_tmp_upgrade_dir) = getUWDirs();
1801 ///////////////////////////////////////////////////////////////////////////////
1802 //// Make sure variables exist
1803 if(empty($base_upgrade_dir)){
1804 $base_upgrade_dir = $p_base_upgrade_dir;
1806 if(empty($base_tmp_upgrade_dir)){
1807 $base_tmp_upgrade_dir = $p_base_tmp_upgrade_dir;
1809 sugar_mkdir($base_tmp_upgrade_dir, 0775, true);
1810 if(!isset($subdirs) || empty($subdirs)){
1811 $subdirs = array('full', 'langpack', 'module', 'patch', 'theme');
1814 $upgrade_progress_dir = $base_tmp_upgrade_dir;
1815 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
1816 if(file_exists($upgrade_progress_file)){
1817 if(function_exists('get_upgrade_progress') && function_exists('didThisStepRunBefore')){
1818 if(didThisStepRunBefore('end')){
1819 include($upgrade_progress_file);
1820 unset($upgrade_config);
1821 unlink($upgrade_progress_file);
1826 // increase the cuttoff time to 1 hour
1827 ini_set("max_execution_time", "3600");
1829 // make sure dirs exist
1830 if($subdirs != null){
1831 foreach($subdirs as $subdir) {
1832 sugar_mkdir("$base_upgrade_dir/$subdir", 0775, true);
1835 // array of special scripts that are executed during (un)installation-- key is type of script, value is filename
1836 if(!defined('SUGARCRM_PRE_INSTALL_FILE')) {
1837 define('SUGARCRM_PRE_INSTALL_FILE', 'scripts/pre_install.php');
1838 define('SUGARCRM_POST_INSTALL_FILE', 'scripts/post_install.php');
1839 define('SUGARCRM_PRE_UNINSTALL_FILE', 'scripts/pre_uninstall.php');
1840 define('SUGARCRM_POST_UNINSTALL_FILE', 'scripts/post_uninstall.php');
1843 $script_files = array(
1844 "pre-install" => constant('SUGARCRM_PRE_INSTALL_FILE'),
1845 "post-install" => constant('SUGARCRM_POST_INSTALL_FILE'),
1846 "pre-uninstall" => constant('SUGARCRM_PRE_UNINSTALL_FILE'),
1847 "post-uninstall" => constant('SUGARCRM_POST_UNINSTALL_FILE'),
1850 // check that the upload limit is set to 6M or greater
1851 define('SUGARCRM_MIN_UPLOAD_MAX_FILESIZE_BYTES', 6 * 1024 * 1024); // 6 Megabytes
1852 $upload_max_filesize = ini_get('upload_max_filesize');
1853 $upload_max_filesize_bytes = return_bytes($upload_max_filesize);
1855 if($upload_max_filesize_bytes < constant('SUGARCRM_MIN_UPLOAD_MAX_FILESIZE_BYTES')) {
1856 $GLOBALS['log']->debug("detected upload_max_filesize: $upload_max_filesize");
1858 echo '<p class="error">'.$mod_strings['MSG_INCREASE_UPLOAD_MAX_FILESIZE'].' '.get_cfg_var('cfg_file_path')."</p>\n";
1862 if ( !function_exists('extractFile') ) {
1863 function extractFile($zip_file, $file_in_zip) {
1864 global $base_tmp_upgrade_dir;
1867 $absolute_base_tmp_upgrade_dir = clean_path($base_tmp_upgrade_dir);
1868 $relative_base_tmp_upgrade_dir = clean_path(str_replace(clean_path(getcwd()), '', $absolute_base_tmp_upgrade_dir));
1870 // mk_temp_dir expects relative pathing
1871 $my_zip_dir = mk_temp_dir($relative_base_tmp_upgrade_dir);
1873 unzip_file($zip_file, $file_in_zip, $my_zip_dir);
1875 return("$my_zip_dir/$file_in_zip");
1879 if ( !function_exists('extractManifest') ) {
1880 function extractManifest($zip_file) {
1881 logThis('extracting manifest.');
1882 return(extractFile($zip_file, "manifest.php"));
1886 if ( !function_exists('getInstallType') ) {
1887 function getInstallType($type_string) {
1890 $subdirs = array('full', 'langpack', 'module', 'patch', 'theme', 'temp');
1891 foreach($subdirs as $subdir) {
1892 if(preg_match("#/$subdir/#", $type_string)) {
1896 // return empty if no match
1901 function getImageForType($type) {
1903 global $mod_strings;
1908 $icon = SugarThemeRegistry::current()->getImage("Upgrade", "",null,null,'.gif',$mod_strings['LBL_UPGRADE']);
1911 $icon = SugarThemeRegistry::current()->getImage("LanguagePacks", "",null,null,'.gif',$mod_strings['LBL_LANGPACKS']);
1914 $icon = SugarThemeRegistry::current()->getImage("ModuleLoader", "",null,null,'.gif',$mod_strings['LBL_MODULELOADER']);
1917 $icon = SugarThemeRegistry::current()->getImage("PatchUpgrades", "",null,null,'.gif',$mod_strings['LBL_PATCHUPGRADES']);
1920 $icon = SugarThemeRegistry::current()->getImage("Themes", "",null,null,'.gif',$mod_strings['LBL_THEMES']);
1928 if ( !function_exists('getLanguagePackName') ) {
1929 function getLanguagePackName($the_file) {
1930 require_once("$the_file");
1931 if(isset($app_list_strings["language_pack_name"])) {
1932 return($app_list_strings["language_pack_name"]);
1938 function getUITextForType($type) {
1939 if($type == "full") {
1940 return("Full Upgrade");
1942 if($type == "langpack") {
1943 return("Language Pack");
1945 if($type == "module") {
1948 if($type == "patch") {
1951 if($type == "theme") {
1956 if ( !function_exists('validate_manifest') ) {
1958 * Verifies a manifest from a patch or module to be compatible with the current Sugar version and flavor
1959 * @param array manifest Standard manifest array
1960 * @return string Error message, blank on success
1962 function validate_manifest($manifest) {
1963 logThis('validating manifest.php file');
1964 // takes a manifest.php manifest array and validates contents
1966 global $sugar_version;
1967 global $sugar_flavor;
1968 global $mod_strings;
1970 if(!isset($manifest['type'])) {
1971 return $mod_strings['ERROR_MANIFEST_TYPE'];
1974 $type = $manifest['type'];
1976 if(getInstallType("/$type/") == "") {
1977 return $mod_strings['ERROR_PACKAGE_TYPE']. ": '" . $type . "'.";
1980 if(isset($manifest['acceptable_sugar_versions'])) {
1981 $version_ok = false;
1982 $matches_empty = true;
1983 if(isset($manifest['acceptable_sugar_versions']['exact_matches'])) {
1984 $matches_empty = false;
1985 foreach($manifest['acceptable_sugar_versions']['exact_matches'] as $match) {
1986 if($match == $sugar_version) {
1991 if(!$version_ok && isset($manifest['acceptable_sugar_versions']['regex_matches'])) {
1992 $matches_empty = false;
1993 foreach($manifest['acceptable_sugar_versions']['regex_matches'] as $match) {
1994 if(preg_match("/$match/", $sugar_version)) {
2000 if(!$matches_empty && !$version_ok) {
2001 return $mod_strings['ERROR_VERSION_INCOMPATIBLE']."<br />".
2002 $mod_strings['ERR_UW_VERSION'].$sugar_version;
2006 if(isset($manifest['acceptable_sugar_flavors']) && sizeof($manifest['acceptable_sugar_flavors']) > 0) {
2008 foreach($manifest['acceptable_sugar_flavors'] as $match) {
2009 if($match == $sugar_flavor) {
2014 return $mod_strings['ERROR_FLAVOR_INCOMPATIBLE']."<br />".
2015 $mod_strings['ERR_UW_FLAVOR'].$sugar_flavor."<br />".
2016 $mod_strings['ERR_UW_FLAVOR_2'].$manifest['acceptable_sugar_flavors'][0];
2024 function unlinkUploadFiles() {
2026 // logThis('at unlinkUploadFiles()');
2028 // if(isset($_SESSION['install_file']) && !empty($_SESSION['install_file'])) {
2029 // $upload = $_SESSION['install_file'];
2031 // if(is_file($upload)) {
2032 // logThis('unlinking ['.$upload.']');
2033 // @unlink($upload);
2039 * deletes files created by unzipping a package
2041 function unlinkUWTempFiles() {
2042 global $sugar_config;
2045 logThis('at unlinkUWTempFiles()');
2047 list($upgDir, $tempDir) = getUWDirs();
2049 if(file_exists($tempDir) && is_dir($tempDir)){
2050 $files = findAllFiles($tempDir, array(), false);
2052 foreach($files as $file) {
2053 if(!is_dir($file)) {
2054 //logThis('unlinking ['.$file.']', $path);
2059 $files = findAllFiles($tempDir, array(), true);
2060 foreach($files as $dir) {
2062 //logThis('removing dir ['.$dir.']', $path);
2066 $cacheFile = sugar_cached("modules/UpgradeWizard/_persistence.php");
2067 if(is_file($cacheFile)) {
2068 logThis("Unlinking Upgrade cache file: '_persistence.php'", $path);
2069 @unlink($cacheFile);
2072 logThis("finished!");
2076 * finds all files in the passed path, but skips select directories
2077 * @param string dir Relative path
2078 * @param array the_array Collections of found files/dirs
2079 * @param bool include_dir True if we want to include directories in the
2080 * returned collection
2082 function uwFindAllFiles($dir, $theArray, $includeDirs=false, $skipDirs=array(), $echo=false) {
2084 if (whetherNeedToSkipDir($dir, $skipDirs))
2089 if (!is_dir($dir)) { return $theArray; } // Bug # 46035, just checking for valid dir
2091 if ($d === false) { return $theArray; } // Bug # 46035, more checking
2093 while($f = $d->read()) {
2094 // bug 40793 Skip Directories array in upgradeWizard does not function correctly
2095 if($f == "." || $f == ".." || whetherNeedToSkipDir("$dir/$f", $skipDirs)) { // skip *nix self/parent
2099 // for AJAX length count
2105 if(is_dir("$dir/$f")) {
2106 if($includeDirs) { // add the directory if flagged
2107 $theArray[] = clean_path("$dir/$f");
2111 $theArray = uwFindAllFiles("$dir/$f/", $theArray, $includeDirs, $skipDirs, $echo);
2113 $theArray[] = clean_path("$dir/$f");
2126 * unset's UW's Session Vars
2128 function resetUwSession() {
2129 logThis('resetting $_SESSION');
2131 if(isset($_SESSION['committed']))
2132 unset($_SESSION['committed']);
2133 if(isset($_SESSION['sugar_version_file']))
2134 unset($_SESSION['sugar_version_file']);
2135 if(isset($_SESSION['upgrade_complete']))
2136 unset($_SESSION['upgrade_complete']);
2137 if(isset($_SESSION['allTables']))
2138 unset($_SESSION['allTables']);
2139 if(isset($_SESSION['alterCustomTableQueries']))
2140 unset($_SESSION['alterCustomTableQueries']);
2141 if(isset($_SESSION['skip_zip_upload']))
2142 unset($_SESSION['skip_zip_upload']);
2143 if(isset($_SESSION['sugar_version_file']))
2144 unset($_SESSION['sugar_version_file']);
2145 if(isset($_SESSION['install_file']))
2146 unset($_SESSION['install_file']);
2147 if(isset($_SESSION['unzip_dir']))
2148 unset($_SESSION['unzip_dir']);
2149 if(isset($_SESSION['zip_from_dir']))
2150 unset($_SESSION['zip_from_dir']);
2151 if(isset($_SESSION['overwrite_files']))
2152 unset($_SESSION['overwrite_files']);
2153 if(isset($_SESSION['schema_change']))
2154 unset($_SESSION['schema_change']);
2155 if(isset($_SESSION['uw_restore_dir']))
2156 unset($_SESSION['uw_restore_dir']);
2157 if(isset($_SESSION['step']))
2158 unset($_SESSION['step']);
2159 if(isset($_SESSION['files']))
2160 unset($_SESSION['files']);
2161 if(isset($_SESSION['Upgraded451Wizard'])){
2162 unset($_SESSION['Upgraded451Wizard']);
2164 if(isset($_SESSION['Initial_451to500_Step'])){
2165 unset($_SESSION['Initial_451to500_Step']);
2167 if(isset($_SESSION['license_shown']))
2168 unset($_SESSION['license_shown']);
2169 if(isset($_SESSION['sugarMergeRunResults']))
2170 unset($_SESSION['sugarMergeRunResults']);
2174 * runs rebuild scripts
2176 function UWrebuild() {
2180 //CCL - Comment this block out, it is called in end.php
2181 logThis('Rebuilding everything...', $path);
2182 require_once('modules/Administration/QuickRepairAndRebuild.php');
2183 $randc = new RepairAndClear();
2184 $randc->repairAndClearAll(array('clearAll'),array(translate('LBL_ALL_MODULES')), false, false);
2186 $query = "DELETE FROM versions WHERE name='Rebuild Extensions'";
2188 logThis('Registering rebuild record: '.$query, $path);
2189 logThis('Rebuild done.', $path);
2191 // insert a new database row to show the rebuild extensions is done
2192 $id = create_guid();
2193 $gmdate = gmdate('Y-m-d H:i:s');
2194 $date_entered = db_convert("'$gmdate'", 'datetime');
2195 $query = 'INSERT INTO versions (id, deleted, date_entered, date_modified, modified_user_id, created_by, name, file_version, db_version) '
2196 . "VALUES ('$id', '0', $date_entered, $date_entered, '1', '1', 'Rebuild Extensions', '4.0.0', '4.0.0')";
2198 logThis('Registering rebuild record in versions table: '.$query, $path);
2201 function getCustomTables() {
2204 return $db->tablesLike('%_cstm');
2207 function alterCustomTables($customTables)
2212 function getAllTables() {
2214 return $db->getTablesArray();
2217 function printAlterTableSql($tables)
2219 $alterTableSql = '';
2221 foreach($tables as $table)
2222 $alterTableSql .= "ALTER TABLE " . $table . " CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;" . "\n";
2224 return $alterTableSql;
2227 function executeConvertTablesSql($tables)
2231 foreach($tables as $table){
2232 $query = "ALTER TABLE " . $table . " CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci";
2234 logThis("Sending query: ".$query);
2235 $db->query($query);//, true, "An error has occured while performing db query. See log file for details.<br>");
2241 function testThis() {
2242 $files = uwFindAllFiles(getcwd().'/test', array());
2244 $out = "<table cellpadding='1' cellspacing='0' border='0'>\n";
2247 foreach($files as $file) {
2248 $relativeFile = clean_path(str_replace(getcwd().'/test', '', $file));
2249 $relativeFile = ($relativeFile{0} == '/') ? substr($relativeFile, 1, strlen($relativeFile)) : $relativeFile;
2251 $relativePath = dirname($relativeFile);
2253 if($relativePath == $priorPath) { // same dir, new file
2254 $out .= "<tr><td>".basename($relativeFile)."</td></tr>";
2255 $priorPath = $relativePath;
2269 function testThis2($dir, $id=0, $hide=false) {
2270 global $mod_strings;
2272 $dh = opendir($dir);
2275 $doHide = ($hide) ? 'none' : '';
2276 $out = "<div id='{$id}' style='display:{$doHide};'>";
2277 $out .= "<table cellpadding='1' cellspacing='0' style='border:0px solid #ccc'>\n";
2279 while($file = readdir($dh)) {
2280 if($file == '.' || $file == '..' || $file == 'CVS' || $file == '.cvsignore')
2283 if(is_dir($path.'/'.$file)) {
2284 $file = $path.'/'.$file;
2285 $newI = create_guid();
2286 $out .= "<tr><td valign='top'><a href='javascript:toggleNwFiles(\"{$newI}\");'>".SugarThemeRegistry::current()->getImage("Workflow", "", null, null, ".gif", $mod_strings['LBL_WORKFLOW'])."</a></td>\n";
2287 $out .= "<td valign='top'><b><a href='javascript:toggleNwFiles(\"{$newI}\");'>".basename($file)."</a></b></td></tr>";
2288 $out .= "<tr><td></td><td valign='top'>".testThis2($file, $newI, true)."</td></tr>";
2290 $out .= "<tr><td valign='top'> </td>\n";
2291 $out .= "<td valign='top'>".basename($file)."</td></tr>";
2295 $out .= "</tr></table>";
2306 function testThis3(&$files, $id, $hide, $previousPath = '') {
2307 if(!is_array($files) || empty($files))
2312 global $mod_strings;
2313 // expecting full path here
2314 foreach($files as $k => $file) {
2315 $file = str_replace(getcwd(), '', $file);
2316 $path = dirname($file);
2317 $fileName = basename($file);
2319 if($fileName == 'CVS' || $fileName == '.cvsignore')
2322 if($path == $previousPath) { // same directory
2323 // new row for each file
2324 $out .= "<tr><td valign='top' align='left'> </td>";
2325 $out .= "<td valign='top' align='left'>{$fileName}</td></tr>";
2326 } else { // new directory
2328 $out .= "<tr><td valign='top'><a href='javascript:toggleNwFiles(\"{$newI}\");'>".SugarThemeRegistry::current()->getImage("Workflow", "", null, null, ".gif", $mod_strings['LBL_WORKFLOW'])."</a></td>\n";
2329 $out .= "<td valign='top'><b><a href='javascript:toggleNwFiles(\"{$newI}\");'>".$fileName."</a></b></td></tr>";
2330 $recurse = testThis3($files, $newI, true, $previousPath);
2331 $out .= "<tr><td></td><td valign='top'>".$recurse."</td></tr>";
2334 $previousPath = $path;
2336 $display = ($hide) ? 'none' : '';
2338 <div id="{$id}" style="display:{$display}">
2339 <table cellpadding='1' cellspacing='0' border='0' style='border:1px solid #ccc'>
2348 function testThis4($filePath, $fileNodes=array(), $fileName='') {
2349 $path = dirname($filePath);
2350 $file = basename($filePath);
2352 $exFile = explode('/', $path);
2354 foreach($exFile as $pathSegment) {
2355 if(is_array($fileNodes[$pathSegment])) { // path already processed
2357 } else { // newly found path
2358 $fileNodes[$pathSegment] = array();
2361 if($fileName != '') {
2362 $fileNodes[$pathSegment][] = $fileName;
2371 ///////////////////////////////////////////////////////////////////////////////
2372 //// SYSTEM CHECK FUNCTIONS
2374 * generates an array with all files in the SugarCRM root directory, skipping
2376 * @return array files Array of files with absolute paths
2378 function getFilesForPermsCheck() {
2379 global $sugar_config;
2381 logThis('Got JSON call to find all files...');
2382 $filesNotWritable = array();
2383 $filesNWPerms = array();
2385 // add directories here that should be skipped when doing file permissions checks (cache/upload is the nasty one)
2387 $sugar_config['upload_dir'],
2389 $files = uwFindAllFiles(".", array(), true, $skipDirs, true);
2394 * checks files for permissions
2395 * @param array files Array of files with absolute paths
2396 * @return string result of check
2398 function checkFiles($files, $echo=false) {
2399 global $mod_strings;
2400 $filesNotWritable = array();
2403 <a href='javascript:void(0); toggleNwFiles(\"filesNw\");'>{$mod_strings['LBL_UW_SHOW_NW_FILES']}</a>
2404 <div id='filesNw' style='display:none;'>
2405 <table cellpadding='3' cellspacing='0' border='0'>
2407 <th align='left'>{$mod_strings['LBL_UW_FILE']}</th>
2408 <th align='left'>{$mod_strings['LBL_UW_FILE_PERMS']}</th>
2409 <th align='left'>{$mod_strings['LBL_UW_FILE_OWNER']}</th>
2410 <th align='left'>{$mod_strings['LBL_UW_FILE_GROUP']}</th>
2413 $isWindows = is_windows();
2414 foreach($files as $file) {
2417 if(!is_writable_windows($file)) {
2418 logThis('WINDOWS: File ['.$file.'] not readable - saving for display');
2419 // don't warn yet - we're going to use this to check against replacement files
2420 // aw: commented out; it's a hack to allow upgrade wizard to continue on windows... will fix later
2421 /*$filesNotWritable[$i] = $file;
2422 $filesNWPerms[$i] = substr(sprintf('%o',fileperms($file)), -4);
2423 $filesOut .= "<tr>".
2424 "<td><span class='error'>{$file}</span></td>".
2425 "<td>{$filesNWPerms[$i]}</td>".
2426 "<td>".$mod_strings['ERR_UW_CANNOT_DETERMINE_USER']."</td>".
2427 "<td>".$mod_strings['ERR_UW_CANNOT_DETERMINE_GROUP']."</td>".
2431 if(!is_writable($file)) {
2432 logThis('File ['.$file.'] not writable - saving for display');
2433 // don't warn yet - we're going to use this to check against replacement files
2434 $filesNotWritable[$i] = $file;
2435 $filesNWPerms[$i] = substr(sprintf('%o',fileperms($file)), -4);
2436 $owner = posix_getpwuid(fileowner($file));
2437 $group = posix_getgrgid(filegroup($file));
2438 $filesOut .= "<tr>".
2439 "<td><span class='error'>{$file}</span></td>".
2440 "<td>{$filesNWPerms[$i]}</td>".
2441 "<td>".$owner['name']."</td>".
2442 "<td>".$group['name']."</td>".
2449 $filesOut .= '</table></div>';
2451 $errors['files']['filesNotWritable'] = (count($filesNotWritable) > 0) ? true : false;
2452 if(count($filesNotWritable) < 1) {
2453 $filesOut = "{$mod_strings['LBL_UW_FILE_NO_ERRORS']}";
2459 function deletePackageOnCancel(){
2460 global $mod_strings;
2461 global $sugar_config;
2462 list($base_upgrade_dir, $base_tmp_upgrade_dir) = getUWDirs();
2463 logThis('running delete');
2464 if(!isset($_SESSION['install_file']) || ($_SESSION['install_file'] == "")) {
2465 logThis('ERROR: trying to delete non-existent file: ['.$_REQUEST['install_file'].']');
2466 $error = $mod_strings['ERR_UW_NO_FILE_UPLOADED'];
2468 // delete file in upgrades/patch
2469 $delete_me = "$base_upgrade_dir/patch/".basename(urldecode( $_REQUEST['install_file'] ));
2470 if(@unlink($delete_me)) {
2471 //logThis('unlinking: '.$delete_me);
2472 $out = basename($delete_me).$mod_strings['LBL_UW_FILE_DELETED'];
2474 logThis('ERROR: could not delete ['.$delete_me.']');
2475 $error = $mod_strings['ERR_UW_FILE_NOT_DELETED'].$delete_me;
2478 if(!empty($error)) {
2479 $out = "<b><span class='error'>{$error}</span></b><br />";
2483 function handleExecuteSqlKeys($db, $tableName, $disable)
2485 if(empty($tableName)) return true;
2486 if(is_callable(array($db, "supports"))) {
2488 return $disable?$db->disableKeys($tableName):$db->enableKeys($tableName);
2491 $op = $disable?"DISABLE":"ENABLE";
2492 return $db->query("ALTER TABLE $tableName $op KEYS");
2496 function parseAndExecuteSqlFile($sqlScript,$forStepQuery='',$resumeFromQuery='')
2498 global $sugar_config;
2499 $alterTableSchema = '';
2500 $sqlErrors = array();
2501 if(!isset($_SESSION['sqlSkippedQueries'])){
2502 $_SESSION['sqlSkippedQueries'] = array();
2504 $db = DBManagerFactory::getInstance();
2505 $disable_keys = ($db->dbType == "mysql"); // have to use old way for now for upgrades
2506 if(strpos($resumeFromQuery,",") != false){
2507 $resumeFromQuery = explode(",",$resumeFromQuery);
2509 if(file_exists($sqlScript)) {
2510 $fp = fopen($sqlScript, 'r');
2511 $contents = stream_get_contents($fp);
2512 $anyScriptChanges =$contents;
2513 $resumeAfterFound = false;
2517 while($line = fgets($fp)) {
2518 if(strpos($line, '--') === false) {
2519 $completeLine .= " ".trim($line);
2520 if(strpos($line, ';') !== false) {
2522 $query = str_replace(';','',$completeLine);
2523 //if resume from query is not null then find out from where
2524 //it should start executing the query.
2526 if($query != null && $resumeFromQuery != null){
2527 if(!$resumeAfterFound){
2528 if(strpos($query,",") != false){
2529 $queArray = explode(",",$query);
2530 for($i=0;$i<sizeof($resumeFromQuery);$i++){
2531 if(strcasecmp(trim($resumeFromQuery[$i]),trim($queArray[$i]))==0){
2532 $resumeAfterFound = true;
2534 $resumeAfterFound = false;
2540 elseif(strcasecmp(trim($resumeFromQuery),trim($query))==0){
2541 $resumeAfterFound = true;
2544 if($resumeAfterFound){
2547 // if $count=1 means it is just found so skip the query. Run the next one
2548 if($query != null && $resumeAfterFound && $count >1){
2549 $tableName = getAlterTable($query);
2552 handleExecuteSqlKeys($db, $tableName, true);
2555 if($db->checkError()){
2556 //put in the array to use later on
2557 $_SESSION['sqlSkippedQueries'][] = $query;
2561 handleExecuteSqlKeys($db, $tableName, false);
2563 $progQuery[$forStepQuery]=$query;
2564 post_install_progress($progQuery,$action='set');
2567 elseif($query != null){
2568 $tableName = getAlterTable($query);
2571 handleExecuteSqlKeys($db, $tableName, true);
2576 handleExecuteSqlKeys($db, $tableName, false);
2578 $progQuery[$forStepQuery]=$query;
2579 post_install_progress($progQuery,$action='set');
2580 if($db->checkError()){
2581 //put in the array to use later on
2582 $_SESSION['sqlSkippedQueries'][] = $query;
2594 function getAlterTable($query){
2595 $query = strtolower($query);
2596 if (preg_match('/^\s*alter\s+table\s+/', $query)) {
2597 $sqlArray = explode(" ", $query);
2598 $key = array_search('table', $sqlArray);
2599 return $sqlArray[($key+1)];
2605 function set_upgrade_vars(){
2606 logThis('setting session variables...');
2607 $upgrade_progress_dir = sugar_cached('upgrades/temp');
2608 if(!is_dir($upgrade_progress_dir)){
2609 mkdir_recursive($upgrade_progress_dir);
2611 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
2612 if(file_exists($upgrade_progress_file)){
2613 include($upgrade_progress_file);
2616 fopen($upgrade_progress_file, 'w+');
2618 if(!isset($upgrade_config) || $upgrade_config == null){
2619 $upgrade_config = array();
2620 $upgrade_config[1]['upgrade_vars']=array();
2622 if(isset($upgrade_config[1]) && isset($upgrade_config[1]['upgrade_vars']) && !is_array($upgrade_config[1]['upgrade_vars'])){
2623 $upgrade_config[1]['upgrade_vars'] = array();
2626 if(!isset($upgrade_vars) || $upgrade_vars == NULL){
2627 $upgrade_vars = array();
2629 if(isset($_SESSION['unzip_dir']) && !empty($_SESSION['unzip_dir']) && file_exists($_SESSION['unzip_dir'])){
2630 $upgrade_vars['unzip_dir']=$_SESSION['unzip_dir'];
2632 if(isset($_SESSION['install_file']) && !empty($_SESSION['install_file']) && file_exists($_SESSION['install_file'])){
2633 $upgrade_vars['install_file']=$_SESSION['install_file'];
2635 if(isset($_SESSION['Upgraded451Wizard']) && !empty($_SESSION['Upgraded451Wizard'])){
2636 $upgrade_vars['Upgraded451Wizard']=$_SESSION['Upgraded451Wizard'];
2638 if(isset($_SESSION['license_shown']) && !empty($_SESSION['license_shown'])){
2639 $upgrade_vars['license_shown']=$_SESSION['license_shown'];
2641 if(isset($_SESSION['Initial_451to500_Step']) && !empty($_SESSION['Initial_451to500_Step'])){
2642 $upgrade_vars['Initial_451to500_Step']=$_SESSION['Initial_451to500_Step'];
2644 if(isset($_SESSION['zip_from_dir']) && !empty($_SESSION['zip_from_dir'])){
2645 $upgrade_vars['zip_from_dir']=$_SESSION['zip_from_dir'];
2647 //place into the upgrade_config array and rewrite config array only if new values are being inserted
2648 if(isset($upgrade_vars) && $upgrade_vars != null && sizeof($upgrade_vars) > 0){
2649 foreach($upgrade_vars as $key=>$val){
2650 if($key != null && $val != null){
2651 $upgrade_config[1]['upgrade_vars'][$key]=$upgrade_vars[$key];
2654 ksort($upgrade_config);
2655 if(is_writable($upgrade_progress_file) && write_array_to_file( "upgrade_config", $upgrade_config,
2656 $upgrade_progress_file)) {
2657 //writing to the file
2662 function initialize_session_vars(){
2663 $upgrade_progress_dir = sugar_cached('upgrades/temp');
2664 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
2665 if(file_exists($upgrade_progress_file)){
2666 include($upgrade_progress_file);
2667 if(isset($upgrade_config) && $upgrade_config != null && is_array($upgrade_config) && sizeof($upgrade_config) >0){
2668 $currVarsArray=$upgrade_config[1]['upgrade_vars'];
2669 //print_r($currVarsArray);
2670 if(isset($currVarsArray) && $currVarsArray != null && is_array($currVarsArray) && sizeof($currVarsArray)>0){
2671 foreach($currVarsArray as $key=>$val){
2672 if($key != null && $val !=null){
2673 //set session variables
2674 $_SESSION[$key]=$val;
2683 //track the upgrade progress on each step
2684 //track the upgrade progress on each step
2685 function set_upgrade_progress($currStep,$currState,$currStepSub='',$currStepSubState=''){
2687 $upgrade_progress_dir = sugar_cached('upgrades/temp');
2688 if(!is_dir($upgrade_progress_dir)){
2689 mkdir_recursive($upgrade_progress_dir);
2691 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
2692 if(file_exists($upgrade_progress_file)){
2693 include($upgrade_progress_file);
2696 if(function_exists('sugar_fopen')){
2697 sugar_fopen($upgrade_progress_file, 'w+');
2700 fopen($upgrade_progress_file, 'w+');
2703 if(!isset($upgrade_config) || $upgrade_config == null){
2704 $upgrade_config = array();
2705 $upgrade_config[1]['upgrade_vars']=array();
2707 if(!is_array($upgrade_config[1]['upgrade_vars'])){
2708 $upgrade_config[1]['upgrade_vars'] = array();
2710 if($currStep != null && $currState != null){
2711 if(sizeof($upgrade_config) > 0){
2712 if($currStepSub != null && $currStepSubState !=null){
2713 //check if new status to be set or update
2714 //get the latest in array. since it has sub components prepare an array
2715 if(!empty($upgrade_config[sizeof($upgrade_config)][$currStep]) && is_array($upgrade_config[sizeof($upgrade_config)][$currStep])){
2716 $latestStepSub = currSubStep($upgrade_config[sizeof($upgrade_config)][$currStep]);
2717 if($latestStepSub == $currStepSub){
2718 $upgrade_config[sizeof($upgrade_config)][$currStep][$latestStepSub]=$currStepSubState;
2719 $upgrade_config[sizeof($upgrade_config)][$currStep][$currStep] = $currState;
2722 $upgrade_config[sizeof($upgrade_config)][$currStep][$currStepSub]=$currStepSubState;
2723 $upgrade_config[sizeof($upgrade_config)][$currStep][$currStep] = $currState;
2727 $currArray = array();
2728 $currArray[$currStep] = $currState;
2729 $currArray[$currStepSub] = $currStepSubState;
2730 $upgrade_config[sizeof($upgrade_config)+1][$currStep] = $currArray;
2734 //get the current upgrade progress
2735 $latestStep = get_upgrade_progress();
2736 //set the upgrade progress
2737 if($latestStep == $currStep){
2738 //update the current step with new progress status
2739 $upgrade_config[sizeof($upgrade_config)][$latestStep]=$currState;
2743 $upgrade_config[sizeof($upgrade_config)+1][$currStep]=$currState;
2745 // now check if there elements within array substeps
2749 //set the upgrade progress (just starting)
2750 $upgrade_config[sizeof($upgrade_config)+1][$currStep]= $currState;
2753 if(is_writable($upgrade_progress_file) && write_array_to_file( "upgrade_config", $upgrade_config,
2754 $upgrade_progress_file)) {
2755 //writing to the file
2761 function get_upgrade_progress(){
2762 $upgrade_progress_dir = sugar_cached('upgrades/temp');
2763 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
2766 if(file_exists($upgrade_progress_file)){
2767 include($upgrade_progress_file);
2768 if(!isset($upgrade_config) || $upgrade_config == null){
2769 $upgrade_config = array();
2771 if($upgrade_config != null && sizeof($upgrade_config) >1){
2772 $currArr = $upgrade_config[sizeof($upgrade_config)];
2773 if(is_array($currArr)){
2774 foreach($currArr as $key=>$val){
2782 function currSubStep($currStep){
2784 if(is_array($currStep)){
2785 foreach($currStep as $key=>$val){
2793 function currUpgradeState($currState){
2795 if(is_array($currState)){
2796 foreach($currState as $key=>$val){
2798 foreach($val as $k=>$v){
2812 function didThisStepRunBefore($step,$SubStep=''){
2813 if($step == null) return;
2814 $upgrade_progress_dir = sugar_cached('upgrades/temp');
2815 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
2818 if(file_exists($upgrade_progress_file)){
2819 include($upgrade_progress_file);
2820 if(isset($upgrade_config) && $upgrade_config != null && is_array($upgrade_config) && sizeof($upgrade_config) >0){
2821 for($i=1;$i<=sizeof($upgrade_config);$i++){
2822 if(is_array($upgrade_config[$i])){
2823 foreach($upgrade_config[$i] as $key=>$val){
2825 if(is_array($upgrade_config[$i][$step])){
2827 foreach ($upgrade_config[$i][$step] as $k=>$v){
2829 foreach($v as $k1=>$v1){
2830 if($SubStep != null){
2831 if($SubStep ==$k1 && $v1=='done'){
2838 elseif($SubStep !=null){
2839 if($SubStep==$k && $v=='done'){
2844 elseif($step==$k && $v=='done'){
2850 elseif($val=='done'){
2864 //get and set post install status
2865 function post_install_progress($progArray='',$action=''){
2866 $upgrade_progress_dir = sugar_cached('upgrades/temp');
2867 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
2868 if($action=='' || $action=='get'){
2869 //get the state of post install
2870 $currProg = array();
2871 if(file_exists($upgrade_progress_file)){
2872 include($upgrade_progress_file);
2873 if(is_array($upgrade_config[sizeof($upgrade_config)]['commit']['post_install']) && sizeof($upgrade_config[sizeof($upgrade_config)]['commit']['post_install'])>0){
2874 foreach($upgrade_config[sizeof($upgrade_config)]['commit']['post_install'] as $k=>$v){
2881 elseif($action=='set'){
2882 if(!is_dir($upgrade_progress_dir)){
2883 mkdir($upgrade_progress_dir);
2885 if(file_exists($upgrade_progress_file)){
2886 include($upgrade_progress_file);
2889 fopen($upgrade_progress_file, 'w+');
2891 if(!is_array($upgrade_config[sizeof($upgrade_config)]['commit']['post_install'])){
2892 $upgrade_config[sizeof($upgrade_config)]['commit']['post_install']=array();
2893 $upgrade_config[sizeof($upgrade_config)]['commit']['post_install']['post_install'] = 'in_progress';
2895 if($progArray != null && is_array($progArray)){
2896 foreach($progArray as $key=>$val){
2897 $upgrade_config[sizeof($upgrade_config)]['commit']['post_install'][$key]=$val;
2900 if(is_writable($upgrade_progress_file) && write_array_to_file( "upgrade_config", $upgrade_config,
2901 $upgrade_progress_file)) {
2902 //writing to the file
2907 function repairDBForUpgrade($execute=false,$path=''){
2909 global $current_user, $beanFiles;
2911 set_time_limit(3600);
2913 $db = &DBManagerFactory::getInstance();
2915 VardefManager::clearVardef();
2916 require_once('include/ListView/ListView.php');
2917 foreach ($beanFiles as $bean => $file) {
2918 require_once ($file);
2919 $focus = new $bean ();
2920 $sql .= $db->repairTable($focus, $execute);
2924 $olddictionary = $dictionary;
2925 unset ($dictionary);
2926 include ('modules/TableDictionary.php');
2927 foreach ($dictionary as $meta) {
2928 $tablename = $meta['table'];
2929 $fielddefs = $meta['fields'];
2930 $indices = $meta['indices'];
2931 $sql .= $db->repairTableParams($tablename, $fielddefs, $indices, $execute);
2934 foreach (explode("\n", $sql) as $line) {
2935 if (!empty ($line) && substr($line, -2) != "*/") {
2938 $qry_str .= $line . "\n";
2949 preg_replace('#(/\*.+?\*/\n*)#', '', $qry_str)
2951 logThis("*******START EXECUTING DB UPGRADE QUERIES***************",$path);
2952 logThis($sql,$path);
2953 logThis("*******END EXECUTING DB UPGRADE QUERIES****************",$path);
2962 * upgradeUserPreferences
2963 * This method updates the user_preferences table and sets the pages/dashlets for users
2964 * which have ACL access to Trackers so that the Tracker dashlets are set in their user perferences
2967 function upgradeUserPreferences() {
2968 global $sugar_config, $sugar_version;
2969 $uw_strings = return_module_language($GLOBALS['current_language'], 'UpgradeWizard');
2971 $localization = new Localization();
2972 $localeCoreDefaults = $localization->getLocaleConfigDefaults();
2974 // check the current system wide default_locale_name_format and add it to the list if it's not there
2975 if(empty($sugar_config['name_formats'])) {
2976 $sugar_config['name_formats'] = $localeCoreDefaults['name_formats'];
2977 if(!rebuildConfigFile($sugar_config, $sugar_version)) {
2978 $errors[] = $uw_strings['ERR_UW_CONFIG_WRITE'];
2982 $currentDefaultLocaleNameFormat = $sugar_config['default_locale_name_format'];
2984 if ($localization->isAllowedNameFormat($currentDefaultLocaleNameFormat)) {
2985 upgradeLocaleNameFormat($currentDefaultLocaleNameFormat);
2987 $sugar_config['default_locale_name_format'] = $localeCoreDefaults['default_locale_name_format'];
2988 if(!rebuildConfigFile($sugar_config, $sugar_version)) {
2989 $errors[] = $uw_strings['ERR_UW_CONFIG_WRITE'];
2991 $localization->createInvalidLocaleNameFormatUpgradeNotice();
2994 $db = &DBManagerFactory::getInstance();
2995 $result = $db->query("SELECT id FROM users where deleted = '0'");
2996 while($row = $db->fetchByAssoc($result))
2998 $current_user = new User();
2999 $current_user->retrieve($row['id']);
3001 // get the user's name locale format, check if it's in our list, add it if it's not, keep it as user's default
3002 $currentUserNameFormat = $current_user->getPreference('default_locale_name_format');
3003 if ($localization->isAllowedNameFormat($currentUserNameFormat)) {
3004 upgradeLocaleNameFormat($currentUserNameFormat);
3006 $current_user->setPreference('default_locale_name_format', 's f l', 0, 'global');
3007 $current_user->savePreferencesToDB();
3015 * Checks if a locale name format is part of the default list, if not adds it to the config
3016 * @param $name_format string a local name format string such as 's f l'
3017 * @return bool true on successful write to config file, false on failure;
3019 function upgradeLocaleNameFormat($name_format) {
3020 global $sugar_config, $sugar_version;
3022 $localization = new Localization();
3023 $localeConfigDefaults = $localization->getLocaleConfigDefaults();
3025 $uw_strings = return_module_language($GLOBALS['current_language'], 'UpgradeWizard');
3026 if(empty($sugar_config['name_formats'])) {
3027 $sugar_config['name_formats'] = $localeConfigDefaults['name_formats'];
3028 if(!rebuildConfigFile($sugar_config, $sugar_version)) {
3029 $errors[] = $uw_strings['ERR_UW_CONFIG_WRITE'];
3032 if (!in_array($name_format, $sugar_config['name_formats'])) {
3033 $new_config = sugarArrayMerge($sugar_config['name_formats'], array($name_format=>$name_format));
3034 $sugar_config['name_formats'] = $new_config;
3035 if(!rebuildConfigFile($sugar_config, $sugar_version)) {
3036 $errors[] = $uw_strings['ERR_UW_CONFIG_WRITE'];
3045 function add_custom_modules_favorites_search(){
3046 $module_directories = scandir('modules');
3048 foreach($module_directories as $module_dir){
3049 if($module_dir == '.' || $module_dir == '..' || !is_dir("modules/{$module_dir}")){
3054 preg_match('/^[a-z0-9]{1,5}_[a-z0-9_]+$/i' , $module_dir, $matches);
3056 // Make sure the module was created by module builder
3057 if(empty($matches)){
3061 $full_module_dir = "modules/{$module_dir}/";
3062 $read_searchdefs_from = "{$full_module_dir}/metadata/searchdefs.php";
3063 $read_SearchFields_from = "{$full_module_dir}/metadata/SearchFields.php";
3064 $read_custom_SearchFields_from = "custom/{$full_module_dir}/metadata/SearchFields.php";
3066 // Studio can possibly override this file, so we check for a custom version of it
3067 if(file_exists("custom/{$full_module_dir}/metadata/searchdefs.php")){
3068 $read_searchdefs_from = "custom/{$full_module_dir}/metadata/searchdefs.php";
3071 if(file_exists($read_searchdefs_from) && file_exists($read_SearchFields_from)){
3074 require($read_searchdefs_from);
3075 foreach($searchdefs[$module_dir]['layout']['basic_search'] as $sf_array){
3076 if(isset($sf_array['name']) && $sf_array['name'] == 'favorites_only'){
3081 require($read_SearchFields_from);
3082 if(isset($searchFields[$module_dir]['favorites_only'])){
3086 if(!$found_sf1 && !$found_sf2){
3087 $searchdefs[$module_dir]['layout']['basic_search']['favorites_only'] = array('name' => 'favorites_only','label' => 'LBL_FAVORITES_FILTER','type' => 'bool',);
3088 $searchdefs[$module_dir]['layout']['advanced_search']['favorites_only'] = array('name' => 'favorites_only','label' => 'LBL_FAVORITES_FILTER','type' => 'bool',);
3089 $searchFields[$module_dir]['favorites_only'] = array(
3090 'query_type'=>'format',
3091 'operator' => 'subquery',
3092 'subquery' => 'SELECT sugarfavorites.record_id FROM sugarfavorites
3093 WHERE sugarfavorites.deleted=0
3094 and sugarfavorites.module = \''.$module_dir.'\'
3095 and sugarfavorites.assigned_user_id = \'{0}\'',
3096 'db_field'=>array('id')
3099 if(!is_dir("custom/{$full_module_dir}/metadata")){
3100 mkdir_recursive("custom/{$full_module_dir}/metadata");
3102 $success_sf1 = write_array_to_file('searchdefs', $searchdefs, "custom/{$full_module_dir}/metadata/searchdefs.php");
3103 $success_sf2 = write_array_to_file('searchFields', $searchFields, "{$full_module_dir}/metadata/SearchFields.php");
3106 logThis("add_custom_modules_favorites_search failed for searchdefs.php for {$module_dir}");
3109 logThis("add_custom_modules_favorites_search failed for SearchFields.php for {$module_dir}");
3111 if($success_sf1 && $success_sf2){
3112 logThis("add_custom_modules_favorites_search successfully updated searchdefs and searchFields for {$module_dir}");
3121 * upgradeModulesForTeamsets
3123 * This method adds the team_set_id values to the module tables that have the new team_set_id column
3124 * added through the SugarCRM 5.5.x upgrade process. It also adds the values into the team_sets and
3125 * team_sets_teams tables.
3127 * @param filter Array of modules to process; empty by default
3129 function upgradeModulesForTeamsets($filter=array()) {
3130 require('include/modules.php');
3131 foreach($beanList as $moduleName=>$beanName) {
3132 if(!empty($filter) && array_search($moduleName, $filter) === false) {
3135 if($moduleName == 'TeamMemberships' || $moduleName == 'ForecastOpportunities'){
3138 $bean = loadBean($moduleName);
3140 empty($bean->table_name)) {
3144 $FieldArray = $GLOBALS['db']->helper->get_columns($bean->table_name);
3145 if(!isset($FieldArray['team_id'])) {
3149 upgradeTeamColumn($bean, 'team_id');
3153 //Upgrade users table
3154 $bean = loadBean('Users');
3155 upgradeTeamColumn($bean, 'default_team');
3156 $result = $GLOBALS['db']->query("SELECT id FROM teams where deleted=0");
3157 while($row = $GLOBALS['db']->fetchByAssoc($result)) {
3158 $teamset = new TeamSet();
3159 $teamset->addTeams($row['id']);
3166 * Helper function to create a team_set_id column and also set team_set_id column
3167 * to have the value of the $column_name parameter
3169 * @param $bean SugarBean which we are adding team_set_id column to
3170 * @param $column_name The name of the column containing the default team_set_id value
3172 function upgradeTeamColumn($bean, $column_name) {
3173 //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
3174 //module that does not use the SugarObjects
3175 if(empty($bean->field_defs['team_set_id']) && $bean->module_dir != 'Trackers'){
3177 //at this point we could assume that since we have a team_id defined and not a team_set_id that we need to
3178 //add that field and the corresponding relationships
3179 $object = $bean->object_name;
3180 $module = $bean->module_dir;
3181 $object_name = $object;
3182 $_object_name = strtolower($object_name);
3184 if(!empty($GLOBALS['dictionary'][$object]['table'])){
3185 $table_name = $GLOBALS['dictionary'][$object]['table'];
3187 $table_name = strtolower($module);
3190 $path = 'include/SugarObjects/implements/team_security/vardefs.php';
3192 //go through each entry in the vardefs from team_security and unset anything that is already set in the core module
3193 //this will ensure we have the proper ordering.
3194 $fieldDiff = array_diff_assoc($vardefs['fields'], $GLOBALS['dictionary'][$bean->object_name]['fields']);
3196 $file = 'custom/Extension/modules/' . $bean->module_dir. '/Ext/Vardefs/teams.php';
3197 $contents = "<?php\n";
3198 if(!empty($fieldDiff)){
3199 foreach($fieldDiff as $key => $val){
3200 $contents .= "\n\$GLOBALS['dictionary']['". $object . "']['fields']['". $key . "']=" . var_export_helper($val) . ";";
3203 $relationshipDiff = array_diff_assoc($vardefs['relationships'], $GLOBALS['dictionary'][$bean->object_name]['relationships']);
3204 if(!empty($relationshipDiff)){
3205 foreach($relationshipDiff as $key => $val){
3206 $contents .= "\n\$GLOBALS['dictionary']['". $object . "']['relationships']['". $key . "']=" . var_export_helper($val) . ";";
3209 $indexDiff = array_diff_assoc($vardefs['indices'], $GLOBALS['dictionary'][$bean->object_name]['indices']);
3210 if(!empty($indexDiff)){
3211 foreach($indexDiff as $key => $val){
3212 $contents .= "\n\$GLOBALS['dictionary']['". $object . "']['indices']['". $key . "']=" . var_export_helper($val) . ";";
3215 if( $fh = @sugar_fopen( $file, 'wt' ) )
3217 fputs( $fh, $contents);
3222 //we have written out the teams.php into custom/Extension/modules/{$module_dir}/Ext/Vardefs/teams.php'
3223 //now let's merge back into vardefs.ext.php
3224 require_once('ModuleInstall/ModuleInstaller.php');
3225 $mi = new ModuleInstaller();
3226 $mi->merge_files('Ext/Vardefs/', 'vardefs.ext.php');
3227 VardefManager::loadVardef($bean->module_dir, $bean->object_name, true);
3228 $bean->field_defs = $GLOBALS['dictionary'][$bean->object_name]['fields'];
3231 if(isset($bean->field_defs['team_set_id'])) {
3232 //Create the team_set_id column
3233 $FieldArray = $GLOBALS['db']->helper->get_columns($bean->table_name);
3234 if(!isset($FieldArray['team_set_id'])) {
3235 $GLOBALS['db']->addColumn($bean->table_name, $bean->field_defs['team_set_id']);
3237 $indexArray = $GLOBALS['db']->helper->get_indices($bean->table_name);
3239 $indexName = getValidDBName('idx_'.strtolower($bean->table_name).'_tmst_id', true, 34);
3242 'name' => $indexName,
3244 'fields' => array('team_set_id')
3247 if(!isset($indexArray[$indexName])) {
3248 $GLOBALS['db']->addIndexes($bean->table_name, $indexDef);
3251 //Update the table's team_set_id column to have the same values as team_id
3252 $GLOBALS['db']->query("UPDATE {$bean->table_name} SET team_set_id = {$column_name}");
3257 * Update the folder subscription table which confirms to the team security mechanism but
3258 * the class SugarFolders does not extend SugarBean and is therefore never picked up by the
3259 * upgradeModulesForTeamsets function.
3261 function upgradeFolderSubscriptionsTeamSetId()
3263 logThis("In upgradeFolderSubscriptionsTeamSetId()");
3264 $query = "UPDATE folders SET team_set_id = team_id";
3265 $result = $GLOBALS['db']->query($query);
3266 logThis("Finished upgradeFolderSubscriptionsTeamSetId()");
3270 * upgradeModulesForTeam
3272 * This method update the associated_user_id, name, name_2 to the private team records on teams table
3273 * This function is used for upgrade process from 5.1.x and 5.2.x.
3276 function upgradeModulesForTeam() {
3277 logThis("In upgradeModulesForTeam()");
3278 $result = $GLOBALS['db']->query("SELECT id, user_name, first_name, last_name FROM users where deleted=0");
3280 while($row = $GLOBALS['db']->fetchByAssoc($result)) {
3281 $results2 = $GLOBALS['db']->query("SELECT id FROM teams WHERE name = '({$row['user_name']})'");
3283 if(!$assoc = $GLOBALS['db']->fetchByAssoc($results2)) {
3284 //if team does not exist, then lets create the team for this user
3287 $user->retrieve($row['id']);
3288 $team->new_user_created($user);
3289 $team_id = $team->id;
3291 $team_id =$assoc['id'];
3295 $name = is_null($row['first_name'])?'':$row['first_name'];
3296 $name_2 = is_null($row['last_name'])?'':$row['last_name'];
3297 $associated_user_id = $row['id'];
3300 //Ensure team->name is not empty by using team->name_2 if available
3301 if(empty($name) && !empty($name_2)) {
3306 $query = "UPDATE teams SET name = '{$name}', name_2 = '{$name_2}', associated_user_id = '{$associated_user_id}' WHERE id = '{$team_id}'";
3307 $GLOBALS['db']->query($query);
3310 //Update the team_set_id and default_team columns
3311 $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'));
3313 //Update team_set_id
3314 if($ce_to_pro_or_ent) {
3315 $GLOBALS['db']->query("update users set team_set_id = (select teams.id from teams where teams.associated_user_id = users.id)");
3316 $GLOBALS['db']->query("update users set default_team = (select teams.id from teams where teams.associated_user_id = users.id)");
3322 function addNewSystemTabsFromUpgrade($from_dir){
3324 if(isset($_SESSION['upgrade_from_flavor'])){
3326 //check to see if there are any new files that need to be added to systems tab
3327 //retrieve old modules list
3328 logThis('check to see if new modules exist',$path);
3329 $oldModuleList = array();
3330 $newModuleList = array();
3331 include($from_dir.'/include/modules.php');
3332 $oldModuleList = $moduleList;
3333 include('include/modules.php');
3334 $newModuleList = $moduleList;
3336 //include tab controller
3337 require_once('modules/MySettings/TabController.php');
3338 $newTB = new TabController();
3340 //make sure new modules list has a key we can reference directly
3341 $newModuleList = $newTB->get_key_array($newModuleList);
3342 $oldModuleList = $newTB->get_key_array($oldModuleList);
3344 //iterate through list and remove commonalities to get new modules
3345 foreach ($newModuleList as $remove_mod){
3346 if(in_array($remove_mod, $oldModuleList)){
3347 unset($newModuleList[$remove_mod]);
3350 //new modules list now has left over modules which are new to this install, so lets add them to the system tabs
3351 logThis('new modules to add are '.var_export($newModuleList,true),$path);
3353 if(!empty($newModuleList))
3355 //grab the existing system tabs
3356 $tabs = $newTB->get_system_tabs();
3358 //add the new tabs to the array
3359 foreach($newModuleList as $nm ){
3363 $newTB->set_system_tabs($tabs);
3365 logThis('module tabs updated',$path);
3371 * This method attempts to fix dropdown lists that were incorrectly named.
3372 * There were versions of SugarCRM that did not enforce naming convention rules
3373 * for the dropdown list field name. This method attempts to resolve that by
3374 * fixing the language files that may have been affected and then updating the
3375 * fields_meta_data table accordingly. It also refreshes any vardefs that may
3376 * have been affected.
3379 function fix_dropdown_list() {
3380 if(file_exists('custom/include/language')) {
3382 $affected_modules = array();
3383 $affected_keys = array();
3385 getFiles($files, 'custom/include/language', '/\.php$/i');
3386 foreach($files as $file) {
3388 if(file_exists($file . '.bak')) {
3389 $bak_mod_time = filemtime($file . '.bak');
3390 $php_mod_time = filemtime($file);
3391 //We're saying if the .php file was modified 30 seconds no more than php.bak file then we
3392 //run these additional cleanup checks
3393 if($php_mod_time - $bak_mod_time < 30) {
3395 $app_list_strings = array();
3396 $GLOBALS['app_list_strings'] = array();
3397 require($file . '.bak');
3398 $bak_app_list_strings = array_merge($app_list_strings, $GLOBALS['app_list_strings']);
3400 $app_list_strings = array();
3401 $GLOBALS['app_list_strings'] = array();
3403 $php_app_list_strings = array_merge($app_list_strings, $GLOBALS['app_list_strings']);
3405 //Get the file contents
3406 $contents = file_get_contents($file);
3408 //Now simulate a fix for the file before we compare w/ the .php file
3409 //we also append to the $contents
3410 foreach($bak_app_list_strings as $key=>$entry) {
3411 if(preg_match('/([^A-Za-z_])/', $key, $matches) && is_array($entry)) {
3412 $new_key = preg_replace('/[^A-Za-z_]/', '_', $key);
3413 $bak_app_list_strings[$new_key] = $bak_app_list_strings[$key];
3414 unset($bak_app_list_strings[$key]);
3415 //Now if the entry doesn't exists in the .php file, then add to contents
3416 if(!isset($php_app_list_strings[$new_key])) {
3417 $contents .= "\n\$GLOBALS['app_list_strings']['{$new_key}'] = " . var_export_helper($bak_app_list_strings[$new_key]) . ";";
3422 //Now load the .php file to do the comparison
3423 foreach($php_app_list_strings as $key=>$entry) {
3424 if(isset($bak_app_list_strings[$key])) {
3425 $diff = array_diff($bak_app_list_strings[$key], $entry);
3427 //There is a difference, so copy the $bak_app_list_strings version into the .php file
3428 $contents .= "\n\$GLOBALS['app_list_strings']['{$key}'] = " . var_export_helper($bak_app_list_strings[$key]) . ";";
3433 //Now write out the file contents
3434 //Create backup just in case
3435 copy($file, $file . '.php_bak');
3436 $fp = @sugar_fopen($file, 'w');
3438 fwrite($fp, $contents);
3441 $GLOBALS['log']->error("Unable to update file contents in fix_dropdown_list for {$file}");
3446 unset($GLOBALS['app_strings']);
3447 unset($GLOBALS['app_list_strings']);
3448 $app_list_strings = array();
3451 $contents = file_get_contents($file);
3452 if ( !isset($GLOBALS['app_list_strings']) ) {
3453 $GLOBALS['app_list_strings'] = $app_list_strings;
3456 $GLOBALS['app_list_strings'] = array_merge($app_list_strings, $GLOBALS['app_list_strings']);
3459 if(isset($GLOBALS['app_list_strings']) && is_array($GLOBALS['app_list_strings'])) {
3460 foreach($GLOBALS['app_list_strings'] as $key=>$entry) {
3461 if(preg_match('/([^A-Za-z_])/', $key, $matches) && is_array($entry)) {
3462 $result = $GLOBALS['db']->query("SELECT custom_module FROM fields_meta_data WHERE ext1 = '{$key}'");
3463 if(!empty($result)) {
3464 while($row = $GLOBALS['db']->fetchByAssoc($result)) {
3465 $custom_module = $row['custom_module'];
3466 if(!empty($GLOBALS['beanList'][$custom_module])) {
3467 $affected_modules[$custom_module] = $GLOBALS['beanList'][$custom_module];
3472 //Replace all invalid characters with '_' character
3473 $new_key = preg_replace('/[^A-Za-z_]/', '_', $key);
3474 $affected_keys[$key] = $new_key;
3476 $GLOBALS['app_list_strings'][$new_key] = $GLOBALS['app_list_strings'][$key];
3477 unset($GLOBALS['app_list_strings'][$key]);
3479 $pattern_match = "/(\[\s*\'{$key}\'\s*\])/";
3480 $new_key = "['{$new_key}']";
3481 $out = preg_replace($pattern_match, $new_key, $contents);
3487 //This is a check for g => h instances where the file contents were incorrectly written
3488 //and also fixes the scenario where via a UI upgrade, the app_list_strings were incorrectly
3489 //merged with app_list_strings variables declared elsewhere
3491 if(preg_match('/\$GLOBALS\s*\[\s*[\"|\']app_list_strings[\"|\']\s*\]\s*=\s*array\s*\(/', $contents)) {
3492 //Now also remove all the non-custom labels that were added
3493 if(preg_match('/language\/([^\.]+)\.lang\.php$/', $file, $matches)) {
3494 $language = $matches[1];
3496 $app_list_strings = array();
3498 if(file_exists("include/language/$language.lang.php")) {
3499 include("include/language/$language.lang.php");
3501 if(file_exists("include/language/$language.lang.override.php")) {
3502 $app_list_strings = _mergeCustomAppListStrings("include/language/$language.lang.override.php" , $app_list_strings) ;
3504 if(file_exists("custom/application/Ext/Language/$language.ext.lang.php")) {
3505 $app_list_strings = _mergeCustomAppListStrings("custom/application/Ext/Language/$language.ext.lang.php" , $app_list_strings) ;
3507 if(file_exists("custom/application/Ext/Language/$language.lang.ext.php")) {
3508 $app_list_strings = _mergeCustomAppListStrings("custom/application/Ext/Language/$language.lang.ext.php" , $app_list_strings) ;
3511 $all_non_custom_include_language_strings = $app_strings;
3512 $all_non_custom_include_language_list_strings = $app_list_strings;
3514 $unset_keys = array();
3515 if(!empty($GLOBALS['app_list_strings'])) {
3516 foreach($GLOBALS['app_list_strings'] as $key=>$value) {
3518 if(isset($all_non_custom_include_language_list_strings[$key])) {
3519 $diff = array_diff($all_non_custom_include_language_list_strings[$key], $GLOBALS['app_list_strings'][$key]);
3522 if(!empty($all_non_custom_include_language_list_strings[$key]) && empty($diff)) {
3523 $unset_keys[] = $key;
3528 foreach($unset_keys as $key) {
3529 unset($GLOBALS['app_list_strings'][$key]);
3532 if(!empty($GLOBALS['app_strings'])) {
3533 foreach($GLOBALS['app_strings'] as $key=>$value) {
3534 if(!empty($all_non_custom_include_language_strings[$key])) {
3535 unset($GLOBALS['app_strings'][$key]);
3539 } //if(preg_match...)
3542 if(!empty($GLOBALS['app_strings'])) {
3543 foreach($GLOBALS['app_strings'] as $key=>$entry) {
3544 $out .= "\n\$GLOBALS['app_strings']['$key']=" . var_export_helper($entry) . ";";
3548 foreach($GLOBALS['app_list_strings'] as $key=>$entry) {
3549 $out .= "\n\$GLOBALS['app_list_strings']['$key']=" . var_export_helper($entry) . ";";
3553 } //if(preg_match...)
3557 //Create a backup just in case
3558 copy($file, $file . '.bak');
3559 $fp = @sugar_fopen($file, 'w');
3564 //If we can't update the file, just return
3565 $GLOBALS['log']->error("Unable to update file contents in fix_dropdown_list.");
3573 //Update db entries (the order matters here... need to process database changes first)
3574 if(!empty($affected_keys)) {
3575 foreach($affected_keys as $old_key=>$new_key) {
3576 $GLOBALS['db']->query("UPDATE fields_meta_data SET ext1 = '{$new_key}' WHERE ext1 = '{$old_key}'");
3580 //Update vardef files for affected modules
3581 if(!empty($affected_modules)) {
3582 foreach($affected_modules as $module=>$object) {
3583 VardefManager::refreshVardefs($module, $object);
3590 function update_iframe_dashlets(){
3591 require_once(sugar_cached('dashlets/dashlets.php'));
3593 $db = DBManagerFactory::getInstance();
3594 $query = "SELECT id, contents, assigned_user_id FROM user_preferences WHERE deleted = 0 AND category = 'Home'";
3595 $result = $db->query($query, true, "Unable to update new default dashlets! ");
3596 while ($row = $db->fetchByAssoc($result)) {
3597 $content = unserialize(base64_decode($row['contents']));
3598 $assigned_user_id = $row['assigned_user_id'];
3599 $record_id = $row['id'];
3601 $current_user = new User();
3602 $current_user->retrieve($row['assigned_user_id']);
3604 if(!empty($content['dashlets']) && !empty($content['pages'])){
3605 $originalDashlets = $content['dashlets'];
3606 foreach($originalDashlets as $key => $ds){
3607 if(!empty($ds['options']['url']) && stristr($ds['options']['url'],'http://www.sugarcrm.com/crm/product/gopro')){
3608 unset($originalDashlets[$key]);
3611 $current_user->setPreference('dashlets', $originalDashlets, 0, 'Home');
3618 * convertImageToText
3620 * This method attempts to convert date type image to text on Microsoft SQL Server.
3621 * This method could NOT be used in any other type of datebases.
3623 function convertImageToText($table_name,$column_name){
3624 $set_lang = "SET LANGUAGE us_english";
3625 $GLOBALS['db']->query($set_lang);
3626 if($GLOBALS['db']->lastError()){
3627 logThis('An error occurred when performing this query-->'.$set_lang);
3629 $q="SELECT data_type
3630 FROM INFORMATION_SCHEMA.Tables T JOIN INFORMATION_SCHEMA.Columns C
3631 ON T.TABLE_NAME = C.TABLE_NAME where T.TABLE_NAME = '$table_name' and C.COLUMN_NAME = '$column_name'";
3632 $res= $GLOBALS['db']->query($q);
3633 if($GLOBALS['db']->lastError()){
3634 logThis('An error occurred when performing this query-->'.$q);
3636 $row= $GLOBALS['db']->fetchByAssoc($res);
3638 if(trim(strtolower($row['data_type'])) == 'image'){
3639 $addContent_temp = "alter table {$table_name} add {$column_name}_temp text null";
3640 $GLOBALS['db']->query($addContent_temp);
3641 if($GLOBALS['db']->lastError()){
3642 logThis('An error occurred when performing this query-->'.$addContent_temp);
3644 $qN = "select count=datalength({$column_name}), id, {$column_name} from {$table_name}";
3645 $result = $GLOBALS['db']->query($qN);
3646 while($row = $GLOBALS['db']->fetchByAssoc($result)){
3647 if($row['count'] >8000){
3648 $contentLength = $row['count'];
3651 $convertedContent = '';
3652 while($contentLength >0){
3653 $stepsQuery = "select cont=convert(varchar(max), convert(varbinary(8000), substring({$column_name},{$start},{$next}))) from {$table_name} where id= '{$row['id']}'";
3654 $steContQ = $GLOBALS['db']->query($stepsQuery);
3655 if($GLOBALS['db']->lastError()){
3656 logThis('An error occurred when performing this query-->'.$stepsQuery);
3658 $stepCont = $GLOBALS['db']->fetchByAssoc($steContQ);
3659 if(isset($stepCont['cont'])){
3660 $convertedContent = $convertedContent.$stepCont['cont'];
3662 $start = $start+$next;
3663 $contentLength = $contentLength - $next;
3665 $addContentDataText="update {$table_name} set {$column_name}_temp = '{$convertedContent}' where id= '{$row['id']}'";
3666 $GLOBALS['db']->query($addContentDataText);
3667 if($GLOBALS['db']->lastError()){
3668 logThis('An error occurred when performing this query-->'.$addContentDataText);
3672 $addContentDataText="update {$table_name} set {$column_name}_temp =
3673 convert(varchar(max), convert(varbinary(8000), {$column_name})) where id= '{$row['id']}'";
3674 $GLOBALS['db']->query($addContentDataText);
3675 if($GLOBALS['db']->lastError()){
3676 logThis('An error occurred when performing this query-->'.$addContentDataText);
3680 //drop the contents now and change contents_temp to contents
3681 $dropColumn = "alter table {$table_name} drop column {$column_name}";
3682 $GLOBALS['db']->query($dropColumn);
3683 if($GLOBALS['db']->lastError()){
3684 logThis('An error occurred when performing this query-->'.$dropColumn);
3686 $changeColumnName = "EXEC sp_rename '{$table_name}.[{$column_name}_temp]','{$column_name}','COLUMN'";
3687 $GLOBALS['db']->query($changeColumnName);
3688 if($GLOBALS['db']->lastError()){
3689 logThis('An error occurred when performing this query-->'.$changeColumnName);
3696 * This method attempts to delete all English inline help files.
3697 * This method was introduced by 5.5.0RC2.
3699 function clearHelpFiles(){
3700 $modulePath = clean_path(getcwd() . '/modules');
3701 $allHelpFiles = array();
3702 getFiles($allHelpFiles, $modulePath, "/en_us.help.*/");
3704 foreach( $allHelpFiles as $the_file ){
3705 if( is_file( $the_file ) ){
3706 unlink( $the_file );
3707 logThis("Deleted file: $the_file");
3715 * upgradeDateTimeFields
3717 * This method came from bug: 39757 where the date_end field is a date field and not a datetime field
3718 * which prevents you from performing timezone offset calculations once the data has been saved.
3720 * @param path String location to log file, empty by default
3722 function upgradeDateTimeFields($path)
3726 $meetingsSql = "UPDATE meetings SET date_end = ".$db->convert("date_start", 'add_time', array('duration_hours', 'duration_minutes'));
3727 $callsSql = "UPDATE calls SET date_end = ".$db->convert("date_start", 'add_time', array('duration_hours', 'duration_minutes'));
3728 logThis('upgradeDateTimeFields Meetings SQL:' . $meetingsSql, $path);
3729 $db->query($meetingsSql);
3731 logThis('upgradeDateTimeFields Calls SQL:' . $callsSql, $path);
3732 $db->query($callsSql);
3736 * upgradeDocumentTypeFields
3739 function upgradeDocumentTypeFields($path){
3743 $documentsSql = "UPDATE documents SET doc_type = 'Sugar' WHERE doc_type IS NULL";
3744 $meetingsSql = "UPDATE meetings SET type = 'Sugar' WHERE type IS NULL";
3746 logThis('upgradeDocumentTypeFields Documents SQL:' . $documentsSql, $path);
3747 $db->query($documentsSql);
3748 logThis('upgradeDocumentTypeFields Meetings SQL:' . $meetingsSql, $path);
3749 $db->query($meetingsSql);
3754 * merge_config_si_settings
3755 * This method checks for the presence of a config_si.php file and, if found, merges the configuration
3756 * settings from the config_si.php file into config.php. If a config_si_location parameter value is not
3757 * supplied it will attempt to discover the config_si.php file location from where the executing script
3760 * @param write_to_upgrade_log boolean optional value to write to the upgradeWizard.log file
3761 * @param config_location String optional value to config.php file location
3762 * @param config_si_location String optional value to config_si.php file location
3763 * @param path String file of the location of log file to write to
3764 * @return boolean value indicating whether or not a merge was attempted with config_si.php file
3766 function merge_config_si_settings($write_to_upgrade_log=false, $config_location='', $config_si_location='', $path='')
3768 if(!empty($config_location) && !file_exists($config_location))
3770 if($write_to_upgrade_log)
3772 logThis('config.php file specified in ' . $config_si_location . ' could not be found. Skip merging', $path);
3775 } else if(empty($config_location)) {
3777 //We are assuming this is from the silentUpgrade scripts so argv[3] will point to SugarCRM install location
3778 if(isset($argv[3]) && is_dir($argv[3]))
3780 $config_location = $argv[3] . DIRECTORY_SEPARATOR . 'config.php';
3784 //If config_location is still empty or if the file cannot be found, skip merging
3785 if(empty($config_location) || !file_exists($config_location))
3787 if($write_to_upgrade_log)
3789 logThis('config.php file at (' . $config_location . ') could not be found. Skip merging.', $path);
3793 if($write_to_upgrade_log)
3795 logThis('Loading config.php file at (' . $config_location . ') for merging.', $path);
3798 include($config_location);
3799 if(empty($sugar_config))
3801 if($write_to_upgrade_log)
3803 logThis('config.php contents are empty. Skip merging.', $path);
3809 if(!empty($config_si_location) && !file_exists($config_si_location))
3811 if($write_to_upgrade_log)
3813 logThis('config_si.php file specified in ' . $config_si_location . ' could not be found. Skip merging', $path);
3816 } else if(empty($config_si_location)) {
3817 if(isset($argv[0]) && is_file($argv[0]))
3819 $php_file = $argv[0];
3820 $p_info = pathinfo($php_file);
3821 $php_dir = (isset($p_info['dirname']) && $p_info['dirname'] != '.') ? $p_info['dirname'] . DIRECTORY_SEPARATOR : '';
3822 $config_si_location = $php_dir . 'config_si.php';
3826 //If config_si_location is still empty or if the file cannot be found, skip merging
3827 if(empty($config_si_location) || !file_exists($config_si_location))
3829 if($write_to_upgrade_log)
3831 logThis('config_si.php file at (' . $config_si_location . ') could not be found. Skip merging.', $path);
3835 if($write_to_upgrade_log)
3837 logThis('Loading config_si.php file at (' . $config_si_location . ') for merging.', $path);
3840 include($config_si_location);
3841 if(empty($sugar_config_si))
3843 if($write_to_upgrade_log)
3845 logThis('config_si.php contents are empty. Skip merging.', $path);
3851 //Now perform the merge operation
3853 foreach($sugar_config_si as $key=>$value)
3855 if(!preg_match('/^setup_/', $key) && !isset($sugar_config[$key]))
3857 if($write_to_upgrade_log)
3859 logThis('Merge key (' . $key . ') with value (' . $value . ')', $path);
3861 $sugar_config[$key] = $value;
3868 if($write_to_upgrade_log)
3870 logThis('Update config.php file with new values', $path);
3873 if(!write_array_to_file("sugar_config", $sugar_config, $config_location)) {
3874 if($write_to_upgrade_log)
3876 logThis('*** ERROR: could not write to config.php', $path);
3881 if($write_to_upgrade_log)
3883 logThis('config.php values are in sync with config_si.php values. Skipped merging.');
3888 if($write_to_upgrade_log)
3890 logThis('End merge_config_si_settings', $path);
3897 * upgrade_connectors
3899 * This function handles support for upgrading connectors it is invoked from both end.php and silentUpgrade_step2.php
3902 function upgrade_connectors() {
3903 require_once('include/connectors/utils/ConnectorUtils.php');
3904 if(!ConnectorUtils::updateMetaDataFiles()) {
3905 $GLOBALS['log']->fatal('Cannot update metadata files for connectors');
3908 //Delete the custom connectors.php file if it exists so that it may be properly rebuilt
3909 if(file_exists('custom/modules/Connectors/metadata/connectors.php'))
3911 unlink('custom/modules/Connectors/metadata/connectors.php');
3916 * Enable the InsideView connector for the four default modules.
3918 function upgradeEnableInsideViewConnector($path='')
3920 logThis('Begin upgradeEnableInsideViewConnector', $path);
3922 // Load up the existing mapping and hand it to the InsideView connector to have it setup the correct logic hooks
3923 $mapFile = 'modules/Connectors/connectors/sources/ext/rest/insideview/mapping.php';
3924 if ( file_exists('custom/'.$mapFile) ) {
3925 logThis('Found CUSTOM mappings', $path);
3926 require('custom/'.$mapFile);
3928 logThis('Used default mapping', $path);
3932 require_once('include/connectors/sources/SourceFactory.php');
3933 $source = SourceFactory::getSource('ext_rest_insideview');
3935 // $mapping is brought in from the mapping.php file above
3936 $source->saveMappingHook($mapping);
3938 require_once('include/connectors/utils/ConnectorUtils.php');
3939 ConnectorUtils::installSource('ext_rest_insideview');
3941 // Now time to set the various modules to active, because this part ignores the default config
3942 require(CONNECTOR_DISPLAY_CONFIG_FILE);
3943 // $modules_sources come from that config file
3944 foreach ( $source->allowedModuleList as $module ) {
3945 $modules_sources[$module]['ext_rest_insideview'] = 'ext_rest_insideview';
3947 if(!write_array_to_file('modules_sources', $modules_sources, CONNECTOR_DISPLAY_CONFIG_FILE)) {
3948 //Log error and return empty array
3949 logThis("Cannot write \$modules_sources to " . CONNECTOR_DISPLAY_CONFIG_FILE,$path);
3952 logThis('End upgradeEnableInsideViewConnector', $path);
3956 function repair_long_relationship_names($path='')
3958 logThis("Begin repair_long_relationship_names", $path);
3959 require_once 'modules/ModuleBuilder/parsers/relationships/DeployedRelationships.php' ;
3960 $GLOBALS['mi_remove_tables'] = false;
3962 foreach($GLOBALS['moduleList'] as $module)
3964 $relationships = new DeployedRelationships ($module) ;
3965 foreach($relationships->getRelationshipList() as $rel_name)
3967 if (strlen($rel_name) > 27 && empty($touched[$rel_name]))
3969 logThis("Rebuilding relationship fields for $rel_name", $path);
3970 $touched[$rel_name] = true;
3971 $rel_obj = $relationships->get($rel_name);
3972 $rel_obj->setReadonly(false);
3973 $relationships->delete($rel_name);
3974 $relationships->save();
3975 $relationships->add($rel_obj);
3976 $relationships->save();
3977 $relationships->build () ;
3981 logThis("End repair_long_relationship_names", $path);
3984 function removeSilentUpgradeVarsCache(){
3985 global $silent_upgrade_vars_loaded;
3987 $cacheFileDir = "{$GLOBALS['sugar_config']['cache_dir']}/silentUpgrader";
3988 $cacheFile = "{$cacheFileDir}/silentUpgradeCache.php";
3990 if(file_exists($cacheFile)){
3994 $silent_upgrade_vars_loaded = array(); // Set to empty to reset it
3999 function loadSilentUpgradeVars(){
4000 global $silent_upgrade_vars_loaded;
4002 if(empty($silent_upgrade_vars_loaded)){
4003 $cacheFile = "{$GLOBALS['sugar_config']['cache_dir']}/silentUpgrader/silentUpgradeCache.php";
4004 // We have no pre existing vars
4005 if(!file_exists($cacheFile)){
4006 // Set the vars array so it's loaded
4007 $silent_upgrade_vars_loaded = array('vars' => array());
4010 require_once($cacheFile);
4011 $silent_upgrade_vars_loaded = $silent_upgrade_vars_cache;
4018 function writeSilentUpgradeVars(){
4019 global $silent_upgrade_vars_loaded;
4021 if(empty($silent_upgrade_vars_loaded)){
4022 return false; // You should have set some values before trying to write the silent upgrade vars
4025 $cacheFileDir = "{$GLOBALS['sugar_config']['cache_dir']}/silentUpgrader";
4026 $cacheFile = "{$cacheFileDir}/silentUpgradeCache.php";
4028 require_once('include/dir_inc.php');
4029 if(!mkdir_recursive($cacheFileDir)){
4032 require_once('include/utils/file_utils.php');
4033 if(!write_array_to_file('silent_upgrade_vars_cache', $silent_upgrade_vars_loaded, $cacheFile, 'w')){
4035 logThis("WARNING: writeSilentUpgradeVars could not write to {$cacheFile}", $path);
4042 function setSilentUpgradeVar($var, $value){
4043 if(!loadSilentUpgradeVars()){
4047 global $silent_upgrade_vars_loaded;
4049 $silent_upgrade_vars_loaded['vars'][$var] = $value;
4054 function getSilentUpgradeVar($var){
4055 if(!loadSilentUpgradeVars()){
4059 global $silent_upgrade_vars_loaded;
4061 if(!isset($silent_upgrade_vars_loaded['vars'][$var])){
4065 return $silent_upgrade_vars_loaded['vars'][$var];
4071 * add_unified_search_to_custom_modules_vardefs
4073 * This method calls the repair code to remove the unified_search_modules.php fiel
4076 function add_unified_search_to_custom_modules_vardefs()
4078 if(file_exists($cachefile = sugar_cached('modules/unified_search_modules.php')))
4086 * change from using the older SugarCache in 6.1 and below to the new one in 6.2
4088 function upgradeSugarCache($file)
4090 global $sugar_config;
4091 $cacheUploadUpgradesTemp = mk_temp_dir(sugar_cached('upgrades/temp'));
4093 unzip($file, $cacheUploadUpgradesTemp);
4095 if(!file_exists(clean_path("{$cacheUploadUpgradesTemp}/manifest.php"))) {
4096 logThis("*** ERROR: no manifest file detected while bootstraping upgrade wizard files!");
4099 include(clean_path("{$cacheUploadUpgradesTemp}/manifest.php"));
4102 $from_dir = "{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}";
4103 $allFiles = array();
4104 if(file_exists("$from_dir/include/SugarCache")) {
4105 $allFiles = findAllFiles("$from_dir/include/SugarCache", $allFiles);
4107 if(file_exists("$from_dir/include/database")) {
4108 $allFiles = findAllFiles("$from_dir/include/database", $allFiles);
4110 if(file_exists("$from_dir/include/utils/external_cache.php")) {
4111 $allFiles[] = "$from_dir/include/utils/external_cache.php";
4113 if(file_exists("$from_dir/include/utils/sugar_file_utils.php")) {
4114 $allFiles[] = "$from_dir/include/utils/sugar_file_utils.php";
4116 if(file_exists("$from_dir/include/utils/sugar_file_utils.php")) {
4117 $allFiles[] = "$from_dir/include/utils/sugar_file_utils.php";
4120 foreach($allFiles as $k => $file) {
4121 $destFile = str_replace($from_dir."/", "", $file);
4122 if(!is_dir(dirname($destFile))) {
4123 mkdir_recursive(dirname($destFile)); // make sure the directory exists
4125 if ( stristr($file,'uw_main.tpl') )
4126 logThis('Skipping "'.$file.'" - file copy will during commit step.');
4128 logThis('updating UpgradeWizard code: '.$destFile);
4129 copy_recursive($file, $destFile);
4136 * upgradeDisplayedTabsAndSubpanels
4138 * @param $version String value of current system version (pre upgrade)
4140 function upgradeDisplayedTabsAndSubpanels($version)
4142 if($version < '620')
4144 logThis('start upgrading system displayed tabs and subpanels');
4145 require_once('modules/MySettings/TabController.php');
4146 $tc = new TabController();
4148 //grab the existing system tabs
4149 $tabs = $tc->get_tabs_system();
4151 //add Calls, Meetings, Tasks, Notes, Prospects (Targets) and ProspectLists (Target Lists)
4152 //to displayed tabs unless explicitly set to hidden
4153 $modules_to_add = array('Calls', 'Meetings', 'Tasks', 'Notes', 'Prospects', 'ProspectLists');
4154 $added_tabs = array();
4156 foreach($modules_to_add as $module)
4158 $tabs[0][$module] = $module;
4159 $added_tabs[] = $module;
4162 logThis('calling set_system_tabs on TabController to add tabs: ' . var_export($added_tabs, true));
4163 $tc->set_system_tabs($tabs[0]);
4164 logThis('finish upgrading system displayed tabs and subpanels');
4170 * unlinkUpgradeFiles
4171 * This is a helper function to clean up
4173 * @param $version String value of current system version (pre upgrade)
4175 function unlinkUpgradeFiles($version)
4177 if(!isset($version))
4182 //First check if we even have the scripts_for_patch/files_to_remove directory
4183 require_once('modules/UpgradeWizard/UpgradeRemoval.php');
4186 if(empty($_SESSION['unzip_dir']))
4188 global $sugar_config;
4189 $base_upgrade_dir = $sugar_config['upload_dir'] . "/upgrades";
4190 $base_tmp_upgrade_dir = "$base_upgrade_dir/temp";
4191 $_SESSION['unzip_dir'] = mk_temp_dir( $base_tmp_upgrade_dir );
4195 if(isset($_SESSION['unzip_dir']) && file_exists($_SESSION['unzip_dir'].'/scripts/files_to_remove'))
4197 $files_to_remove = glob($_SESSION['unzip_dir'].'/scripts/files_to_remove/*.php');
4199 foreach($files_to_remove as $script)
4201 if(preg_match('/UpgradeRemoval(\d+)x\.php/', $script, $matches))
4203 $checkVersion = $matches[1] + 1; //Increment by one to check everything equal or below the target version
4204 $upgradeClass = 'UpgradeRemoval' . $matches[1] . 'x';
4205 require_once($_SESSION['unzip_dir'].'/scripts/files_to_remove/' . $upgradeClass . '.php');
4207 //Check to make sure we should load and run this UpgradeRemoval instance
4208 if($checkVersion <= $version && class_exists($upgradeClass))
4210 $upgradeInstance = new $upgradeClass();
4211 if($upgradeInstance instanceof UpgradeRemoval)
4213 logThis('Running UpgradeRemoval instance ' . $upgradeClass);
4214 logThis('Files will be backed up to custom/backup');
4215 $files = $upgradeInstance->getFilesToRemove($version);
4216 foreach($files as $file)
4220 $upgradeInstance->processFilesToRemove($files);
4227 //Check if we have a custom directory
4228 if(file_exists('custom/scripts/files_to_remove'))
4231 $files_to_remove = glob('custom/scripts/files_to_remove/*.php');
4233 foreach($files_to_remove as $script)
4235 if(preg_match('/\/files_to_remove\/(.*?)\.php$/', $script, $matches))
4237 require_once($script);
4238 $upgradeClass = $matches[1];
4240 if(!class_exists($upgradeClass))
4245 $upgradeInstance = new $upgradeClass();
4246 if($upgradeInstance instanceof UpgradeRemoval)
4248 logThis('Running Custom UpgradeRemoval instance ' . $upgradeClass);
4249 $files = $upgradeInstance->getFilesToRemove($version);
4250 foreach($files as $file)
4254 $upgradeInstance->processFilesToRemove($files);
4262 if (!function_exists("getValidDBName"))
4265 * Return a version of $proposed that can be used as a column name in any of our supported databases
4266 * 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)
4267 * @param string $name Proposed name for the column
4268 * @param string $ensureUnique
4269 * @return string Valid column name trimmed to right length and with invalid characters removed
4271 function getValidDBName ($name, $ensureUnique = false, $maxLen = 30)
4273 // first strip any invalid characters - all but alphanumerics and -
4274 $name = preg_replace ( '/[^\w-]+/i', '', $name ) ;
4275 $len = strlen ( $name ) ;
4279 $md5str = md5($name);
4280 $tail = substr ( $name, -11) ;
4281 $temp = substr($md5str , strlen($md5str)-4 );
4282 $result = substr ( $name, 0, 10) . $temp . $tail ;
4283 }else if ($len > ($maxLen - 5))
4285 $result = substr ( $name, 0, 11) . substr ( $name, 11 - $maxLen + 5);
4287 return strtolower ( $result ) ;
4294 * Get UW directories
4295 * Provides compatibility with both 6.3 and pre-6.3 setup
4297 function getUWDirs()
4299 if(!class_exists('UploadStream')) {
4300 // we're still running the old code
4301 global $sugar_config;
4302 return array($sugar_config['upload_dir'] . "/upgrades", $sugar_config['cache_dir'] . "upload/upgrades/temp");
4304 if(!in_array("upload", stream_get_wrappers())) {
4305 UploadStream::register(); // just in case file was copied, but not run
4307 return array("upload://upgrades", sugar_cached("upgrades/temp"));
4312 * Whether directory exists within list of directories to skip
4313 * @param string $dir dir to be checked
4314 * @param array $skipDirs list with skipped dirs
4317 function whetherNeedToSkipDir($dir, $skipDirs)
4319 foreach($skipDirs as $skipMe) {
4320 if(strpos( clean_path($dir), $skipMe ) !== false) {
4330 * @param silentUpgrade boolean flag indicating whether or not we should treat running the SugarSpriteBuilder as an upgrade operation
4333 function rebuildSprites($fromUpgrade=true)
4335 require_once('modules/Administration/SugarSpriteBuilder.php');
4336 $sb = new SugarSpriteBuilder();
4337 $sb->cssMinify = true;
4338 $sb->fromSilentUpgrade = $fromUpgrade;
4339 $sb->silentRun = $fromUpgrade;
4341 // add common image directories
4342 $sb->addDirectory('default', 'include/images');
4343 $sb->addDirectory('default', 'themes/default/images');
4344 $sb->addDirectory('default', 'themes/default/images/SugarLogic');
4346 // add all theme image directories
4347 if($dh = opendir('themes'))
4349 while (($dir = readdir($dh)) !== false)
4351 if ($dir != "." && $dir != ".." && $dir != 'default' && is_dir('themes/'.$dir)) {
4352 $sb->addDirectory($dir, "themes/{$dir}/images");
4358 // generate the sprite goodies
4359 // everything is saved into cache/sprites
4360 $sb->createSprites();
4365 * repairSearchFields
4367 * This method goes through the list of SearchFields files based and calls TemplateRange::repairCustomSearchFields
4368 * method on the files in an attempt to ensure the range search attributes are properly set in SearchFields.php.
4370 * @param $globString String value used for glob search defaults to searching for all SearchFields.php files in modules directory
4371 * @param $path String value used to point to log file should logging be required. Defaults to empty.
4374 function repairSearchFields($globString='modules/*/metadata/SearchFields.php', $path='')
4378 logThis('Begin repairSearchFields', $path);
4381 require_once('include/dir_inc.php');
4382 require_once('modules/DynamicFields/templates/Fields/TemplateRange.php');
4383 require('include/modules.php');
4386 $searchFieldsFiles = glob($globString);
4388 foreach($searchFieldsFiles as $file)
4390 if(preg_match('/modules\/(.*?)\/metadata\/SearchFields\.php/', $file, $matches) && isset($beanList[$matches[1]]))
4392 $module = $matches[1];
4393 $beanName = $beanList[$module];
4394 VardefManager::loadVardef($module, $beanName);
4395 if(isset($GLOBALS['dictionary'][$beanName]['fields']))
4399 logThis('Calling TemplateRange::repairCustomSearchFields for module ' . $module, $path);
4401 TemplateRange::repairCustomSearchFields($GLOBALS['dictionary'][$beanName]['fields'], $module);
4408 logThis('End repairSearchFields', $path);
4413 * repairUpgradeHistoryTable
4415 * This is a helper function used in the upgrade process to fix upgrade_history entries so that the filename column points
4416 * to the new upload directory location introduced in 6.4 versions
4418 function repairUpgradeHistoryTable()
4420 require_once('modules/Configurator/Configurator.php');
4422 global $sugar_config;
4424 //Now upgrade the upgrade_history table entries
4425 $results = $GLOBALS['db']->query('SELECT id, filename FROM upgrade_history');
4426 $upload_dir = $sugar_config['cache_dir'].'upload/';
4428 //Create regular expression string to
4429 $match = '/^' . str_replace('/', '\/', $upload_dir) . '(.*?)$/';
4431 while(($row = $GLOBALS['db']->fetchByAssoc($results)))
4433 $file = str_replace('//', '/', $row['filename']); //Strip out double-paths that may exist
4435 if(!empty($file) && preg_match($match, $file, $matches))
4437 //Update new file location to use the new $sugar_config['upload_dir'] value
4438 $new_file_location = $sugar_config['upload_dir'] . $matches[1];
4439 $GLOBALS['db']->query("UPDATE upgrade_history SET filename = '{$new_file_location}' WHERE id = '{$row['id']}'");