2 if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
3 /*********************************************************************************
4 * SugarCRM Community Edition is a customer relationship management program developed by
5 * SugarCRM, Inc. Copyright (C) 2004-2011 SugarCRM Inc.
7 * This program is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU Affero General Public License version 3 as published by the
9 * Free Software Foundation with the addition of the following permission added
10 * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
11 * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
12 * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
19 * You should have received a copy of the GNU Affero General Public License along with
20 * this program; if not, see http://www.gnu.org/licenses or write to the Free
21 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24 * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
25 * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
27 * The interactive user interfaces in modified source and object code versions
28 * of this program must display Appropriate Legal Notices, as required under
29 * Section 5 of the GNU Affero General Public License version 3.
31 * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
32 * these Appropriate Legal Notices must retain the display of the "Powered by
33 * SugarCRM" logo. If the display of the logo is not reasonably feasible for
34 * technical reasons, the Appropriate Legal Notices must display the words
35 * "Powered by SugarCRM".
36 ********************************************************************************/
42 * Backs-up files that are targeted for patch/upgrade to a restore directory
43 * @param string rest_dir Full path to the directory containing the original, replaced files.
44 * @param string install_file Full path to the uploaded patch/upgrade zip file
45 * @param string unzip_dir Full path to the unzipped files in a temporary directory
46 * @param string zip_from_dir Name of directory that the unzipped files containing the actuall replacement files
47 * @param array errors Collection of errors to be displayed at end of process
48 * @param string path Optional full path to the log file.
49 * @return array errors
51 function commitMakeBackupFiles($rest_dir, $install_file, $unzip_dir, $zip_from_dir, $errors, $path='') {
53 // create restore file directory
54 mkdir_recursive($rest_dir);
56 if(file_exists($rest_dir) && is_dir($rest_dir)){
57 logThis('backing up files to be overwritten...', $path);
58 $newFiles = findAllFiles(clean_path($unzip_dir . '/' . $zip_from_dir), array());
60 // keep this around for canceling
61 $_SESSION['uw_restore_dir'] = clean_path($rest_dir);
63 foreach ($newFiles as $file) {
64 if (strpos($file, 'md5'))
67 // get name of current file to place in restore directory
68 $cleanFile = str_replace(clean_path($unzip_dir . '/' . $zip_from_dir), '', $file);
70 // make sure the directory exists
71 $cleanDir = $rest_dir . '/' . dirname($cleanFile);
72 if (!is_dir($cleanDir)) {
73 mkdir_recursive($cleanDir);
76 $oldFile = clean_path(getcwd() . '/' . $cleanFile);
78 // only copy restore files for replacements - ignore new files from patch
79 if (is_file($oldFile)) {
80 if (is_writable($rest_dir)) {
81 logThis('Backing up file: ' . $oldFile, $path);
82 if (!copy($oldFile, $rest_dir . '/' . $cleanFile)) {
83 logThis('*** ERROR: could not backup file: ' . $oldFile, $path);
84 $errors[] = "{$mod_strings['LBL_UW_BACKUP']}::{$mod_strings['ERR_UW_FILE_NOT_COPIED']}: {$oldFile}";
86 $backupFilesExist = true;
90 logThis('*** ERROR: directory not writable: ' . $rest_dir, $path);
91 $errors[] = "{$mod_strings['LBL_UW_BACKUP']}::{$mod_strings['ERR_UW_DIR_NOT_WRITABLE']}: {$oldFile}";
96 logThis('file backup done.', $path);
101 * Copies files from the unzipped patch to the destination.
102 * @param string unzip_dir Full path to the temporary directory created during unzip operation.
103 * @param string zip_from_dir Name of folder containing the unzipped files; usually the name of the Patch without the
105 * @param string path Optional full path to alternate upgradeWizard log file.
106 * @return array Two element array containing to $copiedFiles and $skippedFiles.
111 function commitCopyNewFiles($unzip_dir, $zip_from_dir, $path='') {
112 logThis('Starting file copy process...', $path);
113 global $sugar_version;
115 if(substr($sugar_version,0,1) >= 5){
116 $modules = getAllModules();
117 $backwardModules = array();
118 foreach($modules as $mod){
119 if(is_dir(clean_path(getcwd().'/modules/'.$mod.'/.500'))){
121 $files= findAllFiles(clean_path(getcwd().'/modules/'.$mod.'/.500'),$files);
122 if(sizeof($files) >0){
123 //backward compatibility is on
124 $backwardModules[] = $mod;
130 $newFiles = findAllFiles(clean_path($unzip_dir . '/' . $zip_from_dir), array());
131 $zipPath = clean_path($unzip_dir . '/' . $zip_from_dir);
133 // handle special do-not-overwrite conditions
134 $doNotOverwrite = array();
135 $doNotOverwrite[] = '__stub';
136 if(isset($_REQUEST['overwrite_files_serial'])) {
137 $doNotOverwrite = explode('::', $_REQUEST['overwrite_files_serial']);
140 $copiedFiles = array();
141 $skippedFiles = array();
143 foreach($newFiles as $file) {
144 $cleanFile = str_replace($zipPath, '', $file);
145 $srcFile = $zipPath . $cleanFile;
146 $targetFile = clean_path(getcwd() . '/' . $cleanFile);
147 if($backwardModules != null && sizeof($backwardModules) >0){
148 foreach($backwardModules as $mod){
149 $splitPath = explode('/',trim($cleanFile));
150 if('modules' == trim($splitPath[1]) && $mod == trim($splitPath[2])){
151 $cleanFile = str_replace('/modules/'.$mod, '/modules/'.$mod.'/.500', $cleanFile);
152 $targetFile = clean_path(getcwd() . '/' . $cleanFile);
156 if(!is_dir(dirname($targetFile))) {
157 mkdir_recursive(dirname($targetFile)); // make sure the directory exists
160 if((!file_exists($targetFile)) || /* brand new file */
161 (!in_array($targetFile, $doNotOverwrite)) /* manual diff file */
163 // handle sugar_version.php
164 if(strpos($targetFile, 'sugar_version.php') !== false && !preg_match('/\/portal\/sugar_version\.php$/i', $targetFile)) {
165 logThis('Skipping "sugar_version.php" - file copy will occur at end of successful upgrade', $path);
166 $_SESSION['sugar_version_file'] = $srcFile;
170 //logThis('Copying file to destination: ' . $targetFile, $path);
172 if(!copy($srcFile, $targetFile)) {
173 logThis('*** ERROR: could not copy file: ' . $targetFile, $path);
175 $copiedFiles[] = $targetFile;
178 //logThis('Skipping file: ' . $targetFile, $path);
179 $skippedFiles[] = $targetFile;
182 logThis('File copy done.', $path);
185 $ret['copiedFiles'] = $copiedFiles;
186 $ret['skippedFiles'] = $skippedFiles;
192 //On cancel put back the copied files from 500 to 451 state
193 function copyFilesOnCancel($step){
194 //place hoder for cancel action
199 function removeFileFromPath($file,$path, $deleteNot=array()){
201 $cur = $path . '/' . $file;
202 if(file_exists($cur)){
204 foreach($deleteNot as $dn){
214 if(!file_exists($path))return $removed;
216 while($e = $d->read()){
217 $next = $path . '/'. $e;
218 if(substr($e, 0, 1) != '.' && is_dir($next)){
219 $removed += removeFileFromPath($file, $next, $deleteNot);
226 * This function copies/overwrites between directories
228 * @param string the directory name to remove
229 * @param boolean whether to just empty the given directory, without deleting the given directory.
230 * @return boolean True/False whether the directory was deleted.
233 function copyRecursiveBetweenDirectories($from,$to){
234 if(file_exists($from)){
235 $modifiedFiles = array();
236 $modifiedFiles = findAllFiles(clean_path($from), $modifiedFiles);
237 $cwd = clean_path(getcwd());
238 foreach($modifiedFiles as $file) {
239 $srcFile = clean_path($file);
240 //$targetFile = clean_path(getcwd() . '/' . $srcFile);
241 if (strpos($srcFile,".svn") !== false) {
245 $targetFile = str_replace($from, $to, $srcFile);
247 if(!is_dir(dirname($targetFile))) {
248 mkdir_recursive(dirname($targetFile)); // make sure the directory exists
251 // handle sugar_version.php
252 if(strpos($targetFile, 'sugar_version.php') !== false && !preg_match('/\/portal\/sugar_version\.php$/i', $targetFile)) {
253 logThis('Skipping "sugar_version.php" - file copy will occur at end of successful upgrade', $path);
254 $_SESSION['sugar_version_file'] = $srcFile;
258 //logThis('Copying file to destination: ' . $targetFile);
260 if(!copy($srcFile, $targetFile)) {
261 logThis('*** ERROR: could not copy file: ' . $targetFile);
263 //logThis('Copied file: ' . $targetFile);
264 //$copiedFiles[] = $targetFile;
272 function deleteDirectory($dirname,$only_empty=false) {
273 if (!is_dir($dirname))
275 $dscan = array(realpath($dirname));
277 while (!empty($dscan)) {
278 $dcur = array_pop($dscan);
280 if ($d=opendir($dcur)) {
281 while ($f=readdir($d)) {
282 if ($f=='.' || $f=='..')
293 $i_until = ($only_empty)? 1 : 0;
294 for ($i=count($darr)-1; $i>=$i_until; $i--) {
295 //echo "\nDeleting '".$darr[$i]."' ... ";
296 if (rmdir($darr[$i]))
297 logThis('Success :Copying file to destination: ' . $darr[$i]);
299 logThis('Copy problem:Copying file to destination: ' . $darr[$i]);
301 return (($only_empty)? (count(scandir)<=2) : (!is_dir($dirname)));
304 * Get all the customized modules. Compare the file md5s with the base md5s
305 * If a file has been modified then put the module in the list of customized
306 * modules. Show the list in the preflight check UI.
309 function deleteAndOverWriteSelectedFiles($unzip_dir, $zip_from_dir,$delete_dirs){
310 if($delete_dirs != null){
311 foreach($delete_dirs as $del_dir){
312 deleteDirectory($del_dir);
313 $newFiles = findAllFiles(clean_path($unzip_dir . '/' . $zip_from_dir.'/'.$del_dir), array());
314 $zipPath = clean_path($unzip_dir . '/' . $zip_from_dir.'/'.$del_dir);
315 $copiedFiles = array();
316 $skippedFiles = array();
318 foreach($newFiles as $file) {
319 $cleanFile = str_replace($zipPath, '', $file);
320 $srcFile = $zipPath . $cleanFile;
321 $targetFile = clean_path(getcwd() . '/' . $cleanFile);
323 if(!is_dir(dirname($targetFile))) {
324 mkdir_recursive(dirname($targetFile)); // make sure the directory exists
327 if(!file_exists($targetFile)){
328 // handle sugar_version.php
329 if(strpos($targetFile, 'sugar_version.php') !== false) {
330 logThis('Skipping sugar_version.php - file copy will occur at end of successful upgrade');
331 $_SESSION['sugar_version_file'] = $srcFile;
335 //logThis('Copying file to destination: ' . $targetFile);
337 if(!copy($srcFile, $targetFile)) {
338 logThis('*** ERROR: could not copy file: ' . $targetFile);
340 $copiedFiles[] = $targetFile;
343 //logThis('Skipping file: ' . $targetFile);
344 $skippedFiles[] = $targetFile;
350 $ret['copiedFiles'] = $copiedFiles;
351 $ret['skippedFiles'] = $skippedFiles;
356 //Default is empty the directory. For removing set it to false
357 // to use this function to totally remove a directory, write:
358 // recursive_remove_directory('path/to/directory/to/delete',FALSE);
360 // to use this function to empty a directory, write:
361 // recursive_remove_directory('path/to/full_directory');
363 function recursive_empty_or_remove_directory($directory, $exclude_dirs=null,$exclude_files=null,$empty=TRUE)
365 // if the path has a slash at the end we remove it here
366 if(substr($directory,-1) == '/')
368 $directory = substr($directory,0,-1);
371 // if the path is not valid or is not a directory ...
372 if(!file_exists($directory) || !is_dir($directory))
374 // ... we return false and exit the function
377 // ... if the path is not readable
378 }elseif(!is_readable($directory))
380 // ... we return false and exit the function
383 // ... else if the path is readable
386 // we open the directory
387 $handle = opendir($directory);
389 // and scan through the items inside
390 while (FALSE !== ($item = readdir($handle)))
392 // if the filepointer is not the current directory
393 // or the parent directory
394 if($item != '.' && $item != '..')
396 // we build the new path to delete
397 $path = $directory.'/'.$item;
399 // if the new path is a directory
400 //add another check if the dir is in the list to exclude delete
401 if(is_dir($path) && $exclude_dirs != null && in_array($path,$exclude_dirs)){
404 else if(is_dir($path))
406 // we call this function with the new path
407 recursive_empty_or_remove_directory($path);
409 // if the new path is a file
411 // we remove the file
412 if($exclude_files != null && in_array($path,$exclude_files)){
421 // close the directory
424 // if the option to empty is not set to true
427 // try to delete the now empty directory
428 if(!rmdir($directory))
430 // return false if not possible
438 // ------------------------------------------------------------
443 function getAllCustomizedModules() {
445 require_once('files.md5');
447 $return_array = array();
448 $modules = getAllModules();
449 foreach($modules as $mod) {
450 //find all files in each module if the files have been modified
451 //as compared to the base version then add the module to the
452 //customized modules array
453 $modFiles = findAllFiles(clean_path(getcwd())."/modules/$mod", array());
454 foreach($modFiles as $file){
455 $fileContents = file_get_contents($file);
456 $file = str_replace(clean_path(getcwd()),'',$file);
457 if($md5_string['./' . $file]){
458 if(md5($fileContents) != $md5_string['./' . $file]) {
459 //A file has been customized in the module. Put the module into the
460 // customized modules array.
461 echo 'Changed File'.$file;
467 // This is a new file in user's version and indicates that module has been
468 //customized. Put the module in the customized array.
469 echo 'New File'.$file;
476 return $return_array;
480 * Array of all Modules in the version bein upgraded
481 * This method returns an Array of all modules
482 * @return $modules Array of modules.
484 function getAllModules() {
487 while($e = $d->read()){
488 if(substr($e, 0, 1) == '.' || !is_dir('modules/' . $e))continue;
494 //Remove files with the smae md5
496 function removeMd5MatchingFiles($deleteNot=array()){
498 $md5_string = array();
499 if(file_exists(clean_path(getcwd().'/files.md5'))){
500 require(clean_path(getcwd().'/files.md5'));
502 $modulesAll = getAllModules();
503 foreach($modulesAll as $mod){
504 $allModFiles = array();
505 if(is_dir('modules/'.$mod)){
506 $allModFiles = findAllFiles('modules/'.$mod,$allModFiles);
507 foreach($allModFiles as $file){
508 if(file_exists($file) && !in_array(basename($file),$deleteNot)){
509 if(isset($md5_string['./'.$file])) {
510 $fileContents = file_get_contents($file);
511 if(md5($fileContents) == $md5_string['./'.$file]) {
522 * Handles requirements for creating reminder Tasks and Emails
523 * @param array skippedFiles Array of files that were not overwriten and must be manually mereged.
524 * @param string path Optional full path to alternate upgradeWizard log.
526 function commitHandleReminders($skippedFiles, $path='') {
528 global $current_user;
530 if(empty($mod_strings))
531 $mod_strings = return_module_language('en_us', 'UpgradeWizard');
533 if(empty($current_user->id)) {
534 $current_user->getSystemUser();
537 if(count($skippedFiles) > 0) {
538 $desc = $mod_strings['LBL_UW_COMMIT_ADD_TASK_OVERVIEW'] . "\n\n";
539 $desc .= $mod_strings['LBL_UW_COMMIT_ADD_TASK_DESC_1'];
540 $desc .= $_SESSION['uw_restore_dir'] . "\n\n";
541 $desc .= $mod_strings['LBL_UW_COMMIT_ADD_TASK_DESC_2'] . "\n\n";
543 foreach($skippedFiles as $file) {
544 $desc .= $file . "\n";
548 /// Not using new TimeDate stuff here because it needs to be compatible with 6.0
549 $nowDate = gmdate('Y-m-d');
550 $nowTime = gmdate('H:i:s');
551 $nowDateTime = $nowDate . ' ' . $nowTime;
553 if($_REQUEST['addTaskReminder'] == 'remind') {
554 logThis('Adding Task for admin for manual merge.', $path);
557 $task->name = $mod_strings['LBL_UW_COMMIT_ADD_TASK_NAME'];
558 $task->description = $desc;
559 $task->date_due = $nowDate;
560 $task->time_due = $nowTime;
561 $task->priority = 'High';
562 $task->status = 'Not Started';
563 $task->assigned_user_id = $current_user->id;
564 $task->created_by = $current_user->id;
565 $task->date_entered = $nowDateTime;
566 $task->date_modified = $nowDateTime;
570 if($_REQUEST['addEmailReminder'] == 'remind') {
571 logThis('Sending Reminder for admin for manual merge.', $path);
573 $email = new Email();
574 $email->assigned_user_id = $current_user->id;
575 $email->name = $mod_strings['LBL_UW_COMMIT_ADD_TASK_NAME'];
576 $email->description = $desc;
577 $email->description_html = nl2br($desc);
578 $email->from_name = $current_user->full_name;
579 $email->from_addr = $current_user->email1;
580 $email->to_addrs_arr = $email->parse_addrs($current_user->email1, '', '', '');
581 $email->cc_addrs_arr = array();
582 $email->bcc_addrs_arr = array();
583 $email->date_entered = $nowDateTime;
584 $email->date_modified = $nowDateTime;
591 function deleteCache(){
592 //Clean modules from cache
593 if(is_dir($GLOBALS['sugar_config']['cache_dir'].'modules')){
594 $allModFiles = array();
595 $allModFiles = findAllFiles($GLOBALS['sugar_config']['cache_dir'].'modules',$allModFiles);
596 foreach($allModFiles as $file)
598 if(file_exists($file)) {
600 rmdir_recursive($file);
608 //Clean jsLanguage from cache
609 if(is_dir($GLOBALS['sugar_config']['cache_dir'].'jsLanguage')){
610 $allModFiles = array();
611 $allModFiles = findAllFiles($GLOBALS['sugar_config']['cache_dir'].'jsLanguage',$allModFiles);
612 foreach($allModFiles as $file){
613 if(file_exists($file)){
618 //Clean smarty from cache
619 if(is_dir($GLOBALS['sugar_config']['cache_dir'].'smarty')){
620 $allModFiles = array();
621 $allModFiles = findAllFiles($GLOBALS['sugar_config']['cache_dir'].'smarty',$allModFiles);
622 foreach($allModFiles as $file){
623 if(file_exists($file)){
628 //Rebuild dashlets cache
629 require_once('include/Dashlets/DashletCacheBuilder.php');
630 $dc = new DashletCacheBuilder();
634 function deleteChance(){
635 //Clean folder from cache
636 if(is_dir('include/SugarObjects/templates/chance')){
637 rmdir_recursive('include/SugarObjects/templates/chance');
639 if(is_dir('include/SugarObjects/templates/chance')){
640 if(!isset($_SESSION['chance'])){
641 $_SESSION['chance'] = '';
643 $_SESSION['chance'] = 'include/SugarObjects/templates/chance';
644 //rename('include/SugarObjects/templates/chance','include/SugarObjects/templates/chance_removeit');
651 * copies upgrade wizard files from new patch if that dir exists
652 * @param string file Path to uploaded zip file
654 function upgradeUWFiles($file) {
655 global $sugar_config;
656 // file = getcwd().'/'.$sugar_config['upload_dir'].$_FILES['upgrade_zip']['name'];
658 $cacheUploadUpgradesTemp = clean_path(mk_temp_dir("{$sugar_config['upload_dir']}upgrades/temp"));
660 unzip($file, $cacheUploadUpgradesTemp);
662 if(!file_exists(clean_path("{$cacheUploadUpgradesTemp}/manifest.php"))) {
663 logThis("*** ERROR: no manifest file detected while bootstraping upgrade wizard files!");
666 include(clean_path("{$cacheUploadUpgradesTemp}/manifest.php"));
671 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/modules/UpgradeWizard"))) {
672 $allFiles = findAllFiles(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/modules/UpgradeWizard"), $allFiles);
675 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/ModuleInstall"))) {
676 $allFiles = findAllFiles(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/ModuleInstall"), $allFiles);
678 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/javascript/yui"))) {
679 $allFiles = findAllFiles(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/javascript/yui"), $allFiles);
681 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/HandleAjaxCall.php"))) {
682 $allFiles[] = clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/HandleAjaxCall.php");
684 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/SugarTheme"))) {
685 $allFiles = findAllFiles(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/SugarTheme"), $allFiles);
687 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/SugarCache"))) {
688 $allFiles = findAllFiles(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/SugarCache"), $allFiles);
690 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/external_cache.php"))) {
691 $allFiles[] = clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/external_cache.php");
695 * /home/chris/workspace/maint450/cache/upload/upgrades/temp/DlNnqP/
696 * SugarEnt-Patch-4.5.0c/modules/Leads/ConvertLead.html
698 $cwd = clean_path(getcwd());
700 foreach($allFiles as $k => $file) {
701 $file = clean_path($file);
702 $destFile = str_replace(clean_path($cacheUploadUpgradesTemp.'/'.$manifest['copy_files']['from_dir']), $cwd, $file);
703 if(!is_dir(dirname($destFile))) {
704 mkdir_recursive(dirname($destFile)); // make sure the directory exists
706 if ( stristr($file,'uw_main.tpl') )
707 logThis('Skipping "'.$file.'" - file copy will during commit step.');
709 logThis('updating UpgradeWizard code: '.$destFile);
710 copy_recursive($file, $destFile);
713 logThis ('is sugar_file_util there '.file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/sugar_file_utils.php")));
714 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/sugar_file_utils.php"))) {
715 $file = clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/sugar_file_utils.php");
716 $destFile = str_replace(clean_path($cacheUploadUpgradesTemp.'/'.$manifest['copy_files']['from_dir']), $cwd, $file);
717 copy($file,$destFile);
724 * gets valid patch file names that exist in upload/upgrade/patch/
726 function getValidPatchName($returnFull = true) {
727 global $base_upgrade_dir;
730 global $sugar_version;
731 global $sugar_config;
732 $uh = new UpgradeHistory();
733 $base_upgrade_dir = $sugar_config['upload_dir'] . "upgrades";
736 // scan for new files (that are not installed)
737 logThis('finding new files for upgrade');
738 $upgrade_content = '';
739 $upgrade_contents = findAllFiles($base_upgrade_dir, array(), false, 'zip');
740 //other variations of zip file i.e. ZIP, zIp,zIP,Zip,ZIp,ZiP
741 $extns = array('ZIP','ZIp','ZiP','Zip','zIP','zIp','ziP');
742 foreach($extns as $extn){
743 $upgrade_contents = array_merge($upgrade_contents,findAllFiles( "$base_upgrade_dir", array() , false, $extn));
751 <b>{$mod_strings['LBL_ML_NAME']}</b>
754 <b>{$mod_strings['LBL_ML_TYPE']}</b>
757 <b>{$mod_strings['LBL_ML_VERSION']}</b>
760 <b>{$mod_strings['LBL_ML_PUBLISHED']}</b>
763 <b>{$mod_strings['LBL_ML_UNINSTALLABLE']}</b>
766 <b>{$mod_strings['LBL_ML_DESCRIPTION']}</b>
771 // assume old patches are there.
772 $upgradeToVersion = array(); // fill with valid patches - we will only use the latest qualified found patch
774 // cn: bug 10609 - notices for uninitialized variables
779 $published_date = '';
784 foreach($upgrade_contents as $upgrade_content) {
785 if(!preg_match("#.*\.zip\$#i", strtolower($upgrade_content))) {
789 $upgrade_content = clean_path($upgrade_content);
790 $the_base = basename($upgrade_content);
791 $the_md5 = md5_file($upgrade_content);
793 $md5_matches = $uh->findByMd5($the_md5);
795 /* 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.
796 * Edge-case: manual upgrade with a FTP of a patch; UH table has no entry for it. Assume nothing. :( */
797 if(0 == sizeof($md5_matches)) {
798 $target_manifest = remove_file_extension( $upgrade_content ) . '-manifest.php';
799 require_once($target_manifest);
801 if(empty($manifest['version'])) {
802 logThis("*** Potential error: patch found with no version [ {$upgrade_content} ]");
805 if(!isset($manifest['type']) || $manifest['type'] != 'patch') {
806 logThis("*** Potential error: patch found with either no 'type' or non-patch type [ {$upgrade_content} ]");
810 $upgradeToVersion[$manifest['version']] = urlencode($upgrade_content);
812 $name = empty($manifest['name']) ? $upgrade_content : $manifest['name'];
813 $version = empty($manifest['version']) ? '' : $manifest['version'];
814 $published_date = empty($manifest['published_date']) ? '' : $manifest['published_date'];
816 $description = empty($manifest['description']) ? 'None' : $manifest['description'];
817 $uninstallable = empty($manifest['is_uninstallable']) ? 'No' : 'Yes';
818 $type = getUITextForType( $manifest['type'] );
819 $manifest_type = $manifest['type'];
821 if(empty($manifest['icon'])) {
822 $icon = getImageForType( $manifest['type'] );
824 $path_parts = pathinfo( $manifest['icon'] );
825 $icon = "<img src=\"" . remove_file_extension( $upgrade_content ) . "-icon." . $path_parts['extension'] . "\">";
830 // cn: bug 10488 use the NEWEST upgrade/patch available when running upgrade wizard.
831 ksort($upgradeToVersion);
832 $upgradeToVersion = array_values($upgradeToVersion);
833 $newest = array_pop($upgradeToVersion);
834 $_SESSION['install_file'] = urldecode($newest); // in-case it was there from a prior.
835 logThis("*** UW using [ {$_SESSION['install_file']} ] as source for patch files.");
837 $cleanUpgradeContent = urlencode($_SESSION['install_file']);
839 // cn: 10606 - cannot upload a patch file since this returned always.
840 if(!empty($cleanUpgradeContent)) {
841 $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";
844 <form action="index.php" method="post">
845 <input type="hidden" name="module" value="UpgradeWizard">
846 <input type="hidden" name="action" value="index">
847 <input type="hidden" name="step" value="{$_REQUEST['step']}">
848 <input type="hidden" name="run" value="delete">
849 <input type=hidden name="install_file" value="{$cleanUpgradeContent}" />
850 <input type=submit value="{$mod_strings['LBL_BUTTON_DELETE']}" />
854 $disabled = "DISABLED";
859 if(empty($cleanUpgradeContent)){
860 $ready .= "<tr><td colspan='7'><i>None</i></td>\n";
861 $ready .= "</table>\n";
863 $ready .= "<br></ul>\n";
865 $return['ready'] = $ready;
866 $return['disabled'] = $disabled;
875 * finalizes upgrade by setting upgrade versions in DB (config table) and sugar_version.php
876 * @return bool true on success
878 function updateVersions($version) {
880 global $sugar_config;
883 logThis('At updateVersions()... updating config table and sugar_version.php.', $path);
886 if(isset($_SESSION['sugar_version_file']) && !empty($_SESSION['sugar_version_file'])) {
887 if(!copy($_SESSION['sugar_version_file'], clean_path(getcwd().'/sugar_version.php'))) {
888 logThis('*** ERROR: sugar_version.php could not be copied to destination! Cannot complete upgrade', $path);
891 logThis('sugar_version.php successfully updated!', $path);
894 logThis('*** ERROR: no sugar_version.php file location found! - cannot complete upgrade...', $path);
898 // handle config table
899 if($db->dbType == 'mysql') {
900 $q1 = "DELETE FROM `config` WHERE `category` = 'info' AND `name` = 'sugar_version'";
901 $q2 = "INSERT INTO `config` (`category`, `name`, `value`) VALUES ('info', 'sugar_version', '{$version}')";
902 } elseif($db->dbType == 'oci8' || $db->dbType == 'oracle') {
903 } elseif($db->dbType == 'mssql') {
904 $q1 = "DELETE FROM config WHERE category = 'info' AND name = 'sugar_version'";
905 $q2 = "INSERT INTO config (category, name, value) VALUES ('info', 'sugar_version', '{$version}')";
908 logThis('Deleting old DB version info from config table.', $path);
911 logThis('Inserting updated version info into config table.', $path);
914 logThis('updateVersions() complete.', $path);
921 * gets a module's lang pack - does not need to be a SugarModule
922 * @param lang string Language
923 * @param module string Path to language folder
924 * @return array mod_strings
926 function getModuleLanguagePack($lang, $module) {
927 $mod_strings = array();
929 if(!empty($lang) && !empty($module)) {
930 $langPack = clean_path(getcwd().'/'.$module.'/language/'.$lang.'.lang.php');
931 $langPackEn = clean_path(getcwd().'/'.$module.'/language/en_us.lang.php');
933 if(file_exists($langPack))
934 include_once($langPack);
935 elseif(file_exists($langPackEn))
936 include_once($langPackEn);
942 * checks system compliance for 4.5+ codebase
943 * @return array Mixed values
945 function checkSystemCompliance() {
946 global $sugar_config;
947 global $current_language;
951 if(!defined('SUGARCRM_MIN_MEM')) {
952 define('SUGARCRM_MIN_MEM', 40);
955 $installer_mod_strings = getModuleLanguagePack($current_language, './install');
957 $ret['error_found'] = false;
960 $php_version = constant('PHP_VERSION');
961 $check_php_version_result = check_php_version($php_version);
963 switch($check_php_version_result) {
965 $ret['phpVersion'] = "<b><span class=stop>{$installer_mod_strings['ERR_CHECKSYS_PHP_INVALID_VER']} {$php_version} )</span></b>";
966 $ret['error_found'] = true;
969 $ret['phpVersion'] = "<b><span class=go>{$installer_mod_strings['ERR_CHECKSYS_PHP_UNSUPPORTED']} {$php_version} )</span></b>";
972 $ret['phpVersion'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_PHP_OK']} {$php_version} )</span></b>";
976 // database and connect
977 switch($sugar_config['dbconfig']['db_type']){
980 $q = "SELECT version();";
982 $a = $db->fetchByAssoc($r);
983 if(version_compare($a['version()'], '4.1.2') < 0) {
984 $ret['error_found'] = true;
985 $ret['mysqlVersion'] = "<b><span class=stop>".$mod_strings['ERR_UW_MYSQL_VERSION'].$a['version()']."</span></b>";
999 if(function_exists('xml_parser_create')) {
1000 $ret['xmlStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1002 $ret['xmlStatus'] = "<b><span class=stop>{$installer_mod_strings['LBL_CHECKSYS_NOT_AVAILABLE']}</span></b>";
1003 $ret['error_found'] = true;
1007 if(function_exists('curl_init')) {
1008 $ret['curlStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</font></b>";
1010 $ret['curlStatus'] = "<b><span class=go>{$installer_mod_strings['ERR_CHECKSYS_CURL']}</font></b>";
1011 $ret['error_found'] = false;
1015 if(function_exists('mb_strlen')) {
1016 $ret['mbstringStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</font></b>";
1018 $ret['mbstringStatus'] = "<b><span class=stop>{$installer_mod_strings['ERR_CHECKSYS_MBSTRING']}</font></b>";
1019 $ret['error_found'] = true;
1023 if(function_exists('imap_open')) {
1024 $ret['imapStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1026 $ret['imapStatus'] = "<b><span class=go>{$installer_mod_strings['ERR_CHECKSYS_IMAP']}</span></b>";
1027 $ret['error_found'] = false;
1032 if('1' == ini_get('safe_mode')) {
1033 $ret['safeModeStatus'] = "<b><span class=stop>{$installer_mod_strings['ERR_CHECKSYS_SAFE_MODE']}</span></b>";
1034 $ret['error_found'] = true;
1036 $ret['safeModeStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1040 // call time pass by ref
1041 if('1' == ini_get('allow_call_time_pass_reference')) {
1042 $ret['callTimeStatus'] = "<b><span class=stop>{$installer_mod_strings['ERR_CHECKSYS_CALL_TIME']}</span></b>";
1043 //continue upgrading
1045 $ret['callTimeStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1049 $ret['memory_msg'] = "";
1050 $memory_limit = "-1";//ini_get('memory_limit');
1051 $sugarMinMem = constant('SUGARCRM_MIN_MEM');
1052 // logic based on: http://us2.php.net/manual/en/ini.core.php#ini.memory-limit
1053 if( $memory_limit == "" ){ // memory_limit disabled at compile time, no memory limit
1054 $ret['memory_msg'] = "<b><span class=\"go\">{$installer_mod_strings['LBL_CHECKSYS_MEM_OK']}</span></b>";
1055 } elseif( $memory_limit == "-1" ){ // memory_limit enabled, but set to unlimited
1056 $ret['memory_msg'] = "<b><span class=\"go\">{$installer_mod_strings['LBL_CHECKSYS_MEM_UNLIMITED']}</span></b>";
1058 rtrim($memory_limit, 'M');
1059 $memory_limit_int = (int) $memory_limit;
1060 if( $memory_limit_int < constant('SUGARCRM_MIN_MEM') ){
1061 $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>";
1062 $ret['error_found'] = true;
1064 $ret['memory_msg'] = "<b><span class=\"go\">{$installer_mod_strings['LBL_CHECKSYS_OK']} ({$memory_limit})</span></b>";
1068 /* mbstring.func_overload
1069 $ret['mbstring.func_overload'] = '';
1070 $mb = ini_get('mbstring.func_overload');
1073 $ret['mbstring.func_overload'] = "<b><span class=\"stop\">{$mod_strings['ERR_UW_MBSTRING_FUNC_OVERLOAD']}</b>";
1074 $ret['error_found'] = true;
1082 function checkMysqlConnection(){
1083 global $sugar_config;
1084 $configOptions = $sugar_config['dbconfig'];
1085 if($sugar_config['dbconfig']['db_type'] == 'mysql'){
1086 @mysql_ping($GLOBALS['db']->database);
1091 * is a file that we blow away automagically
1093 function isAutoOverwriteFile($file) {
1094 $overwriteDirs = array(
1095 './sugar_version.php',
1096 './modules/UpgradeWizard/uw_main.tpl',
1098 $file = trim('.'.str_replace(clean_path(getcwd()), '', $file));
1100 if(in_array($file, $overwriteDirs)) {
1104 $fileExtension = substr(strrchr($file, "."), 1);
1105 if($fileExtension == 'tpl' || $fileExtension == 'html') {
1115 function logThis($entry, $path='') {
1116 global $mod_strings;
1117 if(file_exists('include/utils/sugar_file_utils.php')){
1118 require_once('include/utils/sugar_file_utils.php');
1120 $log = empty($path) ? clean_path(getcwd().'/upgradeWizard.log') : clean_path($path);
1122 // create if not exists
1123 if(!file_exists($log)) {
1124 if(function_exists('sugar_fopen')){
1125 $fp = @sugar_fopen($log, 'w+'); // attempts to create file
1128 $fp = fopen($log, 'w+'); // attempts to create file
1130 if(!is_resource($fp)) {
1131 $GLOBALS['log']->fatal('UpgradeWizard could not create the upgradeWizard.log file');
1132 die($mod_strings['ERR_UW_LOG_FILE_UNWRITABLE']);
1135 if(function_exists('sugar_fopen')){
1136 $fp = @sugar_fopen($log, 'a+'); // write pointer at end of file
1139 $fp = @fopen($log, 'a+'); // write pointer at end of file
1142 if(!is_resource($fp)) {
1143 $GLOBALS['log']->fatal('UpgradeWizard could not open/lock upgradeWizard.log file');
1144 die($mod_strings['ERR_UW_LOG_FILE_UNWRITABLE']);
1148 $line = date('r').' [UpgradeWizard] - '.$entry."\n";
1150 if(@fwrite($fp, $line) === false) {
1151 $GLOBALS['log']->fatal('UpgradeWizard could not write to upgradeWizard.log: '.$entry);
1152 die($mod_strings['ERR_UW_LOG_FILE_UNWRITABLE']);
1155 if(is_resource($fp)) {
1162 * tries to validate the query based on type
1163 * @param string query The query to verify
1164 * @param string dbType The DB type
1165 * @return string error Non-empty string on error
1167 function verifySqlStatement($query, $dbType, &$newTables) {
1169 logThis('verifying SQL statement');
1171 $table = getTableFromQuery($query);
1173 switch(strtoupper(substr($query, 0, 10))) {
1177 $error = testQueryAlter($table, $dbType, strtoupper($query), $newTables);
1181 $error = testQueryCreate($table, $dbType, $query, $newTables);
1185 $error = testQueryDelete($table, $dbType, $query);
1189 $error = testQueryDrop($table, $dbType, $query);
1193 $error = testQueryInsert($table, $dbType, $query);
1196 case (strtoupper(substr($query, 0, 6)) == 'UPDATE'):
1197 $error = testQueryUpdate($table, $dbType, $query);
1209 * @desc This function is to be used in the upgrade process to preserve changes/customaizations made to pre 5.1 quickcreate layout.
1210 * 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
1211 * was automatically picked up by the quick create. [Addresses Bug 21469]
1212 * This function will check if customizations were made, and will create quickcreatedefs.php in the /cutom/working/$module_name directory.
1214 function updateQuickCreateDefs(){
1215 $d = dir('modules');
1216 $studio_modules = array();
1218 while($e = $d->read()){ //collect all studio modules.
1219 if(substr($e, 0, 1) == '.' || !is_dir('modules/' . $e))continue;
1220 if(file_exists('modules/' . $e . '/metadata/studio.php'))
1222 array_push($studio_modules, $e);
1226 foreach( $studio_modules as $modname ){ //for each studio enabled module
1227 //Check !exists modules/$modname/metadata/quickcreatedefs.php &&
1228 //exists custom/$modname/editviewdefs.php (module was customized) &&
1229 //!exists custom/$modname/quickcreateviewdefs.php
1231 $editviewdefs = "custom/working/modules/".$modname."/metadata/editviewdefs.php";
1232 $quickcreatedefs = "custom/working/modules/".$modname."/metadata/quickcreatedefs.php";
1234 if ( !file_exists("modules/".$modname."/metadata/quickcreatedefs.php") &&
1235 file_exists($editviewdefs) &&
1236 !file_exists($quickcreatedefs) ){
1237 //clone editviewdef and save it in custom/working/modules/metadata
1238 $GLOBALS['log']->debug("Copying editviewdefs.php as quickcreatedefs.php for the $modname module in custom/working/modules/$modname/metadata!");
1239 if(copy( $editviewdefs, $quickcreatedefs)){
1240 if(file_exists($quickcreatedefs) && is_readable($quickcreatedefs)){
1241 $file = file($quickcreatedefs);
1242 //replace 'EditView' with 'QuickCreate'
1243 $fp = fopen($quickcreatedefs,'w');
1244 foreach($file as &$line){
1245 if(preg_match('/^\s*\'EditView\'\s*=>\s*$/', $line) > 0){
1246 $line = "'QuickCreate' =>\n";
1254 $GLOBALS['log']->debug("Failed to replace 'EditView' with QuickCreate because $quickcreatedefs is either not readable or does not exist.");
1257 $GLOBALS['log']->debug("Failed to copy $editviewdefs to $quickcreatedefs!");
1264 function cleanQuery($query, $oci8=false) {
1274 $q = str_replace($bad, $good, $query);
1280 * test perms for CREATE queries
1282 function testPermsCreate($type, $out) {
1283 logThis('Checking CREATE TABLE permissions...');
1285 global $mod_strings;
1290 $db->query('CREATE TABLE temp (id varchar(36))');
1291 if($db->checkError()) {
1292 logThis('cannot CREATE TABLE!');
1293 $out['db']['dbNoCreate'] = true;
1294 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_CREATE']}</span></td></tr>";
1306 * test perms for INSERT
1308 function testPermsInsert($type, $out, $skip=false) {
1309 logThis('Checking INSERT INTO permissions...');
1311 global $mod_strings;
1317 $db->query("INSERT INTO temp (id) VALUES ('abcdef0123456789abcdef0123456789abcd')");
1318 if($db->checkError()) {
1319 logThis('cannot INSERT INTO!');
1320 $out['db']['dbNoInsert'] = true;
1321 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_INSERT']}</span></td></tr>";
1335 * test perms for UPDATE TABLE
1337 function testPermsUpdate($type, $out, $skip=false) {
1338 logThis('Checking UPDATE TABLE permissions...');
1340 global $mod_strings;
1346 $db->query("UPDATE temp SET id = '000000000000000000000000000000000000' WHERE id = 'abcdef0123456789abcdef0123456789abcd'");
1347 if($db->checkError()) {
1348 logThis('cannot UPDATE TABLE!');
1349 $out['db']['dbNoUpdate'] = true;
1350 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_UPDATE']}</span></td></tr>";
1364 * test perms for SELECT
1366 function testPermsSelect($type, $out, $skip=false) {
1367 logThis('Checking SELECT permissions...');
1369 global $mod_strings;
1374 $r = $db->query('SELECT id FROM temp');
1375 if($db->checkError()) {
1376 logThis('cannot SELECT!');
1377 $out['db']['dbNoSelect'] = true;
1378 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_SELECT']}</span></td></tr>";
1380 logThis('Checking validity of SELECT results');
1381 while($a = $db->fetchByAssoc($r)) {
1382 if($a['id'] != '000000000000000000000000000000000000') {
1383 logThis('results DO NOT MATCH! got: '.$a['id']);
1384 $out['db'][] = 'selectFailed';
1385 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_INSERT_FAILED']}</span></td></tr>";
1400 * test perms for DELETE
1402 function testPermsDelete($type, $out, $skip=false) {
1403 logThis('Checking DELETE FROM permissions...');
1405 global $mod_strings;
1410 $db->query("DELETE FROM temp WHERE id = '000000000000000000000000000000000000'");
1411 if($db->checkError()) {
1412 logThis('cannot DELETE FROM!');
1413 $out['db']['dbNoDelete'] = true;
1414 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_DELETE']}</span></td></tr>";
1427 * test perms for ALTER TABLE ADD COLUMN
1429 function testPermsAlterTableAdd($type, $out, $skip=false) {
1430 logThis('Checking ALTER TABLE ADD COLUMN permissions...');
1432 global $mod_strings;
1436 $db->query('ALTER TABLE temp ADD COLUMN test varchar(100)');
1437 if($db->checkError()) {
1438 logThis('cannot ADD COLUMN!');
1439 $out['db']['dbNoAddColumn'] = true;
1440 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_ADD_COLUMN']}</span></td></tr>";
1445 $db->query('ALTER TABLE [temp] ADD [test] [varchar] (100)');
1446 if($db->checkError()) {
1447 logThis('cannot ADD COLUMN!');
1448 $out['db']['dbNoAddColumn'] = true;
1449 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_ADD_COLUMN']}</span></td></tr>";
1464 * test perms for ALTER TABLE ADD COLUMN
1466 function testPermsAlterTableChange($type, $out, $skip=false) {
1467 logThis('Checking ALTER TABLE CHANGE COLUMN permissions...');
1469 global $mod_strings;
1473 $db->query('ALTER TABLE temp CHANGE COLUMN test test varchar(100)');
1474 if($db->checkError()) {
1475 logThis('cannot CHANGE COLUMN!');
1476 $out['db']['dbNoChangeColumn'] = true;
1477 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_CHANGE_COLUMN']}</span></td></tr>";
1482 $db->query('ALTER TABLE [temp] ALTER COLUMN [test] [varchar] (100)');
1483 if($db->checkError()) {
1484 logThis('cannot CHANGE COLUMN!');
1485 $out['db']['dbNoChangeColumn'] = true;
1486 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_CHANGE_COLUMN']}</span></td></tr>";
1500 * test perms for ALTER TABLE DROP COLUMN
1502 function testPermsAlterTableDrop($type, $out, $skip=false) {
1503 logThis('Checking ALTER TABLE DROP COLUMN permissions...');
1505 global $mod_strings;
1510 $db->query('ALTER TABLE temp DROP COLUMN test');
1511 if($db->checkError()) {
1512 logThis('cannot DROP COLUMN!');
1513 $out['db']['dbNoDropColumn'] = true;
1514 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_DROP_COLUMN']}</span></td></tr>";
1527 * test perms for DROP TABLE
1529 function testPermsDropTable($type, $out, $skip=false) {
1530 logThis('Checking DROP TABLE permissions...');
1532 global $mod_strings;
1537 $db->query('DROP TABLE temp');
1538 if($db->checkError()) {
1539 logThis('cannot DROP TABLE!');
1540 $out['db']['dbNoDropTable'] = true;
1541 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_DROP_TABLE']}</span></td></tr>";
1554 function createMSSQLTemp($table) {
1555 global $sugar_config;
1558 $qtest = "SELECT TABLE_NAME tn FROM information.tables WHERE TABLE_NAME = '{$table}__UW_TEMP'";
1559 $rtest = $db->query($qtest);
1560 $atest = $db->fetchByAssoc($rtest);
1563 $tempTable = "CREATE TABLE {$table}__UW_TEMP AS ".$db->limitQuerySql("SELECT * FROM {$table}",0,8);
1564 logThis("Creating temp table for {$table}: {$tempTable}");
1565 $db->query($tempTable);
1568 logThis("Found {$table}__UW_TEMP - skipping temp table creation.");
1573 * Tests an ALTER TABLE query
1574 * @param string table The table name to get DDL
1575 * @param string dbType MySQL, MSSQL, etc.
1576 * @param string query The query to test.
1577 * @return string Non-empty if error found
1579 function testQueryAlter($table, $dbType, $query, $newTables) {
1580 logThis('verifying ALTER statement...');
1582 global $sugar_config;
1585 $db = &DBManagerFactory::getInstance();
1588 // Skipping ALTER TABLE [table] DROP PRIMARY KEY because primary keys are not being copied
1589 // over to the temp tables
1590 if(strpos(strtoupper($query), 'DROP PRIMARY KEY') !== false) {
1591 logThis('Skipping DROP PRIMARY KEY verification');
1595 if ($dbType == 'mysql'){
1596 mysql_error(); // initialize errors
1600 if(!in_array($table, $newTables)) {
1604 logThis('creating temp table for ['.$table.']...');
1605 $q = "SHOW CREATE TABLE {$table}";
1606 $r = $db->query($q);
1607 $a = $db->fetchByAssoc($r);
1609 // rewrite DDL with _temp name
1610 $cleanQuery = cleanQuery($a['Create Table']);
1611 $tempTableQuery = str_replace("CREATE TABLE `{$table}`", "CREATE TABLE `{$table}__uw_temp`", $cleanQuery);
1612 $r2 = $db->query($tempTableQuery);
1614 // get sample data into the temp table to test for data/constraint conflicts
1615 logThis('inserting temp dataset...');
1616 $q3 = "INSERT INTO `{$table}__uw_temp` SELECT * FROM `{$table}` LIMIT 10";
1617 $r3 = $db->query($q3, false, "Preflight Failed for: {$query}");
1619 // test the query on the test table
1620 logThis('testing query: ['.$query.']');
1621 $tempTableTestQuery = str_replace("ALTER TABLE `{$table}`", "ALTER TABLE `{$table}__uw_temp`", $query);
1622 if (strpos($tempTableTestQuery, 'idx') === false) {
1623 if(isRunningAgainstTrueTable($tempTableTestQuery)) {
1624 $error = getFormattedError('Could not use a temp table to test query!', $query);
1628 logThis('testing query on temp table: ['.$tempTableTestQuery.']');
1629 $r4 = $db->query($tempTableTestQuery, false, "Preflight Failed for: {$query}");
1632 // test insertion of an index on a table
1633 $tempTableTestQuery_idx = str_replace("ADD INDEX `idx_", "ADD INDEX `temp_idx_", $tempTableTestQuery);
1634 logThis('testing query on temp table: ['.$tempTableTestQuery_idx.']');
1635 $r4 = $db->query($tempTableTestQuery_idx, false, "Preflight Failed for: {$query}");
1637 $mysqlError = mysql_error(); // empty on no-errors
1638 if(!empty($mysqlError)) {
1639 logThis('*** ERROR: query failed: '.$mysqlError);
1640 $error = getFormattedError($mysqlError, $query);
1644 // clean up moved to end of preflight
1648 logThis('mssql found: skipping test query - ['.$query.']');
1652 logThis('Oracle found: skipping test query - ['.$query.']');
1656 logThis($table . ' is a new table');
1659 logThis('verification done.');
1664 * Tests an CREATE TABLE query
1665 * @param string table The table name to get DDL
1666 * @param string dbType MySQL, MSSQL, etc.
1667 * @param string query The query to test.
1668 * @return string Non-empty if error found
1670 function testQueryCreate($table, $dbType, $query, &$newTables) {
1671 logThis('verifying CREATE statement...');
1674 $db = &DBManagerFactory::getInstance();
1680 // rewrite DDL with _temp name
1681 logThis('testing query: ['.$query.']');
1682 $tempTableQuery = str_replace("CREATE TABLE `{$table}`", "CREATE TABLE `{$table}__uw_temp`", $query);
1684 if(isRunningAgainstTrueTable($tempTableQuery)) {
1685 $error = getFormattedError('Could not use a temp table to test query!', $query);
1689 $r4 = $db->query($tempTableQuery, false, "Preflight Failed for: {$query}");
1691 $error = mysql_error(); // empty on no-errors
1692 if(!empty($error)) {
1693 logThis('*** ERROR: query failed.');
1694 $error = getFormattedError($error, $query);
1697 // check if table exists
1698 logThis('testing for table: '.$table);
1699 $q1 = "DESC `{$table}`";
1700 $r1 = $db->query($q1);
1702 $mysqlError = mysql_error();
1703 if(empty($mysqlError)) {
1704 logThis('*** ERROR: table already exists!: '.$table);
1705 $error = getFormattedError('table exists', $query);
1708 logThis('NEW TABLE: '.$query);
1709 $newTables[] = $table;
1714 logThis('mssql found: skipping test query - ['.$query.']');
1718 logThis('Oracle found: skipping test query - ['.$query.']');
1725 * Tests an DELETE FROM query
1726 * @param string table The table name to get DDL
1727 * @param string dbType MySQL, MSSQL, etc.
1728 * @param string query The query to test.
1729 * @return string Non-empty if error found
1731 function testQueryDelete($table, $dbType, $query) {
1732 logThis('verifying DELETE statements');
1735 $db = &DBManagerFactory::getInstance();
1743 logThis('creating temp table...');
1744 $q = "SHOW CREATE TABLE {$table}";
1745 $r = $db->query($q);
1746 $a = $db->fetchByAssoc($r);
1748 // rewrite DDL with _temp name
1749 $cleanQuery = cleanQuery($a['Create Table']);
1750 $tempTableQuery = str_replace("CREATE TABLE `{$table}`", "CREATE TABLE `{$table}__uw_temp`", $cleanQuery);
1751 $r2 = $db->query($tempTableQuery);
1753 // get sample data into the temp table to test for data/constraint conflicts
1754 logThis('inserting temp dataset...');
1755 $q3 = "INSERT INTO `{$table}__uw_temp` SELECT * FROM `{$table}` LIMIT 10";
1756 $r3 = $db->query($q3);
1758 // test the query on the test table
1759 logThis('testing query: ['.$query.']');
1760 $tempTableTestQuery = str_replace("DELETE FROM `{$table}`", "DELETE FROM `{$table}__uw_temp`", $query);
1762 if(isRunningAgainstTrueTable($tempTableTestQuery)) {
1763 $error = getFormattedError('Could not use a temp table to test query!', $tempTableTestQuery);
1767 $r4 = $db->query($tempTableTestQuery, false, "Preflight Failed for: {$query}");
1768 $error = mysql_error(); // empty on no-errors
1769 if(!empty($error)) {
1770 logThis('*** ERROR: query failed.');
1771 $error = getFormattedError($error, $query);
1776 logThis('mssql found: skipping test query - ['.$query.']');
1780 logThis('Oracle found: skipping test query - ['.$query.']');
1783 logThis('verification done.');
1788 * Tests a DROP TABLE query
1791 function testQueryDrop($table, $dbType, $query) {
1792 logThis('verifying DROP TABLE statement');
1795 $db = &DBManagerFactory::getInstance();
1803 logThis('creating temp table...');
1804 $q = "SHOW CREATE TABLE {$table}";
1805 $r = $db->query($q);
1806 $a = $db->fetchByAssoc($r);
1808 // rewrite DDL with _temp name
1809 $cleanQuery = cleanQuery($a['Create Table']);
1810 $tempTableQuery = str_replace("CREATE TABLE `{$table}`", "CREATE TABLE `{$table}__uw_temp`", $cleanQuery);
1811 $r2 = $db->query($tempTableQuery);
1813 // get sample data into the temp table to test for data/constraint conflicts
1814 logThis('inserting temp dataset...');
1815 $query = stripQuotesUW($query, $table);
1816 $q3 = "INSERT INTO `{$table}__uw_temp` SELECT * FROM `{$table}` LIMIT 10";
1817 $r3 = $db->query($q3);
1819 // test the query on the test table
1820 logThis('testing query: ['.$query.']');
1821 $tempTableTestQuery = str_replace("DROP TABLE `{$table}`", "DROP TABLE `{$table}__uw_temp`", $query);
1823 // make sure the test query is running against a temp table
1824 if(isRunningAgainstTrueTable($tempTableTestQuery)) {
1825 $error = getFormattedError('Could not use a temp table to test query!', $tempTableTestQuery);
1829 $r4 = $db->query($tempTableTestQuery, false, "Preflight Failed for: {$query}");
1830 $error = mysql_error(); // empty on no-errors
1831 if(!empty($error)) {
1832 logThis('*** ERROR: query failed.');
1833 $error = getFormattedError($error, $query);
1838 logThis('mssql found: skipping test query - ['.$query.']');
1842 logThis('Oracle found: skipping test query - ['.$query.']');
1845 logThis('verification done.');
1850 * Tests an INSERT INTO query
1851 * @param string table The table name to get DDL
1852 * @param string dbType MySQL, MSSQL, etc.
1853 * @param string query The query to test.
1854 * @return string Non-empty if error found
1856 function testQueryInsert($table, $dbType, $query) {
1857 logThis('verifying INSERT statement...');
1860 $db = &DBManagerFactory::getInstance();
1868 $q = "SHOW CREATE TABLE {$table}";
1869 $r = $db->query($q);
1870 $a = $db->fetchByAssoc($r);
1872 // rewrite DDL with _temp name
1873 $cleanQuery = cleanQuery($a['Create Table']);
1874 $tempTableQuery = str_replace("CREATE TABLE `{$table}`", "CREATE TABLE `{$table}__uw_temp`", $cleanQuery);
1875 $r2 = $db->query($tempTableQuery);
1877 // test the query on the test table
1878 logThis('testing query: ['.$query.']');
1879 $tempTableTestQuery = str_replace("INSERT INTO `{$table}`", "INSERT INTO `{$table}__uw_temp`", $query);
1881 // make sure the test query is running against a temp table
1882 if(isRunningAgainstTrueTable($tempTableTestQuery)) {
1883 $error = getFormattedError('Could not use a temp table to test query!', $tempTableTestQuery);
1887 $r4 = $db->query($tempTableTestQuery, false, "Preflight Failed for: {$query}");
1888 $error = mysql_error(); // empty on no-errors
1889 if(!empty($error)) {
1890 logThis('*** ERROR: query failed.');
1891 $error = getFormattedError($error, $query);
1896 logThis('mssql found: skipping test query - ['.$query.']');
1900 logThis('Oracle found: skipping test query - ['.$query.']');
1903 logThis('verification done.');
1909 * Tests an UPDATE TABLE query
1910 * @param string table The table name to get DDL
1911 * @param string dbType MySQL, MSSQL, etc.
1912 * @param string query The query to test.
1913 * @return string Non-empty if error found
1915 function testQueryUpdate($table, $dbType, $query) {
1916 logThis('verifying UPDATE TABLE statement...');
1919 $db = &DBManagerFactory::getInstance();
1927 $q = "SHOW CREATE TABLE {$table}";
1928 $r = $db->query($q);
1929 $a = $db->fetchByAssoc($r);
1931 // rewrite DDL with _temp name
1932 $cleanQuery = cleanQuery($a['Create Table']);
1933 $tempTableQuery = str_replace("CREATE TABLE `{$table}`", "CREATE TABLE `{$table}__uw_temp`", $cleanQuery);
1934 $r2 = $db->query($tempTableQuery);
1936 // get sample data into the temp table to test for data/constraint conflicts
1937 logThis('inserting temp dataset...');
1938 $q3 = "INSERT INTO `{$table}__uw_temp` SELECT * FROM `{$table}` LIMIT 10";
1939 $r3 = $db->query($q3, false, "Preflight Failed for: {$query}");
1941 // test the query on the test table
1942 logThis('testing query: ['.$query.']');
1943 $tempTableTestQuery = str_replace("UPDATE `{$table}`", "UPDATE `{$table}__uw_temp`", $query);
1945 // make sure the test query is running against a temp table
1946 if(isRunningAgainstTrueTable($tempTableTestQuery)) {
1947 $error = getFormattedError('Could not use a temp table to test query!', $tempTableTestQuery);
1951 $r4 = $db->query($tempTableTestQuery, false, "Preflight Failed for: {$query}");
1952 $error = mysql_error(); // empty on no-errors
1953 if(!empty($error)) {
1954 logThis('*** ERROR: query failed.');
1955 $error = getFormattedError($error, $query);
1963 logThis('Oracle found: skipping test query - ['.$query.']');
1966 logThis('verification done.');
1972 * strip queries of single and double quotes
1974 function stripQuotesUW($query, $table) {
1977 $start = strpos($query, $table);
1979 if(substr($query, ($start - 1), 1) != ' ') {
1980 $queryStrip = substr($query, 0, ($start-2));
1981 $queryStrip .= " {$table} ";
1982 $queryStrip .= substr($query, ($start + strlen($table) + 2), strlen($query));
1985 return (empty($queryStrip)) ? $query : $queryStrip;
1989 * ensures that a __UW_TEMP table test SQL is running against a temp table, not the real thing
1990 * @param string query
1991 * @return bool false if it is a good query
1993 function isRunningAgainstTrueTable($query) {
1994 $query = strtoupper($query);
1995 if(strpos($query, '__UW_TEMP') === false) {
1996 logThis('***ERROR: test query is NOT running against a temp table!!!! -> '.$query);
2011 * cleans up temp tables created during schema test phase
2013 function testCleanUp($dbType) {
2014 logThis('Cleaning up temporary tables...');
2018 $db = &DBManagerFactory::getInstance();
2024 $q = 'SHOW TABLES LIKE "%__uw_temp"';
2025 $r = $db->query($q, false, "Preflight Failed for: {$q}");
2027 // using raw mysql_command to use integer index
2028 while($a = $db->fetchByAssoc($r)) {
2029 logThis('Dropping table: '.$a[0]);
2030 $qClean = "DROP TABLE {$a[0]}";
2031 $rClean = $db->query($qClean);
2041 logThis('Done cleaning up temp tables.');
2046 function getFormattedError($error, $query) {
2047 $error = "<div><b>".$error;
2048 $error .= "</b>::{$query}</div>";
2056 * parses a query finding the table name
2057 * @param string query The query
2058 * @return string table The table
2060 function getTableFromQuery($query) {
2061 $standardQueries = array('ALTER TABLE', 'DROP TABLE', 'CREATE TABLE', 'INSERT INTO', 'UPDATE', 'DELETE FROM');
2062 $query = preg_replace("/[^A-Za-z0-9\_\s]/", "", $query);
2063 $query = trim(str_replace($standardQueries, '', $query));
2065 $firstSpc = strpos($query, " ");
2066 $end = ($firstSpc > 0) ? $firstSpc : strlen($query);
2067 $table = substr($query, 0, $end);
2074 function preLicenseCheck() {
2075 require_once('modules/UpgradeWizard/uw_files.php');
2077 global $sugar_config;
2078 global $mod_strings;
2079 global $sugar_version;
2081 if(!isset($sugar_version) || empty($sugar_version)) {
2082 require_once('./sugar_version.php');
2085 if(!isset($_SESSION['unzip_dir']) || empty($_SESSION['unzip_dir'])) {
2086 logThis('unzipping files in upgrade archive...');
2088 $base_upgrade_dir = $sugar_config['upload_dir'] . "/upgrades";
2089 $base_tmp_upgrade_dir = "$base_upgrade_dir/temp";
2091 //also come up with mechanism to read from upgrade-progress file
2092 if(!isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !is_file($_SESSION['install_file'])) {
2094 if ($handle = opendir(clean_path($sugar_config['upload_dir']))) {
2095 while (false !== ($file = readdir($handle))) {
2096 if($file !="." && $file !="..") {
2097 $far = explode(".",$file);
2098 if($far[sizeof($far)-1] == 'zip') {
2099 echo $sugar_config['upload_dir'].'/'.$file;
2100 $_SESSION['install_file'] = $sugar_config['upload_dir'].'/'.$file;
2106 if (file_exists(clean_path($base_tmp_upgrade_dir)) && $handle = opendir(clean_path($base_tmp_upgrade_dir))) {
2107 while (false !== ($file = readdir($handle))) {
2108 if($file !="." && $file !="..") {
2109 //echo $base_tmp_upgrade_dir."/".$file.'</br>';
2110 if(is_file($base_tmp_upgrade_dir."/".$file."/manifest.php")){
2111 require_once($base_tmp_upgrade_dir."/".$file."/manifest.php");
2112 $package_name= $manifest['copy_files']['from_dir'];
2113 //echo file_exists($base_tmp_upgrade_dir."/".$file."/".$package_name).'</br>';
2114 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")){
2115 //echo 'Yeah this the directory '. $base_tmp_upgrade_dir."/".$file;
2116 $unzip_dir = $base_tmp_upgrade_dir."/".$file;
2117 if(file_exists($sugar_config['upload_dir'].'/upgrades/patch/'.$package_name.'.zip')){
2118 $_SESSION['install_file'] = $sugar_config['upload_dir'].'/upgrades/patch/'.$package_name.'.zip';
2127 if(!isset($_SESSION['install_file']) || empty($_SESSION['install_file'])){
2130 echo 'Upload File not found so redirecting to Upgrade Start ';
2131 $redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
2132 echo '<form name="redirect" action="' .$redirect_new_wizard. '" method="POST">';
2133 $upgrade_directories_not_found =<<<eoq
2134 <table cellpadding="3" cellspacing="0" border="0">
2136 <th colspan="2" align="left">
2137 <span class='error'><b>'Upload file missing or has been deleted. Refresh the page to go back to UpgradeWizard start'</b></span>
2142 $uwMain = $upgrade_directories_not_found;
2145 $install_file = urldecode( $_SESSION['install_file'] );
2147 if(empty($unzip_dir)){
2148 $unzip_dir = mk_temp_dir( $base_tmp_upgrade_dir );
2150 $zip_from_dir = ".";
2152 $zip_force_copy = array();
2155 logThis('Could not create a temporary directory using mk_temp_dir( $base_tmp_upgrade_dir )');
2156 die($mod_strings['ERR_UW_NO_CREATE_TMP_DIR']);
2159 //double check whether unzipped .
2160 if(file_exists($unzip_dir ."/scripts") && file_exists($unzip_dir."/manifest.php")){
2164 unzip( $install_file, $unzip_dir );
2167 // assumption -- already validated manifest.php at time of upload
2168 require_once( "$unzip_dir/manifest.php" );
2170 if( isset( $manifest['copy_files']['from_dir'] ) && $manifest['copy_files']['from_dir'] != "" ){
2171 $zip_from_dir = $manifest['copy_files']['from_dir'];
2173 if( isset( $manifest['copy_files']['to_dir'] ) && $manifest['copy_files']['to_dir'] != "" ){
2174 $zip_to_dir = $manifest['copy_files']['to_dir'];
2176 if( isset( $manifest['copy_files']['force_copy'] ) && $manifest['copy_files']['force_copy'] != "" ){
2177 $zip_force_copy = $manifest['copy_files']['force_copy'];
2179 if( isset( $manifest['version'] ) ){
2180 $version = $manifest['version'];
2182 if( !is_writable( "config.php" ) ){
2183 return $mod_strings['ERR_UW_CONFIG'];
2186 $_SESSION['unzip_dir'] = clean_path($unzip_dir);
2187 $_SESSION['zip_from_dir'] = clean_path($zip_from_dir);
2188 logThis('unzip done.');
2190 $unzip_dir = $_SESSION['unzip_dir'];
2191 $zip_from_dir = $_SESSION['zip_from_dir'];
2194 //check if $_SESSION['unzip_dir'] and $_SESSION['zip_from_dir'] exist
2195 if(!isset($_SESSION['unzip_dir']) || !file_exists($_SESSION['unzip_dir'])
2196 || !isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !file_exists($_SESSION['install_file'])){
2200 echo 'Upload File not found so redirecting to Upgrade Start ';
2201 $redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
2202 echo '<form name="redirect" action="' .$redirect_new_wizard. '" method="POST">';
2203 $upgrade_directories_not_found =<<<eoq
2204 <table cellpadding="3" cellspacing="0" border="0">
2206 <th colspan="2" align="left">
2207 <span class='error'><b>'Upload file missing or has been deleted. Refresh the page to go back to UpgradeWizard start'</b></span>
2212 $uwMain = $upgrade_directories_not_found;
2216 $parserFiles = array();
2218 if(file_exists(clean_path($unzip_dir.'/'.$zip_from_dir."/include/SugarFields"))) {
2219 $parserFiles = findAllFiles(clean_path($unzip_dir.'/'.$zip_from_dir."/include/SugarFields"), $parserFiles);
2222 $cwd = clean_path(getcwd());
2223 foreach($parserFiles as $file) {
2224 $srcFile = clean_path($file);
2225 //$targetFile = clean_path(getcwd() . '/' . $srcFile);
2226 if (strpos($srcFile,".svn") !== false) {
2230 $targetFile = str_replace(clean_path($unzip_dir.'/'.$zip_from_dir), $cwd, $srcFile);
2232 if(!is_dir(dirname($targetFile))) {
2233 mkdir_recursive(dirname($targetFile)); // make sure the directory exists
2236 if(!file_exists($targetFile))
2238 // handle sugar_version.php
2239 // C.L. - Added check for portal directory
2240 if(strpos($targetFile, 'sugar_version.php') !== false && !preg_match('/\/portal\/sugar_version\.php$/i', $targetFile)) {
2241 logThis('Skipping "sugar_version.php" - file copy will occur at end of successful upgrade', $path);
2242 $_SESSION['sugar_version_file'] = $srcFile;
2246 //logThis('Copying file to destination: ' . $targetFile);
2248 if(!copy($srcFile, $targetFile)) {
2249 logThis('*** ERROR: could not copy file: ' . $targetFile);
2251 $copiedFiles[] = $targetFile;
2254 //logThis('Skipping file: ' . $targetFile);
2255 //$skippedFiles[] = $targetFile;
2260 //Also copy the SugarMerge files
2261 if(file_exists(clean_path($unzip_dir.'/'.$zip_from_dir."/UpgradeWizard510Files"))) {
2262 $parserFiles = findAllFiles(clean_path($unzip_dir.'/'.$zip_from_dir."/UpgradeWizard510Files"), $parserFiles);
2263 foreach($parserFiles as $file) {
2264 $srcFile = clean_path($file);
2265 //$targetFile = clean_path(getcwd() . '/' . $srcFile);
2266 if (strpos($srcFile,".svn") !== false) {
2270 $targetFile = str_replace(clean_path($unzip_dir.'/'.$zip_from_dir."/UpgradeWizard510Files"), $cwd, $srcFile);
2271 if(!is_dir(dirname($targetFile))) {
2272 mkdir_recursive(dirname($targetFile)); // make sure the directory exists
2274 logThis('updating UpgradeWizard code: '.$targetFile);
2275 copy_recursive($file, $targetFile);
2279 logThis ('is SugarConfig there '.file_exists(clean_path($unzip_dir.'/'.$zip_from_dir."/include/SugarObjects/SugarConfig.php")));
2280 if(file_exists(clean_path($unzip_dir.'/'.$zip_from_dir."/include/SugarObjects/SugarConfig.php"))) {
2281 $file = clean_path($unzip_dir.'/'.$zip_from_dir."/include/SugarObjects/SugarConfig.php");
2282 $destFile = str_replace(clean_path($unzip_dir.'/'.$zip_from_dir), $cwd, $file);
2283 if(!is_dir(dirname($destFile))) {
2284 mkdir_recursive(dirname($destFile)); // make sure the directory exists
2286 copy($file,$destFile);
2287 //also copy include utils array utils
2288 $file = clean_path($unzip_dir.'/'.$zip_from_dir."/include/utils/array_utils.php");
2289 $destFile = str_replace(clean_path($unzip_dir.'/'.$zip_from_dir), $cwd, $file);
2290 if(!is_dir(dirname($destFile))) {
2291 mkdir_recursive(dirname($destFile)); // make sure the directory exists
2293 copy($file,$destFile);
2298 function preflightCheck() {
2299 require_once('modules/UpgradeWizard/uw_files.php');
2301 global $sugar_config;
2302 global $mod_strings;
2303 global $sugar_version;
2305 if(!isset($sugar_version) || empty($sugar_version)) {
2306 require_once('./sugar_version.php');
2309 unset($_SESSION['rebuild_relationships']);
2310 unset($_SESSION['rebuild_extensions']);
2312 // don't bother if are rechecking
2313 $manualDiff = array();
2314 if(!isset($_SESSION['unzip_dir']) || empty($_SESSION['unzip_dir'])) {
2315 logThis('unzipping files in upgrade archive...');
2317 $base_upgrade_dir = $sugar_config['upload_dir'] . "/upgrades";
2318 $base_tmp_upgrade_dir = "$base_upgrade_dir/temp";
2320 //Following is if User logged out unexpectedly and then logged into UpgradeWizard again.
2321 //also come up with mechanism to read from upgrade-progress file.
2322 if(!isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !is_file($_SESSION['install_file'])) {
2323 if (file_exists(clean_path($base_tmp_upgrade_dir)) && $handle = opendir(clean_path($base_tmp_upgrade_dir))) {
2324 while (false !== ($file = readdir($handle))) {
2325 if($file !="." && $file !="..") {
2326 //echo $base_tmp_upgrade_dir."/".$file.'</br>';
2327 if(is_file($base_tmp_upgrade_dir."/".$file."/manifest.php")){
2328 require_once($base_tmp_upgrade_dir."/".$file."/manifest.php");
2329 $package_name= $manifest['copy_files']['from_dir'];
2330 //echo file_exists($base_tmp_upgrade_dir."/".$file."/".$package_name).'</br>';
2331 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")){
2332 //echo 'Yeah this the directory '. $base_tmp_upgrade_dir."/".$file;
2333 $unzip_dir = $base_tmp_upgrade_dir."/".$file;
2334 if(file_exists($sugar_config['upload_dir'].'/upgrades/patch/'.$package_name.'.zip')){
2335 $_SESSION['install_file'] = $sugar_config['upload_dir'].'/upgrades/patch/'.$package_name.'.zip';
2344 if(!isset($_SESSION['install_file']) || empty($_SESSION['install_file'])){
2347 echo 'Upload File not found so redirecting to Upgrade Start ';
2348 $redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
2349 echo '<form name="redirect" action="' .$redirect_new_wizard. '" method="POST">';
2350 $upgrade_directories_not_found =<<<eoq
2351 <table cellpadding="3" cellspacing="0" border="0">
2353 <th colspan="2" align="left">
2354 <span class='error'><b>'Upload file missing or has been deleted. Refresh the page to go back to UpgradeWizard start'</b></span>
2359 $uwMain = $upgrade_directories_not_found;
2363 $install_file = urldecode( $_SESSION['install_file'] );
2365 if(empty($unzip_dir)){
2366 $unzip_dir = mk_temp_dir( $base_tmp_upgrade_dir );
2368 $zip_from_dir = ".";
2370 $zip_force_copy = array();
2373 logThis('Could not create a temporary directory using mk_temp_dir( $base_tmp_upgrade_dir )');
2374 die($mod_strings['ERR_UW_NO_CREATE_TMP_DIR']);
2377 //double check whether unzipped .
2378 if(file_exists($unzip_dir ."/scripts") && file_exists($unzip_dir."/manifest.php")){
2382 unzip( $install_file, $unzip_dir );
2385 // assumption -- already validated manifest.php at time of upload
2386 require_once( "$unzip_dir/manifest.php" );
2388 if( isset( $manifest['copy_files']['from_dir'] ) && $manifest['copy_files']['from_dir'] != "" ){
2389 $zip_from_dir = $manifest['copy_files']['from_dir'];
2391 if( isset( $manifest['copy_files']['to_dir'] ) && $manifest['copy_files']['to_dir'] != "" ){
2392 $zip_to_dir = $manifest['copy_files']['to_dir'];
2394 if( isset( $manifest['copy_files']['force_copy'] ) && $manifest['copy_files']['force_copy'] != "" ){
2395 $zip_force_copy = $manifest['copy_files']['force_copy'];
2397 if( isset( $manifest['version'] ) ){
2398 $version = $manifest['version'];
2400 if( !is_writable( "config.php" ) ){
2401 return $mod_strings['ERR_UW_CONFIG'];
2404 $_SESSION['unzip_dir'] = clean_path($unzip_dir);
2405 $_SESSION['zip_from_dir'] = clean_path($zip_from_dir);
2407 //logThis('unzip done.');
2409 $unzip_dir = $_SESSION['unzip_dir'];
2410 $zip_from_dir = $_SESSION['zip_from_dir'];
2412 //check if $_SESSION['unzip_dir'] and $_SESSION['zip_from_dir'] exist
2413 if(!isset($_SESSION['unzip_dir']) || !file_exists($_SESSION['unzip_dir'])
2414 || !isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !file_exists($_SESSION['install_file'])){
2418 echo 'Upload File not found so redirecting to Upgrade Start ';
2419 $redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
2420 echo '<form name="redirect" action="' .$redirect_new_wizard. '" method="POST">';
2421 $upgrade_directories_not_found =<<<eoq
2422 <table cellpadding="3" cellspacing="0" border="0">
2424 <th colspan="2" align="left">
2425 <span class='error'><b>'Upload file missing or has been deleted. Refresh the page to go back to UpgradeWizard start'</b></span>
2430 $uwMain = $upgrade_directories_not_found;
2433 //copy minimum required files
2434 fileCopy('include/utils/sugar_file_utils.php');
2437 if(file_exists('include/utils/file_utils.php')){
2440 $upgradeFiles = findAllFiles(clean_path("$unzip_dir/$zip_from_dir"), array());
2441 $cache_html_files= array();
2442 if(is_dir("{$GLOBALS['sugar_config']['cache_dir']}layout")){
2443 //$cache_html_files = findAllFilesRelative( "cache/layout", array());
2447 $md5_string = array();
2448 if(file_exists(clean_path(getcwd().'/files.md5'))){
2449 require(clean_path(getcwd().'/files.md5'));
2452 // file preflight checks
2453 logThis('verifying md5 checksums for files...');
2454 foreach($upgradeFiles as $file) {
2455 if(in_array(str_replace(clean_path("$unzip_dir/$zip_from_dir") . "/", '', $file), $uw_files))
2456 continue; // skip already loaded files
2458 if(strpos($file, '.md5'))
2459 continue; // skip md5 file
2461 // normalize file paths
2462 $file = clean_path($file);
2464 // check that we can move/delete the upgraded file
2465 if(!is_writable($file)) {
2466 $errors[] = $mod_strings['ERR_UW_FILE_NOT_WRITABLE'].": ".$file;
2468 // check that destination files are writable
2469 $destFile = getcwd().str_replace(clean_path($unzip_dir.'/'.$zip_from_dir), '', $file);
2471 if(is_file($destFile)) { // of course it needs to exist first...
2472 if(!is_writable($destFile)) {
2473 $errors[] = $mod_strings['ERR_UW_FILE_NOT_WRITABLE'].": ".$destFile;
2477 ///////////////////////////////////////////////////////////////////////
2479 // compare md5s and build up a manual merge list
2480 $targetFile = clean_path(".".str_replace(getcwd(),'',$destFile));
2482 if(is_file($destFile)) {
2483 if(strpos($targetFile, '.php')) {
2484 // handle PHP files that were hit with the security regex
2486 if(function_exists('sugar_fopen')){
2487 $fp = sugar_fopen($destFile, 'r');
2490 $fp = fopen($destFile, 'r');
2492 $filesize = filesize($destFile);
2494 $fileContents = stream_get_contents($fp);
2495 $targetMd5 = md5($fileContents);
2498 $targetMd5 = md5_file($destFile);
2502 if(isset($md5_string[$targetFile]) && $md5_string[$targetFile] != $targetMd5) {
2503 logThis('found a file with a differing md5: ['.$targetFile.']');
2504 $manualDiff[] = $destFile;
2507 ///////////////////////////////////////////////////////////////////////
2509 logThis('md5 verification done.');
2510 $errors['manual'] = $manualDiff;
2515 function fileCopy($file_path){
2516 if(file_exists(clean_path($_SESSION['unzip_dir'].'/'.$_SESSION['zip_from_dir'].'/'.$file_path))) {
2517 $file = clean_path($_SESSION['unzip_dir'].'/'.$_SESSION['zip_from_dir'].'/'.$file_path);
2518 $destFile = str_replace(clean_path($_SESSION['unzip_dir'].'/'.$_SESSION['zip_from_dir']), clean_path(getcwd()), $file);
2519 if(!is_dir(dirname($destFile))) {
2520 mkdir_recursive(dirname($destFile)); // make sure the directory exists
2522 copy_recursive($file,$destFile);
2525 function getChecklist($steps, $step) {
2526 global $mod_strings;
2528 $skip = array('start', 'cancel', 'uninstall','end');
2531 $ret = '<table cellpadding="3" cellspacing="4" border="0">';
2532 $ret .= '<tr><th colspan="3" align="left">'.$mod_strings['LBL_UW_CHECKLIST'].':</th></tr>';
2533 foreach($steps['desc'] as $k => $desc) {
2534 if(in_array($steps['files'][$j], $skip)) {
2539 //$status = "<span class='error'>{$mod_strings['LBL_UW_INCOMPLETE']}</span>";
2541 $desc_mod_post = '';
2543 if(isset($_SESSION['step'][$steps['files'][$k]]) && $_SESSION['step'][$steps['files'][$k]] == 'success') {
2544 //$status = $mod_strings['LBL_UW_COMPLETE'];
2548 if($k == $_REQUEST['step']) {
2549 //$status = $mod_strings['LBL_UW_IN_PROGRESS'];
2550 $desc_mod_pre = "<font color=blue><i>";
2551 $desc_mod_post = "</i></font>";
2554 $ret .= "<tr><td> </td><td><b>{$i}: {$desc_mod_pre}{$desc}{$desc_mod_post}</b></td>";
2555 $ret .= "<td id={$steps['files'][$j]}><i></i></td></tr>";
2563 function prepSystemForUpgrade() {
2564 global $sugar_config;
2565 global $sugar_flavor;
2566 global $mod_strings;
2568 global $base_upgrade_dir;
2569 global $base_tmp_upgrade_dir;
2571 ///////////////////////////////////////////////////////////////////////////////
2572 //// Make sure variables exist
2573 if(!isset($base_upgrade_dir) || empty($base_upgrade_dir)){
2574 $base_upgrade_dir = getcwd().'/'.$sugar_config['upload_dir'] . "upgrades";
2576 if(!isset($base_tmp_upgrade_dir) || empty($base_tmp_upgrade_dir)){
2577 $base_tmp_upgrade_dir = "$base_upgrade_dir/temp";
2579 if(!isset($subdirs) || empty($subdirs)){
2580 $subdirs = array('full', 'langpack', 'module', 'patch', 'theme', 'temp');
2583 $upgrade_progress_dir = getcwd().'/'.$GLOBALS['sugar_config']['upload_dir'].'upgrades/temp';
2584 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
2585 if(file_exists($upgrade_progress_file)){
2586 if(function_exists('get_upgrade_progress') && function_exists('didThisStepRunBefore')){
2587 if(didThisStepRunBefore('end')){
2588 include($upgrade_progress_file);
2589 unset($upgrade_config);
2590 unlink($upgrade_progress_file);
2595 // increase the cuttoff time to 1 hour
2596 ini_set("max_execution_time", "3600");
2598 // make sure dirs exist
2599 if($subdirs != null){
2600 foreach($subdirs as $subdir) {
2601 mkdir_recursive("$base_upgrade_dir/$subdir");
2604 // array of special scripts that are executed during (un)installation-- key is type of script, value is filename
2605 if(!defined('SUGARCRM_PRE_INSTALL_FILE')) {
2606 define('SUGARCRM_PRE_INSTALL_FILE', 'scripts/pre_install.php');
2607 define('SUGARCRM_POST_INSTALL_FILE', 'scripts/post_install.php');
2608 define('SUGARCRM_PRE_UNINSTALL_FILE', 'scripts/pre_uninstall.php');
2609 define('SUGARCRM_POST_UNINSTALL_FILE', 'scripts/post_uninstall.php');
2612 $script_files = array(
2613 "pre-install" => constant('SUGARCRM_PRE_INSTALL_FILE'),
2614 "post-install" => constant('SUGARCRM_POST_INSTALL_FILE'),
2615 "pre-uninstall" => constant('SUGARCRM_PRE_UNINSTALL_FILE'),
2616 "post-uninstall" => constant('SUGARCRM_POST_UNINSTALL_FILE'),
2619 // check that the upload limit is set to 6M or greater
2620 define('SUGARCRM_MIN_UPLOAD_MAX_FILESIZE_BYTES', 6 * 1024 * 1024); // 6 Megabytes
2621 $upload_max_filesize = ini_get('upload_max_filesize');
2622 $upload_max_filesize_bytes = return_bytes($upload_max_filesize);
2624 if($upload_max_filesize_bytes < constant('SUGARCRM_MIN_UPLOAD_MAX_FILESIZE_BYTES')) {
2625 $GLOBALS['log']->debug("detected upload_max_filesize: $upload_max_filesize");
2627 echo '<p class="error">'.$mod_strings['MSG_INCREASE_UPLOAD_MAX_FILESIZE'].' '.get_cfg_var('cfg_file_path')."</p>\n";
2631 if ( !function_exists('extractFile') ) {
2632 function extractFile($zip_file, $file_in_zip) {
2633 global $base_tmp_upgrade_dir;
2636 $absolute_base_tmp_upgrade_dir = clean_path($base_tmp_upgrade_dir);
2637 $relative_base_tmp_upgrade_dir = clean_path(str_replace(clean_path(getcwd()), '', $absolute_base_tmp_upgrade_dir));
2639 // mk_temp_dir expects relative pathing
2640 $my_zip_dir = mk_temp_dir($relative_base_tmp_upgrade_dir);
2642 unzip_file($zip_file, $file_in_zip, $my_zip_dir);
2644 return("$my_zip_dir/$file_in_zip");
2648 if ( !function_exists('extractManifest') ) {
2649 function extractManifest($zip_file) {
2650 logThis('extracting manifest.');
2651 return(extractFile($zip_file, "manifest.php"));
2655 if ( !function_exists('getInstallType') ) {
2656 function getInstallType($type_string) {
2659 $subdirs = array('full', 'langpack', 'module', 'patch', 'theme', 'temp');
2660 foreach($subdirs as $subdir) {
2661 if(preg_match("#/$subdir/#", $type_string)) {
2665 // return empty if no match
2670 function getImageForType($type) {
2675 $icon = SugarThemeRegistry::current()->getImage("Upgrade", "");
2678 $icon = SugarThemeRegistry::current()->getImage("LanguagePacks", "");
2681 $icon = SugarThemeRegistry::current()->getImage("ModuleLoader", "");
2684 $icon = SugarThemeRegistry::current()->getImage("PatchUpgrades", "");
2687 $icon = SugarThemeRegistry::current()->getImage("Themes", "");
2695 if ( !function_exists('getLanguagePackName') ) {
2696 function getLanguagePackName($the_file) {
2697 require_once("$the_file");
2698 if(isset($app_list_strings["language_pack_name"])) {
2699 return($app_list_strings["language_pack_name"]);
2705 function getUITextForType($type) {
2706 if($type == "full") {
2707 return("Full Upgrade");
2709 if($type == "langpack") {
2710 return("Language Pack");
2712 if($type == "module") {
2715 if($type == "patch") {
2718 if($type == "theme") {
2725 * @todo this function doesn't seemed to be used anymore; trying kill this off
2727 function run_upgrade_wizard_sql($script) {
2729 global $sugar_config;
2731 $db_type = $sugar_config['dbconfig']['db_type'];
2732 $script = str_replace("%db_type%", $db_type, $script);
2733 if(!run_sql_file("$unzip_dir/$script")) {
2734 die("Error running sql file: $unzip_dir/$script");
2738 if ( !function_exists('validate_manifest') ) {
2740 * Verifies a manifest from a patch or module to be compatible with the current Sugar version and flavor
2741 * @param array manifest Standard manifest array
2742 * @return string Error message, blank on success
2744 function validate_manifest($manifest) {
2745 logThis('validating manifest.php file');
2746 // takes a manifest.php manifest array and validates contents
2748 global $sugar_version;
2749 global $sugar_flavor;
2750 global $mod_strings;
2752 if(!isset($manifest['type'])) {
2753 return $mod_strings['ERROR_MANIFEST_TYPE'];
2756 $type = $manifest['type'];
2758 if(getInstallType("/$type/") == "") {
2759 return $mod_strings['ERROR_PACKAGE_TYPE']. ": '" . $type . "'.";
2762 if(isset($manifest['acceptable_sugar_versions'])) {
2763 $version_ok = false;
2764 $matches_empty = true;
2765 if(isset($manifest['acceptable_sugar_versions']['exact_matches'])) {
2766 $matches_empty = false;
2767 foreach($manifest['acceptable_sugar_versions']['exact_matches'] as $match) {
2768 if($match == $sugar_version) {
2773 if(!$version_ok && isset($manifest['acceptable_sugar_versions']['regex_matches'])) {
2774 $matches_empty = false;
2775 foreach($manifest['acceptable_sugar_versions']['regex_matches'] as $match) {
2776 if(preg_match("/$match/", $sugar_version)) {
2782 if(!$matches_empty && !$version_ok) {
2783 return $mod_strings['ERROR_VERSION_INCOMPATIBLE']."<br />".
2784 $mod_strings['ERR_UW_VERSION'].$sugar_version;
2788 if(isset($manifest['acceptable_sugar_flavors']) && sizeof($manifest['acceptable_sugar_flavors']) > 0) {
2790 foreach($manifest['acceptable_sugar_flavors'] as $match) {
2791 if($match == $sugar_flavor) {
2796 return $mod_strings['ERROR_FLAVOR_INCOMPATIBLE']."<br />".
2797 $mod_strings['ERR_UW_FLAVOR'].$sugar_flavor."<br />".
2798 $mod_strings['ERR_UW_FLAVOR_2'].$manifest['acceptable_sugar_flavors'][0];
2806 function unlinkUploadFiles() {
2808 // logThis('at unlinkUploadFiles()');
2810 // if(isset($_SESSION['install_file']) && !empty($_SESSION['install_file'])) {
2811 // $upload = $_SESSION['install_file'];
2813 // if(is_file($upload)) {
2814 // logThis('unlinking ['.$upload.']');
2815 // @unlink($upload);
2820 if ( !function_exists('unlinkTempFiles') ) {
2822 * deletes files created by unzipping a package
2824 function unlinkTempFiles() {
2825 global $sugar_config;
2828 logThis('at unlinkTempFiles()');
2830 $sugar_config['upload_dir']='cache/upload/';
2831 //if(isset($sugar_config['upload_dir']) && $sugar_config['upload_dir'] != null && $sugar_config['upload_dir']=='cache/upload/'){
2832 $tempDir = clean_path(getcwd().'/'.$sugar_config['upload_dir'].'upgrades/temp');
2835 $uploadDir = getcwd()."/".'cache/upload/';
2836 $tempDir = clean_path(getcwd().'/'.$uploadDir.'upgrades/temp');
2838 if(file_exists($tempDir) && is_dir($tempDir)){
2839 $files = findAllFiles($tempDir, array(), false);
2841 foreach($files as $file) {
2842 if(!is_dir($file)) {
2843 //logThis('unlinking ['.$file.']', $path);
2848 $files = findAllFiles($tempDir, array(), true);
2849 foreach($files as $dir) {
2851 //logThis('removing dir ['.$dir.']', $path);
2855 $cacheFile = "modules/UpgradeWizard/_persistence.php";
2856 if(is_file($cacheFile)) {
2857 logThis("Unlinking Upgrade cache file: '_persistence.php'", $path);
2858 @unlink($cacheFile);
2861 logThis("finished!");
2866 * finds all files in the passed path, but skips select directories
2867 * @param string dir Relative path
2868 * @param array the_array Collections of found files/dirs
2869 * @param bool include_dir True if we want to include directories in the
2870 * returned collection
2872 function uwFindAllFiles($dir, $the_array, $include_dirs=false, $skip_dirs=array(), $echo=false) {
2874 foreach($skip_dirs as $skipMe) {
2875 if(strpos(clean_path($dir), $skipMe) !== false) {
2880 if (!is_dir($dir)) { return $the_array; } // Bug # 46035, just checking for valid dir
2882 if ($d === false) { return $the_array; } // Bug # 46035, more checking
2884 while($f = $d->read()) {
2885 if($f == "." || $f == "..") { // skip *nix self/parent
2889 // for AJAX length count
2895 if(is_dir("$dir/$f")) {
2896 if($include_dirs) { // add the directory if flagged
2897 $the_array[] = clean_path("$dir/$f");
2901 $the_array = uwFindAllFiles("$dir/$f/", $the_array, $include_dirs, $skip_dirs, $echo);
2903 $the_array[] = clean_path("$dir/$f");
2915 * unset's UW's Session Vars
2917 function resetUwSession() {
2918 logThis('resetting $_SESSION');
2920 if(isset($_SESSION['committed']))
2921 unset($_SESSION['committed']);
2922 if(isset($_SESSION['sugar_version_file']))
2923 unset($_SESSION['sugar_version_file']);
2924 if(isset($_SESSION['upgrade_complete']))
2925 unset($_SESSION['upgrade_complete']);
2926 if(isset($_SESSION['allTables']))
2927 unset($_SESSION['allTables']);
2928 if(isset($_SESSION['alterCustomTableQueries']))
2929 unset($_SESSION['alterCustomTableQueries']);
2930 if(isset($_SESSION['skip_zip_upload']))
2931 unset($_SESSION['skip_zip_upload']);
2932 if(isset($_SESSION['sugar_version_file']))
2933 unset($_SESSION['sugar_version_file']);
2934 if(isset($_SESSION['install_file']))
2935 unset($_SESSION['install_file']);
2936 if(isset($_SESSION['unzip_dir']))
2937 unset($_SESSION['unzip_dir']);
2938 if(isset($_SESSION['zip_from_dir']))
2939 unset($_SESSION['zip_from_dir']);
2940 if(isset($_SESSION['overwrite_files']))
2941 unset($_SESSION['overwrite_files']);
2942 if(isset($_SESSION['schema_change']))
2943 unset($_SESSION['schema_change']);
2944 if(isset($_SESSION['uw_restore_dir']))
2945 unset($_SESSION['uw_restore_dir']);
2946 if(isset($_SESSION['step']))
2947 unset($_SESSION['step']);
2948 if(isset($_SESSION['files']))
2949 unset($_SESSION['files']);
2950 if(isset($_SESSION['Upgraded451Wizard'])){
2951 unset($_SESSION['Upgraded451Wizard']);
2953 if(isset($_SESSION['Initial_451to500_Step'])){
2954 unset($_SESSION['Initial_451to500_Step']);
2956 if(isset($_SESSION['license_shown']))
2957 unset($_SESSION['license_shown']);
2958 if(isset($_SESSION['sugarMergeRunResults']))
2959 unset($_SESSION['sugarMergeRunResults']);
2963 * runs rebuild scripts
2965 function UWrebuild() {
2969 //CCL - Comment this block out, it is called in end.php
2970 logThis('Rebuilding everything...', $path);
2971 require_once('modules/Administration/QuickRepairAndRebuild.php');
2972 $randc = new RepairAndClear();
2973 $randc->repairAndClearAll(array('clearAll'),array(translate('LBL_ALL_MODULES')), false, false);
2975 $query = "DELETE FROM versions WHERE name='Rebuild Extensions'";
2977 logThis('Registering rebuild record: '.$query, $path);
2978 logThis('Rebuild done.', $path);
2980 // insert a new database row to show the rebuild extensions is done
2981 $id = create_guid();
2982 $gmdate = gmdate('Y-m-d H:i:s');
2983 $date_entered = db_convert("'$gmdate'", 'datetime');
2984 $query = 'INSERT INTO versions (id, deleted, date_entered, date_modified, modified_user_id, created_by, name, file_version, db_version) '
2985 . "VALUES ('$id', '0', $date_entered, $date_entered, '1', '1', 'Rebuild Extensions', '4.0.0', '4.0.0')";
2987 logThis('Registering rebuild record in versions table: '.$query, $path);
2990 function getCustomTables($dbType) {
2993 $customTables = array();
2997 $query = "SHOW tables LIKE '%_cstm'";
2998 $result = $db->query($query);//, true, 'Error getting custom tables');
2999 while ($row = $db->fetchByAssoc($result)){
3000 $customTables[] = array_pop($row);
3004 return $customTables;
3007 function alterCustomTables($dbType, $customTables)
3012 while( $i < count($customTables) ) {
3013 $alterCustomTableSql[] = "ALTER TABLE " . $customTables[$i] . " CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci";
3020 return $alterCustomTableSql;
3023 function executeAlterCustomTablesSql($dbType, $queries) {
3026 foreach($queries as $query){
3028 logThis("Sending query: ".$query);
3029 if($db->dbType == 'oci8') {
3031 $query_result = $db->query($query);//.';', true, "An error has occured while performing db query. See log file for details.<br>");
3038 function getAllTables($dbType) {
3045 $query = "SHOW tables";
3046 $result = $db->query($query, true, 'Error getting custom tables');
3047 while ($row = $db->fetchByAssoc($result)){
3048 $tables[] = array_pop($row);
3055 function printAlterTableSql($tables)
3057 $alterTableSql = '';
3059 foreach($tables as $table)
3060 $alterTableSql .= "ALTER TABLE " . $table . " CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;" . "\n";
3062 return $alterTableSql;
3065 function executeConvertTablesSql($dbType, $tables) {
3068 foreach($tables as $table){
3069 $query = "ALTER TABLE " . $table . " CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci";
3071 logThis("Sending query: ".$query);
3072 if($db->dbType == 'oci8') {
3074 $query_result = $db->query($query);//.';', true, "An error has occured while performing db query. See log file for details.<br>");
3081 function testThis() {
3082 $files = uwFindAllFiles(getcwd().'/test', array());
3084 $out = "<table cellpadding='1' cellspacing='0' border='0'>\n";
3087 foreach($files as $file) {
3088 $relativeFile = clean_path(str_replace(getcwd().'/test', '', $file));
3089 $relativeFile = ($relativeFile{0} == '/') ? substr($relativeFile, 1, strlen($relativeFile)) : $relativeFile;
3091 $relativePath = dirname($relativeFile);
3093 if($relativePath == $priorPath) { // same dir, new file
3094 $out .= "<tr><td>".basename($relativeFile)."</td></tr>";
3095 $priorPath = $relativePath;
3109 function testThis2($dir, $id=0, $hide=false) {
3111 $dh = opendir($dir);
3114 $doHide = ($hide) ? 'none' : '';
3115 $out = "<div id='{$id}' style='display:{$doHide};'>";
3116 $out .= "<table cellpadding='1' cellspacing='0' border='0' style='border:0px solid #ccc'>\n";
3118 while($file = readdir($dh)) {
3119 if($file == '.' || $file == '..' || $file == 'CVS' || $file == '.cvsignore')
3122 if(is_dir($path.'/'.$file)) {
3123 $file = $path.'/'.$file;
3124 $newI = create_guid();
3125 $out .= "<tr><td valign='top'><a href='javascript:toggleNwFiles(\"{$newI}\");'><img border='0' src='".SugarThemeRegistry::current()->getImageURL('Workflow.gif')."'></a></td>\n";
3126 $out .= "<td valign='top'><b><a href='javascript:toggleNwFiles(\"{$newI}\");'>".basename($file)."</a></b></td></tr>";
3127 $out .= "<tr><td></td><td valign='top'>".testThis2($file, $newI, true)."</td></tr>";
3129 $out .= "<tr><td valign='top'> </td>\n";
3130 $out .= "<td valign='top'>".basename($file)."</td></tr>";
3134 $out .= "</tr></table>";
3145 function testThis3(&$files, $id, $hide, $previousPath = '') {
3146 if(!is_array($files) || empty($files))
3151 // expecting full path here
3152 foreach($files as $k => $file) {
3153 $file = str_replace(getcwd(), '', $file);
3154 $path = dirname($file);
3155 $fileName = basename($file);
3157 if($fileName == 'CVS' || $fileName == '.cvsignore')
3160 if($path == $previousPath) { // same directory
3161 // new row for each file
3162 $out .= "<tr><td valign='top' align='left'> </td>";
3163 $out .= "<td valign='top' align='left'>{$fileName}</td></tr>";
3164 } else { // new directory
3166 $out .= "<tr><td valign='top'><a href='javascript:toggleNwFiles(\"{$newI}\");'><img border='0' src='".SugarThemeRegistry::current()->getImageURL('Workflow.gif')."></a></td>\n";
3167 $out .= "<td valign='top'><b><a href='javascript:toggleNwFiles(\"{$newI}\");'>".$fileName."</a></b></td></tr>";
3168 $recurse = testThis3($files, $newI, true, $previousPath);
3169 $out .= "<tr><td></td><td valign='top'>".$recurse."</td></tr>";
3172 $previousPath = $path;
3174 $display = ($hide) ? 'none' : '';
3176 <div id="{$id}" style="display:{$display}">
3177 <table cellpadding='1' cellspacing='0' border='0' style='border:1px solid #ccc'>
3186 function testThis4($filePath, $fileNodes=array(), $fileName='') {
3187 $path = dirname($filePath);
3188 $file = basename($filePath);
3190 $exFile = explode('/', $path);
3192 foreach($exFile as $pathSegment) {
3193 if(is_array($fileNodes[$pathSegment])) { // path already processed
3195 } else { // newly found path
3196 $fileNodes[$pathSegment] = array();
3199 if($fileName != '') {
3200 $fileNodes[$pathSegment][] = $fileName;
3209 ///////////////////////////////////////////////////////////////////////////////
3210 //// SYSTEM CHECK FUNCTIONS
3212 * generates an array with all files in the SugarCRM root directory, skipping
3214 * @return array files Array of files with absolute paths
3216 function getFilesForPermsCheck() {
3217 global $sugar_config;
3219 logThis('Got JSON call to find all files...');
3220 $filesNotWritable = array();
3221 $filesNWPerms = array();
3223 // add directories here that should be skipped when doing file permissions checks (cache/upload is the nasty one)
3225 $sugar_config['upload_dir'],
3227 $files = uwFindAllFiles(getcwd(), array(), true, $skipDirs, true);
3232 * checks files for permissions
3233 * @param array files Array of files with absolute paths
3234 * @return string result of check
3236 function checkFiles($files, $echo=false) {
3237 global $mod_strings;
3238 $filesNotWritable = array();
3241 <a href='javascript:void(0); toggleNwFiles(\"filesNw\");'>{$mod_strings['LBL_UW_SHOW_NW_FILES']}</a>
3242 <div id='filesNw' style='display:none;'>
3243 <table cellpadding='3' cellspacing='0' border='0'>
3245 <th align='left'>{$mod_strings['LBL_UW_FILE']}</th>
3246 <th align='left'>{$mod_strings['LBL_UW_FILE_PERMS']}</th>
3247 <th align='left'>{$mod_strings['LBL_UW_FILE_OWNER']}</th>
3248 <th align='left'>{$mod_strings['LBL_UW_FILE_GROUP']}</th>
3251 $isWindows = is_windows();
3252 foreach($files as $file) {
3255 if(!is_writable_windows($file)) {
3256 logThis('WINDOWS: File ['.$file.'] not readable - saving for display');
3257 // don't warn yet - we're going to use this to check against replacement files
3258 // aw: commented out; it's a hack to allow upgrade wizard to continue on windows... will fix later
3259 /*$filesNotWritable[$i] = $file;
3260 $filesNWPerms[$i] = substr(sprintf('%o',fileperms($file)), -4);
3261 $filesOut .= "<tr>".
3262 "<td><span class='error'>{$file}</span></td>".
3263 "<td>{$filesNWPerms[$i]}</td>".
3264 "<td>".$mod_strings['ERR_UW_CANNOT_DETERMINE_USER']."</td>".
3265 "<td>".$mod_strings['ERR_UW_CANNOT_DETERMINE_GROUP']."</td>".
3269 if(!is_writable($file)) {
3270 logThis('File ['.$file.'] not writable - saving for display');
3271 // don't warn yet - we're going to use this to check against replacement files
3272 $filesNotWritable[$i] = $file;
3273 $filesNWPerms[$i] = substr(sprintf('%o',fileperms($file)), -4);
3274 $owner = posix_getpwuid(fileowner($file));
3275 $group = posix_getgrgid(filegroup($file));
3276 $filesOut .= "<tr>".
3277 "<td><span class='error'>{$file}</span></td>".
3278 "<td>{$filesNWPerms[$i]}</td>".
3279 "<td>".$owner['name']."</td>".
3280 "<td>".$group['name']."</td>".
3287 $filesOut .= '</table></div>';
3289 $errors['files']['filesNotWritable'] = (count($filesNotWritable) > 0) ? true : false;
3290 if(count($filesNotWritable) < 1) {
3291 $filesOut = "{$mod_strings['LBL_UW_FILE_NO_ERRORS']}";
3297 function deletePackageOnCancel(){
3298 global $mod_strings;
3299 global $sugar_config;
3300 logThis('running delete');
3301 if(!isset($_SESSION['install_file']) || ($_SESSION['install_file'] == "")) {
3302 logThis('ERROR: trying to delete non-existent file: ['.$_REQUEST['install_file'].']');
3303 $error = $mod_strings['ERR_UW_NO_FILE_UPLOADED'];
3305 // delete file in upgrades/patch
3306 $delete_me = urldecode( $_SESSION['install_file'] );
3307 if(@unlink($delete_me)) {
3308 //logThis('unlinking: '.$delete_me);
3309 $out = basename($delete_me).$mod_strings['LBL_UW_FILE_DELETED'];
3311 logThis('ERROR: could not delete ['.$delete_me.']');
3312 $error = $mod_strings['ERR_UW_FILE_NOT_DELETED'].$delete_me;
3315 // delete file in cache/upload
3316 $fileS = explode('/', $delete_me);
3318 $fileName = (isset($fileS[$c-1]) && !empty($fileS[$c-1])) ? $fileS[$c-1] : $fileS[$c-2];
3319 $deleteUpload = getcwd().'/'.$sugar_config['upload_dir'].$fileName;
3320 logThis('Trying to delete '.$deleteUpload);
3321 if(!@unlink($deleteUpload)) {
3322 logThis('ERROR: could not delete: ['.$deleteUpload.']');
3323 $error = $mod_strings['ERR_UW_FILE_NOT_DELETED'].$sugar_config['upload_dir'].$fileName;
3325 if(!empty($error)) {
3326 $out = "<b><span class='error'>{$error}</span></b><br />";
3331 function parseAndExecuteSqlFile($sqlScript,$forStepQuery='',$resumeFromQuery=''){
3332 global $sugar_config;
3333 $alterTableSchema = '';
3334 $sqlErrors = array();
3335 if(!isset($_SESSION['sqlSkippedQueries'])){
3336 $_SESSION['sqlSkippedQueries'] = array();
3338 $db = & DBManagerFactory::getInstance();
3340 if($sugar_config['dbconfig']['db_type'] == 'mysql') {
3343 if($sugar_config['dbconfig']['db_type'] == 'oci8'){
3344 $db->query("CREATE OR REPLACE FUNCTION blob_to_clob (blob_in IN BLOB)
3348 v_varchar VARCHAR2(32767);
3349 v_start PLS_INTEGER := 1;
3350 v_buffer PLS_INTEGER := 32767;
3352 DBMS_LOB.CREATETEMPORARY(v_clob, TRUE);
3354 FOR i IN 1..CEIL(DBMS_LOB.GETLENGTH(blob_in) / v_buffer)
3357 v_varchar := UTL_RAW.CAST_TO_VARCHAR2(DBMS_LOB.SUBSTR(blob_in, v_buffer, v_start));
3359 DBMS_LOB.WRITEAPPEND(v_clob, LENGTH(v_varchar), v_varchar);
3361 v_start := v_start + v_buffer;
3366 END blob_to_clob;");
3368 if(strpos($resumeFromQuery,",") != false){
3369 $resumeFromQuery = explode(",",$resumeFromQuery);
3370 if(is_array($resumeFromQuery)){
3371 //print_r('RES ARRAY '.$resumeFromQuery[0].'</br>');
3374 if(file_exists($sqlScript)) {
3375 $fp = fopen($sqlScript, 'r');
3376 $contents = stream_get_contents($fp);
3377 $anyScriptChanges =$contents;
3378 $resumeAfterFound = false;
3382 while($line = fgets($fp)) {
3383 if(strpos($line, '--') === false) {
3384 $completeLine .= " ".trim($line);
3385 if(strpos($line, ';') !== false) {
3387 $query = str_replace(';','',$completeLine);
3388 //if resume from query is not null then find out from where
3389 //it should start executing the query.
3391 if($query != null && $resumeFromQuery != null){
3392 if(!$resumeAfterFound){
3393 if(strpos($query,",") != false){
3394 $queArray = array();
3395 $queArray = explode(",",$query);
3396 for($i=0;$i<sizeof($resumeFromQuery);$i++){
3397 if(strcmp(strtolower(trim($resumeFromQuery[$i])),strtolower(trim($queArray[$i])))==0){
3398 //echo 'mat found '.$queArray[$i].'</br>';
3399 $resumeAfterFound = true;
3402 $resumeAfterFound = false;
3408 elseif(strcmp(strtolower(trim($resumeFromQuery)),strtolower(trim($query)))==0){
3409 $resumeAfterFound = true;
3412 if($resumeAfterFound){
3415 // if $count=1 means it is just found so skip the query. Run the next one
3416 if($query != null && $resumeAfterFound && $count >1){
3420 $tableName = getAlterTable($query);
3421 if(!empty($tableName))
3423 $db->query('ALTER TABLE '.$tableName.' DISABLE KEYS');
3427 if($db->checkError()){
3428 //put in the array to use later on
3429 $_SESSION['sqlSkippedQueries'][] = $query;
3431 if(!empty($tableName))
3433 $db->query('ALTER TABLE '.$tableName.' ENABLE KEYS');
3435 $progQuery[$forStepQuery]=$query;
3436 post_install_progress($progQuery,$action='set');
3439 elseif($query != null){
3443 $tableName = getAlterTable($query);
3444 if(!empty($tableName))
3446 $db->query('ALTER TABLE '.$tableName.' DISABLE KEYS');
3450 if(!empty($tableName))
3452 $db->query('ALTER TABLE '.$tableName.' ENABLE KEYS');
3454 $progQuery[$forStepQuery]=$query;
3455 post_install_progress($progQuery,$action='set');
3456 if($db->checkError()){
3457 //put in the array to use later on
3458 $_SESSION['sqlSkippedQueries'][] = $query;
3469 function getAlterTable($query){
3470 $query = strtolower($query);
3471 if (preg_match("/^\s*alter\s+table\s+/", $query)) {
3472 $sqlArray = explode(" ", $query);
3473 $key = array_search('table', $sqlArray);
3474 return $sqlArray[($key+1)];
3480 function set_upgrade_vars(){
3481 logThis('setting session variables...');
3482 $upgrade_progress_dir = getcwd().'/'.$GLOBALS['sugar_config']['upload_dir'].'upgrades/temp';
3483 if(!is_dir($upgrade_progress_dir)){
3484 mkdir_recursive($upgrade_progress_dir);
3486 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3487 if(file_exists($upgrade_progress_file)){
3488 include($upgrade_progress_file);
3491 fopen($upgrade_progress_file, 'w+');
3493 if(!isset($upgrade_config) || $upgrade_config == null){
3494 $upgrade_config = array();
3495 $upgrade_config[1]['upgrade_vars']=array();
3497 if(isset($upgrade_config[1]) && isset($upgrade_config[1]['upgrade_vars']) && !is_array($upgrade_config[1]['upgrade_vars'])){
3498 $upgrade_config[1]['upgrade_vars'] = array();
3501 if(!isset($upgrade_vars) || $upgrade_vars == NULL){
3502 $upgrade_vars = array();
3504 if(isset($_SESSION['unzip_dir']) && !empty($_SESSION['unzip_dir']) && file_exists($_SESSION['unzip_dir'])){
3505 $upgrade_vars['unzip_dir']=$_SESSION['unzip_dir'];
3507 if(isset($_SESSION['install_file']) && !empty($_SESSION['install_file']) && file_exists($_SESSION['install_file'])){
3508 $upgrade_vars['install_file']=$_SESSION['install_file'];
3510 if(isset($_SESSION['Upgraded451Wizard']) && !empty($_SESSION['Upgraded451Wizard'])){
3511 $upgrade_vars['Upgraded451Wizard']=$_SESSION['Upgraded451Wizard'];
3513 if(isset($_SESSION['license_shown']) && !empty($_SESSION['license_shown'])){
3514 $upgrade_vars['license_shown']=$_SESSION['license_shown'];
3516 if(isset($_SESSION['Initial_451to500_Step']) && !empty($_SESSION['Initial_451to500_Step'])){
3517 $upgrade_vars['Initial_451to500_Step']=$_SESSION['Initial_451to500_Step'];
3519 if(isset($_SESSION['zip_from_dir']) && !empty($_SESSION['zip_from_dir'])){
3520 $upgrade_vars['zip_from_dir']=$_SESSION['zip_from_dir'];
3522 //place into the upgrade_config array and rewrite config array only if new values are being inserted
3523 if(isset($upgrade_vars) && $upgrade_vars != null && sizeof($upgrade_vars) > 0){
3524 foreach($upgrade_vars as $key=>$val){
3525 if($key != null && $val != null){
3526 $upgrade_config[1]['upgrade_vars'][$key]=$upgrade_vars[$key];
3529 ksort($upgrade_config);
3530 if(is_writable($upgrade_progress_file) && write_array_to_file( "upgrade_config", $upgrade_config,
3531 $upgrade_progress_file)) {
3532 //writing to the file
3537 function initialize_session_vars(){
3538 $upgrade_progress_dir = getcwd().'/'.$GLOBALS['sugar_config']['upload_dir'].'upgrades/temp';
3539 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3540 if(file_exists($upgrade_progress_file)){
3541 include($upgrade_progress_file);
3542 if(isset($upgrade_config) && $upgrade_config != null && is_array($upgrade_config) && sizeof($upgrade_config) >0){
3543 $currVarsArray=$upgrade_config[1]['upgrade_vars'];
3544 //print_r($currVarsArray);
3545 if(isset($currVarsArray) && $currVarsArray != null && is_array($currVarsArray) && sizeof($currVarsArray)>0){
3546 foreach($currVarsArray as $key=>$val){
3547 if($key != null && $val !=null){
3548 //set session variables
3549 $_SESSION[$key]=$val;
3558 //track the upgrade progress on each step
3559 //track the upgrade progress on each step
3560 function set_upgrade_progress($currStep,$currState,$currStepSub='',$currStepSubState=''){
3562 $upgrade_progress_dir = getcwd().'/'.$GLOBALS['sugar_config']['upload_dir'].'upgrades/temp';
3563 if(!is_dir($upgrade_progress_dir)){
3564 mkdir_recursive($upgrade_progress_dir);
3566 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3567 if(file_exists($upgrade_progress_file)){
3568 include($upgrade_progress_file);
3571 if(function_exists('sugar_fopen')){
3572 sugar_fopen($upgrade_progress_file, 'w+');
3575 fopen($upgrade_progress_file, 'w+');
3578 if(!isset($upgrade_config) || $upgrade_config == null){
3579 $upgrade_config = array();
3580 $upgrade_config[1]['upgrade_vars']=array();
3582 if(!is_array($upgrade_config[1]['upgrade_vars'])){
3583 $upgrade_config[1]['upgrade_vars'] = array();
3585 if($currStep != null && $currState != null){
3586 if(sizeof($upgrade_config) > 0){
3587 if($currStepSub != null && $currStepSubState !=null){
3588 //check if new status to be set or update
3589 //get the latest in array. since it has sub components prepare an array
3590 if(!empty($upgrade_config[sizeof($upgrade_config)][$currStep]) && is_array($upgrade_config[sizeof($upgrade_config)][$currStep])){
3591 $latestStepSub = currSubStep($upgrade_config[sizeof($upgrade_config)][$currStep]);
3592 if($latestStepSub == $currStepSub){
3593 $upgrade_config[sizeof($upgrade_config)][$currStep][$latestStepSub]=$currStepSubState;
3594 $upgrade_config[sizeof($upgrade_config)][$currStep][$currStep] = $currState;
3597 $upgrade_config[sizeof($upgrade_config)][$currStep][$currStepSub]=$currStepSubState;
3598 $upgrade_config[sizeof($upgrade_config)][$currStep][$currStep] = $currState;
3602 $currArray = array();
3603 $currArray[$currStep] = $currState;
3604 $currArray[$currStepSub] = $currStepSubState;
3605 $upgrade_config[sizeof($upgrade_config)+1][$currStep] = $currArray;
3609 //get the current upgrade progress
3610 $latestStep = get_upgrade_progress();
3611 //set the upgrade progress
3612 //echo 'latest '.$latestStep;
3613 if($latestStep == $currStep){
3614 //update the current step with new progress status
3616 $upgrade_config[sizeof($upgrade_config)][$latestStep]=$currState;
3621 $upgrade_config[sizeof($upgrade_config)+1][$currStep]=$currState;
3623 // now check if there elements within array substeps
3627 //set the upgrade progress (just starting)
3628 $upgrade_config[sizeof($upgrade_config)+1][$currStep]= $currState;
3631 if(is_writable($upgrade_progress_file) && write_array_to_file( "upgrade_config", $upgrade_config,
3632 $upgrade_progress_file)) {
3633 //writing to the file
3639 function get_upgrade_progress(){
3640 $upgrade_progress_dir = getcwd().'/'.$GLOBALS['sugar_config']['upload_dir'].'upgrades/temp';
3641 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3643 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3645 if(file_exists($upgrade_progress_file)){
3646 include($upgrade_progress_file);
3647 //echo 'upconf '.$upgrade_config;
3648 if(!isset($upgrade_config) || $upgrade_config == null){
3649 $upgrade_config = array();
3651 if($upgrade_config != null && sizeof($upgrade_config) >1){
3652 $currArr = $upgrade_config[sizeof($upgrade_config)];
3653 //echo 'size of '.sizeof($upgrade_config);
3654 if(is_array($currArr)){
3655 foreach($currArr as $key=>$val){
3663 function currSubStep($currStep){
3665 if(is_array($currStep)){
3666 foreach($currStep as $key=>$val){
3674 function currUpgradeState($currState){
3676 if(is_array($currState)){
3677 foreach($currState as $key=>$val){
3679 foreach($val as $k=>$v){
3693 function didThisStepRunBefore($step,$SubStep=''){
3694 if($step == null) return;
3695 $upgrade_progress_dir = getcwd().'/'.$GLOBALS['sugar_config']['upload_dir'].'upgrades/temp';
3696 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3698 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3700 if(file_exists($upgrade_progress_file)){
3701 include($upgrade_progress_file);
3702 if(isset($upgrade_config) && $upgrade_config != null && is_array($upgrade_config) && sizeof($upgrade_config) >0){
3703 for($i=1;$i<=sizeof($upgrade_config);$i++){
3704 if(is_array($upgrade_config[$i])){
3705 foreach($upgrade_config[$i] as $key=>$val){
3707 if(is_array($upgrade_config[$i][$step])){
3709 foreach ($upgrade_config[$i][$step] as $k=>$v){
3711 foreach($v as $k1=>$v1){
3712 if($SubStep != null){
3713 if($SubStep ==$k1 && $v1=='done'){
3714 //echo 'Found Inside '.$k1;
3721 elseif($SubStep !=null){
3722 if($SubStep==$k && $v=='done'){
3723 //echo 'Found1 '.$k;
3728 elseif($step==$k && $v=='done'){
3729 //echo 'Found2 '.$k;
3735 elseif($val=='done'){
3736 //echo 'Foundmmmm '.$key;
3750 //get and set post install status
3751 function post_install_progress($progArray='',$action=''){
3752 if($action=='' || $action=='get'){
3753 //get the state of post install
3754 $upgrade_progress_dir = getcwd().'/'.$GLOBALS['sugar_config']['upload_dir'].'upgrades/temp';
3755 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3756 $currProg = array();
3757 if(file_exists($upgrade_progress_file)){
3758 include($upgrade_progress_file);
3759 if(is_array($upgrade_config[sizeof($upgrade_config)]['commit']['post_install']) && sizeof($upgrade_config[sizeof($upgrade_config)]['commit']['post_install'])>0){
3760 foreach($upgrade_config[sizeof($upgrade_config)]['commit']['post_install'] as $k=>$v){
3767 elseif($action=='set'){
3768 $upgrade_progress_dir = getcwd().'/'.$GLOBALS['sugar_config']['upload_dir'].'upgrades/temp';
3769 if(!is_dir($upgrade_progress_dir)){
3770 mkdir($upgrade_progress_dir);
3772 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3773 if(file_exists($upgrade_progress_file)){
3774 include($upgrade_progress_file);
3777 fopen($upgrade_progress_file, 'w+');
3779 if(!is_array($upgrade_config[sizeof($upgrade_config)]['commit']['post_install'])){
3780 $upgrade_config[sizeof($upgrade_config)]['commit']['post_install']=array();
3781 $upgrade_config[sizeof($upgrade_config)]['commit']['post_install']['post_install'] = 'in_progress';
3783 if($progArray != null && is_array($progArray)){
3784 foreach($progArray as $key=>$val){
3785 $upgrade_config[sizeof($upgrade_config)]['commit']['post_install'][$key]=$val;
3788 if(is_writable($upgrade_progress_file) && write_array_to_file( "upgrade_config", $upgrade_config,
3789 $upgrade_progress_file)) {
3790 //writing to the file
3796 // parse and run sql file
3797 function parseAndExecuteSqlFileExtended($sqlScript){
3798 global $sugar_config;
3799 $alterTableSchema = '';
3800 $db = & DBManagerFactory::getInstance();
3801 if(is_file($sqlScript)) {
3802 $fp = fopen($sqlScript, 'r');
3803 $contents = stream_get_contents($fp);
3804 $anyScriptChanges =$contents;
3808 while($line = fgets($fp)) {
3809 if(strpos($line, '--') === false) {
3810 $completeLine .= " ".trim($line);
3811 if(strpos($line, ';') !== false) {
3812 $completeLine = str_replace(';','',$completeLine);
3813 $currLine = explode(",",$completeLine);
3814 //check if multiple statements are clubbed
3815 if(sizeof($currLine) >1){
3816 $qarr = explode(" ",trim($currLine[0]));
3817 if(strtoupper(trim($qarr[0])) == 'CREATE' && strtoupper(trim($qarr[1])) == 'TABLE'){
3818 if(strtoupper(trim($qarr[2]) != null)){
3819 if($sugar_config['dbconfig']['db_type'] == 'oci8'){
3820 $query= "select table_name from user_tables where table_name=strtoupper(trim($qarr[2]))";
3821 $result = $db->query($query);
3822 $row = $db->fetchByAssociation($result);
3823 if($row['table_name'] != null){
3828 $query= $completeLine;
3837 $qType =trim($qarr[0])." ".trim($qarr[1])." ".trim($qarr[2]);
3838 echo trim($currLine[0])."<br />";
3839 for ($i = 1; $i <= sizeof($currLine)-1; $i++) {
3840 $query = $qType." ".trim($currLine[$i]);
3841 echo $query."<br />";
3847 echo trim($currLine[0]);
3851 //$q3 = $completeLine;
3852 //''$r3 = $GLOBALS['db']->query($q3, false, "Preflight Failed for:");
3853 //echo mysql_error();
3861 //$sqlErrors[] = $mod_strings['ERR_UW_FILE_NOT_READABLE'].'::'.$sqlScript;
3866 function repairDBForUpgrade($execute=false,$path=''){
3868 global $current_user, $beanFiles;
3870 set_time_limit(3600);
3872 $db = &DBManagerFactory::getInstance();
3874 VardefManager::clearVardef();
3875 require_once('include/ListView/ListView.php');
3876 foreach ($beanFiles as $bean => $file) {
3877 require_once ($file);
3878 $focus = new $bean ();
3879 $sql .= $db->repairTable($focus, $execute);
3883 $olddictionary = $dictionary;
3884 unset ($dictionary);
3885 include ('modules/TableDictionary.php');
3886 foreach ($dictionary as $meta) {
3887 $tablename = $meta['table'];
3888 $fielddefs = $meta['fields'];
3889 $indices = $meta['indices'];
3890 $sql .= $db->repairTableParams($tablename, $fielddefs, $indices, $execute);
3893 foreach (explode("\n", $sql) as $line) {
3894 if (!empty ($line) && substr($line, -2) != "*/") {
3897 $qry_str .= $line . "\n";
3908 preg_replace('#(/\*.+?\*/\n*)#', '', $qry_str)
3910 logThis("*******START EXECUTING DB UPGRADE QUERIES***************",$path);
3911 logThis($sql,$path);
3912 logThis("*******END EXECUTING DB UPGRADE QUERIES****************",$path);
3921 * upgradeUserPreferences
3922 * This method updates the user_preferences table and sets the pages/dashlets for users
3923 * which have ACL access to Trackers so that the Tracker dashlets are set in their user perferences
3926 function upgradeUserPreferences() {
3931 function add_custom_modules_favorites_search(){
3932 $module_directories = scandir('modules');
3934 foreach($module_directories as $module_dir){
3935 if($module_dir == '.' || $module_dir == '..' || !is_dir("modules/{$module_dir}")){
3940 preg_match('/^[a-z0-9]{1,5}_[a-z0-9_]+$/i' , $module_dir, $matches);
3942 // Make sure the module was created by module builder
3943 if(empty($matches)){
3947 $full_module_dir = "modules/{$module_dir}/";
3948 $read_searchdefs_from = "{$full_module_dir}/metadata/searchdefs.php";
3949 $read_SearchFields_from = "{$full_module_dir}/metadata/SearchFields.php";
3950 $read_custom_SearchFields_from = "custom/{$full_module_dir}/metadata/SearchFields.php";
3952 // Studio can possibly override this file, so we check for a custom version of it
3953 if(file_exists("custom/{$full_module_dir}/metadata/searchdefs.php")){
3954 $read_searchdefs_from = "custom/{$full_module_dir}/metadata/searchdefs.php";
3957 if(file_exists($read_searchdefs_from) && file_exists($read_SearchFields_from)){
3960 require($read_searchdefs_from);
3961 foreach($searchdefs[$module_dir]['layout']['basic_search'] as $sf_array){
3962 if(isset($sf_array['name']) && $sf_array['name'] == 'favorites_only'){
3967 require($read_SearchFields_from);
3968 if(isset($searchFields[$module_dir]['favorites_only'])){
3972 if(!$found_sf1 && !$found_sf2){
3973 $searchdefs[$module_dir]['layout']['basic_search']['favorites_only'] = array('name' => 'favorites_only','label' => 'LBL_FAVORITES_FILTER','type' => 'bool',);
3974 $searchdefs[$module_dir]['layout']['advanced_search']['favorites_only'] = array('name' => 'favorites_only','label' => 'LBL_FAVORITES_FILTER','type' => 'bool',);
3975 $searchFields[$module_dir]['favorites_only'] = array(
3976 'query_type'=>'format',
3977 'operator' => 'subquery',
3978 'subquery' => 'SELECT sugarfavorites.record_id FROM sugarfavorites
3979 WHERE sugarfavorites.deleted=0
3980 and sugarfavorites.module = \''.$module_dir.'\'
3981 and sugarfavorites.assigned_user_id = \'{0}\'',
3982 'db_field'=>array('id')
3985 if(!is_dir("custom/{$full_module_dir}/metadata")){
3986 mkdir_recursive("custom/{$full_module_dir}/metadata");
3988 $success_sf1 = write_array_to_file('searchdefs', $searchdefs, "custom/{$full_module_dir}/metadata/searchdefs.php");
3989 $success_sf2 = write_array_to_file('searchFields', $searchFields, "{$full_module_dir}/metadata/SearchFields.php");
3992 logThis("add_custom_modules_favorites_search failed for searchdefs.php for {$module_dir}");
3995 logThis("add_custom_modules_favorites_search failed for SearchFields.php for {$module_dir}");
3997 if($success_sf1 && $success_sf2){
3998 logThis("add_custom_modules_favorites_search successfully updated searchdefs and searchFields for {$module_dir}");
4007 * upgradeModulesForTeamsets
4009 * This method adds the team_set_id values to the module tables that have the new team_set_id column
4010 * added through the SugarCRM 5.5.x upgrade process. It also adds the values into the team_sets and
4011 * team_sets_teams tables.
4013 * @param filter Array of modules to process; empty by default
4015 function upgradeModulesForTeamsets($filter=array()) {
4016 require('include/modules.php');
4017 foreach($beanList as $moduleName=>$beanName) {
4018 if(!empty($filter) && array_search($moduleName, $filter) === false) {
4021 if($moduleName == 'TeamMemberships' || $moduleName == 'ForecastOpportunities'){
4024 $bean = loadBean($moduleName);
4026 empty($bean->table_name)) {
4030 $FieldArray = $GLOBALS['db']->helper->get_columns($bean->table_name);
4031 if(!isset($FieldArray['team_id'])) {
4035 upgradeTeamColumn($bean, 'team_id');
4039 //Upgrade users table
4040 $bean = loadBean('Users');
4041 upgradeTeamColumn($bean, 'default_team');
4042 $result = $GLOBALS['db']->query("SELECT id FROM teams where deleted=0");
4043 while($row = $GLOBALS['db']->fetchByAssoc($result)) {
4044 $teamset = new TeamSet();
4045 $teamset->addTeams($row['id']);
4052 * Helper function to create a team_set_id column and also set team_set_id column
4053 * to have the value of the $column_name parameter
4055 * @param $bean SugarBean which we are adding team_set_id column to
4056 * @param $column_name The name of the column containing the default team_set_id value
4058 function upgradeTeamColumn($bean, $column_name) {
4059 //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
4060 //module that does not use the SugarObjects
4061 if(empty($bean->field_defs['team_set_id']) && $bean->module_dir != 'Trackers'){
4063 //at this point we could assume that since we have a team_id defined and not a team_set_id that we need to
4064 //add that field and the corresponding relationships
4065 $object = $bean->object_name;
4066 $module = $bean->module_dir;
4067 $object_name = $object;
4068 $_object_name = strtolower($object_name);
4070 if(!empty($GLOBALS['dictionary'][$object]['table'])){
4071 $table_name = $GLOBALS['dictionary'][$object]['table'];
4073 $table_name = strtolower($module);
4076 $path = 'include/SugarObjects/implements/team_security/vardefs.php';
4078 //go through each entry in the vardefs from team_security and unset anything that is already set in the core module
4079 //this will ensure we have the proper ordering.
4080 $fieldDiff = array_diff_assoc($vardefs['fields'], $GLOBALS['dictionary'][$bean->object_name]['fields']);
4082 $file = 'custom/Extension/modules/' . $bean->module_dir. '/Ext/Vardefs/teams.php';
4083 $contents = "<?php\n";
4084 if(!empty($fieldDiff)){
4085 foreach($fieldDiff as $key => $val){
4086 $contents .= "\n\$GLOBALS['dictionary']['". $object . "']['fields']['". $key . "']=" . var_export_helper($val) . ";";
4089 $relationshipDiff = array_diff_assoc($vardefs['relationships'], $GLOBALS['dictionary'][$bean->object_name]['relationships']);
4090 if(!empty($relationshipDiff)){
4091 foreach($relationshipDiff as $key => $val){
4092 $contents .= "\n\$GLOBALS['dictionary']['". $object . "']['relationships']['". $key . "']=" . var_export_helper($val) . ";";
4095 $indexDiff = array_diff_assoc($vardefs['indices'], $GLOBALS['dictionary'][$bean->object_name]['indices']);
4096 if(!empty($indexDiff)){
4097 foreach($indexDiff as $key => $val){
4098 $contents .= "\n\$GLOBALS['dictionary']['". $object . "']['indices']['". $key . "']=" . var_export_helper($val) . ";";
4101 if( $fh = @sugar_fopen( $file, 'wt' ) )
4103 fputs( $fh, $contents);
4108 //we have written out the teams.php into custom/Extension/modules/{$module_dir}/Ext/Vardefs/teams.php'
4109 //now let's merge back into vardefs.ext.php
4110 require_once('ModuleInstall/ModuleInstaller.php');
4111 $mi = new ModuleInstaller();
4112 $mi->merge_files('Ext/Vardefs/', 'vardefs.ext.php');
4113 VardefManager::loadVardef($bean->module_dir, $bean->object_name, true);
4114 $bean->field_defs = $GLOBALS['dictionary'][$bean->object_name]['fields'];
4117 if(isset($bean->field_defs['team_set_id'])) {
4118 //Create the team_set_id column
4119 $FieldArray = $GLOBALS['db']->helper->get_columns($bean->table_name);
4120 if(!isset($FieldArray['team_set_id'])) {
4121 $GLOBALS['db']->addColumn($bean->table_name, $bean->field_defs['team_set_id']);
4123 $indexArray = $GLOBALS['db']->helper->get_indices($bean->table_name);
4125 $indexName = getValidDBName('idx_'.strtolower($bean->table_name).'_tmst_id', true, 34);
4128 'name' => $indexName,
4130 'fields' => array('team_set_id')
4133 if(!isset($indexArray[$indexName])) {
4134 $GLOBALS['db']->addIndexes($bean->table_name, $indexDef);
4137 //Update the table's team_set_id column to have the same values as team_id
4138 $GLOBALS['db']->query("UPDATE {$bean->table_name} SET team_set_id = {$column_name}");
4143 * Update the folder subscription table which confirms to the team security mechanism but
4144 * the class SugarFolders does not extend SugarBean and is therefore never picked up by the
4145 * upgradeModulesForTeamsets function.
4147 function upgradeFolderSubscriptionsTeamSetId()
4149 logThis("In upgradeFolderSubscriptionsTeamSetId()");
4150 $query = "UPDATE folders SET team_set_id = team_id";
4151 $result = $GLOBALS['db']->query($query);
4152 logThis("Finished upgradeFolderSubscriptionsTeamSetId()");
4156 * upgradeModulesForTeam
4158 * This method update the associated_user_id, name, name_2 to the private team records on teams table
4159 * This function is used for upgrade process from 5.1.x and 5.2.x.
4162 function upgradeModulesForTeam() {
4163 logThis("In upgradeModulesForTeam()");
4164 $result = $GLOBALS['db']->query("SELECT id, user_name, first_name, last_name FROM users where deleted=0");
4166 while($row = $GLOBALS['db']->fetchByAssoc($result)) {
4167 $results2 = $GLOBALS['db']->query("SELECT id FROM teams WHERE name = '({$row['user_name']})'");
4169 if(!$assoc = $GLOBALS['db']->fetchByAssoc($results2)) {
4170 //if team does not exist, then lets create the team for this user
4173 $user->retrieve($row['id']);
4174 $team->new_user_created($user);
4175 $team_id = $team->id;
4177 $team_id =$assoc['id'];
4181 $name = is_null($row['first_name'])?'':$row['first_name'];
4182 $name_2 = is_null($row['last_name'])?'':$row['last_name'];
4183 $associated_user_id = $row['id'];
4186 //Ensure team->name is not empty by using team->name_2 if available
4187 if(empty($name) && !empty($name_2)) {
4192 $query = "UPDATE teams SET name = '{$name}', name_2 = '{$name_2}', associated_user_id = '{$associated_user_id}' WHERE id = '{$team_id}'";
4193 $GLOBALS['db']->query($query);
4196 //Update the team_set_id and default_team columns
4197 $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'));
4199 //Update team_set_id
4200 if($ce_to_pro_or_ent) {
4201 $GLOBALS['db']->query("update users set team_set_id = (select teams.id from teams where teams.associated_user_id = users.id)");
4202 $GLOBALS['db']->query("update users set default_team = (select teams.id from teams where teams.associated_user_id = users.id)");
4208 function addNewSystemTabsFromUpgrade($from_dir){
4210 if(isset($_SESSION['upgrade_from_flavor'])){
4212 //check to see if there are any new files that need to be added to systems tab
4213 //retrieve old modules list
4214 logThis('check to see if new modules exist',$path);
4215 $oldModuleList = array();
4216 $newModuleList = array();
4217 include($from_dir.'/include/modules.php');
4218 $oldModuleList = $moduleList;
4219 include('include/modules.php');
4220 $newModuleList = $moduleList;
4222 //include tab controller
4223 require_once('modules/MySettings/TabController.php');
4224 $newTB = new TabController();
4226 //make sure new modules list has a key we can reference directly
4227 $newModuleList = $newTB->get_key_array($newModuleList);
4228 $oldModuleList = $newTB->get_key_array($oldModuleList);
4230 //iterate through list and remove commonalities to get new modules
4231 foreach ($newModuleList as $remove_mod){
4232 if(in_array($remove_mod, $oldModuleList)){
4233 unset($newModuleList[$remove_mod]);
4236 //new modules list now has left over modules which are new to this install, so lets add them to the system tabs
4237 logThis('new modules to add are '.var_export($newModuleList,true),$path);
4239 if(!empty($newModuleList))
4241 //grab the existing system tabs
4242 $tabs = $newTB->get_system_tabs();
4244 //add the new tabs to the array
4245 foreach($newModuleList as $nm ){
4249 $newTB->set_system_tabs($tabs);
4251 logThis('module tabs updated',$path);
4257 * This method attempts to fix dropdown lists that were incorrectly named.
4258 * There were versions of SugarCRM that did not enforce naming convention rules
4259 * for the dropdown list field name. This method attempts to resolve that by
4260 * fixing the language files that may have been affected and then updating the
4261 * fields_meta_data table accordingly. It also refreshes any vardefs that may
4262 * have been affected.
4265 function fix_dropdown_list() {
4266 if(file_exists('custom/include/language')) {
4268 $affected_modules = array();
4269 $affected_keys = array();
4271 getFiles($files, 'custom/include/language', '/\.php$/i');
4272 foreach($files as $file) {
4274 if(file_exists($file . '.bak')) {
4275 $bak_mod_time = filemtime($file . '.bak');
4276 $php_mod_time = filemtime($file);
4277 //We're saying if the .php file was modified 30 seconds no more than php.bak file then we
4278 //run these additional cleanup checks
4279 if($php_mod_time - $bak_mod_time < 30) {
4281 $app_list_strings = array();
4282 $GLOBALS['app_list_strings'] = array();
4283 require($file . '.bak');
4284 $bak_app_list_strings = array_merge($app_list_strings, $GLOBALS['app_list_strings']);
4286 $app_list_strings = array();
4287 $GLOBALS['app_list_strings'] = array();
4289 $php_app_list_strings = array_merge($app_list_strings, $GLOBALS['app_list_strings']);
4291 //Get the file contents
4292 $contents = file_get_contents($file);
4294 //Now simulate a fix for the file before we compare w/ the .php file
4295 //we also append to the $contents
4296 foreach($bak_app_list_strings as $key=>$entry) {
4297 if(preg_match('/([^A-Za-z_])/', $key, $matches) && is_array($entry)) {
4298 $new_key = preg_replace('/[^A-Za-z_]/', '_', $key);
4299 $bak_app_list_strings[$new_key] = $bak_app_list_strings[$key];
4300 unset($bak_app_list_strings[$key]);
4301 //Now if the entry doesn't exists in the .php file, then add to contents
4302 if(!isset($php_app_list_strings[$new_key])) {
4303 $contents .= "\n\$GLOBALS['app_list_strings']['{$new_key}'] = " . var_export_helper($bak_app_list_strings[$new_key]) . ";";
4308 //Now load the .php file to do the comparison
4309 foreach($php_app_list_strings as $key=>$entry) {
4310 if(isset($bak_app_list_strings[$key])) {
4311 $diff = array_diff($bak_app_list_strings[$key], $entry);
4313 //There is a difference, so copy the $bak_app_list_strings version into the .php file
4314 $contents .= "\n\$GLOBALS['app_list_strings']['{$key}'] = " . var_export_helper($bak_app_list_strings[$key]) . ";";
4319 //Now write out the file contents
4320 //Create backup just in case
4321 copy($file, $file . '.php_bak');
4322 $fp = @sugar_fopen($file, 'w');
4324 fwrite($fp, $contents);
4327 $GLOBALS['log']->error("Unable to update file contents in fix_dropdown_list for {$file}");
4332 unset($GLOBALS['app_strings']);
4333 unset($GLOBALS['app_list_strings']);
4334 $app_list_strings = array();
4337 $contents = file_get_contents($file);
4338 if ( !isset($GLOBALS['app_list_strings']) ) {
4339 $GLOBALS['app_list_strings'] = $app_list_strings;
4342 $GLOBALS['app_list_strings'] = array_merge($app_list_strings, $GLOBALS['app_list_strings']);
4345 if(isset($GLOBALS['app_list_strings']) && is_array($GLOBALS['app_list_strings'])) {
4346 foreach($GLOBALS['app_list_strings'] as $key=>$entry) {
4347 if(preg_match('/([^A-Za-z_])/', $key, $matches) && is_array($entry)) {
4348 $result = $GLOBALS['db']->query("SELECT custom_module FROM fields_meta_data WHERE ext1 = '{$key}'");
4349 if(!empty($result)) {
4350 while($row = $GLOBALS['db']->fetchByAssoc($result)) {
4351 $custom_module = $row['custom_module'];
4352 if(!empty($GLOBALS['beanList'][$custom_module])) {
4353 $affected_modules[$custom_module] = $GLOBALS['beanList'][$custom_module];
4358 //Replace all invalid characters with '_' character
4359 $new_key = preg_replace('/[^A-Za-z_]/', '_', $key);
4360 $affected_keys[$key] = $new_key;
4362 $GLOBALS['app_list_strings'][$new_key] = $GLOBALS['app_list_strings'][$key];
4363 unset($GLOBALS['app_list_strings'][$key]);
4365 $pattern_match = "/(\[\s*\'{$key}\'\s*\])/";
4366 $new_key = "['{$new_key}']";
4367 $out = preg_replace($pattern_match, $new_key, $contents);
4373 //This is a check for g => h instances where the file contents were incorrectly written
4374 //and also fixes the scenario where via a UI upgrade, the app_list_strings were incorrectly
4375 //merged with app_list_strings variables declared elsewhere
4377 if(preg_match('/\$GLOBALS\s*\[\s*[\"|\']app_list_strings[\"|\']\s*\]\s*=\s*array\s*\(/', $contents)) {
4378 //Now also remove all the non-custom labels that were added
4379 if(preg_match('/language\/([^\.]+)\.lang\.php$/', $file, $matches)) {
4380 $language = $matches[1];
4382 $app_list_strings = array();
4384 if(file_exists("include/language/$language.lang.php")) {
4385 include("include/language/$language.lang.php");
4387 if(file_exists("include/language/$language.lang.override.php")) {
4388 $app_list_strings = _mergeCustomAppListStrings("include/language/$language.lang.override.php" , $app_list_strings) ;
4390 if(file_exists("custom/application/Ext/Language/$language.ext.lang.php")) {
4391 $app_list_strings = _mergeCustomAppListStrings("custom/application/Ext/Language/$language.ext.lang.php" , $app_list_strings) ;
4393 if(file_exists("custom/application/Ext/Language/$language.lang.ext.php")) {
4394 $app_list_strings = _mergeCustomAppListStrings("custom/application/Ext/Language/$language.lang.ext.php" , $app_list_strings) ;
4397 $all_non_custom_include_language_strings = $app_strings;
4398 $all_non_custom_include_language_list_strings = $app_list_strings;
4400 $unset_keys = array();
4401 if(!empty($GLOBALS['app_list_strings'])) {
4402 foreach($GLOBALS['app_list_strings'] as $key=>$value) {
4404 if(isset($all_non_custom_include_language_list_strings[$key])) {
4405 $diff = array_diff($all_non_custom_include_language_list_strings[$key], $GLOBALS['app_list_strings'][$key]);
4408 if(!empty($all_non_custom_include_language_list_strings[$key]) && empty($diff)) {
4409 $unset_keys[] = $key;
4414 foreach($unset_keys as $key) {
4415 unset($GLOBALS['app_list_strings'][$key]);
4418 if(!empty($GLOBALS['app_strings'])) {
4419 foreach($GLOBALS['app_strings'] as $key=>$value) {
4420 if(!empty($all_non_custom_include_language_strings[$key])) {
4421 unset($GLOBALS['app_strings'][$key]);
4425 } //if(preg_match...)
4428 if(!empty($GLOBALS['app_strings'])) {
4429 foreach($GLOBALS['app_strings'] as $key=>$entry) {
4430 $out .= "\n\$GLOBALS['app_strings']['$key']=" . var_export_helper($entry) . ";";
4434 foreach($GLOBALS['app_list_strings'] as $key=>$entry) {
4435 $out .= "\n\$GLOBALS['app_list_strings']['$key']=" . var_export_helper($entry) . ";";
4439 } //if(preg_match...)
4443 //Create a backup just in case
4444 copy($file, $file . '.bak');
4445 $fp = @sugar_fopen($file, 'w');
4450 //If we can't update the file, just return
4451 $GLOBALS['log']->error("Unable to update file contents in fix_dropdown_list.");
4459 //Update db entries (the order matters here... need to process database changes first)
4460 if(!empty($affected_keys)) {
4461 foreach($affected_keys as $old_key=>$new_key) {
4462 $GLOBALS['db']->query("UPDATE fields_meta_data SET ext1 = '{$new_key}' WHERE ext1 = '{$old_key}'");
4466 //Update vardef files for affected modules
4467 if(!empty($affected_modules)) {
4468 foreach($affected_modules as $module=>$object) {
4469 VardefManager::refreshVardefs($module, $object);
4476 function update_iframe_dashlets(){
4477 require_once('cache/dashlets/dashlets.php');
4479 $db = DBManagerFactory::getInstance();
4480 $query = "SELECT id, contents, assigned_user_id FROM user_preferences WHERE deleted = 0 AND category = 'Home'";
4481 $result = $db->query($query, true, "Unable to update new default dashlets! ");
4482 while ($row = $db->fetchByAssoc($result)) {
4483 $content = unserialize(base64_decode($row['contents']));
4484 $assigned_user_id = $row['assigned_user_id'];
4485 $record_id = $row['id'];
4487 $current_user = new User();
4488 $current_user->retrieve($row['assigned_user_id']);
4490 if(!empty($content['dashlets']) && !empty($content['pages'])){
4491 $originalDashlets = $content['dashlets'];
4492 foreach($originalDashlets as $key => $ds){
4493 if(!empty($ds['options']['url']) && stristr($ds['options']['url'],'http://www.sugarcrm.com/crm/product/gopro')){
4494 unset($originalDashlets[$key]);
4497 $current_user->setPreference('dashlets', $originalDashlets, 0, 'Home');
4504 * convertImageToText
4505 * This method attempts to convert date type image to text on Microsoft SQL Server.
4506 * This method could NOT be used in any other type of datebases.
4508 function convertImageToText($table_name,$column_name){
4509 $set_lang = "SET LANGUAGE us_english";
4510 $GLOBALS['db']->query($set_lang);
4511 if($GLOBALS['db']->checkError()){
4512 logThis('An error occurred when performing this query-->'.$set_lang);
4514 $q="SELECT data_type
4515 FROM INFORMATION_SCHEMA.Tables T JOIN INFORMATION_SCHEMA.Columns C
4516 ON T.TABLE_NAME = C.TABLE_NAME where T.TABLE_NAME = '$table_name' and C.COLUMN_NAME = '$column_name'";
4517 $res= $GLOBALS['db']->query($q);
4518 if($GLOBALS['db']->checkError()){
4519 logThis('An error occurred when performing this query-->'.$q);
4521 $row= $GLOBALS['db']->fetchByAssoc($res);
4523 if(trim(strtolower($row['data_type'])) == 'image'){
4524 $addContent_temp = "alter table {$table_name} add {$column_name}_temp text null";
4525 $GLOBALS['db']->query($addContent_temp);
4526 if($GLOBALS['db']->checkError()){
4527 logThis('An error occurred when performing this query-->'.$addContent_temp);
4529 $qN = "select count=datalength({$column_name}), id, {$column_name} from {$table_name}";
4530 $result = $GLOBALS['db']->query($qN);
4531 while($row = $GLOBALS['db']->fetchByAssoc($result)){
4532 if($row['count'] >8000){
4533 $contentLength = $row['count'];
4536 $convertedContent = '';
4537 while($contentLength >0){
4538 $stepsQuery = "select cont=convert(varchar(max), convert(varbinary(8000), substring({$column_name},{$start},{$next}))) from {$table_name} where id= '{$row['id']}'";
4539 $steContQ = $GLOBALS['db']->query($stepsQuery);
4540 if($GLOBALS['db']->checkError()){
4541 logThis('An error occurred when performing this query-->'.$stepsQuery);
4543 $stepCont = $GLOBALS['db']->fetchByAssoc($steContQ);
4544 if(isset($stepCont['cont'])){
4545 $convertedContent = $convertedContent.$stepCont['cont'];
4547 $start = $start+$next;
4548 $contentLength = $contentLength - $next;
4550 $addContentDataText="update {$table_name} set {$column_name}_temp = '{$convertedContent}' where id= '{$row['id']}'";
4551 $GLOBALS['db']->query($addContentDataText);
4552 if($GLOBALS['db']->checkError()){
4553 logThis('An error occurred when performing this query-->'.$addContentDataText);
4557 $addContentDataText="update {$table_name} set {$column_name}_temp =
4558 convert(varchar(max), convert(varbinary(8000), {$column_name})) where id= '{$row['id']}'";
4559 $GLOBALS['db']->query($addContentDataText);
4560 if($GLOBALS['db']->checkError()){
4561 logThis('An error occurred when performing this query-->'.$addContentDataText);
4565 //drop the contents now and change contents_temp to contents
4566 $dropColumn = "alter table {$table_name} drop column {$column_name}";
4567 $GLOBALS['db']->query($dropColumn);
4568 if($GLOBALS['db']->checkError()){
4569 logThis('An error occurred when performing this query-->'.$dropColumn);
4571 $changeColumnName = "EXEC sp_rename '{$table_name}.[{$column_name}_temp]','{$column_name}','COLUMN'";
4572 $GLOBALS['db']->query($changeColumnName);
4573 if($GLOBALS['db']->checkError()){
4574 logThis('An error occurred when performing this query-->'.$changeColumnName);
4581 * This method attempts to delete all English inline help files.
4582 * This method was introduced by 5.5.0RC2.
4584 function clearHelpFiles(){
4585 $modulePath = clean_path(getcwd() . '/modules');
4586 $allHelpFiles = array();
4587 getFiles($allHelpFiles, $modulePath, "/en_us.help.*/");
4589 foreach( $allHelpFiles as $the_file ){
4590 if( is_file( $the_file ) ){
4591 unlink( $the_file );
4592 logThis("Deleted file: $the_file", $path);
4600 * upgradeDateTimeFields
4602 * This method came from bug: 39757 where the date_end field is a date field and not a datetime field
4603 * which prevents you from performing timezone offset calculations once the data has been saved.
4605 * @param path String location to log file, empty by default
4607 function upgradeDateTimeFields($path=''){
4610 if($db->dbType == 'mysql')
4612 $meetingsSql = "UPDATE meetings SET date_end = date_add(date_start, INTERVAL + CONCAT(duration_hours, ':', duration_minutes) HOUR_MINUTE)";
4613 $callsSql = "UPDATE calls SET date_end = date_add(date_start, INTERVAL + CONCAT(duration_hours, ':', duration_minutes) HOUR_MINUTE)";
4614 } else if($db->dbType == 'mssql') {
4615 $meetingsSql = "UPDATE meetings set date_end = DATEADD(hh, duration_hours, DATEADD(mi, duration_minutes, date_start))";
4616 $callsSql = "UPDATE calls set date_end = DATEADD(hh, duration_hours, DATEADD(mi, duration_minutes, date_start))";
4617 } else if ($db->dbType == 'oci8') {
4618 $meetingsSql = "UPDATE meetings SET date_end = date_start + duration_hours/24 + duration_minutes/1440";
4619 $callsSql = "UPDATE calls SET date_end = date_start + duration_hours/24 + duration_minutes/1440";
4622 if(isset($meetingsSql) && isset($callsSql))
4624 logThis('upgradeDateTimeFields Meetings SQL:' . $meetingsSql, $path);
4625 $db->query($meetingsSql);
4627 logThis('upgradeDateTimeFields Calls SQL:' . $callsSql, $path);
4628 $db->query($callsSql);
4635 * upgradeDocumentTypeFields
4638 function upgradeDocumentTypeFields($path){
4642 $documentsSql = "UPDATE documents SET doc_type = 'Sugar' WHERE doc_type IS NULL";
4643 $meetingsSql = "UPDATE meetings SET type = 'Sugar' WHERE type IS NULL";
4645 logThis('upgradeDocumentTypeFields Documents SQL:' . $documentsSql, $path);
4646 $db->query($documentsSql);
4647 logThis('upgradeDocumentTypeFields Meetings SQL:' . $meetingsSql, $path);
4648 $db->query($meetingsSql);
4653 * merge_config_si_settings
4654 * This method checks for the presence of a config_si.php file and, if found, merges the configuration
4655 * settings from the config_si.php file into config.php. If a config_si_location parameter value is not
4656 * supplied it will attempt to discover the config_si.php file location from where the executing script
4659 * @param write_to_upgrade_log boolean optional value to write to the upgradeWizard.log file
4660 * @param config_location String optional value to config.php file location
4661 * @param config_si_location String optional value to config_si.php file location
4662 * @param path String file of the location of log file to write to
4663 * @return boolean value indicating whether or not a merge was attempted with config_si.php file
4665 function merge_config_si_settings($write_to_upgrade_log=false, $config_location='', $config_si_location='', $path='')
4667 if(!empty($config_location) && !file_exists($config_location))
4669 if($write_to_upgrade_log)
4671 logThis('config.php file specified in ' . $config_si_location . ' could not be found. Skip merging', $path);
4674 } else if(empty($config_location)) {
4676 //We are assuming this is from the silentUpgrade scripts so argv[3] will point to SugarCRM install location
4677 if(isset($argv[3]) && is_dir($argv[3]))
4679 $config_location = $argv[3] . DIRECTORY_SEPARATOR . 'config.php';
4683 //If config_location is still empty or if the file cannot be found, skip merging
4684 if(empty($config_location) || !file_exists($config_location))
4686 if($write_to_upgrade_log)
4688 logThis('config.php file at (' . $config_location . ') could not be found. Skip merging.', $path);
4692 if($write_to_upgrade_log)
4694 logThis('Loading config.php file at (' . $config_location . ') for merging.', $path);
4697 include($config_location);
4698 if(empty($sugar_config))
4700 if($write_to_upgrade_log)
4702 logThis('config.php contents are empty. Skip merging.', $path);
4708 if(!empty($config_si_location) && !file_exists($config_si_location))
4710 if($write_to_upgrade_log)
4712 logThis('config_si.php file specified in ' . $config_si_location . ' could not be found. Skip merging', $path);
4715 } else if(empty($config_si_location)) {
4716 if(isset($argv[0]) && is_file($argv[0]))
4718 $php_file = $argv[0];
4719 $p_info = pathinfo($php_file);
4720 $php_dir = (isset($p_info['dirname']) && $p_info['dirname'] != '.') ? $p_info['dirname'] . DIRECTORY_SEPARATOR : '';
4721 $config_si_location = $php_dir . 'config_si.php';
4725 //If config_si_location is still empty or if the file cannot be found, skip merging
4726 if(empty($config_si_location) || !file_exists($config_si_location))
4728 if($write_to_upgrade_log)
4730 logThis('config_si.php file at (' . $config_si_location . ') could not be found. Skip merging.', $path);
4734 if($write_to_upgrade_log)
4736 logThis('Loading config_si.php file at (' . $config_si_location . ') for merging.', $path);
4739 include($config_si_location);
4740 if(empty($sugar_config_si))
4742 if($write_to_upgrade_log)
4744 logThis('config_si.php contents are empty. Skip merging.', $path);
4750 //Now perform the merge operation
4752 foreach($sugar_config_si as $key=>$value)
4754 if(!preg_match('/^setup_/', $key) && !isset($sugar_config[$key]))
4756 if($write_to_upgrade_log)
4758 logThis('Merge key (' . $key . ') with value (' . $value . ')', $path);
4760 $sugar_config[$key] = $value;
4767 if($write_to_upgrade_log)
4769 logThis('Update config.php file with new values', $path);
4772 if(!write_array_to_file("sugar_config", $sugar_config, $config_location)) {
4773 if($write_to_upgrade_log)
4775 logThis('*** ERROR: could not write to config.php', $path);
4780 if($write_to_upgrade_log)
4782 logThis('config.php values are in sync with config_si.php values. Skipped merging.');
4787 if($write_to_upgrade_log)
4789 logThis('End merge_config_si_settings', $path);
4795 * upgrade_connectors
4796 * @param $path String variable for the log path
4798 function upgrade_connectors($path='') {
4799 logThis('Begin upgrade_connectors', $path);
4801 $filePath = 'custom/modules/Connectors/connectors/sources/ext/soap/hoovers/config.php';
4802 if(file_exists($filePath))
4804 logThis("{$filePath} file", $path);
4806 if(!is_null($config))
4809 if(isset($config['properties']['hoovers_endpoint']))
4811 $config['properties']['hoovers_endpoint'] = 'http://hapi.hoovers.com/HooversAPI-33';
4815 if(isset($config['properties']['hoovers_wsdl']))
4817 $config['properties']['hoovers_wsdl'] = 'http://hapi.hoovers.com/HooversAPI-33/hooversAPI/hooversAPI.wsdl';
4823 if(!write_array_to_file('config', $config, $filePath)) {
4824 logThis("Could not write new configuration to {$filePath} file", $path);
4826 logThis('Modified file successfully with new configuration entries', $path);
4832 $filePath = 'custom/modules/Connectors/connectors/sources/ext/soap/hoovers/vardefs.php';
4833 if(file_exists($filePath))
4835 logThis("Modifying {$filePath} file", $path);
4837 $fileContents = file_get_contents($filePath);
4838 $out = str_replace('bal.specialtyCriteria.companyKeyword', 'bal.specialtyCriteria.companyName', $fileContents);
4839 file_put_contents($filePath, $out);
4842 logThis('End upgrade_connectors', $path);
4846 * Enable the InsideView connector for the four default modules.
4848 function upgradeEnableInsideViewConnector($path='')
4850 logThis('Begin upgradeEnableInsideViewConnector', $path);
4852 // Load up the existing mapping and hand it to the InsideView connector to have it setup the correct logic hooks
4853 $mapFile = 'modules/Connectors/connectors/sources/ext/rest/insideview/mapping.php';
4854 if ( file_exists('custom/'.$mapFile) ) {
4855 logThis('Found CUSTOM mappings', $path);
4856 require('custom/'.$mapFile);
4858 logThis('Used default mapping', $path);
4862 require_once('include/connectors/sources/SourceFactory.php');
4863 $source = SourceFactory::getSource('ext_rest_insideview');
4865 // $mapping is brought in from the mapping.php file above
4866 $source->saveMappingHook($mapping);
4868 require_once('include/connectors/utils/ConnectorUtils.php');
4869 ConnectorUtils::installSource('ext_rest_insideview');
4871 // Now time to set the various modules to active, because this part ignores the default config
4872 require(CONNECTOR_DISPLAY_CONFIG_FILE);
4873 // $modules_sources come from that config file
4874 foreach ( $source->allowedModuleList as $module ) {
4875 $modules_sources[$module]['ext_rest_insideview'] = 'ext_rest_insideview';
4877 if(!write_array_to_file('modules_sources', $modules_sources, CONNECTOR_DISPLAY_CONFIG_FILE)) {
4878 //Log error and return empty array
4879 logThis("Cannot write \$modules_sources to " . CONNECTOR_DISPLAY_CONFIG_FILE,$path);
4882 logThis('End upgradeEnableInsideViewConnector', $path);
4886 function repair_long_relationship_names($path='')
4888 logThis("Begin repair_long_relationship_names", $path);
4889 require_once 'modules/ModuleBuilder/parsers/relationships/DeployedRelationships.php' ;
4890 $GLOBALS['mi_remove_tables'] = false;
4892 foreach($GLOBALS['moduleList'] as $module)
4894 $relationships = new DeployedRelationships ($module) ;
4895 foreach($relationships->getRelationshipList() as $rel_name)
4897 if (strlen($rel_name) > 27 && empty($touched[$rel_name]))
4899 logThis("Rebuilding relationship fields for $rel_name", $path);
4900 $touched[$rel_name] = true;
4901 $rel_obj = $relationships->get($rel_name);
4902 $rel_obj->setReadonly(false);
4903 $relationships->delete($rel_name);
4904 $relationships->save();
4905 $relationships->add($rel_obj);
4906 $relationships->save();
4907 $relationships->build () ;
4911 logThis("End repair_long_relationship_names", $path);
4914 function removeSilentUpgradeVarsCache(){
4915 global $silent_upgrade_vars_loaded;
4917 $cacheFileDir = "{$GLOBALS['sugar_config']['cache_dir']}/silentUpgrader";
4918 $cacheFile = "{$cacheFileDir}/silentUpgradeCache.php";
4920 if(file_exists($cacheFile)){
4924 $silent_upgrade_vars_loaded = array(); // Set to empty to reset it
4929 function loadSilentUpgradeVars(){
4930 global $silent_upgrade_vars_loaded;
4932 if(empty($silent_upgrade_vars_loaded)){
4933 $cacheFile = "{$GLOBALS['sugar_config']['cache_dir']}/silentUpgrader/silentUpgradeCache.php";
4934 // We have no pre existing vars
4935 if(!file_exists($cacheFile)){
4936 // Set the vars array so it's loaded
4937 $silent_upgrade_vars_loaded = array('vars' => array());
4940 require_once($cacheFile);
4941 $silent_upgrade_vars_loaded = $silent_upgrade_vars_cache;
4948 function writeSilentUpgradeVars(){
4949 global $silent_upgrade_vars_loaded;
4951 if(empty($silent_upgrade_vars_loaded)){
4952 return false; // You should have set some values before trying to write the silent upgrade vars
4955 $cacheFileDir = "{$GLOBALS['sugar_config']['cache_dir']}/silentUpgrader";
4956 $cacheFile = "{$cacheFileDir}/silentUpgradeCache.php";
4958 require_once('include/dir_inc.php');
4959 if(!mkdir_recursive($cacheFileDir)){
4962 require_once('include/utils/file_utils.php');
4963 if(!write_array_to_file('silent_upgrade_vars_cache', $silent_upgrade_vars_loaded, $cacheFile, 'w')){
4965 logThis("WARNING: writeSilentUpgradeVars could not write to {$cacheFile}", $path);
4972 function setSilentUpgradeVar($var, $value){
4973 if(!loadSilentUpgradeVars()){
4977 global $silent_upgrade_vars_loaded;
4979 $silent_upgrade_vars_loaded['vars'][$var] = $value;
4984 function getSilentUpgradeVar($var){
4985 if(!loadSilentUpgradeVars()){
4989 global $silent_upgrade_vars_loaded;
4991 if(!isset($silent_upgrade_vars_loaded['vars'][$var])){
4995 return $silent_upgrade_vars_loaded['vars'][$var];
5001 * add_unified_search_to_custom_modules_vardefs
5003 * This method calls the repair code to remove the unified_search_modules.php fiel
5006 function add_unified_search_to_custom_modules_vardefs()
5008 if(file_exists('cache/modules/unified_search_modules.php'))
5010 unlink('cache/modules/unified_search_modules.php');
5016 * change from using the older SugarCache in 6.1 and below to the new one in 6.2
5018 function upgradeSugarCache($file)
5020 global $sugar_config;
5021 // file = getcwd().'/'.$sugar_config['upload_dir'].$_FILES['upgrade_zip']['name'];
5023 $cacheUploadUpgradesTemp = clean_path(mk_temp_dir("{$sugar_config['upload_dir']}upgrades/temp"));
5025 unzip($file, $cacheUploadUpgradesTemp);
5027 if(!file_exists(clean_path("{$cacheUploadUpgradesTemp}/manifest.php"))) {
5028 logThis("*** ERROR: no manifest file detected while bootstraping upgrade wizard files!");
5031 include(clean_path("{$cacheUploadUpgradesTemp}/manifest.php"));
5034 $allFiles = array();
5035 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/database"))) {
5036 $allFiles = findAllFiles(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/database"), $allFiles);
5038 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/SugarCache"))) {
5039 $allFiles = findAllFiles(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/SugarCache"), $allFiles);
5041 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/external_cache.php"))) {
5042 $allFiles[] = clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/external_cache.php");
5044 $cwd = clean_path(getcwd());
5046 foreach($allFiles as $k => $file) {
5047 $file = clean_path($file);
5048 $destFile = str_replace(clean_path($cacheUploadUpgradesTemp.'/'.$manifest['copy_files']['from_dir']), $cwd, $file);
5049 if(!is_dir(dirname($destFile))) {
5050 mkdir_recursive(dirname($destFile)); // make sure the directory exists
5052 if ( stristr($file,'uw_main.tpl') )
5053 logThis('Skipping "'.$file.'" - file copy will during commit step.');
5055 logThis('updating UpgradeWizard code: '.$destFile);
5056 copy_recursive($file, $destFile);
5059 logThis ('is sugar_file_util there '.file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/sugar_file_utils.php")));
5060 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/sugar_file_utils.php"))) {
5061 $file = clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/sugar_file_utils.php");
5062 $destFile = str_replace(clean_path($cacheUploadUpgradesTemp.'/'.$manifest['copy_files']['from_dir']), $cwd, $file);
5063 copy($file,$destFile);
5069 * upgradeDisplayedTabsAndSubpanels
5071 * @param $version String value of current system version (pre upgrade)
5073 function upgradeDisplayedTabsAndSubpanels($version)
5075 if($version < '620')
5077 logThis('start upgrading system displayed tabs and subpanels');
5078 require_once('modules/MySettings/TabController.php');
5079 $tc = new TabController();
5081 //grab the existing system tabs
5082 $tabs = $tc->get_tabs_system();
5084 //add Calls, Meetings, Tasks, Notes, Prospects (Targets) and ProspectLists (Target Lists)
5085 //to displayed tabs unless explicitly set to hidden
5086 $modules_to_add = array('Calls', 'Meetings', 'Tasks', 'Notes', 'Prospects', 'ProspectLists');
5087 $added_tabs = array();
5089 foreach($modules_to_add as $module)
5091 $tabs[0][$module] = $module;
5092 $added_tabs[] = $module;
5095 logThis('calling set_system_tabs on TabController to add tabs: ' . var_export($added_tabs, true));
5096 $tc->set_system_tabs($tabs[0]);
5097 logThis('finish upgrading system displayed tabs and subpanels');
5103 * unlinkUpgradeFiles
5104 * This is a helper function to clean up
5106 * @param $version String value of current system version (pre upgrade)
5108 function unlinkUpgradeFiles($version)
5110 if(!isset($version))
5115 logThis('start unlinking files from previous upgrade');
5116 if($version < '620')
5118 //list of files to remove
5119 $files_to_remove = array('modules/Notifications/metadata/studio.php', 'modules/Help/Forms.php','themes/Sugar5/images/sugarColors.xml');
5121 foreach($files_to_remove as $f)
5125 logThis('removing file: ' . $f);
5130 logThis('end unlinking files from previous upgrade');
5132 if($version < '620')
5134 logThis('start upgrade for DocumentRevisions classic files (EditView.html, EditView.php, DetailView.html, DetailView.php, Save.php)');
5136 //Use a md5 comparison check to see if we can just remove the file where an exact match is found
5137 if($version < '610')
5140 'modules/DocumentRevisions/DetailView.html' => '17ad4d308ce66643fdeb6fdb3b0172d3',
5141 'modules/DocumentRevisions/DetailView.php' => 'd8606cdcd0281ae9443b2580a43eb5b3',
5142 'modules/DocumentRevisions/EditView.php' => 'c7a1c3ef2bb30e3f5a11d122b3c55ff1',
5143 'modules/DocumentRevisions/EditView.html' => '7d360ca703863c957f40b3719babe8c8',
5144 'modules/DocumentRevisions/Save.php' => 'd7e39293a5fb4d605ca2046e7d1fcf28',
5148 'modules/DocumentRevisions/DetailView.html' => 'a8356ff20cd995daffe6cb7f7b8b2340',
5149 'modules/DocumentRevisions/DetailView.php' => '20edf45dd785469c484fbddff1a3f8f2',
5150 'modules/DocumentRevisions/EditView.php' => 'fb31958496f04031b2851dcb4ce87d50',
5151 'modules/DocumentRevisions/EditView.html' => 'b8cada4fa6fada2b4e4928226d8b81ee',
5152 'modules/DocumentRevisions/Save.php' => '7fb62e4ebff879bafc07a08da62902aa',
5156 foreach($dr_files as $rev_file=>$hash)
5158 if(file_exists($rev_file))
5160 //It's a match here so let's just remove the file
5161 if (md5(file_get_contents($rev_file)) == $hash)
5163 logThis('removing file ' . $rev_file);
5166 if(!copy($rev_file, $rev_file . '.suback.bak'))
5168 logThis('error making backup for file ' . $rev_file);
5170 logThis('copied file ' . $rev_file . ' to ' . $rev_file . '.suback.bak');
5177 logThis('end upgrade for DocumentRevisions classic files');
5180 //First check if we even have the scripts_for_patch/files_to_remove directory
5181 require_once('modules/UpgradeWizard/UpgradeRemoval.php');
5183 if(file_exists($_SESSION['unzip_dir'].'/scripts/files_to_remove'))
5185 $files_to_remove = glob($_SESSION['unzip_dir'].'/scripts/files_to_remove/*.php');
5187 foreach($files_to_remove as $script)
5189 if(preg_match('/UpgradeRemoval(\d+)x\.php/', $script, $matches))
5191 $checkVersion = $matches[1] + 1; //Increment by one to check everything equal or below the target version
5192 $upgradeClass = 'UpgradeRemoval' . $matches[1] . 'x';
5193 require_once($_SESSION['unzip_dir'].'/scripts/files_to_remove/' . $upgradeClass . '.php');
5195 //Check to make sure we should load and run this UpgradeRemoval instance
5196 if($checkVersion <= $version && class_exists($upgradeClass))
5198 $upgradeInstance = new $upgradeClass();
5199 if($upgradeInstance instanceof UpgradeRemoval)
5201 logThis('Running UpgradeRemoval instance ' . $upgradeClass);
5202 logThis('Files will be backed up to custom/backup');
5203 $files = $upgradeInstance->getFilesToRemove($version);
5204 foreach($files as $file)
5208 $upgradeInstance->processFilesToRemove($files);
5215 //Check if we have a custom directory
5216 if(file_exists('custom/scripts/files_to_remove'))
5219 $files_to_remove = glob('custom/scripts/files_to_remove/*.php');
5221 foreach($files_to_remove as $script)
5223 if(preg_match('/\/files_to_remove\/(.*?)\.php$/', $script, $matches))
5225 require_once($script);
5226 $upgradeClass = $matches[1];
5228 if(!class_exists($upgradeClass))
5233 $upgradeInstance = new $upgradeClass();
5234 if($upgradeInstance instanceof UpgradeRemoval)
5236 logThis('Running Custom UpgradeRemoval instance ' . $upgradeClass);
5237 $files = $upgradeInstance->getFilesToRemove($version);
5238 foreach($files as $file)
5242 $upgradeInstance->processFilesToRemove($files);
5250 if (!function_exists("getValidDBName"))
5253 * Return a version of $proposed that can be used as a column name in any of our supported databases
5254 * 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)
5255 * @param string $name Proposed name for the column
5256 * @param string $ensureUnique
5257 * @return string Valid column name trimmed to right length and with invalid characters removed
5259 function getValidDBName ($name, $ensureUnique = false, $maxLen = 30)
5261 // first strip any invalid characters - all but alphanumerics and -
5262 $name = preg_replace ( '/[^\w-]+/i', '', $name ) ;
5263 $len = strlen ( $name ) ;
5267 $md5str = md5($name);
5268 $tail = substr ( $name, -8) ;
5269 $temp = substr($md5str , strlen($md5str)-4 );
5270 $result = substr ( $name, 0, 7) . $temp . $tail ;
5271 }else if ($len > ($maxLen - 5))
5273 $result = substr ( $name, 0, 8) . substr ( $name, 8 - $maxLen + 5);
5275 return strtolower ( $result ) ;