2 if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
3 /*********************************************************************************
4 * SugarCRM Community Edition is a customer relationship management program developed by
5 * SugarCRM, Inc. Copyright (C) 2004-2011 SugarCRM Inc.
7 * This program is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU Affero General Public License version 3 as published by the
9 * Free Software Foundation with the addition of the following permission added
10 * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
11 * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
12 * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
19 * You should have received a copy of the GNU Affero General Public License along with
20 * this program; if not, see http://www.gnu.org/licenses or write to the Free
21 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24 * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
25 * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
27 * The interactive user interfaces in modified source and object code versions
28 * of this program must display Appropriate Legal Notices, as required under
29 * Section 5 of the GNU Affero General Public License version 3.
31 * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
32 * these Appropriate Legal Notices must retain the display of the "Powered by
33 * SugarCRM" logo. If the display of the logo is not reasonably feasible for
34 * technical reasons, the Appropriate Legal Notices must display the words
35 * "Powered by SugarCRM".
36 ********************************************************************************/
42 * Helper function for upgrade - get path from upload:// name
46 function getUploadRelativeName($path)
48 if(class_exists('UploadFile')) {
49 return UploadFile::realpath($path);
51 if(substr($path, 0, 9) == "upload://") {
52 $path = rtrim($GLOBALS['sugar_config']['upload_dir'], "/\\")."/".substr($path, 9);
58 * Backs-up files that are targeted for patch/upgrade to a restore directory
59 * @param string rest_dir Full path to the directory containing the original, replaced files.
60 * @param string install_file Full path to the uploaded patch/upgrade zip file
61 * @param string unzip_dir Full path to the unzipped files in a temporary directory
62 * @param string zip_from_dir Name of directory that the unzipped files containing the actuall replacement files
63 * @param array errors Collection of errors to be displayed at end of process
64 * @param string path Optional full path to the log file.
65 * @return array errors
67 function commitMakeBackupFiles($rest_dir, $install_file, $unzip_dir, $zip_from_dir, $errors, $path='') {
69 // create restore file directory
70 sugar_mkdir($rest_dir, 0775, true);
72 if(file_exists($rest_dir) && is_dir($rest_dir)){
73 logThis('backing up files to be overwritten...', $path);
74 $newFiles = findAllFiles(clean_path($unzip_dir . '/' . $zip_from_dir), array());
76 // keep this around for canceling
77 $_SESSION['uw_restore_dir'] = getUploadRelativeName($rest_dir);
79 foreach ($newFiles as $file) {
80 if (strpos($file, 'md5'))
83 // get name of current file to place in restore directory
84 $cleanFile = str_replace(clean_path($unzip_dir . '/' . $zip_from_dir), '', $file);
86 // make sure the directory exists
87 $cleanDir = $rest_dir . '/' . dirname($cleanFile);
88 sugar_mkdir($cleanDir, 0775, true);
89 $oldFile = clean_path(getcwd() . '/' . $cleanFile);
91 // only copy restore files for replacements - ignore new files from patch
92 if (is_file($oldFile)) {
93 if (is_writable($rest_dir)) {
94 logThis('Backing up file: ' . $oldFile, $path);
95 if (!copy($oldFile, $rest_dir . '/' . $cleanFile)) {
96 logThis('*** ERROR: could not backup file: ' . $oldFile, $path);
97 $errors[] = "{$mod_strings['LBL_UW_BACKUP']}::{$mod_strings['ERR_UW_FILE_NOT_COPIED']}: {$oldFile}";
99 $backupFilesExist = true;
103 logThis('*** ERROR: directory not writable: ' . $rest_dir, $path);
104 $errors[] = "{$mod_strings['LBL_UW_BACKUP']}::{$mod_strings['ERR_UW_DIR_NOT_WRITABLE']}: {$oldFile}";
109 logThis('file backup done.', $path);
114 * Copies files from the unzipped patch to the destination.
115 * @param string unzip_dir Full path to the temporary directory created during unzip operation.
116 * @param string zip_from_dir Name of folder containing the unzipped files; usually the name of the Patch without the
118 * @param string path Optional full path to alternate upgradeWizard log file.
119 * @return array Two element array containing to $copiedFiles and $skippedFiles.
124 function commitCopyNewFiles($unzip_dir, $zip_from_dir, $path='') {
125 logThis('Starting file copy process...', $path);
126 global $sugar_version;
128 if(substr($sugar_version,0,1) >= 5){
129 $modules = getAllModules();
130 $backwardModules = array();
131 foreach($modules as $mod){
132 if(is_dir(clean_path(getcwd().'/modules/'.$mod.'/.500'))){
134 $files= findAllFiles(clean_path(getcwd().'/modules/'.$mod.'/.500'),$files);
135 if(sizeof($files) >0){
136 //backward compatibility is on
137 $backwardModules[] = $mod;
143 $newFiles = findAllFiles(clean_path($unzip_dir . '/' . $zip_from_dir), array());
144 $zipPath = clean_path($unzip_dir . '/' . $zip_from_dir);
146 // handle special do-not-overwrite conditions
147 $doNotOverwrite = array();
148 $doNotOverwrite[] = '__stub';
149 if(isset($_REQUEST['overwrite_files_serial'])) {
150 $doNotOverwrite = explode('::', $_REQUEST['overwrite_files_serial']);
153 $copiedFiles = array();
154 $skippedFiles = array();
156 foreach($newFiles as $file) {
157 $cleanFile = str_replace($zipPath, '', $file);
158 $srcFile = $zipPath . $cleanFile;
159 $targetFile = clean_path(getcwd() . '/' . $cleanFile);
160 if($backwardModules != null && sizeof($backwardModules) >0){
161 foreach($backwardModules as $mod){
162 $splitPath = explode('/',trim($cleanFile));
163 if('modules' == trim($splitPath[1]) && $mod == trim($splitPath[2])){
164 $cleanFile = str_replace('/modules/'.$mod, '/modules/'.$mod.'/.500', $cleanFile);
165 $targetFile = clean_path(getcwd() . '/' . $cleanFile);
169 if(!is_dir(dirname($targetFile))) {
170 mkdir_recursive(dirname($targetFile)); // make sure the directory exists
173 if((!file_exists($targetFile)) || /* brand new file */
174 (!in_array($targetFile, $doNotOverwrite)) /* manual diff file */
176 // handle sugar_version.php
177 if(strpos($targetFile, 'sugar_version.php') !== false && !preg_match('/\/portal\/sugar_version\.php$/i', $targetFile)) {
178 logThis('Skipping "sugar_version.php" - file copy will occur at end of successful upgrade', $path);
179 $_SESSION['sugar_version_file'] = $srcFile;
183 //logThis('Copying file to destination: ' . $targetFile, $path);
185 if(!copy($srcFile, $targetFile)) {
186 logThis('*** ERROR: could not copy file: ' . $targetFile, $path);
188 $copiedFiles[] = $targetFile;
191 //logThis('Skipping file: ' . $targetFile, $path);
192 $skippedFiles[] = $targetFile;
195 logThis('File copy done.', $path);
198 $ret['copiedFiles'] = $copiedFiles;
199 $ret['skippedFiles'] = $skippedFiles;
205 //On cancel put back the copied files from 500 to 451 state
206 function copyFilesOnCancel($step){
207 //place hoder for cancel action
212 function removeFileFromPath($file,$path, $deleteNot=array()){
214 $cur = $path . '/' . $file;
215 if(file_exists($cur)){
217 foreach($deleteNot as $dn){
227 if(!file_exists($path))return $removed;
229 while($e = $d->read()){
230 $next = $path . '/'. $e;
231 if(substr($e, 0, 1) != '.' && is_dir($next)){
232 $removed += removeFileFromPath($file, $next, $deleteNot);
239 * This function copies/overwrites between directories
241 * @param string the directory name to remove
242 * @param boolean whether to just empty the given directory, without deleting the given directory.
243 * @return boolean True/False whether the directory was deleted.
246 function copyRecursiveBetweenDirectories($from,$to){
247 if(file_exists($from)){
248 $modifiedFiles = array();
249 $modifiedFiles = findAllFiles(clean_path($from), $modifiedFiles);
250 $cwd = clean_path(getcwd());
251 foreach($modifiedFiles as $file) {
252 $srcFile = clean_path($file);
253 if (strpos($srcFile,".svn") === false) {
254 $targetFile = str_replace($from, $to, $srcFile);
256 if(!is_dir(dirname($targetFile))) {
257 mkdir_recursive(dirname($targetFile)); // make sure the directory exists
260 // handle sugar_version.php
261 if(strpos($targetFile, 'sugar_version.php') !== false && !preg_match('/\/portal\/sugar_version\.php$/i', $targetFile)) {
262 logThis('Skipping "sugar_version.php" - file copy will occur at end of successful upgrade', $targetFile);
263 $_SESSION['sugar_version_file'] = $srcFile;
267 if(!copy($srcFile, $targetFile)) {
268 logThis("*** ERROR: could not copy file $srcFile to $targetFile");
275 function deleteDirectory($dirname,$only_empty=false) {
276 if (!is_dir($dirname))
278 $dscan = array(realpath($dirname));
280 while (!empty($dscan)) {
281 $dcur = array_pop($dscan);
283 if ($d=opendir($dcur)) {
284 while ($f=readdir($d)) {
285 if ($f=='.' || $f=='..')
296 $i_until = ($only_empty)? 1 : 0;
297 for ($i=count($darr)-1; $i>=$i_until; $i--) {
298 if (rmdir($darr[$i]))
299 logThis('Success :Copying file to destination: ' . $darr[$i]);
301 logThis('Copy problem:Copying file to destination: ' . $darr[$i]);
303 return (($only_empty)? (count(scandir)<=2) : (!is_dir($dirname)));
306 * Get all the customized modules. Compare the file md5s with the base md5s
307 * If a file has been modified then put the module in the list of customized
308 * modules. Show the list in the preflight check UI.
311 function deleteAndOverWriteSelectedFiles($unzip_dir, $zip_from_dir,$delete_dirs){
312 if($delete_dirs != null){
313 foreach($delete_dirs as $del_dir){
314 deleteDirectory($del_dir);
315 $newFiles = findAllFiles(clean_path($unzip_dir . '/' . $zip_from_dir.'/'.$del_dir), array());
316 $zipPath = clean_path($unzip_dir . '/' . $zip_from_dir.'/'.$del_dir);
317 $copiedFiles = array();
318 $skippedFiles = array();
320 foreach($newFiles as $file) {
321 $cleanFile = str_replace($zipPath, '', $file);
322 $srcFile = $zipPath . $cleanFile;
323 $targetFile = clean_path(getcwd() . '/' . $cleanFile);
325 if(!is_dir(dirname($targetFile))) {
326 mkdir_recursive(dirname($targetFile)); // make sure the directory exists
329 if(!file_exists($targetFile)){
330 // handle sugar_version.php
331 if(strpos($targetFile, 'sugar_version.php') !== false) {
332 logThis('Skipping sugar_version.php - file copy will occur at end of successful upgrade');
333 $_SESSION['sugar_version_file'] = $srcFile;
337 //logThis('Copying file to destination: ' . $targetFile);
339 if(!copy($srcFile, $targetFile)) {
340 logThis('*** ERROR: could not copy file: ' . $targetFile);
342 $copiedFiles[] = $targetFile;
345 //logThis('Skipping file: ' . $targetFile);
346 $skippedFiles[] = $targetFile;
352 $ret['copiedFiles'] = $copiedFiles;
353 $ret['skippedFiles'] = $skippedFiles;
358 //Default is empty the directory. For removing set it to false
359 // to use this function to totally remove a directory, write:
360 // recursive_remove_directory('path/to/directory/to/delete',FALSE);
362 // to use this function to empty a directory, write:
363 // recursive_remove_directory('path/to/full_directory');
365 function recursive_empty_or_remove_directory($directory, $exclude_dirs=null,$exclude_files=null,$empty=TRUE)
367 // if the path has a slash at the end we remove it here
368 if(substr($directory,-1) == '/')
370 $directory = substr($directory,0,-1);
373 // if the path is not valid or is not a directory ...
374 if(!file_exists($directory) || !is_dir($directory))
376 // ... we return false and exit the function
379 // ... if the path is not readable
380 }elseif(!is_readable($directory))
382 // ... we return false and exit the function
385 // ... else if the path is readable
388 // we open the directory
389 $handle = opendir($directory);
391 // and scan through the items inside
392 while (FALSE !== ($item = readdir($handle)))
394 // if the filepointer is not the current directory
395 // or the parent directory
396 if($item != '.' && $item != '..')
398 // we build the new path to delete
399 $path = $directory.'/'.$item;
401 // if the new path is a directory
402 //add another check if the dir is in the list to exclude delete
403 if(is_dir($path) && $exclude_dirs != null && in_array($path,$exclude_dirs)){
406 else if(is_dir($path))
408 // we call this function with the new path
409 recursive_empty_or_remove_directory($path);
411 // if the new path is a file
413 // we remove the file
414 if($exclude_files != null && in_array($path,$exclude_files)){
423 // close the directory
426 // if the option to empty is not set to true
429 // try to delete the now empty directory
430 if(!rmdir($directory))
432 // return false if not possible
440 // ------------------------------------------------------------
445 function getAllCustomizedModules() {
447 require_once('files.md5');
449 $return_array = array();
450 $modules = getAllModules();
451 foreach($modules as $mod) {
452 //find all files in each module if the files have been modified
453 //as compared to the base version then add the module to the
454 //customized modules array
455 $modFiles = findAllFiles(clean_path(getcwd())."/modules/$mod", array());
456 foreach($modFiles as $file){
457 $fileContents = file_get_contents($file);
458 $file = str_replace(clean_path(getcwd()),'',$file);
459 if($md5_string['./' . $file]){
460 if(md5($fileContents) != $md5_string['./' . $file]) {
461 //A file has been customized in the module. Put the module into the
462 // customized modules array.
463 echo 'Changed File'.$file;
469 // This is a new file in user's version and indicates that module has been
470 //customized. Put the module in the customized array.
471 echo 'New File'.$file;
478 return $return_array;
482 * Array of all Modules in the version bein upgraded
483 * This method returns an Array of all modules
484 * @return $modules Array of modules.
486 function getAllModules() {
489 while($e = $d->read()){
490 if(substr($e, 0, 1) == '.' || !is_dir('modules/' . $e))continue;
496 //Remove files with the smae md5
498 function removeMd5MatchingFiles($deleteNot=array()){
500 $md5_string = array();
501 if(file_exists(clean_path(getcwd().'/files.md5'))){
502 require(clean_path(getcwd().'/files.md5'));
504 $modulesAll = getAllModules();
505 foreach($modulesAll as $mod){
506 $allModFiles = array();
507 if(is_dir('modules/'.$mod)){
508 $allModFiles = findAllFiles('modules/'.$mod,$allModFiles);
509 foreach($allModFiles as $file){
510 if(file_exists($file) && !in_array(basename($file),$deleteNot)){
511 if(isset($md5_string['./'.$file])) {
512 $fileContents = file_get_contents($file);
513 if(md5($fileContents) == $md5_string['./'.$file]) {
524 * Handles requirements for creating reminder Tasks and Emails
525 * @param array skippedFiles Array of files that were not overwriten and must be manually mereged.
526 * @param string path Optional full path to alternate upgradeWizard log.
528 function commitHandleReminders($skippedFiles, $path='') {
530 global $current_user;
532 if(empty($mod_strings))
533 $mod_strings = return_module_language('en_us', 'UpgradeWizard');
535 if(empty($current_user->id)) {
536 $current_user->getSystemUser();
539 if(count($skippedFiles) > 0) {
540 $desc = $mod_strings['LBL_UW_COMMIT_ADD_TASK_OVERVIEW'] . "\n\n";
541 $desc .= $mod_strings['LBL_UW_COMMIT_ADD_TASK_DESC_1'];
542 $desc .= $_SESSION['uw_restore_dir'] . "\n\n";
543 $desc .= $mod_strings['LBL_UW_COMMIT_ADD_TASK_DESC_2'] . "\n\n";
545 foreach($skippedFiles as $file) {
546 $desc .= $file . "\n";
550 /// Not using new TimeDate stuff here because it needs to be compatible with 6.0
551 $nowDate = gmdate('Y-m-d');
552 $nowTime = gmdate('H:i:s');
553 $nowDateTime = $nowDate . ' ' . $nowTime;
555 if($_REQUEST['addTaskReminder'] == 'remind') {
556 logThis('Adding Task for admin for manual merge.', $path);
559 $task->name = $mod_strings['LBL_UW_COMMIT_ADD_TASK_NAME'];
560 $task->description = $desc;
561 $task->date_due = $nowDate;
562 $task->time_due = $nowTime;
563 $task->priority = 'High';
564 $task->status = 'Not Started';
565 $task->assigned_user_id = $current_user->id;
566 $task->created_by = $current_user->id;
567 $task->date_entered = $nowDateTime;
568 $task->date_modified = $nowDateTime;
572 if($_REQUEST['addEmailReminder'] == 'remind') {
573 logThis('Sending Reminder for admin for manual merge.', $path);
575 $email = new Email();
576 $email->assigned_user_id = $current_user->id;
577 $email->name = $mod_strings['LBL_UW_COMMIT_ADD_TASK_NAME'];
578 $email->description = $desc;
579 $email->description_html = nl2br($desc);
580 $email->from_name = $current_user->full_name;
581 $email->from_addr = $current_user->email1;
582 $email->to_addrs_arr = $email->parse_addrs($current_user->email1, '', '', '');
583 $email->cc_addrs_arr = array();
584 $email->bcc_addrs_arr = array();
585 $email->date_entered = $nowDateTime;
586 $email->date_modified = $nowDateTime;
593 function deleteCache(){
594 //Clean modules from cache
595 $cachedir = sugar_cached('modules');
596 if(is_dir($cachedir)){
597 $allModFiles = array();
598 $allModFiles = findAllFiles($cachedir,$allModFiles, true);
599 foreach($allModFiles as $file) {
600 if(file_exists($file)) {
602 rmdir_recursive($file);
611 //Clean jsLanguage from cache
612 $cachedir = sugar_cached('jsLanguage');
613 if(is_dir($cachedir)){
614 $allModFiles = array();
615 $allModFiles = findAllFiles($cachedir,$allModFiles);
616 foreach($allModFiles as $file){
617 if(file_exists($file)){
622 //Clean smarty from cache
623 $cachedir = sugar_cached('smarty');
624 if(is_dir($cachedir)){
625 $allModFiles = array();
626 $allModFiles = findAllFiles($cachedir,$allModFiles);
627 foreach($allModFiles as $file){
628 if(file_exists($file)){
633 //Rebuild dashlets cache
634 require_once('include/Dashlets/DashletCacheBuilder.php');
635 $dc = new DashletCacheBuilder();
639 function deleteChance(){
640 //Clean folder from cache
641 if(is_dir('include/SugarObjects/templates/chance')){
642 rmdir_recursive('include/SugarObjects/templates/chance');
644 if(is_dir('include/SugarObjects/templates/chance')){
645 if(!isset($_SESSION['chance'])){
646 $_SESSION['chance'] = '';
648 $_SESSION['chance'] = 'include/SugarObjects/templates/chance';
649 //rename('include/SugarObjects/templates/chance','include/SugarObjects/templates/chance_removeit');
657 * This function copies upgrade wizard files from new patch if that dir exists
659 * @param $file String path to uploaded zip file
661 function upgradeUWFiles($file) {
662 $cacheUploadUpgradesTemp = mk_temp_dir(sugar_cached("upgrades/temp"));
664 unzip($file, $cacheUploadUpgradesTemp);
666 if(!file_exists("$cacheUploadUpgradesTemp/manifest.php")) {
667 logThis("*** ERROR: no manifest file detected while bootstraping upgrade wizard files!");
670 include("$cacheUploadUpgradesTemp/manifest.php");
674 $from_dir = "{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}";
677 if(file_exists("$from_dir/include/Localization/Localization.php")) {
678 $allFiles[] = "$from_dir/include/Localization/Localization.php";
681 if(file_exists("$from_dir/modules/UpgradeWizard")) {
682 $allFiles[] = findAllFiles("$from_dir/modules/UpgradeWizard", $allFiles);
685 if(file_exists("$from_dir/ModuleInstall")) {
686 $allFiles[] = findAllFiles("$from_dir/ModuleInstall", $allFiles);
688 if(file_exists("$from_dir/include/javascript/yui")) {
689 $allFiles[] = findAllFiles("$from_dir/include/javascript/yui", $allFiles);
691 if(file_exists("$from_dir/HandleAjaxCall.php")) {
692 $allFiles[] = "$from_dir/HandleAjaxCall.php";
694 if(file_exists("$from_dir/include/SugarTheme")) {
695 $allFiles[] = findAllFiles("$from_dir/include/SugarTheme", $allFiles);
697 if(file_exists("$from_dir/include/SugarCache")) {
698 $allFiles[] = findAllFiles("$from_dir/include/SugarCache", $allFiles);
700 if(file_exists("$from_dir/include/utils/external_cache.php")) {
701 $allFiles[] = "$from_dir/include/utils/external_cache.php";
703 if(file_exists("$from_dir/include/upload_file.php")) {
704 $allFiles[] = "$from_dir/include/upload_file.php";
706 if(file_exists("$from_dir/include/file_utils.php")) {
707 $allFiles[] = "$from_dir/include/file_utils.php";
709 if(file_exists("$from_dir/include/upload_file.php")) {
710 $allFiles[] = "$from_dir/include/upload_file.php";
712 if(file_exists("$from_dir/include/utils/sugar_file_utils.php")) {
713 $allFiles[] = "$from_dir/include/utils/sugar_file_utils.php";
716 if(file_exists("$from_dir/modules/Users")) {
717 $allFiles[] = findAllFiles("$from_dir/modules/Users", $allFiles);
720 upgradeUWFilesCopy($allFiles, $from_dir);
726 * This function recursively copies files from the upgradeUWFiles Array
727 * @see upgradeUWFiles
729 * @param array $allFiles Array of files to copy over after zip file has been uploaded
730 * @param string $from_dir Source directory
732 function upgradeUWFilesCopy($allFiles, $from_dir)
734 foreach($allFiles as $file)
738 upgradeUWFilesCopy($file, $from_dir);
740 $destFile = str_replace($from_dir."/", "", $file);
741 if(!is_dir(dirname($destFile))) {
742 mkdir_recursive(dirname($destFile)); // make sure the directory exists
745 if(stristr($file,'uw_main.tpl'))
746 logThis('Skipping "'.$file.'" - file copy will during commit step.');
748 logThis('updating UpgradeWizard code: '.$destFile);
749 copy_recursive($file, $destFile);
758 * gets valid patch file names that exist in upload/upgrade/patch/
760 function getValidPatchName($returnFull = true) {
761 global $base_upgrade_dir;
764 global $sugar_version;
765 global $sugar_config;
766 $uh = new UpgradeHistory();
767 list($base_upgrade_dir, $base_tmp_upgrade_dir) = getUWDirs();
770 // scan for new files (that are not installed)
771 logThis('finding new files for upgrade');
772 $upgrade_content = '';
773 $upgrade_contents = findAllFiles($base_upgrade_dir, array(), false, 'zip');
774 //other variations of zip file i.e. ZIP, zIp,zIP,Zip,ZIp,ZiP
781 <b>{$mod_strings['LBL_ML_NAME']}</b>
784 <b>{$mod_strings['LBL_ML_TYPE']}</b>
787 <b>{$mod_strings['LBL_ML_VERSION']}</b>
790 <b>{$mod_strings['LBL_ML_PUBLISHED']}</b>
793 <b>{$mod_strings['LBL_ML_UNINSTALLABLE']}</b>
796 <b>{$mod_strings['LBL_ML_DESCRIPTION']}</b>
801 // assume old patches are there.
802 $upgradeToVersion = array(); // fill with valid patches - we will only use the latest qualified found patch
804 // cn: bug 10609 - notices for uninitialized variables
809 $published_date = '';
814 foreach($upgrade_contents as $upgrade_content) {
815 if(!preg_match("#.*\.zip\$#i", $upgrade_content)) {
819 $the_base = basename($upgrade_content);
820 $the_md5 = md5_file($upgrade_content);
822 $md5_matches = $uh->findByMd5($the_md5);
824 /* If a patch is in the /patch dir AND has no record in the upgrade_history table we assume that it's the one we want.
825 * Edge-case: manual upgrade with a FTP of a patch; UH table has no entry for it. Assume nothing. :( */
826 if(0 == sizeof($md5_matches)) {
827 $target_manifest = remove_file_extension( $upgrade_content ) . '-manifest.php';
828 require_once($target_manifest);
830 if(empty($manifest['version'])) {
831 logThis("*** Potential error: patch found with no version [ {$upgrade_content} ]");
834 if(!isset($manifest['type']) || $manifest['type'] != 'patch') {
835 logThis("*** Potential error: patch found with either no 'type' or non-patch type [ {$upgrade_content} ]");
839 $upgradeToVersion[$manifest['version']] = urlencode($upgrade_content);
841 $name = empty($manifest['name']) ? $upgrade_content : $manifest['name'];
842 $version = empty($manifest['version']) ? '' : $manifest['version'];
843 $published_date = empty($manifest['published_date']) ? '' : $manifest['published_date'];
845 $description = empty($manifest['description']) ? 'None' : $manifest['description'];
846 $uninstallable = empty($manifest['is_uninstallable']) ? 'No' : 'Yes';
847 $type = getUITextForType( $manifest['type'] );
848 $manifest_type = $manifest['type'];
850 if(empty($manifest['icon'])) {
851 $icon = getImageForType( $manifest['type'] );
853 $path_parts = pathinfo( $manifest['icon'] );
854 $icon = "<!--not_in_theme!--><img src=\"" . remove_file_extension( $upgrade_content ) . "-icon." . $path_parts['extension'] . "\">";
859 // cn: bug 10488 use the NEWEST upgrade/patch available when running upgrade wizard.
860 ksort($upgradeToVersion);
861 $upgradeToVersion = array_values($upgradeToVersion);
862 $newest = array_pop($upgradeToVersion);
863 $_SESSION['install_file'] = urldecode($newest); // in-case it was there from a prior.
864 logThis("*** UW using [ {$_SESSION['install_file']} ] as source for patch files.");
866 $cleanUpgradeContent = urlencode($_SESSION['install_file']);
868 // cn: 10606 - cannot upload a patch file since this returned always.
869 if(!empty($cleanUpgradeContent)) {
870 $ready .= "<tr><td>$icon</td><td>$name</td><td>$type</td><td>$version</td><td>$published_date</td><td>$uninstallable</td><td>$description</td>\n";
873 <form action="index.php" method="post">
874 <input type="hidden" name="module" value="UpgradeWizard">
875 <input type="hidden" name="action" value="index">
876 <input type="hidden" name="step" value="{$_REQUEST['step']}">
877 <input type="hidden" name="run" value="delete">
878 <input type=hidden name="install_file" value="{$cleanUpgradeContent}" />
879 <input type=submit value="{$mod_strings['LBL_BUTTON_DELETE']}" />
883 $disabled = "DISABLED";
888 if(empty($cleanUpgradeContent)){
889 $ready .= "<tr><td colspan='7'><i>None</i></td>\n";
890 $ready .= "</table>\n";
892 $ready .= "<br></ul>\n";
894 $return['ready'] = $ready;
895 $return['disabled'] = $disabled;
904 * finalizes upgrade by setting upgrade versions in DB (config table) and sugar_version.php
905 * @return bool true on success
907 function updateVersions($version) {
909 global $sugar_config;
912 logThis('At updateVersions()... updating config table and sugar_version.php.', $path);
915 if(isset($_SESSION['sugar_version_file']) && !empty($_SESSION['sugar_version_file'])) {
916 if(!copy($_SESSION['sugar_version_file'], clean_path(getcwd().'/sugar_version.php'))) {
917 logThis('*** ERROR: sugar_version.php could not be copied to destination! Cannot complete upgrade', $path);
920 logThis('sugar_version.php successfully updated!', $path);
923 logThis('*** ERROR: no sugar_version.php file location found! - cannot complete upgrade...', $path);
927 $q1 = "DELETE FROM config WHERE category = 'info' AND name = 'sugar_version'";
928 $q2 = "INSERT INTO config (category, name, value) VALUES ('info', 'sugar_version', '{$version}')";
930 logThis('Deleting old DB version info from config table.', $path);
933 logThis('Inserting updated version info into config table.', $path);
936 logThis('updateVersions() complete.', $path);
943 * gets a module's lang pack - does not need to be a SugarModule
944 * @param lang string Language
945 * @param module string Path to language folder
946 * @return array mod_strings
948 function getModuleLanguagePack($lang, $module) {
949 $mod_strings = array();
951 if(!empty($lang) && !empty($module)) {
952 $langPack = clean_path(getcwd().'/'.$module.'/language/'.$lang.'.lang.php');
953 $langPackEn = clean_path(getcwd().'/'.$module.'/language/en_us.lang.php');
955 if(file_exists($langPack))
956 include_once($langPack);
957 elseif(file_exists($langPackEn))
958 include_once($langPackEn);
964 * checks system compliance for 4.5+ codebase
965 * @return array Mixed values
967 function checkSystemCompliance() {
968 global $sugar_config;
969 global $current_language;
973 if(!defined('SUGARCRM_MIN_MEM')) {
974 define('SUGARCRM_MIN_MEM', 40);
977 $installer_mod_strings = getModuleLanguagePack($current_language, './install');
979 $ret['error_found'] = false;
982 $php_version = constant('PHP_VERSION');
983 $check_php_version_result = check_php_version($php_version);
985 switch($check_php_version_result) {
987 $ret['phpVersion'] = "<b><span class=stop>{$installer_mod_strings['ERR_CHECKSYS_PHP_INVALID_VER']} {$php_version} )</span></b>";
988 $ret['error_found'] = true;
991 $ret['phpVersion'] = "<b><span class=go>{$installer_mod_strings['ERR_CHECKSYS_PHP_UNSUPPORTED']} {$php_version} )</span></b>";
994 $ret['phpVersion'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_PHP_OK']} {$php_version} )</span></b>";
998 // database and connect
1000 if($db->dbType == 'mysql')
1002 if(version_compare($v, '4.1.2') < 0) {
1003 $ret['error_found'] = true;
1004 $ret['mysqlVersion'] = "<b><span class=stop>".$mod_strings['ERR_UW_MYSQL_VERSION'].$v."</span></b>";
1006 } elseif($db->dbType == 'oci8') {
1007 if(!preg_match("/Oracle9i|Oracle Database 10g|11/i", $v)) {
1008 $ret['error_found'] = true;
1009 $ret['ociVersion'] = "<b><span class=stop>".$mod_strings['ERR_UW_OCI8_VERSION'].$v."</span></b>";
1015 if(function_exists('xml_parser_create')) {
1016 $ret['xmlStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1018 $ret['xmlStatus'] = "<b><span class=stop>{$installer_mod_strings['LBL_CHECKSYS_NOT_AVAILABLE']}</span></b>";
1019 $ret['error_found'] = true;
1023 if(function_exists('curl_init')) {
1024 $ret['curlStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1026 $ret['curlStatus'] = "<b><span class=go>{$installer_mod_strings['ERR_CHECKSYS_CURL']}</span></b>";
1027 $ret['error_found'] = false;
1031 if(function_exists('mb_strlen')) {
1032 $ret['mbstringStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1034 $ret['mbstringStatus'] = "<b><span class=stop>{$installer_mod_strings['ERR_CHECKSYS_MBSTRING']}</span></b>";
1035 $ret['error_found'] = true;
1039 if(function_exists('imap_open')) {
1040 $ret['imapStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1042 $ret['imapStatus'] = "<b><span class=go>{$installer_mod_strings['ERR_CHECKSYS_IMAP']}</span></b>";
1043 $ret['error_found'] = false;
1048 if('1' == ini_get('safe_mode')) {
1049 $ret['safeModeStatus'] = "<b><span class=stop>{$installer_mod_strings['ERR_CHECKSYS_SAFE_MODE']}</span></b>";
1050 $ret['error_found'] = true;
1052 $ret['safeModeStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1056 // call time pass by ref
1057 if('1' == ini_get('allow_call_time_pass_reference')) {
1058 $ret['callTimeStatus'] = "<b><span class=stop>{$installer_mod_strings['ERR_CHECKSYS_CALL_TIME']}</span></b>";
1059 //continue upgrading
1061 $ret['callTimeStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1065 $ret['memory_msg'] = "";
1066 $memory_limit = "-1";//ini_get('memory_limit');
1067 $sugarMinMem = constant('SUGARCRM_MIN_MEM');
1068 // logic based on: http://us2.php.net/manual/en/ini.core.php#ini.memory-limit
1069 if( $memory_limit == "" ){ // memory_limit disabled at compile time, no memory limit
1070 $ret['memory_msg'] = "<b><span class=\"go\">{$installer_mod_strings['LBL_CHECKSYS_MEM_OK']}</span></b>";
1071 } elseif( $memory_limit == "-1" ){ // memory_limit enabled, but set to unlimited
1072 $ret['memory_msg'] = "<b><span class=\"go\">{$installer_mod_strings['LBL_CHECKSYS_MEM_UNLIMITED']}</span></b>";
1074 rtrim($memory_limit, 'M');
1075 $memory_limit_int = (int) $memory_limit;
1076 if( $memory_limit_int < constant('SUGARCRM_MIN_MEM') ){
1077 $ret['memory_msg'] = "<b><span class=\"stop\">{$installer_mod_strings['ERR_CHECKSYS_MEM_LIMIT_1']}" . constant('SUGARCRM_MIN_MEM') . "{$installer_mod_strings['ERR_CHECKSYS_MEM_LIMIT_2']}</span></b>";
1078 $ret['error_found'] = true;
1080 $ret['memory_msg'] = "<b><span class=\"go\">{$installer_mod_strings['LBL_CHECKSYS_OK']} ({$memory_limit})</span></b>";
1084 /* mbstring.func_overload
1085 $ret['mbstring.func_overload'] = '';
1086 $mb = ini_get('mbstring.func_overload');
1089 $ret['mbstring.func_overload'] = "<b><span class=\"stop\">{$mod_strings['ERR_UW_MBSTRING_FUNC_OVERLOAD']}</b>";
1090 $ret['error_found'] = true;
1098 * is a file that we blow away automagically
1100 function isAutoOverwriteFile($file) {
1101 $overwriteDirs = array(
1102 './sugar_version.php',
1103 './modules/UpgradeWizard/uw_main.tpl',
1105 $file = trim('.'.str_replace(clean_path(getcwd()), '', $file));
1107 if(in_array($file, $overwriteDirs)) {
1111 $fileExtension = substr(strrchr($file, "."), 1);
1112 if($fileExtension == 'tpl' || $fileExtension == 'html') {
1122 function logThis($entry, $path='') {
1123 global $mod_strings;
1124 if(file_exists('include/utils/sugar_file_utils.php')){
1125 require_once('include/utils/sugar_file_utils.php');
1127 $log = empty($path) ? clean_path(getcwd().'/upgradeWizard.log') : clean_path($path);
1129 // create if not exists
1130 if(!file_exists($log)) {
1131 if(function_exists('sugar_fopen')){
1132 $fp = @sugar_fopen($log, 'w+'); // attempts to create file
1135 $fp = fopen($log, 'w+'); // attempts to create file
1137 if(!is_resource($fp)) {
1138 $GLOBALS['log']->fatal('UpgradeWizard could not create the upgradeWizard.log file');
1139 die($mod_strings['ERR_UW_LOG_FILE_UNWRITABLE']);
1142 if(function_exists('sugar_fopen')){
1143 $fp = @sugar_fopen($log, 'a+'); // write pointer at end of file
1146 $fp = @fopen($log, 'a+'); // write pointer at end of file
1149 if(!is_resource($fp)) {
1150 $GLOBALS['log']->fatal('UpgradeWizard could not open/lock upgradeWizard.log file');
1151 die($mod_strings['ERR_UW_LOG_FILE_UNWRITABLE']);
1155 $line = date('r').' [UpgradeWizard] - '.$entry."\n";
1157 if(@fwrite($fp, $line) === false) {
1158 $GLOBALS['log']->fatal('UpgradeWizard could not write to upgradeWizard.log: '.$entry);
1159 die($mod_strings['ERR_UW_LOG_FILE_UNWRITABLE']);
1162 if(is_resource($fp)) {
1170 * @desc This function is to be used in the upgrade process to preserve changes/customaizations made to pre 5.1 quickcreate layout.
1171 * Prior to 5.1 we have been using editviewdefs as the base for quickcreatedefs. If a custom field was added to edit view layout, it
1172 * was automatically picked up by the quick create. [Addresses Bug 21469]
1173 * This function will check if customizations were made, and will create quickcreatedefs.php in the /cutom/working/$module_name directory.
1175 function updateQuickCreateDefs(){
1176 $d = dir('modules');
1177 $studio_modules = array();
1179 while($e = $d->read()){ //collect all studio modules.
1180 if(substr($e, 0, 1) == '.' || !is_dir('modules/' . $e))continue;
1181 if(file_exists('modules/' . $e . '/metadata/studio.php'))
1183 array_push($studio_modules, $e);
1187 foreach( $studio_modules as $modname ){ //for each studio enabled module
1188 //Check !exists modules/$modname/metadata/quickcreatedefs.php &&
1189 //exists custom/$modname/editviewdefs.php (module was customized) &&
1190 //!exists custom/$modname/quickcreateviewdefs.php
1192 $editviewdefs = "custom/working/modules/".$modname."/metadata/editviewdefs.php";
1193 $quickcreatedefs = "custom/working/modules/".$modname."/metadata/quickcreatedefs.php";
1195 if ( !file_exists("modules/".$modname."/metadata/quickcreatedefs.php") &&
1196 file_exists($editviewdefs) &&
1197 !file_exists($quickcreatedefs) ){
1198 //clone editviewdef and save it in custom/working/modules/metadata
1199 $GLOBALS['log']->debug("Copying editviewdefs.php as quickcreatedefs.php for the $modname module in custom/working/modules/$modname/metadata!");
1200 if(copy( $editviewdefs, $quickcreatedefs)){
1201 if(file_exists($quickcreatedefs) && is_readable($quickcreatedefs)){
1202 $file = file($quickcreatedefs);
1203 //replace 'EditView' with 'QuickCreate'
1204 $fp = fopen($quickcreatedefs,'w');
1205 foreach($file as &$line){
1206 if(preg_match('/^\s*\'EditView\'\s*=>\s*$/', $line) > 0){
1207 $line = "'QuickCreate' =>\n";
1215 $GLOBALS['log']->debug("Failed to replace 'EditView' with QuickCreate because $quickcreatedefs is either not readable or does not exist.");
1218 $GLOBALS['log']->debug("Failed to copy $editviewdefs to $quickcreatedefs!");
1225 * test perms for CREATE queries
1227 function testPermsCreate($db, $out) {
1228 logThis('Checking CREATE TABLE permissions...');
1229 global $mod_strings;
1231 if(!$db->checkPrivilege("CREATE TABLE")) {
1232 logThis('cannot CREATE TABLE!');
1233 $out['db']['dbNoCreate'] = true;
1234 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_CREATE']}</span></td></tr>";
1240 * test perms for INSERT
1242 function testPermsInsert($db, $out, $skip=false) {
1243 logThis('Checking INSERT INTO permissions...');
1244 global $mod_strings;
1246 if(!$db->checkPrivilege("INSERT")) {
1247 logThis('cannot INSERT INTO!');
1248 $out['db']['dbNoInsert'] = true;
1249 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_INSERT']}</span></td></tr>";
1256 * test perms for UPDATE TABLE
1258 function testPermsUpdate($db, $out, $skip=false) {
1259 logThis('Checking UPDATE TABLE permissions...');
1260 global $mod_strings;
1261 if(!$db->checkPrivilege("UPDATE")) {
1262 logThis('cannot UPDATE TABLE!');
1263 $out['db']['dbNoUpdate'] = true;
1264 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_UPDATE']}</span></td></tr>";
1271 * test perms for SELECT
1273 function testPermsSelect($db, $out, $skip=false) {
1274 logThis('Checking SELECT permissions...');
1275 global $mod_strings;
1276 if(!$db->checkPrivilege("SELECT")) {
1277 logThis('cannot SELECT!');
1278 $out['db']['dbNoSelect'] = true;
1279 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_SELECT']}</span></td></tr>";
1285 * test perms for DELETE
1287 function testPermsDelete($db, $out, $skip=false) {
1288 logThis('Checking DELETE FROM permissions...');
1289 global $mod_strings;
1290 if(!$db->checkPrivilege("DELETE")) {
1291 logThis('cannot DELETE FROM!');
1292 $out['db']['dbNoDelete'] = true;
1293 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_DELETE']}</span></td></tr>";
1300 * test perms for ALTER TABLE ADD COLUMN
1302 function testPermsAlterTableAdd($db, $out, $skip=false) {
1303 logThis('Checking ALTER TABLE ADD COLUMN permissions...');
1304 global $mod_strings;
1305 if(!$db->checkPrivilege("ADD COLUMN")) {
1306 logThis('cannot ADD COLUMN!');
1307 $out['db']['dbNoAddColumn'] = true;
1308 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_ADD_COLUMN']}</span></td></tr>";
1314 * test perms for ALTER TABLE ADD COLUMN
1316 function testPermsAlterTableChange($db, $out, $skip=false) {
1317 logThis('Checking ALTER TABLE CHANGE COLUMN permissions...');
1318 global $mod_strings;
1319 if(!$db->checkPrivilege("CHANGE COLUMN")) {
1320 logThis('cannot CHANGE COLUMN!');
1321 $out['db']['dbNoChangeColumn'] = true;
1322 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_CHANGE_COLUMN']}</span></td></tr>";
1328 * test perms for ALTER TABLE DROP COLUMN
1330 function testPermsAlterTableDrop($db, $out, $skip=false) {
1331 logThis('Checking ALTER TABLE DROP COLUMN permissions...');
1332 global $mod_strings;
1333 if(!$db->checkPrivilege("DROP COLUMN")) {
1334 logThis('cannot DROP COLUMN!');
1335 $out['db']['dbNoDropColumn'] = true;
1336 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_DROP_COLUMN']}</span></td></tr>";
1343 * test perms for DROP TABLE
1345 function testPermsDropTable($db, $out, $skip=false) {
1346 logThis('Checking DROP TABLE permissions...');
1347 global $mod_strings;
1348 if(!$db->checkPrivilege("DROP TABLE")) {
1349 logThis('cannot DROP TABLE!');
1350 $out['db']['dbNoDropTable'] = true;
1351 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_DROP_TABLE']}</span></td></tr>";
1356 function getFormattedError($error, $query) {
1357 $error = "<div><b>".$error;
1358 $error .= "</b>::{$query}</div>";
1364 * parses a query finding the table name
1365 * @param string query The query
1366 * @return string table The table
1368 function getTableFromQuery($query) {
1369 $standardQueries = array('ALTER TABLE', 'DROP TABLE', 'CREATE TABLE', 'INSERT INTO', 'UPDATE', 'DELETE FROM');
1370 $query = preg_replace("/[^A-Za-z0-9\_\s]/", "", $query);
1371 $query = trim(str_replace($standardQueries, '', $query));
1373 $firstSpc = strpos($query, " ");
1374 $end = ($firstSpc > 0) ? $firstSpc : strlen($query);
1375 $table = substr($query, 0, $end);
1382 function preLicenseCheck() {
1383 require_once('modules/UpgradeWizard/uw_files.php');
1385 global $sugar_config;
1386 global $mod_strings;
1387 global $sugar_version;
1389 if(!isset($sugar_version) || empty($sugar_version)) {
1390 require_once('./sugar_version.php');
1393 if(!isset($_SESSION['unzip_dir']) || empty($_SESSION['unzip_dir'])) {
1394 logThis('unzipping files in upgrade archive...');
1396 list($base_upgrade_dir, $base_tmp_upgrade_dir) = getUWDirs();
1398 //also come up with mechanism to read from upgrade-progress file
1399 if(!isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !is_file($_SESSION['install_file'])) {
1400 if (file_exists(clean_path($base_tmp_upgrade_dir)) && $handle = opendir(clean_path($base_tmp_upgrade_dir))) {
1401 while (false !== ($file = readdir($handle))) {
1402 if($file !="." && $file !="..") {
1403 if(is_file($base_tmp_upgrade_dir."/".$file."/manifest.php")){
1404 require_once($base_tmp_upgrade_dir."/".$file."/manifest.php");
1405 $package_name= $manifest['copy_files']['from_dir'];
1406 if(file_exists($base_tmp_upgrade_dir."/".$file."/".$package_name) && file_exists($base_tmp_upgrade_dir."/".$file."/scripts") && file_exists($base_tmp_upgrade_dir."/".$file."/manifest.php")){
1407 $unzip_dir = $base_tmp_upgrade_dir."/".$file;
1408 if(file_exists("$base_upgrade_dir/patch/".$package_name.'.zip')){
1409 $_SESSION['install_file'] = $package_name.".zip";
1418 if(empty($_SESSION['install_file'])){
1419 unlinkUWTempFiles();
1421 echo 'Upload File not found so redirecting to Upgrade Start ';
1422 $redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
1423 echo '<form name="redirect" action="' .$redirect_new_wizard. '" method="POST">';
1424 $upgrade_directories_not_found =<<<eoq
1425 <table cellpadding="3" cellspacing="0" border="0">
1427 <th colspan="2" align="left">
1428 <span class='error'><b>'Upload file missing or has been deleted. Refresh the page to go back to UpgradeWizard start'</b></span>
1433 $uwMain = $upgrade_directories_not_found;
1436 $install_file = "$base_upgrade_dir/patch/".basename(urldecode( $_SESSION['install_file'] ));
1438 if(empty($unzip_dir)){
1439 $unzip_dir = mk_temp_dir( $base_tmp_upgrade_dir );
1441 $zip_from_dir = ".";
1443 $zip_force_copy = array();
1446 logThis('Could not create a temporary directory using mk_temp_dir( $base_tmp_upgrade_dir )');
1447 die($mod_strings['ERR_UW_NO_CREATE_TMP_DIR']);
1450 //double check whether unzipped .
1451 if(file_exists($unzip_dir ."/scripts") && file_exists($unzip_dir."/manifest.php")){
1455 unzip( $install_file, $unzip_dir );
1458 // assumption -- already validated manifest.php at time of upload
1459 require_once( "$unzip_dir/manifest.php" );
1461 if( isset( $manifest['copy_files']['from_dir'] ) && $manifest['copy_files']['from_dir'] != "" ){
1462 $zip_from_dir = $manifest['copy_files']['from_dir'];
1464 if( isset( $manifest['copy_files']['to_dir'] ) && $manifest['copy_files']['to_dir'] != "" ){
1465 $zip_to_dir = $manifest['copy_files']['to_dir'];
1467 if( isset( $manifest['copy_files']['force_copy'] ) && $manifest['copy_files']['force_copy'] != "" ){
1468 $zip_force_copy = $manifest['copy_files']['force_copy'];
1470 if( isset( $manifest['version'] ) ){
1471 $version = $manifest['version'];
1473 if( !is_writable( "config.php" ) ){
1474 return $mod_strings['ERR_UW_CONFIG'];
1477 $_SESSION['unzip_dir'] = clean_path($unzip_dir);
1478 $_SESSION['zip_from_dir'] = clean_path($zip_from_dir);
1479 logThis('unzip done.');
1481 $unzip_dir = $_SESSION['unzip_dir'];
1482 $zip_from_dir = $_SESSION['zip_from_dir'];
1485 //check if $_SESSION['unzip_dir'] and $_SESSION['zip_from_dir'] exist
1486 if(!isset($_SESSION['unzip_dir']) || !file_exists($_SESSION['unzip_dir'])
1487 || !isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !file_exists($_SESSION['install_file'])){
1489 unlinkUWTempFiles();
1491 echo 'Upload File not found so redirecting to Upgrade Start ';
1492 $redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
1493 echo '<form name="redirect" action="' .$redirect_new_wizard. '" method="POST">';
1494 $upgrade_directories_not_found =<<<eoq
1495 <table cellpadding="3" cellspacing="0" border="0">
1497 <th colspan="2" align="left">
1498 <span class='error'><b>'Upload file missing or has been deleted. Refresh the page to go back to UpgradeWizard start'</b></span>
1503 $uwMain = $upgrade_directories_not_found;
1507 logThis ('is SugarConfig there '.file_exists(clean_path($unzip_dir.'/'.$zip_from_dir."/include/SugarObjects/SugarConfig.php")));
1508 if(file_exists(clean_path($unzip_dir.'/'.$zip_from_dir."/include/SugarObjects/SugarConfig.php"))) {
1509 $file = clean_path($unzip_dir.'/'.$zip_from_dir."/include/SugarObjects/SugarConfig.php");
1510 $destFile = str_replace(clean_path($unzip_dir.'/'.$zip_from_dir), $cwd, $file);
1511 if(!is_dir(dirname($destFile))) {
1512 mkdir_recursive(dirname($destFile)); // make sure the directory exists
1514 copy($file,$destFile);
1515 //also copy include utils array utils
1516 $file = clean_path($unzip_dir.'/'.$zip_from_dir."/include/utils/array_utils.php");
1517 $destFile = str_replace(clean_path($unzip_dir.'/'.$zip_from_dir), $cwd, $file);
1518 if(!is_dir(dirname($destFile))) {
1519 mkdir_recursive(dirname($destFile)); // make sure the directory exists
1521 copy($file,$destFile);
1526 function preflightCheck() {
1527 require_once('modules/UpgradeWizard/uw_files.php');
1529 global $sugar_config;
1530 global $mod_strings;
1531 global $sugar_version;
1533 if(!isset($sugar_version) || empty($sugar_version)) {
1534 require_once('./sugar_version.php');
1537 unset($_SESSION['rebuild_relationships']);
1538 unset($_SESSION['rebuild_extensions']);
1540 // don't bother if are rechecking
1541 $manualDiff = array();
1542 if(!isset($_SESSION['unzip_dir']) || empty($_SESSION['unzip_dir'])) {
1543 logThis('unzipping files in upgrade archive...');
1545 list($base_upgrade_dir, $base_tmp_upgrade_dir) = getUWDirs();
1547 //Following is if User logged out unexpectedly and then logged into UpgradeWizard again.
1548 //also come up with mechanism to read from upgrade-progress file.
1549 if(!isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !is_file($_SESSION['install_file'])) {
1550 if (file_exists($base_tmp_upgrade_dir) && $handle = opendir($base_tmp_upgrade_dir)) {
1551 while (false !== ($file = readdir($handle))) {
1552 if($file !="." && $file !="..") {
1553 if(is_file($base_tmp_upgrade_dir."/".$file."/manifest.php")){
1554 require_once($base_tmp_upgrade_dir."/".$file."/manifest.php");
1555 $package_name= $manifest['copy_files']['from_dir'];
1556 if(file_exists($base_tmp_upgrade_dir."/".$file."/".$package_name) && file_exists($base_tmp_upgrade_dir."/".$file."/scripts") && file_exists($base_tmp_upgrade_dir."/".$file."/manifest.php")){
1557 $unzip_dir = $base_tmp_upgrade_dir."/".$file;
1558 if(file_exists("$base_upgrade_dir/patch/".$package_name.'.zip')){
1559 $_SESSION['install_file'] = $package_name.".zip";
1568 if(empty($_SESSION['install_file'])){
1569 unlinkUWTempFiles();
1571 echo 'Upload File not found so redirecting to Upgrade Start ';
1572 $redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
1573 echo '<form name="redirect" action="' .$redirect_new_wizard. '" method="POST">';
1574 $upgrade_directories_not_found =<<<eoq
1575 <table cellpadding="3" cellspacing="0" border="0">
1577 <th colspan="2" align="left">
1578 <span class='error'><b>'Upload file missing or has been deleted. Refresh the page to go back to UpgradeWizard start'</b></span>
1583 $uwMain = $upgrade_directories_not_found;
1587 $install_file = "$base_upgrade_dir/patch/".basename(urldecode( $_SESSION['install_file'] ));
1589 if(empty($unzip_dir)){
1590 $unzip_dir = mk_temp_dir( $base_tmp_upgrade_dir );
1592 $zip_from_dir = ".";
1594 $zip_force_copy = array();
1597 logThis('Could not create a temporary directory using mk_temp_dir( $base_tmp_upgrade_dir )');
1598 die($mod_strings['ERR_UW_NO_CREATE_TMP_DIR']);
1601 //double check whether unzipped .
1602 if(file_exists($unzip_dir ."/scripts") && file_exists($unzip_dir."/manifest.php")){
1606 unzip( $install_file, $unzip_dir );
1609 // assumption -- already validated manifest.php at time of upload
1610 require_once( "$unzip_dir/manifest.php" );
1612 if( isset( $manifest['copy_files']['from_dir'] ) && $manifest['copy_files']['from_dir'] != "" ){
1613 $zip_from_dir = $manifest['copy_files']['from_dir'];
1615 if( isset( $manifest['copy_files']['to_dir'] ) && $manifest['copy_files']['to_dir'] != "" ){
1616 $zip_to_dir = $manifest['copy_files']['to_dir'];
1618 if( isset( $manifest['copy_files']['force_copy'] ) && $manifest['copy_files']['force_copy'] != "" ){
1619 $zip_force_copy = $manifest['copy_files']['force_copy'];
1621 if( isset( $manifest['version'] ) ){
1622 $version = $manifest['version'];
1624 if( !is_writable( "config.php" ) ){
1625 return $mod_strings['ERR_UW_CONFIG'];
1628 $_SESSION['unzip_dir'] = clean_path($unzip_dir);
1629 $_SESSION['zip_from_dir'] = clean_path($zip_from_dir);
1631 //logThis('unzip done.');
1633 $unzip_dir = $_SESSION['unzip_dir'];
1634 $zip_from_dir = $_SESSION['zip_from_dir'];
1636 //check if $_SESSION['unzip_dir'] and $_SESSION['zip_from_dir'] exist
1637 if(!isset($_SESSION['unzip_dir']) || !file_exists($_SESSION['unzip_dir'])
1638 || !isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !file_exists($_SESSION['install_file'])){
1640 unlinkUWTempFiles();
1642 echo 'Upload File not found so redirecting to Upgrade Start ';
1643 $redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
1644 echo '<form name="redirect" action="' .$redirect_new_wizard. '" method="POST">';
1645 $upgrade_directories_not_found =<<<eoq
1646 <table cellpadding="3" cellspacing="0" border="0">
1648 <th colspan="2" align="left">
1649 <span class='error'><b>'Upload file missing or has been deleted. Refresh the page to go back to UpgradeWizard start'</b></span>
1654 $uwMain = $upgrade_directories_not_found;
1657 //copy minimum required files
1658 fileCopy('include/utils/sugar_file_utils.php');
1660 $upgradeFiles = findAllFiles(clean_path("$unzip_dir/$zip_from_dir"), array());
1661 $cache_html_files= array();
1664 $md5_string = array();
1665 if(file_exists(clean_path(getcwd().'/files.md5'))){
1666 require(clean_path(getcwd().'/files.md5'));
1669 // file preflight checks
1670 logThis('verifying md5 checksums for files...');
1671 foreach($upgradeFiles as $file) {
1672 if(in_array(str_replace(clean_path("$unzip_dir/$zip_from_dir") . "/", '', $file), $uw_files))
1673 continue; // skip already loaded files
1675 if(strpos($file, '.md5'))
1676 continue; // skip md5 file
1678 // normalize file paths
1679 $file = clean_path($file);
1681 // check that we can move/delete the upgraded file
1682 if(!is_writable($file)) {
1683 $errors[] = $mod_strings['ERR_UW_FILE_NOT_WRITABLE'].": ".$file;
1685 // check that destination files are writable
1686 $destFile = getcwd().str_replace(clean_path($unzip_dir.'/'.$zip_from_dir), '', $file);
1688 if(is_file($destFile)) { // of course it needs to exist first...
1689 if(!is_writable($destFile)) {
1690 $errors[] = $mod_strings['ERR_UW_FILE_NOT_WRITABLE'].": ".$destFile;
1694 ///////////////////////////////////////////////////////////////////////
1696 // compare md5s and build up a manual merge list
1697 $targetFile = clean_path(".".str_replace(getcwd(),'',$destFile));
1699 if(is_file($destFile)) {
1700 if(strpos($targetFile, '.php')) {
1701 // handle PHP files that were hit with the security regex
1703 if(function_exists('sugar_fopen')){
1704 $fp = sugar_fopen($destFile, 'r');
1707 $fp = fopen($destFile, 'r');
1709 $filesize = filesize($destFile);
1711 $fileContents = stream_get_contents($fp);
1712 $targetMd5 = md5($fileContents);
1715 $targetMd5 = md5_file($destFile);
1719 if(isset($md5_string[$targetFile]) && $md5_string[$targetFile] != $targetMd5) {
1720 logThis('found a file with a differing md5: ['.$targetFile.']');
1721 $manualDiff[] = $destFile;
1724 ///////////////////////////////////////////////////////////////////////
1726 logThis('md5 verification done.');
1727 $errors['manual'] = $manualDiff;
1732 function fileCopy($file_path){
1733 if(file_exists(clean_path($_SESSION['unzip_dir'].'/'.$_SESSION['zip_from_dir'].'/'.$file_path))) {
1734 $file = clean_path($_SESSION['unzip_dir'].'/'.$_SESSION['zip_from_dir'].'/'.$file_path);
1735 $destFile = str_replace(clean_path($_SESSION['unzip_dir'].'/'.$_SESSION['zip_from_dir']), clean_path(getcwd()), $file);
1736 if(!is_dir(dirname($destFile))) {
1737 mkdir_recursive(dirname($destFile)); // make sure the directory exists
1739 copy_recursive($file,$destFile);
1742 function getChecklist($steps, $step) {
1743 global $mod_strings;
1745 $skip = array('start', 'cancel', 'uninstall','end');
1748 $ret = '<table cellpadding="3" cellspacing="4" border="0">';
1749 $ret .= '<tr><th colspan="3" align="left">'.$mod_strings['LBL_UW_CHECKLIST'].':</th></tr>';
1750 foreach($steps['desc'] as $k => $desc) {
1751 if(in_array($steps['files'][$j], $skip)) {
1756 //$status = "<span class='error'>{$mod_strings['LBL_UW_INCOMPLETE']}</span>";
1758 $desc_mod_post = '';
1760 if(isset($_SESSION['step'][$steps['files'][$k]]) && $_SESSION['step'][$steps['files'][$k]] == 'success') {
1761 //$status = $mod_strings['LBL_UW_COMPLETE'];
1765 if($k == $_REQUEST['step']) {
1766 //$status = $mod_strings['LBL_UW_IN_PROGRESS'];
1767 $desc_mod_pre = "<font color=blue><i>";
1768 $desc_mod_post = "</i></font>";
1771 $ret .= "<tr><td> </td><td><b>{$i}: {$desc_mod_pre}{$desc}{$desc_mod_post}</b></td>";
1772 $ret .= "<td id={$steps['files'][$j]}><i></i></td></tr>";
1780 function prepSystemForUpgrade() {
1781 global $sugar_config;
1782 global $sugar_flavor;
1783 global $mod_strings;
1785 global $base_upgrade_dir;
1786 global $base_tmp_upgrade_dir;
1787 list($p_base_upgrade_dir, $p_base_tmp_upgrade_dir) = getUWDirs();
1788 ///////////////////////////////////////////////////////////////////////////////
1789 //// Make sure variables exist
1790 if(empty($base_upgrade_dir)){
1791 $base_upgrade_dir = $p_base_upgrade_dir;
1793 if(empty($base_tmp_upgrade_dir)){
1794 $base_tmp_upgrade_dir = $p_base_tmp_upgrade_dir;
1796 sugar_mkdir($base_tmp_upgrade_dir, 0775, true);
1797 if(!isset($subdirs) || empty($subdirs)){
1798 $subdirs = array('full', 'langpack', 'module', 'patch', 'theme');
1801 $upgrade_progress_dir = $base_tmp_upgrade_dir;
1802 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
1803 if(file_exists($upgrade_progress_file)){
1804 if(function_exists('get_upgrade_progress') && function_exists('didThisStepRunBefore')){
1805 if(didThisStepRunBefore('end')){
1806 include($upgrade_progress_file);
1807 unset($upgrade_config);
1808 unlink($upgrade_progress_file);
1813 // increase the cuttoff time to 1 hour
1814 ini_set("max_execution_time", "3600");
1816 // make sure dirs exist
1817 if($subdirs != null){
1818 foreach($subdirs as $subdir) {
1819 sugar_mkdir("$base_upgrade_dir/$subdir", 0775, true);
1822 // array of special scripts that are executed during (un)installation-- key is type of script, value is filename
1823 if(!defined('SUGARCRM_PRE_INSTALL_FILE')) {
1824 define('SUGARCRM_PRE_INSTALL_FILE', 'scripts/pre_install.php');
1825 define('SUGARCRM_POST_INSTALL_FILE', 'scripts/post_install.php');
1826 define('SUGARCRM_PRE_UNINSTALL_FILE', 'scripts/pre_uninstall.php');
1827 define('SUGARCRM_POST_UNINSTALL_FILE', 'scripts/post_uninstall.php');
1830 $script_files = array(
1831 "pre-install" => constant('SUGARCRM_PRE_INSTALL_FILE'),
1832 "post-install" => constant('SUGARCRM_POST_INSTALL_FILE'),
1833 "pre-uninstall" => constant('SUGARCRM_PRE_UNINSTALL_FILE'),
1834 "post-uninstall" => constant('SUGARCRM_POST_UNINSTALL_FILE'),
1837 // check that the upload limit is set to 6M or greater
1838 define('SUGARCRM_MIN_UPLOAD_MAX_FILESIZE_BYTES', 6 * 1024 * 1024); // 6 Megabytes
1839 $upload_max_filesize = ini_get('upload_max_filesize');
1840 $upload_max_filesize_bytes = return_bytes($upload_max_filesize);
1842 if($upload_max_filesize_bytes < constant('SUGARCRM_MIN_UPLOAD_MAX_FILESIZE_BYTES')) {
1843 $GLOBALS['log']->debug("detected upload_max_filesize: $upload_max_filesize");
1845 echo '<p class="error">'.$mod_strings['MSG_INCREASE_UPLOAD_MAX_FILESIZE'].' '.get_cfg_var('cfg_file_path')."</p>\n";
1849 if ( !function_exists('extractFile') ) {
1850 function extractFile($zip_file, $file_in_zip) {
1851 global $base_tmp_upgrade_dir;
1854 $absolute_base_tmp_upgrade_dir = clean_path($base_tmp_upgrade_dir);
1855 $relative_base_tmp_upgrade_dir = clean_path(str_replace(clean_path(getcwd()), '', $absolute_base_tmp_upgrade_dir));
1857 // mk_temp_dir expects relative pathing
1858 $my_zip_dir = mk_temp_dir($relative_base_tmp_upgrade_dir);
1860 unzip_file($zip_file, $file_in_zip, $my_zip_dir);
1862 return("$my_zip_dir/$file_in_zip");
1866 if ( !function_exists('extractManifest') ) {
1867 function extractManifest($zip_file) {
1868 logThis('extracting manifest.');
1869 return(extractFile($zip_file, "manifest.php"));
1873 if ( !function_exists('getInstallType') ) {
1874 function getInstallType($type_string) {
1877 $subdirs = array('full', 'langpack', 'module', 'patch', 'theme', 'temp');
1878 foreach($subdirs as $subdir) {
1879 if(preg_match("#/$subdir/#", $type_string)) {
1883 // return empty if no match
1888 function getImageForType($type) {
1890 global $mod_strings;
1895 $icon = SugarThemeRegistry::current()->getImage("Upgrade", "",null,null,'.gif',$mod_strings['LBL_UPGRADE']);
1898 $icon = SugarThemeRegistry::current()->getImage("LanguagePacks", "",null,null,'.gif',$mod_strings['LBL_LANGPACKS']);
1901 $icon = SugarThemeRegistry::current()->getImage("ModuleLoader", "",null,null,'.gif',$mod_strings['LBL_MODULELOADER']);
1904 $icon = SugarThemeRegistry::current()->getImage("PatchUpgrades", "",null,null,'.gif',$mod_strings['LBL_PATCHUPGRADES']);
1907 $icon = SugarThemeRegistry::current()->getImage("Themes", "",null,null,'.gif',$mod_strings['LBL_THEMES']);
1915 if ( !function_exists('getLanguagePackName') ) {
1916 function getLanguagePackName($the_file) {
1917 require_once("$the_file");
1918 if(isset($app_list_strings["language_pack_name"])) {
1919 return($app_list_strings["language_pack_name"]);
1925 function getUITextForType($type) {
1926 if($type == "full") {
1927 return("Full Upgrade");
1929 if($type == "langpack") {
1930 return("Language Pack");
1932 if($type == "module") {
1935 if($type == "patch") {
1938 if($type == "theme") {
1943 if ( !function_exists('validate_manifest') ) {
1945 * Verifies a manifest from a patch or module to be compatible with the current Sugar version and flavor
1946 * @param array manifest Standard manifest array
1947 * @return string Error message, blank on success
1949 function validate_manifest($manifest) {
1950 logThis('validating manifest.php file');
1951 // takes a manifest.php manifest array and validates contents
1953 global $sugar_version;
1954 global $sugar_flavor;
1955 global $mod_strings;
1957 if(!isset($manifest['type'])) {
1958 return $mod_strings['ERROR_MANIFEST_TYPE'];
1961 $type = $manifest['type'];
1963 if(getInstallType("/$type/") == "") {
1964 return $mod_strings['ERROR_PACKAGE_TYPE']. ": '" . $type . "'.";
1967 if(isset($manifest['acceptable_sugar_versions'])) {
1968 $version_ok = false;
1969 $matches_empty = true;
1970 if(isset($manifest['acceptable_sugar_versions']['exact_matches'])) {
1971 $matches_empty = false;
1972 foreach($manifest['acceptable_sugar_versions']['exact_matches'] as $match) {
1973 if($match == $sugar_version) {
1978 if(!$version_ok && isset($manifest['acceptable_sugar_versions']['regex_matches'])) {
1979 $matches_empty = false;
1980 foreach($manifest['acceptable_sugar_versions']['regex_matches'] as $match) {
1981 if(preg_match("/$match/", $sugar_version)) {
1987 if(!$matches_empty && !$version_ok) {
1988 return $mod_strings['ERROR_VERSION_INCOMPATIBLE']."<br />".
1989 $mod_strings['ERR_UW_VERSION'].$sugar_version;
1993 if(isset($manifest['acceptable_sugar_flavors']) && sizeof($manifest['acceptable_sugar_flavors']) > 0) {
1995 foreach($manifest['acceptable_sugar_flavors'] as $match) {
1996 if($match == $sugar_flavor) {
2001 return $mod_strings['ERROR_FLAVOR_INCOMPATIBLE']."<br />".
2002 $mod_strings['ERR_UW_FLAVOR'].$sugar_flavor."<br />".
2003 $mod_strings['ERR_UW_FLAVOR_2'].$manifest['acceptable_sugar_flavors'][0];
2011 function unlinkUploadFiles() {
2013 // logThis('at unlinkUploadFiles()');
2015 // if(isset($_SESSION['install_file']) && !empty($_SESSION['install_file'])) {
2016 // $upload = $_SESSION['install_file'];
2018 // if(is_file($upload)) {
2019 // logThis('unlinking ['.$upload.']');
2020 // @unlink($upload);
2026 * deletes files created by unzipping a package
2028 function unlinkUWTempFiles() {
2029 global $sugar_config;
2032 logThis('at unlinkUWTempFiles()');
2034 list($upgDir, $tempDir) = getUWDirs();
2036 if(file_exists($tempDir) && is_dir($tempDir)){
2037 $files = findAllFiles($tempDir, array(), false);
2039 foreach($files as $file) {
2040 if(!is_dir($file)) {
2041 //logThis('unlinking ['.$file.']', $path);
2046 $files = findAllFiles($tempDir, array(), true);
2047 foreach($files as $dir) {
2049 //logThis('removing dir ['.$dir.']', $path);
2053 $cacheFile = sugar_cached("modules/UpgradeWizard/_persistence.php");
2054 if(is_file($cacheFile)) {
2055 logThis("Unlinking Upgrade cache file: '_persistence.php'", $path);
2056 @unlink($cacheFile);
2059 logThis("finished!");
2063 * finds all files in the passed path, but skips select directories
2064 * @param string dir Relative path
2065 * @param array the_array Collections of found files/dirs
2066 * @param bool include_dir True if we want to include directories in the
2067 * returned collection
2069 function uwFindAllFiles($dir, $theArray, $includeDirs=false, $skipDirs=array(), $echo=false) {
2071 if (whetherNeedToSkipDir($dir, $skipDirs))
2076 if (!is_dir($dir)) { return $theArray; } // Bug # 46035, just checking for valid dir
2078 if ($d === false) { return $theArray; } // Bug # 46035, more checking
2080 while($f = $d->read()) {
2081 // bug 40793 Skip Directories array in upgradeWizard does not function correctly
2082 if($f == "." || $f == ".." || whetherNeedToSkipDir("$dir/$f", $skipDirs)) { // skip *nix self/parent
2086 // for AJAX length count
2092 if(is_dir("$dir/$f")) {
2093 if($includeDirs) { // add the directory if flagged
2094 $theArray[] = clean_path("$dir/$f");
2098 $theArray = uwFindAllFiles("$dir/$f/", $theArray, $includeDirs, $skipDirs, $echo);
2100 $theArray[] = clean_path("$dir/$f");
2113 * unset's UW's Session Vars
2115 function resetUwSession() {
2116 logThis('resetting $_SESSION');
2118 if(isset($_SESSION['committed']))
2119 unset($_SESSION['committed']);
2120 if(isset($_SESSION['sugar_version_file']))
2121 unset($_SESSION['sugar_version_file']);
2122 if(isset($_SESSION['upgrade_complete']))
2123 unset($_SESSION['upgrade_complete']);
2124 if(isset($_SESSION['allTables']))
2125 unset($_SESSION['allTables']);
2126 if(isset($_SESSION['alterCustomTableQueries']))
2127 unset($_SESSION['alterCustomTableQueries']);
2128 if(isset($_SESSION['skip_zip_upload']))
2129 unset($_SESSION['skip_zip_upload']);
2130 if(isset($_SESSION['sugar_version_file']))
2131 unset($_SESSION['sugar_version_file']);
2132 if(isset($_SESSION['install_file']))
2133 unset($_SESSION['install_file']);
2134 if(isset($_SESSION['unzip_dir']))
2135 unset($_SESSION['unzip_dir']);
2136 if(isset($_SESSION['zip_from_dir']))
2137 unset($_SESSION['zip_from_dir']);
2138 if(isset($_SESSION['overwrite_files']))
2139 unset($_SESSION['overwrite_files']);
2140 if(isset($_SESSION['schema_change']))
2141 unset($_SESSION['schema_change']);
2142 if(isset($_SESSION['uw_restore_dir']))
2143 unset($_SESSION['uw_restore_dir']);
2144 if(isset($_SESSION['step']))
2145 unset($_SESSION['step']);
2146 if(isset($_SESSION['files']))
2147 unset($_SESSION['files']);
2148 if(isset($_SESSION['Upgraded451Wizard'])){
2149 unset($_SESSION['Upgraded451Wizard']);
2151 if(isset($_SESSION['Initial_451to500_Step'])){
2152 unset($_SESSION['Initial_451to500_Step']);
2154 if(isset($_SESSION['license_shown']))
2155 unset($_SESSION['license_shown']);
2156 if(isset($_SESSION['sugarMergeRunResults']))
2157 unset($_SESSION['sugarMergeRunResults']);
2161 * runs rebuild scripts
2163 function UWrebuild() {
2167 //CCL - Comment this block out, it is called in end.php
2168 logThis('Rebuilding everything...', $path);
2169 require_once('modules/Administration/QuickRepairAndRebuild.php');
2170 $randc = new RepairAndClear();
2171 $randc->repairAndClearAll(array('clearAll'),array(translate('LBL_ALL_MODULES')), false, false);
2173 $query = "DELETE FROM versions WHERE name='Rebuild Extensions'";
2175 logThis('Registering rebuild record: '.$query, $path);
2176 logThis('Rebuild done.', $path);
2178 // insert a new database row to show the rebuild extensions is done
2179 $id = create_guid();
2180 $gmdate = gmdate('Y-m-d H:i:s');
2181 $date_entered = db_convert("'$gmdate'", 'datetime');
2182 $query = 'INSERT INTO versions (id, deleted, date_entered, date_modified, modified_user_id, created_by, name, file_version, db_version) '
2183 . "VALUES ('$id', '0', $date_entered, $date_entered, '1', '1', 'Rebuild Extensions', '4.0.0', '4.0.0')";
2185 logThis('Registering rebuild record in versions table: '.$query, $path);
2188 function getCustomTables() {
2191 return $db->tablesLike('%_cstm');
2194 function alterCustomTables($customTables)
2199 function getAllTables() {
2201 return $db->getTablesArray();
2204 function printAlterTableSql($tables)
2206 $alterTableSql = '';
2208 foreach($tables as $table)
2209 $alterTableSql .= "ALTER TABLE " . $table . " CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;" . "\n";
2211 return $alterTableSql;
2214 function executeConvertTablesSql($tables)
2218 foreach($tables as $table){
2219 $query = "ALTER TABLE " . $table . " CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci";
2221 logThis("Sending query: ".$query);
2222 $db->query($query);//, true, "An error has occured while performing db query. See log file for details.<br>");
2228 function testThis() {
2229 $files = uwFindAllFiles(getcwd().'/test', array());
2231 $out = "<table cellpadding='1' cellspacing='0' border='0'>\n";
2234 foreach($files as $file) {
2235 $relativeFile = clean_path(str_replace(getcwd().'/test', '', $file));
2236 $relativeFile = ($relativeFile{0} == '/') ? substr($relativeFile, 1, strlen($relativeFile)) : $relativeFile;
2238 $relativePath = dirname($relativeFile);
2240 if($relativePath == $priorPath) { // same dir, new file
2241 $out .= "<tr><td>".basename($relativeFile)."</td></tr>";
2242 $priorPath = $relativePath;
2256 function testThis2($dir, $id=0, $hide=false) {
2257 global $mod_strings;
2259 $dh = opendir($dir);
2262 $doHide = ($hide) ? 'none' : '';
2263 $out = "<div id='{$id}' style='display:{$doHide};'>";
2264 $out .= "<table cellpadding='1' cellspacing='0' border='0' style='border:0px solid #ccc'>\n";
2266 while($file = readdir($dh)) {
2267 if($file == '.' || $file == '..' || $file == 'CVS' || $file == '.cvsignore')
2270 if(is_dir($path.'/'.$file)) {
2271 $file = $path.'/'.$file;
2272 $newI = create_guid();
2273 $out .= "<tr><td valign='top'><a href='javascript:toggleNwFiles(\"{$newI}\");'>".SugarThemeRegistry::current()->getImage("Workflow", "", null, null, ".gif", $mod_strings['LBL_WORKFLOW'])."</a></td>\n";
2274 $out .= "<td valign='top'><b><a href='javascript:toggleNwFiles(\"{$newI}\");'>".basename($file)."</a></b></td></tr>";
2275 $out .= "<tr><td></td><td valign='top'>".testThis2($file, $newI, true)."</td></tr>";
2277 $out .= "<tr><td valign='top'> </td>\n";
2278 $out .= "<td valign='top'>".basename($file)."</td></tr>";
2282 $out .= "</tr></table>";
2293 function testThis3(&$files, $id, $hide, $previousPath = '') {
2294 if(!is_array($files) || empty($files))
2299 global $mod_strings;
2300 // expecting full path here
2301 foreach($files as $k => $file) {
2302 $file = str_replace(getcwd(), '', $file);
2303 $path = dirname($file);
2304 $fileName = basename($file);
2306 if($fileName == 'CVS' || $fileName == '.cvsignore')
2309 if($path == $previousPath) { // same directory
2310 // new row for each file
2311 $out .= "<tr><td valign='top' align='left'> </td>";
2312 $out .= "<td valign='top' align='left'>{$fileName}</td></tr>";
2313 } else { // new directory
2315 $out .= "<tr><td valign='top'><a href='javascript:toggleNwFiles(\"{$newI}\");'>".SugarThemeRegistry::current()->getImage("Workflow", "", null, null, ".gif", $mod_strings['LBL_WORKFLOW'])."</a></td>\n";
2316 $out .= "<td valign='top'><b><a href='javascript:toggleNwFiles(\"{$newI}\");'>".$fileName."</a></b></td></tr>";
2317 $recurse = testThis3($files, $newI, true, $previousPath);
2318 $out .= "<tr><td></td><td valign='top'>".$recurse."</td></tr>";
2321 $previousPath = $path;
2323 $display = ($hide) ? 'none' : '';
2325 <div id="{$id}" style="display:{$display}">
2326 <table cellpadding='1' cellspacing='0' border='0' style='border:1px solid #ccc'>
2335 function testThis4($filePath, $fileNodes=array(), $fileName='') {
2336 $path = dirname($filePath);
2337 $file = basename($filePath);
2339 $exFile = explode('/', $path);
2341 foreach($exFile as $pathSegment) {
2342 if(is_array($fileNodes[$pathSegment])) { // path already processed
2344 } else { // newly found path
2345 $fileNodes[$pathSegment] = array();
2348 if($fileName != '') {
2349 $fileNodes[$pathSegment][] = $fileName;
2358 ///////////////////////////////////////////////////////////////////////////////
2359 //// SYSTEM CHECK FUNCTIONS
2361 * generates an array with all files in the SugarCRM root directory, skipping
2363 * @return array files Array of files with absolute paths
2365 function getFilesForPermsCheck() {
2366 global $sugar_config;
2368 logThis('Got JSON call to find all files...');
2369 $filesNotWritable = array();
2370 $filesNWPerms = array();
2372 // add directories here that should be skipped when doing file permissions checks (cache/upload is the nasty one)
2374 $sugar_config['upload_dir'],
2376 $files = uwFindAllFiles(".", array(), true, $skipDirs, true);
2381 * checks files for permissions
2382 * @param array files Array of files with absolute paths
2383 * @return string result of check
2385 function checkFiles($files, $echo=false) {
2386 global $mod_strings;
2387 $filesNotWritable = array();
2390 <a href='javascript:void(0); toggleNwFiles(\"filesNw\");'>{$mod_strings['LBL_UW_SHOW_NW_FILES']}</a>
2391 <div id='filesNw' style='display:none;'>
2392 <table cellpadding='3' cellspacing='0' border='0'>
2394 <th align='left'>{$mod_strings['LBL_UW_FILE']}</th>
2395 <th align='left'>{$mod_strings['LBL_UW_FILE_PERMS']}</th>
2396 <th align='left'>{$mod_strings['LBL_UW_FILE_OWNER']}</th>
2397 <th align='left'>{$mod_strings['LBL_UW_FILE_GROUP']}</th>
2400 $isWindows = is_windows();
2401 foreach($files as $file) {
2404 if(!is_writable_windows($file)) {
2405 logThis('WINDOWS: File ['.$file.'] not readable - saving for display');
2406 // don't warn yet - we're going to use this to check against replacement files
2407 // aw: commented out; it's a hack to allow upgrade wizard to continue on windows... will fix later
2408 /*$filesNotWritable[$i] = $file;
2409 $filesNWPerms[$i] = substr(sprintf('%o',fileperms($file)), -4);
2410 $filesOut .= "<tr>".
2411 "<td><span class='error'>{$file}</span></td>".
2412 "<td>{$filesNWPerms[$i]}</td>".
2413 "<td>".$mod_strings['ERR_UW_CANNOT_DETERMINE_USER']."</td>".
2414 "<td>".$mod_strings['ERR_UW_CANNOT_DETERMINE_GROUP']."</td>".
2418 if(!is_writable($file)) {
2419 logThis('File ['.$file.'] not writable - saving for display');
2420 // don't warn yet - we're going to use this to check against replacement files
2421 $filesNotWritable[$i] = $file;
2422 $filesNWPerms[$i] = substr(sprintf('%o',fileperms($file)), -4);
2423 $owner = posix_getpwuid(fileowner($file));
2424 $group = posix_getgrgid(filegroup($file));
2425 $filesOut .= "<tr>".
2426 "<td><span class='error'>{$file}</span></td>".
2427 "<td>{$filesNWPerms[$i]}</td>".
2428 "<td>".$owner['name']."</td>".
2429 "<td>".$group['name']."</td>".
2436 $filesOut .= '</table></div>';
2438 $errors['files']['filesNotWritable'] = (count($filesNotWritable) > 0) ? true : false;
2439 if(count($filesNotWritable) < 1) {
2440 $filesOut = "{$mod_strings['LBL_UW_FILE_NO_ERRORS']}";
2446 function deletePackageOnCancel(){
2447 global $mod_strings;
2448 global $sugar_config;
2449 list($base_upgrade_dir, $base_tmp_upgrade_dir) = getUWDirs();
2450 logThis('running delete');
2451 if(!isset($_SESSION['install_file']) || ($_SESSION['install_file'] == "")) {
2452 logThis('ERROR: trying to delete non-existent file: ['.$_REQUEST['install_file'].']');
2453 $error = $mod_strings['ERR_UW_NO_FILE_UPLOADED'];
2455 // delete file in upgrades/patch
2456 $delete_me = "$base_upgrade_dir/patch/".basename(urldecode( $_REQUEST['install_file'] ));
2457 if(@unlink($delete_me)) {
2458 //logThis('unlinking: '.$delete_me);
2459 $out = basename($delete_me).$mod_strings['LBL_UW_FILE_DELETED'];
2461 logThis('ERROR: could not delete ['.$delete_me.']');
2462 $error = $mod_strings['ERR_UW_FILE_NOT_DELETED'].$delete_me;
2465 if(!empty($error)) {
2466 $out = "<b><span class='error'>{$error}</span></b><br />";
2470 function handleExecuteSqlKeys($db, $tableName, $disable)
2472 if(empty($tableName)) return true;
2473 if(is_callable(array($db, "supports"))) {
2475 return $disable?$db->disableKeys($tableName):$db->enableKeys($tableName);
2478 $op = $disable?"DISABLE":"ENABLE";
2479 return $db->query("ALTER TABLE $tableName $op KEYS");
2483 function parseAndExecuteSqlFile($sqlScript,$forStepQuery='',$resumeFromQuery='')
2485 global $sugar_config;
2486 $alterTableSchema = '';
2487 $sqlErrors = array();
2488 if(!isset($_SESSION['sqlSkippedQueries'])){
2489 $_SESSION['sqlSkippedQueries'] = array();
2491 $db = DBManagerFactory::getInstance();
2492 $disable_keys = ($db->dbType == "mysql"); // have to use old way for now for upgrades
2493 if(strpos($resumeFromQuery,",") != false){
2494 $resumeFromQuery = explode(",",$resumeFromQuery);
2496 if(file_exists($sqlScript)) {
2497 $fp = fopen($sqlScript, 'r');
2498 $contents = stream_get_contents($fp);
2499 $anyScriptChanges =$contents;
2500 $resumeAfterFound = false;
2504 while($line = fgets($fp)) {
2505 if(strpos($line, '--') === false) {
2506 $completeLine .= " ".trim($line);
2507 if(strpos($line, ';') !== false) {
2509 $query = str_replace(';','',$completeLine);
2510 //if resume from query is not null then find out from where
2511 //it should start executing the query.
2513 if($query != null && $resumeFromQuery != null){
2514 if(!$resumeAfterFound){
2515 if(strpos($query,",") != false){
2516 $queArray = explode(",",$query);
2517 for($i=0;$i<sizeof($resumeFromQuery);$i++){
2518 if(strcasecmp(trim($resumeFromQuery[$i]),trim($queArray[$i]))==0){
2519 $resumeAfterFound = true;
2521 $resumeAfterFound = false;
2527 elseif(strcasecmp(trim($resumeFromQuery),trim($query))==0){
2528 $resumeAfterFound = true;
2531 if($resumeAfterFound){
2534 // if $count=1 means it is just found so skip the query. Run the next one
2535 if($query != null && $resumeAfterFound && $count >1){
2536 $tableName = getAlterTable($query);
2539 handleExecuteSqlKeys($db, $tableName, true);
2542 if($db->checkError()){
2543 //put in the array to use later on
2544 $_SESSION['sqlSkippedQueries'][] = $query;
2548 handleExecuteSqlKeys($db, $tableName, false);
2550 $progQuery[$forStepQuery]=$query;
2551 post_install_progress($progQuery,$action='set');
2554 elseif($query != null){
2555 $tableName = getAlterTable($query);
2558 handleExecuteSqlKeys($db, $tableName, true);
2563 handleExecuteSqlKeys($db, $tableName, false);
2565 $progQuery[$forStepQuery]=$query;
2566 post_install_progress($progQuery,$action='set');
2567 if($db->checkError()){
2568 //put in the array to use later on
2569 $_SESSION['sqlSkippedQueries'][] = $query;
2581 function getAlterTable($query){
2582 $query = strtolower($query);
2583 if (preg_match('/^\s*alter\s+table\s+/', $query)) {
2584 $sqlArray = explode(" ", $query);
2585 $key = array_search('table', $sqlArray);
2586 return $sqlArray[($key+1)];
2592 function set_upgrade_vars(){
2593 logThis('setting session variables...');
2594 $upgrade_progress_dir = sugar_cached('upgrades/temp');
2595 if(!is_dir($upgrade_progress_dir)){
2596 mkdir_recursive($upgrade_progress_dir);
2598 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
2599 if(file_exists($upgrade_progress_file)){
2600 include($upgrade_progress_file);
2603 fopen($upgrade_progress_file, 'w+');
2605 if(!isset($upgrade_config) || $upgrade_config == null){
2606 $upgrade_config = array();
2607 $upgrade_config[1]['upgrade_vars']=array();
2609 if(isset($upgrade_config[1]) && isset($upgrade_config[1]['upgrade_vars']) && !is_array($upgrade_config[1]['upgrade_vars'])){
2610 $upgrade_config[1]['upgrade_vars'] = array();
2613 if(!isset($upgrade_vars) || $upgrade_vars == NULL){
2614 $upgrade_vars = array();
2616 if(isset($_SESSION['unzip_dir']) && !empty($_SESSION['unzip_dir']) && file_exists($_SESSION['unzip_dir'])){
2617 $upgrade_vars['unzip_dir']=$_SESSION['unzip_dir'];
2619 if(isset($_SESSION['install_file']) && !empty($_SESSION['install_file']) && file_exists($_SESSION['install_file'])){
2620 $upgrade_vars['install_file']=$_SESSION['install_file'];
2622 if(isset($_SESSION['Upgraded451Wizard']) && !empty($_SESSION['Upgraded451Wizard'])){
2623 $upgrade_vars['Upgraded451Wizard']=$_SESSION['Upgraded451Wizard'];
2625 if(isset($_SESSION['license_shown']) && !empty($_SESSION['license_shown'])){
2626 $upgrade_vars['license_shown']=$_SESSION['license_shown'];
2628 if(isset($_SESSION['Initial_451to500_Step']) && !empty($_SESSION['Initial_451to500_Step'])){
2629 $upgrade_vars['Initial_451to500_Step']=$_SESSION['Initial_451to500_Step'];
2631 if(isset($_SESSION['zip_from_dir']) && !empty($_SESSION['zip_from_dir'])){
2632 $upgrade_vars['zip_from_dir']=$_SESSION['zip_from_dir'];
2634 //place into the upgrade_config array and rewrite config array only if new values are being inserted
2635 if(isset($upgrade_vars) && $upgrade_vars != null && sizeof($upgrade_vars) > 0){
2636 foreach($upgrade_vars as $key=>$val){
2637 if($key != null && $val != null){
2638 $upgrade_config[1]['upgrade_vars'][$key]=$upgrade_vars[$key];
2641 ksort($upgrade_config);
2642 if(is_writable($upgrade_progress_file) && write_array_to_file( "upgrade_config", $upgrade_config,
2643 $upgrade_progress_file)) {
2644 //writing to the file
2649 function initialize_session_vars(){
2650 $upgrade_progress_dir = sugar_cached('upgrades/temp');
2651 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
2652 if(file_exists($upgrade_progress_file)){
2653 include($upgrade_progress_file);
2654 if(isset($upgrade_config) && $upgrade_config != null && is_array($upgrade_config) && sizeof($upgrade_config) >0){
2655 $currVarsArray=$upgrade_config[1]['upgrade_vars'];
2656 //print_r($currVarsArray);
2657 if(isset($currVarsArray) && $currVarsArray != null && is_array($currVarsArray) && sizeof($currVarsArray)>0){
2658 foreach($currVarsArray as $key=>$val){
2659 if($key != null && $val !=null){
2660 //set session variables
2661 $_SESSION[$key]=$val;
2670 //track the upgrade progress on each step
2671 //track the upgrade progress on each step
2672 function set_upgrade_progress($currStep,$currState,$currStepSub='',$currStepSubState=''){
2674 $upgrade_progress_dir = sugar_cached('upgrades/temp');
2675 if(!is_dir($upgrade_progress_dir)){
2676 mkdir_recursive($upgrade_progress_dir);
2678 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
2679 if(file_exists($upgrade_progress_file)){
2680 include($upgrade_progress_file);
2683 if(function_exists('sugar_fopen')){
2684 sugar_fopen($upgrade_progress_file, 'w+');
2687 fopen($upgrade_progress_file, 'w+');
2690 if(!isset($upgrade_config) || $upgrade_config == null){
2691 $upgrade_config = array();
2692 $upgrade_config[1]['upgrade_vars']=array();
2694 if(!is_array($upgrade_config[1]['upgrade_vars'])){
2695 $upgrade_config[1]['upgrade_vars'] = array();
2697 if($currStep != null && $currState != null){
2698 if(sizeof($upgrade_config) > 0){
2699 if($currStepSub != null && $currStepSubState !=null){
2700 //check if new status to be set or update
2701 //get the latest in array. since it has sub components prepare an array
2702 if(!empty($upgrade_config[sizeof($upgrade_config)][$currStep]) && is_array($upgrade_config[sizeof($upgrade_config)][$currStep])){
2703 $latestStepSub = currSubStep($upgrade_config[sizeof($upgrade_config)][$currStep]);
2704 if($latestStepSub == $currStepSub){
2705 $upgrade_config[sizeof($upgrade_config)][$currStep][$latestStepSub]=$currStepSubState;
2706 $upgrade_config[sizeof($upgrade_config)][$currStep][$currStep] = $currState;
2709 $upgrade_config[sizeof($upgrade_config)][$currStep][$currStepSub]=$currStepSubState;
2710 $upgrade_config[sizeof($upgrade_config)][$currStep][$currStep] = $currState;
2714 $currArray = array();
2715 $currArray[$currStep] = $currState;
2716 $currArray[$currStepSub] = $currStepSubState;
2717 $upgrade_config[sizeof($upgrade_config)+1][$currStep] = $currArray;
2721 //get the current upgrade progress
2722 $latestStep = get_upgrade_progress();
2723 //set the upgrade progress
2724 if($latestStep == $currStep){
2725 //update the current step with new progress status
2726 $upgrade_config[sizeof($upgrade_config)][$latestStep]=$currState;
2730 $upgrade_config[sizeof($upgrade_config)+1][$currStep]=$currState;
2732 // now check if there elements within array substeps
2736 //set the upgrade progress (just starting)
2737 $upgrade_config[sizeof($upgrade_config)+1][$currStep]= $currState;
2740 if(is_writable($upgrade_progress_file) && write_array_to_file( "upgrade_config", $upgrade_config,
2741 $upgrade_progress_file)) {
2742 //writing to the file
2748 function get_upgrade_progress(){
2749 $upgrade_progress_dir = sugar_cached('upgrades/temp');
2750 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
2753 if(file_exists($upgrade_progress_file)){
2754 include($upgrade_progress_file);
2755 if(!isset($upgrade_config) || $upgrade_config == null){
2756 $upgrade_config = array();
2758 if($upgrade_config != null && sizeof($upgrade_config) >1){
2759 $currArr = $upgrade_config[sizeof($upgrade_config)];
2760 if(is_array($currArr)){
2761 foreach($currArr as $key=>$val){
2769 function currSubStep($currStep){
2771 if(is_array($currStep)){
2772 foreach($currStep as $key=>$val){
2780 function currUpgradeState($currState){
2782 if(is_array($currState)){
2783 foreach($currState as $key=>$val){
2785 foreach($val as $k=>$v){
2799 function didThisStepRunBefore($step,$SubStep=''){
2800 if($step == null) return;
2801 $upgrade_progress_dir = sugar_cached('upgrades/temp');
2802 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
2805 if(file_exists($upgrade_progress_file)){
2806 include($upgrade_progress_file);
2807 if(isset($upgrade_config) && $upgrade_config != null && is_array($upgrade_config) && sizeof($upgrade_config) >0){
2808 for($i=1;$i<=sizeof($upgrade_config);$i++){
2809 if(is_array($upgrade_config[$i])){
2810 foreach($upgrade_config[$i] as $key=>$val){
2812 if(is_array($upgrade_config[$i][$step])){
2814 foreach ($upgrade_config[$i][$step] as $k=>$v){
2816 foreach($v as $k1=>$v1){
2817 if($SubStep != null){
2818 if($SubStep ==$k1 && $v1=='done'){
2825 elseif($SubStep !=null){
2826 if($SubStep==$k && $v=='done'){
2831 elseif($step==$k && $v=='done'){
2837 elseif($val=='done'){
2851 //get and set post install status
2852 function post_install_progress($progArray='',$action=''){
2853 $upgrade_progress_dir = sugar_cached('upgrades/temp');
2854 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
2855 if($action=='' || $action=='get'){
2856 //get the state of post install
2857 $currProg = array();
2858 if(file_exists($upgrade_progress_file)){
2859 include($upgrade_progress_file);
2860 if(is_array($upgrade_config[sizeof($upgrade_config)]['commit']['post_install']) && sizeof($upgrade_config[sizeof($upgrade_config)]['commit']['post_install'])>0){
2861 foreach($upgrade_config[sizeof($upgrade_config)]['commit']['post_install'] as $k=>$v){
2868 elseif($action=='set'){
2869 if(!is_dir($upgrade_progress_dir)){
2870 mkdir($upgrade_progress_dir);
2872 if(file_exists($upgrade_progress_file)){
2873 include($upgrade_progress_file);
2876 fopen($upgrade_progress_file, 'w+');
2878 if(!is_array($upgrade_config[sizeof($upgrade_config)]['commit']['post_install'])){
2879 $upgrade_config[sizeof($upgrade_config)]['commit']['post_install']=array();
2880 $upgrade_config[sizeof($upgrade_config)]['commit']['post_install']['post_install'] = 'in_progress';
2882 if($progArray != null && is_array($progArray)){
2883 foreach($progArray as $key=>$val){
2884 $upgrade_config[sizeof($upgrade_config)]['commit']['post_install'][$key]=$val;
2887 if(is_writable($upgrade_progress_file) && write_array_to_file( "upgrade_config", $upgrade_config,
2888 $upgrade_progress_file)) {
2889 //writing to the file
2894 function repairDBForUpgrade($execute=false,$path=''){
2896 global $current_user, $beanFiles;
2898 set_time_limit(3600);
2900 $db = &DBManagerFactory::getInstance();
2902 VardefManager::clearVardef();
2903 require_once('include/ListView/ListView.php');
2904 foreach ($beanFiles as $bean => $file) {
2905 require_once ($file);
2906 $focus = new $bean ();
2907 $sql .= $db->repairTable($focus, $execute);
2911 $olddictionary = $dictionary;
2912 unset ($dictionary);
2913 include ('modules/TableDictionary.php');
2914 foreach ($dictionary as $meta) {
2915 $tablename = $meta['table'];
2916 $fielddefs = $meta['fields'];
2917 $indices = $meta['indices'];
2918 $sql .= $db->repairTableParams($tablename, $fielddefs, $indices, $execute);
2921 foreach (explode("\n", $sql) as $line) {
2922 if (!empty ($line) && substr($line, -2) != "*/") {
2925 $qry_str .= $line . "\n";
2936 preg_replace('#(/\*.+?\*/\n*)#', '', $qry_str)
2938 logThis("*******START EXECUTING DB UPGRADE QUERIES***************",$path);
2939 logThis($sql,$path);
2940 logThis("*******END EXECUTING DB UPGRADE QUERIES****************",$path);
2949 * upgradeUserPreferences
2950 * This method updates the user_preferences table and sets the pages/dashlets for users
2951 * which have ACL access to Trackers so that the Tracker dashlets are set in their user perferences
2954 function upgradeUserPreferences() {
2955 global $sugar_config, $sugar_version;
2956 $uw_strings = return_module_language($GLOBALS['current_language'], 'UpgradeWizard');
2958 $localization = new Localization();
2959 $localeCoreDefaults = $localization->getLocaleConfigDefaults();
2961 // check the current system wide default_locale_name_format and add it to the list if it's not there
2962 if(empty($sugar_config['name_formats'])) {
2963 $sugar_config['name_formats'] = $localeCoreDefaults['name_formats'];
2964 if(!rebuildConfigFile($sugar_config, $sugar_version)) {
2965 $errors[] = $uw_strings['ERR_UW_CONFIG_WRITE'];
2969 $currentDefaultLocaleNameFormat = $sugar_config['default_locale_name_format'];
2971 if ($localization->isAllowedNameFormat($currentDefaultLocaleNameFormat)) {
2972 upgradeLocaleNameFormat($currentDefaultLocaleNameFormat);
2974 $sugar_config['default_locale_name_format'] = $localeCoreDefaults['default_locale_name_format'];
2975 if(!rebuildConfigFile($sugar_config, $sugar_version)) {
2976 $errors[] = $uw_strings['ERR_UW_CONFIG_WRITE'];
2978 $localization->createInvalidLocaleNameFormatUpgradeNotice();
2981 $db = &DBManagerFactory::getInstance();
2982 $result = $db->query("SELECT id FROM users where deleted = '0'");
2983 while($row = $db->fetchByAssoc($result))
2985 $current_user = new User();
2986 $current_user->retrieve($row['id']);
2988 // 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
2989 $currentUserNameFormat = $current_user->getPreference('default_locale_name_format');
2990 if ($localization->isAllowedNameFormat($currentUserNameFormat)) {
2991 upgradeLocaleNameFormat($currentUserNameFormat);
2993 $current_user->setPreference('default_locale_name_format', 's f l', 0, 'global');
2994 $current_user->savePreferencesToDB();
3002 * Checks if a locale name format is part of the default list, if not adds it to the config
3003 * @param $name_format string a local name format string such as 's f l'
3004 * @return bool true on successful write to config file, false on failure;
3006 function upgradeLocaleNameFormat($name_format) {
3007 global $sugar_config, $sugar_version;
3009 $localization = new Localization();
3010 $localeConfigDefaults = $localization->getLocaleConfigDefaults();
3012 $uw_strings = return_module_language($GLOBALS['current_language'], 'UpgradeWizard');
3013 if(empty($sugar_config['name_formats'])) {
3014 $sugar_config['name_formats'] = $localeConfigDefaults['name_formats'];
3015 if(!rebuildConfigFile($sugar_config, $sugar_version)) {
3016 $errors[] = $uw_strings['ERR_UW_CONFIG_WRITE'];
3019 if (!in_array($name_format, $sugar_config['name_formats'])) {
3020 $new_config = sugarArrayMerge($sugar_config['name_formats'], array($name_format=>$name_format));
3021 $sugar_config['name_formats'] = $new_config;
3022 if(!rebuildConfigFile($sugar_config, $sugar_version)) {
3023 $errors[] = $uw_strings['ERR_UW_CONFIG_WRITE'];
3032 function add_custom_modules_favorites_search(){
3033 $module_directories = scandir('modules');
3035 foreach($module_directories as $module_dir){
3036 if($module_dir == '.' || $module_dir == '..' || !is_dir("modules/{$module_dir}")){
3041 preg_match('/^[a-z0-9]{1,5}_[a-z0-9_]+$/i' , $module_dir, $matches);
3043 // Make sure the module was created by module builder
3044 if(empty($matches)){
3048 $full_module_dir = "modules/{$module_dir}/";
3049 $read_searchdefs_from = "{$full_module_dir}/metadata/searchdefs.php";
3050 $read_SearchFields_from = "{$full_module_dir}/metadata/SearchFields.php";
3051 $read_custom_SearchFields_from = "custom/{$full_module_dir}/metadata/SearchFields.php";
3053 // Studio can possibly override this file, so we check for a custom version of it
3054 if(file_exists("custom/{$full_module_dir}/metadata/searchdefs.php")){
3055 $read_searchdefs_from = "custom/{$full_module_dir}/metadata/searchdefs.php";
3058 if(file_exists($read_searchdefs_from) && file_exists($read_SearchFields_from)){
3061 require($read_searchdefs_from);
3062 foreach($searchdefs[$module_dir]['layout']['basic_search'] as $sf_array){
3063 if(isset($sf_array['name']) && $sf_array['name'] == 'favorites_only'){
3068 require($read_SearchFields_from);
3069 if(isset($searchFields[$module_dir]['favorites_only'])){
3073 if(!$found_sf1 && !$found_sf2){
3074 $searchdefs[$module_dir]['layout']['basic_search']['favorites_only'] = array('name' => 'favorites_only','label' => 'LBL_FAVORITES_FILTER','type' => 'bool',);
3075 $searchdefs[$module_dir]['layout']['advanced_search']['favorites_only'] = array('name' => 'favorites_only','label' => 'LBL_FAVORITES_FILTER','type' => 'bool',);
3076 $searchFields[$module_dir]['favorites_only'] = array(
3077 'query_type'=>'format',
3078 'operator' => 'subquery',
3079 'subquery' => 'SELECT sugarfavorites.record_id FROM sugarfavorites
3080 WHERE sugarfavorites.deleted=0
3081 and sugarfavorites.module = \''.$module_dir.'\'
3082 and sugarfavorites.assigned_user_id = \'{0}\'',
3083 'db_field'=>array('id')
3086 if(!is_dir("custom/{$full_module_dir}/metadata")){
3087 mkdir_recursive("custom/{$full_module_dir}/metadata");
3089 $success_sf1 = write_array_to_file('searchdefs', $searchdefs, "custom/{$full_module_dir}/metadata/searchdefs.php");
3090 $success_sf2 = write_array_to_file('searchFields', $searchFields, "{$full_module_dir}/metadata/SearchFields.php");
3093 logThis("add_custom_modules_favorites_search failed for searchdefs.php for {$module_dir}");
3096 logThis("add_custom_modules_favorites_search failed for SearchFields.php for {$module_dir}");
3098 if($success_sf1 && $success_sf2){
3099 logThis("add_custom_modules_favorites_search successfully updated searchdefs and searchFields for {$module_dir}");
3108 * upgradeModulesForTeamsets
3110 * This method adds the team_set_id values to the module tables that have the new team_set_id column
3111 * added through the SugarCRM 5.5.x upgrade process. It also adds the values into the team_sets and
3112 * team_sets_teams tables.
3114 * @param filter Array of modules to process; empty by default
3116 function upgradeModulesForTeamsets($filter=array()) {
3117 require('include/modules.php');
3118 foreach($beanList as $moduleName=>$beanName) {
3119 if(!empty($filter) && array_search($moduleName, $filter) === false) {
3122 if($moduleName == 'TeamMemberships' || $moduleName == 'ForecastOpportunities'){
3125 $bean = loadBean($moduleName);
3127 empty($bean->table_name)) {
3131 $FieldArray = $GLOBALS['db']->helper->get_columns($bean->table_name);
3132 if(!isset($FieldArray['team_id'])) {
3136 upgradeTeamColumn($bean, 'team_id');
3140 //Upgrade users table
3141 $bean = loadBean('Users');
3142 upgradeTeamColumn($bean, 'default_team');
3143 $result = $GLOBALS['db']->query("SELECT id FROM teams where deleted=0");
3144 while($row = $GLOBALS['db']->fetchByAssoc($result)) {
3145 $teamset = new TeamSet();
3146 $teamset->addTeams($row['id']);
3153 * Helper function to create a team_set_id column and also set team_set_id column
3154 * to have the value of the $column_name parameter
3156 * @param $bean SugarBean which we are adding team_set_id column to
3157 * @param $column_name The name of the column containing the default team_set_id value
3159 function upgradeTeamColumn($bean, $column_name) {
3160 //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
3161 //module that does not use the SugarObjects
3162 if(empty($bean->field_defs['team_set_id']) && $bean->module_dir != 'Trackers'){
3164 //at this point we could assume that since we have a team_id defined and not a team_set_id that we need to
3165 //add that field and the corresponding relationships
3166 $object = $bean->object_name;
3167 $module = $bean->module_dir;
3168 $object_name = $object;
3169 $_object_name = strtolower($object_name);
3171 if(!empty($GLOBALS['dictionary'][$object]['table'])){
3172 $table_name = $GLOBALS['dictionary'][$object]['table'];
3174 $table_name = strtolower($module);
3177 $path = 'include/SugarObjects/implements/team_security/vardefs.php';
3179 //go through each entry in the vardefs from team_security and unset anything that is already set in the core module
3180 //this will ensure we have the proper ordering.
3181 $fieldDiff = array_diff_assoc($vardefs['fields'], $GLOBALS['dictionary'][$bean->object_name]['fields']);
3183 $file = 'custom/Extension/modules/' . $bean->module_dir. '/Ext/Vardefs/teams.php';
3184 $contents = "<?php\n";
3185 if(!empty($fieldDiff)){
3186 foreach($fieldDiff as $key => $val){
3187 $contents .= "\n\$GLOBALS['dictionary']['". $object . "']['fields']['". $key . "']=" . var_export_helper($val) . ";";
3190 $relationshipDiff = array_diff_assoc($vardefs['relationships'], $GLOBALS['dictionary'][$bean->object_name]['relationships']);
3191 if(!empty($relationshipDiff)){
3192 foreach($relationshipDiff as $key => $val){
3193 $contents .= "\n\$GLOBALS['dictionary']['". $object . "']['relationships']['". $key . "']=" . var_export_helper($val) . ";";
3196 $indexDiff = array_diff_assoc($vardefs['indices'], $GLOBALS['dictionary'][$bean->object_name]['indices']);
3197 if(!empty($indexDiff)){
3198 foreach($indexDiff as $key => $val){
3199 $contents .= "\n\$GLOBALS['dictionary']['". $object . "']['indices']['". $key . "']=" . var_export_helper($val) . ";";
3202 if( $fh = @sugar_fopen( $file, 'wt' ) )
3204 fputs( $fh, $contents);
3209 //we have written out the teams.php into custom/Extension/modules/{$module_dir}/Ext/Vardefs/teams.php'
3210 //now let's merge back into vardefs.ext.php
3211 require_once('ModuleInstall/ModuleInstaller.php');
3212 $mi = new ModuleInstaller();
3213 $mi->merge_files('Ext/Vardefs/', 'vardefs.ext.php');
3214 VardefManager::loadVardef($bean->module_dir, $bean->object_name, true);
3215 $bean->field_defs = $GLOBALS['dictionary'][$bean->object_name]['fields'];
3218 if(isset($bean->field_defs['team_set_id'])) {
3219 //Create the team_set_id column
3220 $FieldArray = $GLOBALS['db']->helper->get_columns($bean->table_name);
3221 if(!isset($FieldArray['team_set_id'])) {
3222 $GLOBALS['db']->addColumn($bean->table_name, $bean->field_defs['team_set_id']);
3224 $indexArray = $GLOBALS['db']->helper->get_indices($bean->table_name);
3226 $indexName = getValidDBName('idx_'.strtolower($bean->table_name).'_tmst_id', true, 34);
3229 'name' => $indexName,
3231 'fields' => array('team_set_id')
3234 if(!isset($indexArray[$indexName])) {
3235 $GLOBALS['db']->addIndexes($bean->table_name, $indexDef);
3238 //Update the table's team_set_id column to have the same values as team_id
3239 $GLOBALS['db']->query("UPDATE {$bean->table_name} SET team_set_id = {$column_name}");
3244 * Update the folder subscription table which confirms to the team security mechanism but
3245 * the class SugarFolders does not extend SugarBean and is therefore never picked up by the
3246 * upgradeModulesForTeamsets function.
3248 function upgradeFolderSubscriptionsTeamSetId()
3250 logThis("In upgradeFolderSubscriptionsTeamSetId()");
3251 $query = "UPDATE folders SET team_set_id = team_id";
3252 $result = $GLOBALS['db']->query($query);
3253 logThis("Finished upgradeFolderSubscriptionsTeamSetId()");
3257 * upgradeModulesForTeam
3259 * This method update the associated_user_id, name, name_2 to the private team records on teams table
3260 * This function is used for upgrade process from 5.1.x and 5.2.x.
3263 function upgradeModulesForTeam() {
3264 logThis("In upgradeModulesForTeam()");
3265 $result = $GLOBALS['db']->query("SELECT id, user_name, first_name, last_name FROM users where deleted=0");
3267 while($row = $GLOBALS['db']->fetchByAssoc($result)) {
3268 $results2 = $GLOBALS['db']->query("SELECT id FROM teams WHERE name = '({$row['user_name']})'");
3270 if(!$assoc = $GLOBALS['db']->fetchByAssoc($results2)) {
3271 //if team does not exist, then lets create the team for this user
3274 $user->retrieve($row['id']);
3275 $team->new_user_created($user);
3276 $team_id = $team->id;
3278 $team_id =$assoc['id'];
3282 $name = is_null($row['first_name'])?'':$row['first_name'];
3283 $name_2 = is_null($row['last_name'])?'':$row['last_name'];
3284 $associated_user_id = $row['id'];
3287 //Ensure team->name is not empty by using team->name_2 if available
3288 if(empty($name) && !empty($name_2)) {
3293 $query = "UPDATE teams SET name = '{$name}', name_2 = '{$name_2}', associated_user_id = '{$associated_user_id}' WHERE id = '{$team_id}'";
3294 $GLOBALS['db']->query($query);
3297 //Update the team_set_id and default_team columns
3298 $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'));
3300 //Update team_set_id
3301 if($ce_to_pro_or_ent) {
3302 $GLOBALS['db']->query("update users set team_set_id = (select teams.id from teams where teams.associated_user_id = users.id)");
3303 $GLOBALS['db']->query("update users set default_team = (select teams.id from teams where teams.associated_user_id = users.id)");
3309 function addNewSystemTabsFromUpgrade($from_dir){
3311 if(isset($_SESSION['upgrade_from_flavor'])){
3313 //check to see if there are any new files that need to be added to systems tab
3314 //retrieve old modules list
3315 logThis('check to see if new modules exist',$path);
3316 $oldModuleList = array();
3317 $newModuleList = array();
3318 include($from_dir.'/include/modules.php');
3319 $oldModuleList = $moduleList;
3320 include('include/modules.php');
3321 $newModuleList = $moduleList;
3323 //include tab controller
3324 require_once('modules/MySettings/TabController.php');
3325 $newTB = new TabController();
3327 //make sure new modules list has a key we can reference directly
3328 $newModuleList = $newTB->get_key_array($newModuleList);
3329 $oldModuleList = $newTB->get_key_array($oldModuleList);
3331 //iterate through list and remove commonalities to get new modules
3332 foreach ($newModuleList as $remove_mod){
3333 if(in_array($remove_mod, $oldModuleList)){
3334 unset($newModuleList[$remove_mod]);
3337 //new modules list now has left over modules which are new to this install, so lets add them to the system tabs
3338 logThis('new modules to add are '.var_export($newModuleList,true),$path);
3340 if(!empty($newModuleList))
3342 //grab the existing system tabs
3343 $tabs = $newTB->get_system_tabs();
3345 //add the new tabs to the array
3346 foreach($newModuleList as $nm ){
3350 $newTB->set_system_tabs($tabs);
3352 logThis('module tabs updated',$path);
3358 * This method attempts to fix dropdown lists that were incorrectly named.
3359 * There were versions of SugarCRM that did not enforce naming convention rules
3360 * for the dropdown list field name. This method attempts to resolve that by
3361 * fixing the language files that may have been affected and then updating the
3362 * fields_meta_data table accordingly. It also refreshes any vardefs that may
3363 * have been affected.
3366 function fix_dropdown_list() {
3367 if(file_exists('custom/include/language')) {
3369 $affected_modules = array();
3370 $affected_keys = array();
3372 getFiles($files, 'custom/include/language', '/\.php$/i');
3373 foreach($files as $file) {
3375 if(file_exists($file . '.bak')) {
3376 $bak_mod_time = filemtime($file . '.bak');
3377 $php_mod_time = filemtime($file);
3378 //We're saying if the .php file was modified 30 seconds no more than php.bak file then we
3379 //run these additional cleanup checks
3380 if($php_mod_time - $bak_mod_time < 30) {
3382 $app_list_strings = array();
3383 $GLOBALS['app_list_strings'] = array();
3384 require($file . '.bak');
3385 $bak_app_list_strings = array_merge($app_list_strings, $GLOBALS['app_list_strings']);
3387 $app_list_strings = array();
3388 $GLOBALS['app_list_strings'] = array();
3390 $php_app_list_strings = array_merge($app_list_strings, $GLOBALS['app_list_strings']);
3392 //Get the file contents
3393 $contents = file_get_contents($file);
3395 //Now simulate a fix for the file before we compare w/ the .php file
3396 //we also append to the $contents
3397 foreach($bak_app_list_strings as $key=>$entry) {
3398 if(preg_match('/([^A-Za-z_])/', $key, $matches) && is_array($entry)) {
3399 $new_key = preg_replace('/[^A-Za-z_]/', '_', $key);
3400 $bak_app_list_strings[$new_key] = $bak_app_list_strings[$key];
3401 unset($bak_app_list_strings[$key]);
3402 //Now if the entry doesn't exists in the .php file, then add to contents
3403 if(!isset($php_app_list_strings[$new_key])) {
3404 $contents .= "\n\$GLOBALS['app_list_strings']['{$new_key}'] = " . var_export_helper($bak_app_list_strings[$new_key]) . ";";
3409 //Now load the .php file to do the comparison
3410 foreach($php_app_list_strings as $key=>$entry) {
3411 if(isset($bak_app_list_strings[$key])) {
3412 $diff = array_diff($bak_app_list_strings[$key], $entry);
3414 //There is a difference, so copy the $bak_app_list_strings version into the .php file
3415 $contents .= "\n\$GLOBALS['app_list_strings']['{$key}'] = " . var_export_helper($bak_app_list_strings[$key]) . ";";
3420 //Now write out the file contents
3421 //Create backup just in case
3422 copy($file, $file . '.php_bak');
3423 $fp = @sugar_fopen($file, 'w');
3425 fwrite($fp, $contents);
3428 $GLOBALS['log']->error("Unable to update file contents in fix_dropdown_list for {$file}");
3433 unset($GLOBALS['app_strings']);
3434 unset($GLOBALS['app_list_strings']);
3435 $app_list_strings = array();
3438 $contents = file_get_contents($file);
3439 if ( !isset($GLOBALS['app_list_strings']) ) {
3440 $GLOBALS['app_list_strings'] = $app_list_strings;
3443 $GLOBALS['app_list_strings'] = array_merge($app_list_strings, $GLOBALS['app_list_strings']);
3446 if(isset($GLOBALS['app_list_strings']) && is_array($GLOBALS['app_list_strings'])) {
3447 foreach($GLOBALS['app_list_strings'] as $key=>$entry) {
3448 if(preg_match('/([^A-Za-z_])/', $key, $matches) && is_array($entry)) {
3449 $result = $GLOBALS['db']->query("SELECT custom_module FROM fields_meta_data WHERE ext1 = '{$key}'");
3450 if(!empty($result)) {
3451 while($row = $GLOBALS['db']->fetchByAssoc($result)) {
3452 $custom_module = $row['custom_module'];
3453 if(!empty($GLOBALS['beanList'][$custom_module])) {
3454 $affected_modules[$custom_module] = $GLOBALS['beanList'][$custom_module];
3459 //Replace all invalid characters with '_' character
3460 $new_key = preg_replace('/[^A-Za-z_]/', '_', $key);
3461 $affected_keys[$key] = $new_key;
3463 $GLOBALS['app_list_strings'][$new_key] = $GLOBALS['app_list_strings'][$key];
3464 unset($GLOBALS['app_list_strings'][$key]);
3466 $pattern_match = "/(\[\s*\'{$key}\'\s*\])/";
3467 $new_key = "['{$new_key}']";
3468 $out = preg_replace($pattern_match, $new_key, $contents);
3474 //This is a check for g => h instances where the file contents were incorrectly written
3475 //and also fixes the scenario where via a UI upgrade, the app_list_strings were incorrectly
3476 //merged with app_list_strings variables declared elsewhere
3478 if(preg_match('/\$GLOBALS\s*\[\s*[\"|\']app_list_strings[\"|\']\s*\]\s*=\s*array\s*\(/', $contents)) {
3479 //Now also remove all the non-custom labels that were added
3480 if(preg_match('/language\/([^\.]+)\.lang\.php$/', $file, $matches)) {
3481 $language = $matches[1];
3483 $app_list_strings = array();
3485 if(file_exists("include/language/$language.lang.php")) {
3486 include("include/language/$language.lang.php");
3488 if(file_exists("include/language/$language.lang.override.php")) {
3489 $app_list_strings = _mergeCustomAppListStrings("include/language/$language.lang.override.php" , $app_list_strings) ;
3491 if(file_exists("custom/application/Ext/Language/$language.ext.lang.php")) {
3492 $app_list_strings = _mergeCustomAppListStrings("custom/application/Ext/Language/$language.ext.lang.php" , $app_list_strings) ;
3494 if(file_exists("custom/application/Ext/Language/$language.lang.ext.php")) {
3495 $app_list_strings = _mergeCustomAppListStrings("custom/application/Ext/Language/$language.lang.ext.php" , $app_list_strings) ;
3498 $all_non_custom_include_language_strings = $app_strings;
3499 $all_non_custom_include_language_list_strings = $app_list_strings;
3501 $unset_keys = array();
3502 if(!empty($GLOBALS['app_list_strings'])) {
3503 foreach($GLOBALS['app_list_strings'] as $key=>$value) {
3505 if(isset($all_non_custom_include_language_list_strings[$key])) {
3506 $diff = array_diff($all_non_custom_include_language_list_strings[$key], $GLOBALS['app_list_strings'][$key]);
3509 if(!empty($all_non_custom_include_language_list_strings[$key]) && empty($diff)) {
3510 $unset_keys[] = $key;
3515 foreach($unset_keys as $key) {
3516 unset($GLOBALS['app_list_strings'][$key]);
3519 if(!empty($GLOBALS['app_strings'])) {
3520 foreach($GLOBALS['app_strings'] as $key=>$value) {
3521 if(!empty($all_non_custom_include_language_strings[$key])) {
3522 unset($GLOBALS['app_strings'][$key]);
3526 } //if(preg_match...)
3529 if(!empty($GLOBALS['app_strings'])) {
3530 foreach($GLOBALS['app_strings'] as $key=>$entry) {
3531 $out .= "\n\$GLOBALS['app_strings']['$key']=" . var_export_helper($entry) . ";";
3535 foreach($GLOBALS['app_list_strings'] as $key=>$entry) {
3536 $out .= "\n\$GLOBALS['app_list_strings']['$key']=" . var_export_helper($entry) . ";";
3540 } //if(preg_match...)
3544 //Create a backup just in case
3545 copy($file, $file . '.bak');
3546 $fp = @sugar_fopen($file, 'w');
3551 //If we can't update the file, just return
3552 $GLOBALS['log']->error("Unable to update file contents in fix_dropdown_list.");
3560 //Update db entries (the order matters here... need to process database changes first)
3561 if(!empty($affected_keys)) {
3562 foreach($affected_keys as $old_key=>$new_key) {
3563 $GLOBALS['db']->query("UPDATE fields_meta_data SET ext1 = '{$new_key}' WHERE ext1 = '{$old_key}'");
3567 //Update vardef files for affected modules
3568 if(!empty($affected_modules)) {
3569 foreach($affected_modules as $module=>$object) {
3570 VardefManager::refreshVardefs($module, $object);
3577 function update_iframe_dashlets(){
3578 require_once(sugar_cached('dashlets/dashlets.php'));
3580 $db = DBManagerFactory::getInstance();
3581 $query = "SELECT id, contents, assigned_user_id FROM user_preferences WHERE deleted = 0 AND category = 'Home'";
3582 $result = $db->query($query, true, "Unable to update new default dashlets! ");
3583 while ($row = $db->fetchByAssoc($result)) {
3584 $content = unserialize(base64_decode($row['contents']));
3585 $assigned_user_id = $row['assigned_user_id'];
3586 $record_id = $row['id'];
3588 $current_user = new User();
3589 $current_user->retrieve($row['assigned_user_id']);
3591 if(!empty($content['dashlets']) && !empty($content['pages'])){
3592 $originalDashlets = $content['dashlets'];
3593 foreach($originalDashlets as $key => $ds){
3594 if(!empty($ds['options']['url']) && stristr($ds['options']['url'],'http://www.sugarcrm.com/crm/product/gopro')){
3595 unset($originalDashlets[$key]);
3598 $current_user->setPreference('dashlets', $originalDashlets, 0, 'Home');
3605 * convertImageToText
3607 * This method attempts to convert date type image to text on Microsoft SQL Server.
3608 * This method could NOT be used in any other type of datebases.
3610 function convertImageToText($table_name,$column_name){
3611 $set_lang = "SET LANGUAGE us_english";
3612 $GLOBALS['db']->query($set_lang);
3613 if($GLOBALS['db']->lastError()){
3614 logThis('An error occurred when performing this query-->'.$set_lang);
3616 $q="SELECT data_type
3617 FROM INFORMATION_SCHEMA.Tables T JOIN INFORMATION_SCHEMA.Columns C
3618 ON T.TABLE_NAME = C.TABLE_NAME where T.TABLE_NAME = '$table_name' and C.COLUMN_NAME = '$column_name'";
3619 $res= $GLOBALS['db']->query($q);
3620 if($GLOBALS['db']->lastError()){
3621 logThis('An error occurred when performing this query-->'.$q);
3623 $row= $GLOBALS['db']->fetchByAssoc($res);
3625 if(trim(strtolower($row['data_type'])) == 'image'){
3626 $addContent_temp = "alter table {$table_name} add {$column_name}_temp text null";
3627 $GLOBALS['db']->query($addContent_temp);
3628 if($GLOBALS['db']->lastError()){
3629 logThis('An error occurred when performing this query-->'.$addContent_temp);
3631 $qN = "select count=datalength({$column_name}), id, {$column_name} from {$table_name}";
3632 $result = $GLOBALS['db']->query($qN);
3633 while($row = $GLOBALS['db']->fetchByAssoc($result)){
3634 if($row['count'] >8000){
3635 $contentLength = $row['count'];
3638 $convertedContent = '';
3639 while($contentLength >0){
3640 $stepsQuery = "select cont=convert(varchar(max), convert(varbinary(8000), substring({$column_name},{$start},{$next}))) from {$table_name} where id= '{$row['id']}'";
3641 $steContQ = $GLOBALS['db']->query($stepsQuery);
3642 if($GLOBALS['db']->lastError()){
3643 logThis('An error occurred when performing this query-->'.$stepsQuery);
3645 $stepCont = $GLOBALS['db']->fetchByAssoc($steContQ);
3646 if(isset($stepCont['cont'])){
3647 $convertedContent = $convertedContent.$stepCont['cont'];
3649 $start = $start+$next;
3650 $contentLength = $contentLength - $next;
3652 $addContentDataText="update {$table_name} set {$column_name}_temp = '{$convertedContent}' where id= '{$row['id']}'";
3653 $GLOBALS['db']->query($addContentDataText);
3654 if($GLOBALS['db']->lastError()){
3655 logThis('An error occurred when performing this query-->'.$addContentDataText);
3659 $addContentDataText="update {$table_name} set {$column_name}_temp =
3660 convert(varchar(max), convert(varbinary(8000), {$column_name})) where id= '{$row['id']}'";
3661 $GLOBALS['db']->query($addContentDataText);
3662 if($GLOBALS['db']->lastError()){
3663 logThis('An error occurred when performing this query-->'.$addContentDataText);
3667 //drop the contents now and change contents_temp to contents
3668 $dropColumn = "alter table {$table_name} drop column {$column_name}";
3669 $GLOBALS['db']->query($dropColumn);
3670 if($GLOBALS['db']->lastError()){
3671 logThis('An error occurred when performing this query-->'.$dropColumn);
3673 $changeColumnName = "EXEC sp_rename '{$table_name}.[{$column_name}_temp]','{$column_name}','COLUMN'";
3674 $GLOBALS['db']->query($changeColumnName);
3675 if($GLOBALS['db']->lastError()){
3676 logThis('An error occurred when performing this query-->'.$changeColumnName);
3683 * This method attempts to delete all English inline help files.
3684 * This method was introduced by 5.5.0RC2.
3686 function clearHelpFiles(){
3687 $modulePath = clean_path(getcwd() . '/modules');
3688 $allHelpFiles = array();
3689 getFiles($allHelpFiles, $modulePath, "/en_us.help.*/");
3691 foreach( $allHelpFiles as $the_file ){
3692 if( is_file( $the_file ) ){
3693 unlink( $the_file );
3694 logThis("Deleted file: $the_file");
3702 * upgradeDateTimeFields
3704 * This method came from bug: 39757 where the date_end field is a date field and not a datetime field
3705 * which prevents you from performing timezone offset calculations once the data has been saved.
3707 * @param path String location to log file, empty by default
3709 function upgradeDateTimeFields($path)
3713 $meetingsSql = "UPDATE meetings SET date_end = ".$db->convert("date_start", 'add_time', array('duration_hours', 'duration_minutes'));
3714 $callsSql = "UPDATE calls SET date_end = ".$db->convert("date_start", 'add_time', array('duration_hours', 'duration_minutes'));
3715 logThis('upgradeDateTimeFields Meetings SQL:' . $meetingsSql, $path);
3716 $db->query($meetingsSql);
3718 logThis('upgradeDateTimeFields Calls SQL:' . $callsSql, $path);
3719 $db->query($callsSql);
3723 * upgradeDocumentTypeFields
3726 function upgradeDocumentTypeFields($path){
3730 $documentsSql = "UPDATE documents SET doc_type = 'Sugar' WHERE doc_type IS NULL";
3731 $meetingsSql = "UPDATE meetings SET type = 'Sugar' WHERE type IS NULL";
3733 logThis('upgradeDocumentTypeFields Documents SQL:' . $documentsSql, $path);
3734 $db->query($documentsSql);
3735 logThis('upgradeDocumentTypeFields Meetings SQL:' . $meetingsSql, $path);
3736 $db->query($meetingsSql);
3741 * merge_config_si_settings
3742 * This method checks for the presence of a config_si.php file and, if found, merges the configuration
3743 * settings from the config_si.php file into config.php. If a config_si_location parameter value is not
3744 * supplied it will attempt to discover the config_si.php file location from where the executing script
3747 * @param write_to_upgrade_log boolean optional value to write to the upgradeWizard.log file
3748 * @param config_location String optional value to config.php file location
3749 * @param config_si_location String optional value to config_si.php file location
3750 * @param path String file of the location of log file to write to
3751 * @return boolean value indicating whether or not a merge was attempted with config_si.php file
3753 function merge_config_si_settings($write_to_upgrade_log=false, $config_location='', $config_si_location='', $path='')
3755 if(!empty($config_location) && !file_exists($config_location))
3757 if($write_to_upgrade_log)
3759 logThis('config.php file specified in ' . $config_si_location . ' could not be found. Skip merging', $path);
3762 } else if(empty($config_location)) {
3764 //We are assuming this is from the silentUpgrade scripts so argv[3] will point to SugarCRM install location
3765 if(isset($argv[3]) && is_dir($argv[3]))
3767 $config_location = $argv[3] . DIRECTORY_SEPARATOR . 'config.php';
3771 //If config_location is still empty or if the file cannot be found, skip merging
3772 if(empty($config_location) || !file_exists($config_location))
3774 if($write_to_upgrade_log)
3776 logThis('config.php file at (' . $config_location . ') could not be found. Skip merging.', $path);
3780 if($write_to_upgrade_log)
3782 logThis('Loading config.php file at (' . $config_location . ') for merging.', $path);
3785 include($config_location);
3786 if(empty($sugar_config))
3788 if($write_to_upgrade_log)
3790 logThis('config.php contents are empty. Skip merging.', $path);
3796 if(!empty($config_si_location) && !file_exists($config_si_location))
3798 if($write_to_upgrade_log)
3800 logThis('config_si.php file specified in ' . $config_si_location . ' could not be found. Skip merging', $path);
3803 } else if(empty($config_si_location)) {
3804 if(isset($argv[0]) && is_file($argv[0]))
3806 $php_file = $argv[0];
3807 $p_info = pathinfo($php_file);
3808 $php_dir = (isset($p_info['dirname']) && $p_info['dirname'] != '.') ? $p_info['dirname'] . DIRECTORY_SEPARATOR : '';
3809 $config_si_location = $php_dir . 'config_si.php';
3813 //If config_si_location is still empty or if the file cannot be found, skip merging
3814 if(empty($config_si_location) || !file_exists($config_si_location))
3816 if($write_to_upgrade_log)
3818 logThis('config_si.php file at (' . $config_si_location . ') could not be found. Skip merging.', $path);
3822 if($write_to_upgrade_log)
3824 logThis('Loading config_si.php file at (' . $config_si_location . ') for merging.', $path);
3827 include($config_si_location);
3828 if(empty($sugar_config_si))
3830 if($write_to_upgrade_log)
3832 logThis('config_si.php contents are empty. Skip merging.', $path);
3838 //Now perform the merge operation
3840 foreach($sugar_config_si as $key=>$value)
3842 if(!preg_match('/^setup_/', $key) && !isset($sugar_config[$key]))
3844 if($write_to_upgrade_log)
3846 logThis('Merge key (' . $key . ') with value (' . $value . ')', $path);
3848 $sugar_config[$key] = $value;
3855 if($write_to_upgrade_log)
3857 logThis('Update config.php file with new values', $path);
3860 if(!write_array_to_file("sugar_config", $sugar_config, $config_location)) {
3861 if($write_to_upgrade_log)
3863 logThis('*** ERROR: could not write to config.php', $path);
3868 if($write_to_upgrade_log)
3870 logThis('config.php values are in sync with config_si.php values. Skipped merging.');
3875 if($write_to_upgrade_log)
3877 logThis('End merge_config_si_settings', $path);
3884 * upgrade_connectors
3885 * This function handles support for upgrading connectors, in particular the Hoovers connector
3886 * that needs the wsdl and endpoint modifications in the config.php file as well as the search
3887 * term change (from bal.specialtyCriteria.companyKeyword to bal.specialtyCriteria.companyName).
3888 * @param $path String variable for the log path
3890 function upgrade_connectors($path='') {
3891 logThis('Begin upgrade_connectors', $path);
3893 $filePath = 'custom/modules/Connectors/connectors/sources/ext/soap/hoovers/config.php';
3894 if(file_exists($filePath))
3896 logThis("{$filePath} file", $path);
3898 if(!is_null($config))
3901 if(isset($config['properties']['hoovers_endpoint']))
3903 $config['properties']['hoovers_endpoint'] = 'http://hapi.hoovers.com/HooversAPI-33';
3907 if(isset($config['properties']['hoovers_wsdl']))
3909 $config['properties']['hoovers_wsdl'] = 'http://hapi.hoovers.com/HooversAPI-33/hooversAPI/hooversAPI.wsdl';
3915 if(!write_array_to_file('config', $config, $filePath)) {
3916 logThis("Could not write new configuration to {$filePath} file", $path);
3918 logThis('Modified file successfully with new configuration entries', $path);
3924 $filePath = 'custom/modules/Connectors/connectors/sources/ext/soap/hoovers/vardefs.php';
3925 if(file_exists($filePath))
3927 logThis("Modifying {$filePath} file", $path);
3929 $fileContents = file_get_contents($filePath);
3930 $out = str_replace('bal.specialtyCriteria.companyKeyword', 'bal.specialtyCriteria.companyName', $fileContents);
3931 file_put_contents($filePath, $out);
3934 logThis('End upgrade_connectors', $path);
3938 * Enable the InsideView connector for the four default modules.
3940 function upgradeEnableInsideViewConnector($path='')
3942 logThis('Begin upgradeEnableInsideViewConnector', $path);
3944 // Load up the existing mapping and hand it to the InsideView connector to have it setup the correct logic hooks
3945 $mapFile = 'modules/Connectors/connectors/sources/ext/rest/insideview/mapping.php';
3946 if ( file_exists('custom/'.$mapFile) ) {
3947 logThis('Found CUSTOM mappings', $path);
3948 require('custom/'.$mapFile);
3950 logThis('Used default mapping', $path);
3954 require_once('include/connectors/sources/SourceFactory.php');
3955 $source = SourceFactory::getSource('ext_rest_insideview');
3957 // $mapping is brought in from the mapping.php file above
3958 $source->saveMappingHook($mapping);
3960 require_once('include/connectors/utils/ConnectorUtils.php');
3961 ConnectorUtils::installSource('ext_rest_insideview');
3963 // Now time to set the various modules to active, because this part ignores the default config
3964 require(CONNECTOR_DISPLAY_CONFIG_FILE);
3965 // $modules_sources come from that config file
3966 foreach ( $source->allowedModuleList as $module ) {
3967 $modules_sources[$module]['ext_rest_insideview'] = 'ext_rest_insideview';
3969 if(!write_array_to_file('modules_sources', $modules_sources, CONNECTOR_DISPLAY_CONFIG_FILE)) {
3970 //Log error and return empty array
3971 logThis("Cannot write \$modules_sources to " . CONNECTOR_DISPLAY_CONFIG_FILE,$path);
3974 logThis('End upgradeEnableInsideViewConnector', $path);
3978 function repair_long_relationship_names($path='')
3980 logThis("Begin repair_long_relationship_names", $path);
3981 require_once 'modules/ModuleBuilder/parsers/relationships/DeployedRelationships.php' ;
3982 $GLOBALS['mi_remove_tables'] = false;
3984 foreach($GLOBALS['moduleList'] as $module)
3986 $relationships = new DeployedRelationships ($module) ;
3987 foreach($relationships->getRelationshipList() as $rel_name)
3989 if (strlen($rel_name) > 27 && empty($touched[$rel_name]))
3991 logThis("Rebuilding relationship fields for $rel_name", $path);
3992 $touched[$rel_name] = true;
3993 $rel_obj = $relationships->get($rel_name);
3994 $rel_obj->setReadonly(false);
3995 $relationships->delete($rel_name);
3996 $relationships->save();
3997 $relationships->add($rel_obj);
3998 $relationships->save();
3999 $relationships->build () ;
4003 logThis("End repair_long_relationship_names", $path);
4006 function removeSilentUpgradeVarsCache(){
4007 global $silent_upgrade_vars_loaded;
4009 $cacheFileDir = "{$GLOBALS['sugar_config']['cache_dir']}/silentUpgrader";
4010 $cacheFile = "{$cacheFileDir}/silentUpgradeCache.php";
4012 if(file_exists($cacheFile)){
4016 $silent_upgrade_vars_loaded = array(); // Set to empty to reset it
4021 function loadSilentUpgradeVars(){
4022 global $silent_upgrade_vars_loaded;
4024 if(empty($silent_upgrade_vars_loaded)){
4025 $cacheFile = "{$GLOBALS['sugar_config']['cache_dir']}/silentUpgrader/silentUpgradeCache.php";
4026 // We have no pre existing vars
4027 if(!file_exists($cacheFile)){
4028 // Set the vars array so it's loaded
4029 $silent_upgrade_vars_loaded = array('vars' => array());
4032 require_once($cacheFile);
4033 $silent_upgrade_vars_loaded = $silent_upgrade_vars_cache;
4040 function writeSilentUpgradeVars(){
4041 global $silent_upgrade_vars_loaded;
4043 if(empty($silent_upgrade_vars_loaded)){
4044 return false; // You should have set some values before trying to write the silent upgrade vars
4047 $cacheFileDir = "{$GLOBALS['sugar_config']['cache_dir']}/silentUpgrader";
4048 $cacheFile = "{$cacheFileDir}/silentUpgradeCache.php";
4050 require_once('include/dir_inc.php');
4051 if(!mkdir_recursive($cacheFileDir)){
4054 require_once('include/utils/file_utils.php');
4055 if(!write_array_to_file('silent_upgrade_vars_cache', $silent_upgrade_vars_loaded, $cacheFile, 'w')){
4057 logThis("WARNING: writeSilentUpgradeVars could not write to {$cacheFile}", $path);
4064 function setSilentUpgradeVar($var, $value){
4065 if(!loadSilentUpgradeVars()){
4069 global $silent_upgrade_vars_loaded;
4071 $silent_upgrade_vars_loaded['vars'][$var] = $value;
4076 function getSilentUpgradeVar($var){
4077 if(!loadSilentUpgradeVars()){
4081 global $silent_upgrade_vars_loaded;
4083 if(!isset($silent_upgrade_vars_loaded['vars'][$var])){
4087 return $silent_upgrade_vars_loaded['vars'][$var];
4093 * add_unified_search_to_custom_modules_vardefs
4095 * This method calls the repair code to remove the unified_search_modules.php fiel
4098 function add_unified_search_to_custom_modules_vardefs()
4100 if(file_exists($cachefile = sugar_cached('modules/unified_search_modules.php')))
4108 * change from using the older SugarCache in 6.1 and below to the new one in 6.2
4110 function upgradeSugarCache($file)
4112 global $sugar_config;
4113 $cacheUploadUpgradesTemp = mk_temp_dir(sugar_cached('upgrades/temp'));
4115 unzip($file, $cacheUploadUpgradesTemp);
4117 if(!file_exists(clean_path("{$cacheUploadUpgradesTemp}/manifest.php"))) {
4118 logThis("*** ERROR: no manifest file detected while bootstraping upgrade wizard files!");
4121 include(clean_path("{$cacheUploadUpgradesTemp}/manifest.php"));
4124 $from_dir = "{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}";
4125 $allFiles = array();
4126 if(file_exists("$from_dir/include/SugarCache")) {
4127 $allFiles = findAllFiles("$from_dir/include/SugarCache", $allFiles);
4129 if(file_exists("$from_dir/include/database")) {
4130 $allFiles = findAllFiles("$from_dir/include/database", $allFiles);
4132 if(file_exists("$from_dir/include/utils/external_cache.php")) {
4133 $allFiles[] = "$from_dir/include/utils/external_cache.php";
4135 if(file_exists("$from_dir/include/utils/sugar_file_utils.php")) {
4136 $allFiles[] = "$from_dir/include/utils/sugar_file_utils.php";
4138 if(file_exists("$from_dir/include/utils/sugar_file_utils.php")) {
4139 $allFiles[] = "$from_dir/include/utils/sugar_file_utils.php";
4142 foreach($allFiles as $k => $file) {
4143 $destFile = str_replace($from_dir."/", "", $file);
4144 if(!is_dir(dirname($destFile))) {
4145 mkdir_recursive(dirname($destFile)); // make sure the directory exists
4147 if ( stristr($file,'uw_main.tpl') )
4148 logThis('Skipping "'.$file.'" - file copy will during commit step.');
4150 logThis('updating UpgradeWizard code: '.$destFile);
4151 copy_recursive($file, $destFile);
4158 * upgradeDisplayedTabsAndSubpanels
4160 * @param $version String value of current system version (pre upgrade)
4162 function upgradeDisplayedTabsAndSubpanels($version)
4164 if($version < '620')
4166 logThis('start upgrading system displayed tabs and subpanels');
4167 require_once('modules/MySettings/TabController.php');
4168 $tc = new TabController();
4170 //grab the existing system tabs
4171 $tabs = $tc->get_tabs_system();
4173 //add Calls, Meetings, Tasks, Notes, Prospects (Targets) and ProspectLists (Target Lists)
4174 //to displayed tabs unless explicitly set to hidden
4175 $modules_to_add = array('Calls', 'Meetings', 'Tasks', 'Notes', 'Prospects', 'ProspectLists');
4176 $added_tabs = array();
4178 foreach($modules_to_add as $module)
4180 $tabs[0][$module] = $module;
4181 $added_tabs[] = $module;
4184 logThis('calling set_system_tabs on TabController to add tabs: ' . var_export($added_tabs, true));
4185 $tc->set_system_tabs($tabs[0]);
4186 logThis('finish upgrading system displayed tabs and subpanels');
4192 * unlinkUpgradeFiles
4193 * This is a helper function to clean up
4195 * @param $version String value of current system version (pre upgrade)
4197 function unlinkUpgradeFiles($version)
4199 if(!isset($version))
4204 //First check if we even have the scripts_for_patch/files_to_remove directory
4205 require_once('modules/UpgradeWizard/UpgradeRemoval.php');
4208 if(empty($_SESSION['unzip_dir']))
4210 global $sugar_config;
4211 $base_upgrade_dir = $sugar_config['upload_dir'] . "/upgrades";
4212 $base_tmp_upgrade_dir = "$base_upgrade_dir/temp";
4213 $_SESSION['unzip_dir'] = mk_temp_dir( $base_tmp_upgrade_dir );
4217 if(isset($_SESSION['unzip_dir']) && file_exists($_SESSION['unzip_dir'].'/scripts/files_to_remove'))
4219 $files_to_remove = glob($_SESSION['unzip_dir'].'/scripts/files_to_remove/*.php');
4221 foreach($files_to_remove as $script)
4223 if(preg_match('/UpgradeRemoval(\d+)x\.php/', $script, $matches))
4225 $checkVersion = $matches[1] + 1; //Increment by one to check everything equal or below the target version
4226 $upgradeClass = 'UpgradeRemoval' . $matches[1] . 'x';
4227 require_once($_SESSION['unzip_dir'].'/scripts/files_to_remove/' . $upgradeClass . '.php');
4229 //Check to make sure we should load and run this UpgradeRemoval instance
4230 if($checkVersion <= $version && class_exists($upgradeClass))
4232 $upgradeInstance = new $upgradeClass();
4233 if($upgradeInstance instanceof UpgradeRemoval)
4235 logThis('Running UpgradeRemoval instance ' . $upgradeClass);
4236 logThis('Files will be backed up to custom/backup');
4237 $files = $upgradeInstance->getFilesToRemove($version);
4238 foreach($files as $file)
4242 $upgradeInstance->processFilesToRemove($files);
4249 //Check if we have a custom directory
4250 if(file_exists('custom/scripts/files_to_remove'))
4253 $files_to_remove = glob('custom/scripts/files_to_remove/*.php');
4255 foreach($files_to_remove as $script)
4257 if(preg_match('/\/files_to_remove\/(.*?)\.php$/', $script, $matches))
4259 require_once($script);
4260 $upgradeClass = $matches[1];
4262 if(!class_exists($upgradeClass))
4267 $upgradeInstance = new $upgradeClass();
4268 if($upgradeInstance instanceof UpgradeRemoval)
4270 logThis('Running Custom UpgradeRemoval instance ' . $upgradeClass);
4271 $files = $upgradeInstance->getFilesToRemove($version);
4272 foreach($files as $file)
4276 $upgradeInstance->processFilesToRemove($files);
4284 if (!function_exists("getValidDBName"))
4287 * Return a version of $proposed that can be used as a column name in any of our supported databases
4288 * 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)
4289 * @param string $name Proposed name for the column
4290 * @param string $ensureUnique
4291 * @return string Valid column name trimmed to right length and with invalid characters removed
4293 function getValidDBName ($name, $ensureUnique = false, $maxLen = 30)
4295 // first strip any invalid characters - all but alphanumerics and -
4296 $name = preg_replace ( '/[^\w-]+/i', '', $name ) ;
4297 $len = strlen ( $name ) ;
4301 $md5str = md5($name);
4302 $tail = substr ( $name, -11) ;
4303 $temp = substr($md5str , strlen($md5str)-4 );
4304 $result = substr ( $name, 0, 10) . $temp . $tail ;
4305 }else if ($len > ($maxLen - 5))
4307 $result = substr ( $name, 0, 11) . substr ( $name, 11 - $maxLen + 5);
4309 return strtolower ( $result ) ;
4316 * Get UW directories
4317 * Provides compatibility with both 6.3 and pre-6.3 setup
4319 function getUWDirs()
4321 if(!class_exists('UploadStream')) {
4322 // we're still running the old code
4323 global $sugar_config;
4324 return array($sugar_config['upload_dir'] . "/upgrades", $sugar_config['cache_dir'] . "upload/upgrades/temp");
4326 if(!in_array("upload", stream_get_wrappers())) {
4327 UploadStream::register(); // just in case file was copied, but not run
4329 return array("upload://upgrades", sugar_cached("upgrades/temp"));
4334 * Whether directory exists within list of directories to skip
4335 * @param string $dir dir to be checked
4336 * @param array $skipDirs list with skipped dirs
4339 function whetherNeedToSkipDir($dir, $skipDirs)
4341 foreach($skipDirs as $skipMe) {
4342 if(strpos( clean_path($dir), $skipMe ) !== false) {
4352 * @param silentUpgrade boolean flag indicating whether or not we should treat running the SugarSpriteBuilder as an upgrade operation
4355 function rebuildSprites($fromUpgrade=true)
4357 require_once('modules/Administration/SugarSpriteBuilder.php');
4358 $sb = new SugarSpriteBuilder();
4359 $sb->cssMinify = true;
4360 $sb->fromSilentUpgrade = $fromUpgrade;
4361 $sb->silentRun = $fromUpgrade;
4363 // add common image directories
4364 $sb->addDirectory('default', 'include/images');
4365 $sb->addDirectory('default', 'themes/default/images');
4366 $sb->addDirectory('default', 'themes/default/images/SugarLogic');
4368 // add all theme image directories
4369 if($dh = opendir('themes'))
4371 while (($dir = readdir($dh)) !== false)
4373 if ($dir != "." && $dir != ".." && $dir != 'default' && is_dir('themes/'.$dir)) {
4374 $sb->addDirectory($dir, "themes/{$dir}/images");
4380 // generate the sprite goodies
4381 // everything is saved into cache/sprites
4382 $sb->createSprites();