2 if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
3 /*********************************************************************************
4 * SugarCRM 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 $nowDate = gmdate($timedate->dbDateFormat);
549 $nowTime = gmdate($timedate->dbTimeFormat);
550 $nowDateTime = $nowDate . ' ' . $nowTime;
552 if($_REQUEST['addTaskReminder'] == 'remind') {
553 logThis('Adding Task for admin for manual merge.', $path);
556 $task->name = $mod_strings['LBL_UW_COMMIT_ADD_TASK_NAME'];
557 $task->description = $desc;
558 $task->date_due = $nowDate;
559 $task->time_due = $nowTime;
560 $task->priority = 'High';
561 $task->status = 'Not Started';
562 $task->assigned_user_id = $current_user->id;
563 $task->created_by = $current_user->id;
564 $task->date_entered = $nowDateTime;
565 $task->date_modified = $nowDateTime;
569 if($_REQUEST['addEmailReminder'] == 'remind') {
570 logThis('Sending Reminder for admin for manual merge.', $path);
572 $email = new Email();
573 $email->assigned_user_id = $current_user->id;
574 $email->name = $mod_strings['LBL_UW_COMMIT_ADD_TASK_NAME'];
575 $email->description = $desc;
576 $email->description_html = nl2br($desc);
577 $email->from_name = $current_user->full_name;
578 $email->from_addr = $current_user->email1;
579 $email->to_addrs_arr = $email->parse_addrs($current_user->email1, '', '', '');
580 $email->cc_addrs_arr = array();
581 $email->bcc_addrs_arr = array();
582 $email->date_entered = $nowDateTime;
583 $email->date_modified = $nowDateTime;
590 function deleteCache(){
591 //Clean modules from cache
592 if(is_dir($GLOBALS['sugar_config']['cache_dir'].'modules')){
593 $allModFiles = array();
594 $allModFiles = findAllFiles($GLOBALS['sugar_config']['cache_dir'].'modules',$allModFiles);
595 foreach($allModFiles as $file){
596 if(file_exists($file)){
601 //Clean jsLanguage from cache
602 if(is_dir($GLOBALS['sugar_config']['cache_dir'].'jsLanguage')){
603 $allModFiles = array();
604 $allModFiles = findAllFiles($GLOBALS['sugar_config']['cache_dir'].'jsLanguage',$allModFiles);
605 foreach($allModFiles as $file){
606 if(file_exists($file)){
611 //Clean smarty from cache
612 if(is_dir($GLOBALS['sugar_config']['cache_dir'].'smarty')){
613 $allModFiles = array();
614 $allModFiles = findAllFiles($GLOBALS['sugar_config']['cache_dir'].'smarty',$allModFiles);
615 foreach($allModFiles as $file){
616 if(file_exists($file)){
621 //Rebuild dashlets cache
622 require_once('include/Dashlets/DashletCacheBuilder.php');
623 $dc = new DashletCacheBuilder();
627 function deleteChance(){
628 //Clean folder from cache
629 if(is_dir('include/SugarObjects/templates/chance')){
630 rmdir_recursive('include/SugarObjects/templates/chance');
632 if(is_dir('include/SugarObjects/templates/chance')){
633 if(!isset($_SESSION['chance'])){
634 $_SESSION['chance'] = '';
636 $_SESSION['chance'] = 'include/SugarObjects/templates/chance';
637 //rename('include/SugarObjects/templates/chance','include/SugarObjects/templates/chance_removeit');
644 * copies upgrade wizard files from new patch if that dir exists
645 * @param string file Path to uploaded zip file
647 function upgradeUWFiles($file) {
648 global $sugar_config;
649 // file = getcwd().'/'.$sugar_config['upload_dir'].$_FILES['upgrade_zip']['name'];
651 $cacheUploadUpgradesTemp = clean_path(mk_temp_dir("{$sugar_config['upload_dir']}upgrades/temp"));
653 unzip($file, $cacheUploadUpgradesTemp);
655 if(!file_exists(clean_path("{$cacheUploadUpgradesTemp}/manifest.php"))) {
656 logThis("*** ERROR: no manifest file detected while bootstraping upgrade wizard files!");
659 include(clean_path("{$cacheUploadUpgradesTemp}/manifest.php"));
664 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/modules/UpgradeWizard"))) {
665 $allFiles = findAllFiles(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/modules/UpgradeWizard"), $allFiles);
668 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/ModuleInstall"))) {
669 $allFiles = findAllFiles(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/ModuleInstall"), $allFiles);
671 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/javascript/yui"))) {
672 $allFiles = findAllFiles(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/javascript/yui"), $allFiles);
674 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/HandleAjaxCall.php"))) {
675 $allFiles[] = clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/HandleAjaxCall.php");
677 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/SugarTheme"))) {
678 $allFiles = findAllFiles(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/SugarTheme"), $allFiles);
682 * /home/chris/workspace/maint450/cache/upload/upgrades/temp/DlNnqP/
683 * SugarEnt-Patch-4.5.0c/modules/Leads/ConvertLead.html
685 $cwd = clean_path(getcwd());
687 foreach($allFiles as $k => $file) {
688 $file = clean_path($file);
689 $destFile = str_replace(clean_path($cacheUploadUpgradesTemp.'/'.$manifest['copy_files']['from_dir']), $cwd, $file);
690 if(!is_dir(dirname($destFile))) {
691 mkdir_recursive(dirname($destFile)); // make sure the directory exists
693 if ( stristr($file,'uw_main.tpl') )
694 logThis('Skipping "'.$file.'" - file copy will during commit step.');
696 logThis('updating UpgradeWizard code: '.$destFile);
697 copy_recursive($file, $destFile);
700 logThis ('is sugar_file_util there '.file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/sugar_file_utils.php")));
701 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/sugar_file_utils.php"))) {
702 $file = clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/sugar_file_utils.php");
703 $destFile = str_replace(clean_path($cacheUploadUpgradesTemp.'/'.$manifest['copy_files']['from_dir']), $cwd, $file);
704 copy($file,$destFile);
711 * gets valid patch file names that exist in upload/upgrade/patch/
713 function getValidPatchName($returnFull = true) {
714 global $base_upgrade_dir;
717 global $sugar_version;
718 global $sugar_config;
719 $uh = new UpgradeHistory();
720 $base_upgrade_dir = $sugar_config['upload_dir'] . "upgrades";
723 // scan for new files (that are not installed)
724 logThis('finding new files for upgrade');
725 $upgrade_content = '';
726 $upgrade_contents = findAllFiles($base_upgrade_dir, array(), false, 'zip');
727 //other variations of zip file i.e. ZIP, zIp,zIP,Zip,ZIp,ZiP
728 $extns = array('ZIP','ZIp','ZiP','Zip','zIP','zIp','ziP');
729 foreach($extns as $extn){
730 $upgrade_contents = array_merge($upgrade_contents,findAllFiles( "$base_upgrade_dir", array() , false, $extn));
738 <b>{$mod_strings['LBL_ML_NAME']}</b>
741 <b>{$mod_strings['LBL_ML_TYPE']}</b>
744 <b>{$mod_strings['LBL_ML_VERSION']}</b>
747 <b>{$mod_strings['LBL_ML_PUBLISHED']}</b>
750 <b>{$mod_strings['LBL_ML_UNINSTALLABLE']}</b>
753 <b>{$mod_strings['LBL_ML_DESCRIPTION']}</b>
758 // assume old patches are there.
759 $upgradeToVersion = array(); // fill with valid patches - we will only use the latest qualified found patch
761 // cn: bug 10609 - notices for uninitialized variables
766 $published_date = '';
771 foreach($upgrade_contents as $upgrade_content) {
772 if(!preg_match("#.*\.zip\$#i", strtolower($upgrade_content))) {
776 $upgrade_content = clean_path($upgrade_content);
777 $the_base = basename($upgrade_content);
778 $the_md5 = md5_file($upgrade_content);
780 $md5_matches = $uh->findByMd5($the_md5);
782 /* 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.
783 * Edge-case: manual upgrade with a FTP of a patch; UH table has no entry for it. Assume nothing. :( */
784 if(0 == sizeof($md5_matches)) {
785 $target_manifest = remove_file_extension( $upgrade_content ) . '-manifest.php';
786 require_once($target_manifest);
788 if(empty($manifest['version'])) {
789 logThis("*** Potential error: patch found with no version [ {$upgrade_content} ]");
792 if(!isset($manifest['type']) || $manifest['type'] != 'patch') {
793 logThis("*** Potential error: patch found with either no 'type' or non-patch type [ {$upgrade_content} ]");
797 $upgradeToVersion[$manifest['version']] = urlencode($upgrade_content);
799 $name = empty($manifest['name']) ? $upgrade_content : $manifest['name'];
800 $version = empty($manifest['version']) ? '' : $manifest['version'];
801 $published_date = empty($manifest['published_date']) ? '' : $manifest['published_date'];
803 $description = empty($manifest['description']) ? 'None' : $manifest['description'];
804 $uninstallable = empty($manifest['is_uninstallable']) ? 'No' : 'Yes';
805 $type = getUITextForType( $manifest['type'] );
806 $manifest_type = $manifest['type'];
808 if(empty($manifest['icon'])) {
809 $icon = getImageForType( $manifest['type'] );
811 $path_parts = pathinfo( $manifest['icon'] );
812 $icon = "<img src=\"" . remove_file_extension( $upgrade_content ) . "-icon." . $path_parts['extension'] . "\">";
817 // cn: bug 10488 use the NEWEST upgrade/patch available when running upgrade wizard.
818 ksort($upgradeToVersion);
819 $upgradeToVersion = array_values($upgradeToVersion);
820 $newest = array_pop($upgradeToVersion);
821 $_SESSION['install_file'] = urldecode($newest); // in-case it was there from a prior.
822 logThis("*** UW using [ {$_SESSION['install_file']} ] as source for patch files.");
824 $cleanUpgradeContent = urlencode($_SESSION['install_file']);
826 // cn: 10606 - cannot upload a patch file since this returned always.
827 if(!empty($cleanUpgradeContent)) {
828 $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";
831 <form action="index.php" method="post">
832 <input type="hidden" name="module" value="UpgradeWizard">
833 <input type="hidden" name="action" value="index">
834 <input type="hidden" name="step" value="{$_REQUEST['step']}">
835 <input type="hidden" name="run" value="delete">
836 <input type=hidden name="install_file" value="{$cleanUpgradeContent}" />
837 <input type=submit value="{$mod_strings['LBL_BUTTON_DELETE']}" />
841 $disabled = "DISABLED";
846 if(empty($cleanUpgradeContent)){
847 $ready .= "<tr><td colspan='7'><i>None</i></td>\n";
848 $ready .= "</table>\n";
850 $ready .= "<br></ul>\n";
852 $return['ready'] = $ready;
853 $return['disabled'] = $disabled;
862 * finalizes upgrade by setting upgrade versions in DB (config table) and sugar_version.php
863 * @return bool true on success
865 function updateVersions($version) {
867 global $sugar_config;
870 logThis('At updateVersions()... updating config table and sugar_version.php.', $path);
873 if(isset($_SESSION['sugar_version_file']) && !empty($_SESSION['sugar_version_file'])) {
874 if(!copy($_SESSION['sugar_version_file'], clean_path(getcwd().'/sugar_version.php'))) {
875 logThis('*** ERROR: sugar_version.php could not be copied to destination! Cannot complete upgrade', $path);
878 logThis('sugar_version.php successfully updated!', $path);
881 logThis('*** ERROR: no sugar_version.php file location found! - cannot complete upgrade...', $path);
885 // handle config table
886 if($db->dbType == 'mysql') {
887 $q1 = "DELETE FROM `config` WHERE `category` = 'info' AND `name` = 'sugar_version'";
888 $q2 = "INSERT INTO `config` (`category`, `name`, `value`) VALUES ('info', 'sugar_version', '{$version}')";
889 } elseif($db->dbType == 'oci8' || $db->dbType == 'oracle') {
890 } elseif($db->dbType == 'mssql') {
891 $q1 = "DELETE FROM config WHERE category = 'info' AND name = 'sugar_version'";
892 $q2 = "INSERT INTO config (category, name, value) VALUES ('info', 'sugar_version', '{$version}')";
895 logThis('Deleting old DB version info from config table.', $path);
898 logThis('Inserting updated version info into config table.', $path);
901 logThis('updateVersions() complete.', $path);
908 * gets a module's lang pack - does not need to be a SugarModule
909 * @param lang string Language
910 * @param module string Path to language folder
911 * @return array mod_strings
913 function getModuleLanguagePack($lang, $module) {
914 $mod_strings = array();
916 if(!empty($lang) && !empty($module)) {
917 $langPack = clean_path(getcwd().'/'.$module.'/language/'.$lang.'.lang.php');
918 $langPackEn = clean_path(getcwd().'/'.$module.'/language/en_us.lang.php');
920 if(file_exists($langPack))
921 include_once($langPack);
922 elseif(file_exists($langPackEn))
923 include_once($langPackEn);
929 * checks system compliance for 4.5+ codebase
930 * @return array Mixed values
932 function checkSystemCompliance() {
933 global $sugar_config;
934 global $current_language;
938 if(!defined('SUGARCRM_MIN_MEM')) {
939 define('SUGARCRM_MIN_MEM', 40);
942 $installer_mod_strings = getModuleLanguagePack($current_language, './install');
944 $ret['error_found'] = false;
947 $php_version = constant('PHP_VERSION');
948 $check_php_version_result = check_php_version($php_version);
950 switch($check_php_version_result) {
952 $ret['phpVersion'] = "<b><span class=stop>{$installer_mod_strings['ERR_CHECKSYS_PHP_INVALID_VER']} {$php_version} )</span></b>";
953 $ret['error_found'] = true;
956 $ret['phpVersion'] = "<b><span class=go>{$installer_mod_strings['ERR_CHECKSYS_PHP_UNSUPPORTED']} {$php_version} )</span></b>";
959 $ret['phpVersion'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_PHP_OK']} {$php_version} )</span></b>";
963 // database and connect
964 switch($sugar_config['dbconfig']['db_type']){
967 $q = "SELECT version();";
969 $a = $db->fetchByAssoc($r);
970 if(version_compare($a['version()'], '4.1.2') < 0) {
971 $ret['error_found'] = true;
972 $ret['mysqlVersion'] = "<b><span class=stop>".$mod_strings['ERR_UW_MYSQL_VERSION'].$a['version()']."</span></b>";
986 if(function_exists('xml_parser_create')) {
987 $ret['xmlStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
989 $ret['xmlStatus'] = "<b><span class=stop>{$installer_mod_strings['LBL_CHECKSYS_NOT_AVAILABLE']}</span></b>";
990 $ret['error_found'] = true;
994 if(function_exists('curl_init')) {
995 $ret['curlStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</font></b>";
997 $ret['curlStatus'] = "<b><span class=go>{$installer_mod_strings['ERR_CHECKSYS_CURL']}</font></b>";
998 $ret['error_found'] = false;
1002 if(function_exists('mb_strlen')) {
1003 $ret['mbstringStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</font></b>";
1005 $ret['mbstringStatus'] = "<b><span class=stop>{$installer_mod_strings['ERR_CHECKSYS_MBSTRING']}</font></b>";
1006 $ret['error_found'] = true;
1010 if(function_exists('imap_open')) {
1011 $ret['imapStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1013 $ret['imapStatus'] = "<b><span class=go>{$installer_mod_strings['ERR_CHECKSYS_IMAP']}</span></b>";
1014 $ret['error_found'] = false;
1019 if('1' == ini_get('safe_mode')) {
1020 $ret['safeModeStatus'] = "<b><span class=stop>{$installer_mod_strings['ERR_CHECKSYS_SAFE_MODE']}</span></b>";
1021 $ret['error_found'] = true;
1023 $ret['safeModeStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1027 // call time pass by ref
1028 if('1' == ini_get('allow_call_time_pass_reference')) {
1029 $ret['callTimeStatus'] = "<b><span class=stop>{$installer_mod_strings['ERR_CHECKSYS_CALL_TIME']}</span></b>";
1030 //continue upgrading
1032 $ret['callTimeStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1036 $ret['memory_msg'] = "";
1037 $memory_limit = "-1";//ini_get('memory_limit');
1038 $sugarMinMem = constant('SUGARCRM_MIN_MEM');
1039 // logic based on: http://us2.php.net/manual/en/ini.core.php#ini.memory-limit
1040 if( $memory_limit == "" ){ // memory_limit disabled at compile time, no memory limit
1041 $ret['memory_msg'] = "<b><span class=\"go\">{$installer_mod_strings['LBL_CHECKSYS_MEM_OK']}</span></b>";
1042 } elseif( $memory_limit == "-1" ){ // memory_limit enabled, but set to unlimited
1043 $ret['memory_msg'] = "<b><span class=\"go\">{$installer_mod_strings['LBL_CHECKSYS_MEM_UNLIMITED']}</span></b>";
1045 rtrim($memory_limit, 'M');
1046 $memory_limit_int = (int) $memory_limit;
1047 if( $memory_limit_int < constant('SUGARCRM_MIN_MEM') ){
1048 $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>";
1049 $ret['error_found'] = true;
1051 $ret['memory_msg'] = "<b><span class=\"go\">{$installer_mod_strings['LBL_CHECKSYS_OK']} ({$memory_limit})</span></b>";
1055 /* mbstring.func_overload
1056 $ret['mbstring.func_overload'] = '';
1057 $mb = ini_get('mbstring.func_overload');
1060 $ret['mbstring.func_overload'] = "<b><span class=\"stop\">{$mod_strings['ERR_UW_MBSTRING_FUNC_OVERLOAD']}</b>";
1061 $ret['error_found'] = true;
1069 function checkMysqlConnection(){
1070 global $sugar_config;
1071 $configOptions = $sugar_config['dbconfig'];
1072 if($sugar_config['dbconfig']['db_type'] == 'mysql'){
1073 @mysql_ping($GLOBALS['db']->database);
1078 * is a file that we blow away automagically
1080 function isAutoOverwriteFile($file) {
1081 $overwriteDirs = array(
1082 './sugar_version.php',
1083 './modules/UpgradeWizard/uw_main.tpl',
1085 $file = trim('.'.str_replace(clean_path(getcwd()), '', $file));
1087 if(in_array($file, $overwriteDirs)) {
1091 $fileExtension = substr(strrchr($file, "."), 1);
1092 if($fileExtension == 'tpl' || $fileExtension == 'html') {
1102 function logThis($entry, $path='') {
1103 global $mod_strings;
1104 if(file_exists('include/utils/sugar_file_utils.php')){
1105 require_once('include/utils/sugar_file_utils.php');
1107 $log = empty($path) ? clean_path(getcwd().'/upgradeWizard.log') : clean_path($path);
1109 // create if not exists
1110 if(!file_exists($log)) {
1111 if(function_exists('sugar_fopen')){
1112 $fp = @sugar_fopen($log, 'w+'); // attempts to create file
1115 $fp = fopen($log, 'w+'); // attempts to create file
1117 if(!is_resource($fp)) {
1118 $GLOBALS['log']->fatal('UpgradeWizard could not create the upgradeWizard.log file');
1119 die($mod_strings['ERR_UW_LOG_FILE_UNWRITABLE']);
1122 if(function_exists('sugar_fopen')){
1123 $fp = @sugar_fopen($log, 'a+'); // write pointer at end of file
1126 $fp = @fopen($log, 'a+'); // write pointer at end of file
1129 if(!is_resource($fp)) {
1130 $GLOBALS['log']->fatal('UpgradeWizard could not open/lock upgradeWizard.log file');
1131 die($mod_strings['ERR_UW_LOG_FILE_UNWRITABLE']);
1135 $line = date('r').' [UpgradeWizard] - '.$entry."\n";
1137 if(@fwrite($fp, $line) === false) {
1138 $GLOBALS['log']->fatal('UpgradeWizard could not write to upgradeWizard.log: '.$entry);
1139 die($mod_strings['ERR_UW_LOG_FILE_UNWRITABLE']);
1142 if(is_resource($fp)) {
1149 * tries to validate the query based on type
1150 * @param string query The query to verify
1151 * @param string dbType The DB type
1152 * @return string error Non-empty string on error
1154 function verifySqlStatement($query, $dbType, &$newTables) {
1156 logThis('verifying SQL statement');
1158 $table = getTableFromQuery($query);
1160 switch(strtoupper(substr($query, 0, 10))) {
1164 $error = testQueryAlter($table, $dbType, strtoupper($query), $newTables);
1168 $error = testQueryCreate($table, $dbType, $query, $newTables);
1172 $error = testQueryDelete($table, $dbType, $query);
1176 $error = testQueryDrop($table, $dbType, $query);
1180 $error = testQueryInsert($table, $dbType, $query);
1183 case (strtoupper(substr($query, 0, 6)) == 'UPDATE'):
1184 $error = testQueryUpdate($table, $dbType, $query);
1196 * @desc This function is to be used in the upgrade process to preserve changes/customaizations made to pre 5.1 quickcreate layout.
1197 * 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
1198 * was automatically picked up by the quick create. [Addresses Bug 21469]
1199 * This function will check if customizations were made, and will create quickcreatedefs.php in the /cutom/working/$module_name directory.
1201 function updateQuickCreateDefs(){
1202 $d = dir('modules');
1203 $studio_modules = array();
1205 while($e = $d->read()){ //collect all studio modules.
1206 if(substr($e, 0, 1) == '.' || !is_dir('modules/' . $e))continue;
1207 if(file_exists('modules/' . $e . '/metadata/studio.php'))
1209 array_push($studio_modules, $e);
1213 foreach( $studio_modules as $modname ){ //for each studio enabled module
1214 //Check !exists modules/$modname/metadata/quickcreatedefs.php &&
1215 //exists custom/$modname/editviewdefs.php (module was customized) &&
1216 //!exists custom/$modname/quickcreateviewdefs.php
1218 $editviewdefs = "custom/working/modules/".$modname."/metadata/editviewdefs.php";
1219 $quickcreatedefs = "custom/working/modules/".$modname."/metadata/quickcreatedefs.php";
1221 if ( !file_exists("modules/".$modname."/metadata/quickcreatedefs.php") &&
1222 file_exists($editviewdefs) &&
1223 !file_exists($quickcreatedefs) ){
1224 //clone editviewdef and save it in custom/working/modules/metadata
1225 $GLOBALS['log']->debug("Copying editviewdefs.php as quickcreatedefs.php for the $modname module in custom/working/modules/$modname/metadata!");
1226 if(copy( $editviewdefs, $quickcreatedefs)){
1227 if(file_exists($quickcreatedefs) && is_readable($quickcreatedefs)){
1228 $file = file($quickcreatedefs);
1229 //replace 'EditView' with 'QuickCreate'
1230 $fp = fopen($quickcreatedefs,'w');
1231 foreach($file as &$line){
1232 if(preg_match("/^\s*'EditView'\s*=>\s*$/", $line) > 0){
1233 $line = "'QuickCreate' =>\n";
1241 $GLOBALS['log']->debug("Failed to replace 'EditView' with QuickCreate because $quickcreatedefs is either not readable or does not exist.");
1244 $GLOBALS['log']->debug("Failed to copy $editviewdefs to $quickcreatedefs!");
1251 function cleanQuery($query, $oci8=false) {
1261 $q = str_replace($bad, $good, $query);
1267 * test perms for CREATE queries
1269 function testPermsCreate($type, $out) {
1270 logThis('Checking CREATE TABLE permissions...');
1272 global $mod_strings;
1277 $db->query('CREATE TABLE temp (id varchar(36))');
1278 if($db->checkError()) {
1279 logThis('cannot CREATE TABLE!');
1280 $out['db']['dbNoCreate'] = true;
1281 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_CREATE']}</span></td></tr>";
1293 * test perms for INSERT
1295 function testPermsInsert($type, $out, $skip=false) {
1296 logThis('Checking INSERT INTO permissions...');
1298 global $mod_strings;
1304 $db->query("INSERT INTO temp (id) VALUES ('abcdef0123456789abcdef0123456789abcd')");
1305 if($db->checkError()) {
1306 logThis('cannot INSERT INTO!');
1307 $out['db']['dbNoInsert'] = true;
1308 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_INSERT']}</span></td></tr>";
1322 * test perms for UPDATE TABLE
1324 function testPermsUpdate($type, $out, $skip=false) {
1325 logThis('Checking UPDATE TABLE permissions...');
1327 global $mod_strings;
1333 $db->query("UPDATE temp SET id = '000000000000000000000000000000000000' WHERE id = 'abcdef0123456789abcdef0123456789abcd'");
1334 if($db->checkError()) {
1335 logThis('cannot UPDATE TABLE!');
1336 $out['db']['dbNoUpdate'] = true;
1337 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_UPDATE']}</span></td></tr>";
1351 * test perms for SELECT
1353 function testPermsSelect($type, $out, $skip=false) {
1354 logThis('Checking SELECT permissions...');
1356 global $mod_strings;
1361 $r = $db->query('SELECT id FROM temp');
1362 if($db->checkError()) {
1363 logThis('cannot SELECT!');
1364 $out['db']['dbNoSelect'] = true;
1365 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_SELECT']}</span></td></tr>";
1367 logThis('Checking validity of SELECT results');
1368 while($a = $db->fetchByAssoc($r)) {
1369 if($a['id'] != '000000000000000000000000000000000000') {
1370 logThis('results DO NOT MATCH! got: '.$a['id']);
1371 $out['db'][] = 'selectFailed';
1372 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_INSERT_FAILED']}</span></td></tr>";
1387 * test perms for DELETE
1389 function testPermsDelete($type, $out, $skip=false) {
1390 logThis('Checking DELETE FROM permissions...');
1392 global $mod_strings;
1397 $db->query("DELETE FROM temp WHERE id = '000000000000000000000000000000000000'");
1398 if($db->checkError()) {
1399 logThis('cannot DELETE FROM!');
1400 $out['db']['dbNoDelete'] = true;
1401 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_DELETE']}</span></td></tr>";
1414 * test perms for ALTER TABLE ADD COLUMN
1416 function testPermsAlterTableAdd($type, $out, $skip=false) {
1417 logThis('Checking ALTER TABLE ADD COLUMN permissions...');
1419 global $mod_strings;
1423 $db->query('ALTER TABLE temp ADD COLUMN test varchar(100)');
1424 if($db->checkError()) {
1425 logThis('cannot ADD COLUMN!');
1426 $out['db']['dbNoAddColumn'] = true;
1427 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_ADD_COLUMN']}</span></td></tr>";
1432 $db->query('ALTER TABLE [temp] ADD [test] [varchar] (100)');
1433 if($db->checkError()) {
1434 logThis('cannot ADD COLUMN!');
1435 $out['db']['dbNoAddColumn'] = true;
1436 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_ADD_COLUMN']}</span></td></tr>";
1451 * test perms for ALTER TABLE ADD COLUMN
1453 function testPermsAlterTableChange($type, $out, $skip=false) {
1454 logThis('Checking ALTER TABLE CHANGE COLUMN permissions...');
1456 global $mod_strings;
1460 $db->query('ALTER TABLE temp CHANGE COLUMN test test varchar(100)');
1461 if($db->checkError()) {
1462 logThis('cannot CHANGE COLUMN!');
1463 $out['db']['dbNoChangeColumn'] = true;
1464 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_CHANGE_COLUMN']}</span></td></tr>";
1469 $db->query('ALTER TABLE [temp] ALTER COLUMN [test] [varchar] (100)');
1470 if($db->checkError()) {
1471 logThis('cannot CHANGE COLUMN!');
1472 $out['db']['dbNoChangeColumn'] = true;
1473 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_CHANGE_COLUMN']}</span></td></tr>";
1487 * test perms for ALTER TABLE DROP COLUMN
1489 function testPermsAlterTableDrop($type, $out, $skip=false) {
1490 logThis('Checking ALTER TABLE DROP COLUMN permissions...');
1492 global $mod_strings;
1497 $db->query('ALTER TABLE temp DROP COLUMN test');
1498 if($db->checkError()) {
1499 logThis('cannot DROP COLUMN!');
1500 $out['db']['dbNoDropColumn'] = true;
1501 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_DROP_COLUMN']}</span></td></tr>";
1514 * test perms for DROP TABLE
1516 function testPermsDropTable($type, $out, $skip=false) {
1517 logThis('Checking DROP TABLE permissions...');
1519 global $mod_strings;
1524 $db->query('DROP TABLE temp');
1525 if($db->checkError()) {
1526 logThis('cannot DROP TABLE!');
1527 $out['db']['dbNoDropTable'] = true;
1528 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_DROP_TABLE']}</span></td></tr>";
1541 function createMSSQLTemp($table) {
1542 global $sugar_config;
1545 $qtest = "SELECT TABLE_NAME tn FROM information.tables WHERE TABLE_NAME = '{$table}__UW_TEMP'";
1546 $rtest = $db->query($qtest);
1547 $atest = $db->fetchByAssoc($rtest);
1550 $tempTable = "CREATE TABLE {$table}__UW_TEMP AS ".$db->limitQuerySql("SELECT * FROM {$table}",0,8);
1551 logThis("Creating temp table for {$table}: {$tempTable}");
1552 $db->query($tempTable);
1555 logThis("Found {$table}__UW_TEMP - skipping temp table creation.");
1560 * Tests an ALTER TABLE query
1561 * @param string table The table name to get DDL
1562 * @param string dbType MySQL, MSSQL, etc.
1563 * @param string query The query to test.
1564 * @return string Non-empty if error found
1566 function testQueryAlter($table, $dbType, $query, $newTables) {
1567 logThis('verifying ALTER statement...');
1569 global $sugar_config;
1572 $db = &DBManagerFactory::getInstance();
1575 // Skipping ALTER TABLE [table] DROP PRIMARY KEY because primary keys are not being copied
1576 // over to the temp tables
1577 if(strpos(strtoupper($query), 'DROP PRIMARY KEY') !== false) {
1578 logThis('Skipping DROP PRIMARY KEY verification');
1582 if ($dbType == 'mysql'){
1583 mysql_error(); // initialize errors
1587 if(!in_array($table, $newTables)) {
1591 logThis('creating temp table for ['.$table.']...');
1592 $q = "SHOW CREATE TABLE {$table}";
1593 $r = $db->query($q);
1594 $a = $db->fetchByAssoc($r);
1596 // rewrite DDL with _temp name
1597 $cleanQuery = cleanQuery($a['Create Table']);
1598 $tempTableQuery = str_replace("CREATE TABLE `{$table}`", "CREATE TABLE `{$table}__uw_temp`", $cleanQuery);
1599 $r2 = $db->query($tempTableQuery);
1601 // get sample data into the temp table to test for data/constraint conflicts
1602 logThis('inserting temp dataset...');
1603 $q3 = "INSERT INTO `{$table}__uw_temp` SELECT * FROM `{$table}` LIMIT 10";
1604 $r3 = $db->query($q3, false, "Preflight Failed for: {$query}");
1606 // test the query on the test table
1607 logThis('testing query: ['.$query.']');
1608 $tempTableTestQuery = str_replace("ALTER TABLE `{$table}`", "ALTER TABLE `{$table}__uw_temp`", $query);
1609 if (strpos($tempTableTestQuery, 'idx') === false) {
1610 if(isRunningAgainstTrueTable($tempTableTestQuery)) {
1611 $error = getFormattedError('Could not use a temp table to test query!', $query);
1615 logThis('testing query on temp table: ['.$tempTableTestQuery.']');
1616 $r4 = $db->query($tempTableTestQuery, false, "Preflight Failed for: {$query}");
1619 // test insertion of an index on a table
1620 $tempTableTestQuery_idx = str_replace("ADD INDEX `idx_", "ADD INDEX `temp_idx_", $tempTableTestQuery);
1621 logThis('testing query on temp table: ['.$tempTableTestQuery_idx.']');
1622 $r4 = $db->query($tempTableTestQuery_idx, false, "Preflight Failed for: {$query}");
1624 $mysqlError = mysql_error(); // empty on no-errors
1625 if(!empty($mysqlError)) {
1626 logThis('*** ERROR: query failed: '.$mysqlError);
1627 $error = getFormattedError($mysqlError, $query);
1631 // clean up moved to end of preflight
1635 logThis('mssql found: skipping test query - ['.$query.']');
1639 logThis('Oracle found: skipping test query - ['.$query.']');
1643 logThis($table . ' is a new table');
1646 logThis('verification done.');
1651 * Tests an CREATE TABLE query
1652 * @param string table The table name to get DDL
1653 * @param string dbType MySQL, MSSQL, etc.
1654 * @param string query The query to test.
1655 * @return string Non-empty if error found
1657 function testQueryCreate($table, $dbType, $query, &$newTables) {
1658 logThis('verifying CREATE statement...');
1661 $db = &DBManagerFactory::getInstance();
1667 // rewrite DDL with _temp name
1668 logThis('testing query: ['.$query.']');
1669 $tempTableQuery = str_replace("CREATE TABLE `{$table}`", "CREATE TABLE `{$table}__uw_temp`", $query);
1671 if(isRunningAgainstTrueTable($tempTableQuery)) {
1672 $error = getFormattedError('Could not use a temp table to test query!', $query);
1676 $r4 = $db->query($tempTableQuery, false, "Preflight Failed for: {$query}");
1678 $error = mysql_error(); // empty on no-errors
1679 if(!empty($error)) {
1680 logThis('*** ERROR: query failed.');
1681 $error = getFormattedError($error, $query);
1684 // check if table exists
1685 logThis('testing for table: '.$table);
1686 $q1 = "DESC `{$table}`";
1687 $r1 = $db->query($q1);
1689 $mysqlError = mysql_error();
1690 if(empty($mysqlError)) {
1691 logThis('*** ERROR: table already exists!: '.$table);
1692 $error = getFormattedError('table exists', $query);
1695 logThis('NEW TABLE: '.$query);
1696 $newTables[] = $table;
1701 logThis('mssql found: skipping test query - ['.$query.']');
1705 logThis('Oracle found: skipping test query - ['.$query.']');
1712 * Tests an DELETE FROM query
1713 * @param string table The table name to get DDL
1714 * @param string dbType MySQL, MSSQL, etc.
1715 * @param string query The query to test.
1716 * @return string Non-empty if error found
1718 function testQueryDelete($table, $dbType, $query) {
1719 logThis('verifying DELETE statements');
1722 $db = &DBManagerFactory::getInstance();
1730 logThis('creating temp table...');
1731 $q = "SHOW CREATE TABLE {$table}";
1732 $r = $db->query($q);
1733 $a = $db->fetchByAssoc($r);
1735 // rewrite DDL with _temp name
1736 $cleanQuery = cleanQuery($a['Create Table']);
1737 $tempTableQuery = str_replace("CREATE TABLE `{$table}`", "CREATE TABLE `{$table}__uw_temp`", $cleanQuery);
1738 $r2 = $db->query($tempTableQuery);
1740 // get sample data into the temp table to test for data/constraint conflicts
1741 logThis('inserting temp dataset...');
1742 $q3 = "INSERT INTO `{$table}__uw_temp` SELECT * FROM `{$table}` LIMIT 10";
1743 $r3 = $db->query($q3);
1745 // test the query on the test table
1746 logThis('testing query: ['.$query.']');
1747 $tempTableTestQuery = str_replace("DELETE FROM `{$table}`", "DELETE FROM `{$table}__uw_temp`", $query);
1749 if(isRunningAgainstTrueTable($tempTableTestQuery)) {
1750 $error = getFormattedError('Could not use a temp table to test query!', $tempTableTestQuery);
1754 $r4 = $db->query($tempTableTestQuery, false, "Preflight Failed for: {$query}");
1755 $error = mysql_error(); // empty on no-errors
1756 if(!empty($error)) {
1757 logThis('*** ERROR: query failed.');
1758 $error = getFormattedError($error, $query);
1763 logThis('mssql found: skipping test query - ['.$query.']');
1767 logThis('Oracle found: skipping test query - ['.$query.']');
1770 logThis('verification done.');
1775 * Tests a DROP TABLE query
1778 function testQueryDrop($table, $dbType, $query) {
1779 logThis('verifying DROP TABLE statement');
1782 $db = &DBManagerFactory::getInstance();
1790 logThis('creating temp table...');
1791 $q = "SHOW CREATE TABLE {$table}";
1792 $r = $db->query($q);
1793 $a = $db->fetchByAssoc($r);
1795 // rewrite DDL with _temp name
1796 $cleanQuery = cleanQuery($a['Create Table']);
1797 $tempTableQuery = str_replace("CREATE TABLE `{$table}`", "CREATE TABLE `{$table}__uw_temp`", $cleanQuery);
1798 $r2 = $db->query($tempTableQuery);
1800 // get sample data into the temp table to test for data/constraint conflicts
1801 logThis('inserting temp dataset...');
1802 $query = stripQuotes($query, $table);
1803 $q3 = "INSERT INTO `{$table}__uw_temp` SELECT * FROM `{$table}` LIMIT 10";
1804 $r3 = $db->query($q3);
1806 // test the query on the test table
1807 logThis('testing query: ['.$query.']');
1808 $tempTableTestQuery = str_replace("DROP TABLE `{$table}`", "DROP TABLE `{$table}__uw_temp`", $query);
1810 // make sure the test query is running against a temp table
1811 if(isRunningAgainstTrueTable($tempTableTestQuery)) {
1812 $error = getFormattedError('Could not use a temp table to test query!', $tempTableTestQuery);
1816 $r4 = $db->query($tempTableTestQuery, false, "Preflight Failed for: {$query}");
1817 $error = mysql_error(); // empty on no-errors
1818 if(!empty($error)) {
1819 logThis('*** ERROR: query failed.');
1820 $error = getFormattedError($error, $query);
1825 logThis('mssql found: skipping test query - ['.$query.']');
1829 logThis('Oracle found: skipping test query - ['.$query.']');
1832 logThis('verification done.');
1837 * Tests an INSERT INTO query
1838 * @param string table The table name to get DDL
1839 * @param string dbType MySQL, MSSQL, etc.
1840 * @param string query The query to test.
1841 * @return string Non-empty if error found
1843 function testQueryInsert($table, $dbType, $query) {
1844 logThis('verifying INSERT statement...');
1847 $db = &DBManagerFactory::getInstance();
1855 $q = "SHOW CREATE TABLE {$table}";
1856 $r = $db->query($q);
1857 $a = $db->fetchByAssoc($r);
1859 // rewrite DDL with _temp name
1860 $cleanQuery = cleanQuery($a['Create Table']);
1861 $tempTableQuery = str_replace("CREATE TABLE `{$table}`", "CREATE TABLE `{$table}__uw_temp`", $cleanQuery);
1862 $r2 = $db->query($tempTableQuery);
1864 // test the query on the test table
1865 logThis('testing query: ['.$query.']');
1866 $tempTableTestQuery = str_replace("INSERT INTO `{$table}`", "INSERT INTO `{$table}__uw_temp`", $query);
1868 // make sure the test query is running against a temp table
1869 if(isRunningAgainstTrueTable($tempTableTestQuery)) {
1870 $error = getFormattedError('Could not use a temp table to test query!', $tempTableTestQuery);
1874 $r4 = $db->query($tempTableTestQuery, false, "Preflight Failed for: {$query}");
1875 $error = mysql_error(); // empty on no-errors
1876 if(!empty($error)) {
1877 logThis('*** ERROR: query failed.');
1878 $error = getFormattedError($error, $query);
1883 logThis('mssql found: skipping test query - ['.$query.']');
1887 logThis('Oracle found: skipping test query - ['.$query.']');
1890 logThis('verification done.');
1896 * Tests an UPDATE TABLE query
1897 * @param string table The table name to get DDL
1898 * @param string dbType MySQL, MSSQL, etc.
1899 * @param string query The query to test.
1900 * @return string Non-empty if error found
1902 function testQueryUpdate($table, $dbType, $query) {
1903 logThis('verifying UPDATE TABLE statement...');
1906 $db = &DBManagerFactory::getInstance();
1914 $q = "SHOW CREATE TABLE {$table}";
1915 $r = $db->query($q);
1916 $a = $db->fetchByAssoc($r);
1918 // rewrite DDL with _temp name
1919 $cleanQuery = cleanQuery($a['Create Table']);
1920 $tempTableQuery = str_replace("CREATE TABLE `{$table}`", "CREATE TABLE `{$table}__uw_temp`", $cleanQuery);
1921 $r2 = $db->query($tempTableQuery);
1923 // get sample data into the temp table to test for data/constraint conflicts
1924 logThis('inserting temp dataset...');
1925 $q3 = "INSERT INTO `{$table}__uw_temp` SELECT * FROM `{$table}` LIMIT 10";
1926 $r3 = $db->query($q3, false, "Preflight Failed for: {$query}");
1928 // test the query on the test table
1929 logThis('testing query: ['.$query.']');
1930 $tempTableTestQuery = str_replace("UPDATE `{$table}`", "UPDATE `{$table}__uw_temp`", $query);
1932 // make sure the test query is running against a temp table
1933 if(isRunningAgainstTrueTable($tempTableTestQuery)) {
1934 $error = getFormattedError('Could not use a temp table to test query!', $tempTableTestQuery);
1938 $r4 = $db->query($tempTableTestQuery, false, "Preflight Failed for: {$query}");
1939 $error = mysql_error(); // empty on no-errors
1940 if(!empty($error)) {
1941 logThis('*** ERROR: query failed.');
1942 $error = getFormattedError($error, $query);
1950 logThis('Oracle found: skipping test query - ['.$query.']');
1953 logThis('verification done.');
1959 * strip queries of single and double quotes
1961 function stripQuotes($query, $table) {
1964 $start = strpos($query, $table);
1966 if(substr($query, ($start - 1), 1) != ' ') {
1967 $queryStrip = substr($query, 0, ($start-2));
1968 $queryStrip .= " {$table} ";
1969 $queryStrip .= substr($query, ($start + strlen($table) + 2), strlen($query));
1972 return (empty($queryStrip)) ? $query : $queryStrip;
1976 * ensures that a __UW_TEMP table test SQL is running against a temp table, not the real thing
1977 * @param string query
1978 * @return bool false if it is a good query
1980 function isRunningAgainstTrueTable($query) {
1981 $query = strtoupper($query);
1982 if(strpos($query, '__UW_TEMP') === false) {
1983 logThis('***ERROR: test query is NOT running against a temp table!!!! -> '.$query);
1998 * cleans up temp tables created during schema test phase
2000 function testCleanUp($dbType) {
2001 logThis('Cleaning up temporary tables...');
2005 $db = &DBManagerFactory::getInstance();
2011 $q = 'SHOW TABLES LIKE "%__uw_temp"';
2012 $r = $db->query($q, false, "Preflight Failed for: {$q}");
2014 // using raw mysql_command to use integer index
2015 while($a = $db->fetchByAssoc($r)) {
2016 logThis('Dropping table: '.$a[0]);
2017 $qClean = "DROP TABLE {$a[0]}";
2018 $rClean = $db->query($qClean);
2028 logThis('Done cleaning up temp tables.');
2033 function getFormattedError($error, $query) {
2034 $error = "<div><b>".$error;
2035 $error .= "</b>::{$query}</div>";
2043 * parses a query finding the table name
2044 * @param string query The query
2045 * @return string table The table
2047 function getTableFromQuery($query) {
2048 $standardQueries = array('ALTER TABLE', 'DROP TABLE', 'CREATE TABLE', 'INSERT INTO', 'UPDATE', 'DELETE FROM');
2049 $query = preg_replace("/[^A-Za-z0-9\_\s]/", "", $query);
2050 $query = trim(str_replace($standardQueries, '', $query));
2052 $firstSpc = strpos($query, " ");
2053 $end = ($firstSpc > 0) ? $firstSpc : strlen($query);
2054 $table = substr($query, 0, $end);
2061 function preLicenseCheck() {
2062 require_once('modules/UpgradeWizard/uw_files.php');
2064 global $sugar_config;
2065 global $mod_strings;
2066 global $sugar_version;
2068 if(!isset($sugar_version) || empty($sugar_version)) {
2069 require_once('./sugar_version.php');
2072 if(!isset($_SESSION['unzip_dir']) || empty($_SESSION['unzip_dir'])) {
2073 logThis('unzipping files in upgrade archive...');
2075 $base_upgrade_dir = $sugar_config['upload_dir'] . "/upgrades";
2076 $base_tmp_upgrade_dir = "$base_upgrade_dir/temp";
2078 //also come up with mechanism to read from upgrade-progress file
2079 if(!isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !is_file($_SESSION['install_file'])) {
2081 if ($handle = opendir(clean_path($sugar_config['upload_dir']))) {
2082 while (false !== ($file = readdir($handle))) {
2083 if($file !="." && $file !="..") {
2084 $far = explode(".",$file);
2085 if($far[sizeof($far)-1] == 'zip') {
2086 echo $sugar_config['upload_dir'].'/'.$file;
2087 $_SESSION['install_file'] = $sugar_config['upload_dir'].'/'.$file;
2093 if (file_exists(clean_path($base_tmp_upgrade_dir)) && $handle = opendir(clean_path($base_tmp_upgrade_dir))) {
2094 while (false !== ($file = readdir($handle))) {
2095 if($file !="." && $file !="..") {
2096 //echo $base_tmp_upgrade_dir."/".$file.'</br>';
2097 if(is_file($base_tmp_upgrade_dir."/".$file."/manifest.php")){
2098 require_once($base_tmp_upgrade_dir."/".$file."/manifest.php");
2099 $package_name= $manifest['copy_files']['from_dir'];
2100 //echo file_exists($base_tmp_upgrade_dir."/".$file."/".$package_name).'</br>';
2101 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")){
2102 //echo 'Yeah this the directory '. $base_tmp_upgrade_dir."/".$file;
2103 $unzip_dir = $base_tmp_upgrade_dir."/".$file;
2104 if(file_exists($sugar_config['upload_dir'].'/upgrades/patch/'.$package_name.'.zip')){
2105 $_SESSION['install_file'] = $sugar_config['upload_dir'].'/upgrades/patch/'.$package_name.'.zip';
2114 if(!isset($_SESSION['install_file']) || empty($_SESSION['install_file'])){
2117 echo 'Upload File not found so redirecting to Upgrade Start ';
2118 $redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
2119 echo '<form name="redirect" action="' .$redirect_new_wizard. '" method="POST">';
2120 $upgrade_directories_not_found =<<<eoq
2121 <table cellpadding="3" cellspacing="0" border="0">
2123 <th colspan="2" align="left">
2124 <span class='error'><b>'Upload file missing or has been deleted. Refresh the page to go back to UpgradeWizard start'</b></span>
2129 $uwMain = $upgrade_directories_not_found;
2132 $install_file = urldecode( $_SESSION['install_file'] );
2134 if(empty($unzip_dir)){
2135 $unzip_dir = mk_temp_dir( $base_tmp_upgrade_dir );
2137 $zip_from_dir = ".";
2139 $zip_force_copy = array();
2142 logThis('Could not create a temporary directory using mk_temp_dir( $base_tmp_upgrade_dir )');
2143 die($mod_strings['ERR_UW_NO_CREATE_TMP_DIR']);
2146 //double check whether unzipped .
2147 if(file_exists($unzip_dir ."/scripts") && file_exists($unzip_dir."/manifest.php")){
2151 unzip( $install_file, $unzip_dir );
2154 // assumption -- already validated manifest.php at time of upload
2155 require_once( "$unzip_dir/manifest.php" );
2157 if( isset( $manifest['copy_files']['from_dir'] ) && $manifest['copy_files']['from_dir'] != "" ){
2158 $zip_from_dir = $manifest['copy_files']['from_dir'];
2160 if( isset( $manifest['copy_files']['to_dir'] ) && $manifest['copy_files']['to_dir'] != "" ){
2161 $zip_to_dir = $manifest['copy_files']['to_dir'];
2163 if( isset( $manifest['copy_files']['force_copy'] ) && $manifest['copy_files']['force_copy'] != "" ){
2164 $zip_force_copy = $manifest['copy_files']['force_copy'];
2166 if( isset( $manifest['version'] ) ){
2167 $version = $manifest['version'];
2169 if( !is_writable( "config.php" ) ){
2170 return $mod_strings['ERR_UW_CONFIG'];
2173 $_SESSION['unzip_dir'] = clean_path($unzip_dir);
2174 $_SESSION['zip_from_dir'] = clean_path($zip_from_dir);
2175 logThis('unzip done.');
2177 $unzip_dir = $_SESSION['unzip_dir'];
2178 $zip_from_dir = $_SESSION['zip_from_dir'];
2181 //check if $_SESSION['unzip_dir'] and $_SESSION['zip_from_dir'] exist
2182 if(!isset($_SESSION['unzip_dir']) || !file_exists($_SESSION['unzip_dir'])
2183 || !isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !file_exists($_SESSION['install_file'])){
2187 echo 'Upload File not found so redirecting to Upgrade Start ';
2188 $redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
2189 echo '<form name="redirect" action="' .$redirect_new_wizard. '" method="POST">';
2190 $upgrade_directories_not_found =<<<eoq
2191 <table cellpadding="3" cellspacing="0" border="0">
2193 <th colspan="2" align="left">
2194 <span class='error'><b>'Upload file missing or has been deleted. Refresh the page to go back to UpgradeWizard start'</b></span>
2199 $uwMain = $upgrade_directories_not_found;
2203 $parserFiles = array();
2205 if(file_exists(clean_path($unzip_dir.'/'.$zip_from_dir."/include/SugarFields"))) {
2206 $parserFiles = findAllFiles(clean_path($unzip_dir.'/'.$zip_from_dir."/include/SugarFields"), $parserFiles);
2209 $cwd = clean_path(getcwd());
2210 foreach($parserFiles as $file) {
2211 $srcFile = clean_path($file);
2212 //$targetFile = clean_path(getcwd() . '/' . $srcFile);
2213 if (strpos($srcFile,".svn") !== false) {
2217 $targetFile = str_replace(clean_path($unzip_dir.'/'.$zip_from_dir), $cwd, $srcFile);
2219 if(!is_dir(dirname($targetFile))) {
2220 mkdir_recursive(dirname($targetFile)); // make sure the directory exists
2223 if(!file_exists($targetFile))
2225 // handle sugar_version.php
2226 // C.L. - Added check for portal directory
2227 if(strpos($targetFile, 'sugar_version.php') !== false && !preg_match('/\/portal\/sugar_version\.php$/i', $targetFile)) {
2228 logThis('Skipping "sugar_version.php" - file copy will occur at end of successful upgrade', $path);
2229 $_SESSION['sugar_version_file'] = $srcFile;
2233 logThis('Copying file to destination: ' . $targetFile);
2235 if(!copy($srcFile, $targetFile)) {
2236 logThis('*** ERROR: could not copy file: ' . $targetFile);
2238 $copiedFiles[] = $targetFile;
2241 logThis('Skipping file: ' . $targetFile);
2242 //$skippedFiles[] = $targetFile;
2247 //Also copy the SugarMerge files
2248 if(file_exists(clean_path($unzip_dir.'/'.$zip_from_dir."/UpgradeWizard510Files"))) {
2249 $parserFiles = findAllFiles(clean_path($unzip_dir.'/'.$zip_from_dir."/UpgradeWizard510Files"), $parserFiles);
2250 foreach($parserFiles as $file) {
2251 $srcFile = clean_path($file);
2252 //$targetFile = clean_path(getcwd() . '/' . $srcFile);
2253 if (strpos($srcFile,".svn") !== false) {
2257 $targetFile = str_replace(clean_path($unzip_dir.'/'.$zip_from_dir."/UpgradeWizard510Files"), $cwd, $srcFile);
2258 if(!is_dir(dirname($targetFile))) {
2259 mkdir_recursive(dirname($targetFile)); // make sure the directory exists
2261 logThis('updating UpgradeWizard code: '.$targetFile);
2262 copy_recursive($file, $targetFile);
2266 logThis ('is SugarConfig there '.file_exists(clean_path($unzip_dir.'/'.$zip_from_dir."/include/SugarObjects/SugarConfig.php")));
2267 if(file_exists(clean_path($unzip_dir.'/'.$zip_from_dir."/include/SugarObjects/SugarConfig.php"))) {
2268 $file = clean_path($unzip_dir.'/'.$zip_from_dir."/include/SugarObjects/SugarConfig.php");
2269 $destFile = str_replace(clean_path($unzip_dir.'/'.$zip_from_dir), $cwd, $file);
2270 if(!is_dir(dirname($destFile))) {
2271 mkdir_recursive(dirname($destFile)); // make sure the directory exists
2273 copy($file,$destFile);
2274 //also copy include utils array utils
2275 $file = clean_path($unzip_dir.'/'.$zip_from_dir."/include/utils/array_utils.php");
2276 $destFile = str_replace(clean_path($unzip_dir.'/'.$zip_from_dir), $cwd, $file);
2277 if(!is_dir(dirname($destFile))) {
2278 mkdir_recursive(dirname($destFile)); // make sure the directory exists
2280 copy($file,$destFile);
2285 function preflightCheck() {
2286 require_once('modules/UpgradeWizard/uw_files.php');
2288 global $sugar_config;
2289 global $mod_strings;
2290 global $sugar_version;
2292 if(!isset($sugar_version) || empty($sugar_version)) {
2293 require_once('./sugar_version.php');
2296 unset($_SESSION['rebuild_relationships']);
2297 unset($_SESSION['rebuild_extensions']);
2299 // don't bother if are rechecking
2300 $manualDiff = array();
2301 if(!isset($_SESSION['unzip_dir']) || empty($_SESSION['unzip_dir'])) {
2302 logThis('unzipping files in upgrade archive...');
2304 $base_upgrade_dir = $sugar_config['upload_dir'] . "/upgrades";
2305 $base_tmp_upgrade_dir = "$base_upgrade_dir/temp";
2307 //Following is if User logged out unexpectedly and then logged into UpgradeWizard again.
2308 //also come up with mechanism to read from upgrade-progress file.
2309 if(!isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !is_file($_SESSION['install_file'])) {
2310 if (file_exists(clean_path($base_tmp_upgrade_dir)) && $handle = opendir(clean_path($base_tmp_upgrade_dir))) {
2311 while (false !== ($file = readdir($handle))) {
2312 if($file !="." && $file !="..") {
2313 //echo $base_tmp_upgrade_dir."/".$file.'</br>';
2314 if(is_file($base_tmp_upgrade_dir."/".$file."/manifest.php")){
2315 require_once($base_tmp_upgrade_dir."/".$file."/manifest.php");
2316 $package_name= $manifest['copy_files']['from_dir'];
2317 //echo file_exists($base_tmp_upgrade_dir."/".$file."/".$package_name).'</br>';
2318 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")){
2319 //echo 'Yeah this the directory '. $base_tmp_upgrade_dir."/".$file;
2320 $unzip_dir = $base_tmp_upgrade_dir."/".$file;
2321 if(file_exists($sugar_config['upload_dir'].'/upgrades/patch/'.$package_name.'.zip')){
2322 $_SESSION['install_file'] = $sugar_config['upload_dir'].'/upgrades/patch/'.$package_name.'.zip';
2331 if(!isset($_SESSION['install_file']) || empty($_SESSION['install_file'])){
2334 echo 'Upload File not found so redirecting to Upgrade Start ';
2335 $redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
2336 echo '<form name="redirect" action="' .$redirect_new_wizard. '" method="POST">';
2337 $upgrade_directories_not_found =<<<eoq
2338 <table cellpadding="3" cellspacing="0" border="0">
2340 <th colspan="2" align="left">
2341 <span class='error'><b>'Upload file missing or has been deleted. Refresh the page to go back to UpgradeWizard start'</b></span>
2346 $uwMain = $upgrade_directories_not_found;
2350 $install_file = urldecode( $_SESSION['install_file'] );
2352 if(empty($unzip_dir)){
2353 $unzip_dir = mk_temp_dir( $base_tmp_upgrade_dir );
2355 $zip_from_dir = ".";
2357 $zip_force_copy = array();
2360 logThis('Could not create a temporary directory using mk_temp_dir( $base_tmp_upgrade_dir )');
2361 die($mod_strings['ERR_UW_NO_CREATE_TMP_DIR']);
2364 //double check whether unzipped .
2365 if(file_exists($unzip_dir ."/scripts") && file_exists($unzip_dir."/manifest.php")){
2369 unzip( $install_file, $unzip_dir );
2372 // assumption -- already validated manifest.php at time of upload
2373 require_once( "$unzip_dir/manifest.php" );
2375 if( isset( $manifest['copy_files']['from_dir'] ) && $manifest['copy_files']['from_dir'] != "" ){
2376 $zip_from_dir = $manifest['copy_files']['from_dir'];
2378 if( isset( $manifest['copy_files']['to_dir'] ) && $manifest['copy_files']['to_dir'] != "" ){
2379 $zip_to_dir = $manifest['copy_files']['to_dir'];
2381 if( isset( $manifest['copy_files']['force_copy'] ) && $manifest['copy_files']['force_copy'] != "" ){
2382 $zip_force_copy = $manifest['copy_files']['force_copy'];
2384 if( isset( $manifest['version'] ) ){
2385 $version = $manifest['version'];
2387 if( !is_writable( "config.php" ) ){
2388 return $mod_strings['ERR_UW_CONFIG'];
2391 $_SESSION['unzip_dir'] = clean_path($unzip_dir);
2392 $_SESSION['zip_from_dir'] = clean_path($zip_from_dir);
2394 //logThis('unzip done.');
2396 $unzip_dir = $_SESSION['unzip_dir'];
2397 $zip_from_dir = $_SESSION['zip_from_dir'];
2399 //check if $_SESSION['unzip_dir'] and $_SESSION['zip_from_dir'] exist
2400 if(!isset($_SESSION['unzip_dir']) || !file_exists($_SESSION['unzip_dir'])
2401 || !isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !file_exists($_SESSION['install_file'])){
2405 echo 'Upload File not found so redirecting to Upgrade Start ';
2406 $redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
2407 echo '<form name="redirect" action="' .$redirect_new_wizard. '" method="POST">';
2408 $upgrade_directories_not_found =<<<eoq
2409 <table cellpadding="3" cellspacing="0" border="0">
2411 <th colspan="2" align="left">
2412 <span class='error'><b>'Upload file missing or has been deleted. Refresh the page to go back to UpgradeWizard start'</b></span>
2417 $uwMain = $upgrade_directories_not_found;
2420 //copy minimum required files
2421 fileCopy('include/utils/sugar_file_utils.php');
2424 if(file_exists('include/utils/file_utils.php')){
2427 $upgradeFiles = findAllFiles(clean_path("$unzip_dir/$zip_from_dir"), array());
2428 $cache_html_files= array();
2429 if(is_dir("{$GLOBALS['sugar_config']['cache_dir']}layout")){
2430 //$cache_html_files = findAllFilesRelative( "cache/layout", array());
2434 $md5_string = array();
2435 if(file_exists(clean_path(getcwd().'/files.md5'))){
2436 require(clean_path(getcwd().'/files.md5'));
2439 // file preflight checks
2440 logThis('verifying md5 checksums for files...');
2441 foreach($upgradeFiles as $file) {
2442 if(in_array(str_replace(clean_path("$unzip_dir/$zip_from_dir") . "/", '', $file), $uw_files))
2443 continue; // skip already loaded files
2445 if(strpos($file, '.md5'))
2446 continue; // skip md5 file
2448 // normalize file paths
2449 $file = clean_path($file);
2451 // check that we can move/delete the upgraded file
2452 if(!is_writable($file)) {
2453 $errors[] = $mod_strings['ERR_UW_FILE_NOT_WRITABLE'].": ".$file;
2455 // check that destination files are writable
2456 $destFile = getcwd().str_replace(clean_path($unzip_dir.'/'.$zip_from_dir), '', $file);
2458 if(is_file($destFile)) { // of course it needs to exist first...
2459 if(!is_writable($destFile)) {
2460 $errors[] = $mod_strings['ERR_UW_FILE_NOT_WRITABLE'].": ".$destFile;
2464 ///////////////////////////////////////////////////////////////////////
2466 // compare md5s and build up a manual merge list
2467 $targetFile = clean_path(".".str_replace(getcwd(),'',$destFile));
2469 if(is_file($destFile)) {
2470 if(strpos($targetFile, '.php')) {
2471 // handle PHP files that were hit with the security regex
2473 if(function_exists('sugar_fopen')){
2474 $fp = sugar_fopen($destFile, 'r');
2477 $fp = fopen($destFile, 'r');
2479 $filesize = filesize($destFile);
2481 $fileContents = fread($fp, $filesize);
2482 $targetMd5 = md5($fileContents);
2485 $targetMd5 = md5_file($destFile);
2489 if(isset($md5_string[$targetFile]) && $md5_string[$targetFile] != $targetMd5) {
2490 logThis('found a file with a differing md5: ['.$targetFile.']');
2491 $manualDiff[] = $destFile;
2494 ///////////////////////////////////////////////////////////////////////
2496 logThis('md5 verification done.');
2497 $errors['manual'] = $manualDiff;
2502 function fileCopy($file_path){
2503 if(file_exists(clean_path($_SESSION['unzip_dir'].'/'.$_SESSION['zip_from_dir'].'/'.$file_path))) {
2504 $file = clean_path($_SESSION['unzip_dir'].'/'.$_SESSION['zip_from_dir'].'/'.$file_path);
2505 $destFile = str_replace(clean_path($_SESSION['unzip_dir'].'/'.$_SESSION['zip_from_dir']), clean_path(getcwd()), $file);
2506 if(!is_dir(dirname($destFile))) {
2507 mkdir_recursive(dirname($destFile)); // make sure the directory exists
2509 copy_recursive($file,$destFile);
2512 function getChecklist($steps, $step) {
2513 global $mod_strings;
2515 $skip = array('start', 'cancel', 'uninstall','end');
2518 $ret = '<table cellpadding="3" cellspacing="4" border="0">';
2519 $ret .= '<tr><th colspan="3" align="left">'.$mod_strings['LBL_UW_CHECKLIST'].':</th></tr>';
2520 foreach($steps['desc'] as $k => $desc) {
2521 if(in_array($steps['files'][$j], $skip)) {
2526 //$status = "<span class='error'>{$mod_strings['LBL_UW_INCOMPLETE']}</span>";
2528 $desc_mod_post = '';
2530 if(isset($_SESSION['step'][$steps['files'][$k]]) && $_SESSION['step'][$steps['files'][$k]] == 'success') {
2531 //$status = $mod_strings['LBL_UW_COMPLETE'];
2535 if($k == $_REQUEST['step']) {
2536 //$status = $mod_strings['LBL_UW_IN_PROGRESS'];
2537 $desc_mod_pre = "<font color=blue><i>";
2538 $desc_mod_post = "</i></font>";
2541 $ret .= "<tr><td> </td><td><b>{$i}: {$desc_mod_pre}{$desc}{$desc_mod_post}</b></td>";
2542 $ret .= "<td id={$steps['files'][$j]}><i></i></td></tr>";
2550 function prepSystemForUpgrade() {
2551 global $sugar_config;
2552 global $sugar_flavor;
2553 global $mod_strings;
2555 global $base_upgrade_dir;
2556 global $base_tmp_upgrade_dir;
2558 ///////////////////////////////////////////////////////////////////////////////
2559 //// Make sure variables exist
2560 if(!isset($base_upgrade_dir) || empty($base_upgrade_dir)){
2561 $base_upgrade_dir = getcwd().'/'.$sugar_config['upload_dir'] . "upgrades";
2563 if(!isset($base_tmp_upgrade_dir) || empty($base_tmp_upgrade_dir)){
2564 $base_tmp_upgrade_dir = "$base_upgrade_dir/temp";
2566 if(!isset($subdirs) || empty($subdirs)){
2567 $subdirs = array('full', 'langpack', 'module', 'patch', 'theme', 'temp');
2570 $upgrade_progress_dir = getcwd().'/'.$GLOBALS['sugar_config']['upload_dir'].'upgrades/temp';
2571 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
2572 if(file_exists($upgrade_progress_file)){
2573 if(function_exists('get_upgrade_progress') && function_exists('didThisStepRunBefore')){
2574 if(didThisStepRunBefore('end')){
2575 include($upgrade_progress_file);
2576 unset($upgrade_config);
2577 unlink($upgrade_progress_file);
2582 // increase the cuttoff time to 1 hour
2583 ini_set("max_execution_time", "3600");
2585 // make sure dirs exist
2586 if($subdirs != null){
2587 foreach($subdirs as $subdir) {
2588 mkdir_recursive("$base_upgrade_dir/$subdir");
2591 // array of special scripts that are executed during (un)installation-- key is type of script, value is filename
2592 if(!defined('SUGARCRM_PRE_INSTALL_FILE')) {
2593 define('SUGARCRM_PRE_INSTALL_FILE', 'scripts/pre_install.php');
2594 define('SUGARCRM_POST_INSTALL_FILE', 'scripts/post_install.php');
2595 define('SUGARCRM_PRE_UNINSTALL_FILE', 'scripts/pre_uninstall.php');
2596 define('SUGARCRM_POST_UNINSTALL_FILE', 'scripts/post_uninstall.php');
2599 $script_files = array(
2600 "pre-install" => constant('SUGARCRM_PRE_INSTALL_FILE'),
2601 "post-install" => constant('SUGARCRM_POST_INSTALL_FILE'),
2602 "pre-uninstall" => constant('SUGARCRM_PRE_UNINSTALL_FILE'),
2603 "post-uninstall" => constant('SUGARCRM_POST_UNINSTALL_FILE'),
2606 // check that the upload limit is set to 6M or greater
2607 define('SUGARCRM_MIN_UPLOAD_MAX_FILESIZE_BYTES', 6 * 1024 * 1024); // 6 Megabytes
2608 $upload_max_filesize = ini_get('upload_max_filesize');
2609 $upload_max_filesize_bytes = return_bytes($upload_max_filesize);
2611 if($upload_max_filesize_bytes < constant('SUGARCRM_MIN_UPLOAD_MAX_FILESIZE_BYTES')) {
2612 $GLOBALS['log']->debug("detected upload_max_filesize: $upload_max_filesize");
2614 echo '<p class="error">'.$mod_strings['MSG_INCREASE_UPLOAD_MAX_FILESIZE'].' '.get_cfg_var('cfg_file_path')."</p>\n";
2618 if ( !function_exists('extractFile') ) {
2619 function extractFile($zip_file, $file_in_zip) {
2620 global $base_tmp_upgrade_dir;
2623 $absolute_base_tmp_upgrade_dir = clean_path($base_tmp_upgrade_dir);
2624 $relative_base_tmp_upgrade_dir = clean_path(str_replace(clean_path(getcwd()), '', $absolute_base_tmp_upgrade_dir));
2626 // mk_temp_dir expects relative pathing
2627 $my_zip_dir = mk_temp_dir($relative_base_tmp_upgrade_dir);
2629 unzip_file($zip_file, $file_in_zip, $my_zip_dir);
2631 return("$my_zip_dir/$file_in_zip");
2635 if ( !function_exists('extractManifest') ) {
2636 function extractManifest($zip_file) {
2637 logThis('extracting manifest.');
2638 return(extractFile($zip_file, "manifest.php"));
2642 if ( !function_exists('getInstallType') ) {
2643 function getInstallType($type_string) {
2646 $subdirs = array('full', 'langpack', 'module', 'patch', 'theme', 'temp');
2647 foreach($subdirs as $subdir) {
2648 if(preg_match("#/$subdir/#", $type_string)) {
2652 // return empty if no match
2657 function getImageForType($type) {
2662 $icon = SugarThemeRegistry::current()->getImage("Upgrade", "");
2665 $icon = SugarThemeRegistry::current()->getImage("LanguagePacks", "");
2668 $icon = SugarThemeRegistry::current()->getImage("ModuleLoader", "");
2671 $icon = SugarThemeRegistry::current()->getImage("PatchUpgrades", "");
2674 $icon = SugarThemeRegistry::current()->getImage("Themes", "");
2682 if ( !function_exists('getLanguagePackName') ) {
2683 function getLanguagePackName($the_file) {
2684 require_once("$the_file");
2685 if(isset($app_list_strings["language_pack_name"])) {
2686 return($app_list_strings["language_pack_name"]);
2692 function getUITextForType($type) {
2693 if($type == "full") {
2694 return("Full Upgrade");
2696 if($type == "langpack") {
2697 return("Language Pack");
2699 if($type == "module") {
2702 if($type == "patch") {
2705 if($type == "theme") {
2712 * @todo this function doesn't seemed to be used anymore; trying kill this off
2714 function run_upgrade_wizard_sql($script) {
2716 global $sugar_config;
2718 $db_type = $sugar_config['dbconfig']['db_type'];
2719 $script = str_replace("%db_type%", $db_type, $script);
2720 if(!run_sql_file("$unzip_dir/$script")) {
2721 die("Error running sql file: $unzip_dir/$script");
2725 if ( !function_exists('validate_manifest') ) {
2727 * Verifies a manifest from a patch or module to be compatible with the current Sugar version and flavor
2728 * @param array manifest Standard manifest array
2729 * @return string Error message, blank on success
2731 function validate_manifest($manifest) {
2732 logThis('validating manifest.php file');
2733 // takes a manifest.php manifest array and validates contents
2735 global $sugar_version;
2736 global $sugar_flavor;
2737 global $mod_strings;
2739 if(!isset($manifest['type'])) {
2740 return $mod_strings['ERROR_MANIFEST_TYPE'];
2743 $type = $manifest['type'];
2745 if(getInstallType("/$type/") == "") {
2746 return $mod_strings['ERROR_PACKAGE_TYPE']. ": '" . $type . "'.";
2749 if(isset($manifest['acceptable_sugar_versions'])) {
2750 $version_ok = false;
2751 $matches_empty = true;
2752 if(isset($manifest['acceptable_sugar_versions']['exact_matches'])) {
2753 $matches_empty = false;
2754 foreach($manifest['acceptable_sugar_versions']['exact_matches'] as $match) {
2755 if($match == $sugar_version) {
2760 if(!$version_ok && isset($manifest['acceptable_sugar_versions']['regex_matches'])) {
2761 $matches_empty = false;
2762 foreach($manifest['acceptable_sugar_versions']['regex_matches'] as $match) {
2763 if(preg_match("/$match/", $sugar_version)) {
2769 if(!$matches_empty && !$version_ok) {
2770 return $mod_strings['ERROR_VERSION_INCOMPATIBLE']."<br />".
2771 $mod_strings['ERR_UW_VERSION'].$sugar_version;
2775 if(isset($manifest['acceptable_sugar_flavors']) && sizeof($manifest['acceptable_sugar_flavors']) > 0) {
2777 foreach($manifest['acceptable_sugar_flavors'] as $match) {
2778 if($match == $sugar_flavor) {
2783 return $mod_strings['ERROR_FLAVOR_INCOMPATIBLE']."<br />".
2784 $mod_strings['ERR_UW_FLAVOR'].$sugar_flavor."<br />".
2785 $mod_strings['ERR_UW_FLAVOR_2'].$manifest['acceptable_sugar_flavors'][0];
2793 function unlinkUploadFiles() {
2795 // logThis('at unlinkUploadFiles()');
2797 // if(isset($_SESSION['install_file']) && !empty($_SESSION['install_file'])) {
2798 // $upload = $_SESSION['install_file'];
2800 // if(is_file($upload)) {
2801 // logThis('unlinking ['.$upload.']');
2802 // @unlink($upload);
2807 if ( !function_exists('unlinkTempFiles') ) {
2809 * deletes files created by unzipping a package
2811 function unlinkTempFiles() {
2812 global $sugar_config;
2815 logThis('at unlinkTempFiles()');
2817 $sugar_config['upload_dir']='cache/upload/';
2818 //if(isset($sugar_config['upload_dir']) && $sugar_config['upload_dir'] != null && $sugar_config['upload_dir']=='cache/upload/'){
2819 $tempDir = clean_path(getcwd().'/'.$sugar_config['upload_dir'].'upgrades/temp');
2822 $uploadDir = getcwd()."/".'cache/upload/';
2823 $tempDir = clean_path(getcwd().'/'.$uploadDir.'upgrades/temp');
2825 if(file_exists($tempDir) && is_dir($tempDir)){
2826 $files = findAllFiles($tempDir, array(), false);
2828 foreach($files as $file) {
2829 if(!is_dir($file)) {
2830 logThis('unlinking ['.$file.']', $path);
2835 $files = findAllFiles($tempDir, array(), true);
2836 foreach($files as $dir) {
2838 logThis('removing dir ['.$dir.']', $path);
2842 $cacheFile = "modules/UpgradeWizard/_persistence.php";
2843 if(is_file($cacheFile)) {
2844 logThis("Unlinking Upgrade cache file: '_persistence.php'", $path);
2845 @unlink($cacheFile);
2848 logThis("finished!");
2853 * finds all files in the passed path, but skips select directories
2854 * @param string dir Relative path
2855 * @param array the_array Collections of found files/dirs
2856 * @param bool include_dir True if we want to include directories in the
2857 * returned collection
2859 function uwFindAllFiles($dir, $the_array, $include_dirs=false, $skip_dirs=array(), $echo=false) {
2861 foreach($skip_dirs as $skipMe) {
2862 if(strpos(clean_path($dir), $skipMe) !== false) {
2869 while($f = $d->read()) {
2870 if($f == "." || $f == "..") { // skip *nix self/parent
2874 // for AJAX length count
2880 if(is_dir("$dir/$f")) {
2881 if($include_dirs) { // add the directory if flagged
2882 $the_array[] = clean_path("$dir/$f");
2886 $the_array = uwFindAllFiles("$dir/$f/", $the_array, $include_dirs, $skip_dirs, $echo);
2888 $the_array[] = clean_path("$dir/$f");
2900 * unset's UW's Session Vars
2902 function resetUwSession() {
2903 logThis('resetting $_SESSION');
2905 if(isset($_SESSION['committed']))
2906 unset($_SESSION['committed']);
2907 if(isset($_SESSION['sugar_version_file']))
2908 unset($_SESSION['sugar_version_file']);
2909 if(isset($_SESSION['upgrade_complete']))
2910 unset($_SESSION['upgrade_complete']);
2911 if(isset($_SESSION['allTables']))
2912 unset($_SESSION['allTables']);
2913 if(isset($_SESSION['alterCustomTableQueries']))
2914 unset($_SESSION['alterCustomTableQueries']);
2915 if(isset($_SESSION['skip_zip_upload']))
2916 unset($_SESSION['skip_zip_upload']);
2917 if(isset($_SESSION['sugar_version_file']))
2918 unset($_SESSION['sugar_version_file']);
2919 if(isset($_SESSION['install_file']))
2920 unset($_SESSION['install_file']);
2921 if(isset($_SESSION['unzip_dir']))
2922 unset($_SESSION['unzip_dir']);
2923 if(isset($_SESSION['zip_from_dir']))
2924 unset($_SESSION['zip_from_dir']);
2925 if(isset($_SESSION['overwrite_files']))
2926 unset($_SESSION['overwrite_files']);
2927 if(isset($_SESSION['schema_change']))
2928 unset($_SESSION['schema_change']);
2929 if(isset($_SESSION['uw_restore_dir']))
2930 unset($_SESSION['uw_restore_dir']);
2931 if(isset($_SESSION['step']))
2932 unset($_SESSION['step']);
2933 if(isset($_SESSION['files']))
2934 unset($_SESSION['files']);
2935 if(isset($_SESSION['Upgraded451Wizard'])){
2936 unset($_SESSION['Upgraded451Wizard']);
2938 if(isset($_SESSION['Initial_451to500_Step'])){
2939 unset($_SESSION['Initial_451to500_Step']);
2941 if(isset($_SESSION['license_shown']))
2942 unset($_SESSION['license_shown']);
2943 if(isset($_SESSION['sugarMergeRunResults']))
2944 unset($_SESSION['sugarMergeRunResults']);
2948 * runs rebuild scripts
2950 function UWrebuild() {
2954 logThis('Rebuilding everything...', $path);
2955 // require_once('ModuleInstall/ModuleInstaller.php');
2956 // $mi = new ModuleInstaller();
2957 // $mi->rebuild_all(true);
2958 require_once('modules/Administration/QuickRepairAndRebuild.php');
2959 $randc = new RepairAndClear();
2960 $randc->repairAndClearAll(array('clearAll'),array(translate('LBL_ALL_MODULES')), false, false);
2962 $query = "DELETE FROM versions WHERE name='Rebuild Extensions'";
2964 logThis('Registering rebuild record: '.$query, $path);
2965 logThis('Rebuild done.', $path);
2967 // insert a new database row to show the rebuild extensions is done
2968 $id = create_guid();
2969 $gmdate = gmdate($GLOBALS['timedate']->get_db_date_time_format());
2970 $date_entered = db_convert("'$gmdate'", 'datetime');
2971 $query = 'INSERT INTO versions (id, deleted, date_entered, date_modified, modified_user_id, created_by, name, file_version, db_version) '
2972 . "VALUES ('$id', '0', $date_entered, $date_entered, '1', '1', 'Rebuild Extensions', '4.0.0', '4.0.0')";
2974 logThis('Registering rebuild record in versions table: '.$query, $path);
2977 function getCustomTables($dbType) {
2980 $customTables = array();
2984 $query = "SHOW tables LIKE '%_cstm'";
2985 $result = $db->query($query);//, true, 'Error getting custom tables');
2986 while ($row = $db->fetchByAssoc($result)){
2987 $customTables[] = array_pop($row);
2991 return $customTables;
2994 function alterCustomTables($dbType, $customTables)
2999 while( $i < count($customTables) ) {
3000 $alterCustomTableSql[] = "ALTER TABLE " . $customTables[$i] . " CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci";
3007 return $alterCustomTableSql;
3010 function executeAlterCustomTablesSql($dbType, $queries) {
3013 foreach($queries as $query){
3015 logThis("Sending query: ".$query);
3016 if($db->dbType == 'oci8') {
3018 $query_result = $db->query($query);//.';', true, "An error has occured while performing db query. See log file for details.<br>");
3025 function getAllTables($dbType) {
3032 $query = "SHOW tables";
3033 $result = $db->query($query, true, 'Error getting custom tables');
3034 while ($row = $db->fetchByAssoc($result)){
3035 $tables[] = array_pop($row);
3042 function printAlterTableSql($tables)
3044 $alterTableSql = '';
3046 foreach($tables as $table)
3047 $alterTableSql .= "ALTER TABLE " . $table . " CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;" . "\n";
3049 return $alterTableSql;
3052 function executeConvertTablesSql($dbType, $tables) {
3055 foreach($tables as $table){
3056 $query = "ALTER TABLE " . $table . " CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci";
3058 logThis("Sending query: ".$query);
3059 if($db->dbType == 'oci8') {
3061 $query_result = $db->query($query);//.';', true, "An error has occured while performing db query. See log file for details.<br>");
3068 function testThis() {
3069 $files = uwFindAllFiles(getcwd().'/test', array());
3071 $out = "<table cellpadding='1' cellspacing='0' border='0'>\n";
3074 foreach($files as $file) {
3075 $relativeFile = clean_path(str_replace(getcwd().'/test', '', $file));
3076 $relativeFile = ($relativeFile{0} == '/') ? substr($relativeFile, 1, strlen($relativeFile)) : $relativeFile;
3078 $relativePath = dirname($relativeFile);
3080 if($relativePath == $priorPath) { // same dir, new file
3081 $out .= "<tr><td>".basename($relativeFile)."</td></tr>";
3082 $priorPath = $relativePath;
3096 function testThis2($dir, $id=0, $hide=false) {
3098 $dh = opendir($dir);
3101 $doHide = ($hide) ? 'none' : '';
3102 $out = "<div id='{$id}' style='display:{$doHide};'>";
3103 $out .= "<table cellpadding='1' cellspacing='0' border='0' style='border:0px solid #ccc'>\n";
3105 while($file = readdir($dh)) {
3106 if($file == '.' || $file == '..' || $file == 'CVS' || $file == '.cvsignore')
3109 if(is_dir($path.'/'.$file)) {
3110 $file = $path.'/'.$file;
3111 $newI = create_guid();
3112 $out .= "<tr><td valign='top'><a href='javascript:toggleNwFiles(\"{$newI}\");'><img border='0' src='".SugarThemeRegistry::current()->getImageURL('Workflow.gif')."'></a></td>\n";
3113 $out .= "<td valign='top'><b><a href='javascript:toggleNwFiles(\"{$newI}\");'>".basename($file)."</a></b></td></tr>";
3114 $out .= "<tr><td></td><td valign='top'>".testThis2($file, $newI, true)."</td></tr>";
3116 $out .= "<tr><td valign='top'> </td>\n";
3117 $out .= "<td valign='top'>".basename($file)."</td></tr>";
3121 $out .= "</tr></table>";
3132 function testThis3(&$files, $id, $hide, $previousPath = '') {
3133 if(!is_array($files) || empty($files))
3138 // expecting full path here
3139 foreach($files as $k => $file) {
3140 $file = str_replace(getcwd(), '', $file);
3141 $path = dirname($file);
3142 $fileName = basename($file);
3144 if($fileName == 'CVS' || $fileName == '.cvsignore')
3147 if($path == $previousPath) { // same directory
3148 // new row for each file
3149 $out .= "<tr><td valign='top' align='left'> </td>";
3150 $out .= "<td valign='top' align='left'>{$fileName}</td></tr>";
3151 } else { // new directory
3153 $out .= "<tr><td valign='top'><a href='javascript:toggleNwFiles(\"{$newI}\");'><img border='0' src='".SugarThemeRegistry::current()->getImageURL('Workflow.gif')."></a></td>\n";
3154 $out .= "<td valign='top'><b><a href='javascript:toggleNwFiles(\"{$newI}\");'>".$fileName."</a></b></td></tr>";
3155 $recurse = testThis3($files, $newI, true, $previousPath);
3156 $out .= "<tr><td></td><td valign='top'>".$recurse."</td></tr>";
3159 $previousPath = $path;
3161 $display = ($hide) ? 'none' : '';
3163 <div id="{$id}" style="display:{$display}">
3164 <table cellpadding='1' cellspacing='0' border='0' style='border:1px solid #ccc'>
3173 function testThis4($filePath, $fileNodes=array(), $fileName='') {
3174 $path = dirname($filePath);
3175 $file = basename($filePath);
3177 $exFile = explode('/', $path);
3179 foreach($exFile as $pathSegment) {
3180 if(is_array($fileNodes[$pathSegment])) { // path already processed
3182 } else { // newly found path
3183 $fileNodes[$pathSegment] = array();
3186 if($fileName != '') {
3187 $fileNodes[$pathSegment][] = $fileName;
3196 ///////////////////////////////////////////////////////////////////////////////
3197 //// SYSTEM CHECK FUNCTIONS
3199 * generates an array with all files in the SugarCRM root directory, skipping
3201 * @return array files Array of files with absolute paths
3203 function getFilesForPermsCheck() {
3204 global $sugar_config;
3206 logThis('Got JSON call to find all files...');
3207 $filesNotWritable = array();
3208 $filesNWPerms = array();
3210 // add directories here that should be skipped when doing file permissions checks (cache/upload is the nasty one)
3212 $sugar_config['upload_dir'],
3214 $files = uwFindAllFiles(getcwd(), array(), true, $skipDirs, true);
3219 * checks files for permissions
3220 * @param array files Array of files with absolute paths
3221 * @return string result of check
3223 function checkFiles($files, $echo=false) {
3224 global $mod_strings;
3225 $filesNotWritable = array();
3228 <a href='javascript:void(0); toggleNwFiles(\"filesNw\");'>{$mod_strings['LBL_UW_SHOW_NW_FILES']}</a>
3229 <div id='filesNw' style='display:none;'>
3230 <table cellpadding='3' cellspacing='0' border='0'>
3232 <th align='left'>{$mod_strings['LBL_UW_FILE']}</th>
3233 <th align='left'>{$mod_strings['LBL_UW_FILE_PERMS']}</th>
3234 <th align='left'>{$mod_strings['LBL_UW_FILE_OWNER']}</th>
3235 <th align='left'>{$mod_strings['LBL_UW_FILE_GROUP']}</th>
3238 $isWindows = is_windows();
3239 foreach($files as $file) {
3242 if(!is_writable_windows($file)) {
3243 logThis('WINDOWS: File ['.$file.'] not readable - saving for display');
3244 // don't warn yet - we're going to use this to check against replacement files
3245 // aw: commented out; it's a hack to allow upgrade wizard to continue on windows... will fix later
3246 /*$filesNotWritable[$i] = $file;
3247 $filesNWPerms[$i] = substr(sprintf('%o',fileperms($file)), -4);
3248 $filesOut .= "<tr>".
3249 "<td><span class='error'>{$file}</span></td>".
3250 "<td>{$filesNWPerms[$i]}</td>".
3251 "<td>".$mod_strings['ERR_UW_CANNOT_DETERMINE_USER']."</td>".
3252 "<td>".$mod_strings['ERR_UW_CANNOT_DETERMINE_GROUP']."</td>".
3256 if(!is_writable($file)) {
3257 logThis('File ['.$file.'] not writable - saving for display');
3258 // don't warn yet - we're going to use this to check against replacement files
3259 $filesNotWritable[$i] = $file;
3260 $filesNWPerms[$i] = substr(sprintf('%o',fileperms($file)), -4);
3261 $owner = posix_getpwuid(fileowner($file));
3262 $group = posix_getgrgid(filegroup($file));
3263 $filesOut .= "<tr>".
3264 "<td><span class='error'>{$file}</span></td>".
3265 "<td>{$filesNWPerms[$i]}</td>".
3266 "<td>".$owner['name']."</td>".
3267 "<td>".$group['name']."</td>".
3274 $filesOut .= '</table></div>';
3276 $errors['files']['filesNotWritable'] = (count($filesNotWritable) > 0) ? true : false;
3277 if(count($filesNotWritable) < 1) {
3278 $filesOut = "{$mod_strings['LBL_UW_FILE_NO_ERRORS']}";
3284 function deletePackageOnCancel(){
3285 global $mod_strings;
3286 global $sugar_config;
3287 logThis('running delete');
3288 if(!isset($_SESSION['install_file']) || ($_SESSION['install_file'] == "")) {
3289 logThis('ERROR: trying to delete non-existent file: ['.$_REQUEST['install_file'].']');
3290 $error = $mod_strings['ERR_UW_NO_FILE_UPLOADED'];
3292 // delete file in upgrades/patch
3293 $delete_me = urldecode( $_SESSION['install_file'] );
3294 if(@unlink($delete_me)) {
3295 logThis('unlinking: '.$delete_me);
3296 $out = basename($delete_me).$mod_strings['LBL_UW_FILE_DELETED'];
3298 logThis('ERROR: could not delete ['.$delete_me.']');
3299 $error = $mod_strings['ERR_UW_FILE_NOT_DELETED'].$delete_me;
3302 // delete file in cache/upload
3303 $fileS = explode('/', $delete_me);
3305 $fileName = (isset($fileS[$c-1]) && !empty($fileS[$c-1])) ? $fileS[$c-1] : $fileS[$c-2];
3306 $deleteUpload = getcwd().'/'.$sugar_config['upload_dir'].$fileName;
3307 logThis('Trying to delete '.$deleteUpload);
3308 if(!@unlink($deleteUpload)) {
3309 logThis('ERROR: could not delete: ['.$deleteUpload.']');
3310 $error = $mod_strings['ERR_UW_FILE_NOT_DELETED'].$sugar_config['upload_dir'].$fileName;
3312 if(!empty($error)) {
3313 $out = "<b><span class='error'>{$error}</span></b><br />";
3318 function parseAndExecuteSqlFile($sqlScript,$forStepQuery='',$resumeFromQuery=''){
3319 global $sugar_config;
3320 $alterTableSchema = '';
3321 $sqlErrors = array();
3322 if(!isset($_SESSION['sqlSkippedQueries'])){
3323 $_SESSION['sqlSkippedQueries'] = array();
3325 $db = & DBManagerFactory::getInstance();
3327 if($sugar_config['dbconfig']['db_type'] == 'mysql') {
3330 if($sugar_config['dbconfig']['db_type'] == 'oci8'){
3331 $db->query("CREATE OR REPLACE FUNCTION blob_to_clob (blob_in IN BLOB)
3335 v_varchar VARCHAR2(32767);
3336 v_start PLS_INTEGER := 1;
3337 v_buffer PLS_INTEGER := 32767;
3339 DBMS_LOB.CREATETEMPORARY(v_clob, TRUE);
3341 FOR i IN 1..CEIL(DBMS_LOB.GETLENGTH(blob_in) / v_buffer)
3344 v_varchar := UTL_RAW.CAST_TO_VARCHAR2(DBMS_LOB.SUBSTR(blob_in, v_buffer, v_start));
3346 DBMS_LOB.WRITEAPPEND(v_clob, LENGTH(v_varchar), v_varchar);
3348 v_start := v_start + v_buffer;
3353 END blob_to_clob;");
3355 if(strpos($resumeFromQuery,",") != false){
3356 $resumeFromQuery = explode(",",$resumeFromQuery);
3357 if(is_array($resumeFromQuery)){
3358 //print_r('RES ARRAY '.$resumeFromQuery[0].'</br>');
3361 if(file_exists($sqlScript)) {
3362 $fp = fopen($sqlScript, 'r');
3363 $contents = fread($fp, filesize($sqlScript));
3364 $anyScriptChanges =$contents;
3365 $resumeAfterFound = false;
3369 while($line = fgets($fp)) {
3370 if(strpos($line, '--') === false) {
3371 $completeLine .= " ".trim($line);
3372 if(strpos($line, ';') !== false) {
3374 $query = str_replace(';','',$completeLine);
3375 //if resume from query is not null then find out from where
3376 //it should start executing the query.
3378 if($query != null && $resumeFromQuery != null){
3379 if(!$resumeAfterFound){
3380 if(strpos($query,",") != false){
3381 $queArray = array();
3382 $queArray = explode(",",$query);
3383 for($i=0;$i<sizeof($resumeFromQuery);$i++){
3384 if(strcmp(strtolower(trim($resumeFromQuery[$i])),strtolower(trim($queArray[$i])))==0){
3385 //echo 'mat found '.$queArray[$i].'</br>';
3386 $resumeAfterFound = true;
3389 $resumeAfterFound = false;
3395 elseif(strcmp(strtolower(trim($resumeFromQuery)),strtolower(trim($query)))==0){
3396 $resumeAfterFound = true;
3399 if($resumeAfterFound){
3402 // if $count=1 means it is just found so skip the query. Run the next one
3403 if($query != null && $resumeAfterFound && $count >1){
3407 $tableName = getAlterTable($query);
3408 if(!empty($tableName))
3410 $db->query('ALTER TABLE '.$tableName.' DISABLE KEYS');
3414 if($db->checkError()){
3415 //put in the array to use later on
3416 $_SESSION['sqlSkippedQueries'][] = $query;
3418 if(!empty($tableName))
3420 $db->query('ALTER TABLE '.$tableName.' ENABLE KEYS');
3422 $progQuery[$forStepQuery]=$query;
3423 post_install_progress($progQuery,$action='set');
3426 elseif($query != null){
3430 $tableName = getAlterTable($query);
3431 if(!empty($tableName))
3433 $db->query('ALTER TABLE '.$tableName.' DISABLE KEYS');
3437 if(!empty($tableName))
3439 $db->query('ALTER TABLE '.$tableName.' ENABLE KEYS');
3441 $progQuery[$forStepQuery]=$query;
3442 post_install_progress($progQuery,$action='set');
3443 if($db->checkError()){
3444 //put in the array to use later on
3445 $_SESSION['sqlSkippedQueries'][] = $query;
3456 function getAlterTable($query){
3457 $query = strtolower($query);
3458 if (preg_match("/^\s*alter\s+table\s+/", $query)) {
3459 $sqlArray = explode(" ", $query);
3460 $key = array_search('table', $sqlArray);
3461 return $sqlArray[($key+1)];
3467 function set_upgrade_vars(){
3468 logThis('setting session variables...');
3469 $upgrade_progress_dir = getcwd().'/'.$GLOBALS['sugar_config']['upload_dir'].'upgrades/temp';
3470 if(!is_dir($upgrade_progress_dir)){
3471 mkdir_recursive($upgrade_progress_dir);
3473 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3474 if(file_exists($upgrade_progress_file)){
3475 include($upgrade_progress_file);
3478 fopen($upgrade_progress_file, 'w+');
3480 if(!isset($upgrade_config) || $upgrade_config == null){
3481 $upgrade_config = array();
3482 $upgrade_config[1]['upgrade_vars']=array();
3484 if(isset($upgrade_config[1]) && isset($upgrade_config[1]['upgrade_vars']) && !is_array($upgrade_config[1]['upgrade_vars'])){
3485 $upgrade_config[1]['upgrade_vars'] = array();
3488 if(!isset($upgrade_vars) || $upgrade_vars == NULL){
3489 $upgrade_vars = array();
3491 if(isset($_SESSION['unzip_dir']) && !empty($_SESSION['unzip_dir']) && file_exists($_SESSION['unzip_dir'])){
3492 $upgrade_vars['unzip_dir']=$_SESSION['unzip_dir'];
3494 if(isset($_SESSION['install_file']) && !empty($_SESSION['install_file']) && file_exists($_SESSION['install_file'])){
3495 $upgrade_vars['install_file']=$_SESSION['install_file'];
3497 if(isset($_SESSION['Upgraded451Wizard']) && !empty($_SESSION['Upgraded451Wizard'])){
3498 $upgrade_vars['Upgraded451Wizard']=$_SESSION['Upgraded451Wizard'];
3500 if(isset($_SESSION['license_shown']) && !empty($_SESSION['license_shown'])){
3501 $upgrade_vars['license_shown']=$_SESSION['license_shown'];
3503 if(isset($_SESSION['Initial_451to500_Step']) && !empty($_SESSION['Initial_451to500_Step'])){
3504 $upgrade_vars['Initial_451to500_Step']=$_SESSION['Initial_451to500_Step'];
3506 if(isset($_SESSION['zip_from_dir']) && !empty($_SESSION['zip_from_dir'])){
3507 $upgrade_vars['zip_from_dir']=$_SESSION['zip_from_dir'];
3509 //place into the upgrade_config array and rewrite config array only if new values are being inserted
3510 if(isset($upgrade_vars) && $upgrade_vars != null && sizeof($upgrade_vars) > 0){
3511 foreach($upgrade_vars as $key=>$val){
3512 if($key != null && $val != null){
3513 $upgrade_config[1]['upgrade_vars'][$key]=$upgrade_vars[$key];
3516 ksort($upgrade_config);
3517 if(is_writable($upgrade_progress_file) && write_array_to_file( "upgrade_config", $upgrade_config,
3518 $upgrade_progress_file)) {
3519 //writing to the file
3524 function initialize_session_vars(){
3525 $upgrade_progress_dir = getcwd().'/'.$GLOBALS['sugar_config']['upload_dir'].'upgrades/temp';
3526 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3527 if(file_exists($upgrade_progress_file)){
3528 include($upgrade_progress_file);
3529 if(isset($upgrade_config) && $upgrade_config != null && is_array($upgrade_config) && sizeof($upgrade_config) >0){
3530 $currVarsArray=$upgrade_config[1]['upgrade_vars'];
3531 //print_r($currVarsArray);
3532 if(isset($currVarsArray) && $currVarsArray != null && is_array($currVarsArray) && sizeof($currVarsArray)>0){
3533 foreach($currVarsArray as $key=>$val){
3534 if($key != null && $val !=null){
3535 //set session variables
3536 $_SESSION[$key]=$val;
3545 //track the upgrade progress on each step
3546 //track the upgrade progress on each step
3547 function set_upgrade_progress($currStep,$currState,$currStepSub='',$currStepSubState=''){
3549 $upgrade_progress_dir = getcwd().'/'.$GLOBALS['sugar_config']['upload_dir'].'upgrades/temp';
3550 if(!is_dir($upgrade_progress_dir)){
3551 mkdir_recursive($upgrade_progress_dir);
3553 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3554 if(file_exists($upgrade_progress_file)){
3555 include($upgrade_progress_file);
3558 if(function_exists('sugar_fopen')){
3559 sugar_fopen($upgrade_progress_file, 'w+');
3562 fopen($upgrade_progress_file, 'w+');
3565 if(!isset($upgrade_config) || $upgrade_config == null){
3566 $upgrade_config = array();
3567 $upgrade_config[1]['upgrade_vars']=array();
3569 if(!is_array($upgrade_config[1]['upgrade_vars'])){
3570 $upgrade_config[1]['upgrade_vars'] = array();
3572 if($currStep != null && $currState != null){
3573 if(sizeof($upgrade_config) > 0){
3574 if($currStepSub != null && $currStepSubState !=null){
3575 //check if new status to be set or update
3576 //get the latest in array. since it has sub components prepare an array
3577 if(!empty($upgrade_config[sizeof($upgrade_config)][$currStep]) && is_array($upgrade_config[sizeof($upgrade_config)][$currStep])){
3578 $latestStepSub = currSubStep($upgrade_config[sizeof($upgrade_config)][$currStep]);
3579 if($latestStepSub == $currStepSub){
3580 $upgrade_config[sizeof($upgrade_config)][$currStep][$latestStepSub]=$currStepSubState;
3581 $upgrade_config[sizeof($upgrade_config)][$currStep][$currStep] = $currState;
3584 $upgrade_config[sizeof($upgrade_config)][$currStep][$currStepSub]=$currStepSubState;
3585 $upgrade_config[sizeof($upgrade_config)][$currStep][$currStep] = $currState;
3589 $currArray = array();
3590 $currArray[$currStep] = $currState;
3591 $currArray[$currStepSub] = $currStepSubState;
3592 $upgrade_config[sizeof($upgrade_config)+1][$currStep] = $currArray;
3596 //get the current upgrade progress
3597 $latestStep = get_upgrade_progress();
3598 //set the upgrade progress
3599 //echo 'latest '.$latestStep;
3600 if($latestStep == $currStep){
3601 //update the current step with new progress status
3603 $upgrade_config[sizeof($upgrade_config)][$latestStep]=$currState;
3608 $upgrade_config[sizeof($upgrade_config)+1][$currStep]=$currState;
3610 // now check if there elements within array substeps
3614 //set the upgrade progress (just starting)
3615 $upgrade_config[sizeof($upgrade_config)+1][$currStep]= $currState;
3618 if(is_writable($upgrade_progress_file) && write_array_to_file( "upgrade_config", $upgrade_config,
3619 $upgrade_progress_file)) {
3620 //writing to the file
3626 function get_upgrade_progress(){
3627 $upgrade_progress_dir = getcwd().'/'.$GLOBALS['sugar_config']['upload_dir'].'upgrades/temp';
3628 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3630 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3632 if(file_exists($upgrade_progress_file)){
3633 include($upgrade_progress_file);
3634 //echo 'upconf '.$upgrade_config;
3635 if(!isset($upgrade_config) || $upgrade_config == null){
3636 $upgrade_config = array();
3638 if($upgrade_config != null && sizeof($upgrade_config) >1){
3639 $currArr = $upgrade_config[sizeof($upgrade_config)];
3640 //echo 'size of '.sizeof($upgrade_config);
3641 if(is_array($currArr)){
3642 foreach($currArr as $key=>$val){
3650 function currSubStep($currStep){
3652 if(is_array($currStep)){
3653 foreach($currStep as $key=>$val){
3661 function currUpgradeState($currState){
3663 if(is_array($currState)){
3664 foreach($currState as $key=>$val){
3666 foreach($val as $k=>$v){
3680 function didThisStepRunBefore($step,$SubStep=''){
3681 if($step == null) return;
3682 $upgrade_progress_dir = getcwd().'/'.$GLOBALS['sugar_config']['upload_dir'].'upgrades/temp';
3683 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3685 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3687 if(file_exists($upgrade_progress_file)){
3688 include($upgrade_progress_file);
3689 if(isset($upgrade_config) && $upgrade_config != null && is_array($upgrade_config) && sizeof($upgrade_config) >0){
3690 for($i=1;$i<=sizeof($upgrade_config);$i++){
3691 if(is_array($upgrade_config[$i])){
3692 foreach($upgrade_config[$i] as $key=>$val){
3694 if(is_array($upgrade_config[$i][$step])){
3696 foreach ($upgrade_config[$i][$step] as $k=>$v){
3698 foreach($v as $k1=>$v1){
3699 if($SubStep != null){
3700 if($SubStep ==$k1 && $v1=='done'){
3701 //echo 'Found Inside '.$k1;
3708 elseif($SubStep !=null){
3709 if($SubStep==$k && $v=='done'){
3710 //echo 'Found1 '.$k;
3715 elseif($step==$k && $v=='done'){
3716 //echo 'Found2 '.$k;
3722 elseif($val=='done'){
3723 //echo 'Foundmmmm '.$key;
3737 //get and set post install status
3738 function post_install_progress($progArray='',$action=''){
3739 if($action=='' || $action=='get'){
3740 //get the state of post install
3741 $upgrade_progress_dir = getcwd().'/'.$GLOBALS['sugar_config']['upload_dir'].'upgrades/temp';
3742 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3743 $currProg = array();
3744 if(file_exists($upgrade_progress_file)){
3745 include($upgrade_progress_file);
3746 if(is_array($upgrade_config[sizeof($upgrade_config)]['commit']['post_install']) && sizeof($upgrade_config[sizeof($upgrade_config)]['commit']['post_install'])>0){
3747 foreach($upgrade_config[sizeof($upgrade_config)]['commit']['post_install'] as $k=>$v){
3754 elseif($action=='set'){
3755 $upgrade_progress_dir = getcwd().'/'.$GLOBALS['sugar_config']['upload_dir'].'upgrades/temp';
3756 if(!is_dir($upgrade_progress_dir)){
3757 mkdir($upgrade_progress_dir);
3759 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3760 if(file_exists($upgrade_progress_file)){
3761 include($upgrade_progress_file);
3764 fopen($upgrade_progress_file, 'w+');
3766 if(!is_array($upgrade_config[sizeof($upgrade_config)]['commit']['post_install'])){
3767 $upgrade_config[sizeof($upgrade_config)]['commit']['post_install']=array();
3768 $upgrade_config[sizeof($upgrade_config)]['commit']['post_install']['post_install'] = 'in_progress';
3770 if($progArray != null && is_array($progArray)){
3771 foreach($progArray as $key=>$val){
3772 $upgrade_config[sizeof($upgrade_config)]['commit']['post_install'][$key]=$val;
3775 if(is_writable($upgrade_progress_file) && write_array_to_file( "upgrade_config", $upgrade_config,
3776 $upgrade_progress_file)) {
3777 //writing to the file
3783 // parse and run sql file
3784 function parseAndExecuteSqlFileExtended($sqlScript){
3785 global $sugar_config;
3786 $alterTableSchema = '';
3787 $db = & DBManagerFactory::getInstance();
3788 if(is_file($sqlScript)) {
3789 $fp = fopen($sqlScript, 'r');
3790 $contents = fread($fp, filesize($sqlScript));
3791 $anyScriptChanges =$contents;
3795 while($line = fgets($fp)) {
3796 if(strpos($line, '--') === false) {
3797 $completeLine .= " ".trim($line);
3798 if(strpos($line, ';') !== false) {
3799 $completeLine = str_replace(';','',$completeLine);
3800 $currLine = explode(",",$completeLine);
3801 //check if multiple statements are clubbed
3802 if(sizeof($currLine) >1){
3803 $qarr = explode(" ",trim($currLine[0]));
3804 if(strtoupper(trim($qarr[0])) == 'CREATE' && strtoupper(trim($qarr[1])) == 'TABLE'){
3805 if(strtoupper(trim($qarr[2]) != null)){
3806 if($sugar_config['dbconfig']['db_type'] == 'oci8'){
3807 $query= "select table_name from user_tables where table_name=strtoupper(trim($qarr[2]))";
3808 $result = $db->query($query);
3809 $row = $db->fetchByAssociation($result);
3810 if($row['table_name'] != null){
3815 $query= $completeLine;
3824 $qType =trim($qarr[0])." ".trim($qarr[1])." ".trim($qarr[2]);
3825 echo trim($currLine[0])."<br />";
3826 for ($i = 1; $i <= sizeof($currLine)-1; $i++) {
3827 $query = $qType." ".trim($currLine[$i]);
3828 echo $query."<br />";
3834 echo trim($currLine[0]);
3838 //$q3 = $completeLine;
3839 //''$r3 = $GLOBALS['db']->query($q3, false, "Preflight Failed for:");
3840 //echo mysql_error();
3848 //$sqlErrors[] = $mod_strings['ERR_UW_FILE_NOT_READABLE'].'::'.$sqlScript;
3852 function createTable(){
3853 if($sugar_config['dbconfig']['db_type'] == 'oci8'){
3854 $query= "select table_name from user_tables where table_name=strtoupper(trim($qarr[2]))";
3855 $result = $db->query($query);
3856 $row = $db->fetchByAssociation($result);
3857 if($row['table_name'] != null){
3862 $query= $completeLine;
3869 function repairDBForUpgrade($execute=false,$path=''){
3871 global $current_user, $beanFiles;
3873 set_time_limit(3600);
3875 $db = &DBManagerFactory::getInstance();
3877 VardefManager::clearVardef();
3878 require_once('include/ListView/ListView.php');
3879 foreach ($beanFiles as $bean => $file) {
3880 require_once ($file);
3881 $focus = new $bean ();
3882 $sql .= $db->repairTable($focus, $execute);
3886 $olddictionary = $dictionary;
3887 unset ($dictionary);
3888 include ('modules/TableDictionary.php');
3889 foreach ($dictionary as $meta) {
3890 $tablename = $meta['table'];
3891 $fielddefs = $meta['fields'];
3892 $indices = $meta['indices'];
3893 $sql .= $db->repairTableParams($tablename, $fielddefs, $indices, $execute);
3896 foreach (explode("\n", $sql) as $line) {
3897 if (!empty ($line) && substr($line, -2) != "*/") {
3900 $qry_str .= $line . "\n";
3911 preg_replace('#(/\*.+?\*/\n*)#', '', $qry_str)
3913 logThis("*******START EXECUTING DB UPGRADE QUERIES***************",$path);
3914 logThis($sql,$path);
3915 logThis("*******END EXECUTING DB UPGRADE QUERIES****************",$path);
3924 * upgradeUserPreferences
3925 * This method updates the user_preferences table and sets the pages/dashlets for users
3926 * which have ACL access to Trackers so that the Tracker dashlets are set in their user perferences
3929 function upgradeUserPreferences() {
3934 function add_custom_modules_favorites_search(){
3935 $module_directories = scandir('modules');
3937 foreach($module_directories as $module_dir){
3938 if($module_dir == '.' || $module_dir == '..' || !is_dir("modules/{$module_dir}")){
3943 preg_match('/^[a-z0-9]{1,5}_[a-z0-9]+$/i' , $module_dir, $matches);
3945 // Make sure the module was created by module builder
3946 if(empty($matches)){
3950 $full_module_dir = "modules/{$module_dir}/";
3951 $read_searchdefs_from = "{$full_module_dir}/metadata/searchdefs.php";
3952 $read_SearchFields_from = "{$full_module_dir}/metadata/SearchFields.php";
3953 $read_custom_SearchFields_from = "custom/{$full_module_dir}/metadata/SearchFields.php";
3955 // Studio can possibly override this file, so we check for a custom version of it
3956 if(file_exists("custom/{$full_module_dir}/metadata/searchdefs.php")){
3957 $read_searchdefs_from = "custom/{$full_module_dir}/metadata/searchdefs.php";
3960 if(file_exists($read_searchdefs_from) && file_exists($read_SearchFields_from)){
3963 require($read_searchdefs_from);
3964 foreach($searchdefs[$module_dir]['layout']['basic_search'] as $sf_array){
3965 if(isset($sf_array['name']) && $sf_array['name'] == 'favorites_only'){
3970 require($read_SearchFields_from);
3971 if(isset($searchFields[$module_dir]['favorites_only'])){
3975 if(!$found_sf1 && !$found_sf2){
3976 $searchdefs[$module_dir]['layout']['basic_search']['favorites_only'] = array('name' => 'favorites_only','label' => 'LBL_FAVORITES_FILTER','type' => 'bool',);
3977 $searchdefs[$module_dir]['layout']['advanced_search']['favorites_only'] = array('name' => 'favorites_only','label' => 'LBL_FAVORITES_FILTER','type' => 'bool',);
3978 $searchFields[$module_dir]['favorites_only'] = array(
3979 'query_type'=>'format',
3980 'operator' => 'subquery',
3981 'subquery' => 'SELECT sugarfavorites.record_id FROM sugarfavorites
3982 WHERE sugarfavorites.deleted=0
3983 and sugarfavorites.module = \''.$module_dir.'\'
3984 and sugarfavorites.assigned_user_id = \'{0}\'',
3985 'db_field'=>array('id')
3988 if(!is_dir("custom/{$full_module_dir}/metadata")){
3989 mkdir_recursive("custom/{$full_module_dir}/metadata");
3991 $success_sf1 = write_array_to_file('searchdefs', $searchdefs, "custom/{$full_module_dir}/metadata/searchdefs.php");
3992 $success_sf2 = write_array_to_file('searchFields', $searchFields, "{$full_module_dir}/metadata/SearchFields.php");
3995 logThis("add_custom_modules_favorites_search failed for searchdefs.php for {$module_dir}");
3998 logThis("add_custom_modules_favorites_search failed for SearchFields.php for {$module_dir}");
4000 if($success_sf1 && $success_sf2){
4001 logThis("add_custom_modules_favorites_search successfully updated searchdefs and searchFields for {$module_dir}");
4010 * upgradeModulesForTeamsets
4012 * This method adds the team_set_id values to the module tables that have the new team_set_id column
4013 * added through the SugarCRM 5.5.x upgrade process. It also adds the values into the team_sets and
4014 * team_sets_teams tables.
4016 * @param filter Array of modules to process; empty by default
4018 function upgradeModulesForTeamsets($filter=array()) {
4019 require('include/modules.php');
4020 foreach($beanList as $moduleName=>$beanName) {
4021 if(!empty($filter) && array_search($moduleName, $filter) === false) {
4024 if($moduleName == 'TeamMemberships' || $moduleName == 'ForecastOpportunities'){
4027 $bean = loadBean($moduleName);
4029 empty($bean->table_name)) {
4033 $FieldArray = $GLOBALS['db']->helper->get_columns($bean->table_name);
4034 if(!isset($FieldArray['team_id'])) {
4038 upgradeTeamColumn($bean, 'team_id');
4042 //Upgrade users table
4043 $bean = loadBean('Users');
4044 upgradeTeamColumn($bean, 'default_team');
4045 $result = $GLOBALS['db']->query("SELECT id FROM teams where deleted=0");
4046 while($row = $GLOBALS['db']->fetchByAssoc($result)) {
4047 $teamset = new TeamSet();
4048 $teamset->addTeams($row['id']);
4055 * Helper function to create a team_set_id column and also set team_set_id column
4056 * to have the value of the $column_name parameter
4058 * @param $bean SugarBean which we are adding team_set_id column to
4059 * @param $column_name The name of the column containing the default team_set_id value
4061 function upgradeTeamColumn($bean, $column_name) {
4062 //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
4063 //module that does not use the SugarObjects
4064 if(empty($bean->field_defs['team_set_id']) && $bean->module_dir != 'Trackers'){
4066 //at this point we could assume that since we have a team_id defined and not a team_set_id that we need to
4067 //add that field and the corresponding relationships
4068 $object = $bean->object_name;
4069 $module = $bean->module_dir;
4070 $object_name = $object;
4071 $_object_name = strtolower($object_name);
4073 if(!empty($GLOBALS['dictionary'][$object]['table'])){
4074 $table_name = $GLOBALS['dictionary'][$object]['table'];
4076 $table_name = strtolower($module);
4079 $path = 'include/SugarObjects/implements/team_security/vardefs.php';
4081 //go through each entry in the vardefs from team_security and unset anything that is already set in the core module
4082 //this will ensure we have the proper ordering.
4083 $fieldDiff = array_diff_assoc($vardefs['fields'], $GLOBALS['dictionary'][$bean->object_name]['fields']);
4085 $file = 'custom/Extension/modules/' . $bean->module_dir. '/Ext/Vardefs/teams.php';
4086 $contents = "<?php\n";
4087 if(!empty($fieldDiff)){
4088 foreach($fieldDiff as $key => $val){
4089 $contents .= "\n\$GLOBALS['dictionary']['". $object . "']['fields']['". $key . "']=" . var_export_helper($val) . ";";
4092 $relationshipDiff = array_diff_assoc($vardefs['relationships'], $GLOBALS['dictionary'][$bean->object_name]['relationships']);
4093 if(!empty($relationshipDiff)){
4094 foreach($relationshipDiff as $key => $val){
4095 $contents .= "\n\$GLOBALS['dictionary']['". $object . "']['relationships']['". $key . "']=" . var_export_helper($val) . ";";
4098 $indexDiff = array_diff_assoc($vardefs['indices'], $GLOBALS['dictionary'][$bean->object_name]['indices']);
4099 if(!empty($indexDiff)){
4100 foreach($indexDiff as $key => $val){
4101 $contents .= "\n\$GLOBALS['dictionary']['". $object . "']['indices']['". $key . "']=" . var_export_helper($val) . ";";
4104 if( $fh = @sugar_fopen( $file, 'wt' ) )
4106 fputs( $fh, $contents);
4111 //we have written out the teams.php into custom/Extension/modules/{$module_dir}/Ext/Vardefs/teams.php'
4112 //now let's merge back into vardefs.ext.php
4113 require_once('ModuleInstall/ModuleInstaller.php');
4114 $mi = new ModuleInstaller();
4115 $mi->merge_files('Ext/Vardefs/', 'vardefs.ext.php');
4116 VardefManager::loadVardef($bean->module_dir, $bean->object_name, true);
4117 $bean->field_defs = $GLOBALS['dictionary'][$bean->object_name]['fields'];
4120 if(isset($bean->field_defs['team_set_id'])) {
4121 //Create the team_set_id column
4122 $FieldArray = $GLOBALS['db']->helper->get_columns($bean->table_name);
4123 if(!isset($FieldArray['team_set_id'])) {
4124 $GLOBALS['db']->addColumn($bean->table_name, $bean->field_defs['team_set_id']);
4126 $indexArray = $GLOBALS['db']->helper->get_indices($bean->table_name);
4129 'name' => 'idx_'.strtolower($bean->table_name).'_tmst_id',
4131 'fields' => array('team_set_id')
4134 if(!isset($indexArray['idx_'.strtolower($bean->table_name).'_tmst_id'])) {
4135 $GLOBALS['db']->addIndexes($bean->table_name, $indexDef);
4138 //Update the table's team_set_id column to have the same values as team_id
4139 $GLOBALS['db']->query("UPDATE {$bean->table_name} SET team_set_id = {$column_name}");
4144 * Update the folder subscription table which confirms to the team security mechanism but
4145 * the class SugarFolders does not extend SugarBean and is therefore never picked up by the
4146 * upgradeModulesForTeamsets function.
4148 function upgradeFolderSubscriptionsTeamSetId()
4150 logThis("In upgradeFolderSubscriptionsTeamSetId()");
4151 $query = "UPDATE folders SET team_set_id = team_id";
4152 $result = $GLOBALS['db']->query($query);
4153 logThis("Finished upgradeFolderSubscriptionsTeamSetId()");
4157 * upgradeModulesForTeam
4159 * This method update the associated_user_id, name, name_2 to the private team records on teams table
4160 * This function is used for upgrade process from 5.1.x and 5.2.x.
4163 function upgradeModulesForTeam() {
4164 logThis("In upgradeModulesForTeam()");
4165 $result = $GLOBALS['db']->query("SELECT id, user_name, first_name, last_name FROM users where deleted=0");
4167 while($row = $GLOBALS['db']->fetchByAssoc($result)) {
4168 $results2 = $GLOBALS['db']->query("SELECT id FROM teams WHERE name = '({$row['user_name']})'");
4170 if(!$assoc = $GLOBALS['db']->fetchByAssoc($results2)) {
4171 //if team does not exist, then lets create the team for this user
4174 $user->retrieve($row['id']);
4175 $team->new_user_created($user);
4176 $team_id = $team->id;
4178 $team_id =$assoc['id'];
4182 $name = is_null($row['first_name'])?'':$row['first_name'];
4183 $name_2 = is_null($row['last_name'])?'':$row['last_name'];
4184 $associated_user_id = $row['id'];
4187 //Ensure team->name is not empty by using team->name_2 if available
4188 if(empty($name) && !empty($name_2)) {
4193 $query = "UPDATE teams SET name = '{$name}', name_2 = '{$name_2}', associated_user_id = '{$associated_user_id}' WHERE id = '{$team_id}'";
4194 $GLOBALS['db']->query($query);
4197 //Update the team_set_id and default_team columns
4198 $ce_to_pro_or_ent = (isset($_SESSION['upgrade_from_flavor']) && ($_SESSION['upgrade_from_flavor'] == 'SugarCE to SugarPro' || $_SESSION['upgrade_from_flavor'] == 'SugarCE to SugarEnt'));
4200 //Update team_set_id
4201 if((isset($_SESSION['current_db_version']) && $_SESSION['current_db_version'] < '550') || $ce_to_pro_or_ent) {
4202 $GLOBALS['db']->query("update users set team_set_id = (select teams.id from teams where teams.associated_user_id = users.id)");
4205 //Update default_team
4206 if($ce_to_pro_or_ent) {
4207 $GLOBALS['db']->query("update users set default_team = (select teams.id from teams where teams.associated_user_id = users.id)");
4213 function addNewSystemTabsFromUpgrade($from_dir){
4215 if(isset($_SESSION['upgrade_from_flavor'])){
4217 //check to see if there are any new files that need to be added to systems tab
4218 //retrieve old modules list
4219 logThis('check to see if new modules exist',$path);
4220 $oldModuleList = array();
4221 $newModuleList = array();
4222 include($from_dir.'/include/modules.php');
4223 $oldModuleList = $moduleList;
4224 include('include/modules.php');
4225 $newModuleList = $moduleList;
4227 //include tab controller
4228 require_once('modules/MySettings/TabController.php');
4229 $newTB = new TabController();
4231 //make sure new modules list has a key we can reference directly
4232 $newModuleList = $newTB->get_key_array($newModuleList);
4233 $oldModuleList = $newTB->get_key_array($oldModuleList);
4235 //iterate through list and remove commonalities to get new modules
4236 foreach ($newModuleList as $remove_mod){
4237 if(in_array($remove_mod, $oldModuleList)){
4238 unset($newModuleList[$remove_mod]);
4241 //new modules list now has left over modules which are new to this install, so lets add them to the system tabs
4242 logThis('new modules to add are '.var_export($newModuleList,true),$path);
4244 //grab the existing system tabs
4245 $tabs = $newTB->get_system_tabs();
4247 //add the new tabs to the array
4248 foreach($newModuleList as $nm ){
4252 if(!file_exists('modules/iFrames/iFrame.php') && isset($tabs['iFrames'])){
4253 unset($tabs['iFrames']);
4256 //Set the default order
4257 $default_order = array(
4259 'Accounts'=>'Accounts',
4260 'Contacts'=>'Contacts',
4261 'Opportunities'=>'Opportunities',
4262 'Activities'=>'Activities',
4263 'Documents'=>'Documents'
4265 $tabs = array_merge($default_order, $tabs);
4267 //now assign the modules to system tabs
4268 $newTB->set_system_tabs($tabs);
4269 logThis('module tabs updated',$path);
4276 * This method attempts to fix dropdown lists that were incorrectly named.
4277 * There were versions of SugarCRM that did not enforce naming convention rules
4278 * for the dropdown list field name. This method attempts to resolve that by
4279 * fixing the language files that may have been affected and then updating the
4280 * fields_meta_data table accordingly. It also refreshes any vardefs that may
4281 * have been affected.
4284 function fix_dropdown_list() {
4285 if(file_exists('custom/include/language')) {
4287 $affected_modules = array();
4288 $affected_keys = array();
4290 getFiles($files, 'custom/include/language', '/\.php$/i');
4291 foreach($files as $file) {
4293 if(file_exists($file . '.bak')) {
4294 $bak_mod_time = filemtime($file . '.bak');
4295 $php_mod_time = filemtime($file);
4296 //We're saying if the .php file was modified 30 seconds no more than php.bak file then we
4297 //run these additional cleanup checks
4298 if($php_mod_time - $bak_mod_time < 30) {
4300 $app_list_strings = array();
4301 $GLOBALS['app_list_strings'] = array();
4302 require($file . '.bak');
4303 $bak_app_list_strings = array_merge($app_list_strings, $GLOBALS['app_list_strings']);
4305 $app_list_strings = array();
4306 $GLOBALS['app_list_strings'] = array();
4308 $php_app_list_strings = array_merge($app_list_strings, $GLOBALS['app_list_strings']);
4310 //Get the file contents
4311 $contents = file_get_contents($file);
4313 //Now simulate a fix for the file before we compare w/ the .php file
4314 //we also append to the $contents
4315 foreach($bak_app_list_strings as $key=>$entry) {
4316 if(preg_match('/([^A-Za-z_])/', $key, $matches) && is_array($entry)) {
4317 $new_key = preg_replace('/[^A-Za-z_]/', '_', $key);
4318 $bak_app_list_strings[$new_key] = $bak_app_list_strings[$key];
4319 unset($bak_app_list_strings[$key]);
4320 //Now if the entry doesn't exists in the .php file, then add to contents
4321 if(!isset($php_app_list_strings[$new_key])) {
4322 $contents .= "\n\$GLOBALS['app_list_strings']['{$new_key}'] = " . var_export_helper($bak_app_list_strings[$new_key]) . ";";
4327 //Now load the .php file to do the comparison
4328 foreach($php_app_list_strings as $key=>$entry) {
4329 if(isset($bak_app_list_strings[$key])) {
4330 $diff = array_diff($bak_app_list_strings[$key], $entry);
4332 //There is a difference, so copy the $bak_app_list_strings version into the .php file
4333 $contents .= "\n\$GLOBALS['app_list_strings']['{$key}'] = " . var_export_helper($bak_app_list_strings[$key]) . ";";
4338 //Now write out the file contents
4339 //Create backup just in case
4340 copy($file, $file . '.php_bak');
4341 $fp = @sugar_fopen($file, 'w');
4343 fwrite($fp, $contents);
4346 $GLOBALS['log']->error("Unable to update file contents in fix_dropdown_list for {$file}");
4351 unset($GLOBALS['app_strings']);
4352 unset($GLOBALS['app_list_strings']);
4353 $app_list_strings = array();
4356 $contents = file_get_contents($file);
4357 if ( !isset($GLOBALS['app_list_strings']) ) {
4358 $GLOBALS['app_list_strings'] = $app_list_strings;
4361 $GLOBALS['app_list_strings'] = array_merge($app_list_strings, $GLOBALS['app_list_strings']);
4363 if(isset($GLOBALS['app_list_strings']) && is_array($GLOBALS['app_list_strings'])) {
4364 foreach($GLOBALS['app_list_strings'] as $key=>$entry) {
4365 if(preg_match('/([^A-Za-z_])/', $key, $matches) && is_array($entry)) {
4366 $result = $GLOBALS['db']->query("SELECT custom_module FROM fields_meta_data WHERE ext1 = '{$key}'");
4367 if(!empty($result)) {
4368 while($row = $GLOBALS['db']->fetchByAssoc($result)) {
4369 $custom_module = $row['custom_module'];
4370 if(!empty($GLOBALS['beanList'][$custom_module])) {
4371 $affected_modules[$custom_module] = $GLOBALS['beanList'][$custom_module];
4376 //Replace all invalid characters with '_' character
4377 $new_key = preg_replace('/[^A-Za-z_]/', '_', $key);
4378 $affected_keys[$key] = $new_key;
4380 $GLOBALS['app_list_strings'][$new_key] = $GLOBALS['app_list_strings'][$key];
4381 unset($GLOBALS['app_list_strings'][$key]);
4383 $pattern_match = "/(\[\s*\'{$key}\'\s*\])/";
4384 $new_key = "['{$new_key}']";
4385 $out = preg_replace($pattern_match, $new_key, $contents);
4391 //This is a check for g => h instances where the file contents were incorrectly written
4392 //and also fixes the scenario where via a UI upgrade, the app_list_strings were incorrectly
4393 //merged with app_list_strings variables declared elsewhere
4395 if(preg_match('/\$GLOBALS\s*\[\s*[\"|\']app_list_strings[\"|\']\s*\]\s*=\s*array\s*\(/', $contents)) {
4396 //Now also remove all the non-custom labels that were added
4397 if(preg_match('/language\/([^\.]+)\.lang\.php$/', $file, $matches)) {
4398 $language = $matches[1];
4400 $app_list_strings = array();
4402 if(file_exists("include/language/$language.lang.php")) {
4403 include("include/language/$language.lang.php");
4405 if(file_exists("include/language/$language.lang.override.php")) {
4406 $app_list_strings = _mergeCustomAppListStrings("include/language/$language.lang.override.php" , $app_list_strings) ;
4408 if(file_exists("custom/application/Ext/Language/$language.ext.lang.php")) {
4409 $app_list_strings = _mergeCustomAppListStrings("custom/application/Ext/Language/$language.ext.lang.php" , $app_list_strings) ;
4411 if(file_exists("custom/application/Ext/Language/$language.lang.ext.php")) {
4412 $app_list_strings = _mergeCustomAppListStrings("custom/application/Ext/Language/$language.lang.ext.php" , $app_list_strings) ;
4415 $all_non_custom_include_language_strings = $app_strings;
4416 $all_non_custom_include_language_list_strings = $app_list_strings;
4418 $unset_keys = array();
4419 if(!empty($GLOBALS['app_list_strings'])) {
4420 foreach($GLOBALS['app_list_strings'] as $key=>$value) {
4422 if(isset($all_non_custom_include_language_list_strings[$key])) {
4423 $diff = array_diff($all_non_custom_include_language_list_strings[$key], $GLOBALS['app_list_strings'][$key]);
4426 if(!empty($all_non_custom_include_language_list_strings[$key]) && empty($diff)) {
4427 $unset_keys[] = $key;
4432 foreach($unset_keys as $key) {
4433 unset($GLOBALS['app_list_strings'][$key]);
4436 if(!empty($GLOBALS['app_strings'])) {
4437 foreach($GLOBALS['app_strings'] as $key=>$value) {
4438 if(!empty($all_non_custom_include_language_strings[$key])) {
4439 unset($GLOBALS['app_strings'][$key]);
4443 } //if(preg_match...)
4446 if(!empty($GLOBALS['app_strings'])) {
4447 foreach($GLOBALS['app_strings'] as $key=>$entry) {
4448 $out .= "\n\$GLOBALS['app_strings']['$key']=" . var_export_helper($entry) . ";";
4452 foreach($GLOBALS['app_list_strings'] as $key=>$entry) {
4453 $out .= "\n\$GLOBALS['app_list_strings']['$key']=" . var_export_helper($entry) . ";";
4457 } //if(preg_match...)
4461 //Create a backup just in case
4462 copy($file, $file . '.bak');
4463 $fp = @sugar_fopen($file, 'w');
4468 //If we can't update the file, just return
4469 $GLOBALS['log']->error("Unable to update file contents in fix_dropdown_list.");
4477 //Update db entries (the order matters here... need to process database changes first)
4478 if(!empty($affected_keys)) {
4479 foreach($affected_keys as $old_key=>$new_key) {
4480 $GLOBALS['db']->query("UPDATE fields_meta_data SET ext1 = '{$new_key}' WHERE ext1 = '{$old_key}'");
4484 //Update vardef files for affected modules
4485 if(!empty($affected_modules)) {
4486 foreach($affected_modules as $module=>$object) {
4487 VardefManager::refreshVardefs($module, $object);
4494 function update_iframe_dashlets(){
4495 require_once('cache/dashlets/dashlets.php');
4497 $db = DBManagerFactory::getInstance();
4498 $query = "SELECT id, contents, assigned_user_id FROM user_preferences WHERE deleted = 0 AND category = 'Home'";
4499 $result = $db->query($query, true, "Unable to update new default dashlets! ");
4500 while ($row = $db->fetchByAssoc($result)) {
4501 $content = unserialize(base64_decode($row['contents']));
4502 $assigned_user_id = $row['assigned_user_id'];
4503 $record_id = $row['id'];
4505 $current_user = new User();
4506 $current_user->retrieve($row['assigned_user_id']);
4508 if(!empty($content['dashlets']) && !empty($content['pages'])){
4509 $originalDashlets = $content['dashlets'];
4510 foreach($originalDashlets as $key => $ds){
4511 if(!empty($ds['options']['url']) && stristr($ds['options']['url'],'http://www.sugarcrm.com/crm/product/gopro')){
4512 unset($originalDashlets[$key]);
4515 $current_user->setPreference('dashlets', $originalDashlets, 0, 'Home');
4522 * convertImageToText
4523 * This method attempts to convert date type image to text on Microsoft SQL Server.
4524 * This method could NOT be used in any other type of datebases.
4526 function convertImageToText($table_name,$column_name){
4527 $set_lang = "SET LANGUAGE us_english";
4528 $GLOBALS['db']->query($set_lang);
4529 if($GLOBALS['db']->checkError()){
4530 logThis('An error occurred when performing this query-->'.$set_lang);
4532 $q="SELECT data_type
4533 FROM INFORMATION_SCHEMA.Tables T JOIN INFORMATION_SCHEMA.Columns C
4534 ON T.TABLE_NAME = C.TABLE_NAME where T.TABLE_NAME = '$table_name' and C.COLUMN_NAME = '$column_name'";
4535 $res= $GLOBALS['db']->query($q);
4536 if($GLOBALS['db']->checkError()){
4537 logThis('An error occurred when performing this query-->'.$q);
4539 $row= $GLOBALS['db']->fetchByAssoc($res);
4541 if(trim(strtolower($row['data_type'])) == 'image'){
4542 $addContent_temp = "alter table {$table_name} add {$column_name}_temp text null";
4543 $GLOBALS['db']->query($addContent_temp);
4544 if($GLOBALS['db']->checkError()){
4545 logThis('An error occurred when performing this query-->'.$addContent_temp);
4547 $qN = "select count=datalength({$column_name}), id, {$column_name} from {$table_name}";
4548 $result = $GLOBALS['db']->query($qN);
4549 while($row = $GLOBALS['db']->fetchByAssoc($result)){
4550 if($row['count'] >8000){
4551 $contentLength = $row['count'];
4554 $convertedContent = '';
4555 while($contentLength >0){
4556 $stepsQuery = "select cont=convert(varchar(max), convert(varbinary(8000), substring({$column_name},{$start},{$next}))) from {$table_name} where id= '{$row['id']}'";
4557 $steContQ = $GLOBALS['db']->query($stepsQuery);
4558 if($GLOBALS['db']->checkError()){
4559 logThis('An error occurred when performing this query-->'.$stepsQuery);
4561 $stepCont = $GLOBALS['db']->fetchByAssoc($steContQ);
4562 if(isset($stepCont['cont'])){
4563 $convertedContent = $convertedContent.$stepCont['cont'];
4565 $start = $start+$next;
4566 $contentLength = $contentLength - $next;
4568 $addContentDataText="update {$table_name} set {$column_name}_temp = '{$convertedContent}' where id= '{$row['id']}'";
4569 $GLOBALS['db']->query($addContentDataText);
4570 if($GLOBALS['db']->checkError()){
4571 logThis('An error occurred when performing this query-->'.$addContentDataText);
4575 $addContentDataText="update {$table_name} set {$column_name}_temp =
4576 convert(varchar(max), convert(varbinary(8000), {$column_name})) where id= '{$row['id']}'";
4577 $GLOBALS['db']->query($addContentDataText);
4578 if($GLOBALS['db']->checkError()){
4579 logThis('An error occurred when performing this query-->'.$addContentDataText);
4583 //drop the contents now and change contents_temp to contents
4584 $dropColumn = "alter table {$table_name} drop column {$column_name}";
4585 $GLOBALS['db']->query($dropColumn);
4586 if($GLOBALS['db']->checkError()){
4587 logThis('An error occurred when performing this query-->'.$dropColumn);
4589 $changeColumnName = "EXEC sp_rename '{$table_name}.[{$column_name}_temp]','{$column_name}','COLUMN'";
4590 $GLOBALS['db']->query($changeColumnName);
4591 if($GLOBALS['db']->checkError()){
4592 logThis('An error occurred when performing this query-->'.$changeColumnName);
4599 * This method attempts to delete all English inline help files.
4600 * This method was introduced by 5.5.0RC2.
4602 function clearHelpFiles(){
4603 $modulePath = clean_path(getcwd() . '/modules');
4604 $allHelpFiles = array();
4605 getFiles($allHelpFiles, $modulePath, "/en_us.help.*/");
4607 foreach( $allHelpFiles as $the_file ){
4608 if( is_file( $the_file ) ){
4609 unlink( $the_file );
4610 _logThis("Deleted file: $the_file", $path);
4617 * upgrade_connectors
4618 * @param $path String variable for the log path
4620 function upgrade_connectors($path='') {
4621 logThis('Begin upgrade_connectors', $path);
4623 $filePath = 'custom/modules/Connectors/connectors/sources/ext/soap/hoovers/config.php';
4624 if(file_exists($filePath))
4626 logThis("{$filePath} file", $path);
4628 if(!is_null($config))
4631 if(isset($config['properties']['hoovers_endpoint']))
4633 $config['properties']['hoovers_endpoint'] = 'http://hapi.hoovers.com/HooversAPI-33';
4637 if(isset($config['properties']['hoovers_wsdl']))
4639 $config['properties']['hoovers_wsdl'] = 'http://hapi.hoovers.com/HooversAPI-33/hooversAPI/hooversAPI.wsdl';
4645 if(!write_array_to_file('config', $config, $filePath)) {
4646 logThis("Could not write new configuration to {$filePath} file", $path);
4648 logThis('Modified file successfully with new configuration entries', $path);
4654 $filePath = 'custom/modules/Connectors/connectors/sources/ext/soap/hoovers/vardefs.php';
4655 if(file_exists($filePath))
4657 logThis("Modifying {$filePath} file", $path);
4659 $fileContents = file_get_contents($filePath);
4660 $out = str_replace('bal.specialtyCriteria.companyKeyword', 'bal.specialtyCriteria.companyName', $fileContents);
4661 file_put_contents($filePath, $out);
4664 logThis('End upgrade_connectors', $path);
4668 function removeSilentUpgradeVarsCache(){
4669 global $silent_upgrade_vars_loaded;
4671 $cacheFileDir = "{$GLOBALS['sugar_config']['cache_dir']}/silentUpgrader";
4672 $cacheFile = "{$cacheFileDir}/silentUpgradeCache.php";
4674 if(file_exists($cacheFile)){
4678 $silent_upgrade_vars_loaded = array(); // Set to empty to reset it
4683 function loadSilentUpgradeVars(){
4684 global $silent_upgrade_vars_loaded;
4686 if(empty($silent_upgrade_vars_loaded)){
4687 $cacheFile = "{$GLOBALS['sugar_config']['cache_dir']}/silentUpgrader/silentUpgradeCache.php";
4688 // We have no pre existing vars
4689 if(!file_exists($cacheFile)){
4690 // Set the vars array so it's loaded
4691 $silent_upgrade_vars_loaded = array('vars' => array());
4694 require_once($cacheFile);
4695 $silent_upgrade_vars_loaded = $silent_upgrade_vars_cache;
4702 function writeSilentUpgradeVars(){
4703 global $silent_upgrade_vars_loaded;
4705 if(empty($silent_upgrade_vars_loaded)){
4706 return false; // You should have set some values before trying to write the silent upgrade vars
4709 $cacheFileDir = "{$GLOBALS['sugar_config']['cache_dir']}/silentUpgrader";
4710 $cacheFile = "{$cacheFileDir}/silentUpgradeCache.php";
4712 require_once('include/dir_inc.php');
4713 if(!mkdir_recursive($cacheFileDir)){
4716 require_once('include/utils/file_utils.php');
4717 if(!write_array_to_file('silent_upgrade_vars_cache', $silent_upgrade_vars_loaded, $cacheFile, 'w')){
4719 logThis("WARNING: writeSilentUpgradeVars could not write to {$cacheFile}", $path);
4726 function setSilentUpgradeVar($var, $value){
4727 if(!loadSilentUpgradeVars()){
4731 global $silent_upgrade_vars_loaded;
4733 $silent_upgrade_vars_loaded['vars'][$var] = $value;
4738 function getSilentUpgradeVar($var){
4739 if(!loadSilentUpgradeVars()){
4743 global $silent_upgrade_vars_loaded;
4745 if(!isset($silent_upgrade_vars_loaded['vars'][$var])){
4749 return $silent_upgrade_vars_loaded['vars'][$var];
4754 * unlinkUpgradeFiles
4755 * This is a helper function to clean up
4757 * @param $version String value of current system version (pre upgrade)
4759 function unlinkUpgradeFiles($version)
4761 if(!isset($version))
4766 logThis('start unlinking files from previous upgrade');
4767 if($version < '614')
4769 //list of files to remove
4770 $files_to_remove = array('modules/Help/Forms.php');
4772 foreach($files_to_remove as $f)
4776 logThis('removing file: ' . $f);
4781 logThis('end unlinking files from previous upgrade');