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 if (!class_exists("ZipArchive"))
1086 $ret['ZipStatus'] = "<b><span class=stop>{$installer_mod_strings['ERR_CHECKSYS_ZIP']}</span></b>";
1087 $ret['error_found'] = true;
1089 $ret['ZipStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1094 /* mbstring.func_overload
1095 $ret['mbstring.func_overload'] = '';
1096 $mb = ini_get('mbstring.func_overload');
1099 $ret['mbstring.func_overload'] = "<b><span class=\"stop\">{$mod_strings['ERR_UW_MBSTRING_FUNC_OVERLOAD']}</b>";
1100 $ret['error_found'] = true;
1108 * is a file that we blow away automagically
1110 function isAutoOverwriteFile($file) {
1111 $overwriteDirs = array(
1112 './sugar_version.php',
1113 './modules/UpgradeWizard/uw_main.tpl',
1115 $file = trim('.'.str_replace(clean_path(getcwd()), '', $file));
1117 if(in_array($file, $overwriteDirs)) {
1121 $fileExtension = substr(strrchr($file, "."), 1);
1122 if($fileExtension == 'tpl' || $fileExtension == 'html') {
1132 function logThis($entry, $path='') {
1133 global $mod_strings;
1134 if(file_exists('include/utils/sugar_file_utils.php')){
1135 require_once('include/utils/sugar_file_utils.php');
1137 $log = empty($path) ? clean_path(getcwd().'/upgradeWizard.log') : clean_path($path);
1139 // create if not exists
1140 if(!file_exists($log)) {
1141 if(function_exists('sugar_fopen')){
1142 $fp = @sugar_fopen($log, 'w+'); // attempts to create file
1145 $fp = fopen($log, 'w+'); // attempts to create file
1147 if(!is_resource($fp)) {
1148 $GLOBALS['log']->fatal('UpgradeWizard could not create the upgradeWizard.log file');
1149 die($mod_strings['ERR_UW_LOG_FILE_UNWRITABLE']);
1152 if(function_exists('sugar_fopen')){
1153 $fp = @sugar_fopen($log, 'a+'); // write pointer at end of file
1156 $fp = @fopen($log, 'a+'); // write pointer at end of file
1159 if(!is_resource($fp)) {
1160 $GLOBALS['log']->fatal('UpgradeWizard could not open/lock upgradeWizard.log file');
1161 die($mod_strings['ERR_UW_LOG_FILE_UNWRITABLE']);
1165 $line = date('r').' [UpgradeWizard] - '.$entry."\n";
1167 if(@fwrite($fp, $line) === false) {
1168 $GLOBALS['log']->fatal('UpgradeWizard could not write to upgradeWizard.log: '.$entry);
1169 die($mod_strings['ERR_UW_LOG_FILE_UNWRITABLE']);
1172 if(is_resource($fp)) {
1180 * @desc This function is to be used in the upgrade process to preserve changes/customaizations made to pre 5.1 quickcreate layout.
1181 * 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
1182 * was automatically picked up by the quick create. [Addresses Bug 21469]
1183 * This function will check if customizations were made, and will create quickcreatedefs.php in the /cutom/working/$module_name directory.
1185 function updateQuickCreateDefs(){
1186 $d = dir('modules');
1187 $studio_modules = array();
1189 while($e = $d->read()){ //collect all studio modules.
1190 if(substr($e, 0, 1) == '.' || !is_dir('modules/' . $e))continue;
1191 if(file_exists('modules/' . $e . '/metadata/studio.php'))
1193 array_push($studio_modules, $e);
1197 foreach( $studio_modules as $modname ){ //for each studio enabled module
1198 //Check !exists modules/$modname/metadata/quickcreatedefs.php &&
1199 //exists custom/$modname/editviewdefs.php (module was customized) &&
1200 //!exists custom/$modname/quickcreateviewdefs.php
1202 $editviewdefs = "custom/working/modules/".$modname."/metadata/editviewdefs.php";
1203 $quickcreatedefs = "custom/working/modules/".$modname."/metadata/quickcreatedefs.php";
1205 if ( !file_exists("modules/".$modname."/metadata/quickcreatedefs.php") &&
1206 file_exists($editviewdefs) &&
1207 !file_exists($quickcreatedefs) ){
1208 //clone editviewdef and save it in custom/working/modules/metadata
1209 $GLOBALS['log']->debug("Copying editviewdefs.php as quickcreatedefs.php for the $modname module in custom/working/modules/$modname/metadata!");
1210 if(copy( $editviewdefs, $quickcreatedefs)){
1211 if(file_exists($quickcreatedefs) && is_readable($quickcreatedefs)){
1212 $file = file($quickcreatedefs);
1213 //replace 'EditView' with 'QuickCreate'
1214 $fp = fopen($quickcreatedefs,'w');
1215 foreach($file as &$line){
1216 if(preg_match('/^\s*\'EditView\'\s*=>\s*$/', $line) > 0){
1217 $line = "'QuickCreate' =>\n";
1225 $GLOBALS['log']->debug("Failed to replace 'EditView' with QuickCreate because $quickcreatedefs is either not readable or does not exist.");
1228 $GLOBALS['log']->debug("Failed to copy $editviewdefs to $quickcreatedefs!");
1235 * test perms for CREATE queries
1237 function testPermsCreate($db, $out) {
1238 logThis('Checking CREATE TABLE permissions...');
1239 global $mod_strings;
1241 if(!$db->checkPrivilege("CREATE TABLE")) {
1242 logThis('cannot CREATE TABLE!');
1243 $out['db']['dbNoCreate'] = true;
1244 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_CREATE']}</span></td></tr>";
1250 * test perms for INSERT
1252 function testPermsInsert($db, $out, $skip=false) {
1253 logThis('Checking INSERT INTO permissions...');
1254 global $mod_strings;
1256 if(!$db->checkPrivilege("INSERT")) {
1257 logThis('cannot INSERT INTO!');
1258 $out['db']['dbNoInsert'] = true;
1259 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_INSERT']}</span></td></tr>";
1266 * test perms for UPDATE TABLE
1268 function testPermsUpdate($db, $out, $skip=false) {
1269 logThis('Checking UPDATE TABLE permissions...');
1270 global $mod_strings;
1271 if(!$db->checkPrivilege("UPDATE")) {
1272 logThis('cannot UPDATE TABLE!');
1273 $out['db']['dbNoUpdate'] = true;
1274 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_UPDATE']}</span></td></tr>";
1281 * test perms for SELECT
1283 function testPermsSelect($db, $out, $skip=false) {
1284 logThis('Checking SELECT permissions...');
1285 global $mod_strings;
1286 if(!$db->checkPrivilege("SELECT")) {
1287 logThis('cannot SELECT!');
1288 $out['db']['dbNoSelect'] = true;
1289 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_SELECT']}</span></td></tr>";
1295 * test perms for DELETE
1297 function testPermsDelete($db, $out, $skip=false) {
1298 logThis('Checking DELETE FROM permissions...');
1299 global $mod_strings;
1300 if(!$db->checkPrivilege("DELETE")) {
1301 logThis('cannot DELETE FROM!');
1302 $out['db']['dbNoDelete'] = true;
1303 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_DELETE']}</span></td></tr>";
1310 * test perms for ALTER TABLE ADD COLUMN
1312 function testPermsAlterTableAdd($db, $out, $skip=false) {
1313 logThis('Checking ALTER TABLE ADD COLUMN permissions...');
1314 global $mod_strings;
1315 if(!$db->checkPrivilege("ADD COLUMN")) {
1316 logThis('cannot ADD COLUMN!');
1317 $out['db']['dbNoAddColumn'] = true;
1318 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_ADD_COLUMN']}</span></td></tr>";
1324 * test perms for ALTER TABLE ADD COLUMN
1326 function testPermsAlterTableChange($db, $out, $skip=false) {
1327 logThis('Checking ALTER TABLE CHANGE COLUMN permissions...');
1328 global $mod_strings;
1329 if(!$db->checkPrivilege("CHANGE COLUMN")) {
1330 logThis('cannot CHANGE COLUMN!');
1331 $out['db']['dbNoChangeColumn'] = true;
1332 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_CHANGE_COLUMN']}</span></td></tr>";
1338 * test perms for ALTER TABLE DROP COLUMN
1340 function testPermsAlterTableDrop($db, $out, $skip=false) {
1341 logThis('Checking ALTER TABLE DROP COLUMN permissions...');
1342 global $mod_strings;
1343 if(!$db->checkPrivilege("DROP COLUMN")) {
1344 logThis('cannot DROP COLUMN!');
1345 $out['db']['dbNoDropColumn'] = true;
1346 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_DROP_COLUMN']}</span></td></tr>";
1353 * test perms for DROP TABLE
1355 function testPermsDropTable($db, $out, $skip=false) {
1356 logThis('Checking DROP TABLE permissions...');
1357 global $mod_strings;
1358 if(!$db->checkPrivilege("DROP TABLE")) {
1359 logThis('cannot DROP TABLE!');
1360 $out['db']['dbNoDropTable'] = true;
1361 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_DROP_TABLE']}</span></td></tr>";
1366 function getFormattedError($error, $query) {
1367 $error = "<div><b>".$error;
1368 $error .= "</b>::{$query}</div>";
1374 * parses a query finding the table name
1375 * @param string query The query
1376 * @return string table The table
1378 function getTableFromQuery($query) {
1379 $standardQueries = array('ALTER TABLE', 'DROP TABLE', 'CREATE TABLE', 'INSERT INTO', 'UPDATE', 'DELETE FROM');
1380 $query = preg_replace("/[^A-Za-z0-9\_\s]/", "", $query);
1381 $query = trim(str_replace($standardQueries, '', $query));
1383 $firstSpc = strpos($query, " ");
1384 $end = ($firstSpc > 0) ? $firstSpc : strlen($query);
1385 $table = substr($query, 0, $end);
1392 function preLicenseCheck() {
1393 require_once('modules/UpgradeWizard/uw_files.php');
1395 global $sugar_config;
1396 global $mod_strings;
1397 global $sugar_version;
1399 if(!isset($sugar_version) || empty($sugar_version)) {
1400 require_once('./sugar_version.php');
1403 if(!isset($_SESSION['unzip_dir']) || empty($_SESSION['unzip_dir'])) {
1404 logThis('unzipping files in upgrade archive...');
1406 list($base_upgrade_dir, $base_tmp_upgrade_dir) = getUWDirs();
1408 //also come up with mechanism to read from upgrade-progress file
1409 if(!isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !is_file($_SESSION['install_file'])) {
1410 if (file_exists(clean_path($base_tmp_upgrade_dir)) && $handle = opendir(clean_path($base_tmp_upgrade_dir))) {
1411 while (false !== ($file = readdir($handle))) {
1412 if($file !="." && $file !="..") {
1413 if(is_file($base_tmp_upgrade_dir."/".$file."/manifest.php")){
1414 require_once($base_tmp_upgrade_dir."/".$file."/manifest.php");
1415 $package_name= $manifest['copy_files']['from_dir'];
1416 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")){
1417 $unzip_dir = $base_tmp_upgrade_dir."/".$file;
1418 if(file_exists("$base_upgrade_dir/patch/".$package_name.'.zip')){
1419 $_SESSION['install_file'] = $package_name.".zip";
1428 if(empty($_SESSION['install_file'])){
1429 unlinkUWTempFiles();
1431 echo 'Upload File not found so redirecting to Upgrade Start ';
1432 $redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
1433 echo '<form name="redirect" action="' .$redirect_new_wizard. '" method="POST">';
1434 $upgrade_directories_not_found =<<<eoq
1435 <table cellpadding="3" cellspacing="0" border="0">
1437 <th colspan="2" align="left">
1438 <span class='error'><b>'Upload file missing or has been deleted. Refresh the page to go back to UpgradeWizard start'</b></span>
1443 $uwMain = $upgrade_directories_not_found;
1446 $install_file = "$base_upgrade_dir/patch/".basename(urldecode( $_SESSION['install_file'] ));
1448 if(empty($unzip_dir)){
1449 $unzip_dir = mk_temp_dir( $base_tmp_upgrade_dir );
1451 $zip_from_dir = ".";
1453 $zip_force_copy = array();
1456 logThis('Could not create a temporary directory using mk_temp_dir( $base_tmp_upgrade_dir )');
1457 die($mod_strings['ERR_UW_NO_CREATE_TMP_DIR']);
1460 //double check whether unzipped .
1461 if(file_exists($unzip_dir ."/scripts") && file_exists($unzip_dir."/manifest.php")){
1465 unzip( $install_file, $unzip_dir );
1468 // assumption -- already validated manifest.php at time of upload
1469 require_once( "$unzip_dir/manifest.php" );
1471 if( isset( $manifest['copy_files']['from_dir'] ) && $manifest['copy_files']['from_dir'] != "" ){
1472 $zip_from_dir = $manifest['copy_files']['from_dir'];
1474 if( isset( $manifest['copy_files']['to_dir'] ) && $manifest['copy_files']['to_dir'] != "" ){
1475 $zip_to_dir = $manifest['copy_files']['to_dir'];
1477 if( isset( $manifest['copy_files']['force_copy'] ) && $manifest['copy_files']['force_copy'] != "" ){
1478 $zip_force_copy = $manifest['copy_files']['force_copy'];
1480 if( isset( $manifest['version'] ) ){
1481 $version = $manifest['version'];
1483 if( !is_writable( "config.php" ) ){
1484 return $mod_strings['ERR_UW_CONFIG'];
1487 $_SESSION['unzip_dir'] = clean_path($unzip_dir);
1488 $_SESSION['zip_from_dir'] = clean_path($zip_from_dir);
1489 logThis('unzip done.');
1491 $unzip_dir = $_SESSION['unzip_dir'];
1492 $zip_from_dir = $_SESSION['zip_from_dir'];
1495 //check if $_SESSION['unzip_dir'] and $_SESSION['zip_from_dir'] exist
1496 if(!isset($_SESSION['unzip_dir']) || !file_exists($_SESSION['unzip_dir'])
1497 || !isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !file_exists($_SESSION['install_file'])){
1499 unlinkUWTempFiles();
1501 echo 'Upload File not found so redirecting to Upgrade Start ';
1502 $redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
1503 echo '<form name="redirect" action="' .$redirect_new_wizard. '" method="POST">';
1504 $upgrade_directories_not_found =<<<eoq
1505 <table cellpadding="3" cellspacing="0" border="0">
1507 <th colspan="2" align="left">
1508 <span class='error'><b>'Upload file missing or has been deleted. Refresh the page to go back to UpgradeWizard start'</b></span>
1513 $uwMain = $upgrade_directories_not_found;
1517 logThis ('is SugarConfig there '.file_exists(clean_path($unzip_dir.'/'.$zip_from_dir."/include/SugarObjects/SugarConfig.php")));
1518 if(file_exists(clean_path($unzip_dir.'/'.$zip_from_dir."/include/SugarObjects/SugarConfig.php"))) {
1519 $file = clean_path($unzip_dir.'/'.$zip_from_dir."/include/SugarObjects/SugarConfig.php");
1520 $destFile = str_replace(clean_path($unzip_dir.'/'.$zip_from_dir), $cwd, $file);
1521 if(!is_dir(dirname($destFile))) {
1522 mkdir_recursive(dirname($destFile)); // make sure the directory exists
1524 copy($file,$destFile);
1525 //also copy include utils array utils
1526 $file = clean_path($unzip_dir.'/'.$zip_from_dir."/include/utils/array_utils.php");
1527 $destFile = str_replace(clean_path($unzip_dir.'/'.$zip_from_dir), $cwd, $file);
1528 if(!is_dir(dirname($destFile))) {
1529 mkdir_recursive(dirname($destFile)); // make sure the directory exists
1531 copy($file,$destFile);
1536 function preflightCheck() {
1537 require_once('modules/UpgradeWizard/uw_files.php');
1539 global $sugar_config;
1540 global $mod_strings;
1541 global $sugar_version;
1543 if(!isset($sugar_version) || empty($sugar_version)) {
1544 require_once('./sugar_version.php');
1547 unset($_SESSION['rebuild_relationships']);
1548 unset($_SESSION['rebuild_extensions']);
1550 // don't bother if are rechecking
1551 $manualDiff = array();
1552 if(!isset($_SESSION['unzip_dir']) || empty($_SESSION['unzip_dir'])) {
1553 logThis('unzipping files in upgrade archive...');
1555 list($base_upgrade_dir, $base_tmp_upgrade_dir) = getUWDirs();
1557 //Following is if User logged out unexpectedly and then logged into UpgradeWizard again.
1558 //also come up with mechanism to read from upgrade-progress file.
1559 if(!isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !is_file($_SESSION['install_file'])) {
1560 if (file_exists($base_tmp_upgrade_dir) && $handle = opendir($base_tmp_upgrade_dir)) {
1561 while (false !== ($file = readdir($handle))) {
1562 if($file !="." && $file !="..") {
1563 if(is_file($base_tmp_upgrade_dir."/".$file."/manifest.php")){
1564 require_once($base_tmp_upgrade_dir."/".$file."/manifest.php");
1565 $package_name= $manifest['copy_files']['from_dir'];
1566 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")){
1567 $unzip_dir = $base_tmp_upgrade_dir."/".$file;
1568 if(file_exists("$base_upgrade_dir/patch/".$package_name.'.zip')){
1569 $_SESSION['install_file'] = $package_name.".zip";
1578 if(empty($_SESSION['install_file'])){
1579 unlinkUWTempFiles();
1581 echo 'Upload File not found so redirecting to Upgrade Start ';
1582 $redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
1583 echo '<form name="redirect" action="' .$redirect_new_wizard. '" method="POST">';
1584 $upgrade_directories_not_found =<<<eoq
1585 <table cellpadding="3" cellspacing="0" border="0">
1587 <th colspan="2" align="left">
1588 <span class='error'><b>'Upload file missing or has been deleted. Refresh the page to go back to UpgradeWizard start'</b></span>
1593 $uwMain = $upgrade_directories_not_found;
1597 $install_file = "$base_upgrade_dir/patch/".basename(urldecode( $_SESSION['install_file'] ));
1599 if(empty($unzip_dir)){
1600 $unzip_dir = mk_temp_dir( $base_tmp_upgrade_dir );
1602 $zip_from_dir = ".";
1604 $zip_force_copy = array();
1607 logThis('Could not create a temporary directory using mk_temp_dir( $base_tmp_upgrade_dir )');
1608 die($mod_strings['ERR_UW_NO_CREATE_TMP_DIR']);
1611 //double check whether unzipped .
1612 if(file_exists($unzip_dir ."/scripts") && file_exists($unzip_dir."/manifest.php")){
1616 unzip( $install_file, $unzip_dir );
1619 // assumption -- already validated manifest.php at time of upload
1620 require_once( "$unzip_dir/manifest.php" );
1622 if( isset( $manifest['copy_files']['from_dir'] ) && $manifest['copy_files']['from_dir'] != "" ){
1623 $zip_from_dir = $manifest['copy_files']['from_dir'];
1625 if( isset( $manifest['copy_files']['to_dir'] ) && $manifest['copy_files']['to_dir'] != "" ){
1626 $zip_to_dir = $manifest['copy_files']['to_dir'];
1628 if( isset( $manifest['copy_files']['force_copy'] ) && $manifest['copy_files']['force_copy'] != "" ){
1629 $zip_force_copy = $manifest['copy_files']['force_copy'];
1631 if( isset( $manifest['version'] ) ){
1632 $version = $manifest['version'];
1634 if( !is_writable( "config.php" ) ){
1635 return $mod_strings['ERR_UW_CONFIG'];
1638 $_SESSION['unzip_dir'] = clean_path($unzip_dir);
1639 $_SESSION['zip_from_dir'] = clean_path($zip_from_dir);
1641 //logThis('unzip done.');
1643 $unzip_dir = $_SESSION['unzip_dir'];
1644 $zip_from_dir = $_SESSION['zip_from_dir'];
1646 //check if $_SESSION['unzip_dir'] and $_SESSION['zip_from_dir'] exist
1647 if(!isset($_SESSION['unzip_dir']) || !file_exists($_SESSION['unzip_dir'])
1648 || !isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !file_exists($_SESSION['install_file'])){
1650 unlinkUWTempFiles();
1652 echo 'Upload File not found so redirecting to Upgrade Start ';
1653 $redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
1654 echo '<form name="redirect" action="' .$redirect_new_wizard. '" method="POST">';
1655 $upgrade_directories_not_found =<<<eoq
1656 <table cellpadding="3" cellspacing="0" border="0">
1658 <th colspan="2" align="left">
1659 <span class='error'><b>'Upload file missing or has been deleted. Refresh the page to go back to UpgradeWizard start'</b></span>
1664 $uwMain = $upgrade_directories_not_found;
1667 //copy minimum required files
1668 fileCopy('include/utils/sugar_file_utils.php');
1670 $upgradeFiles = findAllFiles(clean_path("$unzip_dir/$zip_from_dir"), array());
1671 $cache_html_files= array();
1674 $md5_string = array();
1675 if(file_exists(clean_path(getcwd().'/files.md5'))){
1676 require(clean_path(getcwd().'/files.md5'));
1679 // file preflight checks
1680 logThis('verifying md5 checksums for files...');
1681 foreach($upgradeFiles as $file) {
1682 if(in_array(str_replace(clean_path("$unzip_dir/$zip_from_dir") . "/", '', $file), $uw_files))
1683 continue; // skip already loaded files
1685 if(strpos($file, '.md5'))
1686 continue; // skip md5 file
1688 // normalize file paths
1689 $file = clean_path($file);
1691 // check that we can move/delete the upgraded file
1692 if(!is_writable($file)) {
1693 $errors[] = $mod_strings['ERR_UW_FILE_NOT_WRITABLE'].": ".$file;
1695 // check that destination files are writable
1696 $destFile = getcwd().str_replace(clean_path($unzip_dir.'/'.$zip_from_dir), '', $file);
1698 if(is_file($destFile)) { // of course it needs to exist first...
1699 if(!is_writable($destFile)) {
1700 $errors[] = $mod_strings['ERR_UW_FILE_NOT_WRITABLE'].": ".$destFile;
1704 ///////////////////////////////////////////////////////////////////////
1706 // compare md5s and build up a manual merge list
1707 $targetFile = clean_path(".".str_replace(getcwd(),'',$destFile));
1709 if(is_file($destFile)) {
1710 if(strpos($targetFile, '.php')) {
1711 // handle PHP files that were hit with the security regex
1713 if(function_exists('sugar_fopen')){
1714 $fp = sugar_fopen($destFile, 'r');
1717 $fp = fopen($destFile, 'r');
1719 $filesize = filesize($destFile);
1721 $fileContents = stream_get_contents($fp);
1722 $targetMd5 = md5($fileContents);
1725 $targetMd5 = md5_file($destFile);
1729 if(isset($md5_string[$targetFile]) && $md5_string[$targetFile] != $targetMd5) {
1730 logThis('found a file with a differing md5: ['.$targetFile.']');
1731 $manualDiff[] = $destFile;
1734 ///////////////////////////////////////////////////////////////////////
1736 logThis('md5 verification done.');
1737 $errors['manual'] = $manualDiff;
1742 function fileCopy($file_path){
1743 if(file_exists(clean_path($_SESSION['unzip_dir'].'/'.$_SESSION['zip_from_dir'].'/'.$file_path))) {
1744 $file = clean_path($_SESSION['unzip_dir'].'/'.$_SESSION['zip_from_dir'].'/'.$file_path);
1745 $destFile = str_replace(clean_path($_SESSION['unzip_dir'].'/'.$_SESSION['zip_from_dir']), clean_path(getcwd()), $file);
1746 if(!is_dir(dirname($destFile))) {
1747 mkdir_recursive(dirname($destFile)); // make sure the directory exists
1749 copy_recursive($file,$destFile);
1752 function getChecklist($steps, $step) {
1753 global $mod_strings;
1755 $skip = array('start', 'cancel', 'uninstall','end');
1758 $ret = '<table cellpadding="3" cellspacing="4" border="0">';
1759 $ret .= '<tr><th colspan="3" align="left">'.$mod_strings['LBL_UW_CHECKLIST'].':</th></tr>';
1760 foreach($steps['desc'] as $k => $desc) {
1761 if(in_array($steps['files'][$j], $skip)) {
1766 //$status = "<span class='error'>{$mod_strings['LBL_UW_INCOMPLETE']}</span>";
1768 $desc_mod_post = '';
1770 if(isset($_SESSION['step'][$steps['files'][$k]]) && $_SESSION['step'][$steps['files'][$k]] == 'success') {
1771 //$status = $mod_strings['LBL_UW_COMPLETE'];
1775 if($k == $_REQUEST['step']) {
1776 //$status = $mod_strings['LBL_UW_IN_PROGRESS'];
1777 $desc_mod_pre = "<font color=blue><i>";
1778 $desc_mod_post = "</i></font>";
1781 $ret .= "<tr><td> </td><td><b>{$i}: {$desc_mod_pre}{$desc}{$desc_mod_post}</b></td>";
1782 $ret .= "<td id={$steps['files'][$j]}><i></i></td></tr>";
1790 function prepSystemForUpgrade() {
1791 global $sugar_config;
1792 global $sugar_flavor;
1793 global $mod_strings;
1795 global $base_upgrade_dir;
1796 global $base_tmp_upgrade_dir;
1797 list($p_base_upgrade_dir, $p_base_tmp_upgrade_dir) = getUWDirs();
1798 ///////////////////////////////////////////////////////////////////////////////
1799 //// Make sure variables exist
1800 if(empty($base_upgrade_dir)){
1801 $base_upgrade_dir = $p_base_upgrade_dir;
1803 if(empty($base_tmp_upgrade_dir)){
1804 $base_tmp_upgrade_dir = $p_base_tmp_upgrade_dir;
1806 sugar_mkdir($base_tmp_upgrade_dir, 0775, true);
1807 if(!isset($subdirs) || empty($subdirs)){
1808 $subdirs = array('full', 'langpack', 'module', 'patch', 'theme');
1811 $upgrade_progress_dir = $base_tmp_upgrade_dir;
1812 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
1813 if(file_exists($upgrade_progress_file)){
1814 if(function_exists('get_upgrade_progress') && function_exists('didThisStepRunBefore')){
1815 if(didThisStepRunBefore('end')){
1816 include($upgrade_progress_file);
1817 unset($upgrade_config);
1818 unlink($upgrade_progress_file);
1823 // increase the cuttoff time to 1 hour
1824 ini_set("max_execution_time", "3600");
1826 // make sure dirs exist
1827 if($subdirs != null){
1828 foreach($subdirs as $subdir) {
1829 sugar_mkdir("$base_upgrade_dir/$subdir", 0775, true);
1832 // array of special scripts that are executed during (un)installation-- key is type of script, value is filename
1833 if(!defined('SUGARCRM_PRE_INSTALL_FILE')) {
1834 define('SUGARCRM_PRE_INSTALL_FILE', 'scripts/pre_install.php');
1835 define('SUGARCRM_POST_INSTALL_FILE', 'scripts/post_install.php');
1836 define('SUGARCRM_PRE_UNINSTALL_FILE', 'scripts/pre_uninstall.php');
1837 define('SUGARCRM_POST_UNINSTALL_FILE', 'scripts/post_uninstall.php');
1840 $script_files = array(
1841 "pre-install" => constant('SUGARCRM_PRE_INSTALL_FILE'),
1842 "post-install" => constant('SUGARCRM_POST_INSTALL_FILE'),
1843 "pre-uninstall" => constant('SUGARCRM_PRE_UNINSTALL_FILE'),
1844 "post-uninstall" => constant('SUGARCRM_POST_UNINSTALL_FILE'),
1847 // check that the upload limit is set to 6M or greater
1848 define('SUGARCRM_MIN_UPLOAD_MAX_FILESIZE_BYTES', 6 * 1024 * 1024); // 6 Megabytes
1849 $upload_max_filesize = ini_get('upload_max_filesize');
1850 $upload_max_filesize_bytes = return_bytes($upload_max_filesize);
1852 if($upload_max_filesize_bytes < constant('SUGARCRM_MIN_UPLOAD_MAX_FILESIZE_BYTES')) {
1853 $GLOBALS['log']->debug("detected upload_max_filesize: $upload_max_filesize");
1855 echo '<p class="error">'.$mod_strings['MSG_INCREASE_UPLOAD_MAX_FILESIZE'].' '.get_cfg_var('cfg_file_path')."</p>\n";
1859 if ( !function_exists('extractFile') ) {
1860 function extractFile($zip_file, $file_in_zip) {
1861 global $base_tmp_upgrade_dir;
1864 $absolute_base_tmp_upgrade_dir = clean_path($base_tmp_upgrade_dir);
1865 $relative_base_tmp_upgrade_dir = clean_path(str_replace(clean_path(getcwd()), '', $absolute_base_tmp_upgrade_dir));
1867 // mk_temp_dir expects relative pathing
1868 $my_zip_dir = mk_temp_dir($relative_base_tmp_upgrade_dir);
1870 unzip_file($zip_file, $file_in_zip, $my_zip_dir);
1872 return("$my_zip_dir/$file_in_zip");
1876 if ( !function_exists('extractManifest') ) {
1877 function extractManifest($zip_file) {
1878 logThis('extracting manifest.');
1879 return(extractFile($zip_file, "manifest.php"));
1883 if ( !function_exists('getInstallType') ) {
1884 function getInstallType($type_string) {
1887 $subdirs = array('full', 'langpack', 'module', 'patch', 'theme', 'temp');
1888 foreach($subdirs as $subdir) {
1889 if(preg_match("#/$subdir/#", $type_string)) {
1893 // return empty if no match
1898 function getImageForType($type) {
1900 global $mod_strings;
1905 $icon = SugarThemeRegistry::current()->getImage("Upgrade", "",null,null,'.gif',$mod_strings['LBL_UPGRADE']);
1908 $icon = SugarThemeRegistry::current()->getImage("LanguagePacks", "",null,null,'.gif',$mod_strings['LBL_LANGPACKS']);
1911 $icon = SugarThemeRegistry::current()->getImage("ModuleLoader", "",null,null,'.gif',$mod_strings['LBL_MODULELOADER']);
1914 $icon = SugarThemeRegistry::current()->getImage("PatchUpgrades", "",null,null,'.gif',$mod_strings['LBL_PATCHUPGRADES']);
1917 $icon = SugarThemeRegistry::current()->getImage("Themes", "",null,null,'.gif',$mod_strings['LBL_THEMES']);
1925 if ( !function_exists('getLanguagePackName') ) {
1926 function getLanguagePackName($the_file) {
1927 require_once("$the_file");
1928 if(isset($app_list_strings["language_pack_name"])) {
1929 return($app_list_strings["language_pack_name"]);
1935 function getUITextForType($type) {
1936 if($type == "full") {
1937 return("Full Upgrade");
1939 if($type == "langpack") {
1940 return("Language Pack");
1942 if($type == "module") {
1945 if($type == "patch") {
1948 if($type == "theme") {
1953 if ( !function_exists('validate_manifest') ) {
1955 * Verifies a manifest from a patch or module to be compatible with the current Sugar version and flavor
1956 * @param array manifest Standard manifest array
1957 * @return string Error message, blank on success
1959 function validate_manifest($manifest) {
1960 logThis('validating manifest.php file');
1961 // takes a manifest.php manifest array and validates contents
1963 global $sugar_version;
1964 global $sugar_flavor;
1965 global $mod_strings;
1967 if(!isset($manifest['type'])) {
1968 return $mod_strings['ERROR_MANIFEST_TYPE'];
1971 $type = $manifest['type'];
1973 if(getInstallType("/$type/") == "") {
1974 return $mod_strings['ERROR_PACKAGE_TYPE']. ": '" . $type . "'.";
1977 if(isset($manifest['acceptable_sugar_versions'])) {
1978 $version_ok = false;
1979 $matches_empty = true;
1980 if(isset($manifest['acceptable_sugar_versions']['exact_matches'])) {
1981 $matches_empty = false;
1982 foreach($manifest['acceptable_sugar_versions']['exact_matches'] as $match) {
1983 if($match == $sugar_version) {
1988 if(!$version_ok && isset($manifest['acceptable_sugar_versions']['regex_matches'])) {
1989 $matches_empty = false;
1990 foreach($manifest['acceptable_sugar_versions']['regex_matches'] as $match) {
1991 if(preg_match("/$match/", $sugar_version)) {
1997 if(!$matches_empty && !$version_ok) {
1998 return $mod_strings['ERROR_VERSION_INCOMPATIBLE']."<br />".
1999 $mod_strings['ERR_UW_VERSION'].$sugar_version;
2003 if(isset($manifest['acceptable_sugar_flavors']) && sizeof($manifest['acceptable_sugar_flavors']) > 0) {
2005 foreach($manifest['acceptable_sugar_flavors'] as $match) {
2006 if($match == $sugar_flavor) {
2011 return $mod_strings['ERROR_FLAVOR_INCOMPATIBLE']."<br />".
2012 $mod_strings['ERR_UW_FLAVOR'].$sugar_flavor."<br />".
2013 $mod_strings['ERR_UW_FLAVOR_2'].$manifest['acceptable_sugar_flavors'][0];
2021 function unlinkUploadFiles() {
2023 // logThis('at unlinkUploadFiles()');
2025 // if(isset($_SESSION['install_file']) && !empty($_SESSION['install_file'])) {
2026 // $upload = $_SESSION['install_file'];
2028 // if(is_file($upload)) {
2029 // logThis('unlinking ['.$upload.']');
2030 // @unlink($upload);
2036 * deletes files created by unzipping a package
2038 function unlinkUWTempFiles() {
2039 global $sugar_config;
2042 logThis('at unlinkUWTempFiles()');
2044 list($upgDir, $tempDir) = getUWDirs();
2046 if(file_exists($tempDir) && is_dir($tempDir)){
2047 $files = findAllFiles($tempDir, array(), false);
2049 foreach($files as $file) {
2050 if(!is_dir($file)) {
2051 //logThis('unlinking ['.$file.']', $path);
2056 $files = findAllFiles($tempDir, array(), true);
2057 foreach($files as $dir) {
2059 //logThis('removing dir ['.$dir.']', $path);
2063 $cacheFile = sugar_cached("modules/UpgradeWizard/_persistence.php");
2064 if(is_file($cacheFile)) {
2065 logThis("Unlinking Upgrade cache file: '_persistence.php'", $path);
2066 @unlink($cacheFile);
2069 logThis("finished!");
2073 * finds all files in the passed path, but skips select directories
2074 * @param string dir Relative path
2075 * @param array the_array Collections of found files/dirs
2076 * @param bool include_dir True if we want to include directories in the
2077 * returned collection
2079 function uwFindAllFiles($dir, $theArray, $includeDirs=false, $skipDirs=array(), $echo=false) {
2081 if (whetherNeedToSkipDir($dir, $skipDirs))
2086 if (!is_dir($dir)) { return $theArray; } // Bug # 46035, just checking for valid dir
2088 if ($d === false) { return $theArray; } // Bug # 46035, more checking
2090 while($f = $d->read()) {
2091 // bug 40793 Skip Directories array in upgradeWizard does not function correctly
2092 if($f == "." || $f == ".." || whetherNeedToSkipDir("$dir/$f", $skipDirs)) { // skip *nix self/parent
2096 // for AJAX length count
2102 if(is_dir("$dir/$f")) {
2103 if($includeDirs) { // add the directory if flagged
2104 $theArray[] = clean_path("$dir/$f");
2108 $theArray = uwFindAllFiles("$dir/$f/", $theArray, $includeDirs, $skipDirs, $echo);
2110 $theArray[] = clean_path("$dir/$f");
2123 * unset's UW's Session Vars
2125 function resetUwSession() {
2126 logThis('resetting $_SESSION');
2128 if(isset($_SESSION['committed']))
2129 unset($_SESSION['committed']);
2130 if(isset($_SESSION['sugar_version_file']))
2131 unset($_SESSION['sugar_version_file']);
2132 if(isset($_SESSION['upgrade_complete']))
2133 unset($_SESSION['upgrade_complete']);
2134 if(isset($_SESSION['allTables']))
2135 unset($_SESSION['allTables']);
2136 if(isset($_SESSION['alterCustomTableQueries']))
2137 unset($_SESSION['alterCustomTableQueries']);
2138 if(isset($_SESSION['skip_zip_upload']))
2139 unset($_SESSION['skip_zip_upload']);
2140 if(isset($_SESSION['sugar_version_file']))
2141 unset($_SESSION['sugar_version_file']);
2142 if(isset($_SESSION['install_file']))
2143 unset($_SESSION['install_file']);
2144 if(isset($_SESSION['unzip_dir']))
2145 unset($_SESSION['unzip_dir']);
2146 if(isset($_SESSION['zip_from_dir']))
2147 unset($_SESSION['zip_from_dir']);
2148 if(isset($_SESSION['overwrite_files']))
2149 unset($_SESSION['overwrite_files']);
2150 if(isset($_SESSION['schema_change']))
2151 unset($_SESSION['schema_change']);
2152 if(isset($_SESSION['uw_restore_dir']))
2153 unset($_SESSION['uw_restore_dir']);
2154 if(isset($_SESSION['step']))
2155 unset($_SESSION['step']);
2156 if(isset($_SESSION['files']))
2157 unset($_SESSION['files']);
2158 if(isset($_SESSION['Upgraded451Wizard'])){
2159 unset($_SESSION['Upgraded451Wizard']);
2161 if(isset($_SESSION['Initial_451to500_Step'])){
2162 unset($_SESSION['Initial_451to500_Step']);
2164 if(isset($_SESSION['license_shown']))
2165 unset($_SESSION['license_shown']);
2166 if(isset($_SESSION['sugarMergeRunResults']))
2167 unset($_SESSION['sugarMergeRunResults']);
2171 * runs rebuild scripts
2173 function UWrebuild() {
2177 //CCL - Comment this block out, it is called in end.php
2178 logThis('Rebuilding everything...', $path);
2179 require_once('modules/Administration/QuickRepairAndRebuild.php');
2180 $randc = new RepairAndClear();
2181 $randc->repairAndClearAll(array('clearAll'),array(translate('LBL_ALL_MODULES')), false, false);
2183 $query = "DELETE FROM versions WHERE name='Rebuild Extensions'";
2185 logThis('Registering rebuild record: '.$query, $path);
2186 logThis('Rebuild done.', $path);
2188 // insert a new database row to show the rebuild extensions is done
2189 $id = create_guid();
2190 $gmdate = gmdate('Y-m-d H:i:s');
2191 $date_entered = db_convert("'$gmdate'", 'datetime');
2192 $query = 'INSERT INTO versions (id, deleted, date_entered, date_modified, modified_user_id, created_by, name, file_version, db_version) '
2193 . "VALUES ('$id', '0', $date_entered, $date_entered, '1', '1', 'Rebuild Extensions', '4.0.0', '4.0.0')";
2195 logThis('Registering rebuild record in versions table: '.$query, $path);
2198 function getCustomTables() {
2201 return $db->tablesLike('%_cstm');
2204 function alterCustomTables($customTables)
2209 function getAllTables() {
2211 return $db->getTablesArray();
2214 function printAlterTableSql($tables)
2216 $alterTableSql = '';
2218 foreach($tables as $table)
2219 $alterTableSql .= "ALTER TABLE " . $table . " CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;" . "\n";
2221 return $alterTableSql;
2224 function executeConvertTablesSql($tables)
2228 foreach($tables as $table){
2229 $query = "ALTER TABLE " . $table . " CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci";
2231 logThis("Sending query: ".$query);
2232 $db->query($query);//, true, "An error has occured while performing db query. See log file for details.<br>");
2238 function testThis() {
2239 $files = uwFindAllFiles(getcwd().'/test', array());
2241 $out = "<table cellpadding='1' cellspacing='0' border='0'>\n";
2244 foreach($files as $file) {
2245 $relativeFile = clean_path(str_replace(getcwd().'/test', '', $file));
2246 $relativeFile = ($relativeFile{0} == '/') ? substr($relativeFile, 1, strlen($relativeFile)) : $relativeFile;
2248 $relativePath = dirname($relativeFile);
2250 if($relativePath == $priorPath) { // same dir, new file
2251 $out .= "<tr><td>".basename($relativeFile)."</td></tr>";
2252 $priorPath = $relativePath;
2266 function testThis2($dir, $id=0, $hide=false) {
2267 global $mod_strings;
2269 $dh = opendir($dir);
2272 $doHide = ($hide) ? 'none' : '';
2273 $out = "<div id='{$id}' style='display:{$doHide};'>";
2274 $out .= "<table cellpadding='1' cellspacing='0' style='border:0px solid #ccc'>\n";
2276 while($file = readdir($dh)) {
2277 if($file == '.' || $file == '..' || $file == 'CVS' || $file == '.cvsignore')
2280 if(is_dir($path.'/'.$file)) {
2281 $file = $path.'/'.$file;
2282 $newI = create_guid();
2283 $out .= "<tr><td valign='top'><a href='javascript:toggleNwFiles(\"{$newI}\");'>".SugarThemeRegistry::current()->getImage("Workflow", "", null, null, ".gif", $mod_strings['LBL_WORKFLOW'])."</a></td>\n";
2284 $out .= "<td valign='top'><b><a href='javascript:toggleNwFiles(\"{$newI}\");'>".basename($file)."</a></b></td></tr>";
2285 $out .= "<tr><td></td><td valign='top'>".testThis2($file, $newI, true)."</td></tr>";
2287 $out .= "<tr><td valign='top'> </td>\n";
2288 $out .= "<td valign='top'>".basename($file)."</td></tr>";
2292 $out .= "</tr></table>";
2303 function testThis3(&$files, $id, $hide, $previousPath = '') {
2304 if(!is_array($files) || empty($files))
2309 global $mod_strings;
2310 // expecting full path here
2311 foreach($files as $k => $file) {
2312 $file = str_replace(getcwd(), '', $file);
2313 $path = dirname($file);
2314 $fileName = basename($file);
2316 if($fileName == 'CVS' || $fileName == '.cvsignore')
2319 if($path == $previousPath) { // same directory
2320 // new row for each file
2321 $out .= "<tr><td valign='top' align='left'> </td>";
2322 $out .= "<td valign='top' align='left'>{$fileName}</td></tr>";
2323 } else { // new directory
2325 $out .= "<tr><td valign='top'><a href='javascript:toggleNwFiles(\"{$newI}\");'>".SugarThemeRegistry::current()->getImage("Workflow", "", null, null, ".gif", $mod_strings['LBL_WORKFLOW'])."</a></td>\n";
2326 $out .= "<td valign='top'><b><a href='javascript:toggleNwFiles(\"{$newI}\");'>".$fileName."</a></b></td></tr>";
2327 $recurse = testThis3($files, $newI, true, $previousPath);
2328 $out .= "<tr><td></td><td valign='top'>".$recurse."</td></tr>";
2331 $previousPath = $path;
2333 $display = ($hide) ? 'none' : '';
2335 <div id="{$id}" style="display:{$display}">
2336 <table cellpadding='1' cellspacing='0' border='0' style='border:1px solid #ccc'>
2345 function testThis4($filePath, $fileNodes=array(), $fileName='') {
2346 $path = dirname($filePath);
2347 $file = basename($filePath);
2349 $exFile = explode('/', $path);
2351 foreach($exFile as $pathSegment) {
2352 if(is_array($fileNodes[$pathSegment])) { // path already processed
2354 } else { // newly found path
2355 $fileNodes[$pathSegment] = array();
2358 if($fileName != '') {
2359 $fileNodes[$pathSegment][] = $fileName;
2368 ///////////////////////////////////////////////////////////////////////////////
2369 //// SYSTEM CHECK FUNCTIONS
2371 * generates an array with all files in the SugarCRM root directory, skipping
2373 * @return array files Array of files with absolute paths
2375 function getFilesForPermsCheck() {
2376 global $sugar_config;
2378 logThis('Got JSON call to find all files...');
2379 $filesNotWritable = array();
2380 $filesNWPerms = array();
2382 // add directories here that should be skipped when doing file permissions checks (cache/upload is the nasty one)
2384 $sugar_config['upload_dir'],
2386 $files = uwFindAllFiles(".", array(), true, $skipDirs, true);
2391 * checks files for permissions
2392 * @param array files Array of files with absolute paths
2393 * @return string result of check
2395 function checkFiles($files, $echo=false) {
2396 global $mod_strings;
2397 $filesNotWritable = array();
2400 <a href='javascript:void(0); toggleNwFiles(\"filesNw\");'>{$mod_strings['LBL_UW_SHOW_NW_FILES']}</a>
2401 <div id='filesNw' style='display:none;'>
2402 <table cellpadding='3' cellspacing='0' border='0'>
2404 <th align='left'>{$mod_strings['LBL_UW_FILE']}</th>
2405 <th align='left'>{$mod_strings['LBL_UW_FILE_PERMS']}</th>
2406 <th align='left'>{$mod_strings['LBL_UW_FILE_OWNER']}</th>
2407 <th align='left'>{$mod_strings['LBL_UW_FILE_GROUP']}</th>
2410 $isWindows = is_windows();
2411 foreach($files as $file) {
2414 if(!is_writable_windows($file)) {
2415 logThis('WINDOWS: File ['.$file.'] not readable - saving for display');
2416 // don't warn yet - we're going to use this to check against replacement files
2417 // aw: commented out; it's a hack to allow upgrade wizard to continue on windows... will fix later
2418 /*$filesNotWritable[$i] = $file;
2419 $filesNWPerms[$i] = substr(sprintf('%o',fileperms($file)), -4);
2420 $filesOut .= "<tr>".
2421 "<td><span class='error'>{$file}</span></td>".
2422 "<td>{$filesNWPerms[$i]}</td>".
2423 "<td>".$mod_strings['ERR_UW_CANNOT_DETERMINE_USER']."</td>".
2424 "<td>".$mod_strings['ERR_UW_CANNOT_DETERMINE_GROUP']."</td>".
2428 if(!is_writable($file)) {
2429 logThis('File ['.$file.'] not writable - saving for display');
2430 // don't warn yet - we're going to use this to check against replacement files
2431 $filesNotWritable[$i] = $file;
2432 $filesNWPerms[$i] = substr(sprintf('%o',fileperms($file)), -4);
2433 $owner = posix_getpwuid(fileowner($file));
2434 $group = posix_getgrgid(filegroup($file));
2435 $filesOut .= "<tr>".
2436 "<td><span class='error'>{$file}</span></td>".
2437 "<td>{$filesNWPerms[$i]}</td>".
2438 "<td>".$owner['name']."</td>".
2439 "<td>".$group['name']."</td>".
2446 $filesOut .= '</table></div>';
2448 $errors['files']['filesNotWritable'] = (count($filesNotWritable) > 0) ? true : false;
2449 if(count($filesNotWritable) < 1) {
2450 $filesOut = "{$mod_strings['LBL_UW_FILE_NO_ERRORS']}";
2456 function deletePackageOnCancel(){
2457 global $mod_strings;
2458 global $sugar_config;
2459 list($base_upgrade_dir, $base_tmp_upgrade_dir) = getUWDirs();
2460 logThis('running delete');
2461 if(!isset($_SESSION['install_file']) || ($_SESSION['install_file'] == "")) {
2462 logThis('ERROR: trying to delete non-existent file: ['.$_REQUEST['install_file'].']');
2463 $error = $mod_strings['ERR_UW_NO_FILE_UPLOADED'];
2465 // delete file in upgrades/patch
2466 $delete_me = "$base_upgrade_dir/patch/".basename(urldecode( $_REQUEST['install_file'] ));
2467 if(@unlink($delete_me)) {
2468 //logThis('unlinking: '.$delete_me);
2469 $out = basename($delete_me).$mod_strings['LBL_UW_FILE_DELETED'];
2471 logThis('ERROR: could not delete ['.$delete_me.']');
2472 $error = $mod_strings['ERR_UW_FILE_NOT_DELETED'].$delete_me;
2475 if(!empty($error)) {
2476 $out = "<b><span class='error'>{$error}</span></b><br />";
2480 function handleExecuteSqlKeys($db, $tableName, $disable)
2482 if(empty($tableName)) return true;
2483 if(is_callable(array($db, "supports"))) {
2485 return $disable?$db->disableKeys($tableName):$db->enableKeys($tableName);
2488 $op = $disable?"DISABLE":"ENABLE";
2489 return $db->query("ALTER TABLE $tableName $op KEYS");
2493 function parseAndExecuteSqlFile($sqlScript,$forStepQuery='',$resumeFromQuery='')
2495 global $sugar_config;
2496 $alterTableSchema = '';
2497 $sqlErrors = array();
2498 if(!isset($_SESSION['sqlSkippedQueries'])){
2499 $_SESSION['sqlSkippedQueries'] = array();
2501 $db = DBManagerFactory::getInstance();
2502 $disable_keys = ($db->dbType == "mysql"); // have to use old way for now for upgrades
2503 if(strpos($resumeFromQuery,",") != false){
2504 $resumeFromQuery = explode(",",$resumeFromQuery);
2506 if(file_exists($sqlScript)) {
2507 $fp = fopen($sqlScript, 'r');
2508 $contents = stream_get_contents($fp);
2509 $anyScriptChanges =$contents;
2510 $resumeAfterFound = false;
2514 while($line = fgets($fp)) {
2515 if(strpos($line, '--') === false) {
2516 $completeLine .= " ".trim($line);
2517 if(strpos($line, ';') !== false) {
2519 $query = str_replace(';','',$completeLine);
2520 //if resume from query is not null then find out from where
2521 //it should start executing the query.
2523 if($query != null && $resumeFromQuery != null){
2524 if(!$resumeAfterFound){
2525 if(strpos($query,",") != false){
2526 $queArray = explode(",",$query);
2527 for($i=0;$i<sizeof($resumeFromQuery);$i++){
2528 if(strcasecmp(trim($resumeFromQuery[$i]),trim($queArray[$i]))==0){
2529 $resumeAfterFound = true;
2531 $resumeAfterFound = false;
2537 elseif(strcasecmp(trim($resumeFromQuery),trim($query))==0){
2538 $resumeAfterFound = true;
2541 if($resumeAfterFound){
2544 // if $count=1 means it is just found so skip the query. Run the next one
2545 if($query != null && $resumeAfterFound && $count >1){
2546 $tableName = getAlterTable($query);
2549 handleExecuteSqlKeys($db, $tableName, true);
2552 if($db->checkError()){
2553 //put in the array to use later on
2554 $_SESSION['sqlSkippedQueries'][] = $query;
2558 handleExecuteSqlKeys($db, $tableName, false);
2560 $progQuery[$forStepQuery]=$query;
2561 post_install_progress($progQuery,$action='set');
2564 elseif($query != null){
2565 $tableName = getAlterTable($query);
2568 handleExecuteSqlKeys($db, $tableName, true);
2573 handleExecuteSqlKeys($db, $tableName, false);
2575 $progQuery[$forStepQuery]=$query;
2576 post_install_progress($progQuery,$action='set');
2577 if($db->checkError()){
2578 //put in the array to use later on
2579 $_SESSION['sqlSkippedQueries'][] = $query;
2591 function getAlterTable($query){
2592 $query = strtolower($query);
2593 if (preg_match('/^\s*alter\s+table\s+/', $query)) {
2594 $sqlArray = explode(" ", $query);
2595 $key = array_search('table', $sqlArray);
2596 return $sqlArray[($key+1)];
2602 function set_upgrade_vars(){
2603 logThis('setting session variables...');
2604 $upgrade_progress_dir = sugar_cached('upgrades/temp');
2605 if(!is_dir($upgrade_progress_dir)){
2606 mkdir_recursive($upgrade_progress_dir);
2608 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
2609 if(file_exists($upgrade_progress_file)){
2610 include($upgrade_progress_file);
2613 fopen($upgrade_progress_file, 'w+');
2615 if(!isset($upgrade_config) || $upgrade_config == null){
2616 $upgrade_config = array();
2617 $upgrade_config[1]['upgrade_vars']=array();
2619 if(isset($upgrade_config[1]) && isset($upgrade_config[1]['upgrade_vars']) && !is_array($upgrade_config[1]['upgrade_vars'])){
2620 $upgrade_config[1]['upgrade_vars'] = array();
2623 if(!isset($upgrade_vars) || $upgrade_vars == NULL){
2624 $upgrade_vars = array();
2626 if(isset($_SESSION['unzip_dir']) && !empty($_SESSION['unzip_dir']) && file_exists($_SESSION['unzip_dir'])){
2627 $upgrade_vars['unzip_dir']=$_SESSION['unzip_dir'];
2629 if(isset($_SESSION['install_file']) && !empty($_SESSION['install_file']) && file_exists($_SESSION['install_file'])){
2630 $upgrade_vars['install_file']=$_SESSION['install_file'];
2632 if(isset($_SESSION['Upgraded451Wizard']) && !empty($_SESSION['Upgraded451Wizard'])){
2633 $upgrade_vars['Upgraded451Wizard']=$_SESSION['Upgraded451Wizard'];
2635 if(isset($_SESSION['license_shown']) && !empty($_SESSION['license_shown'])){
2636 $upgrade_vars['license_shown']=$_SESSION['license_shown'];
2638 if(isset($_SESSION['Initial_451to500_Step']) && !empty($_SESSION['Initial_451to500_Step'])){
2639 $upgrade_vars['Initial_451to500_Step']=$_SESSION['Initial_451to500_Step'];
2641 if(isset($_SESSION['zip_from_dir']) && !empty($_SESSION['zip_from_dir'])){
2642 $upgrade_vars['zip_from_dir']=$_SESSION['zip_from_dir'];
2644 //place into the upgrade_config array and rewrite config array only if new values are being inserted
2645 if(isset($upgrade_vars) && $upgrade_vars != null && sizeof($upgrade_vars) > 0){
2646 foreach($upgrade_vars as $key=>$val){
2647 if($key != null && $val != null){
2648 $upgrade_config[1]['upgrade_vars'][$key]=$upgrade_vars[$key];
2651 ksort($upgrade_config);
2652 if(is_writable($upgrade_progress_file) && write_array_to_file( "upgrade_config", $upgrade_config,
2653 $upgrade_progress_file)) {
2654 //writing to the file
2659 function initialize_session_vars(){
2660 $upgrade_progress_dir = sugar_cached('upgrades/temp');
2661 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
2662 if(file_exists($upgrade_progress_file)){
2663 include($upgrade_progress_file);
2664 if(isset($upgrade_config) && $upgrade_config != null && is_array($upgrade_config) && sizeof($upgrade_config) >0){
2665 $currVarsArray=$upgrade_config[1]['upgrade_vars'];
2666 //print_r($currVarsArray);
2667 if(isset($currVarsArray) && $currVarsArray != null && is_array($currVarsArray) && sizeof($currVarsArray)>0){
2668 foreach($currVarsArray as $key=>$val){
2669 if($key != null && $val !=null){
2670 //set session variables
2671 $_SESSION[$key]=$val;
2680 //track the upgrade progress on each step
2681 //track the upgrade progress on each step
2682 function set_upgrade_progress($currStep,$currState,$currStepSub='',$currStepSubState=''){
2684 $upgrade_progress_dir = sugar_cached('upgrades/temp');
2685 if(!is_dir($upgrade_progress_dir)){
2686 mkdir_recursive($upgrade_progress_dir);
2688 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
2689 if(file_exists($upgrade_progress_file)){
2690 include($upgrade_progress_file);
2693 if(function_exists('sugar_fopen')){
2694 sugar_fopen($upgrade_progress_file, 'w+');
2697 fopen($upgrade_progress_file, 'w+');
2700 if(!isset($upgrade_config) || $upgrade_config == null){
2701 $upgrade_config = array();
2702 $upgrade_config[1]['upgrade_vars']=array();
2704 if(!is_array($upgrade_config[1]['upgrade_vars'])){
2705 $upgrade_config[1]['upgrade_vars'] = array();
2707 if($currStep != null && $currState != null){
2708 if(sizeof($upgrade_config) > 0){
2709 if($currStepSub != null && $currStepSubState !=null){
2710 //check if new status to be set or update
2711 //get the latest in array. since it has sub components prepare an array
2712 if(!empty($upgrade_config[sizeof($upgrade_config)][$currStep]) && is_array($upgrade_config[sizeof($upgrade_config)][$currStep])){
2713 $latestStepSub = currSubStep($upgrade_config[sizeof($upgrade_config)][$currStep]);
2714 if($latestStepSub == $currStepSub){
2715 $upgrade_config[sizeof($upgrade_config)][$currStep][$latestStepSub]=$currStepSubState;
2716 $upgrade_config[sizeof($upgrade_config)][$currStep][$currStep] = $currState;
2719 $upgrade_config[sizeof($upgrade_config)][$currStep][$currStepSub]=$currStepSubState;
2720 $upgrade_config[sizeof($upgrade_config)][$currStep][$currStep] = $currState;
2724 $currArray = array();
2725 $currArray[$currStep] = $currState;
2726 $currArray[$currStepSub] = $currStepSubState;
2727 $upgrade_config[sizeof($upgrade_config)+1][$currStep] = $currArray;
2731 //get the current upgrade progress
2732 $latestStep = get_upgrade_progress();
2733 //set the upgrade progress
2734 if($latestStep == $currStep){
2735 //update the current step with new progress status
2736 $upgrade_config[sizeof($upgrade_config)][$latestStep]=$currState;
2740 $upgrade_config[sizeof($upgrade_config)+1][$currStep]=$currState;
2742 // now check if there elements within array substeps
2746 //set the upgrade progress (just starting)
2747 $upgrade_config[sizeof($upgrade_config)+1][$currStep]= $currState;
2750 if(is_writable($upgrade_progress_file) && write_array_to_file( "upgrade_config", $upgrade_config,
2751 $upgrade_progress_file)) {
2752 //writing to the file
2758 function get_upgrade_progress(){
2759 $upgrade_progress_dir = sugar_cached('upgrades/temp');
2760 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
2763 if(file_exists($upgrade_progress_file)){
2764 include($upgrade_progress_file);
2765 if(!isset($upgrade_config) || $upgrade_config == null){
2766 $upgrade_config = array();
2768 if($upgrade_config != null && sizeof($upgrade_config) >1){
2769 $currArr = $upgrade_config[sizeof($upgrade_config)];
2770 if(is_array($currArr)){
2771 foreach($currArr as $key=>$val){
2779 function currSubStep($currStep){
2781 if(is_array($currStep)){
2782 foreach($currStep as $key=>$val){
2790 function currUpgradeState($currState){
2792 if(is_array($currState)){
2793 foreach($currState as $key=>$val){
2795 foreach($val as $k=>$v){
2809 function didThisStepRunBefore($step,$SubStep=''){
2810 if($step == null) return;
2811 $upgrade_progress_dir = sugar_cached('upgrades/temp');
2812 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
2815 if(file_exists($upgrade_progress_file)){
2816 include($upgrade_progress_file);
2817 if(isset($upgrade_config) && $upgrade_config != null && is_array($upgrade_config) && sizeof($upgrade_config) >0){
2818 for($i=1;$i<=sizeof($upgrade_config);$i++){
2819 if(is_array($upgrade_config[$i])){
2820 foreach($upgrade_config[$i] as $key=>$val){
2822 if(is_array($upgrade_config[$i][$step])){
2824 foreach ($upgrade_config[$i][$step] as $k=>$v){
2826 foreach($v as $k1=>$v1){
2827 if($SubStep != null){
2828 if($SubStep ==$k1 && $v1=='done'){
2835 elseif($SubStep !=null){
2836 if($SubStep==$k && $v=='done'){
2841 elseif($step==$k && $v=='done'){
2847 elseif($val=='done'){
2861 //get and set post install status
2862 function post_install_progress($progArray='',$action=''){
2863 $upgrade_progress_dir = sugar_cached('upgrades/temp');
2864 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
2865 if($action=='' || $action=='get'){
2866 //get the state of post install
2867 $currProg = array();
2868 if(file_exists($upgrade_progress_file)){
2869 include($upgrade_progress_file);
2870 if(is_array($upgrade_config[sizeof($upgrade_config)]['commit']['post_install']) && sizeof($upgrade_config[sizeof($upgrade_config)]['commit']['post_install'])>0){
2871 foreach($upgrade_config[sizeof($upgrade_config)]['commit']['post_install'] as $k=>$v){
2878 elseif($action=='set'){
2879 if(!is_dir($upgrade_progress_dir)){
2880 mkdir($upgrade_progress_dir);
2882 if(file_exists($upgrade_progress_file)){
2883 include($upgrade_progress_file);
2886 fopen($upgrade_progress_file, 'w+');
2888 if(!is_array($upgrade_config[sizeof($upgrade_config)]['commit']['post_install'])){
2889 $upgrade_config[sizeof($upgrade_config)]['commit']['post_install']=array();
2890 $upgrade_config[sizeof($upgrade_config)]['commit']['post_install']['post_install'] = 'in_progress';
2892 if($progArray != null && is_array($progArray)){
2893 foreach($progArray as $key=>$val){
2894 $upgrade_config[sizeof($upgrade_config)]['commit']['post_install'][$key]=$val;
2897 if(is_writable($upgrade_progress_file) && write_array_to_file( "upgrade_config", $upgrade_config,
2898 $upgrade_progress_file)) {
2899 //writing to the file
2904 function repairDBForUpgrade($execute=false,$path=''){
2906 global $current_user, $beanFiles;
2908 set_time_limit(3600);
2910 $db = &DBManagerFactory::getInstance();
2912 VardefManager::clearVardef();
2913 require_once('include/ListView/ListView.php');
2914 foreach ($beanFiles as $bean => $file) {
2915 require_once ($file);
2916 $focus = new $bean ();
2917 $sql .= $db->repairTable($focus, $execute);
2921 $olddictionary = $dictionary;
2922 unset ($dictionary);
2923 include ('modules/TableDictionary.php');
2924 foreach ($dictionary as $meta) {
2925 $tablename = $meta['table'];
2926 $fielddefs = $meta['fields'];
2927 $indices = $meta['indices'];
2928 $sql .= $db->repairTableParams($tablename, $fielddefs, $indices, $execute);
2931 foreach (explode("\n", $sql) as $line) {
2932 if (!empty ($line) && substr($line, -2) != "*/") {
2935 $qry_str .= $line . "\n";
2946 preg_replace('#(/\*.+?\*/\n*)#', '', $qry_str)
2948 logThis("*******START EXECUTING DB UPGRADE QUERIES***************",$path);
2949 logThis($sql,$path);
2950 logThis("*******END EXECUTING DB UPGRADE QUERIES****************",$path);
2959 * upgradeUserPreferences
2960 * This method updates the user_preferences table and sets the pages/dashlets for users
2961 * which have ACL access to Trackers so that the Tracker dashlets are set in their user perferences
2964 function upgradeUserPreferences() {
2965 global $sugar_config, $sugar_version;
2966 $uw_strings = return_module_language($GLOBALS['current_language'], 'UpgradeWizard');
2968 $localization = new Localization();
2969 $localeCoreDefaults = $localization->getLocaleConfigDefaults();
2971 // check the current system wide default_locale_name_format and add it to the list if it's not there
2972 if(empty($sugar_config['name_formats'])) {
2973 $sugar_config['name_formats'] = $localeCoreDefaults['name_formats'];
2974 if(!rebuildConfigFile($sugar_config, $sugar_version)) {
2975 $errors[] = $uw_strings['ERR_UW_CONFIG_WRITE'];
2979 $currentDefaultLocaleNameFormat = $sugar_config['default_locale_name_format'];
2981 if ($localization->isAllowedNameFormat($currentDefaultLocaleNameFormat)) {
2982 upgradeLocaleNameFormat($currentDefaultLocaleNameFormat);
2984 $sugar_config['default_locale_name_format'] = $localeCoreDefaults['default_locale_name_format'];
2985 if(!rebuildConfigFile($sugar_config, $sugar_version)) {
2986 $errors[] = $uw_strings['ERR_UW_CONFIG_WRITE'];
2988 $localization->createInvalidLocaleNameFormatUpgradeNotice();
2991 $db = &DBManagerFactory::getInstance();
2992 $result = $db->query("SELECT id FROM users where deleted = '0'");
2993 while($row = $db->fetchByAssoc($result))
2995 $current_user = new User();
2996 $current_user->retrieve($row['id']);
2998 // 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
2999 $currentUserNameFormat = $current_user->getPreference('default_locale_name_format');
3000 if ($localization->isAllowedNameFormat($currentUserNameFormat)) {
3001 upgradeLocaleNameFormat($currentUserNameFormat);
3003 $current_user->setPreference('default_locale_name_format', 's f l', 0, 'global');
3004 $current_user->savePreferencesToDB();
3012 * Checks if a locale name format is part of the default list, if not adds it to the config
3013 * @param $name_format string a local name format string such as 's f l'
3014 * @return bool true on successful write to config file, false on failure;
3016 function upgradeLocaleNameFormat($name_format) {
3017 global $sugar_config, $sugar_version;
3019 $localization = new Localization();
3020 $localeConfigDefaults = $localization->getLocaleConfigDefaults();
3022 $uw_strings = return_module_language($GLOBALS['current_language'], 'UpgradeWizard');
3023 if(empty($sugar_config['name_formats'])) {
3024 $sugar_config['name_formats'] = $localeConfigDefaults['name_formats'];
3025 if(!rebuildConfigFile($sugar_config, $sugar_version)) {
3026 $errors[] = $uw_strings['ERR_UW_CONFIG_WRITE'];
3029 if (!in_array($name_format, $sugar_config['name_formats'])) {
3030 $new_config = sugarArrayMerge($sugar_config['name_formats'], array($name_format=>$name_format));
3031 $sugar_config['name_formats'] = $new_config;
3032 if(!rebuildConfigFile($sugar_config, $sugar_version)) {
3033 $errors[] = $uw_strings['ERR_UW_CONFIG_WRITE'];
3042 function add_custom_modules_favorites_search(){
3043 $module_directories = scandir('modules');
3045 foreach($module_directories as $module_dir){
3046 if($module_dir == '.' || $module_dir == '..' || !is_dir("modules/{$module_dir}")){
3051 preg_match('/^[a-z0-9]{1,5}_[a-z0-9_]+$/i' , $module_dir, $matches);
3053 // Make sure the module was created by module builder
3054 if(empty($matches)){
3058 $full_module_dir = "modules/{$module_dir}/";
3059 $read_searchdefs_from = "{$full_module_dir}/metadata/searchdefs.php";
3060 $read_SearchFields_from = "{$full_module_dir}/metadata/SearchFields.php";
3061 $read_custom_SearchFields_from = "custom/{$full_module_dir}/metadata/SearchFields.php";
3063 // Studio can possibly override this file, so we check for a custom version of it
3064 if(file_exists("custom/{$full_module_dir}/metadata/searchdefs.php")){
3065 $read_searchdefs_from = "custom/{$full_module_dir}/metadata/searchdefs.php";
3068 if(file_exists($read_searchdefs_from) && file_exists($read_SearchFields_from)){
3071 require($read_searchdefs_from);
3072 foreach($searchdefs[$module_dir]['layout']['basic_search'] as $sf_array){
3073 if(isset($sf_array['name']) && $sf_array['name'] == 'favorites_only'){
3078 require($read_SearchFields_from);
3079 if(isset($searchFields[$module_dir]['favorites_only'])){
3083 if(!$found_sf1 && !$found_sf2){
3084 $searchdefs[$module_dir]['layout']['basic_search']['favorites_only'] = array('name' => 'favorites_only','label' => 'LBL_FAVORITES_FILTER','type' => 'bool',);
3085 $searchdefs[$module_dir]['layout']['advanced_search']['favorites_only'] = array('name' => 'favorites_only','label' => 'LBL_FAVORITES_FILTER','type' => 'bool',);
3086 $searchFields[$module_dir]['favorites_only'] = array(
3087 'query_type'=>'format',
3088 'operator' => 'subquery',
3089 'subquery' => 'SELECT sugarfavorites.record_id FROM sugarfavorites
3090 WHERE sugarfavorites.deleted=0
3091 and sugarfavorites.module = \''.$module_dir.'\'
3092 and sugarfavorites.assigned_user_id = \'{0}\'',
3093 'db_field'=>array('id')
3096 if(!is_dir("custom/{$full_module_dir}/metadata")){
3097 mkdir_recursive("custom/{$full_module_dir}/metadata");
3099 $success_sf1 = write_array_to_file('searchdefs', $searchdefs, "custom/{$full_module_dir}/metadata/searchdefs.php");
3100 $success_sf2 = write_array_to_file('searchFields', $searchFields, "{$full_module_dir}/metadata/SearchFields.php");
3103 logThis("add_custom_modules_favorites_search failed for searchdefs.php for {$module_dir}");
3106 logThis("add_custom_modules_favorites_search failed for SearchFields.php for {$module_dir}");
3108 if($success_sf1 && $success_sf2){
3109 logThis("add_custom_modules_favorites_search successfully updated searchdefs and searchFields for {$module_dir}");
3118 * upgradeModulesForTeamsets
3120 * This method adds the team_set_id values to the module tables that have the new team_set_id column
3121 * added through the SugarCRM 5.5.x upgrade process. It also adds the values into the team_sets and
3122 * team_sets_teams tables.
3124 * @param filter Array of modules to process; empty by default
3126 function upgradeModulesForTeamsets($filter=array()) {
3127 require('include/modules.php');
3128 foreach($beanList as $moduleName=>$beanName) {
3129 if(!empty($filter) && array_search($moduleName, $filter) === false) {
3132 if($moduleName == 'TeamMemberships' || $moduleName == 'ForecastOpportunities'){
3135 $bean = loadBean($moduleName);
3137 empty($bean->table_name)) {
3141 $FieldArray = $GLOBALS['db']->helper->get_columns($bean->table_name);
3142 if(!isset($FieldArray['team_id'])) {
3146 upgradeTeamColumn($bean, 'team_id');
3150 //Upgrade users table
3151 $bean = loadBean('Users');
3152 upgradeTeamColumn($bean, 'default_team');
3153 $result = $GLOBALS['db']->query("SELECT id FROM teams where deleted=0");
3154 while($row = $GLOBALS['db']->fetchByAssoc($result)) {
3155 $teamset = new TeamSet();
3156 $teamset->addTeams($row['id']);
3163 * Helper function to create a team_set_id column and also set team_set_id column
3164 * to have the value of the $column_name parameter
3166 * @param $bean SugarBean which we are adding team_set_id column to
3167 * @param $column_name The name of the column containing the default team_set_id value
3169 function upgradeTeamColumn($bean, $column_name) {
3170 //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
3171 //module that does not use the SugarObjects
3172 if(empty($bean->field_defs['team_set_id']) && $bean->module_dir != 'Trackers'){
3174 //at this point we could assume that since we have a team_id defined and not a team_set_id that we need to
3175 //add that field and the corresponding relationships
3176 $object = $bean->object_name;
3177 $module = $bean->module_dir;
3178 $object_name = $object;
3179 $_object_name = strtolower($object_name);
3181 if(!empty($GLOBALS['dictionary'][$object]['table'])){
3182 $table_name = $GLOBALS['dictionary'][$object]['table'];
3184 $table_name = strtolower($module);
3187 $path = 'include/SugarObjects/implements/team_security/vardefs.php';
3189 //go through each entry in the vardefs from team_security and unset anything that is already set in the core module
3190 //this will ensure we have the proper ordering.
3191 $fieldDiff = array_diff_assoc($vardefs['fields'], $GLOBALS['dictionary'][$bean->object_name]['fields']);
3193 $file = 'custom/Extension/modules/' . $bean->module_dir. '/Ext/Vardefs/teams.php';
3194 $contents = "<?php\n";
3195 if(!empty($fieldDiff)){
3196 foreach($fieldDiff as $key => $val){
3197 $contents .= "\n\$GLOBALS['dictionary']['". $object . "']['fields']['". $key . "']=" . var_export_helper($val) . ";";
3200 $relationshipDiff = array_diff_assoc($vardefs['relationships'], $GLOBALS['dictionary'][$bean->object_name]['relationships']);
3201 if(!empty($relationshipDiff)){
3202 foreach($relationshipDiff as $key => $val){
3203 $contents .= "\n\$GLOBALS['dictionary']['". $object . "']['relationships']['". $key . "']=" . var_export_helper($val) . ";";
3206 $indexDiff = array_diff_assoc($vardefs['indices'], $GLOBALS['dictionary'][$bean->object_name]['indices']);
3207 if(!empty($indexDiff)){
3208 foreach($indexDiff as $key => $val){
3209 $contents .= "\n\$GLOBALS['dictionary']['". $object . "']['indices']['". $key . "']=" . var_export_helper($val) . ";";
3212 if( $fh = @sugar_fopen( $file, 'wt' ) )
3214 fputs( $fh, $contents);
3219 //we have written out the teams.php into custom/Extension/modules/{$module_dir}/Ext/Vardefs/teams.php'
3220 //now let's merge back into vardefs.ext.php
3221 require_once('ModuleInstall/ModuleInstaller.php');
3222 $mi = new ModuleInstaller();
3223 $mi->merge_files('Ext/Vardefs/', 'vardefs.ext.php');
3224 VardefManager::loadVardef($bean->module_dir, $bean->object_name, true);
3225 $bean->field_defs = $GLOBALS['dictionary'][$bean->object_name]['fields'];
3228 if(isset($bean->field_defs['team_set_id'])) {
3229 //Create the team_set_id column
3230 $FieldArray = $GLOBALS['db']->helper->get_columns($bean->table_name);
3231 if(!isset($FieldArray['team_set_id'])) {
3232 $GLOBALS['db']->addColumn($bean->table_name, $bean->field_defs['team_set_id']);
3234 $indexArray = $GLOBALS['db']->helper->get_indices($bean->table_name);
3236 $indexName = getValidDBName('idx_'.strtolower($bean->table_name).'_tmst_id', true, 34);
3239 'name' => $indexName,
3241 'fields' => array('team_set_id')
3244 if(!isset($indexArray[$indexName])) {
3245 $GLOBALS['db']->addIndexes($bean->table_name, $indexDef);
3248 //Update the table's team_set_id column to have the same values as team_id
3249 $GLOBALS['db']->query("UPDATE {$bean->table_name} SET team_set_id = {$column_name}");
3254 * Update the folder subscription table which confirms to the team security mechanism but
3255 * the class SugarFolders does not extend SugarBean and is therefore never picked up by the
3256 * upgradeModulesForTeamsets function.
3258 function upgradeFolderSubscriptionsTeamSetId()
3260 logThis("In upgradeFolderSubscriptionsTeamSetId()");
3261 $query = "UPDATE folders SET team_set_id = team_id";
3262 $result = $GLOBALS['db']->query($query);
3263 logThis("Finished upgradeFolderSubscriptionsTeamSetId()");
3267 * upgradeModulesForTeam
3269 * This method update the associated_user_id, name, name_2 to the private team records on teams table
3270 * This function is used for upgrade process from 5.1.x and 5.2.x.
3273 function upgradeModulesForTeam() {
3274 logThis("In upgradeModulesForTeam()");
3275 $result = $GLOBALS['db']->query("SELECT id, user_name, first_name, last_name FROM users where deleted=0");
3277 while($row = $GLOBALS['db']->fetchByAssoc($result)) {
3278 $results2 = $GLOBALS['db']->query("SELECT id FROM teams WHERE name = '({$row['user_name']})'");
3280 if(!$assoc = $GLOBALS['db']->fetchByAssoc($results2)) {
3281 //if team does not exist, then lets create the team for this user
3284 $user->retrieve($row['id']);
3285 $team->new_user_created($user);
3286 $team_id = $team->id;
3288 $team_id =$assoc['id'];
3292 $name = is_null($row['first_name'])?'':$row['first_name'];
3293 $name_2 = is_null($row['last_name'])?'':$row['last_name'];
3294 $associated_user_id = $row['id'];
3297 //Ensure team->name is not empty by using team->name_2 if available
3298 if(empty($name) && !empty($name_2)) {
3303 $query = "UPDATE teams SET name = '{$name}', name_2 = '{$name_2}', associated_user_id = '{$associated_user_id}' WHERE id = '{$team_id}'";
3304 $GLOBALS['db']->query($query);
3307 //Update the team_set_id and default_team columns
3308 $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'));
3310 //Update team_set_id
3311 if($ce_to_pro_or_ent) {
3312 $GLOBALS['db']->query("update users set team_set_id = (select teams.id from teams where teams.associated_user_id = users.id)");
3313 $GLOBALS['db']->query("update users set default_team = (select teams.id from teams where teams.associated_user_id = users.id)");
3319 function addNewSystemTabsFromUpgrade($from_dir){
3321 if(isset($_SESSION['upgrade_from_flavor'])){
3323 //check to see if there are any new files that need to be added to systems tab
3324 //retrieve old modules list
3325 logThis('check to see if new modules exist',$path);
3326 $oldModuleList = array();
3327 $newModuleList = array();
3328 include($from_dir.'/include/modules.php');
3329 $oldModuleList = $moduleList;
3330 include('include/modules.php');
3331 $newModuleList = $moduleList;
3333 //include tab controller
3334 require_once('modules/MySettings/TabController.php');
3335 $newTB = new TabController();
3337 //make sure new modules list has a key we can reference directly
3338 $newModuleList = $newTB->get_key_array($newModuleList);
3339 $oldModuleList = $newTB->get_key_array($oldModuleList);
3341 //iterate through list and remove commonalities to get new modules
3342 foreach ($newModuleList as $remove_mod){
3343 if(in_array($remove_mod, $oldModuleList)){
3344 unset($newModuleList[$remove_mod]);
3347 //new modules list now has left over modules which are new to this install, so lets add them to the system tabs
3348 logThis('new modules to add are '.var_export($newModuleList,true),$path);
3350 if(!empty($newModuleList))
3352 //grab the existing system tabs
3353 $tabs = $newTB->get_system_tabs();
3355 //add the new tabs to the array
3356 foreach($newModuleList as $nm ){
3360 $newTB->set_system_tabs($tabs);
3362 logThis('module tabs updated',$path);
3368 * This method attempts to fix dropdown lists that were incorrectly named.
3369 * There were versions of SugarCRM that did not enforce naming convention rules
3370 * for the dropdown list field name. This method attempts to resolve that by
3371 * fixing the language files that may have been affected and then updating the
3372 * fields_meta_data table accordingly. It also refreshes any vardefs that may
3373 * have been affected.
3376 function fix_dropdown_list() {
3377 if(file_exists('custom/include/language')) {
3379 $affected_modules = array();
3380 $affected_keys = array();
3382 getFiles($files, 'custom/include/language', '/\.php$/i');
3383 foreach($files as $file) {
3385 if(file_exists($file . '.bak')) {
3386 $bak_mod_time = filemtime($file . '.bak');
3387 $php_mod_time = filemtime($file);
3388 //We're saying if the .php file was modified 30 seconds no more than php.bak file then we
3389 //run these additional cleanup checks
3390 if($php_mod_time - $bak_mod_time < 30) {
3392 $app_list_strings = array();
3393 $GLOBALS['app_list_strings'] = array();
3394 require($file . '.bak');
3395 $bak_app_list_strings = array_merge($app_list_strings, $GLOBALS['app_list_strings']);
3397 $app_list_strings = array();
3398 $GLOBALS['app_list_strings'] = array();
3400 $php_app_list_strings = array_merge($app_list_strings, $GLOBALS['app_list_strings']);
3402 //Get the file contents
3403 $contents = file_get_contents($file);
3405 //Now simulate a fix for the file before we compare w/ the .php file
3406 //we also append to the $contents
3407 foreach($bak_app_list_strings as $key=>$entry) {
3408 if(preg_match('/([^A-Za-z_])/', $key, $matches) && is_array($entry)) {
3409 $new_key = preg_replace('/[^A-Za-z_]/', '_', $key);
3410 $bak_app_list_strings[$new_key] = $bak_app_list_strings[$key];
3411 unset($bak_app_list_strings[$key]);
3412 //Now if the entry doesn't exists in the .php file, then add to contents
3413 if(!isset($php_app_list_strings[$new_key])) {
3414 $contents .= "\n\$GLOBALS['app_list_strings']['{$new_key}'] = " . var_export_helper($bak_app_list_strings[$new_key]) . ";";
3419 //Now load the .php file to do the comparison
3420 foreach($php_app_list_strings as $key=>$entry) {
3421 if(isset($bak_app_list_strings[$key])) {
3422 $diff = array_diff($bak_app_list_strings[$key], $entry);
3424 //There is a difference, so copy the $bak_app_list_strings version into the .php file
3425 $contents .= "\n\$GLOBALS['app_list_strings']['{$key}'] = " . var_export_helper($bak_app_list_strings[$key]) . ";";
3430 //Now write out the file contents
3431 //Create backup just in case
3432 copy($file, $file . '.php_bak');
3433 $fp = @sugar_fopen($file, 'w');
3435 fwrite($fp, $contents);
3438 $GLOBALS['log']->error("Unable to update file contents in fix_dropdown_list for {$file}");
3443 unset($GLOBALS['app_strings']);
3444 unset($GLOBALS['app_list_strings']);
3445 $app_list_strings = array();
3448 $contents = file_get_contents($file);
3449 if ( !isset($GLOBALS['app_list_strings']) ) {
3450 $GLOBALS['app_list_strings'] = $app_list_strings;
3453 $GLOBALS['app_list_strings'] = array_merge($app_list_strings, $GLOBALS['app_list_strings']);
3456 if(isset($GLOBALS['app_list_strings']) && is_array($GLOBALS['app_list_strings'])) {
3457 foreach($GLOBALS['app_list_strings'] as $key=>$entry) {
3458 if(preg_match('/([^A-Za-z_])/', $key, $matches) && is_array($entry)) {
3459 $result = $GLOBALS['db']->query("SELECT custom_module FROM fields_meta_data WHERE ext1 = '{$key}'");
3460 if(!empty($result)) {
3461 while($row = $GLOBALS['db']->fetchByAssoc($result)) {
3462 $custom_module = $row['custom_module'];
3463 if(!empty($GLOBALS['beanList'][$custom_module])) {
3464 $affected_modules[$custom_module] = $GLOBALS['beanList'][$custom_module];
3469 //Replace all invalid characters with '_' character
3470 $new_key = preg_replace('/[^A-Za-z_]/', '_', $key);
3471 $affected_keys[$key] = $new_key;
3473 $GLOBALS['app_list_strings'][$new_key] = $GLOBALS['app_list_strings'][$key];
3474 unset($GLOBALS['app_list_strings'][$key]);
3476 $pattern_match = "/(\[\s*\'{$key}\'\s*\])/";
3477 $new_key = "['{$new_key}']";
3478 $out = preg_replace($pattern_match, $new_key, $contents);
3484 //This is a check for g => h instances where the file contents were incorrectly written
3485 //and also fixes the scenario where via a UI upgrade, the app_list_strings were incorrectly
3486 //merged with app_list_strings variables declared elsewhere
3488 if(preg_match('/\$GLOBALS\s*\[\s*[\"|\']app_list_strings[\"|\']\s*\]\s*=\s*array\s*\(/', $contents)) {
3489 //Now also remove all the non-custom labels that were added
3490 if(preg_match('/language\/([^\.]+)\.lang\.php$/', $file, $matches)) {
3491 $language = $matches[1];
3493 $app_list_strings = array();
3495 if(file_exists("include/language/$language.lang.php")) {
3496 include("include/language/$language.lang.php");
3498 if(file_exists("include/language/$language.lang.override.php")) {
3499 $app_list_strings = _mergeCustomAppListStrings("include/language/$language.lang.override.php" , $app_list_strings) ;
3501 if(file_exists("custom/application/Ext/Language/$language.ext.lang.php")) {
3502 $app_list_strings = _mergeCustomAppListStrings("custom/application/Ext/Language/$language.ext.lang.php" , $app_list_strings) ;
3504 if(file_exists("custom/application/Ext/Language/$language.lang.ext.php")) {
3505 $app_list_strings = _mergeCustomAppListStrings("custom/application/Ext/Language/$language.lang.ext.php" , $app_list_strings) ;
3508 $all_non_custom_include_language_strings = $app_strings;
3509 $all_non_custom_include_language_list_strings = $app_list_strings;
3511 $unset_keys = array();
3512 if(!empty($GLOBALS['app_list_strings'])) {
3513 foreach($GLOBALS['app_list_strings'] as $key=>$value) {
3515 if(isset($all_non_custom_include_language_list_strings[$key])) {
3516 $diff = array_diff($all_non_custom_include_language_list_strings[$key], $GLOBALS['app_list_strings'][$key]);
3519 if(!empty($all_non_custom_include_language_list_strings[$key]) && empty($diff)) {
3520 $unset_keys[] = $key;
3525 foreach($unset_keys as $key) {
3526 unset($GLOBALS['app_list_strings'][$key]);
3529 if(!empty($GLOBALS['app_strings'])) {
3530 foreach($GLOBALS['app_strings'] as $key=>$value) {
3531 if(!empty($all_non_custom_include_language_strings[$key])) {
3532 unset($GLOBALS['app_strings'][$key]);
3536 } //if(preg_match...)
3539 if(!empty($GLOBALS['app_strings'])) {
3540 foreach($GLOBALS['app_strings'] as $key=>$entry) {
3541 $out .= "\n\$GLOBALS['app_strings']['$key']=" . var_export_helper($entry) . ";";
3545 foreach($GLOBALS['app_list_strings'] as $key=>$entry) {
3546 $out .= "\n\$GLOBALS['app_list_strings']['$key']=" . var_export_helper($entry) . ";";
3550 } //if(preg_match...)
3554 //Create a backup just in case
3555 copy($file, $file . '.bak');
3556 $fp = @sugar_fopen($file, 'w');
3561 //If we can't update the file, just return
3562 $GLOBALS['log']->error("Unable to update file contents in fix_dropdown_list.");
3570 //Update db entries (the order matters here... need to process database changes first)
3571 if(!empty($affected_keys)) {
3572 foreach($affected_keys as $old_key=>$new_key) {
3573 $GLOBALS['db']->query("UPDATE fields_meta_data SET ext1 = '{$new_key}' WHERE ext1 = '{$old_key}'");
3577 //Update vardef files for affected modules
3578 if(!empty($affected_modules)) {
3579 foreach($affected_modules as $module=>$object) {
3580 VardefManager::refreshVardefs($module, $object);
3587 function update_iframe_dashlets(){
3588 require_once(sugar_cached('dashlets/dashlets.php'));
3590 $db = DBManagerFactory::getInstance();
3591 $query = "SELECT id, contents, assigned_user_id FROM user_preferences WHERE deleted = 0 AND category = 'Home'";
3592 $result = $db->query($query, true, "Unable to update new default dashlets! ");
3593 while ($row = $db->fetchByAssoc($result)) {
3594 $content = unserialize(base64_decode($row['contents']));
3595 $assigned_user_id = $row['assigned_user_id'];
3596 $record_id = $row['id'];
3598 $current_user = new User();
3599 $current_user->retrieve($row['assigned_user_id']);
3601 if(!empty($content['dashlets']) && !empty($content['pages'])){
3602 $originalDashlets = $content['dashlets'];
3603 foreach($originalDashlets as $key => $ds){
3604 if(!empty($ds['options']['url']) && stristr($ds['options']['url'],'http://www.sugarcrm.com/crm/product/gopro')){
3605 unset($originalDashlets[$key]);
3608 $current_user->setPreference('dashlets', $originalDashlets, 0, 'Home');
3615 * convertImageToText
3617 * This method attempts to convert date type image to text on Microsoft SQL Server.
3618 * This method could NOT be used in any other type of datebases.
3620 function convertImageToText($table_name,$column_name){
3621 $set_lang = "SET LANGUAGE us_english";
3622 $GLOBALS['db']->query($set_lang);
3623 if($GLOBALS['db']->lastError()){
3624 logThis('An error occurred when performing this query-->'.$set_lang);
3626 $q="SELECT data_type
3627 FROM INFORMATION_SCHEMA.Tables T JOIN INFORMATION_SCHEMA.Columns C
3628 ON T.TABLE_NAME = C.TABLE_NAME where T.TABLE_NAME = '$table_name' and C.COLUMN_NAME = '$column_name'";
3629 $res= $GLOBALS['db']->query($q);
3630 if($GLOBALS['db']->lastError()){
3631 logThis('An error occurred when performing this query-->'.$q);
3633 $row= $GLOBALS['db']->fetchByAssoc($res);
3635 if(trim(strtolower($row['data_type'])) == 'image'){
3636 $addContent_temp = "alter table {$table_name} add {$column_name}_temp text null";
3637 $GLOBALS['db']->query($addContent_temp);
3638 if($GLOBALS['db']->lastError()){
3639 logThis('An error occurred when performing this query-->'.$addContent_temp);
3641 $qN = "select count=datalength({$column_name}), id, {$column_name} from {$table_name}";
3642 $result = $GLOBALS['db']->query($qN);
3643 while($row = $GLOBALS['db']->fetchByAssoc($result)){
3644 if($row['count'] >8000){
3645 $contentLength = $row['count'];
3648 $convertedContent = '';
3649 while($contentLength >0){
3650 $stepsQuery = "select cont=convert(varchar(max), convert(varbinary(8000), substring({$column_name},{$start},{$next}))) from {$table_name} where id= '{$row['id']}'";
3651 $steContQ = $GLOBALS['db']->query($stepsQuery);
3652 if($GLOBALS['db']->lastError()){
3653 logThis('An error occurred when performing this query-->'.$stepsQuery);
3655 $stepCont = $GLOBALS['db']->fetchByAssoc($steContQ);
3656 if(isset($stepCont['cont'])){
3657 $convertedContent = $convertedContent.$stepCont['cont'];
3659 $start = $start+$next;
3660 $contentLength = $contentLength - $next;
3662 $addContentDataText="update {$table_name} set {$column_name}_temp = '{$convertedContent}' where id= '{$row['id']}'";
3663 $GLOBALS['db']->query($addContentDataText);
3664 if($GLOBALS['db']->lastError()){
3665 logThis('An error occurred when performing this query-->'.$addContentDataText);
3669 $addContentDataText="update {$table_name} set {$column_name}_temp =
3670 convert(varchar(max), convert(varbinary(8000), {$column_name})) where id= '{$row['id']}'";
3671 $GLOBALS['db']->query($addContentDataText);
3672 if($GLOBALS['db']->lastError()){
3673 logThis('An error occurred when performing this query-->'.$addContentDataText);
3677 //drop the contents now and change contents_temp to contents
3678 $dropColumn = "alter table {$table_name} drop column {$column_name}";
3679 $GLOBALS['db']->query($dropColumn);
3680 if($GLOBALS['db']->lastError()){
3681 logThis('An error occurred when performing this query-->'.$dropColumn);
3683 $changeColumnName = "EXEC sp_rename '{$table_name}.[{$column_name}_temp]','{$column_name}','COLUMN'";
3684 $GLOBALS['db']->query($changeColumnName);
3685 if($GLOBALS['db']->lastError()){
3686 logThis('An error occurred when performing this query-->'.$changeColumnName);
3693 * This method attempts to delete all English inline help files.
3694 * This method was introduced by 5.5.0RC2.
3696 function clearHelpFiles(){
3697 $modulePath = clean_path(getcwd() . '/modules');
3698 $allHelpFiles = array();
3699 getFiles($allHelpFiles, $modulePath, "/en_us.help.*/");
3701 foreach( $allHelpFiles as $the_file ){
3702 if( is_file( $the_file ) ){
3703 unlink( $the_file );
3704 logThis("Deleted file: $the_file");
3712 * upgradeDateTimeFields
3714 * This method came from bug: 39757 where the date_end field is a date field and not a datetime field
3715 * which prevents you from performing timezone offset calculations once the data has been saved.
3717 * @param path String location to log file, empty by default
3719 function upgradeDateTimeFields($path)
3723 $meetingsSql = "UPDATE meetings SET date_end = ".$db->convert("date_start", 'add_time', array('duration_hours', 'duration_minutes'));
3724 $callsSql = "UPDATE calls SET date_end = ".$db->convert("date_start", 'add_time', array('duration_hours', 'duration_minutes'));
3725 logThis('upgradeDateTimeFields Meetings SQL:' . $meetingsSql, $path);
3726 $db->query($meetingsSql);
3728 logThis('upgradeDateTimeFields Calls SQL:' . $callsSql, $path);
3729 $db->query($callsSql);
3733 * upgradeDocumentTypeFields
3736 function upgradeDocumentTypeFields($path){
3740 $documentsSql = "UPDATE documents SET doc_type = 'Sugar' WHERE doc_type IS NULL";
3741 $meetingsSql = "UPDATE meetings SET type = 'Sugar' WHERE type IS NULL";
3743 logThis('upgradeDocumentTypeFields Documents SQL:' . $documentsSql, $path);
3744 $db->query($documentsSql);
3745 logThis('upgradeDocumentTypeFields Meetings SQL:' . $meetingsSql, $path);
3746 $db->query($meetingsSql);
3751 * merge_config_si_settings
3752 * This method checks for the presence of a config_si.php file and, if found, merges the configuration
3753 * settings from the config_si.php file into config.php. If a config_si_location parameter value is not
3754 * supplied it will attempt to discover the config_si.php file location from where the executing script
3757 * @param write_to_upgrade_log boolean optional value to write to the upgradeWizard.log file
3758 * @param config_location String optional value to config.php file location
3759 * @param config_si_location String optional value to config_si.php file location
3760 * @param path String file of the location of log file to write to
3761 * @return boolean value indicating whether or not a merge was attempted with config_si.php file
3763 function merge_config_si_settings($write_to_upgrade_log=false, $config_location='', $config_si_location='', $path='')
3765 if(!empty($config_location) && !file_exists($config_location))
3767 if($write_to_upgrade_log)
3769 logThis('config.php file specified in ' . $config_si_location . ' could not be found. Skip merging', $path);
3772 } else if(empty($config_location)) {
3774 //We are assuming this is from the silentUpgrade scripts so argv[3] will point to SugarCRM install location
3775 if(isset($argv[3]) && is_dir($argv[3]))
3777 $config_location = $argv[3] . DIRECTORY_SEPARATOR . 'config.php';
3781 //If config_location is still empty or if the file cannot be found, skip merging
3782 if(empty($config_location) || !file_exists($config_location))
3784 if($write_to_upgrade_log)
3786 logThis('config.php file at (' . $config_location . ') could not be found. Skip merging.', $path);
3790 if($write_to_upgrade_log)
3792 logThis('Loading config.php file at (' . $config_location . ') for merging.', $path);
3795 include($config_location);
3796 if(empty($sugar_config))
3798 if($write_to_upgrade_log)
3800 logThis('config.php contents are empty. Skip merging.', $path);
3806 if(!empty($config_si_location) && !file_exists($config_si_location))
3808 if($write_to_upgrade_log)
3810 logThis('config_si.php file specified in ' . $config_si_location . ' could not be found. Skip merging', $path);
3813 } else if(empty($config_si_location)) {
3814 if(isset($argv[0]) && is_file($argv[0]))
3816 $php_file = $argv[0];
3817 $p_info = pathinfo($php_file);
3818 $php_dir = (isset($p_info['dirname']) && $p_info['dirname'] != '.') ? $p_info['dirname'] . DIRECTORY_SEPARATOR : '';
3819 $config_si_location = $php_dir . 'config_si.php';
3823 //If config_si_location is still empty or if the file cannot be found, skip merging
3824 if(empty($config_si_location) || !file_exists($config_si_location))
3826 if($write_to_upgrade_log)
3828 logThis('config_si.php file at (' . $config_si_location . ') could not be found. Skip merging.', $path);
3832 if($write_to_upgrade_log)
3834 logThis('Loading config_si.php file at (' . $config_si_location . ') for merging.', $path);
3837 include($config_si_location);
3838 if(empty($sugar_config_si))
3840 if($write_to_upgrade_log)
3842 logThis('config_si.php contents are empty. Skip merging.', $path);
3848 //Now perform the merge operation
3850 foreach($sugar_config_si as $key=>$value)
3852 if(!preg_match('/^setup_/', $key) && !isset($sugar_config[$key]))
3854 if($write_to_upgrade_log)
3856 logThis('Merge key (' . $key . ') with value (' . $value . ')', $path);
3858 $sugar_config[$key] = $value;
3865 if($write_to_upgrade_log)
3867 logThis('Update config.php file with new values', $path);
3870 if(!write_array_to_file("sugar_config", $sugar_config, $config_location)) {
3871 if($write_to_upgrade_log)
3873 logThis('*** ERROR: could not write to config.php', $path);
3878 if($write_to_upgrade_log)
3880 logThis('config.php values are in sync with config_si.php values. Skipped merging.');
3885 if($write_to_upgrade_log)
3887 logThis('End merge_config_si_settings', $path);
3894 * upgrade_connectors
3896 * This function handles support for upgrading connectors it is invoked from both end.php and silentUpgrade_step2.php
3899 function upgrade_connectors() {
3900 require_once('include/connectors/utils/ConnectorUtils.php');
3901 if(!ConnectorUtils::updateMetaDataFiles()) {
3902 $GLOBALS['log']->fatal('Cannot update metadata files for connectors');
3905 //Delete the custom connectors.php file if it exists so that it may be properly rebuilt
3906 if(file_exists('custom/modules/Connectors/metadata/connectors.php'))
3908 unlink('custom/modules/Connectors/metadata/connectors.php');
3913 * Enable the InsideView connector for the four default modules.
3915 function upgradeEnableInsideViewConnector($path='')
3917 logThis('Begin upgradeEnableInsideViewConnector', $path);
3919 // Load up the existing mapping and hand it to the InsideView connector to have it setup the correct logic hooks
3920 $mapFile = 'modules/Connectors/connectors/sources/ext/rest/insideview/mapping.php';
3921 if ( file_exists('custom/'.$mapFile) ) {
3922 logThis('Found CUSTOM mappings', $path);
3923 require('custom/'.$mapFile);
3925 logThis('Used default mapping', $path);
3929 require_once('include/connectors/sources/SourceFactory.php');
3930 $source = SourceFactory::getSource('ext_rest_insideview');
3932 // $mapping is brought in from the mapping.php file above
3933 $source->saveMappingHook($mapping);
3935 require_once('include/connectors/utils/ConnectorUtils.php');
3936 ConnectorUtils::installSource('ext_rest_insideview');
3938 // Now time to set the various modules to active, because this part ignores the default config
3939 require(CONNECTOR_DISPLAY_CONFIG_FILE);
3940 // $modules_sources come from that config file
3941 foreach ( $source->allowedModuleList as $module ) {
3942 $modules_sources[$module]['ext_rest_insideview'] = 'ext_rest_insideview';
3944 if(!write_array_to_file('modules_sources', $modules_sources, CONNECTOR_DISPLAY_CONFIG_FILE)) {
3945 //Log error and return empty array
3946 logThis("Cannot write \$modules_sources to " . CONNECTOR_DISPLAY_CONFIG_FILE,$path);
3949 logThis('End upgradeEnableInsideViewConnector', $path);
3953 function repair_long_relationship_names($path='')
3955 logThis("Begin repair_long_relationship_names", $path);
3956 require_once 'modules/ModuleBuilder/parsers/relationships/DeployedRelationships.php' ;
3957 $GLOBALS['mi_remove_tables'] = false;
3959 foreach($GLOBALS['moduleList'] as $module)
3961 $relationships = new DeployedRelationships ($module) ;
3962 foreach($relationships->getRelationshipList() as $rel_name)
3964 if (strlen($rel_name) > 27 && empty($touched[$rel_name]))
3966 logThis("Rebuilding relationship fields for $rel_name", $path);
3967 $touched[$rel_name] = true;
3968 $rel_obj = $relationships->get($rel_name);
3969 $rel_obj->setReadonly(false);
3970 $relationships->delete($rel_name);
3971 $relationships->save();
3972 $relationships->add($rel_obj);
3973 $relationships->save();
3974 $relationships->build () ;
3978 logThis("End repair_long_relationship_names", $path);
3981 function removeSilentUpgradeVarsCache(){
3982 global $silent_upgrade_vars_loaded;
3984 $cacheFileDir = "{$GLOBALS['sugar_config']['cache_dir']}/silentUpgrader";
3985 $cacheFile = "{$cacheFileDir}/silentUpgradeCache.php";
3987 if(file_exists($cacheFile)){
3991 $silent_upgrade_vars_loaded = array(); // Set to empty to reset it
3996 function loadSilentUpgradeVars(){
3997 global $silent_upgrade_vars_loaded;
3999 if(empty($silent_upgrade_vars_loaded)){
4000 $cacheFile = "{$GLOBALS['sugar_config']['cache_dir']}/silentUpgrader/silentUpgradeCache.php";
4001 // We have no pre existing vars
4002 if(!file_exists($cacheFile)){
4003 // Set the vars array so it's loaded
4004 $silent_upgrade_vars_loaded = array('vars' => array());
4007 require_once($cacheFile);
4008 $silent_upgrade_vars_loaded = $silent_upgrade_vars_cache;
4015 function writeSilentUpgradeVars(){
4016 global $silent_upgrade_vars_loaded;
4018 if(empty($silent_upgrade_vars_loaded)){
4019 return false; // You should have set some values before trying to write the silent upgrade vars
4022 $cacheFileDir = "{$GLOBALS['sugar_config']['cache_dir']}/silentUpgrader";
4023 $cacheFile = "{$cacheFileDir}/silentUpgradeCache.php";
4025 require_once('include/dir_inc.php');
4026 if(!mkdir_recursive($cacheFileDir)){
4029 require_once('include/utils/file_utils.php');
4030 if(!write_array_to_file('silent_upgrade_vars_cache', $silent_upgrade_vars_loaded, $cacheFile, 'w')){
4032 logThis("WARNING: writeSilentUpgradeVars could not write to {$cacheFile}", $path);
4039 function setSilentUpgradeVar($var, $value){
4040 if(!loadSilentUpgradeVars()){
4044 global $silent_upgrade_vars_loaded;
4046 $silent_upgrade_vars_loaded['vars'][$var] = $value;
4051 function getSilentUpgradeVar($var){
4052 if(!loadSilentUpgradeVars()){
4056 global $silent_upgrade_vars_loaded;
4058 if(!isset($silent_upgrade_vars_loaded['vars'][$var])){
4062 return $silent_upgrade_vars_loaded['vars'][$var];
4068 * add_unified_search_to_custom_modules_vardefs
4070 * This method calls the repair code to remove the unified_search_modules.php fiel
4073 function add_unified_search_to_custom_modules_vardefs()
4075 if(file_exists($cachefile = sugar_cached('modules/unified_search_modules.php')))
4083 * change from using the older SugarCache in 6.1 and below to the new one in 6.2
4085 function upgradeSugarCache($file)
4087 global $sugar_config;
4088 $cacheUploadUpgradesTemp = mk_temp_dir(sugar_cached('upgrades/temp'));
4090 unzip($file, $cacheUploadUpgradesTemp);
4092 if(!file_exists(clean_path("{$cacheUploadUpgradesTemp}/manifest.php"))) {
4093 logThis("*** ERROR: no manifest file detected while bootstraping upgrade wizard files!");
4096 include(clean_path("{$cacheUploadUpgradesTemp}/manifest.php"));
4099 $from_dir = "{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}";
4100 $allFiles = array();
4101 if(file_exists("$from_dir/include/SugarCache")) {
4102 $allFiles = findAllFiles("$from_dir/include/SugarCache", $allFiles);
4104 if(file_exists("$from_dir/include/database")) {
4105 $allFiles = findAllFiles("$from_dir/include/database", $allFiles);
4107 if(file_exists("$from_dir/include/utils/external_cache.php")) {
4108 $allFiles[] = "$from_dir/include/utils/external_cache.php";
4110 if(file_exists("$from_dir/include/utils/sugar_file_utils.php")) {
4111 $allFiles[] = "$from_dir/include/utils/sugar_file_utils.php";
4113 if(file_exists("$from_dir/include/utils/sugar_file_utils.php")) {
4114 $allFiles[] = "$from_dir/include/utils/sugar_file_utils.php";
4117 foreach($allFiles as $k => $file) {
4118 $destFile = str_replace($from_dir."/", "", $file);
4119 if(!is_dir(dirname($destFile))) {
4120 mkdir_recursive(dirname($destFile)); // make sure the directory exists
4122 if ( stristr($file,'uw_main.tpl') )
4123 logThis('Skipping "'.$file.'" - file copy will during commit step.');
4125 logThis('updating UpgradeWizard code: '.$destFile);
4126 copy_recursive($file, $destFile);
4133 * upgradeDisplayedTabsAndSubpanels
4135 * @param $version String value of current system version (pre upgrade)
4137 function upgradeDisplayedTabsAndSubpanels($version)
4139 if($version < '620')
4141 logThis('start upgrading system displayed tabs and subpanels');
4142 require_once('modules/MySettings/TabController.php');
4143 $tc = new TabController();
4145 //grab the existing system tabs
4146 $tabs = $tc->get_tabs_system();
4148 //add Calls, Meetings, Tasks, Notes, Prospects (Targets) and ProspectLists (Target Lists)
4149 //to displayed tabs unless explicitly set to hidden
4150 $modules_to_add = array('Calls', 'Meetings', 'Tasks', 'Notes', 'Prospects', 'ProspectLists');
4151 $added_tabs = array();
4153 foreach($modules_to_add as $module)
4155 $tabs[0][$module] = $module;
4156 $added_tabs[] = $module;
4159 logThis('calling set_system_tabs on TabController to add tabs: ' . var_export($added_tabs, true));
4160 $tc->set_system_tabs($tabs[0]);
4161 logThis('finish upgrading system displayed tabs and subpanels');
4167 * unlinkUpgradeFiles
4168 * This is a helper function to clean up
4170 * @param $version String value of current system version (pre upgrade)
4172 function unlinkUpgradeFiles($version)
4174 if(!isset($version))
4179 //First check if we even have the scripts_for_patch/files_to_remove directory
4180 require_once('modules/UpgradeWizard/UpgradeRemoval.php');
4183 if(empty($_SESSION['unzip_dir']))
4185 global $sugar_config;
4186 $base_upgrade_dir = $sugar_config['upload_dir'] . "/upgrades";
4187 $base_tmp_upgrade_dir = "$base_upgrade_dir/temp";
4188 $_SESSION['unzip_dir'] = mk_temp_dir( $base_tmp_upgrade_dir );
4192 if(isset($_SESSION['unzip_dir']) && file_exists($_SESSION['unzip_dir'].'/scripts/files_to_remove'))
4194 $files_to_remove = glob($_SESSION['unzip_dir'].'/scripts/files_to_remove/*.php');
4196 foreach($files_to_remove as $script)
4198 if(preg_match('/UpgradeRemoval(\d+)x\.php/', $script, $matches))
4200 $checkVersion = $matches[1] + 1; //Increment by one to check everything equal or below the target version
4201 $upgradeClass = 'UpgradeRemoval' . $matches[1] . 'x';
4202 require_once($_SESSION['unzip_dir'].'/scripts/files_to_remove/' . $upgradeClass . '.php');
4204 //Check to make sure we should load and run this UpgradeRemoval instance
4205 if($checkVersion <= $version && class_exists($upgradeClass))
4207 $upgradeInstance = new $upgradeClass();
4208 if($upgradeInstance instanceof UpgradeRemoval)
4210 logThis('Running UpgradeRemoval instance ' . $upgradeClass);
4211 logThis('Files will be backed up to custom/backup');
4212 $files = $upgradeInstance->getFilesToRemove($version);
4213 foreach($files as $file)
4217 $upgradeInstance->processFilesToRemove($files);
4224 //Check if we have a custom directory
4225 if(file_exists('custom/scripts/files_to_remove'))
4228 $files_to_remove = glob('custom/scripts/files_to_remove/*.php');
4230 foreach($files_to_remove as $script)
4232 if(preg_match('/\/files_to_remove\/(.*?)\.php$/', $script, $matches))
4234 require_once($script);
4235 $upgradeClass = $matches[1];
4237 if(!class_exists($upgradeClass))
4242 $upgradeInstance = new $upgradeClass();
4243 if($upgradeInstance instanceof UpgradeRemoval)
4245 logThis('Running Custom UpgradeRemoval instance ' . $upgradeClass);
4246 $files = $upgradeInstance->getFilesToRemove($version);
4247 foreach($files as $file)
4251 $upgradeInstance->processFilesToRemove($files);
4259 if (!function_exists("getValidDBName"))
4262 * Return a version of $proposed that can be used as a column name in any of our supported databases
4263 * 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)
4264 * @param string $name Proposed name for the column
4265 * @param string $ensureUnique
4266 * @return string Valid column name trimmed to right length and with invalid characters removed
4268 function getValidDBName ($name, $ensureUnique = false, $maxLen = 30)
4270 // first strip any invalid characters - all but alphanumerics and -
4271 $name = preg_replace ( '/[^\w-]+/i', '', $name ) ;
4272 $len = strlen ( $name ) ;
4276 $md5str = md5($name);
4277 $tail = substr ( $name, -11) ;
4278 $temp = substr($md5str , strlen($md5str)-4 );
4279 $result = substr ( $name, 0, 10) . $temp . $tail ;
4280 }else if ($len > ($maxLen - 5))
4282 $result = substr ( $name, 0, 11) . substr ( $name, 11 - $maxLen + 5);
4284 return strtolower ( $result ) ;
4291 * Get UW directories
4292 * Provides compatibility with both 6.3 and pre-6.3 setup
4294 function getUWDirs()
4296 if(!class_exists('UploadStream')) {
4297 // we're still running the old code
4298 global $sugar_config;
4299 return array($sugar_config['upload_dir'] . "/upgrades", $sugar_config['cache_dir'] . "upload/upgrades/temp");
4301 if(!in_array("upload", stream_get_wrappers())) {
4302 UploadStream::register(); // just in case file was copied, but not run
4304 return array("upload://upgrades", sugar_cached("upgrades/temp"));
4309 * Whether directory exists within list of directories to skip
4310 * @param string $dir dir to be checked
4311 * @param array $skipDirs list with skipped dirs
4314 function whetherNeedToSkipDir($dir, $skipDirs)
4316 foreach($skipDirs as $skipMe) {
4317 if(strpos( clean_path($dir), $skipMe ) !== false) {
4327 * @param silentUpgrade boolean flag indicating whether or not we should treat running the SugarSpriteBuilder as an upgrade operation
4330 function rebuildSprites($fromUpgrade=true)
4332 require_once('modules/Administration/SugarSpriteBuilder.php');
4333 $sb = new SugarSpriteBuilder();
4334 $sb->cssMinify = true;
4335 $sb->fromSilentUpgrade = $fromUpgrade;
4336 $sb->silentRun = $fromUpgrade;
4338 // add common image directories
4339 $sb->addDirectory('default', 'include/images');
4340 $sb->addDirectory('default', 'themes/default/images');
4341 $sb->addDirectory('default', 'themes/default/images/SugarLogic');
4343 // add all theme image directories
4344 if($dh = opendir('themes'))
4346 while (($dir = readdir($dh)) !== false)
4348 if ($dir != "." && $dir != ".." && $dir != 'default' && is_dir('themes/'.$dir)) {
4349 $sb->addDirectory($dir, "themes/{$dir}/images");
4355 // generate the sprite goodies
4356 // everything is saved into cache/sprites
4357 $sb->createSprites();
4362 * repairSearchFields
4364 * This method goes through the list of SearchFields files based and calls TemplateRange::repairCustomSearchFields
4365 * method on the files in an attempt to ensure the range search attributes are properly set in SearchFields.php.
4367 * @param $globString String value used for glob search defaults to searching for all SearchFields.php files in modules directory
4368 * @param $path String value used to point to log file should logging be required. Defaults to empty.
4371 function repairSearchFields($globString='modules/*/metadata/SearchFields.php', $path='')
4375 logThis('Begin repairSearchFields', $path);
4378 require_once('include/dir_inc.php');
4379 require_once('modules/DynamicFields/templates/Fields/TemplateRange.php');
4380 require('include/modules.php');
4383 $searchFieldsFiles = glob($globString);
4385 foreach($searchFieldsFiles as $file)
4387 if(preg_match('/modules\/(.*?)\/metadata\/SearchFields\.php/', $file, $matches) && isset($beanList[$matches[1]]))
4389 $module = $matches[1];
4390 $beanName = $beanList[$module];
4391 VardefManager::loadVardef($module, $beanName);
4392 if(isset($GLOBALS['dictionary'][$beanName]['fields']))
4396 logThis('Calling TemplateRange::repairCustomSearchFields for module ' . $module, $path);
4398 TemplateRange::repairCustomSearchFields($GLOBALS['dictionary'][$beanName]['fields'], $module);
4405 logThis('End repairSearchFields', $path);
4410 * repairUpgradeHistoryTable
4412 * This is a helper function used in the upgrade process to fix upgrade_history entries so that the filename column points
4413 * to the new upload directory location introduced in 6.4 versions
4415 function repairUpgradeHistoryTable()
4417 require_once('modules/Configurator/Configurator.php');
4419 global $sugar_config;
4421 //Now upgrade the upgrade_history table entries
4422 $results = $GLOBALS['db']->query('SELECT id, filename FROM upgrade_history');
4423 $upload_dir = $sugar_config['cache_dir'].'upload/';
4425 //Create regular expression string to
4426 $match = '/^' . str_replace('/', '\/', $upload_dir) . '(.*?)$/';
4428 while(($row = $GLOBALS['db']->fetchByAssoc($results)))
4430 $file = str_replace('//', '/', $row['filename']); //Strip out double-paths that may exist
4432 if(!empty($file) && preg_match($match, $file, $matches))
4434 //Update new file location to use the new $sugar_config['upload_dir'] value
4435 $new_file_location = $sugar_config['upload_dir'] . $matches[1];
4436 $GLOBALS['db']->query("UPDATE upgrade_history SET filename = '{$new_file_location}' WHERE id = '{$row['id']}'");