= 5){
$modules = getAllModules();
$backwardModules = array();
foreach($modules as $mod){
if(is_dir(clean_path(getcwd().'/modules/'.$mod.'/.500'))){
$files = array();
$files= findAllFiles(clean_path(getcwd().'/modules/'.$mod.'/.500'),$files);
if(sizeof($files) >0){
//backward compatibility is on
$backwardModules[] = $mod;
}
}
}
}
$newFiles = findAllFiles(clean_path($unzip_dir . '/' . $zip_from_dir), array());
$zipPath = clean_path($unzip_dir . '/' . $zip_from_dir);
// handle special do-not-overwrite conditions
$doNotOverwrite = array();
$doNotOverwrite[] = '__stub';
if(isset($_REQUEST['overwrite_files_serial'])) {
$doNotOverwrite = explode('::', $_REQUEST['overwrite_files_serial']);
}
$copiedFiles = array();
$skippedFiles = array();
foreach($newFiles as $file) {
$cleanFile = str_replace($zipPath, '', $file);
$srcFile = $zipPath . $cleanFile;
$targetFile = clean_path(getcwd() . '/' . $cleanFile);
if($backwardModules != null && sizeof($backwardModules) >0){
foreach($backwardModules as $mod){
$splitPath = explode('/',trim($cleanFile));
if('modules' == trim($splitPath[1]) && $mod == trim($splitPath[2])){
$cleanFile = str_replace('/modules/'.$mod, '/modules/'.$mod.'/.500', $cleanFile);
$targetFile = clean_path(getcwd() . '/' . $cleanFile);
}
}
}
if(!is_dir(dirname($targetFile))) {
mkdir_recursive(dirname($targetFile)); // make sure the directory exists
}
if((!file_exists($targetFile)) || /* brand new file */
(!in_array($targetFile, $doNotOverwrite)) /* manual diff file */
) {
// handle sugar_version.php
if(strpos($targetFile, 'sugar_version.php') !== false && !preg_match('/\/portal\/sugar_version\.php$/i', $targetFile)) {
logThis('Skipping "sugar_version.php" - file copy will occur at end of successful upgrade', $path);
$_SESSION['sugar_version_file'] = $srcFile;
continue;
}
//logThis('Copying file to destination: ' . $targetFile, $path);
if(!copy($srcFile, $targetFile)) {
logThis('*** ERROR: could not copy file: ' . $targetFile, $path);
} else {
$copiedFiles[] = $targetFile;
}
} else {
//logThis('Skipping file: ' . $targetFile, $path);
$skippedFiles[] = $targetFile;
}
}
logThis('File copy done.', $path);
$ret = array();
$ret['copiedFiles'] = $copiedFiles;
$ret['skippedFiles'] = $skippedFiles;
return $ret;
}
//On cancel put back the copied files from 500 to 451 state
function copyFilesOnCancel($step){
//place hoder for cancel action
}
function removeFileFromPath($file,$path, $deleteNot=array()){
$removed = 0;
$cur = $path . '/' . $file;
if(file_exists($cur)){
$del = true;
foreach($deleteNot as $dn){
if($cur == $dn){
$del = false;
}
}
if($del){
unlink($cur);
$removed++;
}
}
if(!file_exists($path))return $removed;
$d = dir($path);
while($e = $d->read()){
$next = $path . '/'. $e;
if(substr($e, 0, 1) != '.' && is_dir($next)){
$removed += removeFileFromPath($file, $next, $deleteNot);
}
}
return $removed;
}
/**
* This function copies/overwrites between directories
*
* @param string the directory name to remove
* @param boolean whether to just empty the given directory, without deleting the given directory.
* @return boolean True/False whether the directory was deleted.
*/
function copyRecursiveBetweenDirectories($from,$to){
if(file_exists($from)){
$modifiedFiles = array();
$modifiedFiles = findAllFiles(clean_path($from), $modifiedFiles);
$cwd = clean_path(getcwd());
foreach($modifiedFiles as $file) {
$srcFile = clean_path($file);
//$targetFile = clean_path(getcwd() . '/' . $srcFile);
if (strpos($srcFile,".svn") !== false) {
//do nothing
}
else{
$targetFile = str_replace($from, $to, $srcFile);
if(!is_dir(dirname($targetFile))) {
mkdir_recursive(dirname($targetFile)); // make sure the directory exists
}
// handle sugar_version.php
if(strpos($targetFile, 'sugar_version.php') !== false && !preg_match('/\/portal\/sugar_version\.php$/i', $targetFile)) {
logThis('Skipping "sugar_version.php" - file copy will occur at end of successful upgrade', $path);
$_SESSION['sugar_version_file'] = $srcFile;
continue;
}
//logThis('Copying file to destination: ' . $targetFile);
if(!copy($srcFile, $targetFile)) {
logThis('*** ERROR: could not copy file: ' . $targetFile);
} else {
//logThis('Copied file: ' . $targetFile);
//$copiedFiles[] = $targetFile;
}
}
}
}
}
function deleteDirectory($dirname,$only_empty=false) {
if (!is_dir($dirname))
return false;
$dscan = array(realpath($dirname));
$darr = array();
while (!empty($dscan)) {
$dcur = array_pop($dscan);
$darr[] = $dcur;
if ($d=opendir($dcur)) {
while ($f=readdir($d)) {
if ($f=='.' || $f=='..')
continue;
$f=$dcur.'/'.$f;
if (is_dir($f))
$dscan[] = $f;
else
unlink($f);
}
closedir($d);
}
}
$i_until = ($only_empty)? 1 : 0;
for ($i=count($darr)-1; $i>=$i_until; $i--) {
//echo "\nDeleting '".$darr[$i]."' ... ";
if (rmdir($darr[$i]))
logThis('Success :Copying file to destination: ' . $darr[$i]);
else
logThis('Copy problem:Copying file to destination: ' . $darr[$i]);
}
return (($only_empty)? (count(scandir)<=2) : (!is_dir($dirname)));
}
/**
* Get all the customized modules. Compare the file md5s with the base md5s
* If a file has been modified then put the module in the list of customized
* modules. Show the list in the preflight check UI.
*/
function deleteAndOverWriteSelectedFiles($unzip_dir, $zip_from_dir,$delete_dirs){
if($delete_dirs != null){
foreach($delete_dirs as $del_dir){
deleteDirectory($del_dir);
$newFiles = findAllFiles(clean_path($unzip_dir . '/' . $zip_from_dir.'/'.$del_dir), array());
$zipPath = clean_path($unzip_dir . '/' . $zip_from_dir.'/'.$del_dir);
$copiedFiles = array();
$skippedFiles = array();
foreach($newFiles as $file) {
$cleanFile = str_replace($zipPath, '', $file);
$srcFile = $zipPath . $cleanFile;
$targetFile = clean_path(getcwd() . '/' . $cleanFile);
if(!is_dir(dirname($targetFile))) {
mkdir_recursive(dirname($targetFile)); // make sure the directory exists
}
if(!file_exists($targetFile)){
// handle sugar_version.php
if(strpos($targetFile, 'sugar_version.php') !== false) {
logThis('Skipping sugar_version.php - file copy will occur at end of successful upgrade');
$_SESSION['sugar_version_file'] = $srcFile;
continue;
}
//logThis('Copying file to destination: ' . $targetFile);
if(!copy($srcFile, $targetFile)) {
logThis('*** ERROR: could not copy file: ' . $targetFile);
} else {
$copiedFiles[] = $targetFile;
}
} else {
//logThis('Skipping file: ' . $targetFile);
$skippedFiles[] = $targetFile;
}
}
}
}
$ret = array();
$ret['copiedFiles'] = $copiedFiles;
$ret['skippedFiles'] = $skippedFiles;
return $ret;
}
//Default is empty the directory. For removing set it to false
// to use this function to totally remove a directory, write:
// recursive_remove_directory('path/to/directory/to/delete',FALSE);
// to use this function to empty a directory, write:
// recursive_remove_directory('path/to/full_directory');
function recursive_empty_or_remove_directory($directory, $exclude_dirs=null,$exclude_files=null,$empty=TRUE)
{
// if the path has a slash at the end we remove it here
if(substr($directory,-1) == '/')
{
$directory = substr($directory,0,-1);
}
// if the path is not valid or is not a directory ...
if(!file_exists($directory) || !is_dir($directory))
{
// ... we return false and exit the function
return FALSE;
// ... if the path is not readable
}elseif(!is_readable($directory))
{
// ... we return false and exit the function
return FALSE;
// ... else if the path is readable
}else{
// we open the directory
$handle = opendir($directory);
// and scan through the items inside
while (FALSE !== ($item = readdir($handle)))
{
// if the filepointer is not the current directory
// or the parent directory
if($item != '.' && $item != '..')
{
// we build the new path to delete
$path = $directory.'/'.$item;
// if the new path is a directory
//add another check if the dir is in the list to exclude delete
if(is_dir($path) && $exclude_dirs != null && in_array($path,$exclude_dirs)){
//do nothing
}
else if(is_dir($path))
{
// we call this function with the new path
recursive_empty_or_remove_directory($path);
}
// if the new path is a file
else{
// we remove the file
if($exclude_files != null && in_array($path,$exclude_files)){
//do nothing
}
else{
unlink($path);
}
}
}
}
// close the directory
closedir($handle);
// if the option to empty is not set to true
if($empty == FALSE)
{
// try to delete the now empty directory
if(!rmdir($directory))
{
// return false if not possible
return FALSE;
}
}
// return success
return TRUE;
}
}
// ------------------------------------------------------------
function getAllCustomizedModules() {
require_once('files.md5');
$return_array = array();
$modules = getAllModules();
foreach($modules as $mod) {
//find all files in each module if the files have been modified
//as compared to the base version then add the module to the
//customized modules array
$modFiles = findAllFiles(clean_path(getcwd())."/modules/$mod", array());
foreach($modFiles as $file){
$fileContents = file_get_contents($file);
$file = str_replace(clean_path(getcwd()),'',$file);
if($md5_string['./' . $file]){
if(md5($fileContents) != $md5_string['./' . $file]) {
//A file has been customized in the module. Put the module into the
// customized modules array.
echo 'Changed File'.$file;
$return_array[$mod];
break;
}
}
else{
// This is a new file in user's version and indicates that module has been
//customized. Put the module in the customized array.
echo 'New File'.$file;
$return_array[$mod];
break;
}
}
} //foreach
return $return_array;
}
/**
* Array of all Modules in the version bein upgraded
* This method returns an Array of all modules
* @return $modules Array of modules.
*/
function getAllModules() {
$modules = array();
$d = dir('modules');
while($e = $d->read()){
if(substr($e, 0, 1) == '.' || !is_dir('modules/' . $e))continue;
$modules[] = $e;
}
return $modules;
}
//Remove files with the smae md5
function removeMd5MatchingFiles($deleteNot=array()){
$md5_string = array();
if(file_exists(clean_path(getcwd().'/files.md5'))){
require(clean_path(getcwd().'/files.md5'));
}
$modulesAll = getAllModules();
foreach($modulesAll as $mod){
$allModFiles = array();
if(is_dir('modules/'.$mod)){
$allModFiles = findAllFiles('modules/'.$mod,$allModFiles);
foreach($allModFiles as $file){
if(file_exists($file) && !in_array(basename($file),$deleteNot)){
if(isset($md5_string['./'.$file])) {
$fileContents = file_get_contents($file);
if(md5($fileContents) == $md5_string['./'.$file]) {
unlink($file);
}
}
}
}
}
}
}
/**
* Handles requirements for creating reminder Tasks and Emails
* @param array skippedFiles Array of files that were not overwriten and must be manually mereged.
* @param string path Optional full path to alternate upgradeWizard log.
*/
function commitHandleReminders($skippedFiles, $path='') {
global $mod_strings;
global $current_user;
if(empty($mod_strings))
$mod_strings = return_module_language('en_us', 'UpgradeWizard');
if(empty($current_user->id)) {
$current_user->getSystemUser();
}
if(count($skippedFiles) > 0) {
$desc = $mod_strings['LBL_UW_COMMIT_ADD_TASK_OVERVIEW'] . "\n\n";
$desc .= $mod_strings['LBL_UW_COMMIT_ADD_TASK_DESC_1'];
$desc .= $_SESSION['uw_restore_dir'] . "\n\n";
$desc .= $mod_strings['LBL_UW_COMMIT_ADD_TASK_DESC_2'] . "\n\n";
foreach($skippedFiles as $file) {
$desc .= $file . "\n";
}
//MFH #13468
/// Not using new TimeDate stuff here because it needs to be compatible with 6.0
$nowDate = gmdate('Y-m-d');
$nowTime = gmdate('H:i:s');
$nowDateTime = $nowDate . ' ' . $nowTime;
if($_REQUEST['addTaskReminder'] == 'remind') {
logThis('Adding Task for admin for manual merge.', $path);
$task = new Task();
$task->name = $mod_strings['LBL_UW_COMMIT_ADD_TASK_NAME'];
$task->description = $desc;
$task->date_due = $nowDate;
$task->time_due = $nowTime;
$task->priority = 'High';
$task->status = 'Not Started';
$task->assigned_user_id = $current_user->id;
$task->created_by = $current_user->id;
$task->date_entered = $nowDateTime;
$task->date_modified = $nowDateTime;
$task->save();
}
if($_REQUEST['addEmailReminder'] == 'remind') {
logThis('Sending Reminder for admin for manual merge.', $path);
$email = new Email();
$email->assigned_user_id = $current_user->id;
$email->name = $mod_strings['LBL_UW_COMMIT_ADD_TASK_NAME'];
$email->description = $desc;
$email->description_html = nl2br($desc);
$email->from_name = $current_user->full_name;
$email->from_addr = $current_user->email1;
$email->to_addrs_arr = $email->parse_addrs($current_user->email1, '', '', '');
$email->cc_addrs_arr = array();
$email->bcc_addrs_arr = array();
$email->date_entered = $nowDateTime;
$email->date_modified = $nowDateTime;
$email->send();
$email->save();
}
}
}
function deleteCache(){
//Clean modules from cache
if(is_dir($GLOBALS['sugar_config']['cache_dir'].'modules')){
$allModFiles = array();
$allModFiles = findAllFiles($GLOBALS['sugar_config']['cache_dir'].'modules',$allModFiles,true);
foreach($allModFiles as $file)
{
if(file_exists($file))
{
if(is_dir($file))
{
rmdir_recursive($file);
} else {
unlink($file);
}
}
}
}
//Clean jsLanguage from cache
if(is_dir($GLOBALS['sugar_config']['cache_dir'].'jsLanguage')){
$allModFiles = array();
$allModFiles = findAllFiles($GLOBALS['sugar_config']['cache_dir'].'jsLanguage',$allModFiles);
foreach($allModFiles as $file){
if(file_exists($file)){
unlink($file);
}
}
}
//Clean smarty from cache
if(is_dir($GLOBALS['sugar_config']['cache_dir'].'smarty')){
$allModFiles = array();
$allModFiles = findAllFiles($GLOBALS['sugar_config']['cache_dir'].'smarty',$allModFiles);
foreach($allModFiles as $file){
if(file_exists($file)){
unlink($file);
}
}
}
//Rebuild dashlets cache
require_once('include/Dashlets/DashletCacheBuilder.php');
$dc = new DashletCacheBuilder();
$dc->buildCache();
}
function deleteChance(){
//Clean folder from cache
if(is_dir('include/SugarObjects/templates/chance')){
rmdir_recursive('include/SugarObjects/templates/chance');
}
if(is_dir('include/SugarObjects/templates/chance')){
if(!isset($_SESSION['chance'])){
$_SESSION['chance'] = '';
}
$_SESSION['chance'] = 'include/SugarObjects/templates/chance';
//rename('include/SugarObjects/templates/chance','include/SugarObjects/templates/chance_removeit');
}
}
/**
* copies upgrade wizard files from new patch if that dir exists
* @param string file Path to uploaded zip file
*/
function upgradeUWFiles($file) {
global $sugar_config;
// file = getcwd().'/'.$sugar_config['upload_dir'].$_FILES['upgrade_zip']['name'];
$cacheUploadUpgradesTemp = clean_path(mk_temp_dir("{$sugar_config['upload_dir']}upgrades/temp"));
unzip($file, $cacheUploadUpgradesTemp);
if(!file_exists(clean_path("{$cacheUploadUpgradesTemp}/manifest.php"))) {
logThis("*** ERROR: no manifest file detected while bootstraping upgrade wizard files!");
return;
} else {
include(clean_path("{$cacheUploadUpgradesTemp}/manifest.php"));
}
$allFiles = array();
// upgradeWizard
if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/modules/UpgradeWizard"))) {
$allFiles = findAllFiles(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/modules/UpgradeWizard"), $allFiles);
}
// moduleInstaller
if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/ModuleInstall"))) {
$allFiles = findAllFiles(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/ModuleInstall"), $allFiles);
}
if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/javascript/yui"))) {
$allFiles = findAllFiles(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/javascript/yui"), $allFiles);
}
if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/HandleAjaxCall.php"))) {
$allFiles[] = clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/HandleAjaxCall.php");
}
if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/SugarTheme"))) {
$allFiles = findAllFiles(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/SugarTheme"), $allFiles);
}
if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/SugarCache"))) {
$allFiles = findAllFiles(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/SugarCache"), $allFiles);
}
if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/external_cache.php"))) {
$allFiles[] = clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/external_cache.php");
}
/*
* /home/chris/workspace/maint450/cache/upload/upgrades/temp/DlNnqP/
* SugarEnt-Patch-4.5.0c/modules/Leads/ConvertLead.html
*/
$cwd = clean_path(getcwd());
foreach($allFiles as $k => $file) {
$file = clean_path($file);
$destFile = str_replace(clean_path($cacheUploadUpgradesTemp.'/'.$manifest['copy_files']['from_dir']), $cwd, $file);
if(!is_dir(dirname($destFile))) {
mkdir_recursive(dirname($destFile)); // make sure the directory exists
}
if ( stristr($file,'uw_main.tpl') )
logThis('Skipping "'.$file.'" - file copy will during commit step.');
else {
logThis('updating UpgradeWizard code: '.$destFile);
copy_recursive($file, $destFile);
}
}
logThis ('is sugar_file_util there '.file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/sugar_file_utils.php")));
if(file_exists(clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/sugar_file_utils.php"))) {
$file = clean_path("{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}/include/utils/sugar_file_utils.php");
$destFile = str_replace(clean_path($cacheUploadUpgradesTemp.'/'.$manifest['copy_files']['from_dir']), $cwd, $file);
copy($file,$destFile);
}
}
/**
* gets valid patch file names that exist in upload/upgrade/patch/
*/
function getValidPatchName($returnFull = true) {
global $base_upgrade_dir;
global $mod_strings;
global $uh;
global $sugar_version;
global $sugar_config;
$uh = new UpgradeHistory();
$base_upgrade_dir = $sugar_config['upload_dir'] . "upgrades";
$return = array();
// scan for new files (that are not installed)
logThis('finding new files for upgrade');
$upgrade_content = '';
$upgrade_contents = findAllFiles($base_upgrade_dir, array(), false, 'zip');
//other variations of zip file i.e. ZIP, zIp,zIP,Zip,ZIp,ZiP
$extns = array('ZIP','ZIp','ZiP','Zip','zIP','zIp','ziP');
foreach($extns as $extn){
$upgrade_contents = array_merge($upgrade_contents,findAllFiles( "$base_upgrade_dir", array() , false, $extn));
}
$ready = "
\n";
$ready .= "
|
{$mod_strings['LBL_ML_NAME']}
|
{$mod_strings['LBL_ML_TYPE']}
|
{$mod_strings['LBL_ML_VERSION']}
|
{$mod_strings['LBL_ML_PUBLISHED']}
|
{$mod_strings['LBL_ML_UNINSTALLABLE']}
|
{$mod_strings['LBL_ML_DESCRIPTION']}
|
";
$disabled = '';
// assume old patches are there.
$upgradeToVersion = array(); // fill with valid patches - we will only use the latest qualified found patch
// cn: bug 10609 - notices for uninitialized variables
$icon = '';
$name = '';
$type = '';
$version = '';
$published_date = '';
$uninstallable = '';
$description = '';
$disabled = '';
foreach($upgrade_contents as $upgrade_content) {
if(!preg_match("#.*\.zip\$#i", strtolower($upgrade_content))) {
continue;
}
$upgrade_content = clean_path($upgrade_content);
$the_base = basename($upgrade_content);
$the_md5 = md5_file($upgrade_content);
$md5_matches = $uh->findByMd5($the_md5);
/* 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.
* Edge-case: manual upgrade with a FTP of a patch; UH table has no entry for it. Assume nothing. :( */
if(0 == sizeof($md5_matches)) {
$target_manifest = remove_file_extension( $upgrade_content ) . '-manifest.php';
require_once($target_manifest);
if(empty($manifest['version'])) {
logThis("*** Potential error: patch found with no version [ {$upgrade_content} ]");
continue;
}
if(!isset($manifest['type']) || $manifest['type'] != 'patch') {
logThis("*** Potential error: patch found with either no 'type' or non-patch type [ {$upgrade_content} ]");
continue;
}
$upgradeToVersion[$manifest['version']] = urlencode($upgrade_content);
$name = empty($manifest['name']) ? $upgrade_content : $manifest['name'];
$version = empty($manifest['version']) ? '' : $manifest['version'];
$published_date = empty($manifest['published_date']) ? '' : $manifest['published_date'];
$icon = '';
$description = empty($manifest['description']) ? 'None' : $manifest['description'];
$uninstallable = empty($manifest['is_uninstallable']) ? 'No' : 'Yes';
$type = getUITextForType( $manifest['type'] );
$manifest_type = $manifest['type'];
if(empty($manifest['icon'])) {
$icon = getImageForType( $manifest['type'] );
} else {
$path_parts = pathinfo( $manifest['icon'] );
$icon = "";
}
}
}
// cn: bug 10488 use the NEWEST upgrade/patch available when running upgrade wizard.
ksort($upgradeToVersion);
$upgradeToVersion = array_values($upgradeToVersion);
$newest = array_pop($upgradeToVersion);
$_SESSION['install_file'] = urldecode($newest); // in-case it was there from a prior.
logThis("*** UW using [ {$_SESSION['install_file']} ] as source for patch files.");
$cleanUpgradeContent = urlencode($_SESSION['install_file']);
// cn: 10606 - cannot upload a patch file since this returned always.
if(!empty($cleanUpgradeContent)) {
$ready .= "$icon | $name | $type | $version | $published_date | $uninstallable | $description | \n";
$ready .=<<
eoq;
$disabled = "DISABLED";
}
if(empty($cleanUpgradeContent)){
$ready .= "None | \n";
$ready .= "\n";
}
$ready .= "
\n";
$return['ready'] = $ready;
$return['disabled'] = $disabled;
if($returnFull) {
return $return;
}
}
/**
* finalizes upgrade by setting upgrade versions in DB (config table) and sugar_version.php
* @return bool true on success
*/
function updateVersions($version) {
global $db;
global $sugar_config;
global $path;
logThis('At updateVersions()... updating config table and sugar_version.php.', $path);
// handle file copy
if(isset($_SESSION['sugar_version_file']) && !empty($_SESSION['sugar_version_file'])) {
if(!copy($_SESSION['sugar_version_file'], clean_path(getcwd().'/sugar_version.php'))) {
logThis('*** ERROR: sugar_version.php could not be copied to destination! Cannot complete upgrade', $path);
return false;
} else {
logThis('sugar_version.php successfully updated!', $path);
}
} else {
logThis('*** ERROR: no sugar_version.php file location found! - cannot complete upgrade...', $path);
return false;
}
// handle config table
if($db->dbType == 'mysql') {
$q1 = "DELETE FROM `config` WHERE `category` = 'info' AND `name` = 'sugar_version'";
$q2 = "INSERT INTO `config` (`category`, `name`, `value`) VALUES ('info', 'sugar_version', '{$version}')";
} elseif($db->dbType == 'oci8' || $db->dbType == 'oracle') {
} elseif($db->dbType == 'mssql') {
$q1 = "DELETE FROM config WHERE category = 'info' AND name = 'sugar_version'";
$q2 = "INSERT INTO config (category, name, value) VALUES ('info', 'sugar_version', '{$version}')";
}
logThis('Deleting old DB version info from config table.', $path);
$db->query($q1);
logThis('Inserting updated version info into config table.', $path);
$db->query($q2);
logThis('updateVersions() complete.', $path);
return true;
}
/**
* gets a module's lang pack - does not need to be a SugarModule
* @param lang string Language
* @param module string Path to language folder
* @return array mod_strings
*/
function getModuleLanguagePack($lang, $module) {
$mod_strings = array();
if(!empty($lang) && !empty($module)) {
$langPack = clean_path(getcwd().'/'.$module.'/language/'.$lang.'.lang.php');
$langPackEn = clean_path(getcwd().'/'.$module.'/language/en_us.lang.php');
if(file_exists($langPack))
include_once($langPack);
elseif(file_exists($langPackEn))
include_once($langPackEn);
}
return $mod_strings;
}
/**
* checks system compliance for 4.5+ codebase
* @return array Mixed values
*/
function checkSystemCompliance() {
global $sugar_config;
global $current_language;
global $db;
global $mod_strings;
if(!defined('SUGARCRM_MIN_MEM')) {
define('SUGARCRM_MIN_MEM', 40);
}
$installer_mod_strings = getModuleLanguagePack($current_language, './install');
$ret = array();
$ret['error_found'] = false;
// PHP version
$php_version = constant('PHP_VERSION');
$check_php_version_result = check_php_version($php_version);
switch($check_php_version_result) {
case -1:
$ret['phpVersion'] = "{$installer_mod_strings['ERR_CHECKSYS_PHP_INVALID_VER']} {$php_version} )";
$ret['error_found'] = true;
break;
case 0:
$ret['phpVersion'] = "{$installer_mod_strings['ERR_CHECKSYS_PHP_UNSUPPORTED']} {$php_version} )";
break;
case 1:
$ret['phpVersion'] = "{$installer_mod_strings['LBL_CHECKSYS_PHP_OK']} {$php_version} )";
break;
}
// database and connect
switch($sugar_config['dbconfig']['db_type']){
case 'mysql':
// mysql version
$q = "SELECT version();";
$r = $db->query($q);
$a = $db->fetchByAssoc($r);
if(version_compare($a['version()'], '4.1.2') < 0) {
$ret['error_found'] = true;
$ret['mysqlVersion'] = "".$mod_strings['ERR_UW_MYSQL_VERSION'].$a['version()']."";
}
break;
case 'mssql':
break;
case 'oci8':
break;
}
// XML Parsing
if(function_exists('xml_parser_create')) {
$ret['xmlStatus'] = "{$installer_mod_strings['LBL_CHECKSYS_OK']}";
} else {
$ret['xmlStatus'] = "{$installer_mod_strings['LBL_CHECKSYS_NOT_AVAILABLE']}";
$ret['error_found'] = true;
}
// cURL
if(function_exists('curl_init')) {
$ret['curlStatus'] = "{$installer_mod_strings['LBL_CHECKSYS_OK']}";
} else {
$ret['curlStatus'] = "{$installer_mod_strings['ERR_CHECKSYS_CURL']}";
$ret['error_found'] = false;
}
// mbstrings
if(function_exists('mb_strlen')) {
$ret['mbstringStatus'] = "{$installer_mod_strings['LBL_CHECKSYS_OK']}";
} else {
$ret['mbstringStatus'] = "{$installer_mod_strings['ERR_CHECKSYS_MBSTRING']}";
$ret['error_found'] = true;
}
// imap
if(function_exists('imap_open')) {
$ret['imapStatus'] = "{$installer_mod_strings['LBL_CHECKSYS_OK']}";
} else {
$ret['imapStatus'] = "{$installer_mod_strings['ERR_CHECKSYS_IMAP']}";
$ret['error_found'] = false;
}
// safe mode
if('1' == ini_get('safe_mode')) {
$ret['safeModeStatus'] = "{$installer_mod_strings['ERR_CHECKSYS_SAFE_MODE']}";
$ret['error_found'] = true;
} else {
$ret['safeModeStatus'] = "{$installer_mod_strings['LBL_CHECKSYS_OK']}";
}
// call time pass by ref
if('1' == ini_get('allow_call_time_pass_reference')) {
$ret['callTimeStatus'] = "{$installer_mod_strings['ERR_CHECKSYS_CALL_TIME']}";
//continue upgrading
} else {
$ret['callTimeStatus'] = "{$installer_mod_strings['LBL_CHECKSYS_OK']}";
}
// memory limit
$ret['memory_msg'] = "";
$memory_limit = "-1";//ini_get('memory_limit');
$sugarMinMem = constant('SUGARCRM_MIN_MEM');
// logic based on: http://us2.php.net/manual/en/ini.core.php#ini.memory-limit
if( $memory_limit == "" ){ // memory_limit disabled at compile time, no memory limit
$ret['memory_msg'] = "{$installer_mod_strings['LBL_CHECKSYS_MEM_OK']}";
} elseif( $memory_limit == "-1" ){ // memory_limit enabled, but set to unlimited
$ret['memory_msg'] = "{$installer_mod_strings['LBL_CHECKSYS_MEM_UNLIMITED']}";
} else {
rtrim($memory_limit, 'M');
$memory_limit_int = (int) $memory_limit;
if( $memory_limit_int < constant('SUGARCRM_MIN_MEM') ){
$ret['memory_msg'] = "{$installer_mod_strings['ERR_CHECKSYS_MEM_LIMIT_1']}" . constant('SUGARCRM_MIN_MEM') . "{$installer_mod_strings['ERR_CHECKSYS_MEM_LIMIT_2']}";
$ret['error_found'] = true;
} else {
$ret['memory_msg'] = "{$installer_mod_strings['LBL_CHECKSYS_OK']} ({$memory_limit})";
}
}
/* mbstring.func_overload
$ret['mbstring.func_overload'] = '';
$mb = ini_get('mbstring.func_overload');
if($mb > 1) {
$ret['mbstring.func_overload'] = "{$mod_strings['ERR_UW_MBSTRING_FUNC_OVERLOAD']}";
$ret['error_found'] = true;
}
*/
return $ret;
}
function checkMysqlConnection(){
global $sugar_config;
$configOptions = $sugar_config['dbconfig'];
if($sugar_config['dbconfig']['db_type'] == 'mysql'){
@mysql_ping($GLOBALS['db']->database);
}
}
/**
* is a file that we blow away automagically
*/
function isAutoOverwriteFile($file) {
$overwriteDirs = array(
'./sugar_version.php',
'./modules/UpgradeWizard/uw_main.tpl',
);
$file = trim('.'.str_replace(clean_path(getcwd()), '', $file));
if(in_array($file, $overwriteDirs)) {
return true;
}
$fileExtension = substr(strrchr($file, "."), 1);
if($fileExtension == 'tpl' || $fileExtension == 'html') {
return false;
}
return true;
}
/**
* flatfile logger
*/
function logThis($entry, $path='') {
global $mod_strings;
if(file_exists('include/utils/sugar_file_utils.php')){
require_once('include/utils/sugar_file_utils.php');
}
$log = empty($path) ? clean_path(getcwd().'/upgradeWizard.log') : clean_path($path);
// create if not exists
if(!file_exists($log)) {
if(function_exists('sugar_fopen')){
$fp = @sugar_fopen($log, 'w+'); // attempts to create file
}
else{
$fp = fopen($log, 'w+'); // attempts to create file
}
if(!is_resource($fp)) {
$GLOBALS['log']->fatal('UpgradeWizard could not create the upgradeWizard.log file');
die($mod_strings['ERR_UW_LOG_FILE_UNWRITABLE']);
}
} else {
if(function_exists('sugar_fopen')){
$fp = @sugar_fopen($log, 'a+'); // write pointer at end of file
}
else{
$fp = @fopen($log, 'a+'); // write pointer at end of file
}
if(!is_resource($fp)) {
$GLOBALS['log']->fatal('UpgradeWizard could not open/lock upgradeWizard.log file');
die($mod_strings['ERR_UW_LOG_FILE_UNWRITABLE']);
}
}
$line = date('r').' [UpgradeWizard] - '.$entry."\n";
if(@fwrite($fp, $line) === false) {
$GLOBALS['log']->fatal('UpgradeWizard could not write to upgradeWizard.log: '.$entry);
die($mod_strings['ERR_UW_LOG_FILE_UNWRITABLE']);
}
if(is_resource($fp)) {
fclose($fp);
}
}
/**
* tries to validate the query based on type
* @param string query The query to verify
* @param string dbType The DB type
* @return string error Non-empty string on error
*/
function verifySqlStatement($query, $dbType, &$newTables) {
$error = '';
logThis('verifying SQL statement');
$table = getTableFromQuery($query);
switch(strtoupper(substr($query, 0, 10))) {
// ignore DROPs
case 'ALTER TABL':
// get ddl
$error = testQueryAlter($table, $dbType, strtoupper($query), $newTables);
break;
case 'CREATE TAB':
$error = testQueryCreate($table, $dbType, $query, $newTables);
break;
case 'DELETE FRO':
$error = testQueryDelete($table, $dbType, $query);
break;
case 'DROP TABLE':
$error = testQueryDrop($table, $dbType, $query);
break;
case 'INSERT INT':
$error = testQueryInsert($table, $dbType, $query);
break;
case (strtoupper(substr($query, 0, 6)) == 'UPDATE'):
$error = testQueryUpdate($table, $dbType, $query);
break;
}
return $error;
}
/**
* @params : none
* @author: nsingh
* @desc This function is to be used in the upgrade process to preserve changes/customaizations made to pre 5.1 quickcreate layout.
* 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
* was automatically picked up by the quick create. [Addresses Bug 21469]
* This function will check if customizations were made, and will create quickcreatedefs.php in the /cutom/working/$module_name directory.
**/
function updateQuickCreateDefs(){
$d = dir('modules');
$studio_modules = array();
while($e = $d->read()){ //collect all studio modules.
if(substr($e, 0, 1) == '.' || !is_dir('modules/' . $e))continue;
if(file_exists('modules/' . $e . '/metadata/studio.php'))
{
array_push($studio_modules, $e);
}
}
foreach( $studio_modules as $modname ){ //for each studio enabled module
//Check !exists modules/$modname/metadata/quickcreatedefs.php &&
//exists custom/$modname/editviewdefs.php (module was customized) &&
//!exists custom/$modname/quickcreateviewdefs.php
$editviewdefs = "custom/working/modules/".$modname."/metadata/editviewdefs.php";
$quickcreatedefs = "custom/working/modules/".$modname."/metadata/quickcreatedefs.php";
if ( !file_exists("modules/".$modname."/metadata/quickcreatedefs.php") &&
file_exists($editviewdefs) &&
!file_exists($quickcreatedefs) ){
//clone editviewdef and save it in custom/working/modules/metadata
$GLOBALS['log']->debug("Copying editviewdefs.php as quickcreatedefs.php for the $modname module in custom/working/modules/$modname/metadata!");
if(copy( $editviewdefs, $quickcreatedefs)){
if(file_exists($quickcreatedefs) && is_readable($quickcreatedefs)){
$file = file($quickcreatedefs);
//replace 'EditView' with 'QuickCreate'
$fp = fopen($quickcreatedefs,'w');
foreach($file as &$line){
if(preg_match('/^\s*\'EditView\'\s*=>\s*$/', $line) > 0){
$line = "'QuickCreate' =>\n";
}
fwrite($fp, $line);
}
//write back.
fclose($fp);
}
else{
$GLOBALS['log']->debug("Failed to replace 'EditView' with QuickCreate because $quickcreatedefs is either not readable or does not exist.");
}
}else{
$GLOBALS['log']->debug("Failed to copy $editviewdefs to $quickcreatedefs!");
}
}
}
}
function cleanQuery($query, $oci8=false) {
$bad = array(
"'",
""",
);
$good = array(
'"',
"",
);
$q = str_replace($bad, $good, $query);
return $q;
}
/**
* test perms for CREATE queries
*/
function testPermsCreate($type, $out) {
logThis('Checking CREATE TABLE permissions...');
global $db;
global $mod_strings;
switch($type) {
case 'mysql':
case 'mssql':
$db->query('CREATE TABLE temp (id varchar(36))');
if($db->checkError()) {
logThis('cannot CREATE TABLE!');
$out['db']['dbNoCreate'] = true;
$out['dbOut'] .= "
{$mod_strings['LBL_UW_DB_NO_CREATE']} |
";
}
break;
case 'oci8':
break;
}
return $out;
}
/**
* test perms for INSERT
*/
function testPermsInsert($type, $out, $skip=false) {
logThis('Checking INSERT INTO permissions...');
global $db;
global $mod_strings;
switch($type) {
case 'mysql':
case 'mssql':
if(!$skip) {
$db->query("INSERT INTO temp (id) VALUES ('abcdef0123456789abcdef0123456789abcd')");
if($db->checkError()) {
logThis('cannot INSERT INTO!');
$out['db']['dbNoInsert'] = true;
$out['dbOut'] .= "{$mod_strings['LBL_UW_DB_NO_INSERT']} |
";
}
}
break;
case 'oci8':
break;
}
return $out;
}
/**
* test perms for UPDATE TABLE
*/
function testPermsUpdate($type, $out, $skip=false) {
logThis('Checking UPDATE TABLE permissions...');
global $db;
global $mod_strings;
switch($type) {
case 'mysql':
case 'mssql':
if(!$skip) {
$db->query("UPDATE temp SET id = '000000000000000000000000000000000000' WHERE id = 'abcdef0123456789abcdef0123456789abcd'");
if($db->checkError()) {
logThis('cannot UPDATE TABLE!');
$out['db']['dbNoUpdate'] = true;
$out['dbOut'] .= "{$mod_strings['LBL_UW_DB_NO_UPDATE']} |
";
}
}
break;
case 'oci8':
break;
}
return $out;
}
/**
* test perms for SELECT
*/
function testPermsSelect($type, $out, $skip=false) {
logThis('Checking SELECT permissions...');
global $db;
global $mod_strings;
switch($type) {
case 'mysql':
case 'mssql':
$r = $db->query('SELECT id FROM temp');
if($db->checkError()) {
logThis('cannot SELECT!');
$out['db']['dbNoSelect'] = true;
$out['dbOut'] .= "{$mod_strings['LBL_UW_DB_NO_SELECT']} |
";
}
logThis('Checking validity of SELECT results');
while($a = $db->fetchByAssoc($r)) {
if($a['id'] != '000000000000000000000000000000000000') {
logThis('results DO NOT MATCH! got: '.$a['id']);
$out['db'][] = 'selectFailed';
$out['dbOut'] .= "{$mod_strings['LBL_UW_DB_INSERT_FAILED']} |
";
}
}
break;
case 'oci8':
break;
}
return $out;
}
/**
* test perms for DELETE
*/
function testPermsDelete($type, $out, $skip=false) {
logThis('Checking DELETE FROM permissions...');
global $db;
global $mod_strings;
switch($type) {
case 'mysql':
case 'mssql':
$db->query("DELETE FROM temp WHERE id = '000000000000000000000000000000000000'");
if($db->checkError()) {
logThis('cannot DELETE FROM!');
$out['db']['dbNoDelete'] = true;
$out['dbOut'] .= "{$mod_strings['LBL_UW_DB_NO_DELETE']} |
";
}
break;
case 'oci8':
break;
}
return $out;
}
/**
* test perms for ALTER TABLE ADD COLUMN
*/
function testPermsAlterTableAdd($type, $out, $skip=false) {
logThis('Checking ALTER TABLE ADD COLUMN permissions...');
global $db;
global $mod_strings;
switch($type) {
case 'mysql':
$db->query('ALTER TABLE temp ADD COLUMN test varchar(100)');
if($db->checkError()) {
logThis('cannot ADD COLUMN!');
$out['db']['dbNoAddColumn'] = true;
$out['dbOut'] .= "{$mod_strings['LBL_UW_DB_NO_ADD_COLUMN']} |
";
}
break;
case 'mssql':
$db->query('ALTER TABLE [temp] ADD [test] [varchar] (100)');
if($db->checkError()) {
logThis('cannot ADD COLUMN!');
$out['db']['dbNoAddColumn'] = true;
$out['dbOut'] .= "{$mod_strings['LBL_UW_DB_NO_ADD_COLUMN']} |
";
}
break;
case 'oci8':
break;
}
return $out;
}
/**
* test perms for ALTER TABLE ADD COLUMN
*/
function testPermsAlterTableChange($type, $out, $skip=false) {
logThis('Checking ALTER TABLE CHANGE COLUMN permissions...');
global $db;
global $mod_strings;
switch($type) {
case 'mysql':
$db->query('ALTER TABLE temp CHANGE COLUMN test test varchar(100)');
if($db->checkError()) {
logThis('cannot CHANGE COLUMN!');
$out['db']['dbNoChangeColumn'] = true;
$out['dbOut'] .= "{$mod_strings['LBL_UW_DB_NO_CHANGE_COLUMN']} |
";
}
break;
case 'mssql':
$db->query('ALTER TABLE [temp] ALTER COLUMN [test] [varchar] (100)');
if($db->checkError()) {
logThis('cannot CHANGE COLUMN!');
$out['db']['dbNoChangeColumn'] = true;
$out['dbOut'] .= "{$mod_strings['LBL_UW_DB_NO_CHANGE_COLUMN']} |
";
}
break;
case 'oci8':
break;
}
return $out;
}
/**
* test perms for ALTER TABLE DROP COLUMN
*/
function testPermsAlterTableDrop($type, $out, $skip=false) {
logThis('Checking ALTER TABLE DROP COLUMN permissions...');
global $db;
global $mod_strings;
switch($type) {
case 'mysql':
case 'mssql':
$db->query('ALTER TABLE temp DROP COLUMN test');
if($db->checkError()) {
logThis('cannot DROP COLUMN!');
$out['db']['dbNoDropColumn'] = true;
$out['dbOut'] .= "{$mod_strings['LBL_UW_DB_NO_DROP_COLUMN']} |
";
}
break;
case 'oci8':
break;
}
return $out;
}
/**
* test perms for DROP TABLE
*/
function testPermsDropTable($type, $out, $skip=false) {
logThis('Checking DROP TABLE permissions...');
global $db;
global $mod_strings;
switch($type) {
case 'mysql':
case 'mssql':
$db->query('DROP TABLE temp');
if($db->checkError()) {
logThis('cannot DROP TABLE!');
$out['db']['dbNoDropTable'] = true;
$out['dbOut'] .= "{$mod_strings['LBL_UW_DB_NO_DROP_TABLE']} |
";
}
break;
case 'oci8':
break;
}
return $out;
}
function createMSSQLTemp($table) {
global $sugar_config;
global $db;
$qtest = "SELECT TABLE_NAME tn FROM information.tables WHERE TABLE_NAME = '{$table}__UW_TEMP'";
$rtest = $db->query($qtest);
$atest = $db->fetchByAssoc($rtest);
if(empty($atest)) {
$tempTable = "CREATE TABLE {$table}__UW_TEMP AS ".$db->limitQuerySql("SELECT * FROM {$table}",0,8);
logThis("Creating temp table for {$table}: {$tempTable}");
$db->query($tempTable);
}
else {
logThis("Found {$table}__UW_TEMP - skipping temp table creation.");
}
}
/**
* Tests an ALTER TABLE query
* @param string table The table name to get DDL
* @param string dbType MySQL, MSSQL, etc.
* @param string query The query to test.
* @return string Non-empty if error found
*/
function testQueryAlter($table, $dbType, $query, $newTables) {
logThis('verifying ALTER statement...');
global $db;
global $sugar_config;
if(empty($db)) {
$db = &DBManagerFactory::getInstance();
}
// Skipping ALTER TABLE [table] DROP PRIMARY KEY because primary keys are not being copied
// over to the temp tables
if(strpos(strtoupper($query), 'DROP PRIMARY KEY') !== false) {
logThis('Skipping DROP PRIMARY KEY verification');
return '';
}
if ($dbType == 'mysql'){
mysql_error(); // initialize errors
}
$error = '';
if(!in_array($table, $newTables)) {
switch($dbType) {
case 'mysql':
// get DDL
logThis('creating temp table for ['.$table.']...');
$q = "SHOW CREATE TABLE {$table}";
$r = $db->query($q);
$a = $db->fetchByAssoc($r);
// rewrite DDL with _temp name
$cleanQuery = cleanQuery($a['Create Table']);
$tempTableQuery = str_replace("CREATE TABLE `{$table}`", "CREATE TABLE `{$table}__uw_temp`", $cleanQuery);
$r2 = $db->query($tempTableQuery);
// get sample data into the temp table to test for data/constraint conflicts
logThis('inserting temp dataset...');
$q3 = "INSERT INTO `{$table}__uw_temp` SELECT * FROM `{$table}` LIMIT 10";
$r3 = $db->query($q3, false, "Preflight Failed for: {$query}");
// test the query on the test table
logThis('testing query: ['.$query.']');
$tempTableTestQuery = str_replace("ALTER TABLE `{$table}`", "ALTER TABLE `{$table}__uw_temp`", $query);
if (strpos($tempTableTestQuery, 'idx') === false) {
if(isRunningAgainstTrueTable($tempTableTestQuery)) {
$error = getFormattedError('Could not use a temp table to test query!', $query);
return $error;
}
logThis('testing query on temp table: ['.$tempTableTestQuery.']');
$r4 = $db->query($tempTableTestQuery, false, "Preflight Failed for: {$query}");
}
else {
// test insertion of an index on a table
$tempTableTestQuery_idx = str_replace("ADD INDEX `idx_", "ADD INDEX `temp_idx_", $tempTableTestQuery);
logThis('testing query on temp table: ['.$tempTableTestQuery_idx.']');
$r4 = $db->query($tempTableTestQuery_idx, false, "Preflight Failed for: {$query}");
}
$mysqlError = mysql_error(); // empty on no-errors
if(!empty($mysqlError)) {
logThis('*** ERROR: query failed: '.$mysqlError);
$error = getFormattedError($mysqlError, $query);
}
// clean up moved to end of preflight
break;
case 'mssql':
logThis('mssql found: skipping test query - ['.$query.']');
break;
case 'oci8':
logThis('Oracle found: skipping test query - ['.$query.']');
break;
} // end switch()
} else {
logThis($table . ' is a new table');
}
logThis('verification done.');
return $error;
}
/**
* Tests an CREATE TABLE query
* @param string table The table name to get DDL
* @param string dbType MySQL, MSSQL, etc.
* @param string query The query to test.
* @return string Non-empty if error found
*/
function testQueryCreate($table, $dbType, $query, &$newTables) {
logThis('verifying CREATE statement...');
global $db;
if(empty($db)) {
$db = &DBManagerFactory::getInstance();
}
$error = '';
switch($dbType) {
case 'mysql':
// rewrite DDL with _temp name
logThis('testing query: ['.$query.']');
$tempTableQuery = str_replace("CREATE TABLE `{$table}`", "CREATE TABLE `{$table}__uw_temp`", $query);
if(isRunningAgainstTrueTable($tempTableQuery)) {
$error = getFormattedError('Could not use a temp table to test query!', $query);
return $error;
}
$r4 = $db->query($tempTableQuery, false, "Preflight Failed for: {$query}");
$error = mysql_error(); // empty on no-errors
if(!empty($error)) {
logThis('*** ERROR: query failed.');
$error = getFormattedError($error, $query);
}
// check if table exists
logThis('testing for table: '.$table);
$q1 = "DESC `{$table}`";
$r1 = $db->query($q1);
$mysqlError = mysql_error();
if(empty($mysqlError)) {
logThis('*** ERROR: table already exists!: '.$table);
$error = getFormattedError('table exists', $query);
}
else {
logThis('NEW TABLE: '.$query);
$newTables[] = $table;
}
break;
case 'mssql':
logThis('mssql found: skipping test query - ['.$query.']');
break;
case 'oci8':
logThis('Oracle found: skipping test query - ['.$query.']');
break;
}
return $error;
}
/**
* Tests an DELETE FROM query
* @param string table The table name to get DDL
* @param string dbType MySQL, MSSQL, etc.
* @param string query The query to test.
* @return string Non-empty if error found
*/
function testQueryDelete($table, $dbType, $query) {
logThis('verifying DELETE statements');
global $db;
if(empty($db)) {
$db = &DBManagerFactory::getInstance();
}
$error = '';
switch($dbType) {
case 'mysql':
// get DDL
logThis('creating temp table...');
$q = "SHOW CREATE TABLE {$table}";
$r = $db->query($q);
$a = $db->fetchByAssoc($r);
// rewrite DDL with _temp name
$cleanQuery = cleanQuery($a['Create Table']);
$tempTableQuery = str_replace("CREATE TABLE `{$table}`", "CREATE TABLE `{$table}__uw_temp`", $cleanQuery);
$r2 = $db->query($tempTableQuery);
// get sample data into the temp table to test for data/constraint conflicts
logThis('inserting temp dataset...');
$q3 = "INSERT INTO `{$table}__uw_temp` SELECT * FROM `{$table}` LIMIT 10";
$r3 = $db->query($q3);
// test the query on the test table
logThis('testing query: ['.$query.']');
$tempTableTestQuery = str_replace("DELETE FROM `{$table}`", "DELETE FROM `{$table}__uw_temp`", $query);
if(isRunningAgainstTrueTable($tempTableTestQuery)) {
$error = getFormattedError('Could not use a temp table to test query!', $tempTableTestQuery);
return $error;
}
$r4 = $db->query($tempTableTestQuery, false, "Preflight Failed for: {$query}");
$error = mysql_error(); // empty on no-errors
if(!empty($error)) {
logThis('*** ERROR: query failed.');
$error = getFormattedError($error, $query);
}
break;
case 'mssql':
logThis('mssql found: skipping test query - ['.$query.']');
break;
case 'oci8':
logThis('Oracle found: skipping test query - ['.$query.']');
break;
}
logThis('verification done.');
return $error;
}
/**
* Tests a DROP TABLE query
*
*/
function testQueryDrop($table, $dbType, $query) {
logThis('verifying DROP TABLE statement');
global $db;
if(empty($db)) {
$db = &DBManagerFactory::getInstance();
}
$error = '';
switch($dbType) {
case 'mysql':
// get DDL
logThis('creating temp table...');
$q = "SHOW CREATE TABLE {$table}";
$r = $db->query($q);
$a = $db->fetchByAssoc($r);
// rewrite DDL with _temp name
$cleanQuery = cleanQuery($a['Create Table']);
$tempTableQuery = str_replace("CREATE TABLE `{$table}`", "CREATE TABLE `{$table}__uw_temp`", $cleanQuery);
$r2 = $db->query($tempTableQuery);
// get sample data into the temp table to test for data/constraint conflicts
logThis('inserting temp dataset...');
$query = stripQuotesUW($query, $table);
$q3 = "INSERT INTO `{$table}__uw_temp` SELECT * FROM `{$table}` LIMIT 10";
$r3 = $db->query($q3);
// test the query on the test table
logThis('testing query: ['.$query.']');
$tempTableTestQuery = str_replace("DROP TABLE `{$table}`", "DROP TABLE `{$table}__uw_temp`", $query);
// make sure the test query is running against a temp table
if(isRunningAgainstTrueTable($tempTableTestQuery)) {
$error = getFormattedError('Could not use a temp table to test query!', $tempTableTestQuery);
return $error;
}
$r4 = $db->query($tempTableTestQuery, false, "Preflight Failed for: {$query}");
$error = mysql_error(); // empty on no-errors
if(!empty($error)) {
logThis('*** ERROR: query failed.');
$error = getFormattedError($error, $query);
}
break;
case 'mssql':
logThis('mssql found: skipping test query - ['.$query.']');
break;
case 'oci8':
logThis('Oracle found: skipping test query - ['.$query.']');
break;
}
logThis('verification done.');
return $error;
}
/**
* Tests an INSERT INTO query
* @param string table The table name to get DDL
* @param string dbType MySQL, MSSQL, etc.
* @param string query The query to test.
* @return string Non-empty if error found
*/
function testQueryInsert($table, $dbType, $query) {
logThis('verifying INSERT statement...');
global $db;
if(empty($db)) {
$db = &DBManagerFactory::getInstance();
}
$error = '';
switch($dbType) {
case 'mysql':
// get DDL
$q = "SHOW CREATE TABLE {$table}";
$r = $db->query($q);
$a = $db->fetchByAssoc($r);
// rewrite DDL with _temp name
$cleanQuery = cleanQuery($a['Create Table']);
$tempTableQuery = str_replace("CREATE TABLE `{$table}`", "CREATE TABLE `{$table}__uw_temp`", $cleanQuery);
$r2 = $db->query($tempTableQuery);
// test the query on the test table
logThis('testing query: ['.$query.']');
$tempTableTestQuery = str_replace("INSERT INTO `{$table}`", "INSERT INTO `{$table}__uw_temp`", $query);
// make sure the test query is running against a temp table
if(isRunningAgainstTrueTable($tempTableTestQuery)) {
$error = getFormattedError('Could not use a temp table to test query!', $tempTableTestQuery);
return $error;
}
$r4 = $db->query($tempTableTestQuery, false, "Preflight Failed for: {$query}");
$error = mysql_error(); // empty on no-errors
if(!empty($error)) {
logThis('*** ERROR: query failed.');
$error = getFormattedError($error, $query);
}
break;
case 'mssql':
logThis('mssql found: skipping test query - ['.$query.']');
break;
case 'oci8':
logThis('Oracle found: skipping test query - ['.$query.']');
break;
}
logThis('verification done.');
return $error;
}
/**
* Tests an UPDATE TABLE query
* @param string table The table name to get DDL
* @param string dbType MySQL, MSSQL, etc.
* @param string query The query to test.
* @return string Non-empty if error found
*/
function testQueryUpdate($table, $dbType, $query) {
logThis('verifying UPDATE TABLE statement...');
global $db;
if(empty($db)) {
$db = &DBManagerFactory::getInstance();
}
$error = '';
switch($dbType) {
case 'mysql':
// get DDL
$q = "SHOW CREATE TABLE {$table}";
$r = $db->query($q);
$a = $db->fetchByAssoc($r);
// rewrite DDL with _temp name
$cleanQuery = cleanQuery($a['Create Table']);
$tempTableQuery = str_replace("CREATE TABLE `{$table}`", "CREATE TABLE `{$table}__uw_temp`", $cleanQuery);
$r2 = $db->query($tempTableQuery);
// get sample data into the temp table to test for data/constraint conflicts
logThis('inserting temp dataset...');
$q3 = "INSERT INTO `{$table}__uw_temp` SELECT * FROM `{$table}` LIMIT 10";
$r3 = $db->query($q3, false, "Preflight Failed for: {$query}");
// test the query on the test table
logThis('testing query: ['.$query.']');
$tempTableTestQuery = str_replace("UPDATE `{$table}`", "UPDATE `{$table}__uw_temp`", $query);
// make sure the test query is running against a temp table
if(isRunningAgainstTrueTable($tempTableTestQuery)) {
$error = getFormattedError('Could not use a temp table to test query!', $tempTableTestQuery);
return $error;
}
$r4 = $db->query($tempTableTestQuery, false, "Preflight Failed for: {$query}");
$error = mysql_error(); // empty on no-errors
if(!empty($error)) {
logThis('*** ERROR: query failed.');
$error = getFormattedError($error, $query);
}
break;
case 'mssql':
break;
case 'oci8':
logThis('Oracle found: skipping test query - ['.$query.']');
break;
}
logThis('verification done.');
return $error;
}
/**
* strip queries of single and double quotes
*/
function stripQuotesUW($query, $table) {
$queryStrip = '';
$start = strpos($query, $table);
if(substr($query, ($start - 1), 1) != ' ') {
$queryStrip = substr($query, 0, ($start-2));
$queryStrip .= " {$table} ";
$queryStrip .= substr($query, ($start + strlen($table) + 2), strlen($query));
}
return (empty($queryStrip)) ? $query : $queryStrip;
}
/**
* ensures that a __UW_TEMP table test SQL is running against a temp table, not the real thing
* @param string query
* @return bool false if it is a good query
*/
function isRunningAgainstTrueTable($query) {
$query = strtoupper($query);
if(strpos($query, '__UW_TEMP') === false) {
logThis('***ERROR: test query is NOT running against a temp table!!!! -> '.$query);
return true;
}
return false;
}
/**
* cleans up temp tables created during schema test phase
*/
function testCleanUp($dbType) {
logThis('Cleaning up temporary tables...');
global $db;
if(empty($db)) {
$db = &DBManagerFactory::getInstance();
}
$error = '';
switch($dbType) {
case 'mysql':
$q = 'SHOW TABLES LIKE "%__uw_temp"';
$r = $db->query($q, false, "Preflight Failed for: {$q}");
// using raw mysql_command to use integer index
while($a = $db->fetchByAssoc($r)) {
logThis('Dropping table: '.$a[0]);
$qClean = "DROP TABLE {$a[0]}";
$rClean = $db->query($qClean);
}
break;
case 'mssql':
break;
case 'oci8':
break;
}
logThis('Done cleaning up temp tables.');
return $error;
}
function getFormattedError($error, $query) {
$error = "".$error;
$error .= "::{$query}
";
return $error;
}
/**
* parses a query finding the table name
* @param string query The query
* @return string table The table
*/
function getTableFromQuery($query) {
$standardQueries = array('ALTER TABLE', 'DROP TABLE', 'CREATE TABLE', 'INSERT INTO', 'UPDATE', 'DELETE FROM');
$query = preg_replace("/[^A-Za-z0-9\_\s]/", "", $query);
$query = trim(str_replace($standardQueries, '', $query));
$firstSpc = strpos($query, " ");
$end = ($firstSpc > 0) ? $firstSpc : strlen($query);
$table = substr($query, 0, $end);
return $table;
}
//prelicense check
function preLicenseCheck() {
require_once('modules/UpgradeWizard/uw_files.php');
global $sugar_config;
global $mod_strings;
global $sugar_version;
if(!isset($sugar_version) || empty($sugar_version)) {
require_once('./sugar_version.php');
}
if(!isset($_SESSION['unzip_dir']) || empty($_SESSION['unzip_dir'])) {
logThis('unzipping files in upgrade archive...');
$errors = array();
$base_upgrade_dir = $sugar_config['upload_dir'] . "/upgrades";
$base_tmp_upgrade_dir = "$base_upgrade_dir/temp";
$unzip_dir = '';
//also come up with mechanism to read from upgrade-progress file
if(!isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !is_file($_SESSION['install_file'])) {
/*
if ($handle = opendir(clean_path($sugar_config['upload_dir']))) {
while (false !== ($file = readdir($handle))) {
if($file !="." && $file !="..") {
$far = explode(".",$file);
if($far[sizeof($far)-1] == 'zip') {
echo $sugar_config['upload_dir'].'/'.$file;
$_SESSION['install_file'] = $sugar_config['upload_dir'].'/'.$file;
}
}
}
}
*/
if (file_exists(clean_path($base_tmp_upgrade_dir)) && $handle = opendir(clean_path($base_tmp_upgrade_dir))) {
while (false !== ($file = readdir($handle))) {
if($file !="." && $file !="..") {
//echo $base_tmp_upgrade_dir."/".$file.'';
if(is_file($base_tmp_upgrade_dir."/".$file."/manifest.php")){
require_once($base_tmp_upgrade_dir."/".$file."/manifest.php");
$package_name= $manifest['copy_files']['from_dir'];
//echo file_exists($base_tmp_upgrade_dir."/".$file."/".$package_name).'';
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")){
//echo 'Yeah this the directory '. $base_tmp_upgrade_dir."/".$file;
$unzip_dir = $base_tmp_upgrade_dir."/".$file;
if(file_exists($sugar_config['upload_dir'].'/upgrades/patch/'.$package_name.'.zip')){
$_SESSION['install_file'] = $sugar_config['upload_dir'].'/upgrades/patch/'.$package_name.'.zip';
break;
}
}
}
}
}
}
}
if(!isset($_SESSION['install_file']) || empty($_SESSION['install_file'])){
unlinkTempFiles();
resetUwSession();
echo 'Upload File not found so redirecting to Upgrade Start ';
$redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
echo '