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,true);
596 foreach($allModFiles as $file)
598 if(file_exists($file))
602 rmdir_recursive($file);
610 //Clean jsLanguage from cache
611 if(is_dir($GLOBALS['sugar_config']['cache_dir'].'jsLanguage')){
612 $allModFiles = array();
613 $allModFiles = findAllFiles($GLOBALS['sugar_config']['cache_dir'].'jsLanguage',$allModFiles);
614 foreach($allModFiles as $file){
615 if(file_exists($file)){
620 //Clean smarty from cache
621 if(is_dir($GLOBALS['sugar_config']['cache_dir'].'smarty')){
622 $allModFiles = array();
623 $allModFiles = findAllFiles($GLOBALS['sugar_config']['cache_dir'].'smarty',$allModFiles);
624 foreach($allModFiles as $file){
625 if(file_exists($file)){
630 //Rebuild dashlets cache
631 require_once('include/Dashlets/DashletCacheBuilder.php');
632 $dc = new DashletCacheBuilder();
636 function deleteChance(){
637 //Clean folder from cache
638 if(is_dir('include/SugarObjects/templates/chance')){
639 rmdir_recursive('include/SugarObjects/templates/chance');
641 if(is_dir('include/SugarObjects/templates/chance')){
642 if(!isset($_SESSION['chance'])){
643 $_SESSION['chance'] = '';
645 $_SESSION['chance'] = 'include/SugarObjects/templates/chance';
646 //rename('include/SugarObjects/templates/chance','include/SugarObjects/templates/chance_removeit');
653 * copies upgrade wizard files from new patch if that dir exists
654 * @param string file Path to uploaded zip file
656 function upgradeUWFiles($file) {
657 global $sugar_config;
658 // file = getcwd().'/'.$sugar_config['upload_dir'].$_FILES['upgrade_zip']['name'];
660 $cacheUploadUpgradesTemp = clean_path(mk_temp_dir("{$sugar_config['upload_dir']}upgrades/temp"));
662 unzip($file, $cacheUploadUpgradesTemp);
664 if(!file_exists(clean_path("{$cacheUploadUpgradesTemp}/manifest.php"))) {
665 logThis("*** ERROR: no manifest file detected while bootstraping upgrade wizard files!");
668 include(clean_path("{$cacheUploadUpgradesTemp}/manifest.php"));
673 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/modules/UpgradeWizard"))) {
674 $allFiles = findAllFiles(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/modules/UpgradeWizard"), $allFiles);
677 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/ModuleInstall"))) {
678 $allFiles = findAllFiles(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/ModuleInstall"), $allFiles);
680 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/javascript/yui"))) {
681 $allFiles = findAllFiles(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/javascript/yui"), $allFiles);
683 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/HandleAjaxCall.php"))) {
684 $allFiles[] = clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/HandleAjaxCall.php");
686 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/SugarTheme"))) {
687 $allFiles = findAllFiles(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/SugarTheme"), $allFiles);
689 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/SugarCache"))) {
690 $allFiles = findAllFiles(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/SugarCache"), $allFiles);
692 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/external_cache.php"))) {
693 $allFiles[] = clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/external_cache.php");
697 * /home/chris/workspace/maint450/cache/upload/upgrades/temp/DlNnqP/
698 * SugarEnt-Patch-4.5.0c/modules/Leads/ConvertLead.html
700 $cwd = clean_path(getcwd());
702 foreach($allFiles as $k => $file) {
703 $file = clean_path($file);
704 $destFile = str_replace(clean_path($cacheUploadUpgradesTemp.'/'.$manifest['copy_files']['from_dir']), $cwd, $file);
705 if(!is_dir(dirname($destFile))) {
706 mkdir_recursive(dirname($destFile)); // make sure the directory exists
708 if ( stristr($file,'uw_main.tpl') )
709 logThis('Skipping "'.$file.'" - file copy will during commit step.');
711 logThis('updating UpgradeWizard code: '.$destFile);
712 copy_recursive($file, $destFile);
715 logThis ('is sugar_file_util there '.file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/sugar_file_utils.php")));
716 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/sugar_file_utils.php"))) {
717 $file = clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/sugar_file_utils.php");
718 $destFile = str_replace(clean_path($cacheUploadUpgradesTemp.'/'.$manifest['copy_files']['from_dir']), $cwd, $file);
719 copy($file,$destFile);
726 * gets valid patch file names that exist in upload/upgrade/patch/
728 function getValidPatchName($returnFull = true) {
729 global $base_upgrade_dir;
732 global $sugar_version;
733 global $sugar_config;
734 $uh = new UpgradeHistory();
735 $base_upgrade_dir = $sugar_config['upload_dir'] . "upgrades";
738 // scan for new files (that are not installed)
739 logThis('finding new files for upgrade');
740 $upgrade_content = '';
741 $upgrade_contents = findAllFiles($base_upgrade_dir, array(), false, 'zip');
742 //other variations of zip file i.e. ZIP, zIp,zIP,Zip,ZIp,ZiP
743 $extns = array('ZIP','ZIp','ZiP','Zip','zIP','zIp','ziP');
744 foreach($extns as $extn){
745 $upgrade_contents = array_merge($upgrade_contents,findAllFiles( "$base_upgrade_dir", array() , false, $extn));
753 <b>{$mod_strings['LBL_ML_NAME']}</b>
756 <b>{$mod_strings['LBL_ML_TYPE']}</b>
759 <b>{$mod_strings['LBL_ML_VERSION']}</b>
762 <b>{$mod_strings['LBL_ML_PUBLISHED']}</b>
765 <b>{$mod_strings['LBL_ML_UNINSTALLABLE']}</b>
768 <b>{$mod_strings['LBL_ML_DESCRIPTION']}</b>
773 // assume old patches are there.
774 $upgradeToVersion = array(); // fill with valid patches - we will only use the latest qualified found patch
776 // cn: bug 10609 - notices for uninitialized variables
781 $published_date = '';
786 foreach($upgrade_contents as $upgrade_content) {
787 if(!preg_match("#.*\.zip\$#i", strtolower($upgrade_content))) {
791 $upgrade_content = clean_path($upgrade_content);
792 $the_base = basename($upgrade_content);
793 $the_md5 = md5_file($upgrade_content);
795 $md5_matches = $uh->findByMd5($the_md5);
797 /* 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.
798 * Edge-case: manual upgrade with a FTP of a patch; UH table has no entry for it. Assume nothing. :( */
799 if(0 == sizeof($md5_matches)) {
800 $target_manifest = remove_file_extension( $upgrade_content ) . '-manifest.php';
801 require_once($target_manifest);
803 if(empty($manifest['version'])) {
804 logThis("*** Potential error: patch found with no version [ {$upgrade_content} ]");
807 if(!isset($manifest['type']) || $manifest['type'] != 'patch') {
808 logThis("*** Potential error: patch found with either no 'type' or non-patch type [ {$upgrade_content} ]");
812 $upgradeToVersion[$manifest['version']] = urlencode($upgrade_content);
814 $name = empty($manifest['name']) ? $upgrade_content : $manifest['name'];
815 $version = empty($manifest['version']) ? '' : $manifest['version'];
816 $published_date = empty($manifest['published_date']) ? '' : $manifest['published_date'];
818 $description = empty($manifest['description']) ? 'None' : $manifest['description'];
819 $uninstallable = empty($manifest['is_uninstallable']) ? 'No' : 'Yes';
820 $type = getUITextForType( $manifest['type'] );
821 $manifest_type = $manifest['type'];
823 if(empty($manifest['icon'])) {
824 $icon = getImageForType( $manifest['type'] );
826 $path_parts = pathinfo( $manifest['icon'] );
827 $icon = "<img src=\"" . remove_file_extension( $upgrade_content ) . "-icon." . $path_parts['extension'] . "\">";
832 // cn: bug 10488 use the NEWEST upgrade/patch available when running upgrade wizard.
833 ksort($upgradeToVersion);
834 $upgradeToVersion = array_values($upgradeToVersion);
835 $newest = array_pop($upgradeToVersion);
836 $_SESSION['install_file'] = urldecode($newest); // in-case it was there from a prior.
837 logThis("*** UW using [ {$_SESSION['install_file']} ] as source for patch files.");
839 $cleanUpgradeContent = urlencode($_SESSION['install_file']);
841 // cn: 10606 - cannot upload a patch file since this returned always.
842 if(!empty($cleanUpgradeContent)) {
843 $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";
846 <form action="index.php" method="post">
847 <input type="hidden" name="module" value="UpgradeWizard">
848 <input type="hidden" name="action" value="index">
849 <input type="hidden" name="step" value="{$_REQUEST['step']}">
850 <input type="hidden" name="run" value="delete">
851 <input type=hidden name="install_file" value="{$cleanUpgradeContent}" />
852 <input type=submit value="{$mod_strings['LBL_BUTTON_DELETE']}" />
856 $disabled = "DISABLED";
861 if(empty($cleanUpgradeContent)){
862 $ready .= "<tr><td colspan='7'><i>None</i></td>\n";
863 $ready .= "</table>\n";
865 $ready .= "<br></ul>\n";
867 $return['ready'] = $ready;
868 $return['disabled'] = $disabled;
877 * finalizes upgrade by setting upgrade versions in DB (config table) and sugar_version.php
878 * @return bool true on success
880 function updateVersions($version) {
882 global $sugar_config;
885 logThis('At updateVersions()... updating config table and sugar_version.php.', $path);
888 if(isset($_SESSION['sugar_version_file']) && !empty($_SESSION['sugar_version_file'])) {
889 if(!copy($_SESSION['sugar_version_file'], clean_path(getcwd().'/sugar_version.php'))) {
890 logThis('*** ERROR: sugar_version.php could not be copied to destination! Cannot complete upgrade', $path);
893 logThis('sugar_version.php successfully updated!', $path);
896 logThis('*** ERROR: no sugar_version.php file location found! - cannot complete upgrade...', $path);
900 // handle config table
901 if($db->dbType == 'mysql') {
902 $q1 = "DELETE FROM `config` WHERE `category` = 'info' AND `name` = 'sugar_version'";
903 $q2 = "INSERT INTO `config` (`category`, `name`, `value`) VALUES ('info', 'sugar_version', '{$version}')";
904 } elseif($db->dbType == 'oci8' || $db->dbType == 'oracle') {
905 } elseif($db->dbType == 'mssql') {
906 $q1 = "DELETE FROM config WHERE category = 'info' AND name = 'sugar_version'";
907 $q2 = "INSERT INTO config (category, name, value) VALUES ('info', 'sugar_version', '{$version}')";
910 logThis('Deleting old DB version info from config table.', $path);
913 logThis('Inserting updated version info into config table.', $path);
916 logThis('updateVersions() complete.', $path);
923 * gets a module's lang pack - does not need to be a SugarModule
924 * @param lang string Language
925 * @param module string Path to language folder
926 * @return array mod_strings
928 function getModuleLanguagePack($lang, $module) {
929 $mod_strings = array();
931 if(!empty($lang) && !empty($module)) {
932 $langPack = clean_path(getcwd().'/'.$module.'/language/'.$lang.'.lang.php');
933 $langPackEn = clean_path(getcwd().'/'.$module.'/language/en_us.lang.php');
935 if(file_exists($langPack))
936 include_once($langPack);
937 elseif(file_exists($langPackEn))
938 include_once($langPackEn);
944 * checks system compliance for 4.5+ codebase
945 * @return array Mixed values
947 function checkSystemCompliance() {
948 global $sugar_config;
949 global $current_language;
953 if(!defined('SUGARCRM_MIN_MEM')) {
954 define('SUGARCRM_MIN_MEM', 40);
957 $installer_mod_strings = getModuleLanguagePack($current_language, './install');
959 $ret['error_found'] = false;
962 $php_version = constant('PHP_VERSION');
963 $check_php_version_result = check_php_version($php_version);
965 switch($check_php_version_result) {
967 $ret['phpVersion'] = "<b><span class=stop>{$installer_mod_strings['ERR_CHECKSYS_PHP_INVALID_VER']} {$php_version} )</span></b>";
968 $ret['error_found'] = true;
971 $ret['phpVersion'] = "<b><span class=go>{$installer_mod_strings['ERR_CHECKSYS_PHP_UNSUPPORTED']} {$php_version} )</span></b>";
974 $ret['phpVersion'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_PHP_OK']} {$php_version} )</span></b>";
978 // database and connect
979 switch($sugar_config['dbconfig']['db_type']){
982 $q = "SELECT version();";
984 $a = $db->fetchByAssoc($r);
985 if(version_compare($a['version()'], '4.1.2') < 0) {
986 $ret['error_found'] = true;
987 $ret['mysqlVersion'] = "<b><span class=stop>".$mod_strings['ERR_UW_MYSQL_VERSION'].$a['version()']."</span></b>";
1001 if(function_exists('xml_parser_create')) {
1002 $ret['xmlStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1004 $ret['xmlStatus'] = "<b><span class=stop>{$installer_mod_strings['LBL_CHECKSYS_NOT_AVAILABLE']}</span></b>";
1005 $ret['error_found'] = true;
1009 if(function_exists('curl_init')) {
1010 $ret['curlStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</font></b>";
1012 $ret['curlStatus'] = "<b><span class=go>{$installer_mod_strings['ERR_CHECKSYS_CURL']}</font></b>";
1013 $ret['error_found'] = false;
1017 if(function_exists('mb_strlen')) {
1018 $ret['mbstringStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</font></b>";
1020 $ret['mbstringStatus'] = "<b><span class=stop>{$installer_mod_strings['ERR_CHECKSYS_MBSTRING']}</font></b>";
1021 $ret['error_found'] = true;
1025 if(function_exists('imap_open')) {
1026 $ret['imapStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1028 $ret['imapStatus'] = "<b><span class=go>{$installer_mod_strings['ERR_CHECKSYS_IMAP']}</span></b>";
1029 $ret['error_found'] = false;
1034 if('1' == ini_get('safe_mode')) {
1035 $ret['safeModeStatus'] = "<b><span class=stop>{$installer_mod_strings['ERR_CHECKSYS_SAFE_MODE']}</span></b>";
1036 $ret['error_found'] = true;
1038 $ret['safeModeStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1042 // call time pass by ref
1043 if('1' == ini_get('allow_call_time_pass_reference')) {
1044 $ret['callTimeStatus'] = "<b><span class=stop>{$installer_mod_strings['ERR_CHECKSYS_CALL_TIME']}</span></b>";
1045 //continue upgrading
1047 $ret['callTimeStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
1051 $ret['memory_msg'] = "";
1052 $memory_limit = "-1";//ini_get('memory_limit');
1053 $sugarMinMem = constant('SUGARCRM_MIN_MEM');
1054 // logic based on: http://us2.php.net/manual/en/ini.core.php#ini.memory-limit
1055 if( $memory_limit == "" ){ // memory_limit disabled at compile time, no memory limit
1056 $ret['memory_msg'] = "<b><span class=\"go\">{$installer_mod_strings['LBL_CHECKSYS_MEM_OK']}</span></b>";
1057 } elseif( $memory_limit == "-1" ){ // memory_limit enabled, but set to unlimited
1058 $ret['memory_msg'] = "<b><span class=\"go\">{$installer_mod_strings['LBL_CHECKSYS_MEM_UNLIMITED']}</span></b>";
1060 rtrim($memory_limit, 'M');
1061 $memory_limit_int = (int) $memory_limit;
1062 if( $memory_limit_int < constant('SUGARCRM_MIN_MEM') ){
1063 $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>";
1064 $ret['error_found'] = true;
1066 $ret['memory_msg'] = "<b><span class=\"go\">{$installer_mod_strings['LBL_CHECKSYS_OK']} ({$memory_limit})</span></b>";
1070 /* mbstring.func_overload
1071 $ret['mbstring.func_overload'] = '';
1072 $mb = ini_get('mbstring.func_overload');
1075 $ret['mbstring.func_overload'] = "<b><span class=\"stop\">{$mod_strings['ERR_UW_MBSTRING_FUNC_OVERLOAD']}</b>";
1076 $ret['error_found'] = true;
1084 function checkMysqlConnection(){
1085 global $sugar_config;
1086 $configOptions = $sugar_config['dbconfig'];
1087 if($sugar_config['dbconfig']['db_type'] == 'mysql'){
1088 @mysql_ping($GLOBALS['db']->database);
1093 * is a file that we blow away automagically
1095 function isAutoOverwriteFile($file) {
1096 $overwriteDirs = array(
1097 './sugar_version.php',
1098 './modules/UpgradeWizard/uw_main.tpl',
1100 $file = trim('.'.str_replace(clean_path(getcwd()), '', $file));
1102 if(in_array($file, $overwriteDirs)) {
1106 $fileExtension = substr(strrchr($file, "."), 1);
1107 if($fileExtension == 'tpl' || $fileExtension == 'html') {
1117 function logThis($entry, $path='') {
1118 global $mod_strings;
1119 if(file_exists('include/utils/sugar_file_utils.php')){
1120 require_once('include/utils/sugar_file_utils.php');
1122 $log = empty($path) ? clean_path(getcwd().'/upgradeWizard.log') : clean_path($path);
1124 // create if not exists
1125 if(!file_exists($log)) {
1126 if(function_exists('sugar_fopen')){
1127 $fp = @sugar_fopen($log, 'w+'); // attempts to create file
1130 $fp = fopen($log, 'w+'); // attempts to create file
1132 if(!is_resource($fp)) {
1133 $GLOBALS['log']->fatal('UpgradeWizard could not create the upgradeWizard.log file');
1134 die($mod_strings['ERR_UW_LOG_FILE_UNWRITABLE']);
1137 if(function_exists('sugar_fopen')){
1138 $fp = @sugar_fopen($log, 'a+'); // write pointer at end of file
1141 $fp = @fopen($log, 'a+'); // write pointer at end of file
1144 if(!is_resource($fp)) {
1145 $GLOBALS['log']->fatal('UpgradeWizard could not open/lock upgradeWizard.log file');
1146 die($mod_strings['ERR_UW_LOG_FILE_UNWRITABLE']);
1150 $line = date('r').' [UpgradeWizard] - '.$entry."\n";
1152 if(@fwrite($fp, $line) === false) {
1153 $GLOBALS['log']->fatal('UpgradeWizard could not write to upgradeWizard.log: '.$entry);
1154 die($mod_strings['ERR_UW_LOG_FILE_UNWRITABLE']);
1157 if(is_resource($fp)) {
1164 * tries to validate the query based on type
1165 * @param string query The query to verify
1166 * @param string dbType The DB type
1167 * @return string error Non-empty string on error
1169 function verifySqlStatement($query, $dbType, &$newTables) {
1171 logThis('verifying SQL statement');
1173 $table = getTableFromQuery($query);
1175 switch(strtoupper(substr($query, 0, 10))) {
1179 $error = testQueryAlter($table, $dbType, strtoupper($query), $newTables);
1183 $error = testQueryCreate($table, $dbType, $query, $newTables);
1187 $error = testQueryDelete($table, $dbType, $query);
1191 $error = testQueryDrop($table, $dbType, $query);
1195 $error = testQueryInsert($table, $dbType, $query);
1198 case (strtoupper(substr($query, 0, 6)) == 'UPDATE'):
1199 $error = testQueryUpdate($table, $dbType, $query);
1211 * @desc This function is to be used in the upgrade process to preserve changes/customaizations made to pre 5.1 quickcreate layout.
1212 * 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
1213 * was automatically picked up by the quick create. [Addresses Bug 21469]
1214 * This function will check if customizations were made, and will create quickcreatedefs.php in the /cutom/working/$module_name directory.
1216 function updateQuickCreateDefs(){
1217 $d = dir('modules');
1218 $studio_modules = array();
1220 while($e = $d->read()){ //collect all studio modules.
1221 if(substr($e, 0, 1) == '.' || !is_dir('modules/' . $e))continue;
1222 if(file_exists('modules/' . $e . '/metadata/studio.php'))
1224 array_push($studio_modules, $e);
1228 foreach( $studio_modules as $modname ){ //for each studio enabled module
1229 //Check !exists modules/$modname/metadata/quickcreatedefs.php &&
1230 //exists custom/$modname/editviewdefs.php (module was customized) &&
1231 //!exists custom/$modname/quickcreateviewdefs.php
1233 $editviewdefs = "custom/working/modules/".$modname."/metadata/editviewdefs.php";
1234 $quickcreatedefs = "custom/working/modules/".$modname."/metadata/quickcreatedefs.php";
1236 if ( !file_exists("modules/".$modname."/metadata/quickcreatedefs.php") &&
1237 file_exists($editviewdefs) &&
1238 !file_exists($quickcreatedefs) ){
1239 //clone editviewdef and save it in custom/working/modules/metadata
1240 $GLOBALS['log']->debug("Copying editviewdefs.php as quickcreatedefs.php for the $modname module in custom/working/modules/$modname/metadata!");
1241 if(copy( $editviewdefs, $quickcreatedefs)){
1242 if(file_exists($quickcreatedefs) && is_readable($quickcreatedefs)){
1243 $file = file($quickcreatedefs);
1244 //replace 'EditView' with 'QuickCreate'
1245 $fp = fopen($quickcreatedefs,'w');
1246 foreach($file as &$line){
1247 if(preg_match('/^\s*\'EditView\'\s*=>\s*$/', $line) > 0){
1248 $line = "'QuickCreate' =>\n";
1256 $GLOBALS['log']->debug("Failed to replace 'EditView' with QuickCreate because $quickcreatedefs is either not readable or does not exist.");
1259 $GLOBALS['log']->debug("Failed to copy $editviewdefs to $quickcreatedefs!");
1266 function cleanQuery($query, $oci8=false) {
1276 $q = str_replace($bad, $good, $query);
1282 * test perms for CREATE queries
1284 function testPermsCreate($type, $out) {
1285 logThis('Checking CREATE TABLE permissions...');
1287 global $mod_strings;
1292 $db->query('CREATE TABLE temp (id varchar(36))');
1293 if($db->checkError()) {
1294 logThis('cannot CREATE TABLE!');
1295 $out['db']['dbNoCreate'] = true;
1296 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_CREATE']}</span></td></tr>";
1308 * test perms for INSERT
1310 function testPermsInsert($type, $out, $skip=false) {
1311 logThis('Checking INSERT INTO permissions...');
1313 global $mod_strings;
1319 $db->query("INSERT INTO temp (id) VALUES ('abcdef0123456789abcdef0123456789abcd')");
1320 if($db->checkError()) {
1321 logThis('cannot INSERT INTO!');
1322 $out['db']['dbNoInsert'] = true;
1323 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_INSERT']}</span></td></tr>";
1337 * test perms for UPDATE TABLE
1339 function testPermsUpdate($type, $out, $skip=false) {
1340 logThis('Checking UPDATE TABLE permissions...');
1342 global $mod_strings;
1348 $db->query("UPDATE temp SET id = '000000000000000000000000000000000000' WHERE id = 'abcdef0123456789abcdef0123456789abcd'");
1349 if($db->checkError()) {
1350 logThis('cannot UPDATE TABLE!');
1351 $out['db']['dbNoUpdate'] = true;
1352 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_UPDATE']}</span></td></tr>";
1366 * test perms for SELECT
1368 function testPermsSelect($type, $out, $skip=false) {
1369 logThis('Checking SELECT permissions...');
1371 global $mod_strings;
1376 $r = $db->query('SELECT id FROM temp');
1377 if($db->checkError()) {
1378 logThis('cannot SELECT!');
1379 $out['db']['dbNoSelect'] = true;
1380 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_SELECT']}</span></td></tr>";
1382 logThis('Checking validity of SELECT results');
1383 while($a = $db->fetchByAssoc($r)) {
1384 if($a['id'] != '000000000000000000000000000000000000') {
1385 logThis('results DO NOT MATCH! got: '.$a['id']);
1386 $out['db'][] = 'selectFailed';
1387 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_INSERT_FAILED']}</span></td></tr>";
1402 * test perms for DELETE
1404 function testPermsDelete($type, $out, $skip=false) {
1405 logThis('Checking DELETE FROM permissions...');
1407 global $mod_strings;
1412 $db->query("DELETE FROM temp WHERE id = '000000000000000000000000000000000000'");
1413 if($db->checkError()) {
1414 logThis('cannot DELETE FROM!');
1415 $out['db']['dbNoDelete'] = true;
1416 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_DELETE']}</span></td></tr>";
1429 * test perms for ALTER TABLE ADD COLUMN
1431 function testPermsAlterTableAdd($type, $out, $skip=false) {
1432 logThis('Checking ALTER TABLE ADD COLUMN permissions...');
1434 global $mod_strings;
1438 $db->query('ALTER TABLE temp ADD COLUMN test varchar(100)');
1439 if($db->checkError()) {
1440 logThis('cannot ADD COLUMN!');
1441 $out['db']['dbNoAddColumn'] = true;
1442 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_ADD_COLUMN']}</span></td></tr>";
1447 $db->query('ALTER TABLE [temp] ADD [test] [varchar] (100)');
1448 if($db->checkError()) {
1449 logThis('cannot ADD COLUMN!');
1450 $out['db']['dbNoAddColumn'] = true;
1451 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_ADD_COLUMN']}</span></td></tr>";
1466 * test perms for ALTER TABLE ADD COLUMN
1468 function testPermsAlterTableChange($type, $out, $skip=false) {
1469 logThis('Checking ALTER TABLE CHANGE COLUMN permissions...');
1471 global $mod_strings;
1475 $db->query('ALTER TABLE temp CHANGE COLUMN test test varchar(100)');
1476 if($db->checkError()) {
1477 logThis('cannot CHANGE COLUMN!');
1478 $out['db']['dbNoChangeColumn'] = true;
1479 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_CHANGE_COLUMN']}</span></td></tr>";
1484 $db->query('ALTER TABLE [temp] ALTER COLUMN [test] [varchar] (100)');
1485 if($db->checkError()) {
1486 logThis('cannot CHANGE COLUMN!');
1487 $out['db']['dbNoChangeColumn'] = true;
1488 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_CHANGE_COLUMN']}</span></td></tr>";
1502 * test perms for ALTER TABLE DROP COLUMN
1504 function testPermsAlterTableDrop($type, $out, $skip=false) {
1505 logThis('Checking ALTER TABLE DROP COLUMN permissions...');
1507 global $mod_strings;
1512 $db->query('ALTER TABLE temp DROP COLUMN test');
1513 if($db->checkError()) {
1514 logThis('cannot DROP COLUMN!');
1515 $out['db']['dbNoDropColumn'] = true;
1516 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_DROP_COLUMN']}</span></td></tr>";
1529 * test perms for DROP TABLE
1531 function testPermsDropTable($type, $out, $skip=false) {
1532 logThis('Checking DROP TABLE permissions...');
1534 global $mod_strings;
1539 $db->query('DROP TABLE temp');
1540 if($db->checkError()) {
1541 logThis('cannot DROP TABLE!');
1542 $out['db']['dbNoDropTable'] = true;
1543 $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_DROP_TABLE']}</span></td></tr>";
1556 function createMSSQLTemp($table) {
1557 global $sugar_config;
1560 $qtest = "SELECT TABLE_NAME tn FROM information.tables WHERE TABLE_NAME = '{$table}__UW_TEMP'";
1561 $rtest = $db->query($qtest);
1562 $atest = $db->fetchByAssoc($rtest);
1565 $tempTable = "CREATE TABLE {$table}__UW_TEMP AS ".$db->limitQuerySql("SELECT * FROM {$table}",0,8);
1566 logThis("Creating temp table for {$table}: {$tempTable}");
1567 $db->query($tempTable);
1570 logThis("Found {$table}__UW_TEMP - skipping temp table creation.");
1575 * Tests an ALTER TABLE query
1576 * @param string table The table name to get DDL
1577 * @param string dbType MySQL, MSSQL, etc.
1578 * @param string query The query to test.
1579 * @return string Non-empty if error found
1581 function testQueryAlter($table, $dbType, $query, $newTables) {
1582 logThis('verifying ALTER statement...');
1584 global $sugar_config;
1587 $db = &DBManagerFactory::getInstance();
1590 // Skipping ALTER TABLE [table] DROP PRIMARY KEY because primary keys are not being copied
1591 // over to the temp tables
1592 if(strpos(strtoupper($query), 'DROP PRIMARY KEY') !== false) {
1593 logThis('Skipping DROP PRIMARY KEY verification');
1597 if ($dbType == 'mysql'){
1598 mysql_error(); // initialize errors
1602 if(!in_array($table, $newTables)) {
1606 logThis('creating temp table for ['.$table.']...');
1607 $q = "SHOW CREATE TABLE {$table}";
1608 $r = $db->query($q);
1609 $a = $db->fetchByAssoc($r);
1611 // rewrite DDL with _temp name
1612 $cleanQuery = cleanQuery($a['Create Table']);
1613 $tempTableQuery = str_replace("CREATE TABLE `{$table}`", "CREATE TABLE `{$table}__uw_temp`", $cleanQuery);
1614 $r2 = $db->query($tempTableQuery);
1616 // get sample data into the temp table to test for data/constraint conflicts
1617 logThis('inserting temp dataset...');
1618 $q3 = "INSERT INTO `{$table}__uw_temp` SELECT * FROM `{$table}` LIMIT 10";
1619 $r3 = $db->query($q3, false, "Preflight Failed for: {$query}");
1621 // test the query on the test table
1622 logThis('testing query: ['.$query.']');
1623 $tempTableTestQuery = str_replace("ALTER TABLE `{$table}`", "ALTER TABLE `{$table}__uw_temp`", $query);
1624 if (strpos($tempTableTestQuery, 'idx') === false) {
1625 if(isRunningAgainstTrueTable($tempTableTestQuery)) {
1626 $error = getFormattedError('Could not use a temp table to test query!', $query);
1630 logThis('testing query on temp table: ['.$tempTableTestQuery.']');
1631 $r4 = $db->query($tempTableTestQuery, false, "Preflight Failed for: {$query}");
1634 // test insertion of an index on a table
1635 $tempTableTestQuery_idx = str_replace("ADD INDEX `idx_", "ADD INDEX `temp_idx_", $tempTableTestQuery);
1636 logThis('testing query on temp table: ['.$tempTableTestQuery_idx.']');
1637 $r4 = $db->query($tempTableTestQuery_idx, false, "Preflight Failed for: {$query}");
1639 $mysqlError = mysql_error(); // empty on no-errors
1640 if(!empty($mysqlError)) {
1641 logThis('*** ERROR: query failed: '.$mysqlError);
1642 $error = getFormattedError($mysqlError, $query);
1646 // clean up moved to end of preflight
1650 logThis('mssql found: skipping test query - ['.$query.']');
1654 logThis('Oracle found: skipping test query - ['.$query.']');
1658 logThis($table . ' is a new table');
1661 logThis('verification done.');
1666 * Tests an CREATE TABLE query
1667 * @param string table The table name to get DDL
1668 * @param string dbType MySQL, MSSQL, etc.
1669 * @param string query The query to test.
1670 * @return string Non-empty if error found
1672 function testQueryCreate($table, $dbType, $query, &$newTables) {
1673 logThis('verifying CREATE statement...');
1676 $db = &DBManagerFactory::getInstance();
1682 // rewrite DDL with _temp name
1683 logThis('testing query: ['.$query.']');
1684 $tempTableQuery = str_replace("CREATE TABLE `{$table}`", "CREATE TABLE `{$table}__uw_temp`", $query);
1686 if(isRunningAgainstTrueTable($tempTableQuery)) {
1687 $error = getFormattedError('Could not use a temp table to test query!', $query);
1691 $r4 = $db->query($tempTableQuery, false, "Preflight Failed for: {$query}");
1693 $error = mysql_error(); // empty on no-errors
1694 if(!empty($error)) {
1695 logThis('*** ERROR: query failed.');
1696 $error = getFormattedError($error, $query);
1699 // check if table exists
1700 logThis('testing for table: '.$table);
1701 $q1 = "DESC `{$table}`";
1702 $r1 = $db->query($q1);
1704 $mysqlError = mysql_error();
1705 if(empty($mysqlError)) {
1706 logThis('*** ERROR: table already exists!: '.$table);
1707 $error = getFormattedError('table exists', $query);
1710 logThis('NEW TABLE: '.$query);
1711 $newTables[] = $table;
1716 logThis('mssql found: skipping test query - ['.$query.']');
1720 logThis('Oracle found: skipping test query - ['.$query.']');
1727 * Tests an DELETE FROM query
1728 * @param string table The table name to get DDL
1729 * @param string dbType MySQL, MSSQL, etc.
1730 * @param string query The query to test.
1731 * @return string Non-empty if error found
1733 function testQueryDelete($table, $dbType, $query) {
1734 logThis('verifying DELETE statements');
1737 $db = &DBManagerFactory::getInstance();
1745 logThis('creating temp table...');
1746 $q = "SHOW CREATE TABLE {$table}";
1747 $r = $db->query($q);
1748 $a = $db->fetchByAssoc($r);
1750 // rewrite DDL with _temp name
1751 $cleanQuery = cleanQuery($a['Create Table']);
1752 $tempTableQuery = str_replace("CREATE TABLE `{$table}`", "CREATE TABLE `{$table}__uw_temp`", $cleanQuery);
1753 $r2 = $db->query($tempTableQuery);
1755 // get sample data into the temp table to test for data/constraint conflicts
1756 logThis('inserting temp dataset...');
1757 $q3 = "INSERT INTO `{$table}__uw_temp` SELECT * FROM `{$table}` LIMIT 10";
1758 $r3 = $db->query($q3);
1760 // test the query on the test table
1761 logThis('testing query: ['.$query.']');
1762 $tempTableTestQuery = str_replace("DELETE FROM `{$table}`", "DELETE FROM `{$table}__uw_temp`", $query);
1764 if(isRunningAgainstTrueTable($tempTableTestQuery)) {
1765 $error = getFormattedError('Could not use a temp table to test query!', $tempTableTestQuery);
1769 $r4 = $db->query($tempTableTestQuery, false, "Preflight Failed for: {$query}");
1770 $error = mysql_error(); // empty on no-errors
1771 if(!empty($error)) {
1772 logThis('*** ERROR: query failed.');
1773 $error = getFormattedError($error, $query);
1778 logThis('mssql found: skipping test query - ['.$query.']');
1782 logThis('Oracle found: skipping test query - ['.$query.']');
1785 logThis('verification done.');
1790 * Tests a DROP TABLE query
1793 function testQueryDrop($table, $dbType, $query) {
1794 logThis('verifying DROP TABLE statement');
1797 $db = &DBManagerFactory::getInstance();
1805 logThis('creating temp table...');
1806 $q = "SHOW CREATE TABLE {$table}";
1807 $r = $db->query($q);
1808 $a = $db->fetchByAssoc($r);
1810 // rewrite DDL with _temp name
1811 $cleanQuery = cleanQuery($a['Create Table']);
1812 $tempTableQuery = str_replace("CREATE TABLE `{$table}`", "CREATE TABLE `{$table}__uw_temp`", $cleanQuery);
1813 $r2 = $db->query($tempTableQuery);
1815 // get sample data into the temp table to test for data/constraint conflicts
1816 logThis('inserting temp dataset...');
1817 $query = stripQuotesUW($query, $table);
1818 $q3 = "INSERT INTO `{$table}__uw_temp` SELECT * FROM `{$table}` LIMIT 10";
1819 $r3 = $db->query($q3);
1821 // test the query on the test table
1822 logThis('testing query: ['.$query.']');
1823 $tempTableTestQuery = str_replace("DROP TABLE `{$table}`", "DROP TABLE `{$table}__uw_temp`", $query);
1825 // make sure the test query is running against a temp table
1826 if(isRunningAgainstTrueTable($tempTableTestQuery)) {
1827 $error = getFormattedError('Could not use a temp table to test query!', $tempTableTestQuery);
1831 $r4 = $db->query($tempTableTestQuery, false, "Preflight Failed for: {$query}");
1832 $error = mysql_error(); // empty on no-errors
1833 if(!empty($error)) {
1834 logThis('*** ERROR: query failed.');
1835 $error = getFormattedError($error, $query);
1840 logThis('mssql found: skipping test query - ['.$query.']');
1844 logThis('Oracle found: skipping test query - ['.$query.']');
1847 logThis('verification done.');
1852 * Tests an INSERT INTO query
1853 * @param string table The table name to get DDL
1854 * @param string dbType MySQL, MSSQL, etc.
1855 * @param string query The query to test.
1856 * @return string Non-empty if error found
1858 function testQueryInsert($table, $dbType, $query) {
1859 logThis('verifying INSERT statement...');
1862 $db = &DBManagerFactory::getInstance();
1870 $q = "SHOW CREATE TABLE {$table}";
1871 $r = $db->query($q);
1872 $a = $db->fetchByAssoc($r);
1874 // rewrite DDL with _temp name
1875 $cleanQuery = cleanQuery($a['Create Table']);
1876 $tempTableQuery = str_replace("CREATE TABLE `{$table}`", "CREATE TABLE `{$table}__uw_temp`", $cleanQuery);
1877 $r2 = $db->query($tempTableQuery);
1879 // test the query on the test table
1880 logThis('testing query: ['.$query.']');
1881 $tempTableTestQuery = str_replace("INSERT INTO `{$table}`", "INSERT INTO `{$table}__uw_temp`", $query);
1883 // make sure the test query is running against a temp table
1884 if(isRunningAgainstTrueTable($tempTableTestQuery)) {
1885 $error = getFormattedError('Could not use a temp table to test query!', $tempTableTestQuery);
1889 $r4 = $db->query($tempTableTestQuery, false, "Preflight Failed for: {$query}");
1890 $error = mysql_error(); // empty on no-errors
1891 if(!empty($error)) {
1892 logThis('*** ERROR: query failed.');
1893 $error = getFormattedError($error, $query);
1898 logThis('mssql found: skipping test query - ['.$query.']');
1902 logThis('Oracle found: skipping test query - ['.$query.']');
1905 logThis('verification done.');
1911 * Tests an UPDATE TABLE query
1912 * @param string table The table name to get DDL
1913 * @param string dbType MySQL, MSSQL, etc.
1914 * @param string query The query to test.
1915 * @return string Non-empty if error found
1917 function testQueryUpdate($table, $dbType, $query) {
1918 logThis('verifying UPDATE TABLE statement...');
1921 $db = &DBManagerFactory::getInstance();
1929 $q = "SHOW CREATE TABLE {$table}";
1930 $r = $db->query($q);
1931 $a = $db->fetchByAssoc($r);
1933 // rewrite DDL with _temp name
1934 $cleanQuery = cleanQuery($a['Create Table']);
1935 $tempTableQuery = str_replace("CREATE TABLE `{$table}`", "CREATE TABLE `{$table}__uw_temp`", $cleanQuery);
1936 $r2 = $db->query($tempTableQuery);
1938 // get sample data into the temp table to test for data/constraint conflicts
1939 logThis('inserting temp dataset...');
1940 $q3 = "INSERT INTO `{$table}__uw_temp` SELECT * FROM `{$table}` LIMIT 10";
1941 $r3 = $db->query($q3, false, "Preflight Failed for: {$query}");
1943 // test the query on the test table
1944 logThis('testing query: ['.$query.']');
1945 $tempTableTestQuery = str_replace("UPDATE `{$table}`", "UPDATE `{$table}__uw_temp`", $query);
1947 // make sure the test query is running against a temp table
1948 if(isRunningAgainstTrueTable($tempTableTestQuery)) {
1949 $error = getFormattedError('Could not use a temp table to test query!', $tempTableTestQuery);
1953 $r4 = $db->query($tempTableTestQuery, false, "Preflight Failed for: {$query}");
1954 $error = mysql_error(); // empty on no-errors
1955 if(!empty($error)) {
1956 logThis('*** ERROR: query failed.');
1957 $error = getFormattedError($error, $query);
1965 logThis('Oracle found: skipping test query - ['.$query.']');
1968 logThis('verification done.');
1974 * strip queries of single and double quotes
1976 function stripQuotesUW($query, $table) {
1979 $start = strpos($query, $table);
1981 if(substr($query, ($start - 1), 1) != ' ') {
1982 $queryStrip = substr($query, 0, ($start-2));
1983 $queryStrip .= " {$table} ";
1984 $queryStrip .= substr($query, ($start + strlen($table) + 2), strlen($query));
1987 return (empty($queryStrip)) ? $query : $queryStrip;
1991 * ensures that a __UW_TEMP table test SQL is running against a temp table, not the real thing
1992 * @param string query
1993 * @return bool false if it is a good query
1995 function isRunningAgainstTrueTable($query) {
1996 $query = strtoupper($query);
1997 if(strpos($query, '__UW_TEMP') === false) {
1998 logThis('***ERROR: test query is NOT running against a temp table!!!! -> '.$query);
2013 * cleans up temp tables created during schema test phase
2015 function testCleanUp($dbType) {
2016 logThis('Cleaning up temporary tables...');
2020 $db = &DBManagerFactory::getInstance();
2026 $q = 'SHOW TABLES LIKE "%__uw_temp"';
2027 $r = $db->query($q, false, "Preflight Failed for: {$q}");
2029 // using raw mysql_command to use integer index
2030 while($a = $db->fetchByAssoc($r)) {
2031 logThis('Dropping table: '.$a[0]);
2032 $qClean = "DROP TABLE {$a[0]}";
2033 $rClean = $db->query($qClean);
2043 logThis('Done cleaning up temp tables.');
2048 function getFormattedError($error, $query) {
2049 $error = "<div><b>".$error;
2050 $error .= "</b>::{$query}</div>";
2058 * parses a query finding the table name
2059 * @param string query The query
2060 * @return string table The table
2062 function getTableFromQuery($query) {
2063 $standardQueries = array('ALTER TABLE', 'DROP TABLE', 'CREATE TABLE', 'INSERT INTO', 'UPDATE', 'DELETE FROM');
2064 $query = preg_replace("/[^A-Za-z0-9\_\s]/", "", $query);
2065 $query = trim(str_replace($standardQueries, '', $query));
2067 $firstSpc = strpos($query, " ");
2068 $end = ($firstSpc > 0) ? $firstSpc : strlen($query);
2069 $table = substr($query, 0, $end);
2076 function preLicenseCheck() {
2077 require_once('modules/UpgradeWizard/uw_files.php');
2079 global $sugar_config;
2080 global $mod_strings;
2081 global $sugar_version;
2083 if(!isset($sugar_version) || empty($sugar_version)) {
2084 require_once('./sugar_version.php');
2087 if(!isset($_SESSION['unzip_dir']) || empty($_SESSION['unzip_dir'])) {
2088 logThis('unzipping files in upgrade archive...');
2090 $base_upgrade_dir = $sugar_config['upload_dir'] . "/upgrades";
2091 $base_tmp_upgrade_dir = "$base_upgrade_dir/temp";
2093 //also come up with mechanism to read from upgrade-progress file
2094 if(!isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !is_file($_SESSION['install_file'])) {
2096 if ($handle = opendir(clean_path($sugar_config['upload_dir']))) {
2097 while (false !== ($file = readdir($handle))) {
2098 if($file !="." && $file !="..") {
2099 $far = explode(".",$file);
2100 if($far[sizeof($far)-1] == 'zip') {
2101 echo $sugar_config['upload_dir'].'/'.$file;
2102 $_SESSION['install_file'] = $sugar_config['upload_dir'].'/'.$file;
2108 if (file_exists(clean_path($base_tmp_upgrade_dir)) && $handle = opendir(clean_path($base_tmp_upgrade_dir))) {
2109 while (false !== ($file = readdir($handle))) {
2110 if($file !="." && $file !="..") {
2111 //echo $base_tmp_upgrade_dir."/".$file.'</br>';
2112 if(is_file($base_tmp_upgrade_dir."/".$file."/manifest.php")){
2113 require_once($base_tmp_upgrade_dir."/".$file."/manifest.php");
2114 $package_name= $manifest['copy_files']['from_dir'];
2115 //echo file_exists($base_tmp_upgrade_dir."/".$file."/".$package_name).'</br>';
2116 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")){
2117 //echo 'Yeah this the directory '. $base_tmp_upgrade_dir."/".$file;
2118 $unzip_dir = $base_tmp_upgrade_dir."/".$file;
2119 if(file_exists($sugar_config['upload_dir'].'/upgrades/patch/'.$package_name.'.zip')){
2120 $_SESSION['install_file'] = $sugar_config['upload_dir'].'/upgrades/patch/'.$package_name.'.zip';
2129 if(!isset($_SESSION['install_file']) || empty($_SESSION['install_file'])){
2132 echo 'Upload File not found so redirecting to Upgrade Start ';
2133 $redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
2134 echo '<form name="redirect" action="' .$redirect_new_wizard. '" method="POST">';
2135 $upgrade_directories_not_found =<<<eoq
2136 <table cellpadding="3" cellspacing="0" border="0">
2138 <th colspan="2" align="left">
2139 <span class='error'><b>'Upload file missing or has been deleted. Refresh the page to go back to UpgradeWizard start'</b></span>
2144 $uwMain = $upgrade_directories_not_found;
2147 $install_file = urldecode( $_SESSION['install_file'] );
2149 if(empty($unzip_dir)){
2150 $unzip_dir = mk_temp_dir( $base_tmp_upgrade_dir );
2152 $zip_from_dir = ".";
2154 $zip_force_copy = array();
2157 logThis('Could not create a temporary directory using mk_temp_dir( $base_tmp_upgrade_dir )');
2158 die($mod_strings['ERR_UW_NO_CREATE_TMP_DIR']);
2161 //double check whether unzipped .
2162 if(file_exists($unzip_dir ."/scripts") && file_exists($unzip_dir."/manifest.php")){
2166 unzip( $install_file, $unzip_dir );
2169 // assumption -- already validated manifest.php at time of upload
2170 require_once( "$unzip_dir/manifest.php" );
2172 if( isset( $manifest['copy_files']['from_dir'] ) && $manifest['copy_files']['from_dir'] != "" ){
2173 $zip_from_dir = $manifest['copy_files']['from_dir'];
2175 if( isset( $manifest['copy_files']['to_dir'] ) && $manifest['copy_files']['to_dir'] != "" ){
2176 $zip_to_dir = $manifest['copy_files']['to_dir'];
2178 if( isset( $manifest['copy_files']['force_copy'] ) && $manifest['copy_files']['force_copy'] != "" ){
2179 $zip_force_copy = $manifest['copy_files']['force_copy'];
2181 if( isset( $manifest['version'] ) ){
2182 $version = $manifest['version'];
2184 if( !is_writable( "config.php" ) ){
2185 return $mod_strings['ERR_UW_CONFIG'];
2188 $_SESSION['unzip_dir'] = clean_path($unzip_dir);
2189 $_SESSION['zip_from_dir'] = clean_path($zip_from_dir);
2190 logThis('unzip done.');
2192 $unzip_dir = $_SESSION['unzip_dir'];
2193 $zip_from_dir = $_SESSION['zip_from_dir'];
2196 //check if $_SESSION['unzip_dir'] and $_SESSION['zip_from_dir'] exist
2197 if(!isset($_SESSION['unzip_dir']) || !file_exists($_SESSION['unzip_dir'])
2198 || !isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !file_exists($_SESSION['install_file'])){
2202 echo 'Upload File not found so redirecting to Upgrade Start ';
2203 $redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
2204 echo '<form name="redirect" action="' .$redirect_new_wizard. '" method="POST">';
2205 $upgrade_directories_not_found =<<<eoq
2206 <table cellpadding="3" cellspacing="0" border="0">
2208 <th colspan="2" align="left">
2209 <span class='error'><b>'Upload file missing or has been deleted. Refresh the page to go back to UpgradeWizard start'</b></span>
2214 $uwMain = $upgrade_directories_not_found;
2218 $parserFiles = array();
2220 if(file_exists(clean_path($unzip_dir.'/'.$zip_from_dir."/include/SugarFields"))) {
2221 $parserFiles = findAllFiles(clean_path($unzip_dir.'/'.$zip_from_dir."/include/SugarFields"), $parserFiles);
2224 $cwd = clean_path(getcwd());
2225 foreach($parserFiles as $file) {
2226 $srcFile = clean_path($file);
2227 //$targetFile = clean_path(getcwd() . '/' . $srcFile);
2228 if (strpos($srcFile,".svn") !== false) {
2232 $targetFile = str_replace(clean_path($unzip_dir.'/'.$zip_from_dir), $cwd, $srcFile);
2234 if(!is_dir(dirname($targetFile))) {
2235 mkdir_recursive(dirname($targetFile)); // make sure the directory exists
2238 if(!file_exists($targetFile))
2240 // handle sugar_version.php
2241 // C.L. - Added check for portal directory
2242 if(strpos($targetFile, 'sugar_version.php') !== false && !preg_match('/\/portal\/sugar_version\.php$/i', $targetFile)) {
2243 logThis('Skipping "sugar_version.php" - file copy will occur at end of successful upgrade', $path);
2244 $_SESSION['sugar_version_file'] = $srcFile;
2248 //logThis('Copying file to destination: ' . $targetFile);
2250 if(!copy($srcFile, $targetFile)) {
2251 logThis('*** ERROR: could not copy file: ' . $targetFile);
2253 $copiedFiles[] = $targetFile;
2256 //logThis('Skipping file: ' . $targetFile);
2257 //$skippedFiles[] = $targetFile;
2262 //Also copy the SugarMerge files
2263 if(file_exists(clean_path($unzip_dir.'/'.$zip_from_dir."/UpgradeWizard510Files"))) {
2264 $parserFiles = findAllFiles(clean_path($unzip_dir.'/'.$zip_from_dir."/UpgradeWizard510Files"), $parserFiles);
2265 foreach($parserFiles as $file) {
2266 $srcFile = clean_path($file);
2267 //$targetFile = clean_path(getcwd() . '/' . $srcFile);
2268 if (strpos($srcFile,".svn") !== false) {
2272 $targetFile = str_replace(clean_path($unzip_dir.'/'.$zip_from_dir."/UpgradeWizard510Files"), $cwd, $srcFile);
2273 if(!is_dir(dirname($targetFile))) {
2274 mkdir_recursive(dirname($targetFile)); // make sure the directory exists
2276 logThis('updating UpgradeWizard code: '.$targetFile);
2277 copy_recursive($file, $targetFile);
2281 logThis ('is SugarConfig there '.file_exists(clean_path($unzip_dir.'/'.$zip_from_dir."/include/SugarObjects/SugarConfig.php")));
2282 if(file_exists(clean_path($unzip_dir.'/'.$zip_from_dir."/include/SugarObjects/SugarConfig.php"))) {
2283 $file = clean_path($unzip_dir.'/'.$zip_from_dir."/include/SugarObjects/SugarConfig.php");
2284 $destFile = str_replace(clean_path($unzip_dir.'/'.$zip_from_dir), $cwd, $file);
2285 if(!is_dir(dirname($destFile))) {
2286 mkdir_recursive(dirname($destFile)); // make sure the directory exists
2288 copy($file,$destFile);
2289 //also copy include utils array utils
2290 $file = clean_path($unzip_dir.'/'.$zip_from_dir."/include/utils/array_utils.php");
2291 $destFile = str_replace(clean_path($unzip_dir.'/'.$zip_from_dir), $cwd, $file);
2292 if(!is_dir(dirname($destFile))) {
2293 mkdir_recursive(dirname($destFile)); // make sure the directory exists
2295 copy($file,$destFile);
2300 function preflightCheck() {
2301 require_once('modules/UpgradeWizard/uw_files.php');
2303 global $sugar_config;
2304 global $mod_strings;
2305 global $sugar_version;
2307 if(!isset($sugar_version) || empty($sugar_version)) {
2308 require_once('./sugar_version.php');
2311 unset($_SESSION['rebuild_relationships']);
2312 unset($_SESSION['rebuild_extensions']);
2314 // don't bother if are rechecking
2315 $manualDiff = array();
2316 if(!isset($_SESSION['unzip_dir']) || empty($_SESSION['unzip_dir'])) {
2317 logThis('unzipping files in upgrade archive...');
2319 $base_upgrade_dir = $sugar_config['upload_dir'] . "/upgrades";
2320 $base_tmp_upgrade_dir = "$base_upgrade_dir/temp";
2322 //Following is if User logged out unexpectedly and then logged into UpgradeWizard again.
2323 //also come up with mechanism to read from upgrade-progress file.
2324 if(!isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !is_file($_SESSION['install_file'])) {
2325 if (file_exists(clean_path($base_tmp_upgrade_dir)) && $handle = opendir(clean_path($base_tmp_upgrade_dir))) {
2326 while (false !== ($file = readdir($handle))) {
2327 if($file !="." && $file !="..") {
2328 //echo $base_tmp_upgrade_dir."/".$file.'</br>';
2329 if(is_file($base_tmp_upgrade_dir."/".$file."/manifest.php")){
2330 require_once($base_tmp_upgrade_dir."/".$file."/manifest.php");
2331 $package_name= $manifest['copy_files']['from_dir'];
2332 //echo file_exists($base_tmp_upgrade_dir."/".$file."/".$package_name).'</br>';
2333 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")){
2334 //echo 'Yeah this the directory '. $base_tmp_upgrade_dir."/".$file;
2335 $unzip_dir = $base_tmp_upgrade_dir."/".$file;
2336 if(file_exists($sugar_config['upload_dir'].'/upgrades/patch/'.$package_name.'.zip')){
2337 $_SESSION['install_file'] = $sugar_config['upload_dir'].'/upgrades/patch/'.$package_name.'.zip';
2346 if(!isset($_SESSION['install_file']) || empty($_SESSION['install_file'])){
2349 echo 'Upload File not found so redirecting to Upgrade Start ';
2350 $redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
2351 echo '<form name="redirect" action="' .$redirect_new_wizard. '" method="POST">';
2352 $upgrade_directories_not_found =<<<eoq
2353 <table cellpadding="3" cellspacing="0" border="0">
2355 <th colspan="2" align="left">
2356 <span class='error'><b>'Upload file missing or has been deleted. Refresh the page to go back to UpgradeWizard start'</b></span>
2361 $uwMain = $upgrade_directories_not_found;
2365 $install_file = urldecode( $_SESSION['install_file'] );
2367 if(empty($unzip_dir)){
2368 $unzip_dir = mk_temp_dir( $base_tmp_upgrade_dir );
2370 $zip_from_dir = ".";
2372 $zip_force_copy = array();
2375 logThis('Could not create a temporary directory using mk_temp_dir( $base_tmp_upgrade_dir )');
2376 die($mod_strings['ERR_UW_NO_CREATE_TMP_DIR']);
2379 //double check whether unzipped .
2380 if(file_exists($unzip_dir ."/scripts") && file_exists($unzip_dir."/manifest.php")){
2384 unzip( $install_file, $unzip_dir );
2387 // assumption -- already validated manifest.php at time of upload
2388 require_once( "$unzip_dir/manifest.php" );
2390 if( isset( $manifest['copy_files']['from_dir'] ) && $manifest['copy_files']['from_dir'] != "" ){
2391 $zip_from_dir = $manifest['copy_files']['from_dir'];
2393 if( isset( $manifest['copy_files']['to_dir'] ) && $manifest['copy_files']['to_dir'] != "" ){
2394 $zip_to_dir = $manifest['copy_files']['to_dir'];
2396 if( isset( $manifest['copy_files']['force_copy'] ) && $manifest['copy_files']['force_copy'] != "" ){
2397 $zip_force_copy = $manifest['copy_files']['force_copy'];
2399 if( isset( $manifest['version'] ) ){
2400 $version = $manifest['version'];
2402 if( !is_writable( "config.php" ) ){
2403 return $mod_strings['ERR_UW_CONFIG'];
2406 $_SESSION['unzip_dir'] = clean_path($unzip_dir);
2407 $_SESSION['zip_from_dir'] = clean_path($zip_from_dir);
2409 //logThis('unzip done.');
2411 $unzip_dir = $_SESSION['unzip_dir'];
2412 $zip_from_dir = $_SESSION['zip_from_dir'];
2414 //check if $_SESSION['unzip_dir'] and $_SESSION['zip_from_dir'] exist
2415 if(!isset($_SESSION['unzip_dir']) || !file_exists($_SESSION['unzip_dir'])
2416 || !isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !file_exists($_SESSION['install_file'])){
2420 echo 'Upload File not found so redirecting to Upgrade Start ';
2421 $redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
2422 echo '<form name="redirect" action="' .$redirect_new_wizard. '" method="POST">';
2423 $upgrade_directories_not_found =<<<eoq
2424 <table cellpadding="3" cellspacing="0" border="0">
2426 <th colspan="2" align="left">
2427 <span class='error'><b>'Upload file missing or has been deleted. Refresh the page to go back to UpgradeWizard start'</b></span>
2432 $uwMain = $upgrade_directories_not_found;
2435 //copy minimum required files
2436 fileCopy('include/utils/sugar_file_utils.php');
2439 if(file_exists('include/utils/file_utils.php')){
2442 $upgradeFiles = findAllFiles(clean_path("$unzip_dir/$zip_from_dir"), array());
2443 $cache_html_files= array();
2444 if(is_dir("{$GLOBALS['sugar_config']['cache_dir']}layout")){
2445 //$cache_html_files = findAllFilesRelative( "cache/layout", array());
2449 $md5_string = array();
2450 if(file_exists(clean_path(getcwd().'/files.md5'))){
2451 require(clean_path(getcwd().'/files.md5'));
2454 // file preflight checks
2455 logThis('verifying md5 checksums for files...');
2456 foreach($upgradeFiles as $file) {
2457 if(in_array(str_replace(clean_path("$unzip_dir/$zip_from_dir") . "/", '', $file), $uw_files))
2458 continue; // skip already loaded files
2460 if(strpos($file, '.md5'))
2461 continue; // skip md5 file
2463 // normalize file paths
2464 $file = clean_path($file);
2466 // check that we can move/delete the upgraded file
2467 if(!is_writable($file)) {
2468 $errors[] = $mod_strings['ERR_UW_FILE_NOT_WRITABLE'].": ".$file;
2470 // check that destination files are writable
2471 $destFile = getcwd().str_replace(clean_path($unzip_dir.'/'.$zip_from_dir), '', $file);
2473 if(is_file($destFile)) { // of course it needs to exist first...
2474 if(!is_writable($destFile)) {
2475 $errors[] = $mod_strings['ERR_UW_FILE_NOT_WRITABLE'].": ".$destFile;
2479 ///////////////////////////////////////////////////////////////////////
2481 // compare md5s and build up a manual merge list
2482 $targetFile = clean_path(".".str_replace(getcwd(),'',$destFile));
2484 if(is_file($destFile)) {
2485 if(strpos($targetFile, '.php')) {
2486 // handle PHP files that were hit with the security regex
2488 if(function_exists('sugar_fopen')){
2489 $fp = sugar_fopen($destFile, 'r');
2492 $fp = fopen($destFile, 'r');
2494 $filesize = filesize($destFile);
2496 $fileContents = stream_get_contents($fp);
2497 $targetMd5 = md5($fileContents);
2500 $targetMd5 = md5_file($destFile);
2504 if(isset($md5_string[$targetFile]) && $md5_string[$targetFile] != $targetMd5) {
2505 logThis('found a file with a differing md5: ['.$targetFile.']');
2506 $manualDiff[] = $destFile;
2509 ///////////////////////////////////////////////////////////////////////
2511 logThis('md5 verification done.');
2512 $errors['manual'] = $manualDiff;
2517 function fileCopy($file_path){
2518 if(file_exists(clean_path($_SESSION['unzip_dir'].'/'.$_SESSION['zip_from_dir'].'/'.$file_path))) {
2519 $file = clean_path($_SESSION['unzip_dir'].'/'.$_SESSION['zip_from_dir'].'/'.$file_path);
2520 $destFile = str_replace(clean_path($_SESSION['unzip_dir'].'/'.$_SESSION['zip_from_dir']), clean_path(getcwd()), $file);
2521 if(!is_dir(dirname($destFile))) {
2522 mkdir_recursive(dirname($destFile)); // make sure the directory exists
2524 copy_recursive($file,$destFile);
2527 function getChecklist($steps, $step) {
2528 global $mod_strings;
2530 $skip = array('start', 'cancel', 'uninstall','end');
2533 $ret = '<table cellpadding="3" cellspacing="4" border="0">';
2534 $ret .= '<tr><th colspan="3" align="left">'.$mod_strings['LBL_UW_CHECKLIST'].':</th></tr>';
2535 foreach($steps['desc'] as $k => $desc) {
2536 if(in_array($steps['files'][$j], $skip)) {
2541 //$status = "<span class='error'>{$mod_strings['LBL_UW_INCOMPLETE']}</span>";
2543 $desc_mod_post = '';
2545 if(isset($_SESSION['step'][$steps['files'][$k]]) && $_SESSION['step'][$steps['files'][$k]] == 'success') {
2546 //$status = $mod_strings['LBL_UW_COMPLETE'];
2550 if($k == $_REQUEST['step']) {
2551 //$status = $mod_strings['LBL_UW_IN_PROGRESS'];
2552 $desc_mod_pre = "<font color=blue><i>";
2553 $desc_mod_post = "</i></font>";
2556 $ret .= "<tr><td> </td><td><b>{$i}: {$desc_mod_pre}{$desc}{$desc_mod_post}</b></td>";
2557 $ret .= "<td id={$steps['files'][$j]}><i></i></td></tr>";
2565 function prepSystemForUpgrade() {
2566 global $sugar_config;
2567 global $sugar_flavor;
2568 global $mod_strings;
2570 global $base_upgrade_dir;
2571 global $base_tmp_upgrade_dir;
2573 ///////////////////////////////////////////////////////////////////////////////
2574 //// Make sure variables exist
2575 if(!isset($base_upgrade_dir) || empty($base_upgrade_dir)){
2576 $base_upgrade_dir = getcwd().'/'.$sugar_config['upload_dir'] . "upgrades";
2578 if(!isset($base_tmp_upgrade_dir) || empty($base_tmp_upgrade_dir)){
2579 $base_tmp_upgrade_dir = "$base_upgrade_dir/temp";
2581 if(!isset($subdirs) || empty($subdirs)){
2582 $subdirs = array('full', 'langpack', 'module', 'patch', 'theme', 'temp');
2585 $upgrade_progress_dir = getcwd().'/'.$GLOBALS['sugar_config']['upload_dir'].'upgrades/temp';
2586 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
2587 if(file_exists($upgrade_progress_file)){
2588 if(function_exists('get_upgrade_progress') && function_exists('didThisStepRunBefore')){
2589 if(didThisStepRunBefore('end')){
2590 include($upgrade_progress_file);
2591 unset($upgrade_config);
2592 unlink($upgrade_progress_file);
2597 // increase the cuttoff time to 1 hour
2598 ini_set("max_execution_time", "3600");
2600 // make sure dirs exist
2601 if($subdirs != null){
2602 foreach($subdirs as $subdir) {
2603 mkdir_recursive("$base_upgrade_dir/$subdir");
2606 // array of special scripts that are executed during (un)installation-- key is type of script, value is filename
2607 if(!defined('SUGARCRM_PRE_INSTALL_FILE')) {
2608 define('SUGARCRM_PRE_INSTALL_FILE', 'scripts/pre_install.php');
2609 define('SUGARCRM_POST_INSTALL_FILE', 'scripts/post_install.php');
2610 define('SUGARCRM_PRE_UNINSTALL_FILE', 'scripts/pre_uninstall.php');
2611 define('SUGARCRM_POST_UNINSTALL_FILE', 'scripts/post_uninstall.php');
2614 $script_files = array(
2615 "pre-install" => constant('SUGARCRM_PRE_INSTALL_FILE'),
2616 "post-install" => constant('SUGARCRM_POST_INSTALL_FILE'),
2617 "pre-uninstall" => constant('SUGARCRM_PRE_UNINSTALL_FILE'),
2618 "post-uninstall" => constant('SUGARCRM_POST_UNINSTALL_FILE'),
2621 // check that the upload limit is set to 6M or greater
2622 define('SUGARCRM_MIN_UPLOAD_MAX_FILESIZE_BYTES', 6 * 1024 * 1024); // 6 Megabytes
2623 $upload_max_filesize = ini_get('upload_max_filesize');
2624 $upload_max_filesize_bytes = return_bytes($upload_max_filesize);
2626 if($upload_max_filesize_bytes < constant('SUGARCRM_MIN_UPLOAD_MAX_FILESIZE_BYTES')) {
2627 $GLOBALS['log']->debug("detected upload_max_filesize: $upload_max_filesize");
2629 echo '<p class="error">'.$mod_strings['MSG_INCREASE_UPLOAD_MAX_FILESIZE'].' '.get_cfg_var('cfg_file_path')."</p>\n";
2633 if ( !function_exists('extractFile') ) {
2634 function extractFile($zip_file, $file_in_zip) {
2635 global $base_tmp_upgrade_dir;
2638 $absolute_base_tmp_upgrade_dir = clean_path($base_tmp_upgrade_dir);
2639 $relative_base_tmp_upgrade_dir = clean_path(str_replace(clean_path(getcwd()), '', $absolute_base_tmp_upgrade_dir));
2641 // mk_temp_dir expects relative pathing
2642 $my_zip_dir = mk_temp_dir($relative_base_tmp_upgrade_dir);
2644 unzip_file($zip_file, $file_in_zip, $my_zip_dir);
2646 return("$my_zip_dir/$file_in_zip");
2650 if ( !function_exists('extractManifest') ) {
2651 function extractManifest($zip_file) {
2652 logThis('extracting manifest.');
2653 return(extractFile($zip_file, "manifest.php"));
2657 if ( !function_exists('getInstallType') ) {
2658 function getInstallType($type_string) {
2661 $subdirs = array('full', 'langpack', 'module', 'patch', 'theme', 'temp');
2662 foreach($subdirs as $subdir) {
2663 if(preg_match("#/$subdir/#", $type_string)) {
2667 // return empty if no match
2672 function getImageForType($type) {
2677 $icon = SugarThemeRegistry::current()->getImage("Upgrade", "");
2680 $icon = SugarThemeRegistry::current()->getImage("LanguagePacks", "");
2683 $icon = SugarThemeRegistry::current()->getImage("ModuleLoader", "");
2686 $icon = SugarThemeRegistry::current()->getImage("PatchUpgrades", "");
2689 $icon = SugarThemeRegistry::current()->getImage("Themes", "");
2697 if ( !function_exists('getLanguagePackName') ) {
2698 function getLanguagePackName($the_file) {
2699 require_once("$the_file");
2700 if(isset($app_list_strings["language_pack_name"])) {
2701 return($app_list_strings["language_pack_name"]);
2707 function getUITextForType($type) {
2708 if($type == "full") {
2709 return("Full Upgrade");
2711 if($type == "langpack") {
2712 return("Language Pack");
2714 if($type == "module") {
2717 if($type == "patch") {
2720 if($type == "theme") {
2727 * @todo this function doesn't seemed to be used anymore; trying kill this off
2729 function run_upgrade_wizard_sql($script) {
2731 global $sugar_config;
2733 $db_type = $sugar_config['dbconfig']['db_type'];
2734 $script = str_replace("%db_type%", $db_type, $script);
2735 if(!run_sql_file("$unzip_dir/$script")) {
2736 die("Error running sql file: $unzip_dir/$script");
2740 if ( !function_exists('validate_manifest') ) {
2742 * Verifies a manifest from a patch or module to be compatible with the current Sugar version and flavor
2743 * @param array manifest Standard manifest array
2744 * @return string Error message, blank on success
2746 function validate_manifest($manifest) {
2747 logThis('validating manifest.php file');
2748 // takes a manifest.php manifest array and validates contents
2750 global $sugar_version;
2751 global $sugar_flavor;
2752 global $mod_strings;
2754 if(!isset($manifest['type'])) {
2755 return $mod_strings['ERROR_MANIFEST_TYPE'];
2758 $type = $manifest['type'];
2760 if(getInstallType("/$type/") == "") {
2761 return $mod_strings['ERROR_PACKAGE_TYPE']. ": '" . $type . "'.";
2764 if(isset($manifest['acceptable_sugar_versions'])) {
2765 $version_ok = false;
2766 $matches_empty = true;
2767 if(isset($manifest['acceptable_sugar_versions']['exact_matches'])) {
2768 $matches_empty = false;
2769 foreach($manifest['acceptable_sugar_versions']['exact_matches'] as $match) {
2770 if($match == $sugar_version) {
2775 if(!$version_ok && isset($manifest['acceptable_sugar_versions']['regex_matches'])) {
2776 $matches_empty = false;
2777 foreach($manifest['acceptable_sugar_versions']['regex_matches'] as $match) {
2778 if(preg_match("/$match/", $sugar_version)) {
2784 if(!$matches_empty && !$version_ok) {
2785 return $mod_strings['ERROR_VERSION_INCOMPATIBLE']."<br />".
2786 $mod_strings['ERR_UW_VERSION'].$sugar_version;
2790 if(isset($manifest['acceptable_sugar_flavors']) && sizeof($manifest['acceptable_sugar_flavors']) > 0) {
2792 foreach($manifest['acceptable_sugar_flavors'] as $match) {
2793 if($match == $sugar_flavor) {
2798 return $mod_strings['ERROR_FLAVOR_INCOMPATIBLE']."<br />".
2799 $mod_strings['ERR_UW_FLAVOR'].$sugar_flavor."<br />".
2800 $mod_strings['ERR_UW_FLAVOR_2'].$manifest['acceptable_sugar_flavors'][0];
2808 function unlinkUploadFiles() {
2810 // logThis('at unlinkUploadFiles()');
2812 // if(isset($_SESSION['install_file']) && !empty($_SESSION['install_file'])) {
2813 // $upload = $_SESSION['install_file'];
2815 // if(is_file($upload)) {
2816 // logThis('unlinking ['.$upload.']');
2817 // @unlink($upload);
2822 if ( !function_exists('unlinkTempFiles') ) {
2824 * deletes files created by unzipping a package
2826 function unlinkTempFiles() {
2827 global $sugar_config;
2830 logThis('at unlinkTempFiles()');
2832 $sugar_config['upload_dir']='cache/upload/';
2833 //if(isset($sugar_config['upload_dir']) && $sugar_config['upload_dir'] != null && $sugar_config['upload_dir']=='cache/upload/'){
2834 $tempDir = clean_path(getcwd().'/'.$sugar_config['upload_dir'].'upgrades/temp');
2837 $uploadDir = getcwd()."/".'cache/upload/';
2838 $tempDir = clean_path(getcwd().'/'.$uploadDir.'upgrades/temp');
2840 if(file_exists($tempDir) && is_dir($tempDir)){
2841 $files = findAllFiles($tempDir, array(), false);
2843 foreach($files as $file) {
2844 if(!is_dir($file)) {
2845 //logThis('unlinking ['.$file.']', $path);
2850 $files = findAllFiles($tempDir, array(), true);
2851 foreach($files as $dir) {
2853 //logThis('removing dir ['.$dir.']', $path);
2857 $cacheFile = "modules/UpgradeWizard/_persistence.php";
2858 if(is_file($cacheFile)) {
2859 logThis("Unlinking Upgrade cache file: '_persistence.php'", $path);
2860 @unlink($cacheFile);
2863 logThis("finished!");
2868 * finds all files in the passed path, but skips select directories
2869 * @param string dir Relative path
2870 * @param array the_array Collections of found files/dirs
2871 * @param bool include_dir True if we want to include directories in the
2872 * returned collection
2874 function uwFindAllFiles($dir, $the_array, $include_dirs=false, $skip_dirs=array(), $echo=false) {
2876 foreach($skip_dirs as $skipMe) {
2877 if(strpos(clean_path($dir), $skipMe) !== false) {
2884 while($f = $d->read()) {
2885 if($f == "." || $f == "..") { // skip *nix self/parent
2889 // for AJAX length count
2895 if(is_dir("$dir/$f")) {
2896 if($include_dirs) { // add the directory if flagged
2897 $the_array[] = clean_path("$dir/$f");
2901 $the_array = uwFindAllFiles("$dir/$f/", $the_array, $include_dirs, $skip_dirs, $echo);
2903 $the_array[] = clean_path("$dir/$f");
2915 * unset's UW's Session Vars
2917 function resetUwSession() {
2918 logThis('resetting $_SESSION');
2920 if(isset($_SESSION['committed']))
2921 unset($_SESSION['committed']);
2922 if(isset($_SESSION['sugar_version_file']))
2923 unset($_SESSION['sugar_version_file']);
2924 if(isset($_SESSION['upgrade_complete']))
2925 unset($_SESSION['upgrade_complete']);
2926 if(isset($_SESSION['allTables']))
2927 unset($_SESSION['allTables']);
2928 if(isset($_SESSION['alterCustomTableQueries']))
2929 unset($_SESSION['alterCustomTableQueries']);
2930 if(isset($_SESSION['skip_zip_upload']))
2931 unset($_SESSION['skip_zip_upload']);
2932 if(isset($_SESSION['sugar_version_file']))
2933 unset($_SESSION['sugar_version_file']);
2934 if(isset($_SESSION['install_file']))
2935 unset($_SESSION['install_file']);
2936 if(isset($_SESSION['unzip_dir']))
2937 unset($_SESSION['unzip_dir']);
2938 if(isset($_SESSION['zip_from_dir']))
2939 unset($_SESSION['zip_from_dir']);
2940 if(isset($_SESSION['overwrite_files']))
2941 unset($_SESSION['overwrite_files']);
2942 if(isset($_SESSION['schema_change']))
2943 unset($_SESSION['schema_change']);
2944 if(isset($_SESSION['uw_restore_dir']))
2945 unset($_SESSION['uw_restore_dir']);
2946 if(isset($_SESSION['step']))
2947 unset($_SESSION['step']);
2948 if(isset($_SESSION['files']))
2949 unset($_SESSION['files']);
2950 if(isset($_SESSION['Upgraded451Wizard'])){
2951 unset($_SESSION['Upgraded451Wizard']);
2953 if(isset($_SESSION['Initial_451to500_Step'])){
2954 unset($_SESSION['Initial_451to500_Step']);
2956 if(isset($_SESSION['license_shown']))
2957 unset($_SESSION['license_shown']);
2958 if(isset($_SESSION['sugarMergeRunResults']))
2959 unset($_SESSION['sugarMergeRunResults']);
2963 * runs rebuild scripts
2965 function UWrebuild() {
2969 //CCL - Comment this block out, it is called in end.php
2970 logThis('Rebuilding everything...', $path);
2971 require_once('modules/Administration/QuickRepairAndRebuild.php');
2972 $randc = new RepairAndClear();
2973 $randc->repairAndClearAll(array('clearAll'),array(translate('LBL_ALL_MODULES')), false, false);
2975 $query = "DELETE FROM versions WHERE name='Rebuild Extensions'";
2977 logThis('Registering rebuild record: '.$query, $path);
2978 logThis('Rebuild done.', $path);
2980 // insert a new database row to show the rebuild extensions is done
2981 $id = create_guid();
2982 $gmdate = gmdate('Y-m-d H:i:s');
2983 $date_entered = db_convert("'$gmdate'", 'datetime');
2984 $query = 'INSERT INTO versions (id, deleted, date_entered, date_modified, modified_user_id, created_by, name, file_version, db_version) '
2985 . "VALUES ('$id', '0', $date_entered, $date_entered, '1', '1', 'Rebuild Extensions', '4.0.0', '4.0.0')";
2987 logThis('Registering rebuild record in versions table: '.$query, $path);
2990 function getCustomTables($dbType) {
2993 $customTables = array();
2997 $query = "SHOW tables LIKE '%_cstm'";
2998 $result = $db->query($query);//, true, 'Error getting custom tables');
2999 while ($row = $db->fetchByAssoc($result)){
3000 $customTables[] = array_pop($row);
3004 return $customTables;
3007 function alterCustomTables($dbType, $customTables)
3012 while( $i < count($customTables) ) {
3013 $alterCustomTableSql[] = "ALTER TABLE " . $customTables[$i] . " CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci";
3020 return $alterCustomTableSql;
3023 function executeAlterCustomTablesSql($dbType, $queries) {
3026 foreach($queries as $query){
3028 logThis("Sending query: ".$query);
3029 if($db->dbType == 'oci8') {
3031 $query_result = $db->query($query);//.';', true, "An error has occured while performing db query. See log file for details.<br>");
3038 function getAllTables($dbType) {
3045 $query = "SHOW tables";
3046 $result = $db->query($query, true, 'Error getting custom tables');
3047 while ($row = $db->fetchByAssoc($result)){
3048 $tables[] = array_pop($row);
3055 function printAlterTableSql($tables)
3057 $alterTableSql = '';
3059 foreach($tables as $table)
3060 $alterTableSql .= "ALTER TABLE " . $table . " CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;" . "\n";
3062 return $alterTableSql;
3065 function executeConvertTablesSql($dbType, $tables) {
3068 foreach($tables as $table){
3069 $query = "ALTER TABLE " . $table . " CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci";
3071 logThis("Sending query: ".$query);
3072 if($db->dbType == 'oci8') {
3074 $query_result = $db->query($query);//.';', true, "An error has occured while performing db query. See log file for details.<br>");
3081 function testThis() {
3082 $files = uwFindAllFiles(getcwd().'/test', array());
3084 $out = "<table cellpadding='1' cellspacing='0' border='0'>\n";
3087 foreach($files as $file) {
3088 $relativeFile = clean_path(str_replace(getcwd().'/test', '', $file));
3089 $relativeFile = ($relativeFile{0} == '/') ? substr($relativeFile, 1, strlen($relativeFile)) : $relativeFile;
3091 $relativePath = dirname($relativeFile);
3093 if($relativePath == $priorPath) { // same dir, new file
3094 $out .= "<tr><td>".basename($relativeFile)."</td></tr>";
3095 $priorPath = $relativePath;
3109 function testThis2($dir, $id=0, $hide=false) {
3111 $dh = opendir($dir);
3114 $doHide = ($hide) ? 'none' : '';
3115 $out = "<div id='{$id}' style='display:{$doHide};'>";
3116 $out .= "<table cellpadding='1' cellspacing='0' border='0' style='border:0px solid #ccc'>\n";
3118 while($file = readdir($dh)) {
3119 if($file == '.' || $file == '..' || $file == 'CVS' || $file == '.cvsignore')
3122 if(is_dir($path.'/'.$file)) {
3123 $file = $path.'/'.$file;
3124 $newI = create_guid();
3125 $out .= "<tr><td valign='top'><a href='javascript:toggleNwFiles(\"{$newI}\");'><img border='0' src='".SugarThemeRegistry::current()->getImageURL('Workflow.gif')."'></a></td>\n";
3126 $out .= "<td valign='top'><b><a href='javascript:toggleNwFiles(\"{$newI}\");'>".basename($file)."</a></b></td></tr>";
3127 $out .= "<tr><td></td><td valign='top'>".testThis2($file, $newI, true)."</td></tr>";
3129 $out .= "<tr><td valign='top'> </td>\n";
3130 $out .= "<td valign='top'>".basename($file)."</td></tr>";
3134 $out .= "</tr></table>";
3145 function testThis3(&$files, $id, $hide, $previousPath = '') {
3146 if(!is_array($files) || empty($files))
3151 // expecting full path here
3152 foreach($files as $k => $file) {
3153 $file = str_replace(getcwd(), '', $file);
3154 $path = dirname($file);
3155 $fileName = basename($file);
3157 if($fileName == 'CVS' || $fileName == '.cvsignore')
3160 if($path == $previousPath) { // same directory
3161 // new row for each file
3162 $out .= "<tr><td valign='top' align='left'> </td>";
3163 $out .= "<td valign='top' align='left'>{$fileName}</td></tr>";
3164 } else { // new directory
3166 $out .= "<tr><td valign='top'><a href='javascript:toggleNwFiles(\"{$newI}\");'><img border='0' src='".SugarThemeRegistry::current()->getImageURL('Workflow.gif')."></a></td>\n";
3167 $out .= "<td valign='top'><b><a href='javascript:toggleNwFiles(\"{$newI}\");'>".$fileName."</a></b></td></tr>";
3168 $recurse = testThis3($files, $newI, true, $previousPath);
3169 $out .= "<tr><td></td><td valign='top'>".$recurse."</td></tr>";
3172 $previousPath = $path;
3174 $display = ($hide) ? 'none' : '';
3176 <div id="{$id}" style="display:{$display}">
3177 <table cellpadding='1' cellspacing='0' border='0' style='border:1px solid #ccc'>
3186 function testThis4($filePath, $fileNodes=array(), $fileName='') {
3187 $path = dirname($filePath);
3188 $file = basename($filePath);
3190 $exFile = explode('/', $path);
3192 foreach($exFile as $pathSegment) {
3193 if(is_array($fileNodes[$pathSegment])) { // path already processed
3195 } else { // newly found path
3196 $fileNodes[$pathSegment] = array();
3199 if($fileName != '') {
3200 $fileNodes[$pathSegment][] = $fileName;
3209 ///////////////////////////////////////////////////////////////////////////////
3210 //// SYSTEM CHECK FUNCTIONS
3212 * generates an array with all files in the SugarCRM root directory, skipping
3214 * @return array files Array of files with absolute paths
3216 function getFilesForPermsCheck() {
3217 global $sugar_config;
3219 logThis('Got JSON call to find all files...');
3220 $filesNotWritable = array();
3221 $filesNWPerms = array();
3223 // add directories here that should be skipped when doing file permissions checks (cache/upload is the nasty one)
3225 $sugar_config['upload_dir'],
3227 $files = uwFindAllFiles(getcwd(), array(), true, $skipDirs, true);
3232 * checks files for permissions
3233 * @param array files Array of files with absolute paths
3234 * @return string result of check
3236 function checkFiles($files, $echo=false) {
3237 global $mod_strings;
3238 $filesNotWritable = array();
3241 <a href='javascript:void(0); toggleNwFiles(\"filesNw\");'>{$mod_strings['LBL_UW_SHOW_NW_FILES']}</a>
3242 <div id='filesNw' style='display:none;'>
3243 <table cellpadding='3' cellspacing='0' border='0'>
3245 <th align='left'>{$mod_strings['LBL_UW_FILE']}</th>
3246 <th align='left'>{$mod_strings['LBL_UW_FILE_PERMS']}</th>
3247 <th align='left'>{$mod_strings['LBL_UW_FILE_OWNER']}</th>
3248 <th align='left'>{$mod_strings['LBL_UW_FILE_GROUP']}</th>
3251 $isWindows = is_windows();
3252 foreach($files as $file) {
3255 if(!is_writable_windows($file)) {
3256 logThis('WINDOWS: File ['.$file.'] not readable - saving for display');
3257 // don't warn yet - we're going to use this to check against replacement files
3258 // aw: commented out; it's a hack to allow upgrade wizard to continue on windows... will fix later
3259 /*$filesNotWritable[$i] = $file;
3260 $filesNWPerms[$i] = substr(sprintf('%o',fileperms($file)), -4);
3261 $filesOut .= "<tr>".
3262 "<td><span class='error'>{$file}</span></td>".
3263 "<td>{$filesNWPerms[$i]}</td>".
3264 "<td>".$mod_strings['ERR_UW_CANNOT_DETERMINE_USER']."</td>".
3265 "<td>".$mod_strings['ERR_UW_CANNOT_DETERMINE_GROUP']."</td>".
3269 if(!is_writable($file)) {
3270 logThis('File ['.$file.'] not writable - saving for display');
3271 // don't warn yet - we're going to use this to check against replacement files
3272 $filesNotWritable[$i] = $file;
3273 $filesNWPerms[$i] = substr(sprintf('%o',fileperms($file)), -4);
3274 $owner = posix_getpwuid(fileowner($file));
3275 $group = posix_getgrgid(filegroup($file));
3276 $filesOut .= "<tr>".
3277 "<td><span class='error'>{$file}</span></td>".
3278 "<td>{$filesNWPerms[$i]}</td>".
3279 "<td>".$owner['name']."</td>".
3280 "<td>".$group['name']."</td>".
3287 $filesOut .= '</table></div>';
3289 $errors['files']['filesNotWritable'] = (count($filesNotWritable) > 0) ? true : false;
3290 if(count($filesNotWritable) < 1) {
3291 $filesOut = "{$mod_strings['LBL_UW_FILE_NO_ERRORS']}";
3297 function deletePackageOnCancel(){
3298 global $mod_strings;
3299 global $sugar_config;
3300 logThis('running delete');
3301 if(!isset($_SESSION['install_file']) || ($_SESSION['install_file'] == "")) {
3302 logThis('ERROR: trying to delete non-existent file: ['.$_REQUEST['install_file'].']');
3303 $error = $mod_strings['ERR_UW_NO_FILE_UPLOADED'];
3305 // delete file in upgrades/patch
3306 $delete_me = urldecode( $_SESSION['install_file'] );
3307 if(@unlink($delete_me)) {
3308 //logThis('unlinking: '.$delete_me);
3309 $out = basename($delete_me).$mod_strings['LBL_UW_FILE_DELETED'];
3311 logThis('ERROR: could not delete ['.$delete_me.']');
3312 $error = $mod_strings['ERR_UW_FILE_NOT_DELETED'].$delete_me;
3315 // delete file in cache/upload
3316 $fileS = explode('/', $delete_me);
3318 $fileName = (isset($fileS[$c-1]) && !empty($fileS[$c-1])) ? $fileS[$c-1] : $fileS[$c-2];
3319 $deleteUpload = getcwd().'/'.$sugar_config['upload_dir'].$fileName;
3320 logThis('Trying to delete '.$deleteUpload);
3321 if(!@unlink($deleteUpload)) {
3322 logThis('ERROR: could not delete: ['.$deleteUpload.']');
3323 $error = $mod_strings['ERR_UW_FILE_NOT_DELETED'].$sugar_config['upload_dir'].$fileName;
3325 if(!empty($error)) {
3326 $out = "<b><span class='error'>{$error}</span></b><br />";
3331 function parseAndExecuteSqlFile($sqlScript,$forStepQuery='',$resumeFromQuery=''){
3332 global $sugar_config;
3333 $alterTableSchema = '';
3334 $sqlErrors = array();
3335 if(!isset($_SESSION['sqlSkippedQueries'])){
3336 $_SESSION['sqlSkippedQueries'] = array();
3338 $db = & DBManagerFactory::getInstance();
3340 if($sugar_config['dbconfig']['db_type'] == 'mysql') {
3343 if($sugar_config['dbconfig']['db_type'] == 'oci8'){
3344 $db->query("CREATE OR REPLACE FUNCTION blob_to_clob (blob_in IN BLOB)
3348 v_varchar VARCHAR2(32767);
3349 v_start PLS_INTEGER := 1;
3350 v_buffer PLS_INTEGER := 32767;
3352 DBMS_LOB.CREATETEMPORARY(v_clob, TRUE);
3354 FOR i IN 1..CEIL(DBMS_LOB.GETLENGTH(blob_in) / v_buffer)
3357 v_varchar := UTL_RAW.CAST_TO_VARCHAR2(DBMS_LOB.SUBSTR(blob_in, v_buffer, v_start));
3359 DBMS_LOB.WRITEAPPEND(v_clob, LENGTH(v_varchar), v_varchar);
3361 v_start := v_start + v_buffer;
3366 END blob_to_clob;");
3368 if(strpos($resumeFromQuery,",") != false){
3369 $resumeFromQuery = explode(",",$resumeFromQuery);
3370 if(is_array($resumeFromQuery)){
3371 //print_r('RES ARRAY '.$resumeFromQuery[0].'</br>');
3374 if(file_exists($sqlScript)) {
3375 $fp = fopen($sqlScript, 'r');
3376 $contents = stream_get_contents($fp);
3377 $anyScriptChanges =$contents;
3378 $resumeAfterFound = false;
3382 while($line = fgets($fp)) {
3383 if(strpos($line, '--') === false) {
3384 $completeLine .= " ".trim($line);
3385 if(strpos($line, ';') !== false) {
3387 $query = str_replace(';','',$completeLine);
3388 //if resume from query is not null then find out from where
3389 //it should start executing the query.
3391 if($query != null && $resumeFromQuery != null){
3392 if(!$resumeAfterFound){
3393 if(strpos($query,",") != false){
3394 $queArray = array();
3395 $queArray = explode(",",$query);
3396 for($i=0;$i<sizeof($resumeFromQuery);$i++){
3397 if(strcmp(strtolower(trim($resumeFromQuery[$i])),strtolower(trim($queArray[$i])))==0){
3398 //echo 'mat found '.$queArray[$i].'</br>';
3399 $resumeAfterFound = true;
3402 $resumeAfterFound = false;
3408 elseif(strcmp(strtolower(trim($resumeFromQuery)),strtolower(trim($query)))==0){
3409 $resumeAfterFound = true;
3412 if($resumeAfterFound){
3415 // if $count=1 means it is just found so skip the query. Run the next one
3416 if($query != null && $resumeAfterFound && $count >1){
3420 $tableName = getAlterTable($query);
3421 if(!empty($tableName))
3423 $db->query('ALTER TABLE '.$tableName.' DISABLE KEYS');
3427 if($db->checkError()){
3428 //put in the array to use later on
3429 $_SESSION['sqlSkippedQueries'][] = $query;
3431 if(!empty($tableName))
3433 $db->query('ALTER TABLE '.$tableName.' ENABLE KEYS');
3435 $progQuery[$forStepQuery]=$query;
3436 post_install_progress($progQuery,$action='set');
3439 elseif($query != null){
3443 $tableName = getAlterTable($query);
3444 if(!empty($tableName))
3446 $db->query('ALTER TABLE '.$tableName.' DISABLE KEYS');
3450 if(!empty($tableName))
3452 $db->query('ALTER TABLE '.$tableName.' ENABLE KEYS');
3454 $progQuery[$forStepQuery]=$query;
3455 post_install_progress($progQuery,$action='set');
3456 if($db->checkError()){
3457 //put in the array to use later on
3458 $_SESSION['sqlSkippedQueries'][] = $query;
3469 function getAlterTable($query){
3470 $query = strtolower($query);
3471 if (preg_match("/^\s*alter\s+table\s+/", $query)) {
3472 $sqlArray = explode(" ", $query);
3473 $key = array_search('table', $sqlArray);
3474 return $sqlArray[($key+1)];
3480 function set_upgrade_vars(){
3481 logThis('setting session variables...');
3482 $upgrade_progress_dir = getcwd().'/'.$GLOBALS['sugar_config']['upload_dir'].'upgrades/temp';
3483 if(!is_dir($upgrade_progress_dir)){
3484 mkdir_recursive($upgrade_progress_dir);
3486 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3487 if(file_exists($upgrade_progress_file)){
3488 include($upgrade_progress_file);
3491 fopen($upgrade_progress_file, 'w+');
3493 if(!isset($upgrade_config) || $upgrade_config == null){
3494 $upgrade_config = array();
3495 $upgrade_config[1]['upgrade_vars']=array();
3497 if(isset($upgrade_config[1]) && isset($upgrade_config[1]['upgrade_vars']) && !is_array($upgrade_config[1]['upgrade_vars'])){
3498 $upgrade_config[1]['upgrade_vars'] = array();
3501 if(!isset($upgrade_vars) || $upgrade_vars == NULL){
3502 $upgrade_vars = array();
3504 if(isset($_SESSION['unzip_dir']) && !empty($_SESSION['unzip_dir']) && file_exists($_SESSION['unzip_dir'])){
3505 $upgrade_vars['unzip_dir']=$_SESSION['unzip_dir'];
3507 if(isset($_SESSION['install_file']) && !empty($_SESSION['install_file']) && file_exists($_SESSION['install_file'])){
3508 $upgrade_vars['install_file']=$_SESSION['install_file'];
3510 if(isset($_SESSION['Upgraded451Wizard']) && !empty($_SESSION['Upgraded451Wizard'])){
3511 $upgrade_vars['Upgraded451Wizard']=$_SESSION['Upgraded451Wizard'];
3513 if(isset($_SESSION['license_shown']) && !empty($_SESSION['license_shown'])){
3514 $upgrade_vars['license_shown']=$_SESSION['license_shown'];
3516 if(isset($_SESSION['Initial_451to500_Step']) && !empty($_SESSION['Initial_451to500_Step'])){
3517 $upgrade_vars['Initial_451to500_Step']=$_SESSION['Initial_451to500_Step'];
3519 if(isset($_SESSION['zip_from_dir']) && !empty($_SESSION['zip_from_dir'])){
3520 $upgrade_vars['zip_from_dir']=$_SESSION['zip_from_dir'];
3522 //place into the upgrade_config array and rewrite config array only if new values are being inserted
3523 if(isset($upgrade_vars) && $upgrade_vars != null && sizeof($upgrade_vars) > 0){
3524 foreach($upgrade_vars as $key=>$val){
3525 if($key != null && $val != null){
3526 $upgrade_config[1]['upgrade_vars'][$key]=$upgrade_vars[$key];
3529 ksort($upgrade_config);
3530 if(is_writable($upgrade_progress_file) && write_array_to_file( "upgrade_config", $upgrade_config,
3531 $upgrade_progress_file)) {
3532 //writing to the file
3537 function initialize_session_vars(){
3538 $upgrade_progress_dir = getcwd().'/'.$GLOBALS['sugar_config']['upload_dir'].'upgrades/temp';
3539 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3540 if(file_exists($upgrade_progress_file)){
3541 include($upgrade_progress_file);
3542 if(isset($upgrade_config) && $upgrade_config != null && is_array($upgrade_config) && sizeof($upgrade_config) >0){
3543 $currVarsArray=$upgrade_config[1]['upgrade_vars'];
3544 //print_r($currVarsArray);
3545 if(isset($currVarsArray) && $currVarsArray != null && is_array($currVarsArray) && sizeof($currVarsArray)>0){
3546 foreach($currVarsArray as $key=>$val){
3547 if($key != null && $val !=null){
3548 //set session variables
3549 $_SESSION[$key]=$val;
3558 //track the upgrade progress on each step
3559 //track the upgrade progress on each step
3560 function set_upgrade_progress($currStep,$currState,$currStepSub='',$currStepSubState=''){
3562 $upgrade_progress_dir = getcwd().'/'.$GLOBALS['sugar_config']['upload_dir'].'upgrades/temp';
3563 if(!is_dir($upgrade_progress_dir)){
3564 mkdir_recursive($upgrade_progress_dir);
3566 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3567 if(file_exists($upgrade_progress_file)){
3568 include($upgrade_progress_file);
3571 if(function_exists('sugar_fopen')){
3572 sugar_fopen($upgrade_progress_file, 'w+');
3575 fopen($upgrade_progress_file, 'w+');
3578 if(!isset($upgrade_config) || $upgrade_config == null){
3579 $upgrade_config = array();
3580 $upgrade_config[1]['upgrade_vars']=array();
3582 if(!is_array($upgrade_config[1]['upgrade_vars'])){
3583 $upgrade_config[1]['upgrade_vars'] = array();
3585 if($currStep != null && $currState != null){
3586 if(sizeof($upgrade_config) > 0){
3587 if($currStepSub != null && $currStepSubState !=null){
3588 //check if new status to be set or update
3589 //get the latest in array. since it has sub components prepare an array
3590 if(!empty($upgrade_config[sizeof($upgrade_config)][$currStep]) && is_array($upgrade_config[sizeof($upgrade_config)][$currStep])){
3591 $latestStepSub = currSubStep($upgrade_config[sizeof($upgrade_config)][$currStep]);
3592 if($latestStepSub == $currStepSub){
3593 $upgrade_config[sizeof($upgrade_config)][$currStep][$latestStepSub]=$currStepSubState;
3594 $upgrade_config[sizeof($upgrade_config)][$currStep][$currStep] = $currState;
3597 $upgrade_config[sizeof($upgrade_config)][$currStep][$currStepSub]=$currStepSubState;
3598 $upgrade_config[sizeof($upgrade_config)][$currStep][$currStep] = $currState;
3602 $currArray = array();
3603 $currArray[$currStep] = $currState;
3604 $currArray[$currStepSub] = $currStepSubState;
3605 $upgrade_config[sizeof($upgrade_config)+1][$currStep] = $currArray;
3609 //get the current upgrade progress
3610 $latestStep = get_upgrade_progress();
3611 //set the upgrade progress
3612 //echo 'latest '.$latestStep;
3613 if($latestStep == $currStep){
3614 //update the current step with new progress status
3616 $upgrade_config[sizeof($upgrade_config)][$latestStep]=$currState;
3621 $upgrade_config[sizeof($upgrade_config)+1][$currStep]=$currState;
3623 // now check if there elements within array substeps
3627 //set the upgrade progress (just starting)
3628 $upgrade_config[sizeof($upgrade_config)+1][$currStep]= $currState;
3631 if(is_writable($upgrade_progress_file) && write_array_to_file( "upgrade_config", $upgrade_config,
3632 $upgrade_progress_file)) {
3633 //writing to the file
3639 function get_upgrade_progress(){
3640 $upgrade_progress_dir = getcwd().'/'.$GLOBALS['sugar_config']['upload_dir'].'upgrades/temp';
3641 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3643 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3645 if(file_exists($upgrade_progress_file)){
3646 include($upgrade_progress_file);
3647 //echo 'upconf '.$upgrade_config;
3648 if(!isset($upgrade_config) || $upgrade_config == null){
3649 $upgrade_config = array();
3651 if($upgrade_config != null && sizeof($upgrade_config) >1){
3652 $currArr = $upgrade_config[sizeof($upgrade_config)];
3653 //echo 'size of '.sizeof($upgrade_config);
3654 if(is_array($currArr)){
3655 foreach($currArr as $key=>$val){
3663 function currSubStep($currStep){
3665 if(is_array($currStep)){
3666 foreach($currStep as $key=>$val){
3674 function currUpgradeState($currState){
3676 if(is_array($currState)){
3677 foreach($currState as $key=>$val){
3679 foreach($val as $k=>$v){
3693 function didThisStepRunBefore($step,$SubStep=''){
3694 if($step == null) return;
3695 $upgrade_progress_dir = getcwd().'/'.$GLOBALS['sugar_config']['upload_dir'].'upgrades/temp';
3696 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3698 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3700 if(file_exists($upgrade_progress_file)){
3701 include($upgrade_progress_file);
3702 if(isset($upgrade_config) && $upgrade_config != null && is_array($upgrade_config) && sizeof($upgrade_config) >0){
3703 for($i=1;$i<=sizeof($upgrade_config);$i++){
3704 if(is_array($upgrade_config[$i])){
3705 foreach($upgrade_config[$i] as $key=>$val){
3707 if(is_array($upgrade_config[$i][$step])){
3709 foreach ($upgrade_config[$i][$step] as $k=>$v){
3711 foreach($v as $k1=>$v1){
3712 if($SubStep != null){
3713 if($SubStep ==$k1 && $v1=='done'){
3714 //echo 'Found Inside '.$k1;
3721 elseif($SubStep !=null){
3722 if($SubStep==$k && $v=='done'){
3723 //echo 'Found1 '.$k;
3728 elseif($step==$k && $v=='done'){
3729 //echo 'Found2 '.$k;
3735 elseif($val=='done'){
3736 //echo 'Foundmmmm '.$key;
3750 //get and set post install status
3751 function post_install_progress($progArray='',$action=''){
3752 if($action=='' || $action=='get'){
3753 //get the state of post install
3754 $upgrade_progress_dir = getcwd().'/'.$GLOBALS['sugar_config']['upload_dir'].'upgrades/temp';
3755 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3756 $currProg = array();
3757 if(file_exists($upgrade_progress_file)){
3758 include($upgrade_progress_file);
3759 if(is_array($upgrade_config[sizeof($upgrade_config)]['commit']['post_install']) && sizeof($upgrade_config[sizeof($upgrade_config)]['commit']['post_install'])>0){
3760 foreach($upgrade_config[sizeof($upgrade_config)]['commit']['post_install'] as $k=>$v){
3767 elseif($action=='set'){
3768 $upgrade_progress_dir = getcwd().'/'.$GLOBALS['sugar_config']['upload_dir'].'upgrades/temp';
3769 if(!is_dir($upgrade_progress_dir)){
3770 mkdir($upgrade_progress_dir);
3772 $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
3773 if(file_exists($upgrade_progress_file)){
3774 include($upgrade_progress_file);
3777 fopen($upgrade_progress_file, 'w+');
3779 if(!is_array($upgrade_config[sizeof($upgrade_config)]['commit']['post_install'])){
3780 $upgrade_config[sizeof($upgrade_config)]['commit']['post_install']=array();
3781 $upgrade_config[sizeof($upgrade_config)]['commit']['post_install']['post_install'] = 'in_progress';
3783 if($progArray != null && is_array($progArray)){
3784 foreach($progArray as $key=>$val){
3785 $upgrade_config[sizeof($upgrade_config)]['commit']['post_install'][$key]=$val;
3788 if(is_writable($upgrade_progress_file) && write_array_to_file( "upgrade_config", $upgrade_config,
3789 $upgrade_progress_file)) {
3790 //writing to the file
3796 // parse and run sql file
3797 function parseAndExecuteSqlFileExtended($sqlScript){
3798 global $sugar_config;
3799 $alterTableSchema = '';
3800 $db = & DBManagerFactory::getInstance();
3801 if(is_file($sqlScript)) {
3802 $fp = fopen($sqlScript, 'r');
3803 $contents = stream_get_contents($fp);
3804 $anyScriptChanges =$contents;
3808 while($line = fgets($fp)) {
3809 if(strpos($line, '--') === false) {
3810 $completeLine .= " ".trim($line);
3811 if(strpos($line, ';') !== false) {
3812 $completeLine = str_replace(';','',$completeLine);
3813 $currLine = explode(",",$completeLine);
3814 //check if multiple statements are clubbed
3815 if(sizeof($currLine) >1){
3816 $qarr = explode(" ",trim($currLine[0]));
3817 if(strtoupper(trim($qarr[0])) == 'CREATE' && strtoupper(trim($qarr[1])) == 'TABLE'){
3818 if(strtoupper(trim($qarr[2]) != null)){
3819 if($sugar_config['dbconfig']['db_type'] == 'oci8'){
3820 $query= "select table_name from user_tables where table_name=strtoupper(trim($qarr[2]))";
3821 $result = $db->query($query);
3822 $row = $db->fetchByAssociation($result);
3823 if($row['table_name'] != null){
3828 $query= $completeLine;
3837 $qType =trim($qarr[0])." ".trim($qarr[1])." ".trim($qarr[2]);
3838 echo trim($currLine[0])."<br />";
3839 for ($i = 1; $i <= sizeof($currLine)-1; $i++) {
3840 $query = $qType." ".trim($currLine[$i]);
3841 echo $query."<br />";
3847 echo trim($currLine[0]);
3851 //$q3 = $completeLine;
3852 //''$r3 = $GLOBALS['db']->query($q3, false, "Preflight Failed for:");
3853 //echo mysql_error();
3861 //$sqlErrors[] = $mod_strings['ERR_UW_FILE_NOT_READABLE'].'::'.$sqlScript;
3866 function repairDBForUpgrade($execute=false,$path=''){
3868 global $current_user, $beanFiles;
3870 set_time_limit(3600);
3872 $db = &DBManagerFactory::getInstance();
3874 VardefManager::clearVardef();
3875 require_once('include/ListView/ListView.php');
3876 foreach ($beanFiles as $bean => $file) {
3877 require_once ($file);
3878 $focus = new $bean ();
3879 $sql .= $db->repairTable($focus, $execute);
3883 $olddictionary = $dictionary;
3884 unset ($dictionary);
3885 include ('modules/TableDictionary.php');
3886 foreach ($dictionary as $meta) {
3887 $tablename = $meta['table'];
3888 $fielddefs = $meta['fields'];
3889 $indices = $meta['indices'];
3890 $sql .= $db->repairTableParams($tablename, $fielddefs, $indices, $execute);
3893 foreach (explode("\n", $sql) as $line) {
3894 if (!empty ($line) && substr($line, -2) != "*/") {
3897 $qry_str .= $line . "\n";
3908 preg_replace('#(/\*.+?\*/\n*)#', '', $qry_str)
3910 logThis("*******START EXECUTING DB UPGRADE QUERIES***************",$path);
3911 logThis($sql,$path);
3912 logThis("*******END EXECUTING DB UPGRADE QUERIES****************",$path);
3921 * upgradeUserPreferences
3922 * This method updates the user_preferences table and sets the pages/dashlets for users
3923 * which have ACL access to Trackers so that the Tracker dashlets are set in their user perferences
3926 function upgradeUserPreferences() {
3931 function add_custom_modules_favorites_search(){
3932 $module_directories = scandir('modules');
3934 foreach($module_directories as $module_dir){
3935 if($module_dir == '.' || $module_dir == '..' || !is_dir("modules/{$module_dir}")){
3940 preg_match('/^[a-z0-9]{1,5}_[a-z0-9_]+$/i' , $module_dir, $matches);
3942 // Make sure the module was created by module builder
3943 if(empty($matches)){
3947 $full_module_dir = "modules/{$module_dir}/";
3948 $read_searchdefs_from = "{$full_module_dir}/metadata/searchdefs.php";
3949 $read_SearchFields_from = "{$full_module_dir}/metadata/SearchFields.php";
3950 $read_custom_SearchFields_from = "custom/{$full_module_dir}/metadata/SearchFields.php";
3952 // Studio can possibly override this file, so we check for a custom version of it
3953 if(file_exists("custom/{$full_module_dir}/metadata/searchdefs.php")){
3954 $read_searchdefs_from = "custom/{$full_module_dir}/metadata/searchdefs.php";
3957 if(file_exists($read_searchdefs_from) && file_exists($read_SearchFields_from)){
3960 require($read_searchdefs_from);
3961 foreach($searchdefs[$module_dir]['layout']['basic_search'] as $sf_array){
3962 if(isset($sf_array['name']) && $sf_array['name'] == 'favorites_only'){
3967 require($read_SearchFields_from);
3968 if(isset($searchFields[$module_dir]['favorites_only'])){
3972 if(!$found_sf1 && !$found_sf2){
3973 $searchdefs[$module_dir]['layout']['basic_search']['favorites_only'] = array('name' => 'favorites_only','label' => 'LBL_FAVORITES_FILTER','type' => 'bool',);
3974 $searchdefs[$module_dir]['layout']['advanced_search']['favorites_only'] = array('name' => 'favorites_only','label' => 'LBL_FAVORITES_FILTER','type' => 'bool',);
3975 $searchFields[$module_dir]['favorites_only'] = array(
3976 'query_type'=>'format',
3977 'operator' => 'subquery',
3978 'subquery' => 'SELECT sugarfavorites.record_id FROM sugarfavorites
3979 WHERE sugarfavorites.deleted=0
3980 and sugarfavorites.module = \''.$module_dir.'\'
3981 and sugarfavorites.assigned_user_id = \'{0}\'',
3982 'db_field'=>array('id')
3985 if(!is_dir("custom/{$full_module_dir}/metadata")){
3986 mkdir_recursive("custom/{$full_module_dir}/metadata");
3988 $success_sf1 = write_array_to_file('searchdefs', $searchdefs, "custom/{$full_module_dir}/metadata/searchdefs.php");
3989 $success_sf2 = write_array_to_file('searchFields', $searchFields, "{$full_module_dir}/metadata/SearchFields.php");
3992 logThis("add_custom_modules_favorites_search failed for searchdefs.php for {$module_dir}");
3995 logThis("add_custom_modules_favorites_search failed for SearchFields.php for {$module_dir}");
3997 if($success_sf1 && $success_sf2){
3998 logThis("add_custom_modules_favorites_search successfully updated searchdefs and searchFields for {$module_dir}");
4007 * upgradeModulesForTeamsets
4009 * This method adds the team_set_id values to the module tables that have the new team_set_id column
4010 * added through the SugarCRM 5.5.x upgrade process. It also adds the values into the team_sets and
4011 * team_sets_teams tables.
4013 * @param filter Array of modules to process; empty by default
4015 function upgradeModulesForTeamsets($filter=array()) {
4016 require('include/modules.php');
4017 foreach($beanList as $moduleName=>$beanName) {
4018 if(!empty($filter) && array_search($moduleName, $filter) === false) {
4021 if($moduleName == 'TeamMemberships' || $moduleName == 'ForecastOpportunities'){
4024 $bean = loadBean($moduleName);
4026 empty($bean->table_name)) {
4030 $FieldArray = $GLOBALS['db']->helper->get_columns($bean->table_name);
4031 if(!isset($FieldArray['team_id'])) {
4035 upgradeTeamColumn($bean, 'team_id');
4039 //Upgrade users table
4040 $bean = loadBean('Users');
4041 upgradeTeamColumn($bean, 'default_team');
4042 $result = $GLOBALS['db']->query("SELECT id FROM teams where deleted=0");
4043 while($row = $GLOBALS['db']->fetchByAssoc($result)) {
4044 $teamset = new TeamSet();
4045 $teamset->addTeams($row['id']);
4052 * Helper function to create a team_set_id column and also set team_set_id column
4053 * to have the value of the $column_name parameter
4055 * @param $bean SugarBean which we are adding team_set_id column to
4056 * @param $column_name The name of the column containing the default team_set_id value
4058 function upgradeTeamColumn($bean, $column_name) {
4059 //first let's check to ensure that the team_set_id field is defined, if not it could be the case that this is an older
4060 //module that does not use the SugarObjects
4061 if(empty($bean->field_defs['team_set_id']) && $bean->module_dir != 'Trackers'){
4063 //at this point we could assume that since we have a team_id defined and not a team_set_id that we need to
4064 //add that field and the corresponding relationships
4065 $object = $bean->object_name;
4066 $module = $bean->module_dir;
4067 $object_name = $object;
4068 $_object_name = strtolower($object_name);
4070 if(!empty($GLOBALS['dictionary'][$object]['table'])){
4071 $table_name = $GLOBALS['dictionary'][$object]['table'];
4073 $table_name = strtolower($module);
4076 $path = 'include/SugarObjects/implements/team_security/vardefs.php';
4078 //go through each entry in the vardefs from team_security and unset anything that is already set in the core module
4079 //this will ensure we have the proper ordering.
4080 $fieldDiff = array_diff_assoc($vardefs['fields'], $GLOBALS['dictionary'][$bean->object_name]['fields']);
4082 $file = 'custom/Extension/modules/' . $bean->module_dir. '/Ext/Vardefs/teams.php';
4083 $contents = "<?php\n";
4084 if(!empty($fieldDiff)){
4085 foreach($fieldDiff as $key => $val){
4086 $contents .= "\n\$GLOBALS['dictionary']['". $object . "']['fields']['". $key . "']=" . var_export_helper($val) . ";";
4089 $relationshipDiff = array_diff_assoc($vardefs['relationships'], $GLOBALS['dictionary'][$bean->object_name]['relationships']);
4090 if(!empty($relationshipDiff)){
4091 foreach($relationshipDiff as $key => $val){
4092 $contents .= "\n\$GLOBALS['dictionary']['". $object . "']['relationships']['". $key . "']=" . var_export_helper($val) . ";";
4095 $indexDiff = array_diff_assoc($vardefs['indices'], $GLOBALS['dictionary'][$bean->object_name]['indices']);
4096 if(!empty($indexDiff)){
4097 foreach($indexDiff as $key => $val){
4098 $contents .= "\n\$GLOBALS['dictionary']['". $object . "']['indices']['". $key . "']=" . var_export_helper($val) . ";";
4101 if( $fh = @sugar_fopen( $file, 'wt' ) )
4103 fputs( $fh, $contents);
4108 //we have written out the teams.php into custom/Extension/modules/{$module_dir}/Ext/Vardefs/teams.php'
4109 //now let's merge back into vardefs.ext.php
4110 require_once('ModuleInstall/ModuleInstaller.php');
4111 $mi = new ModuleInstaller();
4112 $mi->merge_files('Ext/Vardefs/', 'vardefs.ext.php');
4113 VardefManager::loadVardef($bean->module_dir, $bean->object_name, true);
4114 $bean->field_defs = $GLOBALS['dictionary'][$bean->object_name]['fields'];
4117 if(isset($bean->field_defs['team_set_id'])) {
4118 //Create the team_set_id column
4119 $FieldArray = $GLOBALS['db']->helper->get_columns($bean->table_name);
4120 if(!isset($FieldArray['team_set_id'])) {
4121 $GLOBALS['db']->addColumn($bean->table_name, $bean->field_defs['team_set_id']);
4123 $indexArray = $GLOBALS['db']->helper->get_indices($bean->table_name);
4125 $indexName = getValidDBName('idx_'.strtolower($bean->table_name).'_tmst_id', true, 34);
4128 'name' => $indexName,
4130 'fields' => array('team_set_id')
4133 if(!isset($indexArray[$indexName])) {
4134 $GLOBALS['db']->addIndexes($bean->table_name, $indexDef);
4137 //Update the table's team_set_id column to have the same values as team_id
4138 $GLOBALS['db']->query("UPDATE {$bean->table_name} SET team_set_id = {$column_name}");
4143 * Update the folder subscription table which confirms to the team security mechanism but
4144 * the class SugarFolders does not extend SugarBean and is therefore never picked up by the
4145 * upgradeModulesForTeamsets function.
4147 function upgradeFolderSubscriptionsTeamSetId()
4149 logThis("In upgradeFolderSubscriptionsTeamSetId()");
4150 $query = "UPDATE folders SET team_set_id = team_id";
4151 $result = $GLOBALS['db']->query($query);
4152 logThis("Finished upgradeFolderSubscriptionsTeamSetId()");
4156 * upgradeModulesForTeam
4158 * This method update the associated_user_id, name, name_2 to the private team records on teams table
4159 * This function is used for upgrade process from 5.1.x and 5.2.x.
4162 function upgradeModulesForTeam() {
4163 logThis("In upgradeModulesForTeam()");
4164 $result = $GLOBALS['db']->query("SELECT id, user_name, first_name, last_name FROM users where deleted=0");
4166 while($row = $GLOBALS['db']->fetchByAssoc($result)) {
4167 $results2 = $GLOBALS['db']->query("SELECT id FROM teams WHERE name = '({$row['user_name']})'");
4169 if(!$assoc = $GLOBALS['db']->fetchByAssoc($results2)) {
4170 //if team does not exist, then lets create the team for this user
4173 $user->retrieve($row['id']);
4174 $team->new_user_created($user);
4175 $team_id = $team->id;
4177 $team_id =$assoc['id'];
4181 $name = is_null($row['first_name'])?'':$row['first_name'];
4182 $name_2 = is_null($row['last_name'])?'':$row['last_name'];
4183 $associated_user_id = $row['id'];
4186 //Ensure team->name is not empty by using team->name_2 if available
4187 if(empty($name) && !empty($name_2)) {
4192 $query = "UPDATE teams SET name = '{$name}', name_2 = '{$name_2}', associated_user_id = '{$associated_user_id}' WHERE id = '{$team_id}'";
4193 $GLOBALS['db']->query($query);
4196 //Update the team_set_id and default_team columns
4197 $ce_to_pro_or_ent = (isset($_SESSION['upgrade_from_flavor']) && ($_SESSION['upgrade_from_flavor'] == 'SugarCE to SugarPro' || $_SESSION['upgrade_from_flavor'] == 'SugarCE to SugarEnt'));
4199 //Update team_set_id
4200 if($ce_to_pro_or_ent) {
4201 $GLOBALS['db']->query("update users set team_set_id = (select teams.id from teams where teams.associated_user_id = users.id)");
4202 $GLOBALS['db']->query("update users set default_team = (select teams.id from teams where teams.associated_user_id = users.id)");
4208 function addNewSystemTabsFromUpgrade($from_dir){
4210 if(isset($_SESSION['upgrade_from_flavor'])){
4212 //check to see if there are any new files that need to be added to systems tab
4213 //retrieve old modules list
4214 logThis('check to see if new modules exist',$path);
4215 $oldModuleList = array();
4216 $newModuleList = array();
4217 include($from_dir.'/include/modules.php');
4218 $oldModuleList = $moduleList;
4219 include('include/modules.php');
4220 $newModuleList = $moduleList;
4222 //include tab controller
4223 require_once('modules/MySettings/TabController.php');
4224 $newTB = new TabController();
4226 //make sure new modules list has a key we can reference directly
4227 $newModuleList = $newTB->get_key_array($newModuleList);
4228 $oldModuleList = $newTB->get_key_array($oldModuleList);
4230 //iterate through list and remove commonalities to get new modules
4231 foreach ($newModuleList as $remove_mod){
4232 if(in_array($remove_mod, $oldModuleList)){
4233 unset($newModuleList[$remove_mod]);
4236 //new modules list now has left over modules which are new to this install, so lets add them to the system tabs
4237 logThis('new modules to add are '.var_export($newModuleList,true),$path);
4239 if(!empty($newModuleList))
4241 //grab the existing system tabs
4242 $tabs = $newTB->get_system_tabs();
4244 //add the new tabs to the array
4245 foreach($newModuleList as $nm ){
4249 $newTB->set_system_tabs($tabs);
4251 logThis('module tabs updated',$path);
4257 * This method attempts to fix dropdown lists that were incorrectly named.
4258 * There were versions of SugarCRM that did not enforce naming convention rules
4259 * for the dropdown list field name. This method attempts to resolve that by
4260 * fixing the language files that may have been affected and then updating the
4261 * fields_meta_data table accordingly. It also refreshes any vardefs that may
4262 * have been affected.
4265 function fix_dropdown_list() {
4266 if(file_exists('custom/include/language')) {
4268 $affected_modules = array();
4269 $affected_keys = array();
4271 getFiles($files, 'custom/include/language', '/\.php$/i');
4272 foreach($files as $file) {
4274 if(file_exists($file . '.bak')) {
4275 $bak_mod_time = filemtime($file . '.bak');
4276 $php_mod_time = filemtime($file);
4277 //We're saying if the .php file was modified 30 seconds no more than php.bak file then we
4278 //run these additional cleanup checks
4279 if($php_mod_time - $bak_mod_time < 30) {
4281 $app_list_strings = array();
4282 $GLOBALS['app_list_strings'] = array();
4283 require($file . '.bak');
4284 $bak_app_list_strings = array_merge($app_list_strings, $GLOBALS['app_list_strings']);
4286 $app_list_strings = array();
4287 $GLOBALS['app_list_strings'] = array();
4289 $php_app_list_strings = array_merge($app_list_strings, $GLOBALS['app_list_strings']);
4291 //Get the file contents
4292 $contents = file_get_contents($file);
4294 //Now simulate a fix for the file before we compare w/ the .php file
4295 //we also append to the $contents
4296 foreach($bak_app_list_strings as $key=>$entry) {
4297 if(preg_match('/([^A-Za-z_])/', $key, $matches) && is_array($entry)) {
4298 $new_key = preg_replace('/[^A-Za-z_]/', '_', $key);
4299 $bak_app_list_strings[$new_key] = $bak_app_list_strings[$key];
4300 unset($bak_app_list_strings[$key]);
4301 //Now if the entry doesn't exists in the .php file, then add to contents
4302 if(!isset($php_app_list_strings[$new_key])) {
4303 $contents .= "\n\$GLOBALS['app_list_strings']['{$new_key}'] = " . var_export_helper($bak_app_list_strings[$new_key]) . ";";
4308 //Now load the .php file to do the comparison
4309 foreach($php_app_list_strings as $key=>$entry) {
4310 if(isset($bak_app_list_strings[$key])) {
4311 $diff = array_diff($bak_app_list_strings[$key], $entry);
4313 //There is a difference, so copy the $bak_app_list_strings version into the .php file
4314 $contents .= "\n\$GLOBALS['app_list_strings']['{$key}'] = " . var_export_helper($bak_app_list_strings[$key]) . ";";
4319 //Now write out the file contents
4320 //Create backup just in case
4321 copy($file, $file . '.php_bak');
4322 $fp = @sugar_fopen($file, 'w');
4324 fwrite($fp, $contents);
4327 $GLOBALS['log']->error("Unable to update file contents in fix_dropdown_list for {$file}");
4332 unset($GLOBALS['app_strings']);
4333 unset($GLOBALS['app_list_strings']);
4334 $app_list_strings = array();
4337 $contents = file_get_contents($file);
4338 if ( !isset($GLOBALS['app_list_strings']) ) {
4339 $GLOBALS['app_list_strings'] = $app_list_strings;
4342 $GLOBALS['app_list_strings'] = array_merge($app_list_strings, $GLOBALS['app_list_strings']);
4345 if(isset($GLOBALS['app_list_strings']) && is_array($GLOBALS['app_list_strings'])) {
4346 foreach($GLOBALS['app_list_strings'] as $key=>$entry) {
4347 if(preg_match('/([^A-Za-z_])/', $key, $matches) && is_array($entry)) {
4348 $result = $GLOBALS['db']->query("SELECT custom_module FROM fields_meta_data WHERE ext1 = '{$key}'");
4349 if(!empty($result)) {
4350 while($row = $GLOBALS['db']->fetchByAssoc($result)) {
4351 $custom_module = $row['custom_module'];
4352 if(!empty($GLOBALS['beanList'][$custom_module])) {
4353 $affected_modules[$custom_module] = $GLOBALS['beanList'][$custom_module];
4358 //Replace all invalid characters with '_' character
4359 $new_key = preg_replace('/[^A-Za-z_]/', '_', $key);
4360 $affected_keys[$key] = $new_key;
4362 $GLOBALS['app_list_strings'][$new_key] = $GLOBALS['app_list_strings'][$key];
4363 unset($GLOBALS['app_list_strings'][$key]);
4365 $pattern_match = "/(\[\s*\'{$key}\'\s*\])/";
4366 $new_key = "['{$new_key}']";
4367 $out = preg_replace($pattern_match, $new_key, $contents);
4373 //This is a check for g => h instances where the file contents were incorrectly written
4374 //and also fixes the scenario where via a UI upgrade, the app_list_strings were incorrectly
4375 //merged with app_list_strings variables declared elsewhere
4377 if(preg_match('/\$GLOBALS\s*\[\s*[\"|\']app_list_strings[\"|\']\s*\]\s*=\s*array\s*\(/', $contents)) {
4378 //Now also remove all the non-custom labels that were added
4379 if(preg_match('/language\/([^\.]+)\.lang\.php$/', $file, $matches)) {
4380 $language = $matches[1];
4382 $app_list_strings = array();
4384 if(file_exists("include/language/$language.lang.php")) {
4385 include("include/language/$language.lang.php");
4387 if(file_exists("include/language/$language.lang.override.php")) {
4388 $app_list_strings = _mergeCustomAppListStrings("include/language/$language.lang.override.php" , $app_list_strings) ;
4390 if(file_exists("custom/application/Ext/Language/$language.ext.lang.php")) {
4391 $app_list_strings = _mergeCustomAppListStrings("custom/application/Ext/Language/$language.ext.lang.php" , $app_list_strings) ;
4393 if(file_exists("custom/application/Ext/Language/$language.lang.ext.php")) {
4394 $app_list_strings = _mergeCustomAppListStrings("custom/application/Ext/Language/$language.lang.ext.php" , $app_list_strings) ;
4397 $all_non_custom_include_language_strings = $app_strings;
4398 $all_non_custom_include_language_list_strings = $app_list_strings;
4400 $unset_keys = array();
4401 if(!empty($GLOBALS['app_list_strings'])) {
4402 foreach($GLOBALS['app_list_strings'] as $key=>$value) {
4404 if(isset($all_non_custom_include_language_list_strings[$key])) {
4405 $diff = array_diff($all_non_custom_include_language_list_strings[$key], $GLOBALS['app_list_strings'][$key]);
4408 if(!empty($all_non_custom_include_language_list_strings[$key]) && empty($diff)) {
4409 $unset_keys[] = $key;
4414 foreach($unset_keys as $key) {
4415 unset($GLOBALS['app_list_strings'][$key]);
4418 if(!empty($GLOBALS['app_strings'])) {
4419 foreach($GLOBALS['app_strings'] as $key=>$value) {
4420 if(!empty($all_non_custom_include_language_strings[$key])) {
4421 unset($GLOBALS['app_strings'][$key]);
4425 } //if(preg_match...)
4428 if(!empty($GLOBALS['app_strings'])) {
4429 foreach($GLOBALS['app_strings'] as $key=>$entry) {
4430 $out .= "\n\$GLOBALS['app_strings']['$key']=" . var_export_helper($entry) . ";";
4434 foreach($GLOBALS['app_list_strings'] as $key=>$entry) {
4435 $out .= "\n\$GLOBALS['app_list_strings']['$key']=" . var_export_helper($entry) . ";";
4439 } //if(preg_match...)
4443 //Create a backup just in case
4444 copy($file, $file . '.bak');
4445 $fp = @sugar_fopen($file, 'w');
4450 //If we can't update the file, just return
4451 $GLOBALS['log']->error("Unable to update file contents in fix_dropdown_list.");
4459 //Update db entries (the order matters here... need to process database changes first)
4460 if(!empty($affected_keys)) {
4461 foreach($affected_keys as $old_key=>$new_key) {
4462 $GLOBALS['db']->query("UPDATE fields_meta_data SET ext1 = '{$new_key}' WHERE ext1 = '{$old_key}'");
4466 //Update vardef files for affected modules
4467 if(!empty($affected_modules)) {
4468 foreach($affected_modules as $module=>$object) {
4469 VardefManager::refreshVardefs($module, $object);
4476 function update_iframe_dashlets(){
4477 require_once('cache/dashlets/dashlets.php');
4479 $db = DBManagerFactory::getInstance();
4480 $query = "SELECT id, contents, assigned_user_id FROM user_preferences WHERE deleted = 0 AND category = 'Home'";
4481 $result = $db->query($query, true, "Unable to update new default dashlets! ");
4482 while ($row = $db->fetchByAssoc($result)) {
4483 $content = unserialize(base64_decode($row['contents']));
4484 $assigned_user_id = $row['assigned_user_id'];
4485 $record_id = $row['id'];
4487 $current_user = new User();
4488 $current_user->retrieve($row['assigned_user_id']);
4490 if(!empty($content['dashlets']) && !empty($content['pages'])){
4491 $originalDashlets = $content['dashlets'];
4492 foreach($originalDashlets as $key => $ds){
4493 if(!empty($ds['options']['url']) && stristr($ds['options']['url'],'http://www.sugarcrm.com/crm/product/gopro')){
4494 unset($originalDashlets[$key]);
4497 $current_user->setPreference('dashlets', $originalDashlets, 0, 'Home');
4504 * convertImageToText
4505 * This method attempts to convert date type image to text on Microsoft SQL Server.
4506 * This method could NOT be used in any other type of datebases.
4508 function convertImageToText($table_name,$column_name){
4509 $set_lang = "SET LANGUAGE us_english";
4510 $GLOBALS['db']->query($set_lang);
4511 if($GLOBALS['db']->checkError()){
4512 logThis('An error occurred when performing this query-->'.$set_lang);
4514 $q="SELECT data_type
4515 FROM INFORMATION_SCHEMA.Tables T JOIN INFORMATION_SCHEMA.Columns C
4516 ON T.TABLE_NAME = C.TABLE_NAME where T.TABLE_NAME = '$table_name' and C.COLUMN_NAME = '$column_name'";
4517 $res= $GLOBALS['db']->query($q);
4518 if($GLOBALS['db']->checkError()){
4519 logThis('An error occurred when performing this query-->'.$q);
4521 $row= $GLOBALS['db']->fetchByAssoc($res);
4523 if(trim(strtolower($row['data_type'])) == 'image'){
4524 $addContent_temp = "alter table {$table_name} add {$column_name}_temp text null";
4525 $GLOBALS['db']->query($addContent_temp);
4526 if($GLOBALS['db']->checkError()){
4527 logThis('An error occurred when performing this query-->'.$addContent_temp);
4529 $qN = "select count=datalength({$column_name}), id, {$column_name} from {$table_name}";
4530 $result = $GLOBALS['db']->query($qN);
4531 while($row = $GLOBALS['db']->fetchByAssoc($result)){
4532 if($row['count'] >8000){
4533 $contentLength = $row['count'];
4536 $convertedContent = '';
4537 while($contentLength >0){
4538 $stepsQuery = "select cont=convert(varchar(max), convert(varbinary(8000), substring({$column_name},{$start},{$next}))) from {$table_name} where id= '{$row['id']}'";
4539 $steContQ = $GLOBALS['db']->query($stepsQuery);
4540 if($GLOBALS['db']->checkError()){
4541 logThis('An error occurred when performing this query-->'.$stepsQuery);
4543 $stepCont = $GLOBALS['db']->fetchByAssoc($steContQ);
4544 if(isset($stepCont['cont'])){
4545 $convertedContent = $convertedContent.$stepCont['cont'];
4547 $start = $start+$next;
4548 $contentLength = $contentLength - $next;
4550 $addContentDataText="update {$table_name} set {$column_name}_temp = '{$convertedContent}' where id= '{$row['id']}'";
4551 $GLOBALS['db']->query($addContentDataText);
4552 if($GLOBALS['db']->checkError()){
4553 logThis('An error occurred when performing this query-->'.$addContentDataText);
4557 $addContentDataText="update {$table_name} set {$column_name}_temp =
4558 convert(varchar(max), convert(varbinary(8000), {$column_name})) where id= '{$row['id']}'";
4559 $GLOBALS['db']->query($addContentDataText);
4560 if($GLOBALS['db']->checkError()){
4561 logThis('An error occurred when performing this query-->'.$addContentDataText);
4565 //drop the contents now and change contents_temp to contents
4566 $dropColumn = "alter table {$table_name} drop column {$column_name}";
4567 $GLOBALS['db']->query($dropColumn);
4568 if($GLOBALS['db']->checkError()){
4569 logThis('An error occurred when performing this query-->'.$dropColumn);
4571 $changeColumnName = "EXEC sp_rename '{$table_name}.[{$column_name}_temp]','{$column_name}','COLUMN'";
4572 $GLOBALS['db']->query($changeColumnName);
4573 if($GLOBALS['db']->checkError()){
4574 logThis('An error occurred when performing this query-->'.$changeColumnName);
4581 * This method attempts to delete all English inline help files.
4582 * This method was introduced by 5.5.0RC2.
4584 function clearHelpFiles(){
4585 $modulePath = clean_path(getcwd() . '/modules');
4586 $allHelpFiles = array();
4587 getFiles($allHelpFiles, $modulePath, "/en_us.help.*/");
4589 foreach( $allHelpFiles as $the_file ){
4590 if( is_file( $the_file ) ){
4591 unlink( $the_file );
4592 logThis("Deleted file: $the_file", $path);
4600 * upgradeDateTimeFields
4602 * This method came from bug: 39757 where the date_end field is a date field and not a datetime field
4603 * which prevents you from performing timezone offset calculations once the data has been saved.
4605 * @param path String location to log file, empty by default
4607 function upgradeDateTimeFields($path=''){
4610 if($db->dbType == 'mysql')
4612 $meetingsSql = "UPDATE meetings SET date_end = date_add(date_start, INTERVAL + CONCAT(duration_hours, ':', duration_minutes) HOUR_MINUTE)";
4613 $callsSql = "UPDATE calls SET date_end = date_add(date_start, INTERVAL + CONCAT(duration_hours, ':', duration_minutes) HOUR_MINUTE)";
4614 } else if($db->dbType == 'mssql') {
4615 $meetingsSql = "UPDATE meetings set date_end = DATEADD(hh, duration_hours, DATEADD(mi, duration_minutes, date_start))";
4616 $callsSql = "UPDATE calls set date_end = DATEADD(hh, duration_hours, DATEADD(mi, duration_minutes, date_start))";
4617 } else if ($db->dbType == 'oci8') {
4618 $meetingsSql = "UPDATE meetings SET date_end = date_start + duration_hours/24 + duration_minutes/1440";
4619 $callsSql = "UPDATE calls SET date_end = date_start + duration_hours/24 + duration_minutes/1440";
4622 if(isset($meetingsSql) && isset($callsSql))
4624 logThis('upgradeDateTimeFields Meetings SQL:' . $meetingsSql, $path);
4625 $db->query($meetingsSql);
4627 logThis('upgradeDateTimeFields Calls SQL:' . $callsSql, $path);
4628 $db->query($callsSql);
4635 * upgradeDocumentTypeFields
4638 function upgradeDocumentTypeFields($path){
4642 $documentsSql = "UPDATE documents SET doc_type = 'Sugar' WHERE doc_type IS NULL";
4643 $meetingsSql = "UPDATE meetings SET type = 'Sugar' WHERE type IS NULL";
4645 logThis('upgradeDocumentTypeFields Documents SQL:' . $documentsSql, $path);
4646 $db->query($documentsSql);
4647 logThis('upgradeDocumentTypeFields Meetings SQL:' . $meetingsSql, $path);
4648 $db->query($meetingsSql);
4653 * merge_config_si_settings
4654 * This method checks for the presence of a config_si.php file and, if found, merges the configuration
4655 * settings from the config_si.php file into config.php. If a config_si_location parameter value is not
4656 * supplied it will attempt to discover the config_si.php file location from where the executing script
4659 * @param write_to_upgrade_log boolean optional value to write to the upgradeWizard.log file
4660 * @param config_location String optional value to config.php file location
4661 * @param config_si_location String optional value to config_si.php file location
4662 * @param path String file of the location of log file to write to
4663 * @return boolean value indicating whether or not a merge was attempted with config_si.php file
4665 function merge_config_si_settings($write_to_upgrade_log=false, $config_location='', $config_si_location='', $path='')
4667 if(!empty($config_location) && !file_exists($config_location))
4669 if($write_to_upgrade_log)
4671 logThis('config.php file specified in ' . $config_si_location . ' could not be found. Skip merging', $path);
4674 } else if(empty($config_location)) {
4676 //We are assuming this is from the silentUpgrade scripts so argv[3] will point to SugarCRM install location
4677 if(isset($argv[3]) && is_dir($argv[3]))
4679 $config_location = $argv[3] . DIRECTORY_SEPARATOR . 'config.php';
4683 //If config_location is still empty or if the file cannot be found, skip merging
4684 if(empty($config_location) || !file_exists($config_location))
4686 if($write_to_upgrade_log)
4688 logThis('config.php file at (' . $config_location . ') could not be found. Skip merging.', $path);
4692 if($write_to_upgrade_log)
4694 logThis('Loading config.php file at (' . $config_location . ') for merging.', $path);
4697 include($config_location);
4698 if(empty($sugar_config))
4700 if($write_to_upgrade_log)
4702 logThis('config.php contents are empty. Skip merging.', $path);
4708 if(!empty($config_si_location) && !file_exists($config_si_location))
4710 if($write_to_upgrade_log)
4712 logThis('config_si.php file specified in ' . $config_si_location . ' could not be found. Skip merging', $path);
4715 } else if(empty($config_si_location)) {
4716 if(isset($argv[0]) && is_file($argv[0]))
4718 $php_file = $argv[0];
4719 $p_info = pathinfo($php_file);
4720 $php_dir = (isset($p_info['dirname']) && $p_info['dirname'] != '.') ? $p_info['dirname'] . DIRECTORY_SEPARATOR : '';
4721 $config_si_location = $php_dir . 'config_si.php';
4725 //If config_si_location is still empty or if the file cannot be found, skip merging
4726 if(empty($config_si_location) || !file_exists($config_si_location))
4728 if($write_to_upgrade_log)
4730 logThis('config_si.php file at (' . $config_si_location . ') could not be found. Skip merging.', $path);
4734 if($write_to_upgrade_log)
4736 logThis('Loading config_si.php file at (' . $config_si_location . ') for merging.', $path);
4739 include($config_si_location);
4740 if(empty($sugar_config_si))
4742 if($write_to_upgrade_log)
4744 logThis('config_si.php contents are empty. Skip merging.', $path);
4750 //Now perform the merge operation
4752 foreach($sugar_config_si as $key=>$value)
4754 if(!preg_match('/^setup_/', $key) && !isset($sugar_config[$key]))
4756 if($write_to_upgrade_log)
4758 logThis('Merge key (' . $key . ') with value (' . $value . ')', $path);
4760 $sugar_config[$key] = $value;
4767 if($write_to_upgrade_log)
4769 logThis('Update config.php file with new values', $path);
4772 if(!write_array_to_file("sugar_config", $sugar_config, $config_location)) {
4773 if($write_to_upgrade_log)
4775 logThis('*** ERROR: could not write to config.php', $path);
4780 if($write_to_upgrade_log)
4782 logThis('config.php values are in sync with config_si.php values. Skipped merging.');
4787 if($write_to_upgrade_log)
4789 logThis('End merge_config_si_settings', $path);
4795 * upgrade_connectors
4796 * @param $path String variable for the log path
4798 function upgrade_connectors($path='') {
4799 logThis('Begin upgrade_connectors', $path);
4801 $filePath = 'custom/modules/Connectors/connectors/sources/ext/soap/hoovers/config.php';
4802 if(file_exists($filePath))
4804 logThis("{$filePath} file", $path);
4806 if(!is_null($config))
4809 if(isset($config['properties']['hoovers_endpoint']))
4811 $config['properties']['hoovers_endpoint'] = 'http://hapi.hoovers.com/HooversAPI-33';
4815 if(isset($config['properties']['hoovers_wsdl']))
4817 $config['properties']['hoovers_wsdl'] = 'http://hapi.hoovers.com/HooversAPI-33/hooversAPI/hooversAPI.wsdl';
4823 if(!write_array_to_file('config', $config, $filePath)) {
4824 logThis("Could not write new configuration to {$filePath} file", $path);
4826 logThis('Modified file successfully with new configuration entries', $path);
4832 $filePath = 'custom/modules/Connectors/connectors/sources/ext/soap/hoovers/vardefs.php';
4833 if(file_exists($filePath))
4835 logThis("Modifying {$filePath} file", $path);
4837 $fileContents = file_get_contents($filePath);
4838 $out = str_replace('bal.specialtyCriteria.companyKeyword', 'bal.specialtyCriteria.companyName', $fileContents);
4839 file_put_contents($filePath, $out);
4842 logThis('End upgrade_connectors', $path);
4845 function repair_long_relationship_names($path='')
4847 logThis("Begin repair_long_relationship_names", $path);
4848 require_once 'modules/ModuleBuilder/parsers/relationships/DeployedRelationships.php' ;
4849 $GLOBALS['mi_remove_tables'] = false;
4851 foreach($GLOBALS['moduleList'] as $module)
4853 $relationships = new DeployedRelationships ($module) ;
4854 foreach($relationships->getRelationshipList() as $rel_name)
4856 if (strlen($rel_name) > 27 && empty($touched[$rel_name]))
4858 logThis("Rebuilding relationship fields for $rel_name", $path);
4859 $touched[$rel_name] = true;
4860 $rel_obj = $relationships->get($rel_name);
4861 $rel_obj->setReadonly(false);
4862 $relationships->delete($rel_name);
4863 $relationships->save();
4864 $relationships->add($rel_obj);
4865 $relationships->save();
4866 $relationships->build () ;
4870 logThis("End repair_long_relationship_names", $path);
4873 function removeSilentUpgradeVarsCache(){
4874 global $silent_upgrade_vars_loaded;
4876 $cacheFileDir = "{$GLOBALS['sugar_config']['cache_dir']}/silentUpgrader";
4877 $cacheFile = "{$cacheFileDir}/silentUpgradeCache.php";
4879 if(file_exists($cacheFile)){
4883 $silent_upgrade_vars_loaded = array(); // Set to empty to reset it
4888 function loadSilentUpgradeVars(){
4889 global $silent_upgrade_vars_loaded;
4891 if(empty($silent_upgrade_vars_loaded)){
4892 $cacheFile = "{$GLOBALS['sugar_config']['cache_dir']}/silentUpgrader/silentUpgradeCache.php";
4893 // We have no pre existing vars
4894 if(!file_exists($cacheFile)){
4895 // Set the vars array so it's loaded
4896 $silent_upgrade_vars_loaded = array('vars' => array());
4899 require_once($cacheFile);
4900 $silent_upgrade_vars_loaded = $silent_upgrade_vars_cache;
4907 function writeSilentUpgradeVars(){
4908 global $silent_upgrade_vars_loaded;
4910 if(empty($silent_upgrade_vars_loaded)){
4911 return false; // You should have set some values before trying to write the silent upgrade vars
4914 $cacheFileDir = "{$GLOBALS['sugar_config']['cache_dir']}/silentUpgrader";
4915 $cacheFile = "{$cacheFileDir}/silentUpgradeCache.php";
4917 require_once('include/dir_inc.php');
4918 if(!mkdir_recursive($cacheFileDir)){
4921 require_once('include/utils/file_utils.php');
4922 if(!write_array_to_file('silent_upgrade_vars_cache', $silent_upgrade_vars_loaded, $cacheFile, 'w')){
4924 logThis("WARNING: writeSilentUpgradeVars could not write to {$cacheFile}", $path);
4931 function setSilentUpgradeVar($var, $value){
4932 if(!loadSilentUpgradeVars()){
4936 global $silent_upgrade_vars_loaded;
4938 $silent_upgrade_vars_loaded['vars'][$var] = $value;
4943 function getSilentUpgradeVar($var){
4944 if(!loadSilentUpgradeVars()){
4948 global $silent_upgrade_vars_loaded;
4950 if(!isset($silent_upgrade_vars_loaded['vars'][$var])){
4954 return $silent_upgrade_vars_loaded['vars'][$var];
4960 * add_unified_search_to_custom_modules_vardefs
4962 * This method calls the repair code to remove the unified_search_modules.php fiel
4965 function add_unified_search_to_custom_modules_vardefs()
4967 if(file_exists('cache/modules/unified_search_modules.php'))
4969 unlink('cache/modules/unified_search_modules.php');
4975 * change from using the older SugarCache in 6.1 and below to the new one in 6.2
4977 function upgradeSugarCache($file)
4979 global $sugar_config;
4980 // file = getcwd().'/'.$sugar_config['upload_dir'].$_FILES['upgrade_zip']['name'];
4982 $cacheUploadUpgradesTemp = clean_path(mk_temp_dir("{$sugar_config['upload_dir']}upgrades/temp"));
4984 unzip($file, $cacheUploadUpgradesTemp);
4986 if(!file_exists(clean_path("{$cacheUploadUpgradesTemp}/manifest.php"))) {
4987 logThis("*** ERROR: no manifest file detected while bootstraping upgrade wizard files!");
4990 include(clean_path("{$cacheUploadUpgradesTemp}/manifest.php"));
4993 $allFiles = array();
4994 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/SugarCache"))) {
4995 $allFiles = findAllFiles(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/SugarCache"), $allFiles);
4997 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/external_cache.php"))) {
4998 $allFiles[] = clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/external_cache.php");
5000 $cwd = clean_path(getcwd());
5002 foreach($allFiles as $k => $file) {
5003 $file = clean_path($file);
5004 $destFile = str_replace(clean_path($cacheUploadUpgradesTemp.'/'.$manifest['copy_files']['from_dir']), $cwd, $file);
5005 if(!is_dir(dirname($destFile))) {
5006 mkdir_recursive(dirname($destFile)); // make sure the directory exists
5008 if ( stristr($file,'uw_main.tpl') )
5009 logThis('Skipping "'.$file.'" - file copy will during commit step.');
5011 logThis('updating UpgradeWizard code: '.$destFile);
5012 copy_recursive($file, $destFile);
5015 logThis ('is sugar_file_util there '.file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/sugar_file_utils.php")));
5016 if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/sugar_file_utils.php"))) {
5017 $file = clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/sugar_file_utils.php");
5018 $destFile = str_replace(clean_path($cacheUploadUpgradesTemp.'/'.$manifest['copy_files']['from_dir']), $cwd, $file);
5019 copy($file,$destFile);
5025 * upgradeDisplayedTabsAndSubpanels
5027 * @param $version String value of current system version (pre upgrade)
5029 function upgradeDisplayedTabsAndSubpanels($version)
5031 if($version < '620')
5033 logThis('start upgrading system displayed tabs and subpanels');
5034 require_once('modules/MySettings/TabController.php');
5035 $tc = new TabController();
5037 //grab the existing system tabs
5038 $tabs = $tc->get_tabs_system();
5040 //add Calls, Meetings, Tasks, Notes, Prospects (Targets) and ProspectLists (Target Lists)
5041 //to displayed tabs unless explicitly set to hidden
5042 $modules_to_add = array('Calls', 'Meetings', 'Tasks', 'Notes', 'Prospects', 'ProspectLists');
5043 $added_tabs = array();
5045 foreach($modules_to_add as $module)
5047 $tabs[0][$module] = $module;
5048 $added_tabs[] = $module;
5051 logThis('calling set_system_tabs on TabController to add tabs: ' . var_export($added_tabs, true));
5052 $tc->set_system_tabs($tabs[0]);
5053 logThis('finish upgrading system displayed tabs and subpanels');
5059 * unlinkUpgradeFiles
5060 * This is a helper function to clean up
5062 * @param $version String value of current system version (pre upgrade)
5064 function unlinkUpgradeFiles($version)
5066 if(!isset($version))
5071 logThis('start unlinking files from previous upgrade');
5072 if($version < '620')
5074 //list of files to remove
5075 $files_to_remove = array('modules/Notifications/metadata/studio.php', 'modules/Help/Forms.php','themes/Sugar5/images/sugarColors.xml');
5077 foreach($files_to_remove as $f)
5081 logThis('removing file: ' . $f);
5086 logThis('end unlinking files from previous upgrade');
5088 if($version < '620')
5090 logThis('start upgrade for DocumentRevisions classic files (EditView.html, EditView.php, DetailView.html, DetailView.php)');
5092 //Use a md5 comparison check to see if we can just remove the file where an exact match is found
5093 if($version < '610')
5096 'modules/DocumentRevisions/DetailView.html' => '17ad4d308ce66643fdeb6fdb3b0172d3',
5097 'modules/DocumentRevisions/DetailView.php' => 'd8606cdcd0281ae9443b2580a43eb5b3',
5098 'modules/DocumentRevisions/EditView.php' => 'c7a1c3ef2bb30e3f5a11d122b3c55ff1',
5099 'modules/DocumentRevisions/EditView.html' => '7d360ca703863c957f40b3719babe8c8',
5103 'modules/DocumentRevisions/DetailView.html' => 'a8356ff20cd995daffe6cb7f7b8b2340',
5104 'modules/DocumentRevisions/DetailView.php' => '20edf45dd785469c484fbddff1a3f8f2',
5105 'modules/DocumentRevisions/EditView.php' => 'fb31958496f04031b2851dcb4ce87d50',
5106 'modules/DocumentRevisions/EditView.html' => 'b8cada4fa6fada2b4e4928226d8b81ee',
5110 foreach($dr_files as $rev_file=>$hash)
5112 if(file_exists($rev_file))
5114 //It's a match here so let's just remove the file
5115 if (md5(file_get_contents($rev_file)) == $hash)
5117 logThis('removing file ' . $rev_file);
5120 if(!copy($rev_file, $rev_file . '.suback.bak'))
5122 logThis('error making backup for file ' . $rev_file);
5124 logThis('copied file ' . $rev_file . ' to ' . $rev_file . '.suback.bak');
5131 logThis('end upgrade for DocumentRevisions classic files');
5135 if (!function_exists("getValidDBName"))
5138 * Return a version of $proposed that can be used as a column name in any of our supported databases
5139 * 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)
5140 * @param string $name Proposed name for the column
5141 * @param string $ensureUnique
5142 * @return string Valid column name trimmed to right length and with invalid characters removed
5144 function getValidDBName ($name, $ensureUnique = false, $maxLen = 30)
5146 // first strip any invalid characters - all but alphanumerics and -
5147 $name = preg_replace ( '/[^\w-]+/i', '', $name ) ;
5148 $len = strlen ( $name ) ;
5152 $md5str = md5($name);
5153 $tail = substr ( $name, -11) ;
5154 $temp = substr($md5str , strlen($md5str)-4 );
5155 $result = substr ( $name, 0, 10) . $temp . $tail ;
5156 }else if ($len > ($maxLen - 5))
5158 $result = substr ( $name, 0, 11) . substr ( $name, 11 - $maxLen + 5);
5160 return strtolower ( $result ) ;