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))
956 include_once($langPack);
957 elseif(file_exists($langPackEn))
958 include_once($langPackEn);
964 * checks system compliance for 4.5+ codebase
965 * @return array Mixed values
967 function checkSystemCompliance() {
968 global $sugar_config;
969 global $current_language;
973 if(!defined('SUGARCRM_MIN_MEM')) {
974 define('SUGARCRM_MIN_MEM', 40);
977 $installer_mod_strings = getModuleLanguagePack($current_language, './install');
979 $ret['error_found'] = false;
982 $php_version = constant('PHP_VERSION');
983 $check_php_version_result = check_php_version($php_version);
985 switch($check_php_version_result) {
987 $ret['phpVersion'] = "<b><span class=stop>{$installer_mod_strings['ERR_CHECKSYS_PHP_INVALID_VER']} {$php_version} )</span></b>";
988 $ret['error_found'] = true;
991 $ret['phpVersion'] = "<b><span class=go>{$installer_mod_strings['ERR_CHECKSYS_PHP_UNSUPPORTED']} {$php_version} )</span></b>";
994 $ret['phpVersion'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_PHP_OK']} {$php_version} )</span></b>";
998 // database and connect
1000 if($db->dbType == 'mysql')
1002 if(version_compare($v, '4.1.2') < 0) {
1003 $ret['error_found'] = true;
1004 $ret['mysqlVersion'] = "<b><span class=stop>".$mod_strings['ERR_UW_MYSQL_VERSION'].$v."</span></b>";
1006 } elseif($db->dbType == 'oci8') {
1007 if(!preg_match("/Oracle9i|Oracle Database 10g|11/i", $v)) {
1008 $ret['error_found'] = true;
1009 $ret['ociVersion'] = "<b><span class=stop>".$mod_strings['ERR_UW_OCI8_VERSION'].$v."</span></b>";
1015 if(function_exists('xml_parser_create')) {
1016 $ret['xmlStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1018 $ret['xmlStatus'] = "<b><span class=stop>{$installer_mod_strings['LBL_CHECKSYS_NOT_AVAILABLE']}</span></b>";
1019 $ret['error_found'] = true;
1023 if(function_exists('curl_init')) {
1024 $ret['curlStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1026 $ret['curlStatus'] = "<b><span class=go>{$installer_mod_strings['ERR_CHECKSYS_CURL']}</span></b>";
1027 $ret['error_found'] = false;
1031 if(function_exists('mb_strlen')) {
1032 $ret['mbstringStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1034 $ret['mbstringStatus'] = "<b><span class=stop>{$installer_mod_strings['ERR_CHECKSYS_MBSTRING']}</span></b>";
1035 $ret['error_found'] = true;
1039 if(function_exists('imap_open')) {
1040 $ret['imapStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1042 $ret['imapStatus'] = "<b><span class=go>{$installer_mod_strings['ERR_CHECKSYS_IMAP']}</span></b>";
1043 $ret['error_found'] = false;
1048 if('1' == ini_get('safe_mode')) {
1049 $ret['safeModeStatus'] = "<b><span class=stop>{$installer_mod_strings['ERR_CHECKSYS_SAFE_MODE']}</span></b>";
1050 $ret['error_found'] = true;
1052 $ret['safeModeStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1056 // call time pass by ref
1057 if('1' == ini_get('allow_call_time_pass_reference')) {
1058 $ret['callTimeStatus'] = "<b><span class=stop>{$installer_mod_strings['ERR_CHECKSYS_CALL_TIME']}</span></b>";
1059 //continue upgrading
1061 $ret['callTimeStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1065 $ret['memory_msg'] = "";
1066 $memory_limit = "-1";//ini_get('memory_limit');
1067 $sugarMinMem = constant('SUGARCRM_MIN_MEM');
1068 // logic based on: http://us2.php.net/manual/en/ini.core.php#ini.memory-limit
1069 if( $memory_limit == "" ){ // memory_limit disabled at compile time, no memory limit
1070 $ret['memory_msg'] = "<b><span class=\"go\">{$installer_mod_strings['LBL_CHECKSYS_MEM_OK']}</span></b>";
1071 } elseif( $memory_limit == "-1" ){ // memory_limit enabled, but set to unlimited
1072 $ret['memory_msg'] = "<b><span class=\"go\">{$installer_mod_strings['LBL_CHECKSYS_MEM_UNLIMITED']}</span></b>";
1074 rtrim($memory_limit, 'M');
1075 $memory_limit_int = (int) $memory_limit;
1076 if( $memory_limit_int < constant('SUGARCRM_MIN_MEM') ){
1077 $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>";
1078 $ret['error_found'] = true;
1080 $ret['memory_msg'] = "<b><span class=\"go\">{$installer_mod_strings['LBL_CHECKSYS_OK']} ({$memory_limit})</span></b>";
1084 /* mbstring.func_overload
1085 $ret['mbstring.func_overload'] = '';
1086 $mb = ini_get('mbstring.func_overload');
1089 $ret['mbstring.func_overload'] = "<b><span class=\"stop\">{$mod_strings['ERR_UW_MBSTRING_FUNC_OVERLOAD']}</b>";
1090 $ret['error_found'] = true;
1098 * is a file that we blow away automagically
1100 function isAutoOverwriteFile($file) {
1101 $overwriteDirs = array(
1102 './sugar_version.php',
1103 './modules/UpgradeWizard/uw_main.tpl',
1105 $file = trim('.'.str_replace(clean_path(getcwd()), '', $file));
1107 if(in_array($file, $overwriteDirs)) {
1111 $fileExtension = substr(strrchr($file, "."), 1);
1112 if($fileExtension == 'tpl' || $fileExtension == 'html') {
1122 function logThis($entry, $path='') {
1123 global $mod_strings;
1124 if(file_exists('include/utils/sugar_file_utils.php')){
1125 require_once('include/utils/sugar_file_utils.php');
1127 $log = empty($path) ? clean_path(getcwd().'/upgradeWizard.log') : clean_path($path);
1129 // create if not exists
1130 if(!file_exists($log)) {
1131 if(function_exists('sugar_fopen')){
1132 $fp = @sugar_fopen($log, 'w+'); // attempts to create file
1135 $fp = fopen($log, 'w+'); // attempts to create file
1137 if(!is_resource($fp)) {
1138 $GLOBALS['log']->fatal('UpgradeWizard could not create the upgradeWizard.log file');
1139 die($mod_strings['ERR_UW_LOG_FILE_UNWRITABLE']);
1142 if(function_exists('sugar_fopen')){
1143 $fp = @sugar_fopen($log, 'a+'); // write pointer at end of file
1146 $fp = @fopen($log, 'a+'); // write pointer at end of file
1149 if(!is_resource($fp)) {
1150 $GLOBALS['log']->fatal('UpgradeWizard could not open/lock upgradeWizard.log file');
1151 die($mod_strings['ERR_UW_LOG_FILE_UNWRITABLE']);
1155 $line = date('r').' [UpgradeWizard] - '.$entry."\n";
1157 if(@fwrite($fp, $line) === false) {
1158 $GLOBALS['log']->fatal('UpgradeWizard could not write to upgradeWizard.log: '.$entry);
1159 die($mod_strings['ERR_UW_LOG_FILE_UNWRITABLE']);
1162 if(is_resource($fp)) {
1170 * @desc This function is to be used in the upgrade process to preserve changes/customaizations made to pre 5.1 quickcreate layout.
1171 * 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
1172 * was automatically picked up by the quick create. [Addresses Bug 21469]
1173 * This function will check if customizations were made, and will create quickcreatedefs.php in the /cutom/working/$module_name directory.
1175 function updateQuickCreateDefs(){
1176 $d = dir('modules');
1177 $studio_modules = array();
1179 while($e = $d->read()){ //collect all studio modules.
1180 if(substr($e, 0, 1) == '.' || !is_dir('modules/' . $e))continue;
1181 if(file_exists('modules/' . $e . '/metadata/studio.php'))
1183 array_push($studio_modules, $e);
1187 foreach( $studio_modules as $modname ){ //for each studio enabled module
1188 //Check !exists modules/$modname/metadata/quickcreatedefs.php &&
1189 //exists custom/$modname/editviewdefs.php (module was customized) &&
1190 //!exists custom/$modname/quickcreateviewdefs.php
1192 $editviewdefs = "custom/working/modules/".$modname."/metadata/editviewdefs.php";
1193 $quickcreatedefs = "custom/working/modules/".$modname."/metadata/quickcreatedefs.php";
1195 if ( !file_exists("modules/".$modname."/metadata/quickcreatedefs.php") &&
1196 file_exists($editviewdefs) &&
1197 !file_exists($quickcreatedefs) ){
1198 //clone editviewdef and save it in custom/working/modules/metadata
1199 $GLOBALS['log']->debug("Copying editviewdefs.php as quickcreatedefs.php for the $modname module in custom/working/modules/$modname/metadata!");
1200 if(copy( $editviewdefs, $quickcreatedefs)){
1201 if(file_exists($quickcreatedefs) && is_readable($quickcreatedefs)){
1202 $file = file($quickcreatedefs);
1203 //replace 'EditView' with 'QuickCreate'
1204 $fp = fopen($quickcreatedefs,'w');
1205 foreach($file as &$line){
1206 if(preg_match('/^\s*\'EditView\'\s*=>\s*$/', $line) > 0){
1207 $line = "'QuickCreate' =>\n";
1215 $GLOBALS['log']->debug("Failed to replace 'EditView' with QuickCreate because $quickcreatedefs is either not readable or does not exist.");
1218 $GLOBALS['log']->debug("Failed to copy $editviewdefs to $quickcreatedefs!");
1225 * test perms for CREATE queries
1227 function testPermsCreate($db, $out) {
1228 logThis('Checking CREATE TABLE permissions...');
1229 global $mod_strings;
1231 if(!$db->checkPrivilege("CREATE TABLE")) {
1232 logThis('cannot CREATE TABLE!');
1233 $out['db']['dbNoCreate'] = true;
1234 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_CREATE']}</span></td></tr>";
1240 * test perms for INSERT
1242 function testPermsInsert($db, $out, $skip=false) {
1243 logThis('Checking INSERT INTO permissions...');
1244 global $mod_strings;
1246 if(!$db->checkPrivilege("INSERT")) {
1247 logThis('cannot INSERT INTO!');
1248 $out['db']['dbNoInsert'] = true;
1249 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_INSERT']}</span></td></tr>";
1256 * test perms for UPDATE TABLE
1258 function testPermsUpdate($db, $out, $skip=false) {
1259 logThis('Checking UPDATE TABLE permissions...');
1260 global $mod_strings;
1261 if(!$db->checkPrivilege("UPDATE")) {
1262 logThis('cannot UPDATE TABLE!');
1263 $out['db']['dbNoUpdate'] = true;
1264 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_UPDATE']}</span></td></tr>";
1271 * test perms for SELECT
1273 function testPermsSelect($db, $out, $skip=false) {
1274 logThis('Checking SELECT permissions...');
1275 global $mod_strings;
1276 if(!$db->checkPrivilege("SELECT")) {
1277 logThis('cannot SELECT!');
1278 $out['db']['dbNoSelect'] = true;
1279 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_SELECT']}</span></td></tr>";
1285 * test perms for DELETE
1287 function testPermsDelete($db, $out, $skip=false) {
1288 logThis('Checking DELETE FROM permissions...');
1289 global $mod_strings;
1290 if(!$db->checkPrivilege("DELETE")) {
1291 logThis('cannot DELETE FROM!');
1292 $out['db']['dbNoDelete'] = true;
1293 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_DELETE']}</span></td></tr>";
1300 * test perms for ALTER TABLE ADD COLUMN
1302 function testPermsAlterTableAdd($db, $out, $skip=false) {
1303 logThis('Checking ALTER TABLE ADD COLUMN permissions...');
1304 global $mod_strings;
1305 if(!$db->checkPrivilege("ADD COLUMN")) {
1306 logThis('cannot ADD COLUMN!');
1307 $out['db']['dbNoAddColumn'] = true;
1308 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_ADD_COLUMN']}</span></td></tr>";
1314 * test perms for ALTER TABLE ADD COLUMN
1316 function testPermsAlterTableChange($db, $out, $skip=false) {
1317 logThis('Checking ALTER TABLE CHANGE COLUMN permissions...');
1318 global $mod_strings;
1319 if(!$db->checkPrivilege("CHANGE COLUMN")) {
1320 logThis('cannot CHANGE COLUMN!');
1321 $out['db']['dbNoChangeColumn'] = true;
1322 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_CHANGE_COLUMN']}</span></td></tr>";
1328 * test perms for ALTER TABLE DROP COLUMN
1330 function testPermsAlterTableDrop($db, $out, $skip=false) {
1331 logThis('Checking ALTER TABLE DROP COLUMN permissions...');
1332 global $mod_strings;
1333 if(!$db->checkPrivilege("DROP COLUMN")) {
1334 logThis('cannot DROP COLUMN!');
1335 $out['db']['dbNoDropColumn'] = true;
1336 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_DROP_COLUMN']}</span></td></tr>";
1343 * test perms for DROP TABLE
1345 function testPermsDropTable($db, $out, $skip=false) {
1346 logThis('Checking DROP TABLE permissions...');
1347 global $mod_strings;
1348 if(!$db->checkPrivilege("DROP TABLE")) {
1349 logThis('cannot DROP TABLE!');
1350 $out['db']['dbNoDropTable'] = true;
1351 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_DROP_TABLE']}</span></td></tr>";
1356 function getFormattedError($error, $query) {
1357 $error = "<div><b>".$error;
1358 $error .= "</b>::{$query}</div>";
1364 * parses a query finding the table name
1365 * @param string query The query
1366 * @return string table The table
1368 function getTableFromQuery($query) {
1369 $standardQueries = array('ALTER TABLE', 'DROP TABLE', 'CREATE TABLE', 'INSERT INTO', 'UPDATE', 'DELETE FROM');
1370 $query = preg_replace("/[^A-Za-z0-9\_\s]/", "", $query);
1371 $query = trim(str_replace($standardQueries, '', $query));
1373 $firstSpc = strpos($query, " ");
1374 $end = ($firstSpc > 0) ? $firstSpc : strlen($query);
1375 $table = substr($query, 0, $end);
1382 function preLicenseCheck() {
1383 require_once('modules/UpgradeWizard/uw_files.php');
1385 global $sugar_config;
1386 global $mod_strings;
1387 global $sugar_version;
1389 if(!isset($sugar_version) || empty($sugar_version)) {
1390 require_once('./sugar_version.php');
1393 if(!isset($_SESSION['unzip_dir']) || empty($_SESSION['unzip_dir'])) {
1394 logThis('unzipping files in upgrade archive...');
1396 list($base_upgrade_dir, $base_tmp_upgrade_dir) = getUWDirs();
1398 //also come up with mechanism to read from upgrade-progress file
1399 if(!isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !is_file($_SESSION['install_file'])) {
1400 if (file_exists(clean_path($base_tmp_upgrade_dir)) && $handle = opendir(clean_path($base_tmp_upgrade_dir))) {
1401 while (false !== ($file = readdir($handle))) {
1402 if($file !="." && $file !="..") {
1403 if(is_file($base_tmp_upgrade_dir."/".$file."/manifest.php")){
1404 require_once($base_tmp_upgrade_dir."/".$file."/manifest.php");
1405 $package_name= $manifest['copy_files']['from_dir'];
1406 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")){
1407 $unzip_dir = $base_tmp_upgrade_dir."/".$file;
1408 if(file_exists("$base_upgrade_dir/patch/".$package_name.'.zip')){
1409 $_SESSION['install_file'] = $package_name.".zip";
1418 if(empty($_SESSION['install_file'])){
1419 unlinkUWTempFiles();
1421 echo 'Upload File not found so redirecting to Upgrade Start ';
1422 $redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
1423 echo '<form name="redirect" action="' .$redirect_new_wizard. '" method="POST">';
1424 $upgrade_directories_not_found =<<<eoq
1425 <table cellpadding="3" cellspacing="0" border="0">
1427 <th colspan="2" align="left">
1428 <span class='error'><b>'Upload file missing or has been deleted. Refresh the page to go back to UpgradeWizard start'</b></span>
1433 $uwMain = $upgrade_directories_not_found;
1436 $install_file = "$base_upgrade_dir/patch/".basename(urldecode( $_SESSION['install_file'] ));
1438 if(empty($unzip_dir)){
1439 $unzip_dir = mk_temp_dir( $base_tmp_upgrade_dir );
1441 $zip_from_dir = ".";
1443 $zip_force_copy = array();
1446 logThis('Could not create a temporary directory using mk_temp_dir( $base_tmp_upgrade_dir )');
1447 die($mod_strings['ERR_UW_NO_CREATE_TMP_DIR']);
1450 //double check whether unzipped .
1451 if(file_exists($unzip_dir ."/scripts") && file_exists($unzip_dir."/manifest.php")){
1455 unzip( $install_file, $unzip_dir );
1458 // assumption -- already validated manifest.php at time of upload
1459 require_once( "$unzip_dir/manifest.php" );
1461 if( isset( $manifest['copy_files']['from_dir'] ) && $manifest['copy_files']['from_dir'] != "" ){
1462 $zip_from_dir = $manifest['copy_files']['from_dir'];
1464 if( isset( $manifest['copy_files']['to_dir'] ) && $manifest['copy_files']['to_dir'] != "" ){
1465 $zip_to_dir = $manifest['copy_files']['to_dir'];
1467 if( isset( $manifest['copy_files']['force_copy'] ) && $manifest['copy_files']['force_copy'] != "" ){
1468 $zip_force_copy = $manifest['copy_files']['force_copy'];
1470 if( isset( $manifest['version'] ) ){
1471 $version = $manifest['version'];
1473 if( !is_writable( "config.php" ) ){
1474 return $mod_strings['ERR_UW_CONFIG'];
1477 $_SESSION['unzip_dir'] = clean_path($unzip_dir);
1478 $_SESSION['zip_from_dir'] = clean_path($zip_from_dir);
1479 logThis('unzip done.');
1481 $unzip_dir = $_SESSION['unzip_dir'];
1482 $zip_from_dir = $_SESSION['zip_from_dir'];
1485 //check if $_SESSION['unzip_dir'] and $_SESSION['zip_from_dir'] exist
1486 if(!isset($_SESSION['unzip_dir']) || !file_exists($_SESSION['unzip_dir'])
1487 || !isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !file_exists($_SESSION['install_file'])){
1489 unlinkUWTempFiles();
1491 echo 'Upload File not found so redirecting to Upgrade Start ';
1492 $redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
1493 echo '<form name="redirect" action="' .$redirect_new_wizard. '" method="POST">';
1494 $upgrade_directories_not_found =<<<eoq
1495 <table cellpadding="3" cellspacing="0" border="0">
1497 <th colspan="2" align="left">
1498 <span class='error'><b>'Upload file missing or has been deleted. Refresh the page to go back to UpgradeWizard start'</b></span>
1503 $uwMain = $upgrade_directories_not_found;
1507 logThis ('is SugarConfig there '.file_exists(clean_path($unzip_dir.'/'.$zip_from_dir."/include/SugarObjects/SugarConfig.php")));
1508 if(file_exists(clean_path($unzip_dir.'/'.$zip_from_dir."/include/SugarObjects/SugarConfig.php"))) {
1509 $file = clean_path($unzip_dir.'/'.$zip_from_dir."/include/SugarObjects/SugarConfig.php");
1510 $destFile = str_replace(clean_path($unzip_dir.'/'.$zip_from_dir), $cwd, $file);
1511 if(!is_dir(dirname($destFile))) {
1512 mkdir_recursive(dirname($destFile)); // make sure the directory exists
1514 copy($file,$destFile);
1515 //also copy include utils array utils
1516 $file = clean_path($unzip_dir.'/'.$zip_from_dir."/include/utils/array_utils.php");
1517 $destFile = str_replace(clean_path($unzip_dir.'/'.$zip_from_dir), $cwd, $file);
1518 if(!is_dir(dirname($destFile))) {
1519 mkdir_recursive(dirname($destFile)); // make sure the directory exists
1521 copy($file,$destFile);
1526 function preflightCheck() {
1527 require_once('modules/UpgradeWizard/uw_files.php');
1529 global $sugar_config;
1530 global $mod_strings;
1531 global $sugar_version;
1533 if(!isset($sugar_version) || empty($sugar_version)) {
1534 require_once('./sugar_version.php');
1537 unset($_SESSION['rebuild_relationships']);
1538 unset($_SESSION['rebuild_extensions']);
1540 // don't bother if are rechecking
1541 $manualDiff = array();
1542 if(!isset($_SESSION['unzip_dir']) || empty($_SESSION['unzip_dir'])) {
1543 logThis('unzipping files in upgrade archive...');
1545 list($base_upgrade_dir, $base_tmp_upgrade_dir) = getUWDirs();
1547 //Following is if User logged out unexpectedly and then logged into UpgradeWizard again.
1548 //also come up with mechanism to read from upgrade-progress file.
1549 if(!isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !is_file($_SESSION['install_file'])) {
1550 if (file_exists($base_tmp_upgrade_dir) && $handle = opendir($base_tmp_upgrade_dir)) {
1551 while (false !== ($file = readdir($handle))) {
1552 if($file !="." && $file !="..") {
1553 if(is_file($base_tmp_upgrade_dir."/".$file."/manifest.php")){
1554 require_once($base_tmp_upgrade_dir."/".$file."/manifest.php");
1555 $package_name= $manifest['copy_files']['from_dir'];
1556 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")){
1557 $unzip_dir = $base_tmp_upgrade_dir."/".$file;
1558 if(file_exists("$base_upgrade_dir/patch/".$package_name.'.zip')){
1559 $_SESSION['install_file'] = $package_name.".zip";
1568 if(empty($_SESSION['install_file'])){
1569 unlinkUWTempFiles();
1571 echo 'Upload File not found so redirecting to Upgrade Start ';
1572 $redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
1573 echo '<form name="redirect" action="' .$redirect_new_wizard. '" method="POST">';
1574 $upgrade_directories_not_found =<<<eoq
1575 <table cellpadding="3" cellspacing="0" border="0">
1577 <th colspan="2" align="left">
1578 <span class='error'><b>'Upload file missing or has been deleted. Refresh the page to go back to UpgradeWizard start'</b></span>
1583 $uwMain = $upgrade_directories_not_found;
1587 $install_file = "$base_upgrade_dir/patch/".basename(urldecode( $_SESSION['install_file'] ));
1589 if(empty($unzip_dir)){
1590 $unzip_dir = mk_temp_dir( $base_tmp_upgrade_dir );
1592 $zip_from_dir = ".";
1594 $zip_force_copy = array();
1597 logThis('Could not create a temporary directory using mk_temp_dir( $base_tmp_upgrade_dir )');
1598 die($mod_strings['ERR_UW_NO_CREATE_TMP_DIR']);
1601 //double check whether unzipped .
1602 if(file_exists($unzip_dir ."/scripts") && file_exists($unzip_dir."/manifest.php")){
1606 unzip( $install_file, $unzip_dir );
1609 // assumption -- already validated manifest.php at time of upload
1610 require_once( "$unzip_dir/manifest.php" );
1612 if( isset( $manifest['copy_files']['from_dir'] ) && $manifest['copy_files']['from_dir'] != "" ){
1613 $zip_from_dir = $manifest['copy_files']['from_dir'];
1615 if( isset( $manifest['copy_files']['to_dir'] ) && $manifest['copy_files']['to_dir'] != "" ){
1616 $zip_to_dir = $manifest['copy_files']['to_dir'];
1618 if( isset( $manifest['copy_files']['force_copy'] ) && $manifest['copy_files']['force_copy'] != "" ){
1619 $zip_force_copy = $manifest['copy_files']['force_copy'];
1621 if( isset( $manifest['version'] ) ){
1622 $version = $manifest['version'];
1624 if( !is_writable( "config.php" ) ){
1625 return $mod_strings['ERR_UW_CONFIG'];
1628 $_SESSION['unzip_dir'] = clean_path($unzip_dir);
1629 $_SESSION['zip_from_dir'] = clean_path($zip_from_dir);
1631 //logThis('unzip done.');
1633 $unzip_dir = $_SESSION['unzip_dir'];
1634 $zip_from_dir = $_SESSION['zip_from_dir'];
1636 //check if $_SESSION['unzip_dir'] and $_SESSION['zip_from_dir'] exist
1637 if(!isset($_SESSION['unzip_dir']) || !file_exists($_SESSION['unzip_dir'])
1638 || !isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !file_exists($_SESSION['install_file'])){
1640 unlinkUWTempFiles();
1642 echo 'Upload File not found so redirecting to Upgrade Start ';
1643 $redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
1644 echo '<form name="redirect" action="' .$redirect_new_wizard. '" method="POST">';
1645 $upgrade_directories_not_found =<<<eoq
1646 <table cellpadding="3" cellspacing="0" border="0">
1648 <th colspan="2" align="left">
1649 <span class='error'><b>'Upload file missing or has been deleted. Refresh the page to go back to UpgradeWizard start'</b></span>
1654 $uwMain = $upgrade_directories_not_found;
1657 //copy minimum required files
1658 fileCopy('include/utils/sugar_file_utils.php');
1660 $upgradeFiles = findAllFiles(clean_path("$unzip_dir/$zip_from_dir"), array());
1661 $cache_html_files= array();
1664 $md5_string = array();
1665 if(file_exists(clean_path(getcwd().'/files.md5'))){
1666 require(clean_path(getcwd().'/files.md5'));
1669 // file preflight checks
1670 logThis('verifying md5 checksums for files...');
1671 foreach($upgradeFiles as $file) {
1672 if(in_array(str_replace(clean_path("$unzip_dir/$zip_from_dir") . "/", '', $file), $uw_files))
1673 continue; // skip already loaded files
1675 if(strpos($file, '.md5'))
1676 continue; // skip md5 file
1678 // normalize file paths
1679 $file = clean_path($file);
1681 // check that we can move/delete the upgraded file
1682 if(!is_writable($file)) {
1683 $errors[] = $mod_strings['ERR_UW_FILE_NOT_WRITABLE'].": ".$file;
1685 // check that destination files are writable
1686 $destFile = getcwd().str_replace(clean_path($unzip_dir.'/'.$zip_from_dir), '', $file);
1688 if(is_file($destFile)) { // of course it needs to exist first...
1689 if(!is_writable($destFile)) {
1690 $errors[] = $mod_strings['ERR_UW_FILE_NOT_WRITABLE'].": ".$destFile;
1694 ///////////////////////////////////////////////////////////////////////
1696 // compare md5s and build up a manual merge list
1697 $targetFile = clean_path(".".str_replace(getcwd(),'',$destFile));
1699 if(is_file($destFile)) {
1700 if(strpos($targetFile, '.php')) {
1701 // handle PHP files that were hit with the security regex
1703 if(function_exists('sugar_fopen')){
1704 $fp = sugar_fopen($destFile, 'r');
1707 $fp = fopen($destFile, 'r');
1709 $filesize = filesize($destFile);
1711 $fileContents = stream_get_contents($fp);
1712 $targetMd5 = md5($fileContents);
1715 $targetMd5 = md5_file($destFile);
1719 if(isset($md5_string[$targetFile]) && $md5_string[$targetFile] != $targetMd5) {
1720 logThis('found a file with a differing md5: ['.$targetFile.']');
1721 $manualDiff[] = $destFile;
1724 ///////////////////////////////////////////////////////////////////////
1726 logThis('md5 verification done.');
1727 $errors['manual'] = $manualDiff;
1732 function fileCopy($file_path){
1733 if(file_exists(clean_path($_SESSION['unzip_dir'].'/'.$_SESSION['zip_from_dir'].'/'.$file_path))) {
1734 $file = clean_path($_SESSION['unzip_dir'].'/'.$_SESSION['zip_from_dir'].'/'.$file_path);
1735 $destFile = str_replace(clean_path($_SESSION['unzip_dir'].'/'.$_SESSION['zip_from_dir']), clean_path(getcwd()), $file);
1736 if(!is_dir(dirname($destFile))) {
1737 mkdir_recursive(dirname($destFile)); // make sure the directory exists
1739 copy_recursive($file,$destFile);
1742 function getChecklist($steps, $step) {
1743 global $mod_strings;
1745 $skip = array('start', 'cancel', 'uninstall','end');
1748 $ret = '<table cellpadding="3" cellspacing="4" border="0">';
1749 $ret .= '<tr><th colspan="3" align="left">'.$mod_strings['LBL_UW_CHECKLIST'].':</th></tr>';
1750 foreach($steps['desc'] as $k => $desc) {
1751 if(in_array($steps['files'][$j], $skip)) {
1756 //$status = "<span class='error'>{$mod_strings['LBL_UW_INCOMPLETE']}</span>";
1758 $desc_mod_post = '';
1760 if(isset($_SESSION['step'][$steps['files'][$k]]) && $_SESSION['step'][$steps['files'][$k]] == 'success') {
1761 //$status = $mod_strings['LBL_UW_COMPLETE'];
1765 if($k == $_REQUEST['step']) {
1766 //$status = $mod_strings['LBL_UW_IN_PROGRESS'];
1767 $desc_mod_pre = "<font color=blue><i>";
1768 $desc_mod_post = "</i></font>";
1771 $ret .= "<tr><td> </td><td><b>{$i}: {$desc_mod_pre}{$desc}{$desc_mod_post}</b></td>";
1772 $ret .= "<td id={$steps['files'][$j]}><i></i></td></tr>";
1780 function prepSystemForUpgrade() {
1781 global $sugar_config;
1782 global $sugar_flavor;
1783 global $mod_strings;
1784 global $current_language;
1786 global $base_upgrade_dir;
1787 global $base_tmp_upgrade_dir;
1788 list($p_base_upgrade_dir, $p_base_tmp_upgrade_dir) = getUWDirs();
1789 ///////////////////////////////////////////////////////////////////////////////
1790 //// Make sure variables exist
1791 if(empty($base_upgrade_dir)){
1792 $base_upgrade_dir = $p_base_upgrade_dir;
1794 if(empty($base_tmp_upgrade_dir)){
1795 $base_tmp_upgrade_dir = $p_base_tmp_upgrade_dir;
1797 sugar_mkdir($base_tmp_upgrade_dir, 0775, true);
1798 if(!isset($subdirs) || empty($subdirs)){
1799 $subdirs = array('full', 'langpack', 'module', 'patch', 'theme');
1802 $upgrade_progress_dir = $base_tmp_upgrade_dir;
1803 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
1804 if(file_exists($upgrade_progress_file)){
1805 if(function_exists('get_upgrade_progress') && function_exists('didThisStepRunBefore')){
1806 if(didThisStepRunBefore('end')){
1807 include($upgrade_progress_file);
1808 unset($upgrade_config);
1809 unlink($upgrade_progress_file);
1814 // increase the cuttoff time to 1 hour
1815 ini_set("max_execution_time", "3600");
1817 // make sure dirs exist
1818 if($subdirs != null){
1819 foreach($subdirs as $subdir) {
1820 sugar_mkdir("$base_upgrade_dir/$subdir", 0775, true);
1823 // array of special scripts that are executed during (un)installation-- key is type of script, value is filename
1824 if(!defined('SUGARCRM_PRE_INSTALL_FILE')) {
1825 define('SUGARCRM_PRE_INSTALL_FILE', 'scripts/pre_install.php');
1826 define('SUGARCRM_POST_INSTALL_FILE', 'scripts/post_install.php');
1827 define('SUGARCRM_PRE_UNINSTALL_FILE', 'scripts/pre_uninstall.php');
1828 define('SUGARCRM_POST_UNINSTALL_FILE', 'scripts/post_uninstall.php');
1831 $script_files = array(
1832 "pre-install" => constant('SUGARCRM_PRE_INSTALL_FILE'),
1833 "post-install" => constant('SUGARCRM_POST_INSTALL_FILE'),
1834 "pre-uninstall" => constant('SUGARCRM_PRE_UNINSTALL_FILE'),
1835 "post-uninstall" => constant('SUGARCRM_POST_UNINSTALL_FILE'),
1838 // check that the upload limit is set to 6M or greater
1839 define('SUGARCRM_MIN_UPLOAD_MAX_FILESIZE_BYTES', 6 * 1024 * 1024); // 6 Megabytes
1840 $upload_max_filesize = ini_get('upload_max_filesize');
1841 $upload_max_filesize_bytes = return_bytes($upload_max_filesize);
1843 if($upload_max_filesize_bytes < constant('SUGARCRM_MIN_UPLOAD_MAX_FILESIZE_BYTES')) {
1844 $GLOBALS['log']->debug("detected upload_max_filesize: $upload_max_filesize");
1845 $admin_strings = return_module_language($current_language, 'Administration');
1846 echo '<p class="error">'.$admin_strings['MSG_INCREASE_UPLOAD_MAX_FILESIZE'].' '.get_cfg_var('cfg_file_path')."</p>\n";
1850 if ( !function_exists('extractFile') ) {
1851 function extractFile($zip_file, $file_in_zip) {
1852 global $base_tmp_upgrade_dir;
1855 $absolute_base_tmp_upgrade_dir = clean_path($base_tmp_upgrade_dir);
1856 $relative_base_tmp_upgrade_dir = clean_path(str_replace(clean_path(getcwd()), '', $absolute_base_tmp_upgrade_dir));
1858 // mk_temp_dir expects relative pathing
1859 $my_zip_dir = mk_temp_dir($relative_base_tmp_upgrade_dir);
1861 unzip_file($zip_file, $file_in_zip, $my_zip_dir);
1863 return("$my_zip_dir/$file_in_zip");
1867 if ( !function_exists('extractManifest') ) {
1868 function extractManifest($zip_file) {
1869 logThis('extracting manifest.');
1870 return(extractFile($zip_file, "manifest.php"));
1874 if ( !function_exists('getInstallType') ) {
1875 function getInstallType($type_string) {
1878 $subdirs = array('full', 'langpack', 'module', 'patch', 'theme', 'temp');
1879 foreach($subdirs as $subdir) {
1880 if(preg_match("#/$subdir/#", $type_string)) {
1884 // return empty if no match
1889 function getImageForType($type) {
1891 global $mod_strings;
1896 $icon = SugarThemeRegistry::current()->getImage("Upgrade", "",null,null,'.gif',$mod_strings['LBL_UPGRADE']);
1899 $icon = SugarThemeRegistry::current()->getImage("LanguagePacks", "",null,null,'.gif',$mod_strings['LBL_LANGPACKS']);
1902 $icon = SugarThemeRegistry::current()->getImage("ModuleLoader", "",null,null,'.gif',$mod_strings['LBL_MODULELOADER']);
1905 $icon = SugarThemeRegistry::current()->getImage("PatchUpgrades", "",null,null,'.gif',$mod_strings['LBL_PATCHUPGRADES']);
1908 $icon = SugarThemeRegistry::current()->getImage("Themes", "",null,null,'.gif',$mod_strings['LBL_THEMES']);
1916 if ( !function_exists('getLanguagePackName') ) {
1917 function getLanguagePackName($the_file) {
1918 require_once("$the_file");
1919 if(isset($app_list_strings["language_pack_name"])) {
1920 return($app_list_strings["language_pack_name"]);
1926 function getUITextForType($type) {
1927 if($type == "full") {
1928 return("Full Upgrade");
1930 if($type == "langpack") {
1931 return("Language Pack");
1933 if($type == "module") {
1936 if($type == "patch") {
1939 if($type == "theme") {
1944 if ( !function_exists('validate_manifest') ) {
1946 * Verifies a manifest from a patch or module to be compatible with the current Sugar version and flavor
1947 * @param array manifest Standard manifest array
1948 * @return string Error message, blank on success
1950 function validate_manifest($manifest) {
1951 logThis('validating manifest.php file');
1952 // takes a manifest.php manifest array and validates contents
1954 global $sugar_version;
1955 global $sugar_flavor;
1956 global $mod_strings;
1958 if(!isset($manifest['type'])) {
1959 return $mod_strings['ERROR_MANIFEST_TYPE'];
1962 $type = $manifest['type'];
1964 if(getInstallType("/$type/") == "") {
1965 return $mod_strings['ERROR_PACKAGE_TYPE']. ": '" . $type . "'.";
1968 if(isset($manifest['acceptable_sugar_versions'])) {
1969 $version_ok = false;
1970 $matches_empty = true;
1971 if(isset($manifest['acceptable_sugar_versions']['exact_matches'])) {
1972 $matches_empty = false;
1973 foreach($manifest['acceptable_sugar_versions']['exact_matches'] as $match) {
1974 if($match == $sugar_version) {
1979 if(!$version_ok && isset($manifest['acceptable_sugar_versions']['regex_matches'])) {
1980 $matches_empty = false;
1981 foreach($manifest['acceptable_sugar_versions']['regex_matches'] as $match) {
1982 if(preg_match("/$match/", $sugar_version)) {
1988 if(!$matches_empty && !$version_ok) {
1989 return $mod_strings['ERROR_VERSION_INCOMPATIBLE']."<br />".
1990 $mod_strings['ERR_UW_VERSION'].$sugar_version;
1994 if(isset($manifest['acceptable_sugar_flavors']) && sizeof($manifest['acceptable_sugar_flavors']) > 0) {
1996 foreach($manifest['acceptable_sugar_flavors'] as $match) {
1997 if($match == $sugar_flavor) {
2002 return $mod_strings['ERROR_FLAVOR_INCOMPATIBLE']."<br />".
2003 $mod_strings['ERR_UW_FLAVOR'].$sugar_flavor."<br />".
2004 $mod_strings['ERR_UW_FLAVOR_2'].$manifest['acceptable_sugar_flavors'][0];
2012 function unlinkUploadFiles() {
2014 // logThis('at unlinkUploadFiles()');
2016 // if(isset($_SESSION['install_file']) && !empty($_SESSION['install_file'])) {
2017 // $upload = $_SESSION['install_file'];
2019 // if(is_file($upload)) {
2020 // logThis('unlinking ['.$upload.']');
2021 // @unlink($upload);
2027 * deletes files created by unzipping a package
2029 function unlinkUWTempFiles() {
2030 global $sugar_config;
2033 logThis('at unlinkUWTempFiles()');
2035 list($upgDir, $tempDir) = getUWDirs();
2037 if(file_exists($tempDir) && is_dir($tempDir)){
2038 $files = findAllFiles($tempDir, array(), false);
2040 foreach($files as $file) {
2041 if(!is_dir($file)) {
2042 //logThis('unlinking ['.$file.']', $path);
2047 $files = findAllFiles($tempDir, array(), true);
2048 foreach($files as $dir) {
2050 //logThis('removing dir ['.$dir.']', $path);
2054 $cacheFile = sugar_cached("modules/UpgradeWizard/_persistence.php");
2055 if(is_file($cacheFile)) {
2056 logThis("Unlinking Upgrade cache file: '_persistence.php'", $path);
2057 @unlink($cacheFile);
2060 logThis("finished!");
2064 * finds all files in the passed path, but skips select directories
2065 * @param string dir Relative path
2066 * @param array the_array Collections of found files/dirs
2067 * @param bool include_dir True if we want to include directories in the
2068 * returned collection
2070 function uwFindAllFiles($dir, $theArray, $includeDirs=false, $skipDirs=array(), $echo=false) {
2072 if (whetherNeedToSkipDir($dir, $skipDirs))
2077 if (!is_dir($dir)) { return $theArray; } // Bug # 46035, just checking for valid dir
2079 if ($d === false) { return $theArray; } // Bug # 46035, more checking
2081 while($f = $d->read()) {
2082 // bug 40793 Skip Directories array in upgradeWizard does not function correctly
2083 if($f == "." || $f == ".." || whetherNeedToSkipDir("$dir/$f", $skipDirs)) { // skip *nix self/parent
2087 // for AJAX length count
2093 if(is_dir("$dir/$f")) {
2094 if($includeDirs) { // add the directory if flagged
2095 $theArray[] = clean_path("$dir/$f");
2099 $theArray = uwFindAllFiles("$dir/$f/", $theArray, $includeDirs, $skipDirs, $echo);
2101 $theArray[] = clean_path("$dir/$f");
2114 * unset's UW's Session Vars
2116 function resetUwSession() {
2117 logThis('resetting $_SESSION');
2119 if(isset($_SESSION['committed']))
2120 unset($_SESSION['committed']);
2121 if(isset($_SESSION['sugar_version_file']))
2122 unset($_SESSION['sugar_version_file']);
2123 if(isset($_SESSION['upgrade_complete']))
2124 unset($_SESSION['upgrade_complete']);
2125 if(isset($_SESSION['allTables']))
2126 unset($_SESSION['allTables']);
2127 if(isset($_SESSION['alterCustomTableQueries']))
2128 unset($_SESSION['alterCustomTableQueries']);
2129 if(isset($_SESSION['skip_zip_upload']))
2130 unset($_SESSION['skip_zip_upload']);
2131 if(isset($_SESSION['sugar_version_file']))
2132 unset($_SESSION['sugar_version_file']);
2133 if(isset($_SESSION['install_file']))
2134 unset($_SESSION['install_file']);
2135 if(isset($_SESSION['unzip_dir']))
2136 unset($_SESSION['unzip_dir']);
2137 if(isset($_SESSION['zip_from_dir']))
2138 unset($_SESSION['zip_from_dir']);
2139 if(isset($_SESSION['overwrite_files']))
2140 unset($_SESSION['overwrite_files']);
2141 if(isset($_SESSION['schema_change']))
2142 unset($_SESSION['schema_change']);
2143 if(isset($_SESSION['uw_restore_dir']))
2144 unset($_SESSION['uw_restore_dir']);
2145 if(isset($_SESSION['step']))
2146 unset($_SESSION['step']);
2147 if(isset($_SESSION['files']))
2148 unset($_SESSION['files']);
2149 if(isset($_SESSION['Upgraded451Wizard'])){
2150 unset($_SESSION['Upgraded451Wizard']);
2152 if(isset($_SESSION['Initial_451to500_Step'])){
2153 unset($_SESSION['Initial_451to500_Step']);
2155 if(isset($_SESSION['license_shown']))
2156 unset($_SESSION['license_shown']);
2157 if(isset($_SESSION['sugarMergeRunResults']))
2158 unset($_SESSION['sugarMergeRunResults']);
2162 * runs rebuild scripts
2164 function UWrebuild() {
2168 //CCL - Comment this block out, it is called in end.php
2169 logThis('Rebuilding everything...', $path);
2170 require_once('modules/Administration/QuickRepairAndRebuild.php');
2171 $randc = new RepairAndClear();
2172 $randc->repairAndClearAll(array('clearAll'),array(translate('LBL_ALL_MODULES')), false, false);
2174 $query = "DELETE FROM versions WHERE name='Rebuild Extensions'";
2176 logThis('Registering rebuild record: '.$query, $path);
2177 logThis('Rebuild done.', $path);
2179 // insert a new database row to show the rebuild extensions is done
2180 $id = create_guid();
2181 $gmdate = gmdate('Y-m-d H:i:s');
2182 $date_entered = db_convert("'$gmdate'", 'datetime');
2183 $query = 'INSERT INTO versions (id, deleted, date_entered, date_modified, modified_user_id, created_by, name, file_version, db_version) '
2184 . "VALUES ('$id', '0', $date_entered, $date_entered, '1', '1', 'Rebuild Extensions', '4.0.0', '4.0.0')";
2186 logThis('Registering rebuild record in versions table: '.$query, $path);
2189 function getCustomTables() {
2192 return $db->tablesLike('%_cstm');
2195 function alterCustomTables($customTables)
2200 function getAllTables() {
2202 return $db->getTablesArray();
2205 function printAlterTableSql($tables)
2207 $alterTableSql = '';
2209 foreach($tables as $table)
2210 $alterTableSql .= "ALTER TABLE " . $table . " CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;" . "\n";
2212 return $alterTableSql;
2215 function executeConvertTablesSql($tables)
2219 foreach($tables as $table){
2220 $query = "ALTER TABLE " . $table . " CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci";
2222 logThis("Sending query: ".$query);
2223 $db->query($query);//, true, "An error has occured while performing db query. See log file for details.<br>");
2229 function testThis() {
2230 $files = uwFindAllFiles(getcwd().'/test', array());
2232 $out = "<table cellpadding='1' cellspacing='0' border='0'>\n";
2235 foreach($files as $file) {
2236 $relativeFile = clean_path(str_replace(getcwd().'/test', '', $file));
2237 $relativeFile = ($relativeFile{0} == '/') ? substr($relativeFile, 1, strlen($relativeFile)) : $relativeFile;
2239 $relativePath = dirname($relativeFile);
2241 if($relativePath == $priorPath) { // same dir, new file
2242 $out .= "<tr><td>".basename($relativeFile)."</td></tr>";
2243 $priorPath = $relativePath;
2257 function testThis2($dir, $id=0, $hide=false) {
2258 global $mod_strings;
2260 $dh = opendir($dir);
2263 $doHide = ($hide) ? 'none' : '';
2264 $out = "<div id='{$id}' style='display:{$doHide};'>";
2265 $out .= "<table cellpadding='1' cellspacing='0' style='border:0px solid #ccc'>\n";
2267 while($file = readdir($dh)) {
2268 if($file == '.' || $file == '..' || $file == 'CVS' || $file == '.cvsignore')
2271 if(is_dir($path.'/'.$file)) {
2272 $file = $path.'/'.$file;
2273 $newI = create_guid();
2274 $out .= "<tr><td valign='top'><a href='javascript:toggleNwFiles(\"{$newI}\");'>".SugarThemeRegistry::current()->getImage("Workflow", "", null, null, ".gif", $mod_strings['LBL_WORKFLOW'])."</a></td>\n";
2275 $out .= "<td valign='top'><b><a href='javascript:toggleNwFiles(\"{$newI}\");'>".basename($file)."</a></b></td></tr>";
2276 $out .= "<tr><td></td><td valign='top'>".testThis2($file, $newI, true)."</td></tr>";
2278 $out .= "<tr><td valign='top'> </td>\n";
2279 $out .= "<td valign='top'>".basename($file)."</td></tr>";
2283 $out .= "</tr></table>";
2294 function testThis3(&$files, $id, $hide, $previousPath = '') {
2295 if(!is_array($files) || empty($files))
2300 global $mod_strings;
2301 // expecting full path here
2302 foreach($files as $k => $file) {
2303 $file = str_replace(getcwd(), '', $file);
2304 $path = dirname($file);
2305 $fileName = basename($file);
2307 if($fileName == 'CVS' || $fileName == '.cvsignore')
2310 if($path == $previousPath) { // same directory
2311 // new row for each file
2312 $out .= "<tr><td valign='top' align='left'> </td>";
2313 $out .= "<td valign='top' align='left'>{$fileName}</td></tr>";
2314 } else { // new directory
2316 $out .= "<tr><td valign='top'><a href='javascript:toggleNwFiles(\"{$newI}\");'>".SugarThemeRegistry::current()->getImage("Workflow", "", null, null, ".gif", $mod_strings['LBL_WORKFLOW'])."</a></td>\n";
2317 $out .= "<td valign='top'><b><a href='javascript:toggleNwFiles(\"{$newI}\");'>".$fileName."</a></b></td></tr>";
2318 $recurse = testThis3($files, $newI, true, $previousPath);
2319 $out .= "<tr><td></td><td valign='top'>".$recurse."</td></tr>";
2322 $previousPath = $path;
2324 $display = ($hide) ? 'none' : '';
2326 <div id="{$id}" style="display:{$display}">
2327 <table cellpadding='1' cellspacing='0' border='0' style='border:1px solid #ccc'>
2336 function testThis4($filePath, $fileNodes=array(), $fileName='') {
2337 $path = dirname($filePath);
2338 $file = basename($filePath);
2340 $exFile = explode('/', $path);
2342 foreach($exFile as $pathSegment) {
2343 if(is_array($fileNodes[$pathSegment])) { // path already processed
2345 } else { // newly found path
2346 $fileNodes[$pathSegment] = array();
2349 if($fileName != '') {
2350 $fileNodes[$pathSegment][] = $fileName;
2359 ///////////////////////////////////////////////////////////////////////////////
2360 //// SYSTEM CHECK FUNCTIONS
2362 * generates an array with all files in the SugarCRM root directory, skipping
2364 * @return array files Array of files with absolute paths
2366 function getFilesForPermsCheck() {
2367 global $sugar_config;
2369 logThis('Got JSON call to find all files...');
2370 $filesNotWritable = array();
2371 $filesNWPerms = array();
2373 // add directories here that should be skipped when doing file permissions checks (cache/upload is the nasty one)
2375 $sugar_config['upload_dir'],
2377 $files = uwFindAllFiles(".", array(), true, $skipDirs, true);
2382 * checks files for permissions
2383 * @param array files Array of files with absolute paths
2384 * @return string result of check
2386 function checkFiles($files, $echo=false) {
2387 global $mod_strings;
2388 $filesNotWritable = array();
2391 <a href='javascript:void(0); toggleNwFiles(\"filesNw\");'>{$mod_strings['LBL_UW_SHOW_NW_FILES']}</a>
2392 <div id='filesNw' style='display:none;'>
2393 <table cellpadding='3' cellspacing='0' border='0'>
2395 <th align='left'>{$mod_strings['LBL_UW_FILE']}</th>
2396 <th align='left'>{$mod_strings['LBL_UW_FILE_PERMS']}</th>
2397 <th align='left'>{$mod_strings['LBL_UW_FILE_OWNER']}</th>
2398 <th align='left'>{$mod_strings['LBL_UW_FILE_GROUP']}</th>
2401 $isWindows = is_windows();
2402 foreach($files as $file) {
2405 if(!is_writable_windows($file)) {
2406 logThis('WINDOWS: File ['.$file.'] not readable - saving for display');
2407 // don't warn yet - we're going to use this to check against replacement files
2408 // aw: commented out; it's a hack to allow upgrade wizard to continue on windows... will fix later
2409 /*$filesNotWritable[$i] = $file;
2410 $filesNWPerms[$i] = substr(sprintf('%o',fileperms($file)), -4);
2411 $filesOut .= "<tr>".
2412 "<td><span class='error'>{$file}</span></td>".
2413 "<td>{$filesNWPerms[$i]}</td>".
2414 "<td>".$mod_strings['ERR_UW_CANNOT_DETERMINE_USER']."</td>".
2415 "<td>".$mod_strings['ERR_UW_CANNOT_DETERMINE_GROUP']."</td>".
2419 if(!is_writable($file)) {
2420 logThis('File ['.$file.'] not writable - saving for display');
2421 // don't warn yet - we're going to use this to check against replacement files
2422 $filesNotWritable[$i] = $file;
2423 $filesNWPerms[$i] = substr(sprintf('%o',fileperms($file)), -4);
2424 $owner = posix_getpwuid(fileowner($file));
2425 $group = posix_getgrgid(filegroup($file));
2426 $filesOut .= "<tr>".
2427 "<td><span class='error'>{$file}</span></td>".
2428 "<td>{$filesNWPerms[$i]}</td>".
2429 "<td>".$owner['name']."</td>".
2430 "<td>".$group['name']."</td>".
2437 $filesOut .= '</table></div>';
2439 $errors['files']['filesNotWritable'] = (count($filesNotWritable) > 0) ? true : false;
2440 if(count($filesNotWritable) < 1) {
2441 $filesOut = "{$mod_strings['LBL_UW_FILE_NO_ERRORS']}";
2447 function deletePackageOnCancel(){
2448 global $mod_strings;
2449 global $sugar_config;
2450 list($base_upgrade_dir, $base_tmp_upgrade_dir) = getUWDirs();
2451 logThis('running delete');
2452 if(!isset($_SESSION['install_file']) || ($_SESSION['install_file'] == "")) {
2453 logThis('ERROR: trying to delete non-existent file: ['.$_REQUEST['install_file'].']');
2454 $error = $mod_strings['ERR_UW_NO_FILE_UPLOADED'];
2456 // delete file in upgrades/patch
2457 $delete_me = "$base_upgrade_dir/patch/".basename(urldecode( $_REQUEST['install_file'] ));
2458 if(@unlink($delete_me)) {
2459 //logThis('unlinking: '.$delete_me);
2460 $out = basename($delete_me).$mod_strings['LBL_UW_FILE_DELETED'];
2462 logThis('ERROR: could not delete ['.$delete_me.']');
2463 $error = $mod_strings['ERR_UW_FILE_NOT_DELETED'].$delete_me;
2466 if(!empty($error)) {
2467 $out = "<b><span class='error'>{$error}</span></b><br />";
2471 function handleExecuteSqlKeys($db, $tableName, $disable)
2473 if(empty($tableName)) return true;
2474 if(is_callable(array($db, "supports"))) {
2476 return $disable?$db->disableKeys($tableName):$db->enableKeys($tableName);
2479 $op = $disable?"DISABLE":"ENABLE";
2480 return $db->query("ALTER TABLE $tableName $op KEYS");
2484 function parseAndExecuteSqlFile($sqlScript,$forStepQuery='',$resumeFromQuery='')
2486 global $sugar_config;
2487 $alterTableSchema = '';
2488 $sqlErrors = array();
2489 if(!isset($_SESSION['sqlSkippedQueries'])){
2490 $_SESSION['sqlSkippedQueries'] = array();
2492 $db = DBManagerFactory::getInstance();
2493 $disable_keys = ($db->dbType == "mysql"); // have to use old way for now for upgrades
2494 if(strpos($resumeFromQuery,",") != false){
2495 $resumeFromQuery = explode(",",$resumeFromQuery);
2497 if(file_exists($sqlScript)) {
2498 $fp = fopen($sqlScript, 'r');
2499 $contents = stream_get_contents($fp);
2500 $anyScriptChanges =$contents;
2501 $resumeAfterFound = false;
2505 while($line = fgets($fp)) {
2506 if(strpos($line, '--') === false) {
2507 $completeLine .= " ".trim($line);
2508 if(strpos($line, ';') !== false) {
2510 $query = str_replace(';','',$completeLine);
2511 //if resume from query is not null then find out from where
2512 //it should start executing the query.
2514 if($query != null && $resumeFromQuery != null){
2515 if(!$resumeAfterFound){
2516 if(strpos($query,",") != false){
2517 $queArray = explode(",",$query);
2518 for($i=0;$i<sizeof($resumeFromQuery);$i++){
2519 if(strcasecmp(trim($resumeFromQuery[$i]),trim($queArray[$i]))==0){
2520 $resumeAfterFound = true;
2522 $resumeAfterFound = false;
2528 elseif(strcasecmp(trim($resumeFromQuery),trim($query))==0){
2529 $resumeAfterFound = true;
2532 if($resumeAfterFound){
2535 // if $count=1 means it is just found so skip the query. Run the next one
2536 if($query != null && $resumeAfterFound && $count >1){
2537 $tableName = getAlterTable($query);
2540 handleExecuteSqlKeys($db, $tableName, true);
2543 if($db->checkError()){
2544 //put in the array to use later on
2545 $_SESSION['sqlSkippedQueries'][] = $query;
2549 handleExecuteSqlKeys($db, $tableName, false);
2551 $progQuery[$forStepQuery]=$query;
2552 post_install_progress($progQuery,$action='set');
2555 elseif($query != null){
2556 $tableName = getAlterTable($query);
2559 handleExecuteSqlKeys($db, $tableName, true);
2564 handleExecuteSqlKeys($db, $tableName, false);
2566 $progQuery[$forStepQuery]=$query;
2567 post_install_progress($progQuery,$action='set');
2568 if($db->checkError()){
2569 //put in the array to use later on
2570 $_SESSION['sqlSkippedQueries'][] = $query;
2582 function getAlterTable($query){
2583 $query = strtolower($query);
2584 if (preg_match('/^\s*alter\s+table\s+/', $query)) {
2585 $sqlArray = explode(" ", $query);
2586 $key = array_search('table', $sqlArray);
2587 return $sqlArray[($key+1)];
2593 function set_upgrade_vars(){
2594 logThis('setting session variables...');
2595 $upgrade_progress_dir = sugar_cached('upgrades/temp');
2596 if(!is_dir($upgrade_progress_dir)){
2597 mkdir_recursive($upgrade_progress_dir);
2599 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
2600 if(file_exists($upgrade_progress_file)){
2601 include($upgrade_progress_file);
2604 fopen($upgrade_progress_file, 'w+');
2606 if(!isset($upgrade_config) || $upgrade_config == null){
2607 $upgrade_config = array();
2608 $upgrade_config[1]['upgrade_vars']=array();
2610 if(isset($upgrade_config[1]) && isset($upgrade_config[1]['upgrade_vars']) && !is_array($upgrade_config[1]['upgrade_vars'])){
2611 $upgrade_config[1]['upgrade_vars'] = array();
2614 if(!isset($upgrade_vars) || $upgrade_vars == NULL){
2615 $upgrade_vars = array();
2617 if(isset($_SESSION['unzip_dir']) && !empty($_SESSION['unzip_dir']) && file_exists($_SESSION['unzip_dir'])){
2618 $upgrade_vars['unzip_dir']=$_SESSION['unzip_dir'];
2620 if(isset($_SESSION['install_file']) && !empty($_SESSION['install_file']) && file_exists($_SESSION['install_file'])){
2621 $upgrade_vars['install_file']=$_SESSION['install_file'];
2623 if(isset($_SESSION['Upgraded451Wizard']) && !empty($_SESSION['Upgraded451Wizard'])){
2624 $upgrade_vars['Upgraded451Wizard']=$_SESSION['Upgraded451Wizard'];
2626 if(isset($_SESSION['license_shown']) && !empty($_SESSION['license_shown'])){
2627 $upgrade_vars['license_shown']=$_SESSION['license_shown'];
2629 if(isset($_SESSION['Initial_451to500_Step']) && !empty($_SESSION['Initial_451to500_Step'])){
2630 $upgrade_vars['Initial_451to500_Step']=$_SESSION['Initial_451to500_Step'];
2632 if(isset($_SESSION['zip_from_dir']) && !empty($_SESSION['zip_from_dir'])){
2633 $upgrade_vars['zip_from_dir']=$_SESSION['zip_from_dir'];
2635 //place into the upgrade_config array and rewrite config array only if new values are being inserted
2636 if(isset($upgrade_vars) && $upgrade_vars != null && sizeof($upgrade_vars) > 0){
2637 foreach($upgrade_vars as $key=>$val){
2638 if($key != null && $val != null){
2639 $upgrade_config[1]['upgrade_vars'][$key]=$upgrade_vars[$key];
2642 ksort($upgrade_config);
2643 if(is_writable($upgrade_progress_file) && write_array_to_file( "upgrade_config", $upgrade_config,
2644 $upgrade_progress_file)) {
2645 //writing to the file
2650 function initialize_session_vars(){
2651 $upgrade_progress_dir = sugar_cached('upgrades/temp');
2652 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
2653 if(file_exists($upgrade_progress_file)){
2654 include($upgrade_progress_file);
2655 if(isset($upgrade_config) && $upgrade_config != null && is_array($upgrade_config) && sizeof($upgrade_config) >0){
2656 $currVarsArray=$upgrade_config[1]['upgrade_vars'];
2657 //print_r($currVarsArray);
2658 if(isset($currVarsArray) && $currVarsArray != null && is_array($currVarsArray) && sizeof($currVarsArray)>0){
2659 foreach($currVarsArray as $key=>$val){
2660 if($key != null && $val !=null){
2661 //set session variables
2662 $_SESSION[$key]=$val;
2671 //track the upgrade progress on each step
2672 //track the upgrade progress on each step
2673 function set_upgrade_progress($currStep,$currState,$currStepSub='',$currStepSubState=''){
2675 $upgrade_progress_dir = sugar_cached('upgrades/temp');
2676 if(!is_dir($upgrade_progress_dir)){
2677 mkdir_recursive($upgrade_progress_dir);
2679 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
2680 if(file_exists($upgrade_progress_file)){
2681 include($upgrade_progress_file);
2684 if(function_exists('sugar_fopen')){
2685 sugar_fopen($upgrade_progress_file, 'w+');
2688 fopen($upgrade_progress_file, 'w+');
2691 if(!isset($upgrade_config) || $upgrade_config == null){
2692 $upgrade_config = array();
2693 $upgrade_config[1]['upgrade_vars']=array();
2695 if(!is_array($upgrade_config[1]['upgrade_vars'])){
2696 $upgrade_config[1]['upgrade_vars'] = array();
2698 if($currStep != null && $currState != null){
2699 if(sizeof($upgrade_config) > 0){
2700 if($currStepSub != null && $currStepSubState !=null){
2701 //check if new status to be set or update
2702 //get the latest in array. since it has sub components prepare an array
2703 if(!empty($upgrade_config[sizeof($upgrade_config)][$currStep]) && is_array($upgrade_config[sizeof($upgrade_config)][$currStep])){
2704 $latestStepSub = currSubStep($upgrade_config[sizeof($upgrade_config)][$currStep]);
2705 if($latestStepSub == $currStepSub){
2706 $upgrade_config[sizeof($upgrade_config)][$currStep][$latestStepSub]=$currStepSubState;
2707 $upgrade_config[sizeof($upgrade_config)][$currStep][$currStep] = $currState;
2710 $upgrade_config[sizeof($upgrade_config)][$currStep][$currStepSub]=$currStepSubState;
2711 $upgrade_config[sizeof($upgrade_config)][$currStep][$currStep] = $currState;
2715 $currArray = array();
2716 $currArray[$currStep] = $currState;
2717 $currArray[$currStepSub] = $currStepSubState;
2718 $upgrade_config[sizeof($upgrade_config)+1][$currStep] = $currArray;
2722 //get the current upgrade progress
2723 $latestStep = get_upgrade_progress();
2724 //set the upgrade progress
2725 if($latestStep == $currStep){
2726 //update the current step with new progress status
2727 $upgrade_config[sizeof($upgrade_config)][$latestStep]=$currState;
2731 $upgrade_config[sizeof($upgrade_config)+1][$currStep]=$currState;
2733 // now check if there elements within array substeps
2737 //set the upgrade progress (just starting)
2738 $upgrade_config[sizeof($upgrade_config)+1][$currStep]= $currState;
2741 if(is_writable($upgrade_progress_file) && write_array_to_file( "upgrade_config", $upgrade_config,
2742 $upgrade_progress_file)) {
2743 //writing to the file
2749 function get_upgrade_progress(){
2750 $upgrade_progress_dir = sugar_cached('upgrades/temp');
2751 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
2754 if(file_exists($upgrade_progress_file)){
2755 include($upgrade_progress_file);
2756 if(!isset($upgrade_config) || $upgrade_config == null){
2757 $upgrade_config = array();
2759 if($upgrade_config != null && sizeof($upgrade_config) >1){
2760 $currArr = $upgrade_config[sizeof($upgrade_config)];
2761 if(is_array($currArr)){
2762 foreach($currArr as $key=>$val){
2770 function currSubStep($currStep){
2772 if(is_array($currStep)){
2773 foreach($currStep as $key=>$val){
2781 function currUpgradeState($currState){
2783 if(is_array($currState)){
2784 foreach($currState as $key=>$val){
2786 foreach($val as $k=>$v){
2800 function didThisStepRunBefore($step,$SubStep=''){
2801 if($step == null) return;
2802 $upgrade_progress_dir = sugar_cached('upgrades/temp');
2803 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
2806 if(file_exists($upgrade_progress_file)){
2807 include($upgrade_progress_file);
2808 if(isset($upgrade_config) && $upgrade_config != null && is_array($upgrade_config) && sizeof($upgrade_config) >0){
2809 for($i=1;$i<=sizeof($upgrade_config);$i++){
2810 if(is_array($upgrade_config[$i])){
2811 foreach($upgrade_config[$i] as $key=>$val){
2813 if(is_array($upgrade_config[$i][$step])){
2815 foreach ($upgrade_config[$i][$step] as $k=>$v){
2817 foreach($v as $k1=>$v1){
2818 if($SubStep != null){
2819 if($SubStep ==$k1 && $v1=='done'){
2826 elseif($SubStep !=null){
2827 if($SubStep==$k && $v=='done'){
2832 elseif($step==$k && $v=='done'){
2838 elseif($val=='done'){
2852 //get and set post install status
2853 function post_install_progress($progArray='',$action=''){
2854 $upgrade_progress_dir = sugar_cached('upgrades/temp');
2855 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
2856 if($action=='' || $action=='get'){
2857 //get the state of post install
2858 $currProg = array();
2859 if(file_exists($upgrade_progress_file)){
2860 include($upgrade_progress_file);
2861 if(is_array($upgrade_config[sizeof($upgrade_config)]['commit']['post_install']) && sizeof($upgrade_config[sizeof($upgrade_config)]['commit']['post_install'])>0){
2862 foreach($upgrade_config[sizeof($upgrade_config)]['commit']['post_install'] as $k=>$v){
2869 elseif($action=='set'){
2870 if(!is_dir($upgrade_progress_dir)){
2871 mkdir($upgrade_progress_dir);
2873 if(file_exists($upgrade_progress_file)){
2874 include($upgrade_progress_file);
2877 fopen($upgrade_progress_file, 'w+');
2879 if(!is_array($upgrade_config[sizeof($upgrade_config)]['commit']['post_install'])){
2880 $upgrade_config[sizeof($upgrade_config)]['commit']['post_install']=array();
2881 $upgrade_config[sizeof($upgrade_config)]['commit']['post_install']['post_install'] = 'in_progress';
2883 if($progArray != null && is_array($progArray)){
2884 foreach($progArray as $key=>$val){
2885 $upgrade_config[sizeof($upgrade_config)]['commit']['post_install'][$key]=$val;
2888 if(is_writable($upgrade_progress_file) && write_array_to_file( "upgrade_config", $upgrade_config,
2889 $upgrade_progress_file)) {
2890 //writing to the file
2895 function repairDBForUpgrade($execute=false,$path=''){
2897 global $current_user, $beanFiles;
2899 set_time_limit(3600);
2901 $db = &DBManagerFactory::getInstance();
2903 VardefManager::clearVardef();
2904 require_once('include/ListView/ListView.php');
2905 foreach ($beanFiles as $bean => $file) {
2906 require_once ($file);
2907 $focus = new $bean ();
2908 $sql .= $db->repairTable($focus, $execute);
2912 $olddictionary = $dictionary;
2913 unset ($dictionary);
2914 include ('modules/TableDictionary.php');
2915 foreach ($dictionary as $meta) {
2916 $tablename = $meta['table'];
2917 $fielddefs = $meta['fields'];
2918 $indices = $meta['indices'];
2919 $sql .= $db->repairTableParams($tablename, $fielddefs, $indices, $execute);
2922 foreach (explode("\n", $sql) as $line) {
2923 if (!empty ($line) && substr($line, -2) != "*/") {
2926 $qry_str .= $line . "\n";
2937 preg_replace('#(/\*.+?\*/\n*)#', '', $qry_str)
2939 logThis("*******START EXECUTING DB UPGRADE QUERIES***************",$path);
2940 logThis($sql,$path);
2941 logThis("*******END EXECUTING DB UPGRADE QUERIES****************",$path);
2950 * upgradeUserPreferences
2951 * This method updates the user_preferences table and sets the pages/dashlets for users
2952 * which have ACL access to Trackers so that the Tracker dashlets are set in their user perferences
2955 function upgradeUserPreferences() {
2956 global $sugar_config, $sugar_version;
2957 $uw_strings = return_module_language($GLOBALS['current_language'], 'UpgradeWizard');
2959 $localization = new Localization();
2960 $localeCoreDefaults = $localization->getLocaleConfigDefaults();
2962 // check the current system wide default_locale_name_format and add it to the list if it's not there
2963 if(empty($sugar_config['name_formats'])) {
2964 $sugar_config['name_formats'] = $localeCoreDefaults['name_formats'];
2965 if(!rebuildConfigFile($sugar_config, $sugar_version)) {
2966 $errors[] = $uw_strings['ERR_UW_CONFIG_WRITE'];
2970 $currentDefaultLocaleNameFormat = $sugar_config['default_locale_name_format'];
2972 if ($localization->isAllowedNameFormat($currentDefaultLocaleNameFormat)) {
2973 upgradeLocaleNameFormat($currentDefaultLocaleNameFormat);
2975 $sugar_config['default_locale_name_format'] = $localeCoreDefaults['default_locale_name_format'];
2976 if(!rebuildConfigFile($sugar_config, $sugar_version)) {
2977 $errors[] = $uw_strings['ERR_UW_CONFIG_WRITE'];
2979 $localization->createInvalidLocaleNameFormatUpgradeNotice();
2982 $db = &DBManagerFactory::getInstance();
2983 $result = $db->query("SELECT id FROM users where deleted = '0'");
2984 while($row = $db->fetchByAssoc($result))
2986 $current_user = new User();
2987 $current_user->retrieve($row['id']);
2989 // 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
2990 $currentUserNameFormat = $current_user->getPreference('default_locale_name_format');
2991 if ($localization->isAllowedNameFormat($currentUserNameFormat)) {
2992 upgradeLocaleNameFormat($currentUserNameFormat);
2994 $current_user->setPreference('default_locale_name_format', 's f l', 0, 'global');
2995 $current_user->savePreferencesToDB();
3003 * Checks if a locale name format is part of the default list, if not adds it to the config
3004 * @param $name_format string a local name format string such as 's f l'
3005 * @return bool true on successful write to config file, false on failure;
3007 function upgradeLocaleNameFormat($name_format) {
3008 global $sugar_config, $sugar_version;
3010 $localization = new Localization();
3011 $localeConfigDefaults = $localization->getLocaleConfigDefaults();
3013 $uw_strings = return_module_language($GLOBALS['current_language'], 'UpgradeWizard');
3014 if(empty($sugar_config['name_formats'])) {
3015 $sugar_config['name_formats'] = $localeConfigDefaults['name_formats'];
3016 if(!rebuildConfigFile($sugar_config, $sugar_version)) {
3017 $errors[] = $uw_strings['ERR_UW_CONFIG_WRITE'];
3020 if (!in_array($name_format, $sugar_config['name_formats'])) {
3021 $new_config = sugarArrayMerge($sugar_config['name_formats'], array($name_format=>$name_format));
3022 $sugar_config['name_formats'] = $new_config;
3023 if(!rebuildConfigFile($sugar_config, $sugar_version)) {
3024 $errors[] = $uw_strings['ERR_UW_CONFIG_WRITE'];
3033 function add_custom_modules_favorites_search(){
3034 $module_directories = scandir('modules');
3036 foreach($module_directories as $module_dir){
3037 if($module_dir == '.' || $module_dir == '..' || !is_dir("modules/{$module_dir}")){
3042 preg_match('/^[a-z0-9]{1,5}_[a-z0-9_]+$/i' , $module_dir, $matches);
3044 // Make sure the module was created by module builder
3045 if(empty($matches)){
3049 $full_module_dir = "modules/{$module_dir}/";
3050 $read_searchdefs_from = "{$full_module_dir}/metadata/searchdefs.php";
3051 $read_SearchFields_from = "{$full_module_dir}/metadata/SearchFields.php";
3052 $read_custom_SearchFields_from = "custom/{$full_module_dir}/metadata/SearchFields.php";
3054 // Studio can possibly override this file, so we check for a custom version of it
3055 if(file_exists("custom/{$full_module_dir}/metadata/searchdefs.php")){
3056 $read_searchdefs_from = "custom/{$full_module_dir}/metadata/searchdefs.php";
3059 if(file_exists($read_searchdefs_from) && file_exists($read_SearchFields_from)){
3062 require($read_searchdefs_from);
3063 foreach($searchdefs[$module_dir]['layout']['basic_search'] as $sf_array){
3064 if(isset($sf_array['name']) && $sf_array['name'] == 'favorites_only'){
3069 require($read_SearchFields_from);
3070 if(isset($searchFields[$module_dir]['favorites_only'])){
3074 if(!$found_sf1 && !$found_sf2){
3075 $searchdefs[$module_dir]['layout']['basic_search']['favorites_only'] = array('name' => 'favorites_only','label' => 'LBL_FAVORITES_FILTER','type' => 'bool',);
3076 $searchdefs[$module_dir]['layout']['advanced_search']['favorites_only'] = array('name' => 'favorites_only','label' => 'LBL_FAVORITES_FILTER','type' => 'bool',);
3077 $searchFields[$module_dir]['favorites_only'] = array(
3078 'query_type'=>'format',
3079 'operator' => 'subquery',
3080 'subquery' => 'SELECT sugarfavorites.record_id FROM sugarfavorites
3081 WHERE sugarfavorites.deleted=0
3082 and sugarfavorites.module = \''.$module_dir.'\'
3083 and sugarfavorites.assigned_user_id = \'{0}\'',
3084 'db_field'=>array('id')
3087 if(!is_dir("custom/{$full_module_dir}/metadata")){
3088 mkdir_recursive("custom/{$full_module_dir}/metadata");
3090 $success_sf1 = write_array_to_file('searchdefs', $searchdefs, "custom/{$full_module_dir}/metadata/searchdefs.php");
3091 $success_sf2 = write_array_to_file('searchFields', $searchFields, "{$full_module_dir}/metadata/SearchFields.php");
3094 logThis("add_custom_modules_favorites_search failed for searchdefs.php for {$module_dir}");
3097 logThis("add_custom_modules_favorites_search failed for SearchFields.php for {$module_dir}");
3099 if($success_sf1 && $success_sf2){
3100 logThis("add_custom_modules_favorites_search successfully updated searchdefs and searchFields for {$module_dir}");
3109 * upgradeModulesForTeamsets
3111 * This method adds the team_set_id values to the module tables that have the new team_set_id column
3112 * added through the SugarCRM 5.5.x upgrade process. It also adds the values into the team_sets and
3113 * team_sets_teams tables.
3115 * @param filter Array of modules to process; empty by default
3117 function upgradeModulesForTeamsets($filter=array()) {
3118 require('include/modules.php');
3119 foreach($beanList as $moduleName=>$beanName) {
3120 if(!empty($filter) && array_search($moduleName, $filter) === false) {
3123 if($moduleName == 'TeamMemberships' || $moduleName == 'ForecastOpportunities'){
3126 $bean = loadBean($moduleName);
3128 empty($bean->table_name)) {
3132 $FieldArray = $GLOBALS['db']->helper->get_columns($bean->table_name);
3133 if(!isset($FieldArray['team_id'])) {
3137 upgradeTeamColumn($bean, 'team_id');
3141 //Upgrade users table
3142 $bean = loadBean('Users');
3143 upgradeTeamColumn($bean, 'default_team');
3144 $result = $GLOBALS['db']->query("SELECT id FROM teams where deleted=0");
3145 while($row = $GLOBALS['db']->fetchByAssoc($result)) {
3146 $teamset = new TeamSet();
3147 $teamset->addTeams($row['id']);
3154 * Helper function to create a team_set_id column and also set team_set_id column
3155 * to have the value of the $column_name parameter
3157 * @param $bean SugarBean which we are adding team_set_id column to
3158 * @param $column_name The name of the column containing the default team_set_id value
3160 function upgradeTeamColumn($bean, $column_name) {
3161 //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
3162 //module that does not use the SugarObjects
3163 if(empty($bean->field_defs['team_set_id']) && $bean->module_dir != 'Trackers'){
3165 //at this point we could assume that since we have a team_id defined and not a team_set_id that we need to
3166 //add that field and the corresponding relationships
3167 $object = $bean->object_name;
3168 $module = $bean->module_dir;
3169 $object_name = $object;
3170 $_object_name = strtolower($object_name);
3172 if(!empty($GLOBALS['dictionary'][$object]['table'])){
3173 $table_name = $GLOBALS['dictionary'][$object]['table'];
3175 $table_name = strtolower($module);
3178 $path = 'include/SugarObjects/implements/team_security/vardefs.php';
3180 //go through each entry in the vardefs from team_security and unset anything that is already set in the core module
3181 //this will ensure we have the proper ordering.
3182 $fieldDiff = array_diff_assoc($vardefs['fields'], $GLOBALS['dictionary'][$bean->object_name]['fields']);
3184 $file = 'custom/Extension/modules/' . $bean->module_dir. '/Ext/Vardefs/teams.php';
3185 $contents = "<?php\n";
3186 if(!empty($fieldDiff)){
3187 foreach($fieldDiff as $key => $val){
3188 $contents .= "\n\$GLOBALS['dictionary']['". $object . "']['fields']['". $key . "']=" . var_export_helper($val) . ";";
3191 $relationshipDiff = array_diff_assoc($vardefs['relationships'], $GLOBALS['dictionary'][$bean->object_name]['relationships']);
3192 if(!empty($relationshipDiff)){
3193 foreach($relationshipDiff as $key => $val){
3194 $contents .= "\n\$GLOBALS['dictionary']['". $object . "']['relationships']['". $key . "']=" . var_export_helper($val) . ";";
3197 $indexDiff = array_diff_assoc($vardefs['indices'], $GLOBALS['dictionary'][$bean->object_name]['indices']);
3198 if(!empty($indexDiff)){
3199 foreach($indexDiff as $key => $val){
3200 $contents .= "\n\$GLOBALS['dictionary']['". $object . "']['indices']['". $key . "']=" . var_export_helper($val) . ";";
3203 if( $fh = @sugar_fopen( $file, 'wt' ) )
3205 fputs( $fh, $contents);
3210 //we have written out the teams.php into custom/Extension/modules/{$module_dir}/Ext/Vardefs/teams.php'
3211 //now let's merge back into vardefs.ext.php
3212 require_once('ModuleInstall/ModuleInstaller.php');
3213 $mi = new ModuleInstaller();
3214 $mi->merge_files('Ext/Vardefs/', 'vardefs.ext.php');
3215 VardefManager::loadVardef($bean->module_dir, $bean->object_name, true);
3216 $bean->field_defs = $GLOBALS['dictionary'][$bean->object_name]['fields'];
3219 if(isset($bean->field_defs['team_set_id'])) {
3220 //Create the team_set_id column
3221 $FieldArray = $GLOBALS['db']->helper->get_columns($bean->table_name);
3222 if(!isset($FieldArray['team_set_id'])) {
3223 $GLOBALS['db']->addColumn($bean->table_name, $bean->field_defs['team_set_id']);
3225 $indexArray = $GLOBALS['db']->helper->get_indices($bean->table_name);
3227 $indexName = getValidDBName('idx_'.strtolower($bean->table_name).'_tmst_id', true, 34);
3230 'name' => $indexName,
3232 'fields' => array('team_set_id')
3235 if(!isset($indexArray[$indexName])) {
3236 $GLOBALS['db']->addIndexes($bean->table_name, $indexDef);
3239 //Update the table's team_set_id column to have the same values as team_id
3240 $GLOBALS['db']->query("UPDATE {$bean->table_name} SET team_set_id = {$column_name}");
3245 * Update the folder subscription table which confirms to the team security mechanism but
3246 * the class SugarFolders does not extend SugarBean and is therefore never picked up by the
3247 * upgradeModulesForTeamsets function.
3249 function upgradeFolderSubscriptionsTeamSetId()
3251 logThis("In upgradeFolderSubscriptionsTeamSetId()");
3252 $query = "UPDATE folders SET team_set_id = team_id";
3253 $result = $GLOBALS['db']->query($query);
3254 logThis("Finished upgradeFolderSubscriptionsTeamSetId()");
3258 * upgradeModulesForTeam
3260 * This method update the associated_user_id, name, name_2 to the private team records on teams table
3261 * This function is used for upgrade process from 5.1.x and 5.2.x.
3264 function upgradeModulesForTeam() {
3265 logThis("In upgradeModulesForTeam()");
3266 $result = $GLOBALS['db']->query("SELECT id, user_name, first_name, last_name FROM users where deleted=0");
3268 while($row = $GLOBALS['db']->fetchByAssoc($result)) {
3269 $results2 = $GLOBALS['db']->query("SELECT id FROM teams WHERE name = '({$row['user_name']})'");
3271 if(!$assoc = $GLOBALS['db']->fetchByAssoc($results2)) {
3272 //if team does not exist, then lets create the team for this user
3275 $user->retrieve($row['id']);
3276 $team->new_user_created($user);
3277 $team_id = $team->id;
3279 $team_id =$assoc['id'];
3283 $name = is_null($row['first_name'])?'':$row['first_name'];
3284 $name_2 = is_null($row['last_name'])?'':$row['last_name'];
3285 $associated_user_id = $row['id'];
3288 //Ensure team->name is not empty by using team->name_2 if available
3289 if(empty($name) && !empty($name_2)) {
3294 $query = "UPDATE teams SET name = '{$name}', name_2 = '{$name_2}', associated_user_id = '{$associated_user_id}' WHERE id = '{$team_id}'";
3295 $GLOBALS['db']->query($query);
3298 //Update the team_set_id and default_team columns
3299 $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'));
3301 //Update team_set_id
3302 if($ce_to_pro_or_ent) {
3303 $GLOBALS['db']->query("update users set team_set_id = (select teams.id from teams where teams.associated_user_id = users.id)");
3304 $GLOBALS['db']->query("update users set default_team = (select teams.id from teams where teams.associated_user_id = users.id)");
3310 function addNewSystemTabsFromUpgrade($from_dir){
3312 if(isset($_SESSION['upgrade_from_flavor'])){
3314 //check to see if there are any new files that need to be added to systems tab
3315 //retrieve old modules list
3316 logThis('check to see if new modules exist',$path);
3317 $oldModuleList = array();
3318 $newModuleList = array();
3319 include($from_dir.'/include/modules.php');
3320 $oldModuleList = $moduleList;
3321 include('include/modules.php');
3322 $newModuleList = $moduleList;
3324 //include tab controller
3325 require_once('modules/MySettings/TabController.php');
3326 $newTB = new TabController();
3328 //make sure new modules list has a key we can reference directly
3329 $newModuleList = $newTB->get_key_array($newModuleList);
3330 $oldModuleList = $newTB->get_key_array($oldModuleList);
3332 //iterate through list and remove commonalities to get new modules
3333 foreach ($newModuleList as $remove_mod){
3334 if(in_array($remove_mod, $oldModuleList)){
3335 unset($newModuleList[$remove_mod]);
3338 //new modules list now has left over modules which are new to this install, so lets add them to the system tabs
3339 logThis('new modules to add are '.var_export($newModuleList,true),$path);
3341 if(!empty($newModuleList))
3343 //grab the existing system tabs
3344 $tabs = $newTB->get_system_tabs();
3346 //add the new tabs to the array
3347 foreach($newModuleList as $nm ){
3351 $newTB->set_system_tabs($tabs);
3353 logThis('module tabs updated',$path);
3359 * This method attempts to fix dropdown lists that were incorrectly named.
3360 * There were versions of SugarCRM that did not enforce naming convention rules
3361 * for the dropdown list field name. This method attempts to resolve that by
3362 * fixing the language files that may have been affected and then updating the
3363 * fields_meta_data table accordingly. It also refreshes any vardefs that may
3364 * have been affected.
3367 function fix_dropdown_list() {
3368 if(file_exists('custom/include/language')) {
3370 $affected_modules = array();
3371 $affected_keys = array();
3373 getFiles($files, 'custom/include/language', '/\.php$/i');
3374 foreach($files as $file) {
3376 if(file_exists($file . '.bak')) {
3377 $bak_mod_time = filemtime($file . '.bak');
3378 $php_mod_time = filemtime($file);
3379 //We're saying if the .php file was modified 30 seconds no more than php.bak file then we
3380 //run these additional cleanup checks
3381 if($php_mod_time - $bak_mod_time < 30) {
3383 $app_list_strings = array();
3384 $GLOBALS['app_list_strings'] = array();
3385 require($file . '.bak');
3386 $bak_app_list_strings = array_merge($app_list_strings, $GLOBALS['app_list_strings']);
3388 $app_list_strings = array();
3389 $GLOBALS['app_list_strings'] = array();
3391 $php_app_list_strings = array_merge($app_list_strings, $GLOBALS['app_list_strings']);
3393 //Get the file contents
3394 $contents = file_get_contents($file);
3396 //Now simulate a fix for the file before we compare w/ the .php file
3397 //we also append to the $contents
3398 foreach($bak_app_list_strings as $key=>$entry) {
3399 if(preg_match('/([^A-Za-z_])/', $key, $matches) && is_array($entry)) {
3400 $new_key = preg_replace('/[^A-Za-z_]/', '_', $key);
3401 $bak_app_list_strings[$new_key] = $bak_app_list_strings[$key];
3402 unset($bak_app_list_strings[$key]);
3403 //Now if the entry doesn't exists in the .php file, then add to contents
3404 if(!isset($php_app_list_strings[$new_key])) {
3405 $contents .= "\n\$GLOBALS['app_list_strings']['{$new_key}'] = " . var_export_helper($bak_app_list_strings[$new_key]) . ";";
3410 //Now load the .php file to do the comparison
3411 foreach($php_app_list_strings as $key=>$entry) {
3412 if(isset($bak_app_list_strings[$key])) {
3413 $diff = array_diff($bak_app_list_strings[$key], $entry);
3415 //There is a difference, so copy the $bak_app_list_strings version into the .php file
3416 $contents .= "\n\$GLOBALS['app_list_strings']['{$key}'] = " . var_export_helper($bak_app_list_strings[$key]) . ";";
3421 //Now write out the file contents
3422 //Create backup just in case
3423 copy($file, $file . '.php_bak');
3424 $fp = @sugar_fopen($file, 'w');
3426 fwrite($fp, $contents);
3429 $GLOBALS['log']->error("Unable to update file contents in fix_dropdown_list for {$file}");
3434 unset($GLOBALS['app_strings']);
3435 unset($GLOBALS['app_list_strings']);
3436 $app_list_strings = array();
3439 $contents = file_get_contents($file);
3440 if ( !isset($GLOBALS['app_list_strings']) ) {
3441 $GLOBALS['app_list_strings'] = $app_list_strings;
3444 $GLOBALS['app_list_strings'] = array_merge($app_list_strings, $GLOBALS['app_list_strings']);
3447 if(isset($GLOBALS['app_list_strings']) && is_array($GLOBALS['app_list_strings'])) {
3448 foreach($GLOBALS['app_list_strings'] as $key=>$entry) {
3449 if(preg_match('/([^A-Za-z_])/', $key, $matches) && is_array($entry)) {
3450 $result = $GLOBALS['db']->query("SELECT custom_module FROM fields_meta_data WHERE ext1 = '{$key}'");
3451 if(!empty($result)) {
3452 while($row = $GLOBALS['db']->fetchByAssoc($result)) {
3453 $custom_module = $row['custom_module'];
3454 if(!empty($GLOBALS['beanList'][$custom_module])) {
3455 $affected_modules[$custom_module] = $GLOBALS['beanList'][$custom_module];
3460 //Replace all invalid characters with '_' character
3461 $new_key = preg_replace('/[^A-Za-z_]/', '_', $key);
3462 $affected_keys[$key] = $new_key;
3464 $GLOBALS['app_list_strings'][$new_key] = $GLOBALS['app_list_strings'][$key];
3465 unset($GLOBALS['app_list_strings'][$key]);
3467 $pattern_match = "/(\[\s*\'{$key}\'\s*\])/";
3468 $new_key = "['{$new_key}']";
3469 $out = preg_replace($pattern_match, $new_key, $contents);
3475 //This is a check for g => h instances where the file contents were incorrectly written
3476 //and also fixes the scenario where via a UI upgrade, the app_list_strings were incorrectly
3477 //merged with app_list_strings variables declared elsewhere
3479 if(preg_match('/\$GLOBALS\s*\[\s*[\"|\']app_list_strings[\"|\']\s*\]\s*=\s*array\s*\(/', $contents)) {
3480 //Now also remove all the non-custom labels that were added
3481 if(preg_match('/language\/([^\.]+)\.lang\.php$/', $file, $matches)) {
3482 $language = $matches[1];
3484 $app_list_strings = array();
3486 if(file_exists("include/language/$language.lang.php")) {
3487 include("include/language/$language.lang.php");
3489 if(file_exists("include/language/$language.lang.override.php")) {
3490 $app_list_strings = _mergeCustomAppListStrings("include/language/$language.lang.override.php" , $app_list_strings) ;
3492 if(file_exists("custom/application/Ext/Language/$language.ext.lang.php")) {
3493 $app_list_strings = _mergeCustomAppListStrings("custom/application/Ext/Language/$language.ext.lang.php" , $app_list_strings) ;
3495 if(file_exists("custom/application/Ext/Language/$language.lang.ext.php")) {
3496 $app_list_strings = _mergeCustomAppListStrings("custom/application/Ext/Language/$language.lang.ext.php" , $app_list_strings) ;
3499 $all_non_custom_include_language_strings = $app_strings;
3500 $all_non_custom_include_language_list_strings = $app_list_strings;
3502 $unset_keys = array();
3503 if(!empty($GLOBALS['app_list_strings'])) {
3504 foreach($GLOBALS['app_list_strings'] as $key=>$value) {
3506 if(isset($all_non_custom_include_language_list_strings[$key])) {
3507 $diff = array_diff($all_non_custom_include_language_list_strings[$key], $GLOBALS['app_list_strings'][$key]);
3510 if(!empty($all_non_custom_include_language_list_strings[$key]) && empty($diff)) {
3511 $unset_keys[] = $key;
3516 foreach($unset_keys as $key) {
3517 unset($GLOBALS['app_list_strings'][$key]);
3520 if(!empty($GLOBALS['app_strings'])) {
3521 foreach($GLOBALS['app_strings'] as $key=>$value) {
3522 if(!empty($all_non_custom_include_language_strings[$key])) {
3523 unset($GLOBALS['app_strings'][$key]);
3527 } //if(preg_match...)
3530 if(!empty($GLOBALS['app_strings'])) {
3531 foreach($GLOBALS['app_strings'] as $key=>$entry) {
3532 $out .= "\n\$GLOBALS['app_strings']['$key']=" . var_export_helper($entry) . ";";
3536 foreach($GLOBALS['app_list_strings'] as $key=>$entry) {
3537 $out .= "\n\$GLOBALS['app_list_strings']['$key']=" . var_export_helper($entry) . ";";
3541 } //if(preg_match...)
3545 //Create a backup just in case
3546 copy($file, $file . '.bak');
3547 $fp = @sugar_fopen($file, 'w');
3552 //If we can't update the file, just return
3553 $GLOBALS['log']->error("Unable to update file contents in fix_dropdown_list.");
3561 //Update db entries (the order matters here... need to process database changes first)
3562 if(!empty($affected_keys)) {
3563 foreach($affected_keys as $old_key=>$new_key) {
3564 $GLOBALS['db']->query("UPDATE fields_meta_data SET ext1 = '{$new_key}' WHERE ext1 = '{$old_key}'");
3568 //Update vardef files for affected modules
3569 if(!empty($affected_modules)) {
3570 foreach($affected_modules as $module=>$object) {
3571 VardefManager::refreshVardefs($module, $object);
3578 function update_iframe_dashlets(){
3579 require_once(sugar_cached('dashlets/dashlets.php'));
3581 $db = DBManagerFactory::getInstance();
3582 $query = "SELECT id, contents, assigned_user_id FROM user_preferences WHERE deleted = 0 AND category = 'Home'";
3583 $result = $db->query($query, true, "Unable to update new default dashlets! ");
3584 while ($row = $db->fetchByAssoc($result)) {
3585 $content = unserialize(base64_decode($row['contents']));
3586 $assigned_user_id = $row['assigned_user_id'];
3587 $record_id = $row['id'];
3589 $current_user = new User();
3590 $current_user->retrieve($row['assigned_user_id']);
3592 if(!empty($content['dashlets']) && !empty($content['pages'])){
3593 $originalDashlets = $content['dashlets'];
3594 foreach($originalDashlets as $key => $ds){
3595 if(!empty($ds['options']['url']) && stristr($ds['options']['url'],'http://www.sugarcrm.com/crm/product/gopro')){
3596 unset($originalDashlets[$key]);
3599 $current_user->setPreference('dashlets', $originalDashlets, 0, 'Home');
3606 * convertImageToText
3608 * This method attempts to convert date type image to text on Microsoft SQL Server.
3609 * This method could NOT be used in any other type of datebases.
3611 function convertImageToText($table_name,$column_name){
3612 $set_lang = "SET LANGUAGE us_english";
3613 $GLOBALS['db']->query($set_lang);
3614 if($GLOBALS['db']->lastError()){
3615 logThis('An error occurred when performing this query-->'.$set_lang);
3617 $q="SELECT data_type
3618 FROM INFORMATION_SCHEMA.Tables T JOIN INFORMATION_SCHEMA.Columns C
3619 ON T.TABLE_NAME = C.TABLE_NAME where T.TABLE_NAME = '$table_name' and C.COLUMN_NAME = '$column_name'";
3620 $res= $GLOBALS['db']->query($q);
3621 if($GLOBALS['db']->lastError()){
3622 logThis('An error occurred when performing this query-->'.$q);
3624 $row= $GLOBALS['db']->fetchByAssoc($res);
3626 if(trim(strtolower($row['data_type'])) == 'image'){
3627 $addContent_temp = "alter table {$table_name} add {$column_name}_temp text null";
3628 $GLOBALS['db']->query($addContent_temp);
3629 if($GLOBALS['db']->lastError()){
3630 logThis('An error occurred when performing this query-->'.$addContent_temp);
3632 $qN = "select count=datalength({$column_name}), id, {$column_name} from {$table_name}";
3633 $result = $GLOBALS['db']->query($qN);
3634 while($row = $GLOBALS['db']->fetchByAssoc($result)){
3635 if($row['count'] >8000){
3636 $contentLength = $row['count'];
3639 $convertedContent = '';
3640 while($contentLength >0){
3641 $stepsQuery = "select cont=convert(varchar(max), convert(varbinary(8000), substring({$column_name},{$start},{$next}))) from {$table_name} where id= '{$row['id']}'";
3642 $steContQ = $GLOBALS['db']->query($stepsQuery);
3643 if($GLOBALS['db']->lastError()){
3644 logThis('An error occurred when performing this query-->'.$stepsQuery);
3646 $stepCont = $GLOBALS['db']->fetchByAssoc($steContQ);
3647 if(isset($stepCont['cont'])){
3648 $convertedContent = $convertedContent.$stepCont['cont'];
3650 $start = $start+$next;
3651 $contentLength = $contentLength - $next;
3653 $addContentDataText="update {$table_name} set {$column_name}_temp = '{$convertedContent}' where id= '{$row['id']}'";
3654 $GLOBALS['db']->query($addContentDataText);
3655 if($GLOBALS['db']->lastError()){
3656 logThis('An error occurred when performing this query-->'.$addContentDataText);
3660 $addContentDataText="update {$table_name} set {$column_name}_temp =
3661 convert(varchar(max), convert(varbinary(8000), {$column_name})) where id= '{$row['id']}'";
3662 $GLOBALS['db']->query($addContentDataText);
3663 if($GLOBALS['db']->lastError()){
3664 logThis('An error occurred when performing this query-->'.$addContentDataText);
3668 //drop the contents now and change contents_temp to contents
3669 $dropColumn = "alter table {$table_name} drop column {$column_name}";
3670 $GLOBALS['db']->query($dropColumn);
3671 if($GLOBALS['db']->lastError()){
3672 logThis('An error occurred when performing this query-->'.$dropColumn);
3674 $changeColumnName = "EXEC sp_rename '{$table_name}.[{$column_name}_temp]','{$column_name}','COLUMN'";
3675 $GLOBALS['db']->query($changeColumnName);
3676 if($GLOBALS['db']->lastError()){
3677 logThis('An error occurred when performing this query-->'.$changeColumnName);
3684 * This method attempts to delete all English inline help files.
3685 * This method was introduced by 5.5.0RC2.
3687 function clearHelpFiles(){
3688 $modulePath = clean_path(getcwd() . '/modules');
3689 $allHelpFiles = array();
3690 getFiles($allHelpFiles, $modulePath, "/en_us.help.*/");
3692 foreach( $allHelpFiles as $the_file ){
3693 if( is_file( $the_file ) ){
3694 unlink( $the_file );
3695 logThis("Deleted file: $the_file");
3703 * upgradeDateTimeFields
3705 * This method came from bug: 39757 where the date_end field is a date field and not a datetime field
3706 * which prevents you from performing timezone offset calculations once the data has been saved.
3708 * @param path String location to log file, empty by default
3710 function upgradeDateTimeFields($path)
3714 $meetingsSql = "UPDATE meetings SET date_end = ".$db->convert("date_start", 'add_time', array('duration_hours', 'duration_minutes'));
3715 $callsSql = "UPDATE calls SET date_end = ".$db->convert("date_start", 'add_time', array('duration_hours', 'duration_minutes'));
3716 logThis('upgradeDateTimeFields Meetings SQL:' . $meetingsSql, $path);
3717 $db->query($meetingsSql);
3719 logThis('upgradeDateTimeFields Calls SQL:' . $callsSql, $path);
3720 $db->query($callsSql);
3724 * upgradeDocumentTypeFields
3727 function upgradeDocumentTypeFields($path){
3731 $documentsSql = "UPDATE documents SET doc_type = 'Sugar' WHERE doc_type IS NULL";
3732 $meetingsSql = "UPDATE meetings SET type = 'Sugar' WHERE type IS NULL";
3734 logThis('upgradeDocumentTypeFields Documents SQL:' . $documentsSql, $path);
3735 $db->query($documentsSql);
3736 logThis('upgradeDocumentTypeFields Meetings SQL:' . $meetingsSql, $path);
3737 $db->query($meetingsSql);
3742 * merge_config_si_settings
3743 * This method checks for the presence of a config_si.php file and, if found, merges the configuration
3744 * settings from the config_si.php file into config.php. If a config_si_location parameter value is not
3745 * supplied it will attempt to discover the config_si.php file location from where the executing script
3748 * @param write_to_upgrade_log boolean optional value to write to the upgradeWizard.log file
3749 * @param config_location String optional value to config.php file location
3750 * @param config_si_location String optional value to config_si.php file location
3751 * @param path String file of the location of log file to write to
3752 * @return boolean value indicating whether or not a merge was attempted with config_si.php file
3754 function merge_config_si_settings($write_to_upgrade_log=false, $config_location='', $config_si_location='', $path='')
3756 if(!empty($config_location) && !file_exists($config_location))
3758 if($write_to_upgrade_log)
3760 logThis('config.php file specified in ' . $config_si_location . ' could not be found. Skip merging', $path);
3763 } else if(empty($config_location)) {
3765 //We are assuming this is from the silentUpgrade scripts so argv[3] will point to SugarCRM install location
3766 if(isset($argv[3]) && is_dir($argv[3]))
3768 $config_location = $argv[3] . DIRECTORY_SEPARATOR . 'config.php';
3772 //If config_location is still empty or if the file cannot be found, skip merging
3773 if(empty($config_location) || !file_exists($config_location))
3775 if($write_to_upgrade_log)
3777 logThis('config.php file at (' . $config_location . ') could not be found. Skip merging.', $path);
3781 if($write_to_upgrade_log)
3783 logThis('Loading config.php file at (' . $config_location . ') for merging.', $path);
3786 include($config_location);
3787 if(empty($sugar_config))
3789 if($write_to_upgrade_log)
3791 logThis('config.php contents are empty. Skip merging.', $path);
3797 if(!empty($config_si_location) && !file_exists($config_si_location))
3799 if($write_to_upgrade_log)
3801 logThis('config_si.php file specified in ' . $config_si_location . ' could not be found. Skip merging', $path);
3804 } else if(empty($config_si_location)) {
3805 if(isset($argv[0]) && is_file($argv[0]))
3807 $php_file = $argv[0];
3808 $p_info = pathinfo($php_file);
3809 $php_dir = (isset($p_info['dirname']) && $p_info['dirname'] != '.') ? $p_info['dirname'] . DIRECTORY_SEPARATOR : '';
3810 $config_si_location = $php_dir . 'config_si.php';
3814 //If config_si_location is still empty or if the file cannot be found, skip merging
3815 if(empty($config_si_location) || !file_exists($config_si_location))
3817 if($write_to_upgrade_log)
3819 logThis('config_si.php file at (' . $config_si_location . ') could not be found. Skip merging.', $path);
3823 if($write_to_upgrade_log)
3825 logThis('Loading config_si.php file at (' . $config_si_location . ') for merging.', $path);
3828 include($config_si_location);
3829 if(empty($sugar_config_si))
3831 if($write_to_upgrade_log)
3833 logThis('config_si.php contents are empty. Skip merging.', $path);
3839 //Now perform the merge operation
3841 foreach($sugar_config_si as $key=>$value)
3843 if(!preg_match('/^setup_/', $key) && !isset($sugar_config[$key]))
3845 if($write_to_upgrade_log)
3847 logThis('Merge key (' . $key . ') with value (' . $value . ')', $path);
3849 $sugar_config[$key] = $value;
3856 if($write_to_upgrade_log)
3858 logThis('Update config.php file with new values', $path);
3861 if(!write_array_to_file("sugar_config", $sugar_config, $config_location)) {
3862 if($write_to_upgrade_log)
3864 logThis('*** ERROR: could not write to config.php', $path);
3869 if($write_to_upgrade_log)
3871 logThis('config.php values are in sync with config_si.php values. Skipped merging.');
3876 if($write_to_upgrade_log)
3878 logThis('End merge_config_si_settings', $path);
3885 * upgrade_connectors
3887 * This function handles support for upgrading connectors it is invoked from both end.php and silentUpgrade_step2.php
3890 function upgrade_connectors() {
3891 require_once('include/connectors/utils/ConnectorUtils.php');
3892 if(!ConnectorUtils::updateMetaDataFiles()) {
3893 $GLOBALS['log']->fatal('Cannot update metadata files for connectors');
3896 //Delete the custom connectors.php file if it exists so that it may be properly rebuilt
3897 if(file_exists('custom/modules/Connectors/metadata/connectors.php'))
3899 unlink('custom/modules/Connectors/metadata/connectors.php');
3904 * Enable the InsideView connector for the four default modules.
3906 function upgradeEnableInsideViewConnector($path='')
3908 logThis('Begin upgradeEnableInsideViewConnector', $path);
3910 // Load up the existing mapping and hand it to the InsideView connector to have it setup the correct logic hooks
3911 $mapFile = 'modules/Connectors/connectors/sources/ext/rest/insideview/mapping.php';
3912 if ( file_exists('custom/'.$mapFile) ) {
3913 logThis('Found CUSTOM mappings', $path);
3914 require('custom/'.$mapFile);
3916 logThis('Used default mapping', $path);
3920 require_once('include/connectors/sources/SourceFactory.php');
3921 $source = SourceFactory::getSource('ext_rest_insideview');
3923 // $mapping is brought in from the mapping.php file above
3924 $source->saveMappingHook($mapping);
3926 require_once('include/connectors/utils/ConnectorUtils.php');
3927 ConnectorUtils::installSource('ext_rest_insideview');
3929 // Now time to set the various modules to active, because this part ignores the default config
3930 require(CONNECTOR_DISPLAY_CONFIG_FILE);
3931 // $modules_sources come from that config file
3932 foreach ( $source->allowedModuleList as $module ) {
3933 $modules_sources[$module]['ext_rest_insideview'] = 'ext_rest_insideview';
3935 if(!write_array_to_file('modules_sources', $modules_sources, CONNECTOR_DISPLAY_CONFIG_FILE)) {
3936 //Log error and return empty array
3937 logThis("Cannot write \$modules_sources to " . CONNECTOR_DISPLAY_CONFIG_FILE,$path);
3940 logThis('End upgradeEnableInsideViewConnector', $path);
3944 function repair_long_relationship_names($path='')
3946 logThis("Begin repair_long_relationship_names", $path);
3947 require_once 'modules/ModuleBuilder/parsers/relationships/DeployedRelationships.php' ;
3948 $GLOBALS['mi_remove_tables'] = false;
3950 foreach($GLOBALS['moduleList'] as $module)
3952 $relationships = new DeployedRelationships ($module) ;
3953 foreach($relationships->getRelationshipList() as $rel_name)
3955 if (strlen($rel_name) > 27 && empty($touched[$rel_name]))
3957 logThis("Rebuilding relationship fields for $rel_name", $path);
3958 $touched[$rel_name] = true;
3959 $rel_obj = $relationships->get($rel_name);
3960 $rel_obj->setReadonly(false);
3961 $relationships->delete($rel_name);
3962 $relationships->save();
3963 $relationships->add($rel_obj);
3964 $relationships->save();
3965 $relationships->build () ;
3969 logThis("End repair_long_relationship_names", $path);
3972 function removeSilentUpgradeVarsCache(){
3973 global $silent_upgrade_vars_loaded;
3975 $cacheFileDir = "{$GLOBALS['sugar_config']['cache_dir']}/silentUpgrader";
3976 $cacheFile = "{$cacheFileDir}/silentUpgradeCache.php";
3978 if(file_exists($cacheFile)){
3982 $silent_upgrade_vars_loaded = array(); // Set to empty to reset it
3987 function loadSilentUpgradeVars(){
3988 global $silent_upgrade_vars_loaded;
3990 if(empty($silent_upgrade_vars_loaded)){
3991 $cacheFile = "{$GLOBALS['sugar_config']['cache_dir']}/silentUpgrader/silentUpgradeCache.php";
3992 // We have no pre existing vars
3993 if(!file_exists($cacheFile)){
3994 // Set the vars array so it's loaded
3995 $silent_upgrade_vars_loaded = array('vars' => array());
3998 require_once($cacheFile);
3999 $silent_upgrade_vars_loaded = $silent_upgrade_vars_cache;
4006 function writeSilentUpgradeVars(){
4007 global $silent_upgrade_vars_loaded;
4009 if(empty($silent_upgrade_vars_loaded)){
4010 return false; // You should have set some values before trying to write the silent upgrade vars
4013 $cacheFileDir = "{$GLOBALS['sugar_config']['cache_dir']}/silentUpgrader";
4014 $cacheFile = "{$cacheFileDir}/silentUpgradeCache.php";
4016 require_once('include/dir_inc.php');
4017 if(!mkdir_recursive($cacheFileDir)){
4020 require_once('include/utils/file_utils.php');
4021 if(!write_array_to_file('silent_upgrade_vars_cache', $silent_upgrade_vars_loaded, $cacheFile, 'w')){
4023 logThis("WARNING: writeSilentUpgradeVars could not write to {$cacheFile}", $path);
4030 function setSilentUpgradeVar($var, $value){
4031 if(!loadSilentUpgradeVars()){
4035 global $silent_upgrade_vars_loaded;
4037 $silent_upgrade_vars_loaded['vars'][$var] = $value;
4042 function getSilentUpgradeVar($var){
4043 if(!loadSilentUpgradeVars()){
4047 global $silent_upgrade_vars_loaded;
4049 if(!isset($silent_upgrade_vars_loaded['vars'][$var])){
4053 return $silent_upgrade_vars_loaded['vars'][$var];
4059 * add_unified_search_to_custom_modules_vardefs
4061 * This method calls the repair code to remove the unified_search_modules.php fiel
4064 function add_unified_search_to_custom_modules_vardefs()
4066 if(file_exists($cachefile = sugar_cached('modules/unified_search_modules.php')))
4074 * change from using the older SugarCache in 6.1 and below to the new one in 6.2
4076 function upgradeSugarCache($file)
4078 global $sugar_config;
4079 $cacheUploadUpgradesTemp = mk_temp_dir(sugar_cached('upgrades/temp'));
4081 unzip($file, $cacheUploadUpgradesTemp);
4083 if(!file_exists(clean_path("{$cacheUploadUpgradesTemp}/manifest.php"))) {
4084 logThis("*** ERROR: no manifest file detected while bootstraping upgrade wizard files!");
4087 include(clean_path("{$cacheUploadUpgradesTemp}/manifest.php"));
4090 $from_dir = "{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}";
4091 $allFiles = array();
4092 if(file_exists("$from_dir/include/SugarCache")) {
4093 $allFiles = findAllFiles("$from_dir/include/SugarCache", $allFiles);
4095 if(file_exists("$from_dir/include/database")) {
4096 $allFiles = findAllFiles("$from_dir/include/database", $allFiles);
4098 if(file_exists("$from_dir/include/utils/external_cache.php")) {
4099 $allFiles[] = "$from_dir/include/utils/external_cache.php";
4101 if(file_exists("$from_dir/include/utils/sugar_file_utils.php")) {
4102 $allFiles[] = "$from_dir/include/utils/sugar_file_utils.php";
4104 if(file_exists("$from_dir/include/utils/sugar_file_utils.php")) {
4105 $allFiles[] = "$from_dir/include/utils/sugar_file_utils.php";
4108 foreach($allFiles as $k => $file) {
4109 $destFile = str_replace($from_dir."/", "", $file);
4110 if(!is_dir(dirname($destFile))) {
4111 mkdir_recursive(dirname($destFile)); // make sure the directory exists
4113 if ( stristr($file,'uw_main.tpl') )
4114 logThis('Skipping "'.$file.'" - file copy will during commit step.');
4116 logThis('updating UpgradeWizard code: '.$destFile);
4117 copy_recursive($file, $destFile);
4124 * upgradeDisplayedTabsAndSubpanels
4126 * @param $version String value of current system version (pre upgrade)
4128 function upgradeDisplayedTabsAndSubpanels($version)
4130 if($version < '620')
4132 logThis('start upgrading system displayed tabs and subpanels');
4133 require_once('modules/MySettings/TabController.php');
4134 $tc = new TabController();
4136 //grab the existing system tabs
4137 $tabs = $tc->get_tabs_system();
4139 //add Calls, Meetings, Tasks, Notes, Prospects (Targets) and ProspectLists (Target Lists)
4140 //to displayed tabs unless explicitly set to hidden
4141 $modules_to_add = array('Calls', 'Meetings', 'Tasks', 'Notes', 'Prospects', 'ProspectLists');
4142 $added_tabs = array();
4144 foreach($modules_to_add as $module)
4146 $tabs[0][$module] = $module;
4147 $added_tabs[] = $module;
4150 logThis('calling set_system_tabs on TabController to add tabs: ' . var_export($added_tabs, true));
4151 $tc->set_system_tabs($tabs[0]);
4152 logThis('finish upgrading system displayed tabs and subpanels');
4158 * unlinkUpgradeFiles
4159 * This is a helper function to clean up
4161 * @param $version String value of current system version (pre upgrade)
4163 function unlinkUpgradeFiles($version)
4165 if(!isset($version))
4170 //First check if we even have the scripts_for_patch/files_to_remove directory
4171 require_once('modules/UpgradeWizard/UpgradeRemoval.php');
4174 if(empty($_SESSION['unzip_dir']))
4176 global $sugar_config;
4177 $base_upgrade_dir = $sugar_config['upload_dir'] . "/upgrades";
4178 $base_tmp_upgrade_dir = "$base_upgrade_dir/temp";
4179 $_SESSION['unzip_dir'] = mk_temp_dir( $base_tmp_upgrade_dir );
4183 if(isset($_SESSION['unzip_dir']) && file_exists($_SESSION['unzip_dir'].'/scripts/files_to_remove'))
4185 $files_to_remove = glob($_SESSION['unzip_dir'].'/scripts/files_to_remove/*.php');
4187 foreach($files_to_remove as $script)
4189 if(preg_match('/UpgradeRemoval(\d+)x\.php/', $script, $matches))
4191 $checkVersion = $matches[1] + 1; //Increment by one to check everything equal or below the target version
4192 $upgradeClass = 'UpgradeRemoval' . $matches[1] . 'x';
4193 require_once($_SESSION['unzip_dir'].'/scripts/files_to_remove/' . $upgradeClass . '.php');
4195 //Check to make sure we should load and run this UpgradeRemoval instance
4196 if($checkVersion <= $version && class_exists($upgradeClass))
4198 $upgradeInstance = new $upgradeClass();
4199 if($upgradeInstance instanceof UpgradeRemoval)
4201 logThis('Running UpgradeRemoval instance ' . $upgradeClass);
4202 logThis('Files will be backed up to custom/backup');
4203 $files = $upgradeInstance->getFilesToRemove($version);
4204 foreach($files as $file)
4208 $upgradeInstance->processFilesToRemove($files);
4215 //Check if we have a custom directory
4216 if(file_exists('custom/scripts/files_to_remove'))
4219 $files_to_remove = glob('custom/scripts/files_to_remove/*.php');
4221 foreach($files_to_remove as $script)
4223 if(preg_match('/\/files_to_remove\/(.*?)\.php$/', $script, $matches))
4225 require_once($script);
4226 $upgradeClass = $matches[1];
4228 if(!class_exists($upgradeClass))
4233 $upgradeInstance = new $upgradeClass();
4234 if($upgradeInstance instanceof UpgradeRemoval)
4236 logThis('Running Custom UpgradeRemoval instance ' . $upgradeClass);
4237 $files = $upgradeInstance->getFilesToRemove($version);
4238 foreach($files as $file)
4242 $upgradeInstance->processFilesToRemove($files);
4250 if (!function_exists("getValidDBName"))
4253 * Return a version of $proposed that can be used as a column name in any of our supported databases
4254 * 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)
4255 * @param string $name Proposed name for the column
4256 * @param string $ensureUnique
4257 * @return string Valid column name trimmed to right length and with invalid characters removed
4259 function getValidDBName ($name, $ensureUnique = false, $maxLen = 30)
4261 // first strip any invalid characters - all but alphanumerics and -
4262 $name = preg_replace ( '/[^\w-]+/i', '', $name ) ;
4263 $len = strlen ( $name ) ;
4267 $md5str = md5($name);
4268 $tail = substr ( $name, -11) ;
4269 $temp = substr($md5str , strlen($md5str)-4 );
4270 $result = substr ( $name, 0, 10) . $temp . $tail ;
4271 }else if ($len > ($maxLen - 5))
4273 $result = substr ( $name, 0, 11) . substr ( $name, 11 - $maxLen + 5);
4275 return strtolower ( $result ) ;
4282 * Get UW directories
4283 * Provides compatibility with both 6.3 and pre-6.3 setup
4285 function getUWDirs()
4287 if(!class_exists('UploadStream')) {
4288 // we're still running the old code
4289 global $sugar_config;
4290 return array($sugar_config['upload_dir'] . "/upgrades", $sugar_config['cache_dir'] . "upload/upgrades/temp");
4292 if(!in_array("upload", stream_get_wrappers())) {
4293 UploadStream::register(); // just in case file was copied, but not run
4295 return array("upload://upgrades", sugar_cached("upgrades/temp"));
4300 * Whether directory exists within list of directories to skip
4301 * @param string $dir dir to be checked
4302 * @param array $skipDirs list with skipped dirs
4305 function whetherNeedToSkipDir($dir, $skipDirs)
4307 foreach($skipDirs as $skipMe) {
4308 if(strpos( clean_path($dir), $skipMe ) !== false) {
4318 * @param silentUpgrade boolean flag indicating whether or not we should treat running the SugarSpriteBuilder as an upgrade operation
4321 function rebuildSprites($fromUpgrade=true)
4323 require_once('modules/Administration/SugarSpriteBuilder.php');
4324 $sb = new SugarSpriteBuilder();
4325 $sb->cssMinify = true;
4326 $sb->fromSilentUpgrade = $fromUpgrade;
4327 $sb->silentRun = $fromUpgrade;
4329 // add common image directories
4330 $sb->addDirectory('default', 'include/images');
4331 $sb->addDirectory('default', 'themes/default/images');
4332 $sb->addDirectory('default', 'themes/default/images/SugarLogic');
4334 // add all theme image directories
4335 if($dh = opendir('themes'))
4337 while (($dir = readdir($dh)) !== false)
4339 if ($dir != "." && $dir != ".." && $dir != 'default' && is_dir('themes/'.$dir)) {
4340 $sb->addDirectory($dir, "themes/{$dir}/images");
4346 // generate the sprite goodies
4347 // everything is saved into cache/sprites
4348 $sb->createSprites();
4353 * repairSearchFields
4355 * This method goes through the list of SearchFields files based and calls TemplateRange::repairCustomSearchFields
4356 * method on the files in an attempt to ensure the range search attributes are properly set in SearchFields.php.
4358 * @param $globString String value used for glob search defaults to searching for all SearchFields.php files in modules directory
4359 * @param $path String value used to point to log file should logging be required. Defaults to empty.
4362 function repairSearchFields($globString='modules/*/metadata/SearchFields.php', $path='')
4366 logThis('Begin repairSearchFields', $path);
4369 require_once('include/dir_inc.php');
4370 require_once('modules/DynamicFields/templates/Fields/TemplateRange.php');
4371 require('include/modules.php');
4374 $searchFieldsFiles = glob($globString);
4376 foreach($searchFieldsFiles as $file)
4378 if(preg_match('/modules\/(.*?)\/metadata\/SearchFields\.php/', $file, $matches) && isset($beanList[$matches[1]]))
4380 $module = $matches[1];
4381 $beanName = $beanList[$module];
4382 VardefManager::loadVardef($module, $beanName);
4383 if(isset($GLOBALS['dictionary'][$beanName]['fields']))
4387 logThis('Calling TemplateRange::repairCustomSearchFields for module ' . $module, $path);
4389 TemplateRange::repairCustomSearchFields($GLOBALS['dictionary'][$beanName]['fields'], $module);
4396 logThis('End repairSearchFields', $path);
4401 * repairUpgradeHistoryTable
4403 * This is a helper function used in the upgrade process to fix upgrade_history entries so that the filename column points
4404 * to the new upload directory location introduced in 6.4 versions
4406 function repairUpgradeHistoryTable()
4408 require_once('modules/Configurator/Configurator.php');
4410 global $sugar_config;
4412 //Now upgrade the upgrade_history table entries
4413 $results = $GLOBALS['db']->query('SELECT id, filename FROM upgrade_history');
4414 $upload_dir = $sugar_config['cache_dir'].'upload/';
4416 //Create regular expression string to
4417 $match = '/^' . str_replace('/', '\/', $upload_dir) . '(.*?)$/';
4419 while(($row = $GLOBALS['db']->fetchByAssoc($results)))
4421 $file = str_replace('//', '/', $row['filename']); //Strip out double-paths that may exist
4423 if(!empty($file) && preg_match($match, $file, $matches))
4425 //Update new file location to use the new $sugar_config['upload_dir'] value
4426 $new_file_location = $sugar_config['upload_dir'] . $matches[1];
4427 $GLOBALS['db']->query("UPDATE upgrade_history SET filename = '{$new_file_location}' WHERE id = '{$row['id']}'");