2 if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
3 /*********************************************************************************
4 * SugarCRM Community Edition is a customer relationship management program developed by
5 * SugarCRM, Inc. Copyright (C) 2004-2011 SugarCRM Inc.
7 * This program is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU Affero General Public License version 3 as published by the
9 * Free Software Foundation with the addition of the following permission added
10 * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
11 * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
12 * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
19 * You should have received a copy of the GNU Affero General Public License along with
20 * this program; if not, see http://www.gnu.org/licenses or write to the Free
21 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24 * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
25 * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
27 * The interactive user interfaces in modified source and object code versions
28 * of this program must display Appropriate Legal Notices, as required under
29 * Section 5 of the GNU Affero General Public License version 3.
31 * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
32 * these Appropriate Legal Notices must retain the display of the "Powered by
33 * SugarCRM" logo. If the display of the logo is not reasonably feasible for
34 * technical reasons, the Appropriate Legal Notices must display the words
35 * "Powered by SugarCRM".
36 ********************************************************************************/
42 * Backs-up files that are targeted for patch/upgrade to a restore directory
43 * @param string rest_dir Full path to the directory containing the original, replaced files.
44 * @param string install_file Full path to the uploaded patch/upgrade zip file
45 * @param string unzip_dir Full path to the unzipped files in a temporary directory
46 * @param string zip_from_dir Name of directory that the unzipped files containing the actuall replacement files
47 * @param array errors Collection of errors to be displayed at end of process
48 * @param string path Optional full path to the log file.
49 * @return array errors
51 function commitMakeBackupFiles($rest_dir, $install_file, $unzip_dir, $zip_from_dir, $errors, $path='') {
53 // create restore file directory
54 mkdir_recursive($rest_dir);
56 if(file_exists($rest_dir) && is_dir($rest_dir)){
57 logThis('backing up files to be overwritten...', $path);
58 $newFiles = findAllFiles(clean_path($unzip_dir . '/' . $zip_from_dir), array());
60 // keep this around for canceling
61 $_SESSION['uw_restore_dir'] = clean_path($rest_dir);
63 foreach ($newFiles as $file) {
64 if (strpos($file, 'md5'))
67 // get name of current file to place in restore directory
68 $cleanFile = str_replace(clean_path($unzip_dir . '/' . $zip_from_dir), '', $file);
70 // make sure the directory exists
71 $cleanDir = $rest_dir . '/' . dirname($cleanFile);
72 if (!is_dir($cleanDir)) {
73 mkdir_recursive($cleanDir);
76 $oldFile = clean_path(getcwd() . '/' . $cleanFile);
78 // only copy restore files for replacements - ignore new files from patch
79 if (is_file($oldFile)) {
80 if (is_writable($rest_dir)) {
81 logThis('Backing up file: ' . $oldFile, $path);
82 if (!copy($oldFile, $rest_dir . '/' . $cleanFile)) {
83 logThis('*** ERROR: could not backup file: ' . $oldFile, $path);
84 $errors[] = "{$mod_strings['LBL_UW_BACKUP']}::{$mod_strings['ERR_UW_FILE_NOT_COPIED']}: {$oldFile}";
86 $backupFilesExist = true;
90 logThis('*** ERROR: directory not writable: ' . $rest_dir, $path);
91 $errors[] = "{$mod_strings['LBL_UW_BACKUP']}::{$mod_strings['ERR_UW_DIR_NOT_WRITABLE']}: {$oldFile}";
96 logThis('file backup done.', $path);
101 * Copies files from the unzipped patch to the destination.
102 * @param string unzip_dir Full path to the temporary directory created during unzip operation.
103 * @param string zip_from_dir Name of folder containing the unzipped files; usually the name of the Patch without the
105 * @param string path Optional full path to alternate upgradeWizard log file.
106 * @return array Two element array containing to $copiedFiles and $skippedFiles.
111 function commitCopyNewFiles($unzip_dir, $zip_from_dir, $path='') {
112 logThis('Starting file copy process...', $path);
113 global $sugar_version;
115 if(substr($sugar_version,0,1) >= 5){
116 $modules = getAllModules();
117 $backwardModules = array();
118 foreach($modules as $mod){
119 if(is_dir(clean_path(getcwd().'/modules/'.$mod.'/.500'))){
121 $files= findAllFiles(clean_path(getcwd().'/modules/'.$mod.'/.500'),$files);
122 if(sizeof($files) >0){
123 //backward compatibility is on
124 $backwardModules[] = $mod;
130 $newFiles = findAllFiles(clean_path($unzip_dir . '/' . $zip_from_dir), array());
131 $zipPath = clean_path($unzip_dir . '/' . $zip_from_dir);
133 // handle special do-not-overwrite conditions
134 $doNotOverwrite = array();
135 $doNotOverwrite[] = '__stub';
136 if(isset($_REQUEST['overwrite_files_serial'])) {
137 $doNotOverwrite = explode('::', $_REQUEST['overwrite_files_serial']);
140 $copiedFiles = array();
141 $skippedFiles = array();
143 foreach($newFiles as $file) {
144 $cleanFile = str_replace($zipPath, '', $file);
145 $srcFile = $zipPath . $cleanFile;
146 $targetFile = clean_path(getcwd() . '/' . $cleanFile);
147 if($backwardModules != null && sizeof($backwardModules) >0){
148 foreach($backwardModules as $mod){
149 $splitPath = explode('/',trim($cleanFile));
150 if('modules' == trim($splitPath[1]) && $mod == trim($splitPath[2])){
151 $cleanFile = str_replace('/modules/'.$mod, '/modules/'.$mod.'/.500', $cleanFile);
152 $targetFile = clean_path(getcwd() . '/' . $cleanFile);
156 if(!is_dir(dirname($targetFile))) {
157 mkdir_recursive(dirname($targetFile)); // make sure the directory exists
160 if((!file_exists($targetFile)) || /* brand new file */
161 (!in_array($targetFile, $doNotOverwrite)) /* manual diff file */
163 // handle sugar_version.php
164 if(strpos($targetFile, 'sugar_version.php') !== false && !preg_match('/\/portal\/sugar_version\.php$/i', $targetFile)) {
165 logThis('Skipping "sugar_version.php" - file copy will occur at end of successful upgrade', $path);
166 $_SESSION['sugar_version_file'] = $srcFile;
170 //logThis('Copying file to destination: ' . $targetFile, $path);
172 if(!copy($srcFile, $targetFile)) {
173 logThis('*** ERROR: could not copy file: ' . $targetFile, $path);
175 $copiedFiles[] = $targetFile;
178 //logThis('Skipping file: ' . $targetFile, $path);
179 $skippedFiles[] = $targetFile;
182 logThis('File copy done.', $path);
185 $ret['copiedFiles'] = $copiedFiles;
186 $ret['skippedFiles'] = $skippedFiles;
192 //On cancel put back the copied files from 500 to 451 state
193 function copyFilesOnCancel($step){
194 //place hoder for cancel action
199 function removeFileFromPath($file,$path, $deleteNot=array()){
201 $cur = $path . '/' . $file;
202 if(file_exists($cur)){
204 foreach($deleteNot as $dn){
214 if(!file_exists($path))return $removed;
216 while($e = $d->read()){
217 $next = $path . '/'. $e;
218 if(substr($e, 0, 1) != '.' && is_dir($next)){
219 $removed += removeFileFromPath($file, $next, $deleteNot);
226 * This function copies/overwrites between directories
228 * @param string the directory name to remove
229 * @param boolean whether to just empty the given directory, without deleting the given directory.
230 * @return boolean True/False whether the directory was deleted.
233 function copyRecursiveBetweenDirectories($from,$to){
234 if(file_exists($from)){
235 $modifiedFiles = array();
236 $modifiedFiles = findAllFiles(clean_path($from), $modifiedFiles);
237 $cwd = clean_path(getcwd());
238 foreach($modifiedFiles as $file) {
239 $srcFile = clean_path($file);
240 //$targetFile = clean_path(getcwd() . '/' . $srcFile);
241 if (strpos($srcFile,".svn") !== false) {
245 $targetFile = str_replace($from, $to, $srcFile);
247 if(!is_dir(dirname($targetFile))) {
248 mkdir_recursive(dirname($targetFile)); // make sure the directory exists
251 // handle sugar_version.php
252 if(strpos($targetFile, 'sugar_version.php') !== false && !preg_match('/\/portal\/sugar_version\.php$/i', $targetFile)) {
253 logThis('Skipping "sugar_version.php" - file copy will occur at end of successful upgrade', $path);
254 $_SESSION['sugar_version_file'] = $srcFile;
258 //logThis('Copying file to destination: ' . $targetFile);
260 if(!copy($srcFile, $targetFile)) {
261 logThis('*** ERROR: could not copy file: ' . $targetFile);
263 //logThis('Copied file: ' . $targetFile);
264 //$copiedFiles[] = $targetFile;
272 function deleteDirectory($dirname,$only_empty=false) {
273 if (!is_dir($dirname))
275 $dscan = array(realpath($dirname));
277 while (!empty($dscan)) {
278 $dcur = array_pop($dscan);
280 if ($d=opendir($dcur)) {
281 while ($f=readdir($d)) {
282 if ($f=='.' || $f=='..')
293 $i_until = ($only_empty)? 1 : 0;
294 for ($i=count($darr)-1; $i>=$i_until; $i--) {
295 //echo "\nDeleting '".$darr[$i]."' ... ";
296 if (rmdir($darr[$i]))
297 logThis('Success :Copying file to destination: ' . $darr[$i]);
299 logThis('Copy problem:Copying file to destination: ' . $darr[$i]);
301 return (($only_empty)? (count(scandir)<=2) : (!is_dir($dirname)));
304 * Get all the customized modules. Compare the file md5s with the base md5s
305 * If a file has been modified then put the module in the list of customized
306 * modules. Show the list in the preflight check UI.
309 function deleteAndOverWriteSelectedFiles($unzip_dir, $zip_from_dir,$delete_dirs){
310 if($delete_dirs != null){
311 foreach($delete_dirs as $del_dir){
312 deleteDirectory($del_dir);
313 $newFiles = findAllFiles(clean_path($unzip_dir . '/' . $zip_from_dir.'/'.$del_dir), array());
314 $zipPath = clean_path($unzip_dir . '/' . $zip_from_dir.'/'.$del_dir);
315 $copiedFiles = array();
316 $skippedFiles = array();
318 foreach($newFiles as $file) {
319 $cleanFile = str_replace($zipPath, '', $file);
320 $srcFile = $zipPath . $cleanFile;
321 $targetFile = clean_path(getcwd() . '/' . $cleanFile);
323 if(!is_dir(dirname($targetFile))) {
324 mkdir_recursive(dirname($targetFile)); // make sure the directory exists
327 if(!file_exists($targetFile)){
328 // handle sugar_version.php
329 if(strpos($targetFile, 'sugar_version.php') !== false) {
330 logThis('Skipping sugar_version.php - file copy will occur at end of successful upgrade');
331 $_SESSION['sugar_version_file'] = $srcFile;
335 //logThis('Copying file to destination: ' . $targetFile);
337 if(!copy($srcFile, $targetFile)) {
338 logThis('*** ERROR: could not copy file: ' . $targetFile);
340 $copiedFiles[] = $targetFile;
343 //logThis('Skipping file: ' . $targetFile);
344 $skippedFiles[] = $targetFile;
350 $ret['copiedFiles'] = $copiedFiles;
351 $ret['skippedFiles'] = $skippedFiles;
356 //Default is empty the directory. For removing set it to false
357 // to use this function to totally remove a directory, write:
358 // recursive_remove_directory('path/to/directory/to/delete',FALSE);
360 // to use this function to empty a directory, write:
361 // recursive_remove_directory('path/to/full_directory');
363 function recursive_empty_or_remove_directory($directory, $exclude_dirs=null,$exclude_files=null,$empty=TRUE)
365 // if the path has a slash at the end we remove it here
366 if(substr($directory,-1) == '/')
368 $directory = substr($directory,0,-1);
371 // if the path is not valid or is not a directory ...
372 if(!file_exists($directory) || !is_dir($directory))
374 // ... we return false and exit the function
377 // ... if the path is not readable
378 }elseif(!is_readable($directory))
380 // ... we return false and exit the function
383 // ... else if the path is readable
386 // we open the directory
387 $handle = opendir($directory);
389 // and scan through the items inside
390 while (FALSE !== ($item = readdir($handle)))
392 // if the filepointer is not the current directory
393 // or the parent directory
394 if($item != '.' && $item != '..')
396 // we build the new path to delete
397 $path = $directory.'/'.$item;
399 // if the new path is a directory
400 //add another check if the dir is in the list to exclude delete
401 if(is_dir($path) && $exclude_dirs != null && in_array($path,$exclude_dirs)){
404 else if(is_dir($path))
406 // we call this function with the new path
407 recursive_empty_or_remove_directory($path);
409 // if the new path is a file
411 // we remove the file
412 if($exclude_files != null && in_array($path,$exclude_files)){
421 // close the directory
424 // if the option to empty is not set to true
427 // try to delete the now empty directory
428 if(!rmdir($directory))
430 // return false if not possible
438 // ------------------------------------------------------------
443 function getAllCustomizedModules() {
445 require_once('files.md5');
447 $return_array = array();
448 $modules = getAllModules();
449 foreach($modules as $mod) {
450 //find all files in each module if the files have been modified
451 //as compared to the base version then add the module to the
452 //customized modules array
453 $modFiles = findAllFiles(clean_path(getcwd())."/modules/$mod", array());
454 foreach($modFiles as $file){
455 $fileContents = file_get_contents($file);
456 $file = str_replace(clean_path(getcwd()),'',$file);
457 if($md5_string['./' . $file]){
458 if(md5($fileContents) != $md5_string['./' . $file]) {
459 //A file has been customized in the module. Put the module into the
460 // customized modules array.
461 echo 'Changed File'.$file;
467 // This is a new file in user's version and indicates that module has been
468 //customized. Put the module in the customized array.
469 echo 'New File'.$file;
476 return $return_array;
480 * Array of all Modules in the version bein upgraded
481 * This method returns an Array of all modules
482 * @return $modules Array of modules.
484 function getAllModules() {
487 while($e = $d->read()){
488 if(substr($e, 0, 1) == '.' || !is_dir('modules/' . $e))continue;
494 //Remove files with the smae md5
496 function removeMd5MatchingFiles($deleteNot=array()){
498 $md5_string = array();
499 if(file_exists(clean_path(getcwd().'/files.md5'))){
500 require(clean_path(getcwd().'/files.md5'));
502 $modulesAll = getAllModules();
503 foreach($modulesAll as $mod){
504 $allModFiles = array();
505 if(is_dir('modules/'.$mod)){
506 $allModFiles = findAllFiles('modules/'.$mod,$allModFiles);
507 foreach($allModFiles as $file){
508 if(file_exists($file) && !in_array(basename($file),$deleteNot)){
509 if(isset($md5_string['./'.$file])) {
510 $fileContents = file_get_contents($file);
511 if(md5($fileContents) == $md5_string['./'.$file]) {
522 * Handles requirements for creating reminder Tasks and Emails
523 * @param array skippedFiles Array of files that were not overwriten and must be manually mereged.
524 * @param string path Optional full path to alternate upgradeWizard log.
526 function commitHandleReminders($skippedFiles, $path='') {
528 global $current_user;
530 if(empty($mod_strings))
531 $mod_strings = return_module_language('en_us', 'UpgradeWizard');
533 if(empty($current_user->id)) {
534 $current_user->getSystemUser();
537 if(count($skippedFiles) > 0) {
538 $desc = $mod_strings['LBL_UW_COMMIT_ADD_TASK_OVERVIEW'] . "\n\n";
539 $desc .= $mod_strings['LBL_UW_COMMIT_ADD_TASK_DESC_1'];
540 $desc .= $_SESSION['uw_restore_dir'] . "\n\n";
541 $desc .= $mod_strings['LBL_UW_COMMIT_ADD_TASK_DESC_2'] . "\n\n";
543 foreach($skippedFiles as $file) {
544 $desc .= $file . "\n";
548 /// Not using new TimeDate stuff here because it needs to be compatible with 6.0
549 $nowDate = gmdate('Y-m-d');
550 $nowTime = gmdate('H:i:s');
551 $nowDateTime = $nowDate . ' ' . $nowTime;
553 if($_REQUEST['addTaskReminder'] == 'remind') {
554 logThis('Adding Task for admin for manual merge.', $path);
557 $task->name = $mod_strings['LBL_UW_COMMIT_ADD_TASK_NAME'];
558 $task->description = $desc;
559 $task->date_due = $nowDate;
560 $task->time_due = $nowTime;
561 $task->priority = 'High';
562 $task->status = 'Not Started';
563 $task->assigned_user_id = $current_user->id;
564 $task->created_by = $current_user->id;
565 $task->date_entered = $nowDateTime;
566 $task->date_modified = $nowDateTime;
570 if($_REQUEST['addEmailReminder'] == 'remind') {
571 logThis('Sending Reminder for admin for manual merge.', $path);
573 $email = new Email();
574 $email->assigned_user_id = $current_user->id;
575 $email->name = $mod_strings['LBL_UW_COMMIT_ADD_TASK_NAME'];
576 $email->description = $desc;
577 $email->description_html = nl2br($desc);
578 $email->from_name = $current_user->full_name;
579 $email->from_addr = $current_user->email1;
580 $email->to_addrs_arr = $email->parse_addrs($current_user->email1, '', '', '');
581 $email->cc_addrs_arr = array();
582 $email->bcc_addrs_arr = array();
583 $email->date_entered = $nowDateTime;
584 $email->date_modified = $nowDateTime;
591 function deleteCache(){
592 //Clean modules from cache
593 if(is_dir($GLOBALS['sugar_config']['cache_dir'].'modules')){
594 $allModFiles = array();
595 $allModFiles = findAllFiles($GLOBALS['sugar_config']['cache_dir'].'modules',$allModFiles);
596 foreach($allModFiles as $file)
598 if(file_exists($file))
605 //Clean jsLanguage from cache
606 if(is_dir($GLOBALS['sugar_config']['cache_dir'].'jsLanguage')){
607 $allModFiles = array();
608 $allModFiles = findAllFiles($GLOBALS['sugar_config']['cache_dir'].'jsLanguage',$allModFiles);
609 foreach($allModFiles as $file){
610 if(file_exists($file)){
615 //Clean smarty from cache
616 if(is_dir($GLOBALS['sugar_config']['cache_dir'].'smarty')){
617 $allModFiles = array();
618 $allModFiles = findAllFiles($GLOBALS['sugar_config']['cache_dir'].'smarty',$allModFiles);
619 foreach($allModFiles as $file){
620 if(file_exists($file)){
625 //Rebuild dashlets cache
626 require_once('include/Dashlets/DashletCacheBuilder.php');
627 $dc = new DashletCacheBuilder();
631 function deleteChance(){
632 //Clean folder from cache
633 if(is_dir('include/SugarObjects/templates/chance')){
634 rmdir_recursive('include/SugarObjects/templates/chance');
636 if(is_dir('include/SugarObjects/templates/chance')){
637 if(!isset($_SESSION['chance'])){
638 $_SESSION['chance'] = '';
640 $_SESSION['chance'] = 'include/SugarObjects/templates/chance';
641 //rename('include/SugarObjects/templates/chance','include/SugarObjects/templates/chance_removeit');
648 * copies upgrade wizard files from new patch if that dir exists
649 * @param string file Path to uploaded zip file
651 function upgradeUWFiles($file) {
652 global $sugar_config;
653 // file = getcwd().'/'.$sugar_config['upload_dir'].$_FILES['upgrade_zip']['name'];
655 $cacheUploadUpgradesTemp = clean_path(mk_temp_dir("{$sugar_config['upload_dir']}upgrades/temp"));
657 unzip($file, $cacheUploadUpgradesTemp);
659 if(!file_exists(clean_path("{$cacheUploadUpgradesTemp}/manifest.php"))) {
660 logThis("*** ERROR: no manifest file detected while bootstraping upgrade wizard files!");
663 include(clean_path("{$cacheUploadUpgradesTemp}/manifest.php"));
668 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/modules/UpgradeWizard"))) {
669 $allFiles = findAllFiles(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/modules/UpgradeWizard"), $allFiles);
672 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/ModuleInstall"))) {
673 $allFiles = findAllFiles(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/ModuleInstall"), $allFiles);
675 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/javascript/yui"))) {
676 $allFiles = findAllFiles(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/javascript/yui"), $allFiles);
678 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/HandleAjaxCall.php"))) {
679 $allFiles[] = clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/HandleAjaxCall.php");
681 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/SugarTheme"))) {
682 $allFiles = findAllFiles(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/SugarTheme"), $allFiles);
684 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/SugarCache"))) {
685 $allFiles = findAllFiles(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/SugarCache"), $allFiles);
687 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/external_cache.php"))) {
688 $allFiles[] = clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/external_cache.php");
692 * /home/chris/workspace/maint450/cache/upload/upgrades/temp/DlNnqP/
693 * SugarEnt-Patch-4.5.0c/modules/Leads/ConvertLead.html
695 $cwd = clean_path(getcwd());
697 foreach($allFiles as $k => $file) {
698 $file = clean_path($file);
699 $destFile = str_replace(clean_path($cacheUploadUpgradesTemp.'/'.$manifest['copy_files']['from_dir']), $cwd, $file);
700 if(!is_dir(dirname($destFile))) {
701 mkdir_recursive(dirname($destFile)); // make sure the directory exists
703 if ( stristr($file,'uw_main.tpl') )
704 logThis('Skipping "'.$file.'" - file copy will during commit step.');
706 logThis('updating UpgradeWizard code: '.$destFile);
707 copy_recursive($file, $destFile);
710 logThis ('is sugar_file_util there '.file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/sugar_file_utils.php")));
711 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/sugar_file_utils.php"))) {
712 $file = clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/sugar_file_utils.php");
713 $destFile = str_replace(clean_path($cacheUploadUpgradesTemp.'/'.$manifest['copy_files']['from_dir']), $cwd, $file);
714 copy($file,$destFile);
721 * gets valid patch file names that exist in upload/upgrade/patch/
723 function getValidPatchName($returnFull = true) {
724 global $base_upgrade_dir;
727 global $sugar_version;
728 global $sugar_config;
729 $uh = new UpgradeHistory();
730 $base_upgrade_dir = $sugar_config['upload_dir'] . "upgrades";
733 // scan for new files (that are not installed)
734 logThis('finding new files for upgrade');
735 $upgrade_content = '';
736 $upgrade_contents = findAllFiles($base_upgrade_dir, array(), false, 'zip');
737 //other variations of zip file i.e. ZIP, zIp,zIP,Zip,ZIp,ZiP
738 $extns = array('ZIP','ZIp','ZiP','Zip','zIP','zIp','ziP');
739 foreach($extns as $extn){
740 $upgrade_contents = array_merge($upgrade_contents,findAllFiles( "$base_upgrade_dir", array() , false, $extn));
748 <b>{$mod_strings['LBL_ML_NAME']}</b>
751 <b>{$mod_strings['LBL_ML_TYPE']}</b>
754 <b>{$mod_strings['LBL_ML_VERSION']}</b>
757 <b>{$mod_strings['LBL_ML_PUBLISHED']}</b>
760 <b>{$mod_strings['LBL_ML_UNINSTALLABLE']}</b>
763 <b>{$mod_strings['LBL_ML_DESCRIPTION']}</b>
768 // assume old patches are there.
769 $upgradeToVersion = array(); // fill with valid patches - we will only use the latest qualified found patch
771 // cn: bug 10609 - notices for uninitialized variables
776 $published_date = '';
781 foreach($upgrade_contents as $upgrade_content) {
782 if(!preg_match("#.*\.zip\$#i", strtolower($upgrade_content))) {
786 $upgrade_content = clean_path($upgrade_content);
787 $the_base = basename($upgrade_content);
788 $the_md5 = md5_file($upgrade_content);
790 $md5_matches = $uh->findByMd5($the_md5);
792 /* 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.
793 * Edge-case: manual upgrade with a FTP of a patch; UH table has no entry for it. Assume nothing. :( */
794 if(0 == sizeof($md5_matches)) {
795 $target_manifest = remove_file_extension( $upgrade_content ) . '-manifest.php';
796 require_once($target_manifest);
798 if(empty($manifest['version'])) {
799 logThis("*** Potential error: patch found with no version [ {$upgrade_content} ]");
802 if(!isset($manifest['type']) || $manifest['type'] != 'patch') {
803 logThis("*** Potential error: patch found with either no 'type' or non-patch type [ {$upgrade_content} ]");
807 $upgradeToVersion[$manifest['version']] = urlencode($upgrade_content);
809 $name = empty($manifest['name']) ? $upgrade_content : $manifest['name'];
810 $version = empty($manifest['version']) ? '' : $manifest['version'];
811 $published_date = empty($manifest['published_date']) ? '' : $manifest['published_date'];
813 $description = empty($manifest['description']) ? 'None' : $manifest['description'];
814 $uninstallable = empty($manifest['is_uninstallable']) ? 'No' : 'Yes';
815 $type = getUITextForType( $manifest['type'] );
816 $manifest_type = $manifest['type'];
818 if(empty($manifest['icon'])) {
819 $icon = getImageForType( $manifest['type'] );
821 $path_parts = pathinfo( $manifest['icon'] );
822 $icon = "<img src=\"" . remove_file_extension( $upgrade_content ) . "-icon." . $path_parts['extension'] . "\">";
827 // cn: bug 10488 use the NEWEST upgrade/patch available when running upgrade wizard.
828 ksort($upgradeToVersion);
829 $upgradeToVersion = array_values($upgradeToVersion);
830 $newest = array_pop($upgradeToVersion);
831 $_SESSION['install_file'] = urldecode($newest); // in-case it was there from a prior.
832 logThis("*** UW using [ {$_SESSION['install_file']} ] as source for patch files.");
834 $cleanUpgradeContent = urlencode($_SESSION['install_file']);
836 // cn: 10606 - cannot upload a patch file since this returned always.
837 if(!empty($cleanUpgradeContent)) {
838 $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";
841 <form action="index.php" method="post">
842 <input type="hidden" name="module" value="UpgradeWizard">
843 <input type="hidden" name="action" value="index">
844 <input type="hidden" name="step" value="{$_REQUEST['step']}">
845 <input type="hidden" name="run" value="delete">
846 <input type=hidden name="install_file" value="{$cleanUpgradeContent}" />
847 <input type=submit value="{$mod_strings['LBL_BUTTON_DELETE']}" />
851 $disabled = "DISABLED";
856 if(empty($cleanUpgradeContent)){
857 $ready .= "<tr><td colspan='7'><i>None</i></td>\n";
858 $ready .= "</table>\n";
860 $ready .= "<br></ul>\n";
862 $return['ready'] = $ready;
863 $return['disabled'] = $disabled;
872 * finalizes upgrade by setting upgrade versions in DB (config table) and sugar_version.php
873 * @return bool true on success
875 function updateVersions($version) {
877 global $sugar_config;
880 logThis('At updateVersions()... updating config table and sugar_version.php.', $path);
883 if(isset($_SESSION['sugar_version_file']) && !empty($_SESSION['sugar_version_file'])) {
884 if(!copy($_SESSION['sugar_version_file'], clean_path(getcwd().'/sugar_version.php'))) {
885 logThis('*** ERROR: sugar_version.php could not be copied to destination! Cannot complete upgrade', $path);
888 logThis('sugar_version.php successfully updated!', $path);
891 logThis('*** ERROR: no sugar_version.php file location found! - cannot complete upgrade...', $path);
895 // handle config table
896 if($db->dbType == 'mysql') {
897 $q1 = "DELETE FROM `config` WHERE `category` = 'info' AND `name` = 'sugar_version'";
898 $q2 = "INSERT INTO `config` (`category`, `name`, `value`) VALUES ('info', 'sugar_version', '{$version}')";
899 } elseif($db->dbType == 'oci8' || $db->dbType == 'oracle') {
900 } elseif($db->dbType == 'mssql') {
901 $q1 = "DELETE FROM config WHERE category = 'info' AND name = 'sugar_version'";
902 $q2 = "INSERT INTO config (category, name, value) VALUES ('info', 'sugar_version', '{$version}')";
905 logThis('Deleting old DB version info from config table.', $path);
908 logThis('Inserting updated version info into config table.', $path);
911 logThis('updateVersions() complete.', $path);
918 * gets a module's lang pack - does not need to be a SugarModule
919 * @param lang string Language
920 * @param module string Path to language folder
921 * @return array mod_strings
923 function getModuleLanguagePack($lang, $module) {
924 $mod_strings = array();
926 if(!empty($lang) && !empty($module)) {
927 $langPack = clean_path(getcwd().'/'.$module.'/language/'.$lang.'.lang.php');
928 $langPackEn = clean_path(getcwd().'/'.$module.'/language/en_us.lang.php');
930 if(file_exists($langPack))
931 include_once($langPack);
932 elseif(file_exists($langPackEn))
933 include_once($langPackEn);
939 * checks system compliance for 4.5+ codebase
940 * @return array Mixed values
942 function checkSystemCompliance() {
943 global $sugar_config;
944 global $current_language;
948 if(!defined('SUGARCRM_MIN_MEM')) {
949 define('SUGARCRM_MIN_MEM', 40);
952 $installer_mod_strings = getModuleLanguagePack($current_language, './install');
954 $ret['error_found'] = false;
957 $php_version = constant('PHP_VERSION');
958 $check_php_version_result = check_php_version($php_version);
960 switch($check_php_version_result) {
962 $ret['phpVersion'] = "<b><span class=stop>{$installer_mod_strings['ERR_CHECKSYS_PHP_INVALID_VER']} {$php_version} )</span></b>";
963 $ret['error_found'] = true;
966 $ret['phpVersion'] = "<b><span class=go>{$installer_mod_strings['ERR_CHECKSYS_PHP_UNSUPPORTED']} {$php_version} )</span></b>";
969 $ret['phpVersion'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_PHP_OK']} {$php_version} )</span></b>";
973 // database and connect
974 switch($sugar_config['dbconfig']['db_type']){
977 $q = "SELECT version();";
979 $a = $db->fetchByAssoc($r);
980 if(version_compare($a['version()'], '4.1.2') < 0) {
981 $ret['error_found'] = true;
982 $ret['mysqlVersion'] = "<b><span class=stop>".$mod_strings['ERR_UW_MYSQL_VERSION'].$a['version()']."</span></b>";
996 if(function_exists('xml_parser_create')) {
997 $ret['xmlStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
999 $ret['xmlStatus'] = "<b><span class=stop>{$installer_mod_strings['LBL_CHECKSYS_NOT_AVAILABLE']}</span></b>";
1000 $ret['error_found'] = true;
1004 if(function_exists('curl_init')) {
1005 $ret['curlStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</font></b>";
1007 $ret['curlStatus'] = "<b><span class=go>{$installer_mod_strings['ERR_CHECKSYS_CURL']}</font></b>";
1008 $ret['error_found'] = false;
1012 if(function_exists('mb_strlen')) {
1013 $ret['mbstringStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</font></b>";
1015 $ret['mbstringStatus'] = "<b><span class=stop>{$installer_mod_strings['ERR_CHECKSYS_MBSTRING']}</font></b>";
1016 $ret['error_found'] = true;
1020 if(function_exists('imap_open')) {
1021 $ret['imapStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1023 $ret['imapStatus'] = "<b><span class=go>{$installer_mod_strings['ERR_CHECKSYS_IMAP']}</span></b>";
1024 $ret['error_found'] = false;
1029 if('1' == ini_get('safe_mode')) {
1030 $ret['safeModeStatus'] = "<b><span class=stop>{$installer_mod_strings['ERR_CHECKSYS_SAFE_MODE']}</span></b>";
1031 $ret['error_found'] = true;
1033 $ret['safeModeStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1037 // call time pass by ref
1038 if('1' == ini_get('allow_call_time_pass_reference')) {
1039 $ret['callTimeStatus'] = "<b><span class=stop>{$installer_mod_strings['ERR_CHECKSYS_CALL_TIME']}</span></b>";
1040 //continue upgrading
1042 $ret['callTimeStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1046 $ret['memory_msg'] = "";
1047 $memory_limit = "-1";//ini_get('memory_limit');
1048 $sugarMinMem = constant('SUGARCRM_MIN_MEM');
1049 // logic based on: http://us2.php.net/manual/en/ini.core.php#ini.memory-limit
1050 if( $memory_limit == "" ){ // memory_limit disabled at compile time, no memory limit
1051 $ret['memory_msg'] = "<b><span class=\"go\">{$installer_mod_strings['LBL_CHECKSYS_MEM_OK']}</span></b>";
1052 } elseif( $memory_limit == "-1" ){ // memory_limit enabled, but set to unlimited
1053 $ret['memory_msg'] = "<b><span class=\"go\">{$installer_mod_strings['LBL_CHECKSYS_MEM_UNLIMITED']}</span></b>";
1055 rtrim($memory_limit, 'M');
1056 $memory_limit_int = (int) $memory_limit;
1057 if( $memory_limit_int < constant('SUGARCRM_MIN_MEM') ){
1058 $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>";
1059 $ret['error_found'] = true;
1061 $ret['memory_msg'] = "<b><span class=\"go\">{$installer_mod_strings['LBL_CHECKSYS_OK']} ({$memory_limit})</span></b>";
1065 /* mbstring.func_overload
1066 $ret['mbstring.func_overload'] = '';
1067 $mb = ini_get('mbstring.func_overload');
1070 $ret['mbstring.func_overload'] = "<b><span class=\"stop\">{$mod_strings['ERR_UW_MBSTRING_FUNC_OVERLOAD']}</b>";
1071 $ret['error_found'] = true;
1079 function checkMysqlConnection(){
1080 global $sugar_config;
1081 $configOptions = $sugar_config['dbconfig'];
1082 if($sugar_config['dbconfig']['db_type'] == 'mysql'){
1083 @mysql_ping($GLOBALS['db']->database);
1088 * is a file that we blow away automagically
1090 function isAutoOverwriteFile($file) {
1091 $overwriteDirs = array(
1092 './sugar_version.php',
1093 './modules/UpgradeWizard/uw_main.tpl',
1095 $file = trim('.'.str_replace(clean_path(getcwd()), '', $file));
1097 if(in_array($file, $overwriteDirs)) {
1101 $fileExtension = substr(strrchr($file, "."), 1);
1102 if($fileExtension == 'tpl' || $fileExtension == 'html') {
1112 function logThis($entry, $path='') {
1113 global $mod_strings;
1114 if(file_exists('include/utils/sugar_file_utils.php')){
1115 require_once('include/utils/sugar_file_utils.php');
1117 $log = empty($path) ? clean_path(getcwd().'/upgradeWizard.log') : clean_path($path);
1119 // create if not exists
1120 if(!file_exists($log)) {
1121 if(function_exists('sugar_fopen')){
1122 $fp = @sugar_fopen($log, 'w+'); // attempts to create file
1125 $fp = fopen($log, 'w+'); // attempts to create file
1127 if(!is_resource($fp)) {
1128 $GLOBALS['log']->fatal('UpgradeWizard could not create the upgradeWizard.log file');
1129 die($mod_strings['ERR_UW_LOG_FILE_UNWRITABLE']);
1132 if(function_exists('sugar_fopen')){
1133 $fp = @sugar_fopen($log, 'a+'); // write pointer at end of file
1136 $fp = @fopen($log, 'a+'); // write pointer at end of file
1139 if(!is_resource($fp)) {
1140 $GLOBALS['log']->fatal('UpgradeWizard could not open/lock upgradeWizard.log file');
1141 die($mod_strings['ERR_UW_LOG_FILE_UNWRITABLE']);
1145 $line = date('r').' [UpgradeWizard] - '.$entry."\n";
1147 if(@fwrite($fp, $line) === false) {
1148 $GLOBALS['log']->fatal('UpgradeWizard could not write to upgradeWizard.log: '.$entry);
1149 die($mod_strings['ERR_UW_LOG_FILE_UNWRITABLE']);
1152 if(is_resource($fp)) {
1159 * tries to validate the query based on type
1160 * @param string query The query to verify
1161 * @param string dbType The DB type
1162 * @return string error Non-empty string on error
1164 function verifySqlStatement($query, $dbType, &$newTables) {
1166 logThis('verifying SQL statement');
1168 $table = getTableFromQuery($query);
1170 switch(strtoupper(substr($query, 0, 10))) {
1174 $error = testQueryAlter($table, $dbType, strtoupper($query), $newTables);
1178 $error = testQueryCreate($table, $dbType, $query, $newTables);
1182 $error = testQueryDelete($table, $dbType, $query);
1186 $error = testQueryDrop($table, $dbType, $query);
1190 $error = testQueryInsert($table, $dbType, $query);
1193 case (strtoupper(substr($query, 0, 6)) == 'UPDATE'):
1194 $error = testQueryUpdate($table, $dbType, $query);
1206 * @desc This function is to be used in the upgrade process to preserve changes/customaizations made to pre 5.1 quickcreate layout.
1207 * 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
1208 * was automatically picked up by the quick create. [Addresses Bug 21469]
1209 * This function will check if customizations were made, and will create quickcreatedefs.php in the /cutom/working/$module_name directory.
1211 function updateQuickCreateDefs(){
1212 $d = dir('modules');
1213 $studio_modules = array();
1215 while($e = $d->read()){ //collect all studio modules.
1216 if(substr($e, 0, 1) == '.' || !is_dir('modules/' . $e))continue;
1217 if(file_exists('modules/' . $e . '/metadata/studio.php'))
1219 array_push($studio_modules, $e);
1223 foreach( $studio_modules as $modname ){ //for each studio enabled module
1224 //Check !exists modules/$modname/metadata/quickcreatedefs.php &&
1225 //exists custom/$modname/editviewdefs.php (module was customized) &&
1226 //!exists custom/$modname/quickcreateviewdefs.php
1228 $editviewdefs = "custom/working/modules/".$modname."/metadata/editviewdefs.php";
1229 $quickcreatedefs = "custom/working/modules/".$modname."/metadata/quickcreatedefs.php";
1231 if ( !file_exists("modules/".$modname."/metadata/quickcreatedefs.php") &&
1232 file_exists($editviewdefs) &&
1233 !file_exists($quickcreatedefs) ){
1234 //clone editviewdef and save it in custom/working/modules/metadata
1235 $GLOBALS['log']->debug("Copying editviewdefs.php as quickcreatedefs.php for the $modname module in custom/working/modules/$modname/metadata!");
1236 if(copy( $editviewdefs, $quickcreatedefs)){
1237 if(file_exists($quickcreatedefs) && is_readable($quickcreatedefs)){
1238 $file = file($quickcreatedefs);
1239 //replace 'EditView' with 'QuickCreate'
1240 $fp = fopen($quickcreatedefs,'w');
1241 foreach($file as &$line){
1242 if(preg_match('/^\s*\'EditView\'\s*=>\s*$/', $line) > 0){
1243 $line = "'QuickCreate' =>\n";
1251 $GLOBALS['log']->debug("Failed to replace 'EditView' with QuickCreate because $quickcreatedefs is either not readable or does not exist.");
1254 $GLOBALS['log']->debug("Failed to copy $editviewdefs to $quickcreatedefs!");
1261 function cleanQuery($query, $oci8=false) {
1271 $q = str_replace($bad, $good, $query);
1277 * test perms for CREATE queries
1279 function testPermsCreate($type, $out) {
1280 logThis('Checking CREATE TABLE permissions...');
1282 global $mod_strings;
1287 $db->query('CREATE TABLE temp (id varchar(36))');
1288 if($db->checkError()) {
1289 logThis('cannot CREATE TABLE!');
1290 $out['db']['dbNoCreate'] = true;
1291 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_CREATE']}</span></td></tr>";
1303 * test perms for INSERT
1305 function testPermsInsert($type, $out, $skip=false) {
1306 logThis('Checking INSERT INTO permissions...');
1308 global $mod_strings;
1314 $db->query("INSERT INTO temp (id) VALUES ('abcdef0123456789abcdef0123456789abcd')");
1315 if($db->checkError()) {
1316 logThis('cannot INSERT INTO!');
1317 $out['db']['dbNoInsert'] = true;
1318 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_INSERT']}</span></td></tr>";
1332 * test perms for UPDATE TABLE
1334 function testPermsUpdate($type, $out, $skip=false) {
1335 logThis('Checking UPDATE TABLE permissions...');
1337 global $mod_strings;
1343 $db->query("UPDATE temp SET id = '000000000000000000000000000000000000' WHERE id = 'abcdef0123456789abcdef0123456789abcd'");
1344 if($db->checkError()) {
1345 logThis('cannot UPDATE TABLE!');
1346 $out['db']['dbNoUpdate'] = true;
1347 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_UPDATE']}</span></td></tr>";
1361 * test perms for SELECT
1363 function testPermsSelect($type, $out, $skip=false) {
1364 logThis('Checking SELECT permissions...');
1366 global $mod_strings;
1371 $r = $db->query('SELECT id FROM temp');
1372 if($db->checkError()) {
1373 logThis('cannot SELECT!');
1374 $out['db']['dbNoSelect'] = true;
1375 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_SELECT']}</span></td></tr>";
1377 logThis('Checking validity of SELECT results');
1378 while($a = $db->fetchByAssoc($r)) {
1379 if($a['id'] != '000000000000000000000000000000000000') {
1380 logThis('results DO NOT MATCH! got: '.$a['id']);
1381 $out['db'][] = 'selectFailed';
1382 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_INSERT_FAILED']}</span></td></tr>";
1397 * test perms for DELETE
1399 function testPermsDelete($type, $out, $skip=false) {
1400 logThis('Checking DELETE FROM permissions...');
1402 global $mod_strings;
1407 $db->query("DELETE FROM temp WHERE id = '000000000000000000000000000000000000'");
1408 if($db->checkError()) {
1409 logThis('cannot DELETE FROM!');
1410 $out['db']['dbNoDelete'] = true;
1411 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_DELETE']}</span></td></tr>";
1424 * test perms for ALTER TABLE ADD COLUMN
1426 function testPermsAlterTableAdd($type, $out, $skip=false) {
1427 logThis('Checking ALTER TABLE ADD COLUMN permissions...');
1429 global $mod_strings;
1433 $db->query('ALTER TABLE temp ADD COLUMN test varchar(100)');
1434 if($db->checkError()) {
1435 logThis('cannot ADD COLUMN!');
1436 $out['db']['dbNoAddColumn'] = true;
1437 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_ADD_COLUMN']}</span></td></tr>";
1442 $db->query('ALTER TABLE [temp] ADD [test] [varchar] (100)');
1443 if($db->checkError()) {
1444 logThis('cannot ADD COLUMN!');
1445 $out['db']['dbNoAddColumn'] = true;
1446 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_ADD_COLUMN']}</span></td></tr>";
1461 * test perms for ALTER TABLE ADD COLUMN
1463 function testPermsAlterTableChange($type, $out, $skip=false) {
1464 logThis('Checking ALTER TABLE CHANGE COLUMN permissions...');
1466 global $mod_strings;
1470 $db->query('ALTER TABLE temp CHANGE COLUMN test test varchar(100)');
1471 if($db->checkError()) {
1472 logThis('cannot CHANGE COLUMN!');
1473 $out['db']['dbNoChangeColumn'] = true;
1474 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_CHANGE_COLUMN']}</span></td></tr>";
1479 $db->query('ALTER TABLE [temp] ALTER COLUMN [test] [varchar] (100)');
1480 if($db->checkError()) {
1481 logThis('cannot CHANGE COLUMN!');
1482 $out['db']['dbNoChangeColumn'] = true;
1483 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_CHANGE_COLUMN']}</span></td></tr>";
1497 * test perms for ALTER TABLE DROP COLUMN
1499 function testPermsAlterTableDrop($type, $out, $skip=false) {
1500 logThis('Checking ALTER TABLE DROP COLUMN permissions...');
1502 global $mod_strings;
1507 $db->query('ALTER TABLE temp DROP COLUMN test');
1508 if($db->checkError()) {
1509 logThis('cannot DROP COLUMN!');
1510 $out['db']['dbNoDropColumn'] = true;
1511 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_DROP_COLUMN']}</span></td></tr>";
1524 * test perms for DROP TABLE
1526 function testPermsDropTable($type, $out, $skip=false) {
1527 logThis('Checking DROP TABLE permissions...');
1529 global $mod_strings;
1534 $db->query('DROP TABLE temp');
1535 if($db->checkError()) {
1536 logThis('cannot DROP TABLE!');
1537 $out['db']['dbNoDropTable'] = true;
1538 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_DROP_TABLE']}</span></td></tr>";
1551 function createMSSQLTemp($table) {
1552 global $sugar_config;
1555 $qtest = "SELECT TABLE_NAME tn FROM information.tables WHERE TABLE_NAME = '{$table}__UW_TEMP'";
1556 $rtest = $db->query($qtest);
1557 $atest = $db->fetchByAssoc($rtest);
1560 $tempTable = "CREATE TABLE {$table}__UW_TEMP AS ".$db->limitQuerySql("SELECT * FROM {$table}",0,8);
1561 logThis("Creating temp table for {$table}: {$tempTable}");
1562 $db->query($tempTable);
1565 logThis("Found {$table}__UW_TEMP - skipping temp table creation.");
1570 * Tests an ALTER TABLE query
1571 * @param string table The table name to get DDL
1572 * @param string dbType MySQL, MSSQL, etc.
1573 * @param string query The query to test.
1574 * @return string Non-empty if error found
1576 function testQueryAlter($table, $dbType, $query, $newTables) {
1577 logThis('verifying ALTER statement...');
1579 global $sugar_config;
1582 $db = &DBManagerFactory::getInstance();
1585 // Skipping ALTER TABLE [table] DROP PRIMARY KEY because primary keys are not being copied
1586 // over to the temp tables
1587 if(strpos(strtoupper($query), 'DROP PRIMARY KEY') !== false) {
1588 logThis('Skipping DROP PRIMARY KEY verification');
1592 if ($dbType == 'mysql'){
1593 mysql_error(); // initialize errors
1597 if(!in_array($table, $newTables)) {
1601 logThis('creating temp table for ['.$table.']...');
1602 $q = "SHOW CREATE TABLE {$table}";
1603 $r = $db->query($q);
1604 $a = $db->fetchByAssoc($r);
1606 // rewrite DDL with _temp name
1607 $cleanQuery = cleanQuery($a['Create Table']);
1608 $tempTableQuery = str_replace("CREATE TABLE `{$table}`", "CREATE TABLE `{$table}__uw_temp`", $cleanQuery);
1609 $r2 = $db->query($tempTableQuery);
1611 // get sample data into the temp table to test for data/constraint conflicts
1612 logThis('inserting temp dataset...');
1613 $q3 = "INSERT INTO `{$table}__uw_temp` SELECT * FROM `{$table}` LIMIT 10";
1614 $r3 = $db->query($q3, false, "Preflight Failed for: {$query}");
1616 // test the query on the test table
1617 logThis('testing query: ['.$query.']');
1618 $tempTableTestQuery = str_replace("ALTER TABLE `{$table}`", "ALTER TABLE `{$table}__uw_temp`", $query);
1619 if (strpos($tempTableTestQuery, 'idx') === false) {
1620 if(isRunningAgainstTrueTable($tempTableTestQuery)) {
1621 $error = getFormattedError('Could not use a temp table to test query!', $query);
1625 logThis('testing query on temp table: ['.$tempTableTestQuery.']');
1626 $r4 = $db->query($tempTableTestQuery, false, "Preflight Failed for: {$query}");
1629 // test insertion of an index on a table
1630 $tempTableTestQuery_idx = str_replace("ADD INDEX `idx_", "ADD INDEX `temp_idx_", $tempTableTestQuery);
1631 logThis('testing query on temp table: ['.$tempTableTestQuery_idx.']');
1632 $r4 = $db->query($tempTableTestQuery_idx, false, "Preflight Failed for: {$query}");
1634 $mysqlError = mysql_error(); // empty on no-errors
1635 if(!empty($mysqlError)) {
1636 logThis('*** ERROR: query failed: '.$mysqlError);
1637 $error = getFormattedError($mysqlError, $query);
1641 // clean up moved to end of preflight
1645 logThis('mssql found: skipping test query - ['.$query.']');
1649 logThis('Oracle found: skipping test query - ['.$query.']');
1653 logThis($table . ' is a new table');
1656 logThis('verification done.');
1661 * Tests an CREATE TABLE query
1662 * @param string table The table name to get DDL
1663 * @param string dbType MySQL, MSSQL, etc.
1664 * @param string query The query to test.
1665 * @return string Non-empty if error found
1667 function testQueryCreate($table, $dbType, $query, &$newTables) {
1668 logThis('verifying CREATE statement...');
1671 $db = &DBManagerFactory::getInstance();
1677 // rewrite DDL with _temp name
1678 logThis('testing query: ['.$query.']');
1679 $tempTableQuery = str_replace("CREATE TABLE `{$table}`", "CREATE TABLE `{$table}__uw_temp`", $query);
1681 if(isRunningAgainstTrueTable($tempTableQuery)) {
1682 $error = getFormattedError('Could not use a temp table to test query!', $query);
1686 $r4 = $db->query($tempTableQuery, false, "Preflight Failed for: {$query}");
1688 $error = mysql_error(); // empty on no-errors
1689 if(!empty($error)) {
1690 logThis('*** ERROR: query failed.');
1691 $error = getFormattedError($error, $query);
1694 // check if table exists
1695 logThis('testing for table: '.$table);
1696 $q1 = "DESC `{$table}`";
1697 $r1 = $db->query($q1);
1699 $mysqlError = mysql_error();
1700 if(empty($mysqlError)) {
1701 logThis('*** ERROR: table already exists!: '.$table);
1702 $error = getFormattedError('table exists', $query);
1705 logThis('NEW TABLE: '.$query);
1706 $newTables[] = $table;
1711 logThis('mssql found: skipping test query - ['.$query.']');
1715 logThis('Oracle found: skipping test query - ['.$query.']');
1722 * Tests an DELETE FROM query
1723 * @param string table The table name to get DDL
1724 * @param string dbType MySQL, MSSQL, etc.
1725 * @param string query The query to test.
1726 * @return string Non-empty if error found
1728 function testQueryDelete($table, $dbType, $query) {
1729 logThis('verifying DELETE statements');
1732 $db = &DBManagerFactory::getInstance();
1740 logThis('creating temp table...');
1741 $q = "SHOW CREATE TABLE {$table}";
1742 $r = $db->query($q);
1743 $a = $db->fetchByAssoc($r);
1745 // rewrite DDL with _temp name
1746 $cleanQuery = cleanQuery($a['Create Table']);
1747 $tempTableQuery = str_replace("CREATE TABLE `{$table}`", "CREATE TABLE `{$table}__uw_temp`", $cleanQuery);
1748 $r2 = $db->query($tempTableQuery);
1750 // get sample data into the temp table to test for data/constraint conflicts
1751 logThis('inserting temp dataset...');
1752 $q3 = "INSERT INTO `{$table}__uw_temp` SELECT * FROM `{$table}` LIMIT 10";
1753 $r3 = $db->query($q3);
1755 // test the query on the test table
1756 logThis('testing query: ['.$query.']');
1757 $tempTableTestQuery = str_replace("DELETE FROM `{$table}`", "DELETE FROM `{$table}__uw_temp`", $query);
1759 if(isRunningAgainstTrueTable($tempTableTestQuery)) {
1760 $error = getFormattedError('Could not use a temp table to test query!', $tempTableTestQuery);
1764 $r4 = $db->query($tempTableTestQuery, false, "Preflight Failed for: {$query}");
1765 $error = mysql_error(); // empty on no-errors
1766 if(!empty($error)) {
1767 logThis('*** ERROR: query failed.');
1768 $error = getFormattedError($error, $query);
1773 logThis('mssql found: skipping test query - ['.$query.']');
1777 logThis('Oracle found: skipping test query - ['.$query.']');
1780 logThis('verification done.');
1785 * Tests a DROP TABLE query
1788 function testQueryDrop($table, $dbType, $query) {
1789 logThis('verifying DROP TABLE statement');
1792 $db = &DBManagerFactory::getInstance();
1800 logThis('creating temp table...');
1801 $q = "SHOW CREATE TABLE {$table}";
1802 $r = $db->query($q);
1803 $a = $db->fetchByAssoc($r);
1805 // rewrite DDL with _temp name
1806 $cleanQuery = cleanQuery($a['Create Table']);
1807 $tempTableQuery = str_replace("CREATE TABLE `{$table}`", "CREATE TABLE `{$table}__uw_temp`", $cleanQuery);
1808 $r2 = $db->query($tempTableQuery);
1810 // get sample data into the temp table to test for data/constraint conflicts
1811 logThis('inserting temp dataset...');
1812 $query = stripQuotesUW($query, $table);
1813 $q3 = "INSERT INTO `{$table}__uw_temp` SELECT * FROM `{$table}` LIMIT 10";
1814 $r3 = $db->query($q3);
1816 // test the query on the test table
1817 logThis('testing query: ['.$query.']');
1818 $tempTableTestQuery = str_replace("DROP TABLE `{$table}`", "DROP TABLE `{$table}__uw_temp`", $query);
1820 // make sure the test query is running against a temp table
1821 if(isRunningAgainstTrueTable($tempTableTestQuery)) {
1822 $error = getFormattedError('Could not use a temp table to test query!', $tempTableTestQuery);
1826 $r4 = $db->query($tempTableTestQuery, false, "Preflight Failed for: {$query}");
1827 $error = mysql_error(); // empty on no-errors
1828 if(!empty($error)) {
1829 logThis('*** ERROR: query failed.');
1830 $error = getFormattedError($error, $query);
1835 logThis('mssql found: skipping test query - ['.$query.']');
1839 logThis('Oracle found: skipping test query - ['.$query.']');
1842 logThis('verification done.');
1847 * Tests an INSERT INTO query
1848 * @param string table The table name to get DDL
1849 * @param string dbType MySQL, MSSQL, etc.
1850 * @param string query The query to test.
1851 * @return string Non-empty if error found
1853 function testQueryInsert($table, $dbType, $query) {
1854 logThis('verifying INSERT statement...');
1857 $db = &DBManagerFactory::getInstance();
1865 $q = "SHOW CREATE TABLE {$table}";
1866 $r = $db->query($q);
1867 $a = $db->fetchByAssoc($r);
1869 // rewrite DDL with _temp name
1870 $cleanQuery = cleanQuery($a['Create Table']);
1871 $tempTableQuery = str_replace("CREATE TABLE `{$table}`", "CREATE TABLE `{$table}__uw_temp`", $cleanQuery);
1872 $r2 = $db->query($tempTableQuery);
1874 // test the query on the test table
1875 logThis('testing query: ['.$query.']');
1876 $tempTableTestQuery = str_replace("INSERT INTO `{$table}`", "INSERT INTO `{$table}__uw_temp`", $query);
1878 // make sure the test query is running against a temp table
1879 if(isRunningAgainstTrueTable($tempTableTestQuery)) {
1880 $error = getFormattedError('Could not use a temp table to test query!', $tempTableTestQuery);
1884 $r4 = $db->query($tempTableTestQuery, false, "Preflight Failed for: {$query}");
1885 $error = mysql_error(); // empty on no-errors
1886 if(!empty($error)) {
1887 logThis('*** ERROR: query failed.');
1888 $error = getFormattedError($error, $query);
1893 logThis('mssql found: skipping test query - ['.$query.']');
1897 logThis('Oracle found: skipping test query - ['.$query.']');
1900 logThis('verification done.');
1906 * Tests an UPDATE TABLE query
1907 * @param string table The table name to get DDL
1908 * @param string dbType MySQL, MSSQL, etc.
1909 * @param string query The query to test.
1910 * @return string Non-empty if error found
1912 function testQueryUpdate($table, $dbType, $query) {
1913 logThis('verifying UPDATE TABLE statement...');
1916 $db = &DBManagerFactory::getInstance();
1924 $q = "SHOW CREATE TABLE {$table}";
1925 $r = $db->query($q);
1926 $a = $db->fetchByAssoc($r);
1928 // rewrite DDL with _temp name
1929 $cleanQuery = cleanQuery($a['Create Table']);
1930 $tempTableQuery = str_replace("CREATE TABLE `{$table}`", "CREATE TABLE `{$table}__uw_temp`", $cleanQuery);
1931 $r2 = $db->query($tempTableQuery);
1933 // get sample data into the temp table to test for data/constraint conflicts
1934 logThis('inserting temp dataset...');
1935 $q3 = "INSERT INTO `{$table}__uw_temp` SELECT * FROM `{$table}` LIMIT 10";
1936 $r3 = $db->query($q3, false, "Preflight Failed for: {$query}");
1938 // test the query on the test table
1939 logThis('testing query: ['.$query.']');
1940 $tempTableTestQuery = str_replace("UPDATE `{$table}`", "UPDATE `{$table}__uw_temp`", $query);
1942 // make sure the test query is running against a temp table
1943 if(isRunningAgainstTrueTable($tempTableTestQuery)) {
1944 $error = getFormattedError('Could not use a temp table to test query!', $tempTableTestQuery);
1948 $r4 = $db->query($tempTableTestQuery, false, "Preflight Failed for: {$query}");
1949 $error = mysql_error(); // empty on no-errors
1950 if(!empty($error)) {
1951 logThis('*** ERROR: query failed.');
1952 $error = getFormattedError($error, $query);
1960 logThis('Oracle found: skipping test query - ['.$query.']');
1963 logThis('verification done.');
1969 * strip queries of single and double quotes
1971 function stripQuotesUW($query, $table) {
1974 $start = strpos($query, $table);
1976 if(substr($query, ($start - 1), 1) != ' ') {
1977 $queryStrip = substr($query, 0, ($start-2));
1978 $queryStrip .= " {$table} ";
1979 $queryStrip .= substr($query, ($start + strlen($table) + 2), strlen($query));
1982 return (empty($queryStrip)) ? $query : $queryStrip;
1986 * ensures that a __UW_TEMP table test SQL is running against a temp table, not the real thing
1987 * @param string query
1988 * @return bool false if it is a good query
1990 function isRunningAgainstTrueTable($query) {
1991 $query = strtoupper($query);
1992 if(strpos($query, '__UW_TEMP') === false) {
1993 logThis('***ERROR: test query is NOT running against a temp table!!!! -> '.$query);
2008 * cleans up temp tables created during schema test phase
2010 function testCleanUp($dbType) {
2011 logThis('Cleaning up temporary tables...');
2015 $db = &DBManagerFactory::getInstance();
2021 $q = 'SHOW TABLES LIKE "%__uw_temp"';
2022 $r = $db->query($q, false, "Preflight Failed for: {$q}");
2024 // using raw mysql_command to use integer index
2025 while($a = $db->fetchByAssoc($r)) {
2026 logThis('Dropping table: '.$a[0]);
2027 $qClean = "DROP TABLE {$a[0]}";
2028 $rClean = $db->query($qClean);
2038 logThis('Done cleaning up temp tables.');
2043 function getFormattedError($error, $query) {
2044 $error = "<div><b>".$error;
2045 $error .= "</b>::{$query}</div>";
2053 * parses a query finding the table name
2054 * @param string query The query
2055 * @return string table The table
2057 function getTableFromQuery($query) {
2058 $standardQueries = array('ALTER TABLE', 'DROP TABLE', 'CREATE TABLE', 'INSERT INTO', 'UPDATE', 'DELETE FROM');
2059 $query = preg_replace("/[^A-Za-z0-9\_\s]/", "", $query);
2060 $query = trim(str_replace($standardQueries, '', $query));
2062 $firstSpc = strpos($query, " ");
2063 $end = ($firstSpc > 0) ? $firstSpc : strlen($query);
2064 $table = substr($query, 0, $end);
2071 function preLicenseCheck() {
2072 require_once('modules/UpgradeWizard/uw_files.php');
2074 global $sugar_config;
2075 global $mod_strings;
2076 global $sugar_version;
2078 if(!isset($sugar_version) || empty($sugar_version)) {
2079 require_once('./sugar_version.php');
2082 if(!isset($_SESSION['unzip_dir']) || empty($_SESSION['unzip_dir'])) {
2083 logThis('unzipping files in upgrade archive...');
2085 $base_upgrade_dir = $sugar_config['upload_dir'] . "/upgrades";
2086 $base_tmp_upgrade_dir = "$base_upgrade_dir/temp";
2088 //also come up with mechanism to read from upgrade-progress file
2089 if(!isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !is_file($_SESSION['install_file'])) {
2091 if ($handle = opendir(clean_path($sugar_config['upload_dir']))) {
2092 while (false !== ($file = readdir($handle))) {
2093 if($file !="." && $file !="..") {
2094 $far = explode(".",$file);
2095 if($far[sizeof($far)-1] == 'zip') {
2096 echo $sugar_config['upload_dir'].'/'.$file;
2097 $_SESSION['install_file'] = $sugar_config['upload_dir'].'/'.$file;
2103 if (file_exists(clean_path($base_tmp_upgrade_dir)) && $handle = opendir(clean_path($base_tmp_upgrade_dir))) {
2104 while (false !== ($file = readdir($handle))) {
2105 if($file !="." && $file !="..") {
2106 //echo $base_tmp_upgrade_dir."/".$file.'</br>';
2107 if(is_file($base_tmp_upgrade_dir."/".$file."/manifest.php")){
2108 require_once($base_tmp_upgrade_dir."/".$file."/manifest.php");
2109 $package_name= $manifest['copy_files']['from_dir'];
2110 //echo file_exists($base_tmp_upgrade_dir."/".$file."/".$package_name).'</br>';
2111 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")){
2112 //echo 'Yeah this the directory '. $base_tmp_upgrade_dir."/".$file;
2113 $unzip_dir = $base_tmp_upgrade_dir."/".$file;
2114 if(file_exists($sugar_config['upload_dir'].'/upgrades/patch/'.$package_name.'.zip')){
2115 $_SESSION['install_file'] = $sugar_config['upload_dir'].'/upgrades/patch/'.$package_name.'.zip';
2124 if(!isset($_SESSION['install_file']) || empty($_SESSION['install_file'])){
2127 echo 'Upload File not found so redirecting to Upgrade Start ';
2128 $redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
2129 echo '<form name="redirect" action="' .$redirect_new_wizard. '" method="POST">';
2130 $upgrade_directories_not_found =<<<eoq
2131 <table cellpadding="3" cellspacing="0" border="0">
2133 <th colspan="2" align="left">
2134 <span class='error'><b>'Upload file missing or has been deleted. Refresh the page to go back to UpgradeWizard start'</b></span>
2139 $uwMain = $upgrade_directories_not_found;
2142 $install_file = urldecode( $_SESSION['install_file'] );
2144 if(empty($unzip_dir)){
2145 $unzip_dir = mk_temp_dir( $base_tmp_upgrade_dir );
2147 $zip_from_dir = ".";
2149 $zip_force_copy = array();
2152 logThis('Could not create a temporary directory using mk_temp_dir( $base_tmp_upgrade_dir )');
2153 die($mod_strings['ERR_UW_NO_CREATE_TMP_DIR']);
2156 //double check whether unzipped .
2157 if(file_exists($unzip_dir ."/scripts") && file_exists($unzip_dir."/manifest.php")){
2161 unzip( $install_file, $unzip_dir );
2164 // assumption -- already validated manifest.php at time of upload
2165 require_once( "$unzip_dir/manifest.php" );
2167 if( isset( $manifest['copy_files']['from_dir'] ) && $manifest['copy_files']['from_dir'] != "" ){
2168 $zip_from_dir = $manifest['copy_files']['from_dir'];
2170 if( isset( $manifest['copy_files']['to_dir'] ) && $manifest['copy_files']['to_dir'] != "" ){
2171 $zip_to_dir = $manifest['copy_files']['to_dir'];
2173 if( isset( $manifest['copy_files']['force_copy'] ) && $manifest['copy_files']['force_copy'] != "" ){
2174 $zip_force_copy = $manifest['copy_files']['force_copy'];
2176 if( isset( $manifest['version'] ) ){
2177 $version = $manifest['version'];
2179 if( !is_writable( "config.php" ) ){
2180 return $mod_strings['ERR_UW_CONFIG'];
2183 $_SESSION['unzip_dir'] = clean_path($unzip_dir);
2184 $_SESSION['zip_from_dir'] = clean_path($zip_from_dir);
2185 logThis('unzip done.');
2187 $unzip_dir = $_SESSION['unzip_dir'];
2188 $zip_from_dir = $_SESSION['zip_from_dir'];
2191 //check if $_SESSION['unzip_dir'] and $_SESSION['zip_from_dir'] exist
2192 if(!isset($_SESSION['unzip_dir']) || !file_exists($_SESSION['unzip_dir'])
2193 || !isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !file_exists($_SESSION['install_file'])){
2197 echo 'Upload File not found so redirecting to Upgrade Start ';
2198 $redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
2199 echo '<form name="redirect" action="' .$redirect_new_wizard. '" method="POST">';
2200 $upgrade_directories_not_found =<<<eoq
2201 <table cellpadding="3" cellspacing="0" border="0">
2203 <th colspan="2" align="left">
2204 <span class='error'><b>'Upload file missing or has been deleted. Refresh the page to go back to UpgradeWizard start'</b></span>
2209 $uwMain = $upgrade_directories_not_found;
2213 $parserFiles = array();
2215 if(file_exists(clean_path($unzip_dir.'/'.$zip_from_dir."/include/SugarFields"))) {
2216 $parserFiles = findAllFiles(clean_path($unzip_dir.'/'.$zip_from_dir."/include/SugarFields"), $parserFiles);
2219 $cwd = clean_path(getcwd());
2220 foreach($parserFiles as $file) {
2221 $srcFile = clean_path($file);
2222 //$targetFile = clean_path(getcwd() . '/' . $srcFile);
2223 if (strpos($srcFile,".svn") !== false) {
2227 $targetFile = str_replace(clean_path($unzip_dir.'/'.$zip_from_dir), $cwd, $srcFile);
2229 if(!is_dir(dirname($targetFile))) {
2230 mkdir_recursive(dirname($targetFile)); // make sure the directory exists
2233 if(!file_exists($targetFile))
2235 // handle sugar_version.php
2236 // C.L. - Added check for portal directory
2237 if(strpos($targetFile, 'sugar_version.php') !== false && !preg_match('/\/portal\/sugar_version\.php$/i', $targetFile)) {
2238 logThis('Skipping "sugar_version.php" - file copy will occur at end of successful upgrade', $path);
2239 $_SESSION['sugar_version_file'] = $srcFile;
2243 //logThis('Copying file to destination: ' . $targetFile);
2245 if(!copy($srcFile, $targetFile)) {
2246 logThis('*** ERROR: could not copy file: ' . $targetFile);
2248 $copiedFiles[] = $targetFile;
2251 //logThis('Skipping file: ' . $targetFile);
2252 //$skippedFiles[] = $targetFile;
2257 //Also copy the SugarMerge files
2258 if(file_exists(clean_path($unzip_dir.'/'.$zip_from_dir."/UpgradeWizard510Files"))) {
2259 $parserFiles = findAllFiles(clean_path($unzip_dir.'/'.$zip_from_dir."/UpgradeWizard510Files"), $parserFiles);
2260 foreach($parserFiles as $file) {
2261 $srcFile = clean_path($file);
2262 //$targetFile = clean_path(getcwd() . '/' . $srcFile);
2263 if (strpos($srcFile,".svn") !== false) {
2267 $targetFile = str_replace(clean_path($unzip_dir.'/'.$zip_from_dir."/UpgradeWizard510Files"), $cwd, $srcFile);
2268 if(!is_dir(dirname($targetFile))) {
2269 mkdir_recursive(dirname($targetFile)); // make sure the directory exists
2271 logThis('updating UpgradeWizard code: '.$targetFile);
2272 copy_recursive($file, $targetFile);
2276 logThis ('is SugarConfig there '.file_exists(clean_path($unzip_dir.'/'.$zip_from_dir."/include/SugarObjects/SugarConfig.php")));
2277 if(file_exists(clean_path($unzip_dir.'/'.$zip_from_dir."/include/SugarObjects/SugarConfig.php"))) {
2278 $file = clean_path($unzip_dir.'/'.$zip_from_dir."/include/SugarObjects/SugarConfig.php");
2279 $destFile = str_replace(clean_path($unzip_dir.'/'.$zip_from_dir), $cwd, $file);
2280 if(!is_dir(dirname($destFile))) {
2281 mkdir_recursive(dirname($destFile)); // make sure the directory exists
2283 copy($file,$destFile);
2284 //also copy include utils array utils
2285 $file = clean_path($unzip_dir.'/'.$zip_from_dir."/include/utils/array_utils.php");
2286 $destFile = str_replace(clean_path($unzip_dir.'/'.$zip_from_dir), $cwd, $file);
2287 if(!is_dir(dirname($destFile))) {
2288 mkdir_recursive(dirname($destFile)); // make sure the directory exists
2290 copy($file,$destFile);
2295 function preflightCheck() {
2296 require_once('modules/UpgradeWizard/uw_files.php');
2298 global $sugar_config;
2299 global $mod_strings;
2300 global $sugar_version;
2302 if(!isset($sugar_version) || empty($sugar_version)) {
2303 require_once('./sugar_version.php');
2306 unset($_SESSION['rebuild_relationships']);
2307 unset($_SESSION['rebuild_extensions']);
2309 // don't bother if are rechecking
2310 $manualDiff = array();
2311 if(!isset($_SESSION['unzip_dir']) || empty($_SESSION['unzip_dir'])) {
2312 logThis('unzipping files in upgrade archive...');
2314 $base_upgrade_dir = $sugar_config['upload_dir'] . "/upgrades";
2315 $base_tmp_upgrade_dir = "$base_upgrade_dir/temp";
2317 //Following is if User logged out unexpectedly and then logged into UpgradeWizard again.
2318 //also come up with mechanism to read from upgrade-progress file.
2319 if(!isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !is_file($_SESSION['install_file'])) {
2320 if (file_exists(clean_path($base_tmp_upgrade_dir)) && $handle = opendir(clean_path($base_tmp_upgrade_dir))) {
2321 while (false !== ($file = readdir($handle))) {
2322 if($file !="." && $file !="..") {
2323 //echo $base_tmp_upgrade_dir."/".$file.'</br>';
2324 if(is_file($base_tmp_upgrade_dir."/".$file."/manifest.php")){
2325 require_once($base_tmp_upgrade_dir."/".$file."/manifest.php");
2326 $package_name= $manifest['copy_files']['from_dir'];
2327 //echo file_exists($base_tmp_upgrade_dir."/".$file."/".$package_name).'</br>';
2328 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")){
2329 //echo 'Yeah this the directory '. $base_tmp_upgrade_dir."/".$file;
2330 $unzip_dir = $base_tmp_upgrade_dir."/".$file;
2331 if(file_exists($sugar_config['upload_dir'].'/upgrades/patch/'.$package_name.'.zip')){
2332 $_SESSION['install_file'] = $sugar_config['upload_dir'].'/upgrades/patch/'.$package_name.'.zip';
2341 if(!isset($_SESSION['install_file']) || empty($_SESSION['install_file'])){
2344 echo 'Upload File not found so redirecting to Upgrade Start ';
2345 $redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
2346 echo '<form name="redirect" action="' .$redirect_new_wizard. '" method="POST">';
2347 $upgrade_directories_not_found =<<<eoq
2348 <table cellpadding="3" cellspacing="0" border="0">
2350 <th colspan="2" align="left">
2351 <span class='error'><b>'Upload file missing or has been deleted. Refresh the page to go back to UpgradeWizard start'</b></span>
2356 $uwMain = $upgrade_directories_not_found;
2360 $install_file = urldecode( $_SESSION['install_file'] );
2362 if(empty($unzip_dir)){
2363 $unzip_dir = mk_temp_dir( $base_tmp_upgrade_dir );
2365 $zip_from_dir = ".";
2367 $zip_force_copy = array();
2370 logThis('Could not create a temporary directory using mk_temp_dir( $base_tmp_upgrade_dir )');
2371 die($mod_strings['ERR_UW_NO_CREATE_TMP_DIR']);
2374 //double check whether unzipped .
2375 if(file_exists($unzip_dir ."/scripts") && file_exists($unzip_dir."/manifest.php")){
2379 unzip( $install_file, $unzip_dir );
2382 // assumption -- already validated manifest.php at time of upload
2383 require_once( "$unzip_dir/manifest.php" );
2385 if( isset( $manifest['copy_files']['from_dir'] ) && $manifest['copy_files']['from_dir'] != "" ){
2386 $zip_from_dir = $manifest['copy_files']['from_dir'];
2388 if( isset( $manifest['copy_files']['to_dir'] ) && $manifest['copy_files']['to_dir'] != "" ){
2389 $zip_to_dir = $manifest['copy_files']['to_dir'];
2391 if( isset( $manifest['copy_files']['force_copy'] ) && $manifest['copy_files']['force_copy'] != "" ){
2392 $zip_force_copy = $manifest['copy_files']['force_copy'];
2394 if( isset( $manifest['version'] ) ){
2395 $version = $manifest['version'];
2397 if( !is_writable( "config.php" ) ){
2398 return $mod_strings['ERR_UW_CONFIG'];
2401 $_SESSION['unzip_dir'] = clean_path($unzip_dir);
2402 $_SESSION['zip_from_dir'] = clean_path($zip_from_dir);
2404 //logThis('unzip done.');
2406 $unzip_dir = $_SESSION['unzip_dir'];
2407 $zip_from_dir = $_SESSION['zip_from_dir'];
2409 //check if $_SESSION['unzip_dir'] and $_SESSION['zip_from_dir'] exist
2410 if(!isset($_SESSION['unzip_dir']) || !file_exists($_SESSION['unzip_dir'])
2411 || !isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !file_exists($_SESSION['install_file'])){
2415 echo 'Upload File not found so redirecting to Upgrade Start ';
2416 $redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
2417 echo '<form name="redirect" action="' .$redirect_new_wizard. '" method="POST">';
2418 $upgrade_directories_not_found =<<<eoq
2419 <table cellpadding="3" cellspacing="0" border="0">
2421 <th colspan="2" align="left">
2422 <span class='error'><b>'Upload file missing or has been deleted. Refresh the page to go back to UpgradeWizard start'</b></span>
2427 $uwMain = $upgrade_directories_not_found;
2430 //copy minimum required files
2431 fileCopy('include/utils/sugar_file_utils.php');
2434 if(file_exists('include/utils/file_utils.php')){
2437 $upgradeFiles = findAllFiles(clean_path("$unzip_dir/$zip_from_dir"), array());
2438 $cache_html_files= array();
2439 if(is_dir("{$GLOBALS['sugar_config']['cache_dir']}layout")){
2440 //$cache_html_files = findAllFilesRelative( "cache/layout", array());
2444 $md5_string = array();
2445 if(file_exists(clean_path(getcwd().'/files.md5'))){
2446 require(clean_path(getcwd().'/files.md5'));
2449 // file preflight checks
2450 logThis('verifying md5 checksums for files...');
2451 foreach($upgradeFiles as $file) {
2452 if(in_array(str_replace(clean_path("$unzip_dir/$zip_from_dir") . "/", '', $file), $uw_files))
2453 continue; // skip already loaded files
2455 if(strpos($file, '.md5'))
2456 continue; // skip md5 file
2458 // normalize file paths
2459 $file = clean_path($file);
2461 // check that we can move/delete the upgraded file
2462 if(!is_writable($file)) {
2463 $errors[] = $mod_strings['ERR_UW_FILE_NOT_WRITABLE'].": ".$file;
2465 // check that destination files are writable
2466 $destFile = getcwd().str_replace(clean_path($unzip_dir.'/'.$zip_from_dir), '', $file);
2468 if(is_file($destFile)) { // of course it needs to exist first...
2469 if(!is_writable($destFile)) {
2470 $errors[] = $mod_strings['ERR_UW_FILE_NOT_WRITABLE'].": ".$destFile;
2474 ///////////////////////////////////////////////////////////////////////
2476 // compare md5s and build up a manual merge list
2477 $targetFile = clean_path(".".str_replace(getcwd(),'',$destFile));
2479 if(is_file($destFile)) {
2480 if(strpos($targetFile, '.php')) {
2481 // handle PHP files that were hit with the security regex
2483 if(function_exists('sugar_fopen')){
2484 $fp = sugar_fopen($destFile, 'r');
2487 $fp = fopen($destFile, 'r');
2489 $filesize = filesize($destFile);
2491 $fileContents = stream_get_contents($fp);
2492 $targetMd5 = md5($fileContents);
2495 $targetMd5 = md5_file($destFile);
2499 if(isset($md5_string[$targetFile]) && $md5_string[$targetFile] != $targetMd5) {
2500 logThis('found a file with a differing md5: ['.$targetFile.']');
2501 $manualDiff[] = $destFile;
2504 ///////////////////////////////////////////////////////////////////////
2506 logThis('md5 verification done.');
2507 $errors['manual'] = $manualDiff;
2512 function fileCopy($file_path){
2513 if(file_exists(clean_path($_SESSION['unzip_dir'].'/'.$_SESSION['zip_from_dir'].'/'.$file_path))) {
2514 $file = clean_path($_SESSION['unzip_dir'].'/'.$_SESSION['zip_from_dir'].'/'.$file_path);
2515 $destFile = str_replace(clean_path($_SESSION['unzip_dir'].'/'.$_SESSION['zip_from_dir']), clean_path(getcwd()), $file);
2516 if(!is_dir(dirname($destFile))) {
2517 mkdir_recursive(dirname($destFile)); // make sure the directory exists
2519 copy_recursive($file,$destFile);
2522 function getChecklist($steps, $step) {
2523 global $mod_strings;
2525 $skip = array('start', 'cancel', 'uninstall','end');
2528 $ret = '<table cellpadding="3" cellspacing="4" border="0">';
2529 $ret .= '<tr><th colspan="3" align="left">'.$mod_strings['LBL_UW_CHECKLIST'].':</th></tr>';
2530 foreach($steps['desc'] as $k => $desc) {
2531 if(in_array($steps['files'][$j], $skip)) {
2536 //$status = "<span class='error'>{$mod_strings['LBL_UW_INCOMPLETE']}</span>";
2538 $desc_mod_post = '';
2540 if(isset($_SESSION['step'][$steps['files'][$k]]) && $_SESSION['step'][$steps['files'][$k]] == 'success') {
2541 //$status = $mod_strings['LBL_UW_COMPLETE'];
2545 if($k == $_REQUEST['step']) {
2546 //$status = $mod_strings['LBL_UW_IN_PROGRESS'];
2547 $desc_mod_pre = "<font color=blue><i>";
2548 $desc_mod_post = "</i></font>";
2551 $ret .= "<tr><td> </td><td><b>{$i}: {$desc_mod_pre}{$desc}{$desc_mod_post}</b></td>";
2552 $ret .= "<td id={$steps['files'][$j]}><i></i></td></tr>";
2560 function prepSystemForUpgrade() {
2561 global $sugar_config;
2562 global $sugar_flavor;
2563 global $mod_strings;
2565 global $base_upgrade_dir;
2566 global $base_tmp_upgrade_dir;
2568 ///////////////////////////////////////////////////////////////////////////////
2569 //// Make sure variables exist
2570 if(!isset($base_upgrade_dir) || empty($base_upgrade_dir)){
2571 $base_upgrade_dir = getcwd().'/'.$sugar_config['upload_dir'] . "upgrades";
2573 if(!isset($base_tmp_upgrade_dir) || empty($base_tmp_upgrade_dir)){
2574 $base_tmp_upgrade_dir = "$base_upgrade_dir/temp";
2576 if(!isset($subdirs) || empty($subdirs)){
2577 $subdirs = array('full', 'langpack', 'module', 'patch', 'theme', 'temp');
2580 $upgrade_progress_dir = getcwd().'/'.$GLOBALS['sugar_config']['upload_dir'].'upgrades/temp';
2581 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
2582 if(file_exists($upgrade_progress_file)){
2583 if(function_exists('get_upgrade_progress') && function_exists('didThisStepRunBefore')){
2584 if(didThisStepRunBefore('end')){
2585 include($upgrade_progress_file);
2586 unset($upgrade_config);
2587 unlink($upgrade_progress_file);
2592 // increase the cuttoff time to 1 hour
2593 ini_set("max_execution_time", "3600");
2595 // make sure dirs exist
2596 if($subdirs != null){
2597 foreach($subdirs as $subdir) {
2598 mkdir_recursive("$base_upgrade_dir/$subdir");
2601 // array of special scripts that are executed during (un)installation-- key is type of script, value is filename
2602 if(!defined('SUGARCRM_PRE_INSTALL_FILE')) {
2603 define('SUGARCRM_PRE_INSTALL_FILE', 'scripts/pre_install.php');
2604 define('SUGARCRM_POST_INSTALL_FILE', 'scripts/post_install.php');
2605 define('SUGARCRM_PRE_UNINSTALL_FILE', 'scripts/pre_uninstall.php');
2606 define('SUGARCRM_POST_UNINSTALL_FILE', 'scripts/post_uninstall.php');
2609 $script_files = array(
2610 "pre-install" => constant('SUGARCRM_PRE_INSTALL_FILE'),
2611 "post-install" => constant('SUGARCRM_POST_INSTALL_FILE'),
2612 "pre-uninstall" => constant('SUGARCRM_PRE_UNINSTALL_FILE'),
2613 "post-uninstall" => constant('SUGARCRM_POST_UNINSTALL_FILE'),
2616 // check that the upload limit is set to 6M or greater
2617 define('SUGARCRM_MIN_UPLOAD_MAX_FILESIZE_BYTES', 6 * 1024 * 1024); // 6 Megabytes
2618 $upload_max_filesize = ini_get('upload_max_filesize');
2619 $upload_max_filesize_bytes = return_bytes($upload_max_filesize);
2621 if($upload_max_filesize_bytes < constant('SUGARCRM_MIN_UPLOAD_MAX_FILESIZE_BYTES')) {
2622 $GLOBALS['log']->debug("detected upload_max_filesize: $upload_max_filesize");
2624 echo '<p class="error">'.$mod_strings['MSG_INCREASE_UPLOAD_MAX_FILESIZE'].' '.get_cfg_var('cfg_file_path')."</p>\n";
2628 if ( !function_exists('extractFile') ) {
2629 function extractFile($zip_file, $file_in_zip) {
2630 global $base_tmp_upgrade_dir;
2633 $absolute_base_tmp_upgrade_dir = clean_path($base_tmp_upgrade_dir);
2634 $relative_base_tmp_upgrade_dir = clean_path(str_replace(clean_path(getcwd()), '', $absolute_base_tmp_upgrade_dir));
2636 // mk_temp_dir expects relative pathing
2637 $my_zip_dir = mk_temp_dir($relative_base_tmp_upgrade_dir);
2639 unzip_file($zip_file, $file_in_zip, $my_zip_dir);
2641 return("$my_zip_dir/$file_in_zip");
2645 if ( !function_exists('extractManifest') ) {
2646 function extractManifest($zip_file) {
2647 logThis('extracting manifest.');
2648 return(extractFile($zip_file, "manifest.php"));
2652 if ( !function_exists('getInstallType') ) {
2653 function getInstallType($type_string) {
2656 $subdirs = array('full', 'langpack', 'module', 'patch', 'theme', 'temp');
2657 foreach($subdirs as $subdir) {
2658 if(preg_match("#/$subdir/#", $type_string)) {
2662 // return empty if no match
2667 function getImageForType($type) {
2672 $icon = SugarThemeRegistry::current()->getImage("Upgrade", "");
2675 $icon = SugarThemeRegistry::current()->getImage("LanguagePacks", "");
2678 $icon = SugarThemeRegistry::current()->getImage("ModuleLoader", "");
2681 $icon = SugarThemeRegistry::current()->getImage("PatchUpgrades", "");
2684 $icon = SugarThemeRegistry::current()->getImage("Themes", "");
2692 if ( !function_exists('getLanguagePackName') ) {
2693 function getLanguagePackName($the_file) {
2694 require_once("$the_file");
2695 if(isset($app_list_strings["language_pack_name"])) {
2696 return($app_list_strings["language_pack_name"]);
2702 function getUITextForType($type) {
2703 if($type == "full") {
2704 return("Full Upgrade");
2706 if($type == "langpack") {
2707 return("Language Pack");
2709 if($type == "module") {
2712 if($type == "patch") {
2715 if($type == "theme") {
2722 * @todo this function doesn't seemed to be used anymore; trying kill this off
2724 function run_upgrade_wizard_sql($script) {
2726 global $sugar_config;
2728 $db_type = $sugar_config['dbconfig']['db_type'];
2729 $script = str_replace("%db_type%", $db_type, $script);
2730 if(!run_sql_file("$unzip_dir/$script")) {
2731 die("Error running sql file: $unzip_dir/$script");
2735 if ( !function_exists('validate_manifest') ) {
2737 * Verifies a manifest from a patch or module to be compatible with the current Sugar version and flavor
2738 * @param array manifest Standard manifest array
2739 * @return string Error message, blank on success
2741 function validate_manifest($manifest) {
2742 logThis('validating manifest.php file');
2743 // takes a manifest.php manifest array and validates contents
2745 global $sugar_version;
2746 global $sugar_flavor;
2747 global $mod_strings;
2749 if(!isset($manifest['type'])) {
2750 return $mod_strings['ERROR_MANIFEST_TYPE'];
2753 $type = $manifest['type'];
2755 if(getInstallType("/$type/") == "") {
2756 return $mod_strings['ERROR_PACKAGE_TYPE']. ": '" . $type . "'.";
2759 if(isset($manifest['acceptable_sugar_versions'])) {
2760 $version_ok = false;
2761 $matches_empty = true;
2762 if(isset($manifest['acceptable_sugar_versions']['exact_matches'])) {
2763 $matches_empty = false;
2764 foreach($manifest['acceptable_sugar_versions']['exact_matches'] as $match) {
2765 if($match == $sugar_version) {
2770 if(!$version_ok && isset($manifest['acceptable_sugar_versions']['regex_matches'])) {
2771 $matches_empty = false;
2772 foreach($manifest['acceptable_sugar_versions']['regex_matches'] as $match) {
2773 if(preg_match("/$match/", $sugar_version)) {
2779 if(!$matches_empty && !$version_ok) {
2780 return $mod_strings['ERROR_VERSION_INCOMPATIBLE']."<br />".
2781 $mod_strings['ERR_UW_VERSION'].$sugar_version;
2785 if(isset($manifest['acceptable_sugar_flavors']) && sizeof($manifest['acceptable_sugar_flavors']) > 0) {
2787 foreach($manifest['acceptable_sugar_flavors'] as $match) {
2788 if($match == $sugar_flavor) {
2793 return $mod_strings['ERROR_FLAVOR_INCOMPATIBLE']."<br />".
2794 $mod_strings['ERR_UW_FLAVOR'].$sugar_flavor."<br />".
2795 $mod_strings['ERR_UW_FLAVOR_2'].$manifest['acceptable_sugar_flavors'][0];
2803 function unlinkUploadFiles() {
2805 // logThis('at unlinkUploadFiles()');
2807 // if(isset($_SESSION['install_file']) && !empty($_SESSION['install_file'])) {
2808 // $upload = $_SESSION['install_file'];
2810 // if(is_file($upload)) {
2811 // logThis('unlinking ['.$upload.']');
2812 // @unlink($upload);
2817 if ( !function_exists('unlinkTempFiles') ) {
2819 * deletes files created by unzipping a package
2821 function unlinkTempFiles() {
2822 global $sugar_config;
2825 logThis('at unlinkTempFiles()');
2827 $sugar_config['upload_dir']='cache/upload/';
2828 //if(isset($sugar_config['upload_dir']) && $sugar_config['upload_dir'] != null && $sugar_config['upload_dir']=='cache/upload/'){
2829 $tempDir = clean_path(getcwd().'/'.$sugar_config['upload_dir'].'upgrades/temp');
2832 $uploadDir = getcwd()."/".'cache/upload/';
2833 $tempDir = clean_path(getcwd().'/'.$uploadDir.'upgrades/temp');
2835 if(file_exists($tempDir) && is_dir($tempDir)){
2836 $files = findAllFiles($tempDir, array(), false);
2838 foreach($files as $file) {
2839 if(!is_dir($file)) {
2840 //logThis('unlinking ['.$file.']', $path);
2845 $files = findAllFiles($tempDir, array(), true);
2846 foreach($files as $dir) {
2848 //logThis('removing dir ['.$dir.']', $path);
2852 $cacheFile = "modules/UpgradeWizard/_persistence.php";
2853 if(is_file($cacheFile)) {
2854 logThis("Unlinking Upgrade cache file: '_persistence.php'", $path);
2855 @unlink($cacheFile);
2858 logThis("finished!");
2863 * finds all files in the passed path, but skips select directories
2864 * @param string dir Relative path
2865 * @param array the_array Collections of found files/dirs
2866 * @param bool include_dir True if we want to include directories in the
2867 * returned collection
2869 function uwFindAllFiles($dir, $the_array, $include_dirs=false, $skip_dirs=array(), $echo=false) {
2871 foreach($skip_dirs as $skipMe) {
2872 if(strpos(clean_path($dir), $skipMe) !== false) {
2879 while($f = $d->read()) {
2880 if($f == "." || $f == "..") { // skip *nix self/parent
2884 // for AJAX length count
2890 if(is_dir("$dir/$f")) {
2891 if($include_dirs) { // add the directory if flagged
2892 $the_array[] = clean_path("$dir/$f");
2896 $the_array = uwFindAllFiles("$dir/$f/", $the_array, $include_dirs, $skip_dirs, $echo);
2898 $the_array[] = clean_path("$dir/$f");
2910 * unset's UW's Session Vars
2912 function resetUwSession() {
2913 logThis('resetting $_SESSION');
2915 if(isset($_SESSION['committed']))
2916 unset($_SESSION['committed']);
2917 if(isset($_SESSION['sugar_version_file']))
2918 unset($_SESSION['sugar_version_file']);
2919 if(isset($_SESSION['upgrade_complete']))
2920 unset($_SESSION['upgrade_complete']);
2921 if(isset($_SESSION['allTables']))
2922 unset($_SESSION['allTables']);
2923 if(isset($_SESSION['alterCustomTableQueries']))
2924 unset($_SESSION['alterCustomTableQueries']);
2925 if(isset($_SESSION['skip_zip_upload']))
2926 unset($_SESSION['skip_zip_upload']);
2927 if(isset($_SESSION['sugar_version_file']))
2928 unset($_SESSION['sugar_version_file']);
2929 if(isset($_SESSION['install_file']))
2930 unset($_SESSION['install_file']);
2931 if(isset($_SESSION['unzip_dir']))
2932 unset($_SESSION['unzip_dir']);
2933 if(isset($_SESSION['zip_from_dir']))
2934 unset($_SESSION['zip_from_dir']);
2935 if(isset($_SESSION['overwrite_files']))
2936 unset($_SESSION['overwrite_files']);
2937 if(isset($_SESSION['schema_change']))
2938 unset($_SESSION['schema_change']);
2939 if(isset($_SESSION['uw_restore_dir']))
2940 unset($_SESSION['uw_restore_dir']);
2941 if(isset($_SESSION['step']))
2942 unset($_SESSION['step']);
2943 if(isset($_SESSION['files']))
2944 unset($_SESSION['files']);
2945 if(isset($_SESSION['Upgraded451Wizard'])){
2946 unset($_SESSION['Upgraded451Wizard']);
2948 if(isset($_SESSION['Initial_451to500_Step'])){
2949 unset($_SESSION['Initial_451to500_Step']);
2951 if(isset($_SESSION['license_shown']))
2952 unset($_SESSION['license_shown']);
2953 if(isset($_SESSION['sugarMergeRunResults']))
2954 unset($_SESSION['sugarMergeRunResults']);
2958 * runs rebuild scripts
2960 function UWrebuild() {
2964 //CCL - Comment this block out, it is called in end.php
2965 logThis('Rebuilding everything...', $path);
2966 require_once('modules/Administration/QuickRepairAndRebuild.php');
2967 $randc = new RepairAndClear();
2968 $randc->repairAndClearAll(array('clearAll'),array(translate('LBL_ALL_MODULES')), false, false);
2970 $query = "DELETE FROM versions WHERE name='Rebuild Extensions'";
2972 logThis('Registering rebuild record: '.$query, $path);
2973 logThis('Rebuild done.', $path);
2975 // insert a new database row to show the rebuild extensions is done
2976 $id = create_guid();
2977 $gmdate = gmdate('Y-m-d H:i:s');
2978 $date_entered = db_convert("'$gmdate'", 'datetime');
2979 $query = 'INSERT INTO versions (id, deleted, date_entered, date_modified, modified_user_id, created_by, name, file_version, db_version) '
2980 . "VALUES ('$id', '0', $date_entered, $date_entered, '1', '1', 'Rebuild Extensions', '4.0.0', '4.0.0')";
2982 logThis('Registering rebuild record in versions table: '.$query, $path);
2985 function getCustomTables($dbType) {
2988 $customTables = array();
2992 $query = "SHOW tables LIKE '%_cstm'";
2993 $result = $db->query($query);//, true, 'Error getting custom tables');
2994 while ($row = $db->fetchByAssoc($result)){
2995 $customTables[] = array_pop($row);
2999 return $customTables;
3002 function alterCustomTables($dbType, $customTables)
3007 while( $i < count($customTables) ) {
3008 $alterCustomTableSql[] = "ALTER TABLE " . $customTables[$i] . " CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci";
3015 return $alterCustomTableSql;
3018 function executeAlterCustomTablesSql($dbType, $queries) {
3021 foreach($queries as $query){
3023 logThis("Sending query: ".$query);
3024 if($db->dbType == 'oci8') {
3026 $query_result = $db->query($query);//.';', true, "An error has occured while performing db query. See log file for details.<br>");
3033 function getAllTables($dbType) {
3040 $query = "SHOW tables";
3041 $result = $db->query($query, true, 'Error getting custom tables');
3042 while ($row = $db->fetchByAssoc($result)){
3043 $tables[] = array_pop($row);
3050 function printAlterTableSql($tables)
3052 $alterTableSql = '';
3054 foreach($tables as $table)
3055 $alterTableSql .= "ALTER TABLE " . $table . " CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;" . "\n";
3057 return $alterTableSql;
3060 function executeConvertTablesSql($dbType, $tables) {
3063 foreach($tables as $table){
3064 $query = "ALTER TABLE " . $table . " CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci";
3066 logThis("Sending query: ".$query);
3067 if($db->dbType == 'oci8') {
3069 $query_result = $db->query($query);//.';', true, "An error has occured while performing db query. See log file for details.<br>");
3076 function testThis() {
3077 $files = uwFindAllFiles(getcwd().'/test', array());
3079 $out = "<table cellpadding='1' cellspacing='0' border='0'>\n";
3082 foreach($files as $file) {
3083 $relativeFile = clean_path(str_replace(getcwd().'/test', '', $file));
3084 $relativeFile = ($relativeFile{0} == '/') ? substr($relativeFile, 1, strlen($relativeFile)) : $relativeFile;
3086 $relativePath = dirname($relativeFile);
3088 if($relativePath == $priorPath) { // same dir, new file
3089 $out .= "<tr><td>".basename($relativeFile)."</td></tr>";
3090 $priorPath = $relativePath;
3104 function testThis2($dir, $id=0, $hide=false) {
3106 $dh = opendir($dir);
3109 $doHide = ($hide) ? 'none' : '';
3110 $out = "<div id='{$id}' style='display:{$doHide};'>";
3111 $out .= "<table cellpadding='1' cellspacing='0' border='0' style='border:0px solid #ccc'>\n";
3113 while($file = readdir($dh)) {
3114 if($file == '.' || $file == '..' || $file == 'CVS' || $file == '.cvsignore')
3117 if(is_dir($path.'/'.$file)) {
3118 $file = $path.'/'.$file;
3119 $newI = create_guid();
3120 $out .= "<tr><td valign='top'><a href='javascript:toggleNwFiles(\"{$newI}\");'><img border='0' src='".SugarThemeRegistry::current()->getImageURL('Workflow.gif')."'></a></td>\n";
3121 $out .= "<td valign='top'><b><a href='javascript:toggleNwFiles(\"{$newI}\");'>".basename($file)."</a></b></td></tr>";
3122 $out .= "<tr><td></td><td valign='top'>".testThis2($file, $newI, true)."</td></tr>";
3124 $out .= "<tr><td valign='top'> </td>\n";
3125 $out .= "<td valign='top'>".basename($file)."</td></tr>";
3129 $out .= "</tr></table>";
3140 function testThis3(&$files, $id, $hide, $previousPath = '') {
3141 if(!is_array($files) || empty($files))
3146 // expecting full path here
3147 foreach($files as $k => $file) {
3148 $file = str_replace(getcwd(), '', $file);
3149 $path = dirname($file);
3150 $fileName = basename($file);
3152 if($fileName == 'CVS' || $fileName == '.cvsignore')
3155 if($path == $previousPath) { // same directory
3156 // new row for each file
3157 $out .= "<tr><td valign='top' align='left'> </td>";
3158 $out .= "<td valign='top' align='left'>{$fileName}</td></tr>";
3159 } else { // new directory
3161 $out .= "<tr><td valign='top'><a href='javascript:toggleNwFiles(\"{$newI}\");'><img border='0' src='".SugarThemeRegistry::current()->getImageURL('Workflow.gif')."></a></td>\n";
3162 $out .= "<td valign='top'><b><a href='javascript:toggleNwFiles(\"{$newI}\");'>".$fileName."</a></b></td></tr>";
3163 $recurse = testThis3($files, $newI, true, $previousPath);
3164 $out .= "<tr><td></td><td valign='top'>".$recurse."</td></tr>";
3167 $previousPath = $path;
3169 $display = ($hide) ? 'none' : '';
3171 <div id="{$id}" style="display:{$display}">
3172 <table cellpadding='1' cellspacing='0' border='0' style='border:1px solid #ccc'>
3181 function testThis4($filePath, $fileNodes=array(), $fileName='') {
3182 $path = dirname($filePath);
3183 $file = basename($filePath);
3185 $exFile = explode('/', $path);
3187 foreach($exFile as $pathSegment) {
3188 if(is_array($fileNodes[$pathSegment])) { // path already processed
3190 } else { // newly found path
3191 $fileNodes[$pathSegment] = array();
3194 if($fileName != '') {
3195 $fileNodes[$pathSegment][] = $fileName;
3204 ///////////////////////////////////////////////////////////////////////////////
3205 //// SYSTEM CHECK FUNCTIONS
3207 * generates an array with all files in the SugarCRM root directory, skipping
3209 * @return array files Array of files with absolute paths
3211 function getFilesForPermsCheck() {
3212 global $sugar_config;
3214 logThis('Got JSON call to find all files...');
3215 $filesNotWritable = array();
3216 $filesNWPerms = array();
3218 // add directories here that should be skipped when doing file permissions checks (cache/upload is the nasty one)
3220 $sugar_config['upload_dir'],
3222 $files = uwFindAllFiles(getcwd(), array(), true, $skipDirs, true);
3227 * checks files for permissions
3228 * @param array files Array of files with absolute paths
3229 * @return string result of check
3231 function checkFiles($files, $echo=false) {
3232 global $mod_strings;
3233 $filesNotWritable = array();
3236 <a href='javascript:void(0); toggleNwFiles(\"filesNw\");'>{$mod_strings['LBL_UW_SHOW_NW_FILES']}</a>
3237 <div id='filesNw' style='display:none;'>
3238 <table cellpadding='3' cellspacing='0' border='0'>
3240 <th align='left'>{$mod_strings['LBL_UW_FILE']}</th>
3241 <th align='left'>{$mod_strings['LBL_UW_FILE_PERMS']}</th>
3242 <th align='left'>{$mod_strings['LBL_UW_FILE_OWNER']}</th>
3243 <th align='left'>{$mod_strings['LBL_UW_FILE_GROUP']}</th>
3246 $isWindows = is_windows();
3247 foreach($files as $file) {
3250 if(!is_writable_windows($file)) {
3251 logThis('WINDOWS: File ['.$file.'] not readable - saving for display');
3252 // don't warn yet - we're going to use this to check against replacement files
3253 // aw: commented out; it's a hack to allow upgrade wizard to continue on windows... will fix later
3254 /*$filesNotWritable[$i] = $file;
3255 $filesNWPerms[$i] = substr(sprintf('%o',fileperms($file)), -4);
3256 $filesOut .= "<tr>".
3257 "<td><span class='error'>{$file}</span></td>".
3258 "<td>{$filesNWPerms[$i]}</td>".
3259 "<td>".$mod_strings['ERR_UW_CANNOT_DETERMINE_USER']."</td>".
3260 "<td>".$mod_strings['ERR_UW_CANNOT_DETERMINE_GROUP']."</td>".
3264 if(!is_writable($file)) {
3265 logThis('File ['.$file.'] not writable - saving for display');
3266 // don't warn yet - we're going to use this to check against replacement files
3267 $filesNotWritable[$i] = $file;
3268 $filesNWPerms[$i] = substr(sprintf('%o',fileperms($file)), -4);
3269 $owner = posix_getpwuid(fileowner($file));
3270 $group = posix_getgrgid(filegroup($file));
3271 $filesOut .= "<tr>".
3272 "<td><span class='error'>{$file}</span></td>".
3273 "<td>{$filesNWPerms[$i]}</td>".
3274 "<td>".$owner['name']."</td>".
3275 "<td>".$group['name']."</td>".
3282 $filesOut .= '</table></div>';
3284 $errors['files']['filesNotWritable'] = (count($filesNotWritable) > 0) ? true : false;
3285 if(count($filesNotWritable) < 1) {
3286 $filesOut = "{$mod_strings['LBL_UW_FILE_NO_ERRORS']}";
3292 function deletePackageOnCancel(){
3293 global $mod_strings;
3294 global $sugar_config;
3295 logThis('running delete');
3296 if(!isset($_SESSION['install_file']) || ($_SESSION['install_file'] == "")) {
3297 logThis('ERROR: trying to delete non-existent file: ['.$_REQUEST['install_file'].']');
3298 $error = $mod_strings['ERR_UW_NO_FILE_UPLOADED'];
3300 // delete file in upgrades/patch
3301 $delete_me = urldecode( $_SESSION['install_file'] );
3302 if(@unlink($delete_me)) {
3303 //logThis('unlinking: '.$delete_me);
3304 $out = basename($delete_me).$mod_strings['LBL_UW_FILE_DELETED'];
3306 logThis('ERROR: could not delete ['.$delete_me.']');
3307 $error = $mod_strings['ERR_UW_FILE_NOT_DELETED'].$delete_me;
3310 // delete file in cache/upload
3311 $fileS = explode('/', $delete_me);
3313 $fileName = (isset($fileS[$c-1]) && !empty($fileS[$c-1])) ? $fileS[$c-1] : $fileS[$c-2];
3314 $deleteUpload = getcwd().'/'.$sugar_config['upload_dir'].$fileName;
3315 logThis('Trying to delete '.$deleteUpload);
3316 if(!@unlink($deleteUpload)) {
3317 logThis('ERROR: could not delete: ['.$deleteUpload.']');
3318 $error = $mod_strings['ERR_UW_FILE_NOT_DELETED'].$sugar_config['upload_dir'].$fileName;
3320 if(!empty($error)) {
3321 $out = "<b><span class='error'>{$error}</span></b><br />";
3326 function parseAndExecuteSqlFile($sqlScript,$forStepQuery='',$resumeFromQuery=''){
3327 global $sugar_config;
3328 $alterTableSchema = '';
3329 $sqlErrors = array();
3330 if(!isset($_SESSION['sqlSkippedQueries'])){
3331 $_SESSION['sqlSkippedQueries'] = array();
3333 $db = & DBManagerFactory::getInstance();
3335 if($sugar_config['dbconfig']['db_type'] == 'mysql') {
3338 if($sugar_config['dbconfig']['db_type'] == 'oci8'){
3339 $db->query("CREATE OR REPLACE FUNCTION blob_to_clob (blob_in IN BLOB)
3343 v_varchar VARCHAR2(32767);
3344 v_start PLS_INTEGER := 1;
3345 v_buffer PLS_INTEGER := 32767;
3347 DBMS_LOB.CREATETEMPORARY(v_clob, TRUE);
3349 FOR i IN 1..CEIL(DBMS_LOB.GETLENGTH(blob_in) / v_buffer)
3352 v_varchar := UTL_RAW.CAST_TO_VARCHAR2(DBMS_LOB.SUBSTR(blob_in, v_buffer, v_start));
3354 DBMS_LOB.WRITEAPPEND(v_clob, LENGTH(v_varchar), v_varchar);
3356 v_start := v_start + v_buffer;
3361 END blob_to_clob;");
3363 if(strpos($resumeFromQuery,",") != false){
3364 $resumeFromQuery = explode(",",$resumeFromQuery);
3365 if(is_array($resumeFromQuery)){
3366 //print_r('RES ARRAY '.$resumeFromQuery[0].'</br>');
3369 if(file_exists($sqlScript)) {
3370 $fp = fopen($sqlScript, 'r');
3371 $contents = stream_get_contents($fp);
3372 $anyScriptChanges =$contents;
3373 $resumeAfterFound = false;
3377 while($line = fgets($fp)) {
3378 if(strpos($line, '--') === false) {
3379 $completeLine .= " ".trim($line);
3380 if(strpos($line, ';') !== false) {
3382 $query = str_replace(';','',$completeLine);
3383 //if resume from query is not null then find out from where
3384 //it should start executing the query.
3386 if($query != null && $resumeFromQuery != null){
3387 if(!$resumeAfterFound){
3388 if(strpos($query,",") != false){
3389 $queArray = array();
3390 $queArray = explode(",",$query);
3391 for($i=0;$i<sizeof($resumeFromQuery);$i++){
3392 if(strcmp(strtolower(trim($resumeFromQuery[$i])),strtolower(trim($queArray[$i])))==0){
3393 //echo 'mat found '.$queArray[$i].'</br>';
3394 $resumeAfterFound = true;
3397 $resumeAfterFound = false;
3403 elseif(strcmp(strtolower(trim($resumeFromQuery)),strtolower(trim($query)))==0){
3404 $resumeAfterFound = true;
3407 if($resumeAfterFound){
3410 // if $count=1 means it is just found so skip the query. Run the next one
3411 if($query != null && $resumeAfterFound && $count >1){
3415 $tableName = getAlterTable($query);
3416 if(!empty($tableName))
3418 $db->query('ALTER TABLE '.$tableName.' DISABLE KEYS');
3422 if($db->checkError()){
3423 //put in the array to use later on
3424 $_SESSION['sqlSkippedQueries'][] = $query;
3426 if(!empty($tableName))
3428 $db->query('ALTER TABLE '.$tableName.' ENABLE KEYS');
3430 $progQuery[$forStepQuery]=$query;
3431 post_install_progress($progQuery,$action='set');
3434 elseif($query != null){
3438 $tableName = getAlterTable($query);
3439 if(!empty($tableName))
3441 $db->query('ALTER TABLE '.$tableName.' DISABLE KEYS');
3445 if(!empty($tableName))
3447 $db->query('ALTER TABLE '.$tableName.' ENABLE KEYS');
3449 $progQuery[$forStepQuery]=$query;
3450 post_install_progress($progQuery,$action='set');
3451 if($db->checkError()){
3452 //put in the array to use later on
3453 $_SESSION['sqlSkippedQueries'][] = $query;
3464 function getAlterTable($query){
3465 $query = strtolower($query);
3466 if (preg_match("/^\s*alter\s+table\s+/", $query)) {
3467 $sqlArray = explode(" ", $query);
3468 $key = array_search('table', $sqlArray);
3469 return $sqlArray[($key+1)];
3475 function set_upgrade_vars(){
3476 logThis('setting session variables...');
3477 $upgrade_progress_dir = getcwd().'/'.$GLOBALS['sugar_config']['upload_dir'].'upgrades/temp';
3478 if(!is_dir($upgrade_progress_dir)){
3479 mkdir_recursive($upgrade_progress_dir);
3481 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3482 if(file_exists($upgrade_progress_file)){
3483 include($upgrade_progress_file);
3486 fopen($upgrade_progress_file, 'w+');
3488 if(!isset($upgrade_config) || $upgrade_config == null){
3489 $upgrade_config = array();
3490 $upgrade_config[1]['upgrade_vars']=array();
3492 if(isset($upgrade_config[1]) && isset($upgrade_config[1]['upgrade_vars']) && !is_array($upgrade_config[1]['upgrade_vars'])){
3493 $upgrade_config[1]['upgrade_vars'] = array();
3496 if(!isset($upgrade_vars) || $upgrade_vars == NULL){
3497 $upgrade_vars = array();
3499 if(isset($_SESSION['unzip_dir']) && !empty($_SESSION['unzip_dir']) && file_exists($_SESSION['unzip_dir'])){
3500 $upgrade_vars['unzip_dir']=$_SESSION['unzip_dir'];
3502 if(isset($_SESSION['install_file']) && !empty($_SESSION['install_file']) && file_exists($_SESSION['install_file'])){
3503 $upgrade_vars['install_file']=$_SESSION['install_file'];
3505 if(isset($_SESSION['Upgraded451Wizard']) && !empty($_SESSION['Upgraded451Wizard'])){
3506 $upgrade_vars['Upgraded451Wizard']=$_SESSION['Upgraded451Wizard'];
3508 if(isset($_SESSION['license_shown']) && !empty($_SESSION['license_shown'])){
3509 $upgrade_vars['license_shown']=$_SESSION['license_shown'];
3511 if(isset($_SESSION['Initial_451to500_Step']) && !empty($_SESSION['Initial_451to500_Step'])){
3512 $upgrade_vars['Initial_451to500_Step']=$_SESSION['Initial_451to500_Step'];
3514 if(isset($_SESSION['zip_from_dir']) && !empty($_SESSION['zip_from_dir'])){
3515 $upgrade_vars['zip_from_dir']=$_SESSION['zip_from_dir'];
3517 //place into the upgrade_config array and rewrite config array only if new values are being inserted
3518 if(isset($upgrade_vars) && $upgrade_vars != null && sizeof($upgrade_vars) > 0){
3519 foreach($upgrade_vars as $key=>$val){
3520 if($key != null && $val != null){
3521 $upgrade_config[1]['upgrade_vars'][$key]=$upgrade_vars[$key];
3524 ksort($upgrade_config);
3525 if(is_writable($upgrade_progress_file) && write_array_to_file( "upgrade_config", $upgrade_config,
3526 $upgrade_progress_file)) {
3527 //writing to the file
3532 function initialize_session_vars(){
3533 $upgrade_progress_dir = getcwd().'/'.$GLOBALS['sugar_config']['upload_dir'].'upgrades/temp';
3534 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3535 if(file_exists($upgrade_progress_file)){
3536 include($upgrade_progress_file);
3537 if(isset($upgrade_config) && $upgrade_config != null && is_array($upgrade_config) && sizeof($upgrade_config) >0){
3538 $currVarsArray=$upgrade_config[1]['upgrade_vars'];
3539 //print_r($currVarsArray);
3540 if(isset($currVarsArray) && $currVarsArray != null && is_array($currVarsArray) && sizeof($currVarsArray)>0){
3541 foreach($currVarsArray as $key=>$val){
3542 if($key != null && $val !=null){
3543 //set session variables
3544 $_SESSION[$key]=$val;
3553 //track the upgrade progress on each step
3554 //track the upgrade progress on each step
3555 function set_upgrade_progress($currStep,$currState,$currStepSub='',$currStepSubState=''){
3557 $upgrade_progress_dir = getcwd().'/'.$GLOBALS['sugar_config']['upload_dir'].'upgrades/temp';
3558 if(!is_dir($upgrade_progress_dir)){
3559 mkdir_recursive($upgrade_progress_dir);
3561 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3562 if(file_exists($upgrade_progress_file)){
3563 include($upgrade_progress_file);
3566 if(function_exists('sugar_fopen')){
3567 sugar_fopen($upgrade_progress_file, 'w+');
3570 fopen($upgrade_progress_file, 'w+');
3573 if(!isset($upgrade_config) || $upgrade_config == null){
3574 $upgrade_config = array();
3575 $upgrade_config[1]['upgrade_vars']=array();
3577 if(!is_array($upgrade_config[1]['upgrade_vars'])){
3578 $upgrade_config[1]['upgrade_vars'] = array();
3580 if($currStep != null && $currState != null){
3581 if(sizeof($upgrade_config) > 0){
3582 if($currStepSub != null && $currStepSubState !=null){
3583 //check if new status to be set or update
3584 //get the latest in array. since it has sub components prepare an array
3585 if(!empty($upgrade_config[sizeof($upgrade_config)][$currStep]) && is_array($upgrade_config[sizeof($upgrade_config)][$currStep])){
3586 $latestStepSub = currSubStep($upgrade_config[sizeof($upgrade_config)][$currStep]);
3587 if($latestStepSub == $currStepSub){
3588 $upgrade_config[sizeof($upgrade_config)][$currStep][$latestStepSub]=$currStepSubState;
3589 $upgrade_config[sizeof($upgrade_config)][$currStep][$currStep] = $currState;
3592 $upgrade_config[sizeof($upgrade_config)][$currStep][$currStepSub]=$currStepSubState;
3593 $upgrade_config[sizeof($upgrade_config)][$currStep][$currStep] = $currState;
3597 $currArray = array();
3598 $currArray[$currStep] = $currState;
3599 $currArray[$currStepSub] = $currStepSubState;
3600 $upgrade_config[sizeof($upgrade_config)+1][$currStep] = $currArray;
3604 //get the current upgrade progress
3605 $latestStep = get_upgrade_progress();
3606 //set the upgrade progress
3607 //echo 'latest '.$latestStep;
3608 if($latestStep == $currStep){
3609 //update the current step with new progress status
3611 $upgrade_config[sizeof($upgrade_config)][$latestStep]=$currState;
3616 $upgrade_config[sizeof($upgrade_config)+1][$currStep]=$currState;
3618 // now check if there elements within array substeps
3622 //set the upgrade progress (just starting)
3623 $upgrade_config[sizeof($upgrade_config)+1][$currStep]= $currState;
3626 if(is_writable($upgrade_progress_file) && write_array_to_file( "upgrade_config", $upgrade_config,
3627 $upgrade_progress_file)) {
3628 //writing to the file
3634 function get_upgrade_progress(){
3635 $upgrade_progress_dir = getcwd().'/'.$GLOBALS['sugar_config']['upload_dir'].'upgrades/temp';
3636 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3638 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3640 if(file_exists($upgrade_progress_file)){
3641 include($upgrade_progress_file);
3642 //echo 'upconf '.$upgrade_config;
3643 if(!isset($upgrade_config) || $upgrade_config == null){
3644 $upgrade_config = array();
3646 if($upgrade_config != null && sizeof($upgrade_config) >1){
3647 $currArr = $upgrade_config[sizeof($upgrade_config)];
3648 //echo 'size of '.sizeof($upgrade_config);
3649 if(is_array($currArr)){
3650 foreach($currArr as $key=>$val){
3658 function currSubStep($currStep){
3660 if(is_array($currStep)){
3661 foreach($currStep as $key=>$val){
3669 function currUpgradeState($currState){
3671 if(is_array($currState)){
3672 foreach($currState as $key=>$val){
3674 foreach($val as $k=>$v){
3688 function didThisStepRunBefore($step,$SubStep=''){
3689 if($step == null) return;
3690 $upgrade_progress_dir = getcwd().'/'.$GLOBALS['sugar_config']['upload_dir'].'upgrades/temp';
3691 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3693 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3695 if(file_exists($upgrade_progress_file)){
3696 include($upgrade_progress_file);
3697 if(isset($upgrade_config) && $upgrade_config != null && is_array($upgrade_config) && sizeof($upgrade_config) >0){
3698 for($i=1;$i<=sizeof($upgrade_config);$i++){
3699 if(is_array($upgrade_config[$i])){
3700 foreach($upgrade_config[$i] as $key=>$val){
3702 if(is_array($upgrade_config[$i][$step])){
3704 foreach ($upgrade_config[$i][$step] as $k=>$v){
3706 foreach($v as $k1=>$v1){
3707 if($SubStep != null){
3708 if($SubStep ==$k1 && $v1=='done'){
3709 //echo 'Found Inside '.$k1;
3716 elseif($SubStep !=null){
3717 if($SubStep==$k && $v=='done'){
3718 //echo 'Found1 '.$k;
3723 elseif($step==$k && $v=='done'){
3724 //echo 'Found2 '.$k;
3730 elseif($val=='done'){
3731 //echo 'Foundmmmm '.$key;
3745 //get and set post install status
3746 function post_install_progress($progArray='',$action=''){
3747 if($action=='' || $action=='get'){
3748 //get the state of post install
3749 $upgrade_progress_dir = getcwd().'/'.$GLOBALS['sugar_config']['upload_dir'].'upgrades/temp';
3750 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3751 $currProg = array();
3752 if(file_exists($upgrade_progress_file)){
3753 include($upgrade_progress_file);
3754 if(is_array($upgrade_config[sizeof($upgrade_config)]['commit']['post_install']) && sizeof($upgrade_config[sizeof($upgrade_config)]['commit']['post_install'])>0){
3755 foreach($upgrade_config[sizeof($upgrade_config)]['commit']['post_install'] as $k=>$v){
3762 elseif($action=='set'){
3763 $upgrade_progress_dir = getcwd().'/'.$GLOBALS['sugar_config']['upload_dir'].'upgrades/temp';
3764 if(!is_dir($upgrade_progress_dir)){
3765 mkdir($upgrade_progress_dir);
3767 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3768 if(file_exists($upgrade_progress_file)){
3769 include($upgrade_progress_file);
3772 fopen($upgrade_progress_file, 'w+');
3774 if(!is_array($upgrade_config[sizeof($upgrade_config)]['commit']['post_install'])){
3775 $upgrade_config[sizeof($upgrade_config)]['commit']['post_install']=array();
3776 $upgrade_config[sizeof($upgrade_config)]['commit']['post_install']['post_install'] = 'in_progress';
3778 if($progArray != null && is_array($progArray)){
3779 foreach($progArray as $key=>$val){
3780 $upgrade_config[sizeof($upgrade_config)]['commit']['post_install'][$key]=$val;
3783 if(is_writable($upgrade_progress_file) && write_array_to_file( "upgrade_config", $upgrade_config,
3784 $upgrade_progress_file)) {
3785 //writing to the file
3791 // parse and run sql file
3792 function parseAndExecuteSqlFileExtended($sqlScript){
3793 global $sugar_config;
3794 $alterTableSchema = '';
3795 $db = & DBManagerFactory::getInstance();
3796 if(is_file($sqlScript)) {
3797 $fp = fopen($sqlScript, 'r');
3798 $contents = stream_get_contents($fp);
3799 $anyScriptChanges =$contents;
3803 while($line = fgets($fp)) {
3804 if(strpos($line, '--') === false) {
3805 $completeLine .= " ".trim($line);
3806 if(strpos($line, ';') !== false) {
3807 $completeLine = str_replace(';','',$completeLine);
3808 $currLine = explode(",",$completeLine);
3809 //check if multiple statements are clubbed
3810 if(sizeof($currLine) >1){
3811 $qarr = explode(" ",trim($currLine[0]));
3812 if(strtoupper(trim($qarr[0])) == 'CREATE' && strtoupper(trim($qarr[1])) == 'TABLE'){
3813 if(strtoupper(trim($qarr[2]) != null)){
3814 if($sugar_config['dbconfig']['db_type'] == 'oci8'){
3815 $query= "select table_name from user_tables where table_name=strtoupper(trim($qarr[2]))";
3816 $result = $db->query($query);
3817 $row = $db->fetchByAssociation($result);
3818 if($row['table_name'] != null){
3823 $query= $completeLine;
3832 $qType =trim($qarr[0])." ".trim($qarr[1])." ".trim($qarr[2]);
3833 echo trim($currLine[0])."<br />";
3834 for ($i = 1; $i <= sizeof($currLine)-1; $i++) {
3835 $query = $qType." ".trim($currLine[$i]);
3836 echo $query."<br />";
3842 echo trim($currLine[0]);
3846 //$q3 = $completeLine;
3847 //''$r3 = $GLOBALS['db']->query($q3, false, "Preflight Failed for:");
3848 //echo mysql_error();
3856 //$sqlErrors[] = $mod_strings['ERR_UW_FILE_NOT_READABLE'].'::'.$sqlScript;
3861 function repairDBForUpgrade($execute=false,$path=''){
3863 global $current_user, $beanFiles;
3865 set_time_limit(3600);
3867 $db = &DBManagerFactory::getInstance();
3869 VardefManager::clearVardef();
3870 require_once('include/ListView/ListView.php');
3871 foreach ($beanFiles as $bean => $file) {
3872 require_once ($file);
3873 $focus = new $bean ();
3874 $sql .= $db->repairTable($focus, $execute);
3878 $olddictionary = $dictionary;
3879 unset ($dictionary);
3880 include ('modules/TableDictionary.php');
3881 foreach ($dictionary as $meta) {
3882 $tablename = $meta['table'];
3883 $fielddefs = $meta['fields'];
3884 $indices = $meta['indices'];
3885 $sql .= $db->repairTableParams($tablename, $fielddefs, $indices, $execute);
3888 foreach (explode("\n", $sql) as $line) {
3889 if (!empty ($line) && substr($line, -2) != "*/") {
3892 $qry_str .= $line . "\n";
3903 preg_replace('#(/\*.+?\*/\n*)#', '', $qry_str)
3905 logThis("*******START EXECUTING DB UPGRADE QUERIES***************",$path);
3906 logThis($sql,$path);
3907 logThis("*******END EXECUTING DB UPGRADE QUERIES****************",$path);
3916 * upgradeUserPreferences
3917 * This method updates the user_preferences table and sets the pages/dashlets for users
3918 * which have ACL access to Trackers so that the Tracker dashlets are set in their user perferences
3921 function upgradeUserPreferences() {
3926 function add_custom_modules_favorites_search(){
3927 $module_directories = scandir('modules');
3929 foreach($module_directories as $module_dir){
3930 if($module_dir == '.' || $module_dir == '..' || !is_dir("modules/{$module_dir}")){
3935 preg_match('/^[a-z0-9]{1,5}_[a-z0-9_]+$/i' , $module_dir, $matches);
3937 // Make sure the module was created by module builder
3938 if(empty($matches)){
3942 $full_module_dir = "modules/{$module_dir}/";
3943 $read_searchdefs_from = "{$full_module_dir}/metadata/searchdefs.php";
3944 $read_SearchFields_from = "{$full_module_dir}/metadata/SearchFields.php";
3945 $read_custom_SearchFields_from = "custom/{$full_module_dir}/metadata/SearchFields.php";
3947 // Studio can possibly override this file, so we check for a custom version of it
3948 if(file_exists("custom/{$full_module_dir}/metadata/searchdefs.php")){
3949 $read_searchdefs_from = "custom/{$full_module_dir}/metadata/searchdefs.php";
3952 if(file_exists($read_searchdefs_from) && file_exists($read_SearchFields_from)){
3955 require($read_searchdefs_from);
3956 foreach($searchdefs[$module_dir]['layout']['basic_search'] as $sf_array){
3957 if(isset($sf_array['name']) && $sf_array['name'] == 'favorites_only'){
3962 require($read_SearchFields_from);
3963 if(isset($searchFields[$module_dir]['favorites_only'])){
3967 if(!$found_sf1 && !$found_sf2){
3968 $searchdefs[$module_dir]['layout']['basic_search']['favorites_only'] = array('name' => 'favorites_only','label' => 'LBL_FAVORITES_FILTER','type' => 'bool',);
3969 $searchdefs[$module_dir]['layout']['advanced_search']['favorites_only'] = array('name' => 'favorites_only','label' => 'LBL_FAVORITES_FILTER','type' => 'bool',);
3970 $searchFields[$module_dir]['favorites_only'] = array(
3971 'query_type'=>'format',
3972 'operator' => 'subquery',
3973 'subquery' => 'SELECT sugarfavorites.record_id FROM sugarfavorites
3974 WHERE sugarfavorites.deleted=0
3975 and sugarfavorites.module = \''.$module_dir.'\'
3976 and sugarfavorites.assigned_user_id = \'{0}\'',
3977 'db_field'=>array('id')
3980 if(!is_dir("custom/{$full_module_dir}/metadata")){
3981 mkdir_recursive("custom/{$full_module_dir}/metadata");
3983 $success_sf1 = write_array_to_file('searchdefs', $searchdefs, "custom/{$full_module_dir}/metadata/searchdefs.php");
3984 $success_sf2 = write_array_to_file('searchFields', $searchFields, "{$full_module_dir}/metadata/SearchFields.php");
3987 logThis("add_custom_modules_favorites_search failed for searchdefs.php for {$module_dir}");
3990 logThis("add_custom_modules_favorites_search failed for SearchFields.php for {$module_dir}");
3992 if($success_sf1 && $success_sf2){
3993 logThis("add_custom_modules_favorites_search successfully updated searchdefs and searchFields for {$module_dir}");
4002 * upgradeModulesForTeamsets
4004 * This method adds the team_set_id values to the module tables that have the new team_set_id column
4005 * added through the SugarCRM 5.5.x upgrade process. It also adds the values into the team_sets and
4006 * team_sets_teams tables.
4008 * @param filter Array of modules to process; empty by default
4010 function upgradeModulesForTeamsets($filter=array()) {
4011 require('include/modules.php');
4012 foreach($beanList as $moduleName=>$beanName) {
4013 if(!empty($filter) && array_search($moduleName, $filter) === false) {
4016 if($moduleName == 'TeamMemberships' || $moduleName == 'ForecastOpportunities'){
4019 $bean = loadBean($moduleName);
4021 empty($bean->table_name)) {
4025 $FieldArray = $GLOBALS['db']->helper->get_columns($bean->table_name);
4026 if(!isset($FieldArray['team_id'])) {
4030 upgradeTeamColumn($bean, 'team_id');
4034 //Upgrade users table
4035 $bean = loadBean('Users');
4036 upgradeTeamColumn($bean, 'default_team');
4037 $result = $GLOBALS['db']->query("SELECT id FROM teams where deleted=0");
4038 while($row = $GLOBALS['db']->fetchByAssoc($result)) {
4039 $teamset = new TeamSet();
4040 $teamset->addTeams($row['id']);
4047 * Helper function to create a team_set_id column and also set team_set_id column
4048 * to have the value of the $column_name parameter
4050 * @param $bean SugarBean which we are adding team_set_id column to
4051 * @param $column_name The name of the column containing the default team_set_id value
4053 function upgradeTeamColumn($bean, $column_name) {
4054 //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
4055 //module that does not use the SugarObjects
4056 if(empty($bean->field_defs['team_set_id']) && $bean->module_dir != 'Trackers'){
4058 //at this point we could assume that since we have a team_id defined and not a team_set_id that we need to
4059 //add that field and the corresponding relationships
4060 $object = $bean->object_name;
4061 $module = $bean->module_dir;
4062 $object_name = $object;
4063 $_object_name = strtolower($object_name);
4065 if(!empty($GLOBALS['dictionary'][$object]['table'])){
4066 $table_name = $GLOBALS['dictionary'][$object]['table'];
4068 $table_name = strtolower($module);
4071 $path = 'include/SugarObjects/implements/team_security/vardefs.php';
4073 //go through each entry in the vardefs from team_security and unset anything that is already set in the core module
4074 //this will ensure we have the proper ordering.
4075 $fieldDiff = array_diff_assoc($vardefs['fields'], $GLOBALS['dictionary'][$bean->object_name]['fields']);
4077 $file = 'custom/Extension/modules/' . $bean->module_dir. '/Ext/Vardefs/teams.php';
4078 $contents = "<?php\n";
4079 if(!empty($fieldDiff)){
4080 foreach($fieldDiff as $key => $val){
4081 $contents .= "\n\$GLOBALS['dictionary']['". $object . "']['fields']['". $key . "']=" . var_export_helper($val) . ";";
4084 $relationshipDiff = array_diff_assoc($vardefs['relationships'], $GLOBALS['dictionary'][$bean->object_name]['relationships']);
4085 if(!empty($relationshipDiff)){
4086 foreach($relationshipDiff as $key => $val){
4087 $contents .= "\n\$GLOBALS['dictionary']['". $object . "']['relationships']['". $key . "']=" . var_export_helper($val) . ";";
4090 $indexDiff = array_diff_assoc($vardefs['indices'], $GLOBALS['dictionary'][$bean->object_name]['indices']);
4091 if(!empty($indexDiff)){
4092 foreach($indexDiff as $key => $val){
4093 $contents .= "\n\$GLOBALS['dictionary']['". $object . "']['indices']['". $key . "']=" . var_export_helper($val) . ";";
4096 if( $fh = @sugar_fopen( $file, 'wt' ) )
4098 fputs( $fh, $contents);
4103 //we have written out the teams.php into custom/Extension/modules/{$module_dir}/Ext/Vardefs/teams.php'
4104 //now let's merge back into vardefs.ext.php
4105 require_once('ModuleInstall/ModuleInstaller.php');
4106 $mi = new ModuleInstaller();
4107 $mi->merge_files('Ext/Vardefs/', 'vardefs.ext.php');
4108 VardefManager::loadVardef($bean->module_dir, $bean->object_name, true);
4109 $bean->field_defs = $GLOBALS['dictionary'][$bean->object_name]['fields'];
4112 if(isset($bean->field_defs['team_set_id'])) {
4113 //Create the team_set_id column
4114 $FieldArray = $GLOBALS['db']->helper->get_columns($bean->table_name);
4115 if(!isset($FieldArray['team_set_id'])) {
4116 $GLOBALS['db']->addColumn($bean->table_name, $bean->field_defs['team_set_id']);
4118 $indexArray = $GLOBALS['db']->helper->get_indices($bean->table_name);
4120 $indexName = getValidDBName('idx_'.strtolower($bean->table_name).'_tmst_id', true, 34);
4123 'name' => $indexName,
4125 'fields' => array('team_set_id')
4128 if(!isset($indexArray[$indexName])) {
4129 $GLOBALS['db']->addIndexes($bean->table_name, $indexDef);
4132 //Update the table's team_set_id column to have the same values as team_id
4133 $GLOBALS['db']->query("UPDATE {$bean->table_name} SET team_set_id = {$column_name}");
4138 * Update the folder subscription table which confirms to the team security mechanism but
4139 * the class SugarFolders does not extend SugarBean and is therefore never picked up by the
4140 * upgradeModulesForTeamsets function.
4142 function upgradeFolderSubscriptionsTeamSetId()
4144 logThis("In upgradeFolderSubscriptionsTeamSetId()");
4145 $query = "UPDATE folders SET team_set_id = team_id";
4146 $result = $GLOBALS['db']->query($query);
4147 logThis("Finished upgradeFolderSubscriptionsTeamSetId()");
4151 * upgradeModulesForTeam
4153 * This method update the associated_user_id, name, name_2 to the private team records on teams table
4154 * This function is used for upgrade process from 5.1.x and 5.2.x.
4157 function upgradeModulesForTeam() {
4158 logThis("In upgradeModulesForTeam()");
4159 $result = $GLOBALS['db']->query("SELECT id, user_name, first_name, last_name FROM users where deleted=0");
4161 while($row = $GLOBALS['db']->fetchByAssoc($result)) {
4162 $results2 = $GLOBALS['db']->query("SELECT id FROM teams WHERE name = '({$row['user_name']})'");
4164 if(!$assoc = $GLOBALS['db']->fetchByAssoc($results2)) {
4165 //if team does not exist, then lets create the team for this user
4168 $user->retrieve($row['id']);
4169 $team->new_user_created($user);
4170 $team_id = $team->id;
4172 $team_id =$assoc['id'];
4176 $name = is_null($row['first_name'])?'':$row['first_name'];
4177 $name_2 = is_null($row['last_name'])?'':$row['last_name'];
4178 $associated_user_id = $row['id'];
4181 //Ensure team->name is not empty by using team->name_2 if available
4182 if(empty($name) && !empty($name_2)) {
4187 $query = "UPDATE teams SET name = '{$name}', name_2 = '{$name_2}', associated_user_id = '{$associated_user_id}' WHERE id = '{$team_id}'";
4188 $GLOBALS['db']->query($query);
4191 //Update the team_set_id and default_team columns
4192 $ce_to_pro_or_ent = (isset($_SESSION['upgrade_from_flavor']) && ($_SESSION['upgrade_from_flavor'] == 'SugarCE to SugarPro' || $_SESSION['upgrade_from_flavor'] == 'SugarCE to SugarEnt' || $_SESSION['upgrade_from_flavor'] == 'SugarCE to SugarCorp' || $_SESSION['upgrade_from_flavor'] == 'SugarCE to SugarUlt'));
4194 //Update team_set_id
4195 if($ce_to_pro_or_ent) {
4196 $GLOBALS['db']->query("update users set team_set_id = (select teams.id from teams where teams.associated_user_id = users.id)");
4197 $GLOBALS['db']->query("update users set default_team = (select teams.id from teams where teams.associated_user_id = users.id)");
4203 function addNewSystemTabsFromUpgrade($from_dir){
4205 if(isset($_SESSION['upgrade_from_flavor'])){
4207 //check to see if there are any new files that need to be added to systems tab
4208 //retrieve old modules list
4209 logThis('check to see if new modules exist',$path);
4210 $oldModuleList = array();
4211 $newModuleList = array();
4212 include($from_dir.'/include/modules.php');
4213 $oldModuleList = $moduleList;
4214 include('include/modules.php');
4215 $newModuleList = $moduleList;
4217 //include tab controller
4218 require_once('modules/MySettings/TabController.php');
4219 $newTB = new TabController();
4221 //make sure new modules list has a key we can reference directly
4222 $newModuleList = $newTB->get_key_array($newModuleList);
4223 $oldModuleList = $newTB->get_key_array($oldModuleList);
4225 //iterate through list and remove commonalities to get new modules
4226 foreach ($newModuleList as $remove_mod){
4227 if(in_array($remove_mod, $oldModuleList)){
4228 unset($newModuleList[$remove_mod]);
4231 //new modules list now has left over modules which are new to this install, so lets add them to the system tabs
4232 logThis('new modules to add are '.var_export($newModuleList,true),$path);
4234 if(!empty($newModuleList))
4236 //grab the existing system tabs
4237 $tabs = $newTB->get_system_tabs();
4239 //add the new tabs to the array
4240 foreach($newModuleList as $nm ){
4244 $newTB->set_system_tabs($tabs);
4246 logThis('module tabs updated',$path);
4252 * This method attempts to fix dropdown lists that were incorrectly named.
4253 * There were versions of SugarCRM that did not enforce naming convention rules
4254 * for the dropdown list field name. This method attempts to resolve that by
4255 * fixing the language files that may have been affected and then updating the
4256 * fields_meta_data table accordingly. It also refreshes any vardefs that may
4257 * have been affected.
4260 function fix_dropdown_list() {
4261 if(file_exists('custom/include/language')) {
4263 $affected_modules = array();
4264 $affected_keys = array();
4266 getFiles($files, 'custom/include/language', '/\.php$/i');
4267 foreach($files as $file) {
4269 if(file_exists($file . '.bak')) {
4270 $bak_mod_time = filemtime($file . '.bak');
4271 $php_mod_time = filemtime($file);
4272 //We're saying if the .php file was modified 30 seconds no more than php.bak file then we
4273 //run these additional cleanup checks
4274 if($php_mod_time - $bak_mod_time < 30) {
4276 $app_list_strings = array();
4277 $GLOBALS['app_list_strings'] = array();
4278 require($file . '.bak');
4279 $bak_app_list_strings = array_merge($app_list_strings, $GLOBALS['app_list_strings']);
4281 $app_list_strings = array();
4282 $GLOBALS['app_list_strings'] = array();
4284 $php_app_list_strings = array_merge($app_list_strings, $GLOBALS['app_list_strings']);
4286 //Get the file contents
4287 $contents = file_get_contents($file);
4289 //Now simulate a fix for the file before we compare w/ the .php file
4290 //we also append to the $contents
4291 foreach($bak_app_list_strings as $key=>$entry) {
4292 if(preg_match('/([^A-Za-z_])/', $key, $matches) && is_array($entry)) {
4293 $new_key = preg_replace('/[^A-Za-z_]/', '_', $key);
4294 $bak_app_list_strings[$new_key] = $bak_app_list_strings[$key];
4295 unset($bak_app_list_strings[$key]);
4296 //Now if the entry doesn't exists in the .php file, then add to contents
4297 if(!isset($php_app_list_strings[$new_key])) {
4298 $contents .= "\n\$GLOBALS['app_list_strings']['{$new_key}'] = " . var_export_helper($bak_app_list_strings[$new_key]) . ";";
4303 //Now load the .php file to do the comparison
4304 foreach($php_app_list_strings as $key=>$entry) {
4305 if(isset($bak_app_list_strings[$key])) {
4306 $diff = array_diff($bak_app_list_strings[$key], $entry);
4308 //There is a difference, so copy the $bak_app_list_strings version into the .php file
4309 $contents .= "\n\$GLOBALS['app_list_strings']['{$key}'] = " . var_export_helper($bak_app_list_strings[$key]) . ";";
4314 //Now write out the file contents
4315 //Create backup just in case
4316 copy($file, $file . '.php_bak');
4317 $fp = @sugar_fopen($file, 'w');
4319 fwrite($fp, $contents);
4322 $GLOBALS['log']->error("Unable to update file contents in fix_dropdown_list for {$file}");
4327 unset($GLOBALS['app_strings']);
4328 unset($GLOBALS['app_list_strings']);
4329 $app_list_strings = array();
4332 $contents = file_get_contents($file);
4333 if ( !isset($GLOBALS['app_list_strings']) ) {
4334 $GLOBALS['app_list_strings'] = $app_list_strings;
4337 $GLOBALS['app_list_strings'] = array_merge($app_list_strings, $GLOBALS['app_list_strings']);
4340 if(isset($GLOBALS['app_list_strings']) && is_array($GLOBALS['app_list_strings'])) {
4341 foreach($GLOBALS['app_list_strings'] as $key=>$entry) {
4342 if(preg_match('/([^A-Za-z_])/', $key, $matches) && is_array($entry)) {
4343 $result = $GLOBALS['db']->query("SELECT custom_module FROM fields_meta_data WHERE ext1 = '{$key}'");
4344 if(!empty($result)) {
4345 while($row = $GLOBALS['db']->fetchByAssoc($result)) {
4346 $custom_module = $row['custom_module'];
4347 if(!empty($GLOBALS['beanList'][$custom_module])) {
4348 $affected_modules[$custom_module] = $GLOBALS['beanList'][$custom_module];
4353 //Replace all invalid characters with '_' character
4354 $new_key = preg_replace('/[^A-Za-z_]/', '_', $key);
4355 $affected_keys[$key] = $new_key;
4357 $GLOBALS['app_list_strings'][$new_key] = $GLOBALS['app_list_strings'][$key];
4358 unset($GLOBALS['app_list_strings'][$key]);
4360 $pattern_match = "/(\[\s*\'{$key}\'\s*\])/";
4361 $new_key = "['{$new_key}']";
4362 $out = preg_replace($pattern_match, $new_key, $contents);
4368 //This is a check for g => h instances where the file contents were incorrectly written
4369 //and also fixes the scenario where via a UI upgrade, the app_list_strings were incorrectly
4370 //merged with app_list_strings variables declared elsewhere
4372 if(preg_match('/\$GLOBALS\s*\[\s*[\"|\']app_list_strings[\"|\']\s*\]\s*=\s*array\s*\(/', $contents)) {
4373 //Now also remove all the non-custom labels that were added
4374 if(preg_match('/language\/([^\.]+)\.lang\.php$/', $file, $matches)) {
4375 $language = $matches[1];
4377 $app_list_strings = array();
4379 if(file_exists("include/language/$language.lang.php")) {
4380 include("include/language/$language.lang.php");
4382 if(file_exists("include/language/$language.lang.override.php")) {
4383 $app_list_strings = _mergeCustomAppListStrings("include/language/$language.lang.override.php" , $app_list_strings) ;
4385 if(file_exists("custom/application/Ext/Language/$language.ext.lang.php")) {
4386 $app_list_strings = _mergeCustomAppListStrings("custom/application/Ext/Language/$language.ext.lang.php" , $app_list_strings) ;
4388 if(file_exists("custom/application/Ext/Language/$language.lang.ext.php")) {
4389 $app_list_strings = _mergeCustomAppListStrings("custom/application/Ext/Language/$language.lang.ext.php" , $app_list_strings) ;
4392 $all_non_custom_include_language_strings = $app_strings;
4393 $all_non_custom_include_language_list_strings = $app_list_strings;
4395 $unset_keys = array();
4396 if(!empty($GLOBALS['app_list_strings'])) {
4397 foreach($GLOBALS['app_list_strings'] as $key=>$value) {
4399 if(isset($all_non_custom_include_language_list_strings[$key])) {
4400 $diff = array_diff($all_non_custom_include_language_list_strings[$key], $GLOBALS['app_list_strings'][$key]);
4403 if(!empty($all_non_custom_include_language_list_strings[$key]) && empty($diff)) {
4404 $unset_keys[] = $key;
4409 foreach($unset_keys as $key) {
4410 unset($GLOBALS['app_list_strings'][$key]);
4413 if(!empty($GLOBALS['app_strings'])) {
4414 foreach($GLOBALS['app_strings'] as $key=>$value) {
4415 if(!empty($all_non_custom_include_language_strings[$key])) {
4416 unset($GLOBALS['app_strings'][$key]);
4420 } //if(preg_match...)
4423 if(!empty($GLOBALS['app_strings'])) {
4424 foreach($GLOBALS['app_strings'] as $key=>$entry) {
4425 $out .= "\n\$GLOBALS['app_strings']['$key']=" . var_export_helper($entry) . ";";
4429 foreach($GLOBALS['app_list_strings'] as $key=>$entry) {
4430 $out .= "\n\$GLOBALS['app_list_strings']['$key']=" . var_export_helper($entry) . ";";
4434 } //if(preg_match...)
4438 //Create a backup just in case
4439 copy($file, $file . '.bak');
4440 $fp = @sugar_fopen($file, 'w');
4445 //If we can't update the file, just return
4446 $GLOBALS['log']->error("Unable to update file contents in fix_dropdown_list.");
4454 //Update db entries (the order matters here... need to process database changes first)
4455 if(!empty($affected_keys)) {
4456 foreach($affected_keys as $old_key=>$new_key) {
4457 $GLOBALS['db']->query("UPDATE fields_meta_data SET ext1 = '{$new_key}' WHERE ext1 = '{$old_key}'");
4461 //Update vardef files for affected modules
4462 if(!empty($affected_modules)) {
4463 foreach($affected_modules as $module=>$object) {
4464 VardefManager::refreshVardefs($module, $object);
4471 function update_iframe_dashlets(){
4472 require_once('cache/dashlets/dashlets.php');
4474 $db = DBManagerFactory::getInstance();
4475 $query = "SELECT id, contents, assigned_user_id FROM user_preferences WHERE deleted = 0 AND category = 'Home'";
4476 $result = $db->query($query, true, "Unable to update new default dashlets! ");
4477 while ($row = $db->fetchByAssoc($result)) {
4478 $content = unserialize(base64_decode($row['contents']));
4479 $assigned_user_id = $row['assigned_user_id'];
4480 $record_id = $row['id'];
4482 $current_user = new User();
4483 $current_user->retrieve($row['assigned_user_id']);
4485 if(!empty($content['dashlets']) && !empty($content['pages'])){
4486 $originalDashlets = $content['dashlets'];
4487 foreach($originalDashlets as $key => $ds){
4488 if(!empty($ds['options']['url']) && stristr($ds['options']['url'],'http://www.sugarcrm.com/crm/product/gopro')){
4489 unset($originalDashlets[$key]);
4492 $current_user->setPreference('dashlets', $originalDashlets, 0, 'Home');
4499 * convertImageToText
4500 * This method attempts to convert date type image to text on Microsoft SQL Server.
4501 * This method could NOT be used in any other type of datebases.
4503 function convertImageToText($table_name,$column_name){
4504 $set_lang = "SET LANGUAGE us_english";
4505 $GLOBALS['db']->query($set_lang);
4506 if($GLOBALS['db']->checkError()){
4507 logThis('An error occurred when performing this query-->'.$set_lang);
4509 $q="SELECT data_type
4510 FROM INFORMATION_SCHEMA.Tables T JOIN INFORMATION_SCHEMA.Columns C
4511 ON T.TABLE_NAME = C.TABLE_NAME where T.TABLE_NAME = '$table_name' and C.COLUMN_NAME = '$column_name'";
4512 $res= $GLOBALS['db']->query($q);
4513 if($GLOBALS['db']->checkError()){
4514 logThis('An error occurred when performing this query-->'.$q);
4516 $row= $GLOBALS['db']->fetchByAssoc($res);
4518 if(trim(strtolower($row['data_type'])) == 'image'){
4519 $addContent_temp = "alter table {$table_name} add {$column_name}_temp text null";
4520 $GLOBALS['db']->query($addContent_temp);
4521 if($GLOBALS['db']->checkError()){
4522 logThis('An error occurred when performing this query-->'.$addContent_temp);
4524 $qN = "select count=datalength({$column_name}), id, {$column_name} from {$table_name}";
4525 $result = $GLOBALS['db']->query($qN);
4526 while($row = $GLOBALS['db']->fetchByAssoc($result)){
4527 if($row['count'] >8000){
4528 $contentLength = $row['count'];
4531 $convertedContent = '';
4532 while($contentLength >0){
4533 $stepsQuery = "select cont=convert(varchar(max), convert(varbinary(8000), substring({$column_name},{$start},{$next}))) from {$table_name} where id= '{$row['id']}'";
4534 $steContQ = $GLOBALS['db']->query($stepsQuery);
4535 if($GLOBALS['db']->checkError()){
4536 logThis('An error occurred when performing this query-->'.$stepsQuery);
4538 $stepCont = $GLOBALS['db']->fetchByAssoc($steContQ);
4539 if(isset($stepCont['cont'])){
4540 $convertedContent = $convertedContent.$stepCont['cont'];
4542 $start = $start+$next;
4543 $contentLength = $contentLength - $next;
4545 $addContentDataText="update {$table_name} set {$column_name}_temp = '{$convertedContent}' where id= '{$row['id']}'";
4546 $GLOBALS['db']->query($addContentDataText);
4547 if($GLOBALS['db']->checkError()){
4548 logThis('An error occurred when performing this query-->'.$addContentDataText);
4552 $addContentDataText="update {$table_name} set {$column_name}_temp =
4553 convert(varchar(max), convert(varbinary(8000), {$column_name})) where id= '{$row['id']}'";
4554 $GLOBALS['db']->query($addContentDataText);
4555 if($GLOBALS['db']->checkError()){
4556 logThis('An error occurred when performing this query-->'.$addContentDataText);
4560 //drop the contents now and change contents_temp to contents
4561 $dropColumn = "alter table {$table_name} drop column {$column_name}";
4562 $GLOBALS['db']->query($dropColumn);
4563 if($GLOBALS['db']->checkError()){
4564 logThis('An error occurred when performing this query-->'.$dropColumn);
4566 $changeColumnName = "EXEC sp_rename '{$table_name}.[{$column_name}_temp]','{$column_name}','COLUMN'";
4567 $GLOBALS['db']->query($changeColumnName);
4568 if($GLOBALS['db']->checkError()){
4569 logThis('An error occurred when performing this query-->'.$changeColumnName);
4576 * This method attempts to delete all English inline help files.
4577 * This method was introduced by 5.5.0RC2.
4579 function clearHelpFiles(){
4580 $modulePath = clean_path(getcwd() . '/modules');
4581 $allHelpFiles = array();
4582 getFiles($allHelpFiles, $modulePath, "/en_us.help.*/");
4584 foreach( $allHelpFiles as $the_file ){
4585 if( is_file( $the_file ) ){
4586 unlink( $the_file );
4587 logThis("Deleted file: $the_file", $path);
4595 * upgradeDateTimeFields
4597 * This method came from bug: 39757 where the date_end field is a date field and not a datetime field
4598 * which prevents you from performing timezone offset calculations once the data has been saved.
4600 * @param path String location to log file, empty by default
4602 function upgradeDateTimeFields($path=''){
4605 if($db->dbType == 'mysql')
4607 $meetingsSql = "UPDATE meetings SET date_end = date_add(date_start, INTERVAL + CONCAT(duration_hours, ':', duration_minutes) HOUR_MINUTE)";
4608 $callsSql = "UPDATE calls SET date_end = date_add(date_start, INTERVAL + CONCAT(duration_hours, ':', duration_minutes) HOUR_MINUTE)";
4609 } else if($db->dbType == 'mssql') {
4610 $meetingsSql = "UPDATE meetings set date_end = DATEADD(hh, duration_hours, DATEADD(mi, duration_minutes, date_start))";
4611 $callsSql = "UPDATE calls set date_end = DATEADD(hh, duration_hours, DATEADD(mi, duration_minutes, date_start))";
4612 } else if ($db->dbType == 'oci8') {
4613 $meetingsSql = "UPDATE meetings SET date_end = date_start + duration_hours/24 + duration_minutes/1440";
4614 $callsSql = "UPDATE calls SET date_end = date_start + duration_hours/24 + duration_minutes/1440";
4617 if(isset($meetingsSql) && isset($callsSql))
4619 logThis('upgradeDateTimeFields Meetings SQL:' . $meetingsSql, $path);
4620 $db->query($meetingsSql);
4622 logThis('upgradeDateTimeFields Calls SQL:' . $callsSql, $path);
4623 $db->query($callsSql);
4630 * upgradeDocumentTypeFields
4633 function upgradeDocumentTypeFields($path){
4637 $documentsSql = "UPDATE documents SET doc_type = 'Sugar' WHERE doc_type IS NULL";
4638 $meetingsSql = "UPDATE meetings SET type = 'Sugar' WHERE type IS NULL";
4640 logThis('upgradeDocumentTypeFields Documents SQL:' . $documentsSql, $path);
4641 $db->query($documentsSql);
4642 logThis('upgradeDocumentTypeFields Meetings SQL:' . $meetingsSql, $path);
4643 $db->query($meetingsSql);
4648 * merge_config_si_settings
4649 * This method checks for the presence of a config_si.php file and, if found, merges the configuration
4650 * settings from the config_si.php file into config.php. If a config_si_location parameter value is not
4651 * supplied it will attempt to discover the config_si.php file location from where the executing script
4654 * @param write_to_upgrade_log boolean optional value to write to the upgradeWizard.log file
4655 * @param config_location String optional value to config.php file location
4656 * @param config_si_location String optional value to config_si.php file location
4657 * @param path String file of the location of log file to write to
4658 * @return boolean value indicating whether or not a merge was attempted with config_si.php file
4660 function merge_config_si_settings($write_to_upgrade_log=false, $config_location='', $config_si_location='', $path='')
4662 if(!empty($config_location) && !file_exists($config_location))
4664 if($write_to_upgrade_log)
4666 logThis('config.php file specified in ' . $config_si_location . ' could not be found. Skip merging', $path);
4669 } else if(empty($config_location)) {
4671 //We are assuming this is from the silentUpgrade scripts so argv[3] will point to SugarCRM install location
4672 if(isset($argv[3]) && is_dir($argv[3]))
4674 $config_location = $argv[3] . DIRECTORY_SEPARATOR . 'config.php';
4678 //If config_location is still empty or if the file cannot be found, skip merging
4679 if(empty($config_location) || !file_exists($config_location))
4681 if($write_to_upgrade_log)
4683 logThis('config.php file at (' . $config_location . ') could not be found. Skip merging.', $path);
4687 if($write_to_upgrade_log)
4689 logThis('Loading config.php file at (' . $config_location . ') for merging.', $path);
4692 include($config_location);
4693 if(empty($sugar_config))
4695 if($write_to_upgrade_log)
4697 logThis('config.php contents are empty. Skip merging.', $path);
4703 if(!empty($config_si_location) && !file_exists($config_si_location))
4705 if($write_to_upgrade_log)
4707 logThis('config_si.php file specified in ' . $config_si_location . ' could not be found. Skip merging', $path);
4710 } else if(empty($config_si_location)) {
4711 if(isset($argv[0]) && is_file($argv[0]))
4713 $php_file = $argv[0];
4714 $p_info = pathinfo($php_file);
4715 $php_dir = (isset($p_info['dirname']) && $p_info['dirname'] != '.') ? $p_info['dirname'] . DIRECTORY_SEPARATOR : '';
4716 $config_si_location = $php_dir . 'config_si.php';
4720 //If config_si_location is still empty or if the file cannot be found, skip merging
4721 if(empty($config_si_location) || !file_exists($config_si_location))
4723 if($write_to_upgrade_log)
4725 logThis('config_si.php file at (' . $config_si_location . ') could not be found. Skip merging.', $path);
4729 if($write_to_upgrade_log)
4731 logThis('Loading config_si.php file at (' . $config_si_location . ') for merging.', $path);
4734 include($config_si_location);
4735 if(empty($sugar_config_si))
4737 if($write_to_upgrade_log)
4739 logThis('config_si.php contents are empty. Skip merging.', $path);
4745 //Now perform the merge operation
4747 foreach($sugar_config_si as $key=>$value)
4749 if(!preg_match('/^setup_/', $key) && !isset($sugar_config[$key]))
4751 if($write_to_upgrade_log)
4753 logThis('Merge key (' . $key . ') with value (' . $value . ')', $path);
4755 $sugar_config[$key] = $value;
4762 if($write_to_upgrade_log)
4764 logThis('Update config.php file with new values', $path);
4767 if(!write_array_to_file("sugar_config", $sugar_config, $config_location)) {
4768 if($write_to_upgrade_log)
4770 logThis('*** ERROR: could not write to config.php', $path);
4775 if($write_to_upgrade_log)
4777 logThis('config.php values are in sync with config_si.php values. Skipped merging.');
4782 if($write_to_upgrade_log)
4784 logThis('End merge_config_si_settings', $path);
4790 * upgrade_connectors
4791 * @param $path String variable for the log path
4793 function upgrade_connectors($path='') {
4794 logThis('Begin upgrade_connectors', $path);
4796 $filePath = 'custom/modules/Connectors/connectors/sources/ext/soap/hoovers/config.php';
4797 if(file_exists($filePath))
4799 logThis("{$filePath} file", $path);
4801 if(!is_null($config))
4804 if(isset($config['properties']['hoovers_endpoint']))
4806 $config['properties']['hoovers_endpoint'] = 'http://hapi.hoovers.com/HooversAPI-33';
4810 if(isset($config['properties']['hoovers_wsdl']))
4812 $config['properties']['hoovers_wsdl'] = 'http://hapi.hoovers.com/HooversAPI-33/hooversAPI/hooversAPI.wsdl';
4818 if(!write_array_to_file('config', $config, $filePath)) {
4819 logThis("Could not write new configuration to {$filePath} file", $path);
4821 logThis('Modified file successfully with new configuration entries', $path);
4827 $filePath = 'custom/modules/Connectors/connectors/sources/ext/soap/hoovers/vardefs.php';
4828 if(file_exists($filePath))
4830 logThis("Modifying {$filePath} file", $path);
4832 $fileContents = file_get_contents($filePath);
4833 $out = str_replace('bal.specialtyCriteria.companyKeyword', 'bal.specialtyCriteria.companyName', $fileContents);
4834 file_put_contents($filePath, $out);
4837 logThis('End upgrade_connectors', $path);
4841 * Enable the InsideView connector for the four default modules.
4843 function upgradeEnableInsideViewConnector($path='')
4845 logThis('Begin upgradeEnableInsideViewConnector', $path);
4847 // Load up the existing mapping and hand it to the InsideView connector to have it setup the correct logic hooks
4848 $mapFile = 'modules/Connectors/connectors/sources/ext/rest/insideview/mapping.php';
4849 if ( file_exists('custom/'.$mapFile) ) {
4850 logThis('Found CUSTOM mappings', $path);
4851 require('custom/'.$mapFile);
4853 logThis('Used default mapping', $path);
4857 require_once('include/connectors/sources/SourceFactory.php');
4858 $source = SourceFactory::getSource('ext_rest_insideview');
4860 // $mapping is brought in from the mapping.php file above
4861 $source->saveMappingHook($mapping);
4863 require_once('include/connectors/utils/ConnectorUtils.php');
4864 ConnectorUtils::installSource('ext_rest_insideview');
4866 // Now time to set the various modules to active, because this part ignores the default config
4867 require(CONNECTOR_DISPLAY_CONFIG_FILE);
4868 // $modules_sources come from that config file
4869 foreach ( $source->allowedModuleList as $module ) {
4870 $modules_sources[$module]['ext_rest_insideview'] = 'ext_rest_insideview';
4872 if(!write_array_to_file('modules_sources', $modules_sources, CONNECTOR_DISPLAY_CONFIG_FILE)) {
4873 //Log error and return empty array
4874 logThis("Cannot write \$modules_sources to " . CONNECTOR_DISPLAY_CONFIG_FILE,$path);
4877 logThis('End upgradeEnableInsideViewConnector', $path);
4881 function repair_long_relationship_names($path='')
4883 logThis("Begin repair_long_relationship_names", $path);
4884 require_once 'modules/ModuleBuilder/parsers/relationships/DeployedRelationships.php' ;
4885 $GLOBALS['mi_remove_tables'] = false;
4887 foreach($GLOBALS['moduleList'] as $module)
4889 $relationships = new DeployedRelationships ($module) ;
4890 foreach($relationships->getRelationshipList() as $rel_name)
4892 if (strlen($rel_name) > 27 && empty($touched[$rel_name]))
4894 logThis("Rebuilding relationship fields for $rel_name", $path);
4895 $touched[$rel_name] = true;
4896 $rel_obj = $relationships->get($rel_name);
4897 $rel_obj->setReadonly(false);
4898 $relationships->delete($rel_name);
4899 $relationships->save();
4900 $relationships->add($rel_obj);
4901 $relationships->save();
4902 $relationships->build () ;
4906 logThis("End repair_long_relationship_names", $path);
4909 function removeSilentUpgradeVarsCache(){
4910 global $silent_upgrade_vars_loaded;
4912 $cacheFileDir = "{$GLOBALS['sugar_config']['cache_dir']}/silentUpgrader";
4913 $cacheFile = "{$cacheFileDir}/silentUpgradeCache.php";
4915 if(file_exists($cacheFile)){
4919 $silent_upgrade_vars_loaded = array(); // Set to empty to reset it
4924 function loadSilentUpgradeVars(){
4925 global $silent_upgrade_vars_loaded;
4927 if(empty($silent_upgrade_vars_loaded)){
4928 $cacheFile = "{$GLOBALS['sugar_config']['cache_dir']}/silentUpgrader/silentUpgradeCache.php";
4929 // We have no pre existing vars
4930 if(!file_exists($cacheFile)){
4931 // Set the vars array so it's loaded
4932 $silent_upgrade_vars_loaded = array('vars' => array());
4935 require_once($cacheFile);
4936 $silent_upgrade_vars_loaded = $silent_upgrade_vars_cache;
4943 function writeSilentUpgradeVars(){
4944 global $silent_upgrade_vars_loaded;
4946 if(empty($silent_upgrade_vars_loaded)){
4947 return false; // You should have set some values before trying to write the silent upgrade vars
4950 $cacheFileDir = "{$GLOBALS['sugar_config']['cache_dir']}/silentUpgrader";
4951 $cacheFile = "{$cacheFileDir}/silentUpgradeCache.php";
4953 require_once('include/dir_inc.php');
4954 if(!mkdir_recursive($cacheFileDir)){
4957 require_once('include/utils/file_utils.php');
4958 if(!write_array_to_file('silent_upgrade_vars_cache', $silent_upgrade_vars_loaded, $cacheFile, 'w')){
4960 logThis("WARNING: writeSilentUpgradeVars could not write to {$cacheFile}", $path);
4967 function setSilentUpgradeVar($var, $value){
4968 if(!loadSilentUpgradeVars()){
4972 global $silent_upgrade_vars_loaded;
4974 $silent_upgrade_vars_loaded['vars'][$var] = $value;
4979 function getSilentUpgradeVar($var){
4980 if(!loadSilentUpgradeVars()){
4984 global $silent_upgrade_vars_loaded;
4986 if(!isset($silent_upgrade_vars_loaded['vars'][$var])){
4990 return $silent_upgrade_vars_loaded['vars'][$var];
4996 * add_unified_search_to_custom_modules_vardefs
4998 * This method calls the repair code to remove the unified_search_modules.php fiel
5001 function add_unified_search_to_custom_modules_vardefs()
5003 if(file_exists('cache/modules/unified_search_modules.php'))
5005 unlink('cache/modules/unified_search_modules.php');
5011 * change from using the older SugarCache in 6.1 and below to the new one in 6.2
5013 function upgradeSugarCache($file)
5015 global $sugar_config;
5016 // file = getcwd().'/'.$sugar_config['upload_dir'].$_FILES['upgrade_zip']['name'];
5018 $cacheUploadUpgradesTemp = clean_path(mk_temp_dir("{$sugar_config['upload_dir']}upgrades/temp"));
5020 unzip($file, $cacheUploadUpgradesTemp);
5022 if(!file_exists(clean_path("{$cacheUploadUpgradesTemp}/manifest.php"))) {
5023 logThis("*** ERROR: no manifest file detected while bootstraping upgrade wizard files!");
5026 include(clean_path("{$cacheUploadUpgradesTemp}/manifest.php"));
5029 $allFiles = array();
5030 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/SugarCache"))) {
5031 $allFiles = findAllFiles(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/SugarCache"), $allFiles);
5033 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/external_cache.php"))) {
5034 $allFiles[] = clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/external_cache.php");
5036 $cwd = clean_path(getcwd());
5038 foreach($allFiles as $k => $file) {
5039 $file = clean_path($file);
5040 $destFile = str_replace(clean_path($cacheUploadUpgradesTemp.'/'.$manifest['copy_files']['from_dir']), $cwd, $file);
5041 if(!is_dir(dirname($destFile))) {
5042 mkdir_recursive(dirname($destFile)); // make sure the directory exists
5044 if ( stristr($file,'uw_main.tpl') )
5045 logThis('Skipping "'.$file.'" - file copy will during commit step.');
5047 logThis('updating UpgradeWizard code: '.$destFile);
5048 copy_recursive($file, $destFile);
5051 logThis ('is sugar_file_util there '.file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/sugar_file_utils.php")));
5052 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/sugar_file_utils.php"))) {
5053 $file = clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/sugar_file_utils.php");
5054 $destFile = str_replace(clean_path($cacheUploadUpgradesTemp.'/'.$manifest['copy_files']['from_dir']), $cwd, $file);
5055 copy($file,$destFile);
5061 * upgradeDisplayedTabsAndSubpanels
5063 * @param $version String value of current system version (pre upgrade)
5065 function upgradeDisplayedTabsAndSubpanels($version)
5067 if($version < '620')
5069 logThis('start upgrading system displayed tabs and subpanels');
5070 require_once('modules/MySettings/TabController.php');
5071 $tc = new TabController();
5073 //grab the existing system tabs
5074 $tabs = $tc->get_tabs_system();
5076 //add Calls, Meetings, Tasks, Notes, Prospects (Targets) and ProspectLists (Target Lists)
5077 //to displayed tabs unless explicitly set to hidden
5078 $modules_to_add = array('Calls', 'Meetings', 'Tasks', 'Notes', 'Prospects', 'ProspectLists');
5079 $added_tabs = array();
5081 foreach($modules_to_add as $module)
5083 $tabs[0][$module] = $module;
5084 $added_tabs[] = $module;
5087 logThis('calling set_system_tabs on TabController to add tabs: ' . var_export($added_tabs, true));
5088 $tc->set_system_tabs($tabs[0]);
5089 logThis('finish upgrading system displayed tabs and subpanels');
5095 * unlinkUpgradeFiles
5096 * This is a helper function to clean up
5098 * @param $version String value of current system version (pre upgrade)
5100 function unlinkUpgradeFiles($version)
5102 if(!isset($version))
5107 logThis('start unlinking files from previous upgrade');
5108 if($version < '620')
5110 //list of files to remove
5111 $files_to_remove = array('modules/Notifications/metadata/studio.php', 'modules/Help/Forms.php','themes/Sugar5/images/sugarColors.xml');
5113 foreach($files_to_remove as $f)
5117 logThis('removing file: ' . $f);
5122 logThis('end unlinking files from previous upgrade');
5124 if($version < '620')
5126 logThis('start upgrade for DocumentRevisions classic files (EditView.html, EditView.php, DetailView.html, DetailView.php, Save.php)');
5128 //Use a md5 comparison check to see if we can just remove the file where an exact match is found
5129 if($version < '610')
5132 'modules/DocumentRevisions/DetailView.html' => '17ad4d308ce66643fdeb6fdb3b0172d3',
5133 'modules/DocumentRevisions/DetailView.php' => 'd8606cdcd0281ae9443b2580a43eb5b3',
5134 'modules/DocumentRevisions/EditView.php' => 'c7a1c3ef2bb30e3f5a11d122b3c55ff1',
5135 'modules/DocumentRevisions/EditView.html' => '7d360ca703863c957f40b3719babe8c8',
5136 'modules/DocumentRevisions/Save.php' => 'd7e39293a5fb4d605ca2046e7d1fcf28',
5140 'modules/DocumentRevisions/DetailView.html' => 'a8356ff20cd995daffe6cb7f7b8b2340',
5141 'modules/DocumentRevisions/DetailView.php' => '20edf45dd785469c484fbddff1a3f8f2',
5142 'modules/DocumentRevisions/EditView.php' => 'fb31958496f04031b2851dcb4ce87d50',
5143 'modules/DocumentRevisions/EditView.html' => 'b8cada4fa6fada2b4e4928226d8b81ee',
5144 'modules/DocumentRevisions/Save.php' => '7fb62e4ebff879bafc07a08da62902aa',
5148 foreach($dr_files as $rev_file=>$hash)
5150 if(file_exists($rev_file))
5152 //It's a match here so let's just remove the file
5153 if (md5(file_get_contents($rev_file)) == $hash)
5155 logThis('removing file ' . $rev_file);
5158 if(!copy($rev_file, $rev_file . '.suback.bak'))
5160 logThis('error making backup for file ' . $rev_file);
5162 logThis('copied file ' . $rev_file . ' to ' . $rev_file . '.suback.bak');
5169 logThis('end upgrade for DocumentRevisions classic files');
5173 if (!function_exists("getValidDBName"))
5176 * Return a version of $proposed that can be used as a column name in any of our supported databases
5177 * Practically this means no longer than 25 characters as the smallest identifier length for our supported DBs is 30 chars for Oracle plus we add on at least four characters in some places (for indicies for example)
5178 * @param string $name Proposed name for the column
5179 * @param string $ensureUnique
5180 * @return string Valid column name trimmed to right length and with invalid characters removed
5182 function getValidDBName ($name, $ensureUnique = false, $maxLen = 30)
5184 // first strip any invalid characters - all but alphanumerics and -
5185 $name = preg_replace ( '/[^\w-]+/i', '', $name ) ;
5186 $len = strlen ( $name ) ;
5190 $md5str = md5($name);
5191 $tail = substr ( $name, -11) ;
5192 $temp = substr($md5str , strlen($md5str)-4 );
5193 $result = substr ( $name, 0, 10) . $temp . $tail ;
5194 }else if ($len > ($maxLen - 5))
5196 $result = substr ( $name, 0, 11) . substr ( $name, 11 - $maxLen + 5);
5198 return strtolower ( $result ) ;