PageRenderTime 70ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 1ms

/modules/UpgradeWizard/uw_utils.php

https://bitbucket.org/cviolette/sugarcrm
PHP | 4475 lines | 3282 code | 539 blank | 654 comment | 836 complexity | 9837434d4d6640181bbc0908b18d8abc MD5 | raw file
Possible License(s): LGPL-2.1, MPL-2.0-no-copyleft-exception, BSD-3-Clause
  1. <?php
  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-2012 SugarCRM Inc.
  6. *
  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.
  13. *
  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
  17. * details.
  18. *
  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
  22. * 02110-1301 USA.
  23. *
  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.
  26. *
  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.
  30. *
  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. ********************************************************************************/
  37. /**
  38. * Helper function for upgrade - get path from upload:// name
  39. * @param string $path
  40. * return string
  41. */
  42. function getUploadRelativeName($path)
  43. {
  44. if(class_exists('UploadFile')) {
  45. return UploadFile::realpath($path);
  46. }
  47. if(substr($path, 0, 9) == "upload://") {
  48. $path = rtrim($GLOBALS['sugar_config']['upload_dir'], "/\\")."/".substr($path, 9);
  49. }
  50. return $path;
  51. }
  52. /**
  53. * Backs-up files that are targeted for patch/upgrade to a restore directory
  54. * @param string rest_dir Full path to the directory containing the original, replaced files.
  55. * @param string install_file Full path to the uploaded patch/upgrade zip file
  56. * @param string unzip_dir Full path to the unzipped files in a temporary directory
  57. * @param string zip_from_dir Name of directory that the unzipped files containing the actuall replacement files
  58. * @param array errors Collection of errors to be displayed at end of process
  59. * @param string path Optional full path to the log file.
  60. * @return array errors
  61. */
  62. function commitMakeBackupFiles($rest_dir, $install_file, $unzip_dir, $zip_from_dir, $errors, $path='') {
  63. global $mod_strings;
  64. // create restore file directory
  65. sugar_mkdir($rest_dir, 0775, true);
  66. if(file_exists($rest_dir) && is_dir($rest_dir)){
  67. logThis('backing up files to be overwritten...', $path);
  68. $newFiles = findAllFiles(clean_path($unzip_dir . '/' . $zip_from_dir), array());
  69. // keep this around for canceling
  70. $_SESSION['uw_restore_dir'] = getUploadRelativeName($rest_dir);
  71. foreach ($newFiles as $file) {
  72. if (strpos($file, 'md5'))
  73. continue;
  74. // get name of current file to place in restore directory
  75. $cleanFile = str_replace(clean_path($unzip_dir . '/' . $zip_from_dir), '', $file);
  76. // make sure the directory exists
  77. $cleanDir = $rest_dir . '/' . dirname($cleanFile);
  78. sugar_mkdir($cleanDir, 0775, true);
  79. $oldFile = clean_path(getcwd() . '/' . $cleanFile);
  80. // only copy restore files for replacements - ignore new files from patch
  81. if (is_file($oldFile)) {
  82. if (is_writable($rest_dir)) {
  83. logThis('Backing up file: ' . $oldFile, $path);
  84. if (!copy($oldFile, $rest_dir . '/' . $cleanFile)) {
  85. logThis('*** ERROR: could not backup file: ' . $oldFile, $path);
  86. $errors[] = "{$mod_strings['LBL_UW_BACKUP']}::{$mod_strings['ERR_UW_FILE_NOT_COPIED']}: {$oldFile}";
  87. } else {
  88. $backupFilesExist = true;
  89. }
  90. } else {
  91. logThis('*** ERROR: directory not writable: ' . $rest_dir, $path);
  92. $errors[] = "{$mod_strings['LBL_UW_BACKUP']}::{$mod_strings['ERR_UW_DIR_NOT_WRITABLE']}: {$oldFile}";
  93. }
  94. }
  95. }
  96. }
  97. logThis('file backup done.', $path);
  98. return $errors;
  99. }
  100. /**
  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
  104. * extension.
  105. * @param string path Optional full path to alternate upgradeWizard log file.
  106. * @return array Two element array containing to $copiedFiles and $skippedFiles.
  107. */
  108. function commitCopyNewFiles($unzip_dir, $zip_from_dir, $path='') {
  109. logThis('Starting file copy process...', $path);
  110. global $sugar_version;
  111. $backwardModules='';
  112. if(substr($sugar_version,0,1) >= 5){
  113. $modules = getAllModules();
  114. $backwardModules = array();
  115. foreach($modules as $mod){
  116. if(is_dir(clean_path(getcwd().'/modules/'.$mod.'/.500'))){
  117. $files = array();
  118. $files= findAllFiles(clean_path(getcwd().'/modules/'.$mod.'/.500'),$files);
  119. if(sizeof($files) >0){
  120. //backward compatibility is on
  121. $backwardModules[] = $mod;
  122. }
  123. }
  124. }
  125. }
  126. $newFiles = findAllFiles(clean_path($unzip_dir . '/' . $zip_from_dir), array());
  127. $zipPath = clean_path($unzip_dir . '/' . $zip_from_dir);
  128. // handle special do-not-overwrite conditions
  129. $doNotOverwrite = array();
  130. $doNotOverwrite[] = '__stub';
  131. if(isset($_REQUEST['overwrite_files_serial'])) {
  132. $doNotOverwrite = explode('::', $_REQUEST['overwrite_files_serial']);
  133. }
  134. $copiedFiles = array();
  135. $skippedFiles = array();
  136. foreach($newFiles as $file) {
  137. $cleanFile = str_replace($zipPath, '', $file);
  138. $srcFile = $zipPath . $cleanFile;
  139. $targetFile = clean_path(getcwd() . '/' . $cleanFile);
  140. if($backwardModules != null && sizeof($backwardModules) >0){
  141. foreach($backwardModules as $mod){
  142. $splitPath = explode('/',trim($cleanFile));
  143. if('modules' == trim($splitPath[1]) && $mod == trim($splitPath[2])){
  144. $cleanFile = str_replace('/modules/'.$mod, '/modules/'.$mod.'/.500', $cleanFile);
  145. $targetFile = clean_path(getcwd() . '/' . $cleanFile);
  146. }
  147. }
  148. }
  149. if(!is_dir(dirname($targetFile))) {
  150. mkdir_recursive(dirname($targetFile)); // make sure the directory exists
  151. }
  152. if((!file_exists($targetFile)) || /* brand new file */
  153. (!in_array($targetFile, $doNotOverwrite)) /* manual diff file */
  154. ) {
  155. // handle sugar_version.php
  156. if(strpos($targetFile, 'sugar_version.php') !== false && !preg_match('/\/portal\/sugar_version\.php$/i', $targetFile)) {
  157. logThis('Skipping "sugar_version.php" - file copy will occur at end of successful upgrade', $path);
  158. $_SESSION['sugar_version_file'] = $srcFile;
  159. continue;
  160. }
  161. //logThis('Copying file to destination: ' . $targetFile, $path);
  162. if(!copy($srcFile, $targetFile)) {
  163. logThis('*** ERROR: could not copy file: ' . $targetFile, $path);
  164. } else {
  165. $copiedFiles[] = $targetFile;
  166. }
  167. } else {
  168. //logThis('Skipping file: ' . $targetFile, $path);
  169. $skippedFiles[] = $targetFile;
  170. }
  171. }
  172. logThis('File copy done.', $path);
  173. $ret = array();
  174. $ret['copiedFiles'] = $copiedFiles;
  175. $ret['skippedFiles'] = $skippedFiles;
  176. return $ret;
  177. }
  178. //On cancel put back the copied files from 500 to 451 state
  179. function copyFilesOnCancel($step){
  180. //place hoder for cancel action
  181. }
  182. function removeFileFromPath($file,$path, $deleteNot=array()){
  183. $removed = 0;
  184. $cur = $path . '/' . $file;
  185. if(file_exists($cur)){
  186. $del = true;
  187. foreach($deleteNot as $dn){
  188. if($cur == $dn){
  189. $del = false;
  190. }
  191. }
  192. if($del){
  193. unlink($cur);
  194. $removed++;
  195. }
  196. }
  197. if(!file_exists($path))return $removed;
  198. $d = dir($path);
  199. while(false !== ($e = $d->read())){ // Fixed bug. !== is required to literally match the type and value of false, so that a filename that could evaluate and cast to false, ie "false" or "0", still allows the while loop to continue. From example at http://www.php.net/manual/en/function.dir.php
  200. $next = $path . '/'. $e;
  201. if(substr($e, 0, 1) != '.' && is_dir($next)){
  202. $removed += removeFileFromPath($file, $next, $deleteNot);
  203. }
  204. }
  205. $d->close(); // from example at http://www.php.net/manual/en/function.dir.php
  206. return $removed;
  207. }
  208. /**
  209. * This function copies/overwrites between directories
  210. *
  211. * @param string the directory name to remove
  212. * @param boolean whether to just empty the given directory, without deleting the given directory.
  213. * @return boolean True/False whether the directory was deleted.
  214. */
  215. function copyRecursiveBetweenDirectories($from,$to){
  216. if(file_exists($from)){
  217. $modifiedFiles = array();
  218. $modifiedFiles = findAllFiles(clean_path($from), $modifiedFiles);
  219. $cwd = clean_path(getcwd());
  220. foreach($modifiedFiles as $file) {
  221. $srcFile = clean_path($file);
  222. if (strpos($srcFile,".svn") === false) {
  223. $targetFile = str_replace($from, $to, $srcFile);
  224. if(!is_dir(dirname($targetFile))) {
  225. mkdir_recursive(dirname($targetFile)); // make sure the directory exists
  226. }
  227. // handle sugar_version.php
  228. if(strpos($targetFile, 'sugar_version.php') !== false && !preg_match('/\/portal\/sugar_version\.php$/i', $targetFile)) {
  229. logThis('Skipping "sugar_version.php" - file copy will occur at end of successful upgrade', $targetFile);
  230. $_SESSION['sugar_version_file'] = $srcFile;
  231. continue;
  232. }
  233. if(!copy($srcFile, $targetFile)) {
  234. logThis("*** ERROR: could not copy file $srcFile to $targetFile");
  235. }
  236. }
  237. }
  238. }
  239. }
  240. function deleteDirectory($dirname,$only_empty=false) {
  241. if (!is_dir($dirname))
  242. return false;
  243. $dscan = array(realpath($dirname));
  244. $darr = array();
  245. while (!empty($dscan)) {
  246. $dcur = array_pop($dscan);
  247. $darr[] = $dcur;
  248. if ($d=opendir($dcur)) {
  249. while ($f=readdir($d)) {
  250. if ($f=='.' || $f=='..')
  251. continue;
  252. $f=$dcur.'/'.$f;
  253. if (is_dir($f))
  254. $dscan[] = $f;
  255. else
  256. unlink($f);
  257. }
  258. closedir($d);
  259. }
  260. }
  261. $i_until = ($only_empty)? 1 : 0;
  262. for ($i=count($darr)-1; $i>=$i_until; $i--) {
  263. if (rmdir($darr[$i]))
  264. logThis('Success :Copying file to destination: ' . $darr[$i]);
  265. else
  266. logThis('Copy problem:Copying file to destination: ' . $darr[$i]);
  267. }
  268. return (($only_empty)? (count(scandir)<=2) : (!is_dir($dirname)));
  269. }
  270. /**
  271. * Get all the customized modules. Compare the file md5s with the base md5s
  272. * If a file has been modified then put the module in the list of customized
  273. * modules. Show the list in the preflight check UI.
  274. */
  275. function deleteAndOverWriteSelectedFiles($unzip_dir, $zip_from_dir,$delete_dirs){
  276. if($delete_dirs != null){
  277. foreach($delete_dirs as $del_dir){
  278. deleteDirectory($del_dir);
  279. $newFiles = findAllFiles(clean_path($unzip_dir . '/' . $zip_from_dir.'/'.$del_dir), array());
  280. $zipPath = clean_path($unzip_dir . '/' . $zip_from_dir.'/'.$del_dir);
  281. $copiedFiles = array();
  282. $skippedFiles = array();
  283. foreach($newFiles as $file) {
  284. $cleanFile = str_replace($zipPath, '', $file);
  285. $srcFile = $zipPath . $cleanFile;
  286. $targetFile = clean_path(getcwd() . '/' . $cleanFile);
  287. if(!is_dir(dirname($targetFile))) {
  288. mkdir_recursive(dirname($targetFile)); // make sure the directory exists
  289. }
  290. if(!file_exists($targetFile)){
  291. // handle sugar_version.php
  292. if(strpos($targetFile, 'sugar_version.php') !== false) {
  293. logThis('Skipping sugar_version.php - file copy will occur at end of successful upgrade');
  294. $_SESSION['sugar_version_file'] = $srcFile;
  295. continue;
  296. }
  297. //logThis('Copying file to destination: ' . $targetFile);
  298. if(!copy($srcFile, $targetFile)) {
  299. logThis('*** ERROR: could not copy file: ' . $targetFile);
  300. } else {
  301. $copiedFiles[] = $targetFile;
  302. }
  303. } else {
  304. //logThis('Skipping file: ' . $targetFile);
  305. $skippedFiles[] = $targetFile;
  306. }
  307. }
  308. }
  309. }
  310. $ret = array();
  311. $ret['copiedFiles'] = $copiedFiles;
  312. $ret['skippedFiles'] = $skippedFiles;
  313. return $ret;
  314. }
  315. //Default is empty the directory. For removing set it to false
  316. // to use this function to totally remove a directory, write:
  317. // recursive_remove_directory('path/to/directory/to/delete',FALSE);
  318. // to use this function to empty a directory, write:
  319. // recursive_remove_directory('path/to/full_directory');
  320. function recursive_empty_or_remove_directory($directory, $exclude_dirs=null,$exclude_files=null,$empty=TRUE)
  321. {
  322. // if the path has a slash at the end we remove it here
  323. if(substr($directory,-1) == '/')
  324. {
  325. $directory = substr($directory,0,-1);
  326. }
  327. // if the path is not valid or is not a directory ...
  328. if(!file_exists($directory) || !is_dir($directory))
  329. {
  330. // ... we return false and exit the function
  331. return FALSE;
  332. // ... if the path is not readable
  333. }elseif(!is_readable($directory))
  334. {
  335. // ... we return false and exit the function
  336. return FALSE;
  337. // ... else if the path is readable
  338. }else{
  339. // we open the directory
  340. $handle = opendir($directory);
  341. // and scan through the items inside
  342. while (FALSE !== ($item = readdir($handle)))
  343. {
  344. // if the filepointer is not the current directory
  345. // or the parent directory
  346. if($item != '.' && $item != '..')
  347. {
  348. // we build the new path to delete
  349. $path = $directory.'/'.$item;
  350. // if the new path is a directory
  351. //add another check if the dir is in the list to exclude delete
  352. if(is_dir($path) && $exclude_dirs != null && in_array($path,$exclude_dirs)){
  353. //do nothing
  354. }
  355. else if(is_dir($path))
  356. {
  357. // we call this function with the new path
  358. recursive_empty_or_remove_directory($path);
  359. }
  360. // if the new path is a file
  361. else{
  362. // we remove the file
  363. if($exclude_files != null && in_array($path,$exclude_files)){
  364. //do nothing
  365. }
  366. else{
  367. unlink($path);
  368. }
  369. }
  370. }
  371. }
  372. // close the directory
  373. closedir($handle);
  374. // if the option to empty is not set to true
  375. if($empty == FALSE)
  376. {
  377. // try to delete the now empty directory
  378. if(!rmdir($directory))
  379. {
  380. // return false if not possible
  381. return FALSE;
  382. }
  383. }
  384. // return success
  385. return TRUE;
  386. }
  387. }
  388. // ------------------------------------------------------------
  389. function getAllCustomizedModules() {
  390. require_once('files.md5');
  391. $return_array = array();
  392. $modules = getAllModules();
  393. foreach($modules as $mod) {
  394. //find all files in each module if the files have been modified
  395. //as compared to the base version then add the module to the
  396. //customized modules array
  397. $modFiles = findAllFiles(clean_path(getcwd())."/modules/$mod", array());
  398. foreach($modFiles as $file){
  399. $fileContents = file_get_contents($file);
  400. $file = str_replace(clean_path(getcwd()),'',$file);
  401. if($md5_string['./' . $file]){
  402. if(md5($fileContents) != $md5_string['./' . $file]) {
  403. //A file has been customized in the module. Put the module into the
  404. // customized modules array.
  405. echo 'Changed File'.$file;
  406. $return_array[$mod];
  407. break;
  408. }
  409. }
  410. else{
  411. // This is a new file in user's version and indicates that module has been
  412. //customized. Put the module in the customized array.
  413. echo 'New File'.$file;
  414. $return_array[$mod];
  415. break;
  416. }
  417. }
  418. } //foreach
  419. return $return_array;
  420. }
  421. /**
  422. * Array of all Modules in the version bein upgraded
  423. * This method returns an Array of all modules
  424. * @return $modules Array of modules.
  425. */
  426. function getAllModules() {
  427. $modules = array();
  428. $d = dir('modules');
  429. while($e = $d->read()){
  430. if(substr($e, 0, 1) == '.' || !is_dir('modules/' . $e))continue;
  431. $modules[] = $e;
  432. }
  433. return $modules;
  434. }
  435. //Remove files with the smae md5
  436. function removeMd5MatchingFiles($deleteNot=array()){
  437. $md5_string = array();
  438. if(file_exists(clean_path(getcwd().'/files.md5'))){
  439. require(clean_path(getcwd().'/files.md5'));
  440. }
  441. $modulesAll = getAllModules();
  442. foreach($modulesAll as $mod){
  443. $allModFiles = array();
  444. if(is_dir('modules/'.$mod)){
  445. $allModFiles = findAllFiles('modules/'.$mod,$allModFiles);
  446. foreach($allModFiles as $file){
  447. if(file_exists($file) && !in_array(basename($file),$deleteNot)){
  448. if(isset($md5_string['./'.$file])) {
  449. $fileContents = file_get_contents($file);
  450. if(md5($fileContents) == $md5_string['./'.$file]) {
  451. unlink($file);
  452. }
  453. }
  454. }
  455. }
  456. }
  457. }
  458. }
  459. /**
  460. * Handles requirements for creating reminder Tasks and Emails
  461. * @param array skippedFiles Array of files that were not overwriten and must be manually mereged.
  462. * @param string path Optional full path to alternate upgradeWizard log.
  463. */
  464. function commitHandleReminders($skippedFiles, $path='') {
  465. global $mod_strings;
  466. global $current_user;
  467. if(empty($mod_strings))
  468. $mod_strings = return_module_language('en_us', 'UpgradeWizard');
  469. if(empty($current_user->id)) {
  470. $current_user->getSystemUser();
  471. }
  472. if(count($skippedFiles) > 0) {
  473. $desc = $mod_strings['LBL_UW_COMMIT_ADD_TASK_OVERVIEW'] . "\n\n";
  474. $desc .= $mod_strings['LBL_UW_COMMIT_ADD_TASK_DESC_1'];
  475. $desc .= $_SESSION['uw_restore_dir'] . "\n\n";
  476. $desc .= $mod_strings['LBL_UW_COMMIT_ADD_TASK_DESC_2'] . "\n\n";
  477. foreach($skippedFiles as $file) {
  478. $desc .= $file . "\n";
  479. }
  480. //MFH #13468
  481. /// Not using new TimeDate stuff here because it needs to be compatible with 6.0
  482. $nowDate = gmdate('Y-m-d');
  483. $nowTime = gmdate('H:i:s');
  484. $nowDateTime = $nowDate . ' ' . $nowTime;
  485. if($_REQUEST['addTaskReminder'] == 'remind') {
  486. logThis('Adding Task for admin for manual merge.', $path);
  487. $task = new Task();
  488. $task->name = $mod_strings['LBL_UW_COMMIT_ADD_TASK_NAME'];
  489. $task->description = $desc;
  490. $task->date_due = $nowDate;
  491. $task->time_due = $nowTime;
  492. $task->priority = 'High';
  493. $task->status = 'Not Started';
  494. $task->assigned_user_id = $current_user->id;
  495. $task->created_by = $current_user->id;
  496. $task->date_entered = $nowDateTime;
  497. $task->date_modified = $nowDateTime;
  498. $task->save();
  499. }
  500. if($_REQUEST['addEmailReminder'] == 'remind') {
  501. logThis('Sending Reminder for admin for manual merge.', $path);
  502. $email = new Email();
  503. $email->assigned_user_id = $current_user->id;
  504. $email->name = $mod_strings['LBL_UW_COMMIT_ADD_TASK_NAME'];
  505. $email->description = $desc;
  506. $email->description_html = nl2br($desc);
  507. $email->from_name = $current_user->full_name;
  508. $email->from_addr = $current_user->email1;
  509. $email->to_addrs_arr = $email->parse_addrs($current_user->email1, '', '', '');
  510. $email->cc_addrs_arr = array();
  511. $email->bcc_addrs_arr = array();
  512. $email->date_entered = $nowDateTime;
  513. $email->date_modified = $nowDateTime;
  514. $email->send();
  515. $email->save();
  516. }
  517. }
  518. }
  519. function deleteCache(){
  520. //Clean modules from cache
  521. $cachedir = sugar_cached('modules');
  522. if(is_dir($cachedir)){
  523. $allModFiles = array();
  524. $allModFiles = findAllFiles($cachedir,$allModFiles, true);
  525. foreach($allModFiles as $file) {
  526. if(file_exists($file)) {
  527. if(is_dir($file)) {
  528. rmdir_recursive($file);
  529. } else {
  530. unlink($file);
  531. }
  532. }
  533. }
  534. }
  535. //Clean jsLanguage from cache
  536. $cachedir = sugar_cached('jsLanguage');
  537. if(is_dir($cachedir)){
  538. $allModFiles = array();
  539. $allModFiles = findAllFiles($cachedir,$allModFiles);
  540. foreach($allModFiles as $file){
  541. if(file_exists($file)){
  542. unlink($file);
  543. }
  544. }
  545. }
  546. //Clean smarty from cache
  547. $cachedir = sugar_cached('smarty');
  548. if(is_dir($cachedir)){
  549. $allModFiles = array();
  550. $allModFiles = findAllFiles($cachedir,$allModFiles);
  551. foreach($allModFiles as $file){
  552. if(file_exists($file)){
  553. unlink($file);
  554. }
  555. }
  556. }
  557. //Rebuild dashlets cache
  558. require_once('include/Dashlets/DashletCacheBuilder.php');
  559. $dc = new DashletCacheBuilder();
  560. $dc->buildCache();
  561. }
  562. function deleteChance(){
  563. //Clean folder from cache
  564. if(is_dir('include/SugarObjects/templates/chance')){
  565. rmdir_recursive('include/SugarObjects/templates/chance');
  566. }
  567. if(is_dir('include/SugarObjects/templates/chance')){
  568. if(!isset($_SESSION['chance'])){
  569. $_SESSION['chance'] = '';
  570. }
  571. $_SESSION['chance'] = 'include/SugarObjects/templates/chance';
  572. //rename('include/SugarObjects/templates/chance','include/SugarObjects/templates/chance_removeit');
  573. }
  574. }
  575. /**
  576. * upgradeUWFiles
  577. * This function copies upgrade wizard files from new patch if that dir exists
  578. *
  579. * @param $file String path to uploaded zip file
  580. */
  581. function upgradeUWFiles($file) {
  582. $cacheUploadUpgradesTemp = mk_temp_dir(sugar_cached("upgrades/temp"));
  583. unzip($file, $cacheUploadUpgradesTemp);
  584. if(!file_exists("$cacheUploadUpgradesTemp/manifest.php")) {
  585. logThis("*** ERROR: no manifest file detected while bootstraping upgrade wizard files!");
  586. return;
  587. } else {
  588. include("$cacheUploadUpgradesTemp/manifest.php");
  589. }
  590. $allFiles = array();
  591. $from_dir = "{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}";
  592. // Localization
  593. if(file_exists("$from_dir/include/Localization/Localization.php")) {
  594. $allFiles[] = "$from_dir/include/Localization/Localization.php";
  595. }
  596. // upgradeWizard
  597. if(file_exists("$from_dir/modules/UpgradeWizard")) {
  598. $allFiles[] = findAllFiles("$from_dir/modules/UpgradeWizard", $allFiles);
  599. }
  600. // moduleInstaller
  601. if(file_exists("$from_dir/ModuleInstall")) {
  602. $allFiles[] = findAllFiles("$from_dir/ModuleInstall", $allFiles);
  603. }
  604. if(file_exists("$from_dir/include/javascript/yui")) {
  605. $allFiles[] = findAllFiles("$from_dir/include/javascript/yui", $allFiles);
  606. }
  607. if(file_exists("$from_dir/HandleAjaxCall.php")) {
  608. $allFiles[] = "$from_dir/HandleAjaxCall.php";
  609. }
  610. if(file_exists("$from_dir/include/SugarTheme")) {
  611. $allFiles[] = findAllFiles("$from_dir/include/SugarTheme", $allFiles);
  612. }
  613. if(file_exists("$from_dir/include/SugarCache")) {
  614. $allFiles[] = findAllFiles("$from_dir/include/SugarCache", $allFiles);
  615. }
  616. if(file_exists("$from_dir/include/utils/external_cache.php")) {
  617. $allFiles[] = "$from_dir/include/utils/external_cache.php";
  618. }
  619. if(file_exists("$from_dir/include/upload_file.php")) {
  620. $allFiles[] = "$from_dir/include/upload_file.php";
  621. }
  622. if(file_exists("$from_dir/include/file_utils.php")) {
  623. $allFiles[] = "$from_dir/include/file_utils.php";
  624. }
  625. if(file_exists("$from_dir/include/upload_file.php")) {
  626. $allFiles[] = "$from_dir/include/upload_file.php";
  627. }
  628. if(file_exists("$from_dir/include/utils/sugar_file_utils.php")) {
  629. $allFiles[] = "$from_dir/include/utils/sugar_file_utils.php";
  630. }
  631. // users
  632. if(file_exists("$from_dir/modules/Users")) {
  633. $allFiles[] = findAllFiles("$from_dir/modules/Users", $allFiles);
  634. }
  635. upgradeUWFilesCopy($allFiles, $from_dir);
  636. }
  637. /**
  638. * upgradeUWFilesCopy
  639. *
  640. * This function recursively copies files from the upgradeUWFiles Array
  641. * @see upgradeUWFiles
  642. *
  643. * @param array $allFiles Array of files to copy over after zip file has been uploaded
  644. * @param string $from_dir Source directory
  645. */
  646. function upgradeUWFilesCopy($allFiles, $from_dir)
  647. {
  648. foreach($allFiles as $file)
  649. {
  650. if(is_array($file))
  651. {
  652. upgradeUWFilesCopy($file, $from_dir);
  653. } else {
  654. $destFile = str_replace($from_dir."/", "", $file);
  655. if(!is_dir(dirname($destFile))) {
  656. mkdir_recursive(dirname($destFile)); // make sure the directory exists
  657. }
  658. if(stristr($file,'uw_main.tpl'))
  659. logThis('Skipping "'.$file.'" - file copy will during commit step.');
  660. else {
  661. logThis('updating UpgradeWizard code: '.$destFile);
  662. copy_recursive($file, $destFile);
  663. }
  664. }
  665. }
  666. }
  667. /**
  668. * gets valid patch file names that exist in upload/upgrade/patch/
  669. */
  670. function getValidPatchName($returnFull = true) {
  671. global $base_upgrade_dir;
  672. global $mod_strings;
  673. global $uh;
  674. global $sugar_version;
  675. global $sugar_config;
  676. $uh = new UpgradeHistory();
  677. list($base_upgrade_dir, $base_tmp_upgrade_dir) = getUWDirs();
  678. $return = array();
  679. // scan for new files (that are not installed)
  680. logThis('finding new files for upgrade');
  681. $upgrade_content = '';
  682. $upgrade_contents = findAllFiles($base_upgrade_dir, array(), false, 'zip');
  683. //other variations of zip file i.e. ZIP, zIp,zIP,Zip,ZIp,ZiP
  684. $ready = "<ul>\n";
  685. $ready .= "
  686. <table>
  687. <tr>
  688. <td></td>
  689. <td align=left>
  690. <b>{$mod_strings['LBL_ML_NAME']}</b>
  691. </td>
  692. <td align=left>
  693. <b>{$mod_strings['LBL_ML_TYPE']}</b>
  694. </td>
  695. <td align=left>
  696. <b>{$mod_strings['LBL_ML_VERSION']}</b>
  697. </td>
  698. <td align=left>
  699. <b>{$mod_strings['LBL_ML_PUBLISHED']}</b>
  700. </td>
  701. <td align=left>
  702. <b>{$mod_strings['LBL_ML_UNINSTALLABLE']}</b>
  703. </td>
  704. <td align=left>
  705. <b>{$mod_strings['LBL_ML_DESCRIPTION']}</b>
  706. </td>
  707. </tr>";
  708. $disabled = '';
  709. // assume old patches are there.
  710. $upgradeToVersion = array(); // fill with valid patches - we will only use the latest qualified found patch
  711. // cn: bug 10609 - notices for uninitialized variables
  712. $icon = '';
  713. $name = '';
  714. $type = '';
  715. $version = '';
  716. $published_date = '';
  717. $uninstallable = '';
  718. $description = '';
  719. $disabled = '';
  720. foreach($upgrade_contents as $upgrade_content) {
  721. if(!preg_match("#.*\.zip\$#i", $upgrade_content)) {
  722. continue;
  723. }
  724. $the_base = basename($upgrade_content);
  725. $the_md5 = md5_file($upgrade_content);
  726. $md5_matches = $uh->findByMd5($the_md5);
  727. /* 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.
  728. * Edge-case: manual upgrade with a FTP of a patch; UH table has no entry for it. Assume nothing. :( */
  729. if(0 == sizeof($md5_matches)) {
  730. $target_manifest = remove_file_extension( $upgrade_content ) . '-manifest.php';
  731. require_once($target_manifest);
  732. if(empty($manifest['version'])) {
  733. logThis("*** Potential error: patch found with no version [ {$upgrade_content} ]");
  734. continue;
  735. }
  736. if(!isset($manifest['type']) || $manifest['type'] != 'patch') {
  737. logThis("*** Potential error: patch found with either no 'type' or non-patch type [ {$upgrade_content} ]");
  738. continue;
  739. }
  740. $upgradeToVersion[$manifest['version']] = urlencode($upgrade_content);
  741. $name = empty($manifest['name']) ? $upgrade_content : $manifest['name'];
  742. $version = empty($manifest['version']) ? '' : $manifest['version'];
  743. $published_date = empty($manifest['published_date']) ? '' : $manifest['published_date'];
  744. $icon = '';
  745. $description = empty($manifest['description']) ? 'None' : $manifest['description'];
  746. $uninstallable = empty($manifest['is_uninstallable']) ? 'No' : 'Yes';
  747. $type = getUITextForType( $manifest['type'] );
  748. $manifest_type = $manifest['type'];
  749. if(empty($manifest['icon'])) {
  750. $icon = getImageForType( $manifest['type'] );
  751. } else {
  752. $path_parts = pathinfo( $manifest['icon'] );
  753. $icon = "<!--not_in_theme!--><img src=\"" . remove_file_extension( $upgrade_content ) . "-icon." . $path_parts['extension'] . "\">";
  754. }
  755. }
  756. }
  757. // cn: bug 10488 use the NEWEST upgrade/patch available when running upgrade wizard.
  758. ksort($upgradeToVersion);
  759. $upgradeToVersion = array_values($upgradeToVersion);
  760. $newest = array_pop($upgradeToVersion);
  761. $_SESSION['install_file'] = urldecode($newest); // in-case it was there from a prior.
  762. logThis("*** UW using [ {$_SESSION['install_file']} ] as source for patch files.");
  763. $cleanUpgradeContent = urlencode($_SESSION['install_file']);
  764. // cn: 10606 - cannot upload a patch file since this returned always.
  765. if(!empty($cleanUpgradeContent)) {
  766. $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";
  767. $ready .=<<<eoq
  768. <td>
  769. <form action="index.php" method="post">
  770. <input type="hidden" name="module" value="UpgradeWizard">
  771. <input type="hidden" name="action" value="index">
  772. <input type="hidden" name="step" value="{$_REQUEST['step']}">
  773. <input type="hidden" name="run" value="delete">
  774. <input type=hidden name="install_file" value="{$cleanUpgradeContent}" />
  775. <input type=submit value="{$mod_strings['LBL_BUTTON_DELETE']}" />
  776. </form>
  777. </td></table>
  778. eoq;
  779. $disabled = "DISABLED";
  780. }
  781. if(empty($cleanUpgradeContent)){
  782. $ready .= "<tr><td colspan='7'><i>None</i></td>\n";
  783. $ready .= "</table>\n";
  784. }
  785. $ready .= "<br></ul>\n";
  786. $return['ready'] = $ready;
  787. $return['disabled'] = $disabled;
  788. if($returnFull) {
  789. return $return;
  790. }
  791. }
  792. /**
  793. * finalizes upgrade by setting upgrade versions in DB (config table) and sugar_version.php
  794. * @return bool true on success
  795. */
  796. function updateVersions($version) {
  797. global $db;
  798. global $sugar_config;
  799. global $path;
  800. logThis('At updateVersions()... updating config table and sugar_version.php.', $path);
  801. // handle file copy
  802. if(isset($_SESSION['sugar_version_file']) && !empty($_SESSION['sugar_version_file'])) {
  803. if(!copy($_SESSION['sugar_version_file'], clean_path(getcwd().'/sugar_version.php'))) {
  804. logThis('*** ERROR: sugar_version.php could not be copied to destination! Cannot complete upgrade', $path);
  805. return false;
  806. } else {
  807. logThis('sugar_version.php successfully updated!', $path);
  808. }
  809. } else {
  810. logThis('*** ERROR: no sugar_version.php file location found! - cannot complete upgrade...', $path);
  811. return false;
  812. }
  813. $q1 = "DELETE FROM config WHERE category = 'info' AND name = 'sugar_version'";
  814. $q2 = "INSERT INTO config (category, name, value) VALUES ('info', 'sugar_version', '{$version}')";
  815. logThis('Deleting old DB version info from config table.', $path);
  816. $db->query($q1);
  817. logThis('Inserting updated version info into config table.', $path);
  818. $db->query($q2);
  819. logThis('updateVersions() complete.', $path);
  820. return true;
  821. }
  822. /**
  823. * gets a module's lang pack - does not need to be a SugarModule
  824. * @param lang string Language
  825. * @param module string Path to language folder
  826. * @return array mod_strings
  827. */
  828. function getModuleLanguagePack($lang, $module) {
  829. $mod_strings = array();
  830. if(!empty($lang) && !empty($module)) {
  831. $langPack = clean_path(getcwd().'/'.$module.'/language/'.$lang.'.lang.php');
  832. $langPackEn = clean_path(getcwd().'/'.$module.'/language/en_us.lang.php');
  833. if (file_exists($langPack))
  834. {
  835. include($langPack);
  836. }
  837. elseif (file_exists($langPackEn))
  838. {
  839. include($langPackEn);
  840. }
  841. }
  842. return $mod_strings;
  843. }
  844. /**
  845. * checks system compliance for 4.5+ codebase
  846. * @return array Mixed values
  847. */
  848. function checkSystemCompliance() {
  849. global $sugar_config;
  850. global $current_language;
  851. global $db;
  852. global $mod_strings;
  853. global $app_strings;
  854. if(!defined('SUGARCRM_MIN_MEM')) {
  855. define('SUGARCRM_MIN_MEM', 40);
  856. }
  857. $installer_mod_strings = getModuleLanguagePack($current_language, './install');
  858. $ret = array();
  859. $ret['error_found'] = false;
  860. // PHP version
  861. $php_version = constant('PHP_VERSION');
  862. $check_php_version_result = check_php_version($php_version);
  863. switch($check_php_version_result) {
  864. case -1:
  865. $ret['phpVersion'] = "<b><span class=stop>{$installer_mod_strings['ERR_CHECKSYS_PHP_INVALID_VER']} {$php_version} )</span></b>";
  866. $ret['error_found'] = true;
  867. break;
  868. case 0:
  869. $ret['phpVersion'] = "<b><span class=go>{$installer_mod_strings['ERR_CHECKSYS_PHP_UNSUPPORTED']} {$php_version} )</span></b>";
  870. break;
  871. case 1:
  872. $ret['phpVersion'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_PHP_OK']} {$php_version} )</span></b>";
  873. break;
  874. }
  875. // database and connect
  876. $canInstall = $db->canInstall();
  877. if ($canInstall !== true)
  878. {
  879. $ret['error_found'] = true;
  880. if (count($canInstall) == 1)
  881. {
  882. $ret['dbVersion'] = "<b><span class=stop>" . $installer_mod_strings[$canInstall[0]] . "</span></b>";
  883. }
  884. else
  885. {
  886. $ret['dbVersion'] = "<b><span class=stop>" . sprintf($installer_mod_strings[$canInstall[0]], $canInstall[1]) . "</span></b>";
  887. }
  888. }
  889. // XML Parsing
  890. if(function_exists('xml_parser_create')) {
  891. $ret['xmlStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
  892. } else {
  893. $ret['xmlStatus'] = "<b><span class=stop>{$installer_mod_strings['LBL_CHECKSYS_NOT_AVAILABLE']}</span></b>";
  894. $ret['error_found'] = true;
  895. }
  896. // cURL
  897. if(function_exists('curl_init')) {
  898. $ret['curlStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
  899. } else {
  900. $ret['curlStatus'] = "<b><span class=go>{$installer_mod_strings['ERR_CHECKSYS_CURL']}</span></b>";
  901. $ret['error_found'] = false;
  902. }
  903. // mbstrings
  904. if(function_exists('mb_strlen')) {
  905. $ret['mbstringStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
  906. } else {
  907. $ret['mbstringStatus'] = "<b><span class=stop>{$installer_mod_strings['ERR_CHECKSYS_MBSTRING']}</span></b>";
  908. $ret['error_found'] = true;
  909. }
  910. // imap
  911. if(function_exists('imap_open')) {
  912. $ret['imapStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
  913. } else {
  914. $ret['imapStatus'] = "<b><span class=go>{$installer_mod_strings['ERR_CHECKSYS_IMAP']}</span></b>";
  915. $ret['error_found'] = false;
  916. }
  917. // safe mode
  918. if('1' == ini_get('safe_mode')) {
  919. $ret['safeModeStatus'] = "<b><span class=stop>{$installer_mod_strings['ERR_CHECKSYS_SAFE_MODE']}</span></b>";
  920. $ret['error_found'] = true;
  921. } else {
  922. $ret['safeModeStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
  923. }
  924. // call time pass by ref
  925. if('1' == ini_get('allow_call_time_pass_reference')) {
  926. $ret['callTimeStatus'] = "<b><span class=stop>{$installer_mod_strings['ERR_CHECKSYS_CALL_TIME']}</span></b>";
  927. //continue upgrading
  928. } else {
  929. $ret['callTimeStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
  930. }
  931. // memory limit
  932. $ret['memory_msg'] = "";
  933. $memory_limit = "-1";//ini_get('memory_limit');
  934. $sugarMinMem = constant('SUGARCRM_MIN_MEM');
  935. // logic based on: http://us2.php.net/manual/en/ini.core.php#ini.memory-limit
  936. if( $memory_limit == "" ){ // memory_limit disabled at compile time, no memory limit
  937. $ret['memory_msg'] = "<b><span class=\"go\">{$installer_mod_strings['LBL_CHECKSYS_MEM_OK']}</span></b>";
  938. } elseif( $memory_limit == "-1" ){ // memory_limit enabled, but set to unlimited
  939. $ret['memory_msg'] = "<b><span class=\"go\">{$installer_mod_strings['LBL_CHECKSYS_MEM_UNLIMITED']}</span></b>";
  940. } else {
  941. rtrim($memory_limit, 'M');
  942. $memory_limit_int = (int) $memory_limit;
  943. if( $memory_limit_int < constant('SUGARCRM_MIN_MEM') ){
  944. $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>";
  945. $ret['error_found'] = true;
  946. } else {
  947. $ret['memory_msg'] = "<b><span class=\"go\">{$installer_mod_strings['LBL_CHECKSYS_OK']} ({$memory_limit})</span></b>";
  948. }
  949. }
  950. // zip support
  951. if (!class_exists("ZipArchive"))
  952. {
  953. $ret['ZipStatus'] = "<b><span class=stop>{$installer_mod_strings['ERR_CHECKSYS_ZIP']}</span></b>";
  954. $ret['error_found'] = true;
  955. } else {
  956. $ret['ZipStatus'] = "<b><span class=go>{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
  957. }
  958. // Suhosin allow to use upload://
  959. $ret['stream_msg'] = '';
  960. if (UploadStream::getSuhosinStatus() == true)
  961. {
  962. $ret['stream_msg'] = "<b><span class=\"go\">{$installer_mod_strings['LBL_CHECKSYS_OK']}</span></b>";
  963. }
  964. else
  965. {
  966. $ret['stream_msg'] = "<b><span class=\"stop\">{$app_strings['ERR_SUHOSIN']}</span></b>";
  967. $ret['error_found'] = true;
  968. }
  969. /* mbstring.func_overload
  970. $ret['mbstring.func_overload'] = '';
  971. $mb = ini_get('mbstring.func_overload');
  972. if($mb > 1) {
  973. $ret['mbstring.func_overload'] = "<b><span class=\"stop\">{$mod_strings['ERR_UW_MBSTRING_FUNC_OVERLOAD']}</b>";
  974. $ret['error_found'] = true;
  975. }
  976. */
  977. return $ret;
  978. }
  979. /**
  980. * is a file that we blow away automagically
  981. */
  982. function isAutoOverwriteFile($file) {
  983. $overwriteDirs = array(
  984. './sugar_version.php',
  985. './modules/UpgradeWizard/uw_main.tpl',
  986. );
  987. $file = trim('.'.str_replace(clean_path(getcwd()), '', $file));
  988. if(in_array($file, $overwriteDirs)) {
  989. return true;
  990. }
  991. $fileExtension = substr(strrchr($file, "."), 1);
  992. if($fileExtension == 'tpl' || $fileExtension == 'html') {
  993. return false;
  994. }
  995. return true;
  996. }
  997. /**
  998. * flatfile logger
  999. */
  1000. function logThis($entry, $path='') {
  1001. global $mod_strings;
  1002. if(file_exists('include/utils/sugar_file_utils.php')){
  1003. require_once('include/utils/sugar_file_utils.php');
  1004. }
  1005. $log = empty($path) ? clean_path(getcwd().'/upgradeWizard.log') : clean_path($path);
  1006. // create if not exists
  1007. if(!file_exists($log)) {
  1008. if(function_exists('sugar_fopen')){
  1009. $fp = @sugar_fopen($log, 'w+'); // attempts to create file
  1010. }
  1011. else{
  1012. $fp = fopen($log, 'w+'); // attempts to create file
  1013. }
  1014. if(!is_resource($fp)) {
  1015. $GLOBALS['log']->fatal('UpgradeWizard could not create the upgradeWizard.log file');
  1016. die($mod_strings['ERR_UW_LOG_FILE_UNWRITABLE']);
  1017. }
  1018. } else {
  1019. if(function_exists('sugar_fopen')){
  1020. $fp = @sugar_fopen($log, 'a+'); // write pointer at end of file
  1021. }
  1022. else{
  1023. $fp = @fopen($log, 'a+'); // write pointer at end of file
  1024. }
  1025. if(!is_resource($fp)) {
  1026. $GLOBALS['log']->fatal('UpgradeWizard could not open/lock upgradeWizard.log file');
  1027. die($mod_strings['ERR_UW_LOG_FILE_UNWRITABLE']);
  1028. }
  1029. }
  1030. $line = date('r').' [UpgradeWizard] - '.$entry."\n";
  1031. if(@fwrite($fp, $line) === false) {
  1032. $GLOBALS['log']->fatal('UpgradeWizard could not write to upgradeWizard.log: '.$entry);
  1033. die($mod_strings['ERR_UW_LOG_FILE_UNWRITABLE']);
  1034. }
  1035. if(is_resource($fp)) {
  1036. fclose($fp);
  1037. }
  1038. }
  1039. /**
  1040. * @params : none
  1041. * @author: nsingh
  1042. * @desc This function is to be used in the upgrade process to preserve changes/customaizations made to pre 5.1 quickcreate layout.
  1043. * 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
  1044. * was automatically picked up by the quick create. [Addresses Bug 21469]
  1045. * This function will check if customizations were made, and will create quickcreatedefs.php in the /cutom/working/$module_name directory.
  1046. **/
  1047. function updateQuickCreateDefs(){
  1048. $d = dir('modules');
  1049. $studio_modules = array();
  1050. while($e = $d->read()){ //collect all studio modules.
  1051. if(substr($e, 0, 1) == '.' || !is_dir('modules/' . $e))continue;
  1052. if(file_exists('modules/' . $e . '/metadata/studio.php'))
  1053. {
  1054. array_push($studio_modules, $e);
  1055. }
  1056. }
  1057. foreach( $studio_modules as $modname ){ //for each studio enabled module
  1058. //Check !exists modules/$modname/metadata/quickcreatedefs.php &&
  1059. //exists custom/$modname/editviewdefs.php (module was customized) &&
  1060. //!exists custom/$modname/quickcreateviewdefs.php
  1061. $editviewdefs = "custom/working/modules/".$modname."/metadata/editviewdefs.php";
  1062. $quickcreatedefs = "custom/working/modules/".$modname."/metadata/quickcreatedefs.php";
  1063. if ( !file_exists("modules/".$modname."/metadata/quickcreatedefs.php") &&
  1064. file_exists($editviewdefs) &&
  1065. !file_exists($quickcreatedefs) ){
  1066. //clone editviewdef and save it in custom/working/modules/metadata
  1067. $GLOBALS['log']->debug("Copying editviewdefs.php as quickcreatedefs.php for the $modname module in custom/working/modules/$modname/metadata!");
  1068. if(copy( $editviewdefs, $quickcreatedefs)){
  1069. if(file_exists($quickcreatedefs) && is_readable($quickcreatedefs)){
  1070. $file = file($quickcreatedefs);
  1071. //replace 'EditView' with 'QuickCreate'
  1072. $fp = fopen($quickcreatedefs,'w');
  1073. foreach($file as &$line){
  1074. if(preg_match('/^\s*\'EditView\'\s*=>\s*$/', $line) > 0){
  1075. $line = "'QuickCreate' =>\n";
  1076. }
  1077. fwrite($fp, $line);
  1078. }
  1079. //write back.
  1080. fclose($fp);
  1081. }
  1082. else{
  1083. $GLOBALS['log']->debug("Failed to replace 'EditView' with QuickCreate because $quickcreatedefs is either not readable or does not exist.");
  1084. }
  1085. }else{
  1086. $GLOBALS['log']->debug("Failed to copy $editviewdefs to $quickcreatedefs!");
  1087. }
  1088. }
  1089. }
  1090. }
  1091. /**
  1092. * test perms for CREATE queries
  1093. */
  1094. function testPermsCreate($db, $out) {
  1095. logThis('Checking CREATE TABLE permissions...');
  1096. global $mod_strings;
  1097. if(!$db->checkPrivilege("CREATE TABLE")) {
  1098. logThis('cannot CREATE TABLE!');
  1099. $out['db']['dbNoCreate'] = true;
  1100. $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_CREATE']}</span></td></tr>";
  1101. }
  1102. return $out;
  1103. }
  1104. /**
  1105. * test perms for INSERT
  1106. */
  1107. function testPermsInsert($db, $out, $skip=false) {
  1108. logThis('Checking INSERT INTO permissions...');
  1109. global $mod_strings;
  1110. if(!$db->checkPrivilege("INSERT")) {
  1111. logThis('cannot INSERT INTO!');
  1112. $out['db']['dbNoInsert'] = true;
  1113. $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_INSERT']}</span></td></tr>";
  1114. }
  1115. return $out;
  1116. }
  1117. /**
  1118. * test perms for UPDATE TABLE
  1119. */
  1120. function testPermsUpdate($db, $out, $skip=false) {
  1121. logThis('Checking UPDATE TABLE permissions...');
  1122. global $mod_strings;
  1123. if(!$db->checkPrivilege("UPDATE")) {
  1124. logThis('cannot UPDATE TABLE!');
  1125. $out['db']['dbNoUpdate'] = true;
  1126. $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_UPDATE']}</span></td></tr>";
  1127. }
  1128. return $out;
  1129. }
  1130. /**
  1131. * test perms for SELECT
  1132. */
  1133. function testPermsSelect($db, $out, $skip=false) {
  1134. logThis('Checking SELECT permissions...');
  1135. global $mod_strings;
  1136. if(!$db->checkPrivilege("SELECT")) {
  1137. logThis('cannot SELECT!');
  1138. $out['db']['dbNoSelect'] = true;
  1139. $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_SELECT']}</span></td></tr>";
  1140. }
  1141. return $out;
  1142. }
  1143. /**
  1144. * test perms for DELETE
  1145. */
  1146. function testPermsDelete($db, $out, $skip=false) {
  1147. logThis('Checking DELETE FROM permissions...');
  1148. global $mod_strings;
  1149. if(!$db->checkPrivilege("DELETE")) {
  1150. logThis('cannot DELETE FROM!');
  1151. $out['db']['dbNoDelete'] = true;
  1152. $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_DELETE']}</span></td></tr>";
  1153. }
  1154. return $out;
  1155. }
  1156. /**
  1157. * test perms for ALTER TABLE ADD COLUMN
  1158. */
  1159. function testPermsAlterTableAdd($db, $out, $skip=false) {
  1160. logThis('Checking ALTER TABLE ADD COLUMN permissions...');
  1161. global $mod_strings;
  1162. if(!$db->checkPrivilege("ADD COLUMN")) {
  1163. logThis('cannot ADD COLUMN!');
  1164. $out['db']['dbNoAddColumn'] = true;
  1165. $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_ADD_COLUMN']}</span></td></tr>";
  1166. }
  1167. return $out;
  1168. }
  1169. /**
  1170. * test perms for ALTER TABLE ADD COLUMN
  1171. */
  1172. function testPermsAlterTableChange($db, $out, $skip=false) {
  1173. logThis('Checking ALTER TABLE CHANGE COLUMN permissions...');
  1174. global $mod_strings;
  1175. if(!$db->checkPrivilege("CHANGE COLUMN")) {
  1176. logThis('cannot CHANGE COLUMN!');
  1177. $out['db']['dbNoChangeColumn'] = true;
  1178. $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_CHANGE_COLUMN']}</span></td></tr>";
  1179. }
  1180. return $out;
  1181. }
  1182. /**
  1183. * test perms for ALTER TABLE DROP COLUMN
  1184. */
  1185. function testPermsAlterTableDrop($db, $out, $skip=false) {
  1186. logThis('Checking ALTER TABLE DROP COLUMN permissions...');
  1187. global $mod_strings;
  1188. if(!$db->checkPrivilege("DROP COLUMN")) {
  1189. logThis('cannot DROP COLUMN!');
  1190. $out['db']['dbNoDropColumn'] = true;
  1191. $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_DROP_COLUMN']}</span></td></tr>";
  1192. }
  1193. return $out;
  1194. }
  1195. /**
  1196. * test perms for DROP TABLE
  1197. */
  1198. function testPermsDropTable($db, $out, $skip=false) {
  1199. logThis('Checking DROP TABLE permissions...');
  1200. global $mod_strings;
  1201. if(!$db->checkPrivilege("DROP TABLE")) {
  1202. logThis('cannot DROP TABLE!');
  1203. $out['db']['dbNoDropTable'] = true;
  1204. $out['dbOut'] .= "<tr><td align='left'><span class='error'>{$mod_strings['LBL_UW_DB_NO_DROP_TABLE']}</span></td></tr>";
  1205. }
  1206. return $out;
  1207. }
  1208. function getFormattedError($error, $query) {
  1209. $error = "<div><b>".$error;
  1210. $error .= "</b>::{$query}</div>";
  1211. return $error;
  1212. }
  1213. /**
  1214. * parses a query finding the table name
  1215. * @param string query The query
  1216. * @return string table The table
  1217. */
  1218. function getTableFromQuery($query) {
  1219. $standardQueries = array('ALTER TABLE', 'DROP TABLE', 'CREATE TABLE', 'INSERT INTO', 'UPDATE', 'DELETE FROM');
  1220. $query = preg_replace("/[^A-Za-z0-9\_\s]/", "", $query);
  1221. $query = trim(str_replace($standardQueries, '', $query));
  1222. $firstSpc = strpos($query, " ");
  1223. $end = ($firstSpc > 0) ? $firstSpc : strlen($query);
  1224. $table = substr($query, 0, $end);
  1225. return $table;
  1226. }
  1227. //prelicense check
  1228. function preLicenseCheck() {
  1229. require_once('modules/UpgradeWizard/uw_files.php');
  1230. global $sugar_config;
  1231. global $mod_strings;
  1232. global $sugar_version;
  1233. if(!isset($sugar_version) || empty($sugar_version)) {
  1234. require_once('./sugar_version.php');
  1235. }
  1236. if(!isset($_SESSION['unzip_dir']) || empty($_SESSION['unzip_dir'])) {
  1237. logThis('unzipping files in upgrade archive...');
  1238. $errors = array();
  1239. list($base_upgrade_dir, $base_tmp_upgrade_dir) = getUWDirs();
  1240. $unzip_dir = '';
  1241. //also come up with mechanism to read from upgrade-progress file
  1242. if(!isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !is_file($_SESSION['install_file'])) {
  1243. if (file_exists(clean_path($base_tmp_upgrade_dir)) && $handle = opendir(clean_path($base_tmp_upgrade_dir))) {
  1244. while (false !== ($file = readdir($handle))) {
  1245. if($file !="." && $file !="..") {
  1246. if(is_file($base_tmp_upgrade_dir."/".$file."/manifest.php")){
  1247. require_once($base_tmp_upgrade_dir."/".$file."/manifest.php");
  1248. $package_name= $manifest['copy_files']['from_dir'];
  1249. 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")){
  1250. $unzip_dir = $base_tmp_upgrade_dir."/".$file;
  1251. if(file_exists("$base_upgrade_dir/patch/".$package_name.'.zip')){
  1252. $_SESSION['install_file'] = $package_name.".zip";
  1253. break;
  1254. }
  1255. }
  1256. }
  1257. }
  1258. }
  1259. }
  1260. }
  1261. if(empty($_SESSION['install_file'])){
  1262. unlinkUWTempFiles();
  1263. resetUwSession();
  1264. echo 'Upload File not found so redirecting to Upgrade Start ';
  1265. $redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
  1266. echo '<form name="redirect" action="' .$redirect_new_wizard. '" method="POST">';
  1267. $upgrade_directories_not_found =<<<eoq
  1268. <table cellpadding="3" cellspacing="0" border="0">
  1269. <tr>
  1270. <th colspan="2" align="left">
  1271. <span class='error'><b>'Upload file missing or has been deleted. Refresh the page to go back to UpgradeWizard start'</b></span>
  1272. </th>
  1273. </tr>
  1274. </table>
  1275. eoq;
  1276. $uwMain = $upgrade_directories_not_found;
  1277. return '';
  1278. }
  1279. $install_file = "$base_upgrade_dir/patch/".basename(urldecode( $_SESSION['install_file'] ));
  1280. $show_files = true;
  1281. if(empty($unzip_dir)){
  1282. $unzip_dir = mk_temp_dir( $base_tmp_upgrade_dir );
  1283. }
  1284. $zip_from_dir = ".";
  1285. $zip_to_dir = ".";
  1286. $zip_force_copy = array();
  1287. if(!$unzip_dir){
  1288. logThis('Could not create a temporary directory using mk_temp_dir( $base_tmp_upgrade_dir )');
  1289. die($mod_strings['ERR_UW_NO_CREATE_TMP_DIR']);
  1290. }
  1291. //double check whether unzipped .
  1292. if(file_exists($unzip_dir ."/scripts") && file_exists($unzip_dir."/manifest.php")){
  1293. //already unzipped
  1294. }
  1295. else{
  1296. unzip( $install_file, $unzip_dir );
  1297. }
  1298. // assumption -- already validated manifest.php at time of upload
  1299. require_once( "$unzip_dir/manifest.php" );
  1300. if( isset( $manifest['copy_files']['from_dir'] ) && $manifest['copy_files']['from_dir'] != "" ){
  1301. $zip_from_dir = $manifest['copy_files']['from_dir'];
  1302. }
  1303. if( isset( $manifest['copy_files']['to_dir'] ) && $manifest['copy_files']['to_dir'] != "" ){
  1304. $zip_to_dir = $manifest['copy_files']['to_dir'];
  1305. }
  1306. if( isset( $manifest['copy_files']['force_copy'] ) && $manifest['copy_files']['force_copy'] != "" ){
  1307. $zip_force_copy = $manifest['copy_files']['force_copy'];
  1308. }
  1309. if( isset( $manifest['version'] ) ){
  1310. $version = $manifest['version'];
  1311. }
  1312. if( !is_writable( "config.php" ) ){
  1313. return $mod_strings['ERR_UW_CONFIG'];
  1314. }
  1315. $_SESSION['unzip_dir'] = clean_path($unzip_dir);
  1316. $_SESSION['zip_from_dir'] = clean_path($zip_from_dir);
  1317. logThis('unzip done.');
  1318. } else {
  1319. $unzip_dir = $_SESSION['unzip_dir'];
  1320. $zip_from_dir = $_SESSION['zip_from_dir'];
  1321. }
  1322. //check if $_SESSION['unzip_dir'] and $_SESSION['zip_from_dir'] exist
  1323. if(!isset($_SESSION['unzip_dir']) || !file_exists($_SESSION['unzip_dir'])
  1324. || !isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !file_exists($_SESSION['install_file'])){
  1325. //redirect to start
  1326. unlinkUWTempFiles();
  1327. resetUwSession();
  1328. echo 'Upload File not found so redirecting to Upgrade Start ';
  1329. $redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
  1330. echo '<form name="redirect" action="' .$redirect_new_wizard. '" method="POST">';
  1331. $upgrade_directories_not_found =<<<eoq
  1332. <table cellpadding="3" cellspacing="0" border="0">
  1333. <tr>
  1334. <th colspan="2" align="left">
  1335. <span class='error'><b>'Upload file missing or has been deleted. Refresh the page to go back to UpgradeWizard start'</b></span>
  1336. </th>
  1337. </tr>
  1338. </table>
  1339. eoq;
  1340. $uwMain = $upgrade_directories_not_found;
  1341. return '';
  1342. }
  1343. logThis ('is SugarConfig there '.file_exists(clean_path($unzip_dir.'/'.$zip_from_dir."/include/SugarObjects/SugarConfig.php")));
  1344. if(file_exists(clean_path($unzip_dir.'/'.$zip_from_dir."/include/SugarObjects/SugarConfig.php"))) {
  1345. $file = clean_path($unzip_dir.'/'.$zip_from_dir."/include/SugarObjects/SugarConfig.php");
  1346. $destFile = str_replace(clean_path($unzip_dir.'/'.$zip_from_dir), $cwd, $file);
  1347. if(!is_dir(dirname($destFile))) {
  1348. mkdir_recursive(dirname($destFile)); // make sure the directory exists
  1349. }
  1350. copy($file,$destFile);
  1351. //also copy include utils array utils
  1352. $file = clean_path($unzip_dir.'/'.$zip_from_dir."/include/utils/array_utils.php");
  1353. $destFile = str_replace(clean_path($unzip_dir.'/'.$zip_from_dir), $cwd, $file);
  1354. if(!is_dir(dirname($destFile))) {
  1355. mkdir_recursive(dirname($destFile)); // make sure the directory exists
  1356. }
  1357. copy($file,$destFile);
  1358. }
  1359. }
  1360. function preflightCheck() {
  1361. require_once('modules/UpgradeWizard/uw_files.php');
  1362. global $sugar_config;
  1363. global $mod_strings;
  1364. global $sugar_version;
  1365. if(!isset($sugar_version) || empty($sugar_version)) {
  1366. require_once('./sugar_version.php');
  1367. }
  1368. unset($_SESSION['rebuild_relationships']);
  1369. unset($_SESSION['rebuild_extensions']);
  1370. // don't bother if are rechecking
  1371. $manualDiff = array();
  1372. if(!isset($_SESSION['unzip_dir']) || empty($_SESSION['unzip_dir'])) {
  1373. logThis('unzipping files in upgrade archive...');
  1374. $errors = array();
  1375. list($base_upgrade_dir, $base_tmp_upgrade_dir) = getUWDirs();
  1376. $unzip_dir = '';
  1377. //Following is if User logged out unexpectedly and then logged into UpgradeWizard again.
  1378. //also come up with mechanism to read from upgrade-progress file.
  1379. if(!isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !is_file($_SESSION['install_file'])) {
  1380. if (file_exists($base_tmp_upgrade_dir) && $handle = opendir($base_tmp_upgrade_dir)) {
  1381. while (false !== ($file = readdir($handle))) {
  1382. if($file !="." && $file !="..") {
  1383. if(is_file($base_tmp_upgrade_dir."/".$file."/manifest.php")){
  1384. require_once($base_tmp_upgrade_dir."/".$file."/manifest.php");
  1385. $package_name= $manifest['copy_files']['from_dir'];
  1386. 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")){
  1387. $unzip_dir = $base_tmp_upgrade_dir."/".$file;
  1388. if(file_exists("$base_upgrade_dir/patch/".$package_name.'.zip')){
  1389. $_SESSION['install_file'] = $package_name.".zip";
  1390. break;
  1391. }
  1392. }
  1393. }
  1394. }
  1395. }
  1396. }
  1397. }
  1398. if(empty($_SESSION['install_file'])){
  1399. unlinkUWTempFiles();
  1400. resetUwSession();
  1401. echo 'Upload File not found so redirecting to Upgrade Start ';
  1402. $redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
  1403. echo '<form name="redirect" action="' .$redirect_new_wizard. '" method="POST">';
  1404. $upgrade_directories_not_found =<<<eoq
  1405. <table cellpadding="3" cellspacing="0" border="0">
  1406. <tr>
  1407. <th colspan="2" align="left">
  1408. <span class='error'><b>'Upload file missing or has been deleted. Refresh the page to go back to UpgradeWizard start'</b></span>
  1409. </th>
  1410. </tr>
  1411. </table>
  1412. eoq;
  1413. $uwMain = $upgrade_directories_not_found;
  1414. return '';
  1415. }
  1416. $install_file = "$base_upgrade_dir/patch/".basename(urldecode( $_SESSION['install_file'] ));
  1417. $show_files = true;
  1418. if(empty($unzip_dir)){
  1419. $unzip_dir = mk_temp_dir( $base_tmp_upgrade_dir );
  1420. }
  1421. $zip_from_dir = ".";
  1422. $zip_to_dir = ".";
  1423. $zip_force_copy = array();
  1424. if(!$unzip_dir){
  1425. logThis('Could not create a temporary directory using mk_temp_dir( $base_tmp_upgrade_dir )');
  1426. die($mod_strings['ERR_UW_NO_CREATE_TMP_DIR']);
  1427. }
  1428. //double check whether unzipped .
  1429. if(file_exists($unzip_dir ."/scripts") && file_exists($unzip_dir."/manifest.php")){
  1430. //already unzipped
  1431. }
  1432. else{
  1433. unzip( $install_file, $unzip_dir );
  1434. }
  1435. // assumption -- already validated manifest.php at time of upload
  1436. require_once( "$unzip_dir/manifest.php" );
  1437. if( isset( $manifest['copy_files']['from_dir'] ) && $manifest['copy_files']['from_dir'] != "" ){
  1438. $zip_from_dir = $manifest['copy_files']['from_dir'];
  1439. }
  1440. if( isset( $manifest['copy_files']['to_dir'] ) && $manifest['copy_files']['to_dir'] != "" ){
  1441. $zip_to_dir = $manifest['copy_files']['to_dir'];
  1442. }
  1443. if( isset( $manifest['copy_files']['force_copy'] ) && $manifest['copy_files']['force_copy'] != "" ){
  1444. $zip_force_copy = $manifest['copy_files']['force_copy'];
  1445. }
  1446. if( isset( $manifest['version'] ) ){
  1447. $version = $manifest['version'];
  1448. }
  1449. if( !is_writable( "config.php" ) ){
  1450. return $mod_strings['ERR_UW_CONFIG'];
  1451. }
  1452. $_SESSION['unzip_dir'] = clean_path($unzip_dir);
  1453. $_SESSION['zip_from_dir'] = clean_path($zip_from_dir);
  1454. //logThis('unzip done.');
  1455. } else {
  1456. $unzip_dir = $_SESSION['unzip_dir'];
  1457. $zip_from_dir = $_SESSION['zip_from_dir'];
  1458. }
  1459. //check if $_SESSION['unzip_dir'] and $_SESSION['zip_from_dir'] exist
  1460. if(!isset($_SESSION['unzip_dir']) || !file_exists($_SESSION['unzip_dir'])
  1461. || !isset($_SESSION['install_file']) || empty($_SESSION['install_file']) || !file_exists($_SESSION['install_file'])){
  1462. //redirect to start
  1463. unlinkUWTempFiles();
  1464. resetUwSession();
  1465. echo 'Upload File not found so redirecting to Upgrade Start ';
  1466. $redirect_new_wizard = $sugar_config['site_url' ].'/index.php?module=UpgradeWizard&action=index';
  1467. echo '<form name="redirect" action="' .$redirect_new_wizard. '" method="POST">';
  1468. $upgrade_directories_not_found =<<<eoq
  1469. <table cellpadding="3" cellspacing="0" border="0">
  1470. <tr>
  1471. <th colspan="2" align="left">
  1472. <span class='error'><b>'Upload file missing or has been deleted. Refresh the page to go back to UpgradeWizard start'</b></span>
  1473. </th>
  1474. </tr>
  1475. </table>
  1476. eoq;
  1477. $uwMain = $upgrade_directories_not_found;
  1478. return '';
  1479. }
  1480. //copy minimum required files
  1481. fileCopy('include/utils/sugar_file_utils.php');
  1482. $upgradeFiles = findAllFiles(clean_path("$unzip_dir/$zip_from_dir"), array());
  1483. $cache_html_files= array();
  1484. // get md5 sums
  1485. $md5_string = array();
  1486. if(file_exists(clean_path(getcwd().'/files.md5'))){
  1487. require(clean_path(getcwd().'/files.md5'));
  1488. }
  1489. // file preflight checks
  1490. logThis('verifying md5 checksums for files...');
  1491. foreach($upgradeFiles as $file) {
  1492. if(in_array(str_replace(clean_path("$unzip_dir/$zip_from_dir") . "/", '', $file), $uw_files))
  1493. continue; // skip already loaded files
  1494. if(strpos($file, '.md5'))
  1495. continue; // skip md5 file
  1496. // normalize file paths
  1497. $file = clean_path($file);
  1498. // check that we can move/delete the upgraded file
  1499. if(!is_writable($file)) {
  1500. $errors[] = $mod_strings['ERR_UW_FILE_NOT_WRITABLE'].": ".$file;
  1501. }
  1502. // check that destination files are writable
  1503. $destFile = getcwd().str_replace(clean_path($unzip_dir.'/'.$zip_from_dir), '', $file);
  1504. if(is_file($destFile)) { // of course it needs to exist first...
  1505. if(!is_writable($destFile)) {
  1506. $errors[] = $mod_strings['ERR_UW_FILE_NOT_WRITABLE'].": ".$destFile;
  1507. }
  1508. }
  1509. ///////////////////////////////////////////////////////////////////////
  1510. //// DIFFS
  1511. // compare md5s and build up a manual merge list
  1512. $targetFile = clean_path(".".str_replace(getcwd(),'',$destFile));
  1513. $targetMd5 = '0';
  1514. if(is_file($destFile)) {
  1515. if(strpos($targetFile, '.php')) {
  1516. // handle PHP files that were hit with the security regex
  1517. $fp = '';
  1518. if(function_exists('sugar_fopen')){
  1519. $fp = sugar_fopen($destFile, 'r');
  1520. }
  1521. else{
  1522. $fp = fopen($destFile, 'r');
  1523. }
  1524. $filesize = filesize($destFile);
  1525. if($filesize > 0) {
  1526. $fileContents = stream_get_contents($fp);
  1527. $targetMd5 = md5($fileContents);
  1528. }
  1529. } else {
  1530. $targetMd5 = md5_file($destFile);
  1531. }
  1532. }
  1533. if(isset($md5_string[$targetFile]) && $md5_string[$targetFile] != $targetMd5) {
  1534. logThis('found a file with a differing md5: ['.$targetFile.']');
  1535. $manualDiff[] = $destFile;
  1536. }
  1537. //// END DIFFS
  1538. ///////////////////////////////////////////////////////////////////////
  1539. }
  1540. logThis('md5 verification done.');
  1541. $errors['manual'] = $manualDiff;
  1542. return $errors;
  1543. }
  1544. function fileCopy($file_path){
  1545. if(file_exists(clean_path($_SESSION['unzip_dir'].'/'.$_SESSION['zip_from_dir'].'/'.$file_path))) {
  1546. $file = clean_path($_SESSION['unzip_dir'].'/'.$_SESSION['zip_from_dir'].'/'.$file_path);
  1547. $destFile = str_replace(clean_path($_SESSION['unzip_dir'].'/'.$_SESSION['zip_from_dir']), clean_path(getcwd()), $file);
  1548. if(!is_dir(dirname($destFile))) {
  1549. mkdir_recursive(dirname($destFile)); // make sure the directory exists
  1550. }
  1551. copy_recursive($file,$destFile);
  1552. }
  1553. }
  1554. function getChecklist($steps, $step) {
  1555. global $mod_strings;
  1556. $skip = array('start', 'cancel', 'uninstall','end');
  1557. $j=0;
  1558. $i=1;
  1559. $ret = '<table cellpadding="3" cellspacing="4" border="0">';
  1560. $ret .= '<tr><th colspan="3" align="left">'.$mod_strings['LBL_UW_CHECKLIST'].':</th></tr>';
  1561. foreach($steps['desc'] as $k => $desc) {
  1562. if(in_array($steps['files'][$j], $skip)) {
  1563. $j++;
  1564. continue;
  1565. }
  1566. //$status = "<span class='error'>{$mod_strings['LBL_UW_INCOMPLETE']}</span>";
  1567. $desc_mod_pre = '';
  1568. $desc_mod_post = '';
  1569. /*
  1570. if(isset($_SESSION['step'][$steps['files'][$k]]) && $_SESSION['step'][$steps['files'][$k]] == 'success') {
  1571. //$status = $mod_strings['LBL_UW_COMPLETE'];
  1572. }
  1573. */
  1574. if($k == $_REQUEST['step']) {
  1575. //$status = $mod_strings['LBL_UW_IN_PROGRESS'];
  1576. $desc_mod_pre = "<font color=blue><i>";
  1577. $desc_mod_post = "</i></font>";
  1578. }
  1579. $ret .= "<tr><td>&nbsp;</td><td><b>{$i}: {$desc_mod_pre}{$desc}{$desc_mod_post}</b></td>";
  1580. $ret .= "<td id={$steps['files'][$j]}><i></i></td></tr>";
  1581. $i++;
  1582. $j++;
  1583. }
  1584. $ret .= "</table>";
  1585. return $ret;
  1586. }
  1587. function prepSystemForUpgrade() {
  1588. global $sugar_config;
  1589. global $sugar_flavor;
  1590. global $mod_strings;
  1591. global $current_language;
  1592. global $subdirs;
  1593. global $base_upgrade_dir;
  1594. global $base_tmp_upgrade_dir;
  1595. list($p_base_upgrade_dir, $p_base_tmp_upgrade_dir) = getUWDirs();
  1596. ///////////////////////////////////////////////////////////////////////////////
  1597. //// Make sure variables exist
  1598. if(empty($base_upgrade_dir)){
  1599. $base_upgrade_dir = $p_base_upgrade_dir;
  1600. }
  1601. if(empty($base_tmp_upgrade_dir)){
  1602. $base_tmp_upgrade_dir = $p_base_tmp_upgrade_dir;
  1603. }
  1604. sugar_mkdir($base_tmp_upgrade_dir, 0775, true);
  1605. if(!isset($subdirs) || empty($subdirs)){
  1606. $subdirs = array('full', 'langpack', 'module', 'patch', 'theme');
  1607. }
  1608. $upgrade_progress_dir = $base_tmp_upgrade_dir;
  1609. $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
  1610. if(file_exists($upgrade_progress_file)){
  1611. if(function_exists('get_upgrade_progress') && function_exists('didThisStepRunBefore')){
  1612. if(didThisStepRunBefore('end')){
  1613. include($upgrade_progress_file);
  1614. unset($upgrade_config);
  1615. unlink($upgrade_progress_file);
  1616. }
  1617. }
  1618. }
  1619. // increase the cuttoff time to 1 hour
  1620. ini_set("max_execution_time", "3600");
  1621. // make sure dirs exist
  1622. if($subdirs != null){
  1623. foreach($subdirs as $subdir) {
  1624. sugar_mkdir("$base_upgrade_dir/$subdir", 0775, true);
  1625. }
  1626. }
  1627. // array of special scripts that are executed during (un)installation-- key is type of script, value is filename
  1628. if(!defined('SUGARCRM_PRE_INSTALL_FILE')) {
  1629. define('SUGARCRM_PRE_INSTALL_FILE', 'scripts/pre_install.php');
  1630. define('SUGARCRM_POST_INSTALL_FILE', 'scripts/post_install.php');
  1631. define('SUGARCRM_PRE_UNINSTALL_FILE', 'scripts/pre_uninstall.php');
  1632. define('SUGARCRM_POST_UNINSTALL_FILE', 'scripts/post_uninstall.php');
  1633. }
  1634. $script_files = array(
  1635. "pre-install" => constant('SUGARCRM_PRE_INSTALL_FILE'),
  1636. "post-install" => constant('SUGARCRM_POST_INSTALL_FILE'),
  1637. "pre-uninstall" => constant('SUGARCRM_PRE_UNINSTALL_FILE'),
  1638. "post-uninstall" => constant('SUGARCRM_POST_UNINSTALL_FILE'),
  1639. );
  1640. // check that the upload limit is set to 6M or greater
  1641. define('SUGARCRM_MIN_UPLOAD_MAX_FILESIZE_BYTES', 6 * 1024 * 1024); // 6 Megabytes
  1642. $upload_max_filesize = ini_get('upload_max_filesize');
  1643. $upload_max_filesize_bytes = return_bytes($upload_max_filesize);
  1644. if($upload_max_filesize_bytes < constant('SUGARCRM_MIN_UPLOAD_MAX_FILESIZE_BYTES')) {
  1645. $GLOBALS['log']->debug("detected upload_max_filesize: $upload_max_filesize");
  1646. $admin_strings = return_module_language($current_language, 'Administration');
  1647. echo '<p class="error">'.$admin_strings['MSG_INCREASE_UPLOAD_MAX_FILESIZE'].' '.get_cfg_var('cfg_file_path')."</p>\n";
  1648. }
  1649. }
  1650. if ( !function_exists('extractFile') ) {
  1651. function extractFile($zip_file, $file_in_zip) {
  1652. global $base_tmp_upgrade_dir;
  1653. // strip cwd
  1654. $absolute_base_tmp_upgrade_dir = clean_path($base_tmp_upgrade_dir);
  1655. $relative_base_tmp_upgrade_dir = clean_path(str_replace(clean_path(getcwd()), '', $absolute_base_tmp_upgrade_dir));
  1656. // mk_temp_dir expects relative pathing
  1657. $my_zip_dir = mk_temp_dir($relative_base_tmp_upgrade_dir);
  1658. unzip_file($zip_file, $file_in_zip, $my_zip_dir);
  1659. return("$my_zip_dir/$file_in_zip");
  1660. }
  1661. }
  1662. if ( !function_exists('extractManifest') ) {
  1663. function extractManifest($zip_file) {
  1664. logThis('extracting manifest.');
  1665. return(extractFile($zip_file, "manifest.php"));
  1666. }
  1667. }
  1668. if ( !function_exists('getInstallType') ) {
  1669. function getInstallType($type_string) {
  1670. // detect file type
  1671. global $subdirs;
  1672. $subdirs = array('full', 'langpack', 'module', 'patch', 'theme', 'temp');
  1673. foreach($subdirs as $subdir) {
  1674. if(preg_match("#/$subdir/#", $type_string)) {
  1675. return($subdir);
  1676. }
  1677. }
  1678. // return empty if no match
  1679. return("");
  1680. }
  1681. }
  1682. function getImageForType($type) {
  1683. global $image_path;
  1684. global $mod_strings;
  1685. $icon = "";
  1686. switch($type) {
  1687. case "full":
  1688. $icon = SugarThemeRegistry::current()->getImage("Upgrade", "",null,null,'.gif',$mod_strings['LBL_UPGRADE']);
  1689. break;
  1690. case "langpack":
  1691. $icon = SugarThemeRegistry::current()->getImage("LanguagePacks", "",null,null,'.gif',$mod_strings['LBL_LANGPACKS']);
  1692. break;
  1693. case "module":
  1694. $icon = SugarThemeRegistry::current()->getImage("ModuleLoader", "",null,null,'.gif',$mod_strings['LBL_MODULELOADER']);
  1695. break;
  1696. case "patch":
  1697. $icon = SugarThemeRegistry::current()->getImage("PatchUpgrades", "",null,null,'.gif',$mod_strings['LBL_PATCHUPGRADES']);
  1698. break;
  1699. case "theme":
  1700. $icon = SugarThemeRegistry::current()->getImage("Themes", "",null,null,'.gif',$mod_strings['LBL_THEMES']);
  1701. break;
  1702. default:
  1703. break;
  1704. }
  1705. return($icon);
  1706. }
  1707. if ( !function_exists('getLanguagePackName') ) {
  1708. function getLanguagePackName($the_file) {
  1709. require_once("$the_file");
  1710. if(isset($app_list_strings["language_pack_name"])) {
  1711. return($app_list_strings["language_pack_name"]);
  1712. }
  1713. return("");
  1714. }
  1715. }
  1716. function getUITextForType($type) {
  1717. if($type == "full") {
  1718. return("Full Upgrade");
  1719. }
  1720. if($type == "langpack") {
  1721. return("Language Pack");
  1722. }
  1723. if($type == "module") {
  1724. return("Module");
  1725. }
  1726. if($type == "patch") {
  1727. return("Patch");
  1728. }
  1729. if($type == "theme") {
  1730. return("Theme");
  1731. }
  1732. }
  1733. if ( !function_exists('validate_manifest') ) {
  1734. /**
  1735. * Verifies a manifest from a patch or module to be compatible with the current Sugar version and flavor
  1736. * @param array manifest Standard manifest array
  1737. * @return string Error message, blank on success
  1738. */
  1739. function validate_manifest($manifest) {
  1740. logThis('validating manifest.php file');
  1741. // takes a manifest.php manifest array and validates contents
  1742. global $subdirs;
  1743. global $sugar_version;
  1744. global $sugar_flavor;
  1745. global $mod_strings;
  1746. if(!isset($manifest['type'])) {
  1747. return $mod_strings['ERROR_MANIFEST_TYPE'];
  1748. }
  1749. $type = $manifest['type'];
  1750. if(getInstallType("/$type/") == "") {
  1751. return $mod_strings['ERROR_PACKAGE_TYPE']. ": '" . $type . "'.";
  1752. }
  1753. if(isset($manifest['acceptable_sugar_versions'])) {
  1754. $version_ok = false;
  1755. $matches_empty = true;
  1756. if(isset($manifest['acceptable_sugar_versions']['exact_matches'])) {
  1757. $matches_empty = false;
  1758. foreach($manifest['acceptable_sugar_versions']['exact_matches'] as $match) {
  1759. if($match == $sugar_version) {
  1760. $version_ok = true;
  1761. }
  1762. }
  1763. }
  1764. if(!$version_ok && isset($manifest['acceptable_sugar_versions']['regex_matches'])) {
  1765. $matches_empty = false;
  1766. foreach($manifest['acceptable_sugar_versions']['regex_matches'] as $match) {
  1767. if(preg_match("/$match/", $sugar_version)) {
  1768. $version_ok = true;
  1769. }
  1770. }
  1771. }
  1772. if(!$matches_empty && !$version_ok) {
  1773. return $mod_strings['ERROR_VERSION_INCOMPATIBLE']."<br />".
  1774. $mod_strings['ERR_UW_VERSION'].$sugar_version;
  1775. }
  1776. }
  1777. if(isset($manifest['acceptable_sugar_flavors']) && sizeof($manifest['acceptable_sugar_flavors']) > 0) {
  1778. $flavor_ok = false;
  1779. foreach($manifest['acceptable_sugar_flavors'] as $match) {
  1780. if($match == $sugar_flavor) {
  1781. $flavor_ok = true;
  1782. }
  1783. }
  1784. if(!$flavor_ok) {
  1785. return $mod_strings['ERROR_FLAVOR_INCOMPATIBLE']."<br />".
  1786. $mod_strings['ERR_UW_FLAVOR'].$sugar_flavor."<br />".
  1787. $mod_strings['ERR_UW_FLAVOR_2'].$manifest['acceptable_sugar_flavors'][0];
  1788. }
  1789. }
  1790. return '';
  1791. }
  1792. }
  1793. function unlinkUploadFiles() {
  1794. return;
  1795. // logThis('at unlinkUploadFiles()');
  1796. //
  1797. // if(isset($_SESSION['install_file']) && !empty($_SESSION['install_file'])) {
  1798. // $upload = $_SESSION['install_file'];
  1799. //
  1800. // if(is_file($upload)) {
  1801. // logThis('unlinking ['.$upload.']');
  1802. // @unlink($upload);
  1803. // }
  1804. // }
  1805. }
  1806. /**
  1807. * deletes files created by unzipping a package
  1808. */
  1809. function unlinkUWTempFiles() {
  1810. global $sugar_config;
  1811. global $path;
  1812. logThis('at unlinkUWTempFiles()');
  1813. $tempDir='';
  1814. list($upgDir, $tempDir) = getUWDirs();
  1815. if(file_exists($tempDir) && is_dir($tempDir)){
  1816. $files = findAllFiles($tempDir, array(), false);
  1817. rsort($files);
  1818. foreach($files as $file) {
  1819. if(!is_dir($file)) {
  1820. //logThis('unlinking ['.$file.']', $path);
  1821. @unlink($file);
  1822. }
  1823. }
  1824. // now do dirs
  1825. $files = findAllFiles($tempDir, array(), true);
  1826. foreach($files as $dir) {
  1827. if(is_dir($dir)) {
  1828. //logThis('removing dir ['.$dir.']', $path);
  1829. @rmdir($dir);
  1830. }
  1831. }
  1832. $cacheFile = sugar_cached("modules/UpgradeWizard/_persistence.php");
  1833. if(is_file($cacheFile)) {
  1834. logThis("Unlinking Upgrade cache file: '_persistence.php'", $path);
  1835. @unlink($cacheFile);
  1836. }
  1837. }
  1838. logThis("finished!");
  1839. }
  1840. /**
  1841. * finds all files in the passed path, but skips select directories
  1842. * @param string dir Relative path
  1843. * @param array the_array Collections of found files/dirs
  1844. * @param bool include_dir True if we want to include directories in the
  1845. * returned collection
  1846. */
  1847. function uwFindAllFiles($dir, $theArray, $includeDirs=false, $skipDirs=array(), $echo=false) {
  1848. // check skips
  1849. if (whetherNeedToSkipDir($dir, $skipDirs))
  1850. {
  1851. return $theArray;
  1852. }
  1853. if (!is_dir($dir)) { return $theArray; } // Bug # 46035, just checking for valid dir
  1854. $d = dir($dir);
  1855. if ($d === false) { return $theArray; } // Bug # 46035, more checking
  1856. while($f = $d->read()) {
  1857. // bug 40793 Skip Directories array in upgradeWizard does not function correctly
  1858. if($f == "." || $f == ".." || whetherNeedToSkipDir("$dir/$f", $skipDirs)) { // skip *nix self/parent
  1859. continue;
  1860. }
  1861. // for AJAX length count
  1862. if($echo) {
  1863. echo '.';
  1864. ob_flush();
  1865. }
  1866. if(is_dir("$dir/$f")) {
  1867. if($includeDirs) { // add the directory if flagged
  1868. $theArray[] = clean_path("$dir/$f");
  1869. }
  1870. // recurse in
  1871. $theArray = uwFindAllFiles("$dir/$f/", $theArray, $includeDirs, $skipDirs, $echo);
  1872. } else {
  1873. $theArray[] = clean_path("$dir/$f");
  1874. }
  1875. }
  1876. rsort($theArray);
  1877. $d->close();
  1878. return $theArray;
  1879. }
  1880. /**
  1881. * unset's UW's Session Vars
  1882. */
  1883. function resetUwSession() {
  1884. logThis('resetting $_SESSION');
  1885. if(isset($_SESSION['committed']))
  1886. unset($_SESSION['committed']);
  1887. if(isset($_SESSION['sugar_version_file']))
  1888. unset($_SESSION['sugar_version_file']);
  1889. if(isset($_SESSION['upgrade_complete']))
  1890. unset($_SESSION['upgrade_complete']);
  1891. if(isset($_SESSION['allTables']))
  1892. unset($_SESSION['allTables']);
  1893. if(isset($_SESSION['alterCustomTableQueries']))
  1894. unset($_SESSION['alterCustomTableQueries']);
  1895. if(isset($_SESSION['skip_zip_upload']))
  1896. unset($_SESSION['skip_zip_upload']);
  1897. if(isset($_SESSION['sugar_version_file']))
  1898. unset($_SESSION['sugar_version_file']);
  1899. if(isset($_SESSION['install_file']))
  1900. unset($_SESSION['install_file']);
  1901. if(isset($_SESSION['unzip_dir']))
  1902. unset($_SESSION['unzip_dir']);
  1903. if(isset($_SESSION['zip_from_dir']))
  1904. unset($_SESSION['zip_from_dir']);
  1905. if(isset($_SESSION['overwrite_files']))
  1906. unset($_SESSION['overwrite_files']);
  1907. if(isset($_SESSION['schema_change']))
  1908. unset($_SESSION['schema_change']);
  1909. if(isset($_SESSION['uw_restore_dir']))
  1910. unset($_SESSION['uw_restore_dir']);
  1911. if(isset($_SESSION['step']))
  1912. unset($_SESSION['step']);
  1913. if(isset($_SESSION['files']))
  1914. unset($_SESSION['files']);
  1915. if(isset($_SESSION['Upgraded451Wizard'])){
  1916. unset($_SESSION['Upgraded451Wizard']);
  1917. }
  1918. if(isset($_SESSION['Initial_451to500_Step'])){
  1919. unset($_SESSION['Initial_451to500_Step']);
  1920. }
  1921. if(isset($_SESSION['license_shown']))
  1922. unset($_SESSION['license_shown']);
  1923. if(isset($_SESSION['sugarMergeRunResults']))
  1924. unset($_SESSION['sugarMergeRunResults']);
  1925. }
  1926. /**
  1927. * runs rebuild scripts
  1928. */
  1929. function UWrebuild() {
  1930. global $db;
  1931. global $path;
  1932. /*
  1933. //CCL - Comment this block out, it is called in end.php
  1934. logThis('Rebuilding everything...', $path);
  1935. require_once('modules/Administration/QuickRepairAndRebuild.php');
  1936. $randc = new RepairAndClear();
  1937. $randc->repairAndClearAll(array('clearAll'),array(translate('LBL_ALL_MODULES')), false, false);
  1938. */
  1939. $query = "DELETE FROM versions WHERE name='Rebuild Extensions'";
  1940. $db->query($query);
  1941. logThis('Registering rebuild record: '.$query, $path);
  1942. logThis('Rebuild done.', $path);
  1943. // insert a new database row to show the rebuild extensions is done
  1944. $id = create_guid();
  1945. $gmdate = gmdate('Y-m-d H:i:s');
  1946. $date_entered = db_convert("'$gmdate'", 'datetime');
  1947. $query = 'INSERT INTO versions (id, deleted, date_entered, date_modified, modified_user_id, created_by, name, file_version, db_version) '
  1948. . "VALUES ('$id', '0', $date_entered, $date_entered, '1', '1', 'Rebuild Extensions', '4.0.0', '4.0.0')";
  1949. $db->query($query);
  1950. logThis('Registering rebuild record in versions table: '.$query, $path);
  1951. }
  1952. function getCustomTables() {
  1953. global $db;
  1954. return $db->tablesLike('%_cstm');
  1955. }
  1956. function alterCustomTables($customTables)
  1957. {
  1958. return array();
  1959. }
  1960. function getAllTables() {
  1961. global $db;
  1962. return $db->getTablesArray();
  1963. }
  1964. function printAlterTableSql($tables)
  1965. {
  1966. $alterTableSql = '';
  1967. foreach($tables as $table)
  1968. $alterTableSql .= "ALTER TABLE " . $table . " CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;" . "\n";
  1969. return $alterTableSql;
  1970. }
  1971. function executeConvertTablesSql($tables)
  1972. {
  1973. global $db;
  1974. foreach($tables as $table){
  1975. $query = "ALTER TABLE " . $table . " CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci";
  1976. if(!empty($table)){
  1977. logThis("Sending query: ".$query);
  1978. $db->query($query);//, true, "An error has occured while performing db query. See log file for details.<br>");
  1979. }
  1980. }
  1981. return true;
  1982. }
  1983. function testThis() {
  1984. $files = uwFindAllFiles(getcwd().'/test', array());
  1985. $out = "<table cellpadding='1' cellspacing='0' border='0'>\n";
  1986. $priorPath = '';
  1987. foreach($files as $file) {
  1988. $relativeFile = clean_path(str_replace(getcwd().'/test', '', $file));
  1989. $relativeFile = ($relativeFile{0} == '/') ? substr($relativeFile, 1, strlen($relativeFile)) : $relativeFile;
  1990. $relativePath = dirname($relativeFile);
  1991. if($relativePath == $priorPath) { // same dir, new file
  1992. $out .= "<tr><td>".basename($relativeFile)."</td></tr>";
  1993. $priorPath = $relativePath;
  1994. } else { // new dir
  1995. }
  1996. }
  1997. $out .= "</table>";
  1998. echo $out;
  1999. }
  2000. function testThis2($dir, $id=0, $hide=false) {
  2001. global $mod_strings;
  2002. $path = $dir;
  2003. $dh = opendir($dir);
  2004. rewinddir($dh);
  2005. $doHide = ($hide) ? 'none' : '';
  2006. $out = "<div id='{$id}' style='display:{$doHide};'>";
  2007. $out .= "<table cellpadding='1' cellspacing='0' style='border:0px solid #ccc'>\n";
  2008. while($file = readdir($dh)) {
  2009. if($file == '.' || $file == '..' || $file == 'CVS' || $file == '.cvsignore')
  2010. continue;
  2011. if(is_dir($path.'/'.$file)) {
  2012. $file = $path.'/'.$file;
  2013. $newI = create_guid();
  2014. $out .= "<tr><td valign='top'><a href='javascript:toggleNwFiles(\"{$newI}\");'>".SugarThemeRegistry::current()->getImage("Workflow", "", null, null, ".gif", $mod_strings['LBL_WORKFLOW'])."</a></td>\n";
  2015. $out .= "<td valign='top'><b><a href='javascript:toggleNwFiles(\"{$newI}\");'>".basename($file)."</a></b></td></tr>";
  2016. $out .= "<tr><td></td><td valign='top'>".testThis2($file, $newI, true)."</td></tr>";
  2017. } else {
  2018. $out .= "<tr><td valign='top'>&nbsp;</td>\n";
  2019. $out .= "<td valign='top'>".basename($file)."</td></tr>";
  2020. }
  2021. }
  2022. $out .= "</tr></table>";
  2023. $out .= "</div>";
  2024. closedir($dh);
  2025. return $out;
  2026. }
  2027. function testThis3(&$files, $id, $hide, $previousPath = '') {
  2028. if(!is_array($files) || empty($files))
  2029. return '';
  2030. $out = '';
  2031. global $mod_strings;
  2032. // expecting full path here
  2033. foreach($files as $k => $file) {
  2034. $file = str_replace(getcwd(), '', $file);
  2035. $path = dirname($file);
  2036. $fileName = basename($file);
  2037. if($fileName == 'CVS' || $fileName == '.cvsignore')
  2038. continue;
  2039. if($path == $previousPath) { // same directory
  2040. // new row for each file
  2041. $out .= "<tr><td valign='top' align='left'>&nbsp;</td>";
  2042. $out .= "<td valign='top' align='left'>{$fileName}</td></tr>";
  2043. } else { // new directory
  2044. $newI = $k;
  2045. $out .= "<tr><td valign='top'><a href='javascript:toggleNwFiles(\"{$newI}\");'>".SugarThemeRegistry::current()->getImage("Workflow", "", null, null, ".gif", $mod_strings['LBL_WORKFLOW'])."</a></td>\n";
  2046. $out .= "<td valign='top'><b><a href='javascript:toggleNwFiles(\"{$newI}\");'>".$fileName."</a></b></td></tr>";
  2047. $recurse = testThis3($files, $newI, true, $previousPath);
  2048. $out .= "<tr><td></td><td valign='top'>".$recurse."</td></tr>";
  2049. }
  2050. $previousPath = $path;
  2051. }
  2052. $display = ($hide) ? 'none' : '';
  2053. $ret = <<<eoq
  2054. <div id="{$id}" style="display:{$display}">
  2055. <table cellpadding='1' cellspacing='0' border='0' style='border:1px solid #ccc'>
  2056. {$out}
  2057. </table>
  2058. </div>
  2059. eoq;
  2060. return $ret;
  2061. }
  2062. function testThis4($filePath, $fileNodes=array(), $fileName='') {
  2063. $path = dirname($filePath);
  2064. $file = basename($filePath);
  2065. $exFile = explode('/', $path);
  2066. foreach($exFile as $pathSegment) {
  2067. if(is_array($fileNodes[$pathSegment])) { // path already processed
  2068. } else { // newly found path
  2069. $fileNodes[$pathSegment] = array();
  2070. }
  2071. if($fileName != '') {
  2072. $fileNodes[$pathSegment][] = $fileName;
  2073. }
  2074. }
  2075. return $fileNodes;
  2076. }
  2077. ///////////////////////////////////////////////////////////////////////////////
  2078. //// SYSTEM CHECK FUNCTIONS
  2079. /**
  2080. * generates an array with all files in the SugarCRM root directory, skipping
  2081. * cache/
  2082. * @return array files Array of files with absolute paths
  2083. */
  2084. function getFilesForPermsCheck() {
  2085. global $sugar_config;
  2086. logThis('Got JSON call to find all files...');
  2087. $filesNotWritable = array();
  2088. $filesNWPerms = array();
  2089. // add directories here that should be skipped when doing file permissions checks (cache/upload is the nasty one)
  2090. $skipDirs = array(
  2091. $sugar_config['upload_dir'],
  2092. );
  2093. $files = uwFindAllFiles(".", array(), true, $skipDirs, true);
  2094. return $files;
  2095. }
  2096. /**
  2097. * checks files for permissions
  2098. * @param array files Array of files with absolute paths
  2099. * @return string result of check
  2100. */
  2101. function checkFiles($files, $echo=false) {
  2102. global $mod_strings;
  2103. $filesNotWritable = array();
  2104. $i=0;
  2105. $filesOut = "
  2106. <a href='javascript:void(0); toggleNwFiles(\"filesNw\");'>{$mod_strings['LBL_UW_SHOW_NW_FILES']}</a>
  2107. <div id='filesNw' style='display:none;'>
  2108. <table cellpadding='3' cellspacing='0' border='0'>
  2109. <tr>
  2110. <th align='left'>{$mod_strings['LBL_UW_FILE']}</th>
  2111. <th align='left'>{$mod_strings['LBL_UW_FILE_PERMS']}</th>
  2112. <th align='left'>{$mod_strings['LBL_UW_FILE_OWNER']}</th>
  2113. <th align='left'>{$mod_strings['LBL_UW_FILE_GROUP']}</th>
  2114. </tr>";
  2115. $isWindows = is_windows();
  2116. foreach($files as $file) {
  2117. if($isWindows) {
  2118. if(!is_writable_windows($file)) {
  2119. logThis('WINDOWS: File ['.$file.'] not readable - saving for display');
  2120. // don't warn yet - we're going to use this to check against replacement files
  2121. // aw: commented out; it's a hack to allow upgrade wizard to continue on windows... will fix later
  2122. /*$filesNotWritable[$i] = $file;
  2123. $filesNWPerms[$i] = substr(sprintf('%o',fileperms($file)), -4);
  2124. $filesOut .= "<tr>".
  2125. "<td><span class='error'>{$file}</span></td>".
  2126. "<td>{$filesNWPerms[$i]}</td>".
  2127. "<td>".$mod_strings['ERR_UW_CANNOT_DETERMINE_USER']."</td>".
  2128. "<td>".$mod_strings['ERR_UW_CANNOT_DETERMINE_GROUP']."</td>".
  2129. "</tr>";*/
  2130. }
  2131. } else {
  2132. if(!is_writable($file)) {
  2133. logThis('File ['.$file.'] not writable - saving for display');
  2134. // don't warn yet - we're going to use this to check against replacement files
  2135. $filesNotWritable[$i] = $file;
  2136. $filesNWPerms[$i] = substr(sprintf('%o',fileperms($file)), -4);
  2137. $owner = posix_getpwuid(fileowner($file));
  2138. $group = posix_getgrgid(filegroup($file));
  2139. $filesOut .= "<tr>".
  2140. "<td><span class='error'>{$file}</span></td>".
  2141. "<td>{$filesNWPerms[$i]}</td>".
  2142. "<td>".$owner['name']."</td>".
  2143. "<td>".$group['name']."</td>".
  2144. "</tr>";
  2145. }
  2146. }
  2147. $i++;
  2148. }
  2149. $filesOut .= '</table></div>';
  2150. // not a stop error
  2151. $errors['files']['filesNotWritable'] = (count($filesNotWritable) > 0) ? true : false;
  2152. if(count($filesNotWritable) < 1) {
  2153. $filesOut = "{$mod_strings['LBL_UW_FILE_NO_ERRORS']}";
  2154. }
  2155. return $filesOut;
  2156. }
  2157. function deletePackageOnCancel(){
  2158. global $mod_strings;
  2159. global $sugar_config;
  2160. list($base_upgrade_dir, $base_tmp_upgrade_dir) = getUWDirs();
  2161. logThis('running delete');
  2162. if(!isset($_SESSION['install_file']) || ($_SESSION['install_file'] == "")) {
  2163. logThis('ERROR: trying to delete non-existent file: ['.$_REQUEST['install_file'].']');
  2164. $error = $mod_strings['ERR_UW_NO_FILE_UPLOADED'];
  2165. }
  2166. // delete file in upgrades/patch
  2167. $delete_me = "$base_upgrade_dir/patch/".basename(urldecode( $_REQUEST['install_file'] ));
  2168. if(@unlink($delete_me)) {
  2169. //logThis('unlinking: '.$delete_me);
  2170. $out = basename($delete_me).$mod_strings['LBL_UW_FILE_DELETED'];
  2171. } else {
  2172. logThis('ERROR: could not delete ['.$delete_me.']');
  2173. $error = $mod_strings['ERR_UW_FILE_NOT_DELETED'].$delete_me;
  2174. }
  2175. if(!empty($error)) {
  2176. $out = "<b><span class='error'>{$error}</span></b><br />";
  2177. }
  2178. }
  2179. function handleExecuteSqlKeys($db, $tableName, $disable)
  2180. {
  2181. if(empty($tableName)) return true;
  2182. if(is_callable(array($db, "supports"))) {
  2183. // new API
  2184. return $disable?$db->disableKeys($tableName):$db->enableKeys($tableName);
  2185. } else {
  2186. // old api
  2187. $op = $disable?"DISABLE":"ENABLE";
  2188. return $db->query("ALTER TABLE $tableName $op KEYS");
  2189. }
  2190. }
  2191. function parseAndExecuteSqlFile($sqlScript,$forStepQuery='',$resumeFromQuery='')
  2192. {
  2193. global $sugar_config;
  2194. $alterTableSchema = '';
  2195. $sqlErrors = array();
  2196. if(!isset($_SESSION['sqlSkippedQueries'])){
  2197. $_SESSION['sqlSkippedQueries'] = array();
  2198. }
  2199. $db = DBManagerFactory::getInstance();
  2200. $disable_keys = ($db->dbType == "mysql"); // have to use old way for now for upgrades
  2201. if(strpos($resumeFromQuery,",") != false){
  2202. $resumeFromQuery = explode(",",$resumeFromQuery);
  2203. }
  2204. if(file_exists($sqlScript)) {
  2205. $fp = fopen($sqlScript, 'r');
  2206. $contents = stream_get_contents($fp);
  2207. $anyScriptChanges =$contents;
  2208. $resumeAfterFound = false;
  2209. if(rewind($fp)) {
  2210. $completeLine = '';
  2211. $count = 0;
  2212. while($line = fgets($fp)) {
  2213. if(strpos($line, '--') === false) {
  2214. $completeLine .= " ".trim($line);
  2215. if(strpos($line, ';') !== false) {
  2216. $query = '';
  2217. $query = str_replace(';','',$completeLine);
  2218. //if resume from query is not null then find out from where
  2219. //it should start executing the query.
  2220. if($query != null && $resumeFromQuery != null){
  2221. if(!$resumeAfterFound){
  2222. if(strpos($query,",") != false){
  2223. $queArray = explode(",",$query);
  2224. for($i=0;$i<sizeof($resumeFromQuery);$i++){
  2225. if(strcasecmp(trim($resumeFromQuery[$i]),trim($queArray[$i]))==0){
  2226. $resumeAfterFound = true;
  2227. } else {
  2228. $resumeAfterFound = false;
  2229. break;
  2230. }
  2231. }//for
  2232. }
  2233. elseif(strcasecmp(trim($resumeFromQuery),trim($query))==0){
  2234. $resumeAfterFound = true;
  2235. }
  2236. }
  2237. if($resumeAfterFound){
  2238. $count++;
  2239. }
  2240. // if $count=1 means it is just found so skip the query. Run the next one
  2241. if($query != null && $resumeAfterFound && $count >1){
  2242. $tableName = getAlterTable($query);
  2243. if($disable_keys)
  2244. {
  2245. handleExecuteSqlKeys($db, $tableName, true);
  2246. }
  2247. $db->query($query);
  2248. if($db->checkError()){
  2249. //put in the array to use later on
  2250. $_SESSION['sqlSkippedQueries'][] = $query;
  2251. }
  2252. if($disable_keys)
  2253. {
  2254. handleExecuteSqlKeys($db, $tableName, false);
  2255. }
  2256. $progQuery[$forStepQuery]=$query;
  2257. post_install_progress($progQuery,$action='set');
  2258. }//if
  2259. }
  2260. elseif($query != null){
  2261. $tableName = getAlterTable($query);
  2262. if($disable_keys)
  2263. {
  2264. handleExecuteSqlKeys($db, $tableName, true);
  2265. }
  2266. $db->query($query);
  2267. if($disable_keys)
  2268. {
  2269. handleExecuteSqlKeys($db, $tableName, false);
  2270. }
  2271. $progQuery[$forStepQuery]=$query;
  2272. post_install_progress($progQuery,$action='set');
  2273. if($db->checkError()){
  2274. //put in the array to use later on
  2275. $_SESSION['sqlSkippedQueries'][] = $query;
  2276. }
  2277. }
  2278. $completeLine = '';
  2279. }
  2280. }
  2281. }//while
  2282. }
  2283. }
  2284. }
  2285. function getAlterTable($query){
  2286. $query = strtolower($query);
  2287. if (preg_match('/^\s*alter\s+table\s+/', $query)) {
  2288. $sqlArray = explode(" ", $query);
  2289. $key = array_search('table', $sqlArray);
  2290. return $sqlArray[($key+1)];
  2291. }else {
  2292. return '';
  2293. }
  2294. }
  2295. function set_upgrade_vars(){
  2296. logThis('setting session variables...');
  2297. $upgrade_progress_dir = sugar_cached('upgrades/temp');
  2298. if(!is_dir($upgrade_progress_dir)){
  2299. mkdir_recursive($upgrade_progress_dir);
  2300. }
  2301. $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
  2302. if(file_exists($upgrade_progress_file)){
  2303. include($upgrade_progress_file);
  2304. }
  2305. else{
  2306. fopen($upgrade_progress_file, 'w+');
  2307. }
  2308. if(!isset($upgrade_config) || $upgrade_config == null){
  2309. $upgrade_config = array();
  2310. $upgrade_config[1]['upgrade_vars']=array();
  2311. }
  2312. if(isset($upgrade_config[1]) && isset($upgrade_config[1]['upgrade_vars']) && !is_array($upgrade_config[1]['upgrade_vars'])){
  2313. $upgrade_config[1]['upgrade_vars'] = array();
  2314. }
  2315. if(!isset($upgrade_vars) || $upgrade_vars == NULL){
  2316. $upgrade_vars = array();
  2317. }
  2318. if(isset($_SESSION['unzip_dir']) && !empty($_SESSION['unzip_dir']) && file_exists($_SESSION['unzip_dir'])){
  2319. $upgrade_vars['unzip_dir']=$_SESSION['unzip_dir'];
  2320. }
  2321. if(isset($_SESSION['install_file']) && !empty($_SESSION['install_file']) && file_exists($_SESSION['install_file'])){
  2322. $upgrade_vars['install_file']=$_SESSION['install_file'];
  2323. }
  2324. if(isset($_SESSION['Upgraded451Wizard']) && !empty($_SESSION['Upgraded451Wizard'])){
  2325. $upgrade_vars['Upgraded451Wizard']=$_SESSION['Upgraded451Wizard'];
  2326. }
  2327. if(isset($_SESSION['license_shown']) && !empty($_SESSION['license_shown'])){
  2328. $upgrade_vars['license_shown']=$_SESSION['license_shown'];
  2329. }
  2330. if(isset($_SESSION['Initial_451to500_Step']) && !empty($_SESSION['Initial_451to500_Step'])){
  2331. $upgrade_vars['Initial_451to500_Step']=$_SESSION['Initial_451to500_Step'];
  2332. }
  2333. if(isset($_SESSION['zip_from_dir']) && !empty($_SESSION['zip_from_dir'])){
  2334. $upgrade_vars['zip_from_dir']=$_SESSION['zip_from_dir'];
  2335. }
  2336. //place into the upgrade_config array and rewrite config array only if new values are being inserted
  2337. if(isset($upgrade_vars) && $upgrade_vars != null && sizeof($upgrade_vars) > 0){
  2338. foreach($upgrade_vars as $key=>$val){
  2339. if($key != null && $val != null){
  2340. $upgrade_config[1]['upgrade_vars'][$key]=$upgrade_vars[$key];
  2341. }
  2342. }
  2343. ksort($upgrade_config);
  2344. if(is_writable($upgrade_progress_file) && write_array_to_file( "upgrade_config", $upgrade_config,
  2345. $upgrade_progress_file)) {
  2346. //writing to the file
  2347. }
  2348. }
  2349. }
  2350. function initialize_session_vars(){
  2351. $upgrade_progress_dir = sugar_cached('upgrades/temp');
  2352. $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
  2353. if(file_exists($upgrade_progress_file)){
  2354. include($upgrade_progress_file);
  2355. if(isset($upgrade_config) && $upgrade_config != null && is_array($upgrade_config) && sizeof($upgrade_config) >0){
  2356. $currVarsArray=$upgrade_config[1]['upgrade_vars'];
  2357. //print_r($currVarsArray);
  2358. if(isset($currVarsArray) && $currVarsArray != null && is_array($currVarsArray) && sizeof($currVarsArray)>0){
  2359. foreach($currVarsArray as $key=>$val){
  2360. if($key != null && $val !=null){
  2361. //set session variables
  2362. $_SESSION[$key]=$val;
  2363. //set varibales
  2364. '$'.$key=$val;
  2365. }
  2366. }
  2367. }
  2368. }
  2369. }
  2370. }
  2371. //track the upgrade progress on each step
  2372. //track the upgrade progress on each step
  2373. function set_upgrade_progress($currStep,$currState,$currStepSub='',$currStepSubState=''){
  2374. $upgrade_progress_dir = sugar_cached('upgrades/temp');
  2375. if(!is_dir($upgrade_progress_dir)){
  2376. mkdir_recursive($upgrade_progress_dir);
  2377. }
  2378. $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
  2379. if(file_exists($upgrade_progress_file)){
  2380. include($upgrade_progress_file);
  2381. }
  2382. else{
  2383. if(function_exists('sugar_fopen')){
  2384. sugar_fopen($upgrade_progress_file, 'w+');
  2385. }
  2386. else{
  2387. fopen($upgrade_progress_file, 'w+');
  2388. }
  2389. }
  2390. if(!isset($upgrade_config) || $upgrade_config == null){
  2391. $upgrade_config = array();
  2392. $upgrade_config[1]['upgrade_vars']=array();
  2393. }
  2394. if(!is_array($upgrade_config[1]['upgrade_vars'])){
  2395. $upgrade_config[1]['upgrade_vars'] = array();
  2396. }
  2397. if($currStep != null && $currState != null){
  2398. if(sizeof($upgrade_config) > 0){
  2399. if($currStepSub != null && $currStepSubState !=null){
  2400. //check if new status to be set or update
  2401. //get the latest in array. since it has sub components prepare an array
  2402. if(!empty($upgrade_config[sizeof($upgrade_config)][$currStep]) && is_array($upgrade_config[sizeof($upgrade_config)][$currStep])){
  2403. $latestStepSub = currSubStep($upgrade_config[sizeof($upgrade_config)][$currStep]);
  2404. if($latestStepSub == $currStepSub){
  2405. $upgrade_config[sizeof($upgrade_config)][$currStep][$latestStepSub]=$currStepSubState;
  2406. $upgrade_config[sizeof($upgrade_config)][$currStep][$currStep] = $currState;
  2407. }
  2408. else{
  2409. $upgrade_config[sizeof($upgrade_config)][$currStep][$currStepSub]=$currStepSubState;
  2410. $upgrade_config[sizeof($upgrade_config)][$currStep][$currStep] = $currState;
  2411. }
  2412. }
  2413. else{
  2414. $currArray = array();
  2415. $currArray[$currStep] = $currState;
  2416. $currArray[$currStepSub] = $currStepSubState;
  2417. $upgrade_config[sizeof($upgrade_config)+1][$currStep] = $currArray;
  2418. }
  2419. }
  2420. else{
  2421. //get the current upgrade progress
  2422. $latestStep = get_upgrade_progress();
  2423. //set the upgrade progress
  2424. if($latestStep == $currStep){
  2425. //update the current step with new progress status
  2426. $upgrade_config[sizeof($upgrade_config)][$latestStep]=$currState;
  2427. }
  2428. else{
  2429. //it's a new step
  2430. $upgrade_config[sizeof($upgrade_config)+1][$currStep]=$currState;
  2431. }
  2432. // now check if there elements within array substeps
  2433. }
  2434. }
  2435. else{
  2436. //set the upgrade progress (just starting)
  2437. $upgrade_config[sizeof($upgrade_config)+1][$currStep]= $currState;
  2438. }
  2439. if(is_writable($upgrade_progress_file) && write_array_to_file( "upgrade_config", $upgrade_config,
  2440. $upgrade_progress_file)) {
  2441. //writing to the file
  2442. }
  2443. }
  2444. }
  2445. function get_upgrade_progress(){
  2446. $upgrade_progress_dir = sugar_cached('upgrades/temp');
  2447. $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
  2448. $currState = '';
  2449. if(file_exists($upgrade_progress_file)){
  2450. include($upgrade_progress_file);
  2451. if(!isset($upgrade_config) || $upgrade_config == null){
  2452. $upgrade_config = array();
  2453. }
  2454. if($upgrade_config != null && sizeof($upgrade_config) >1){
  2455. $currArr = $upgrade_config[sizeof($upgrade_config)];
  2456. if(is_array($currArr)){
  2457. foreach($currArr as $key=>$val){
  2458. $currState = $key;
  2459. }
  2460. }
  2461. }
  2462. }
  2463. return $currState;
  2464. }
  2465. function currSubStep($currStep){
  2466. $currSubStep = '';
  2467. if(is_array($currStep)){
  2468. foreach($currStep as $key=>$val){
  2469. if($key != null){
  2470. $currState = $key;
  2471. }
  2472. }
  2473. }
  2474. return $currState;
  2475. }
  2476. function currUpgradeState($currState){
  2477. $currState = '';
  2478. if(is_array($currState)){
  2479. foreach($currState as $key=>$val){
  2480. if(is_array($val)){
  2481. foreach($val as $k=>$v){
  2482. if($k != null){
  2483. $currState = $k;
  2484. }
  2485. }
  2486. }
  2487. else{
  2488. $currState = $key;
  2489. }
  2490. }
  2491. }
  2492. return $currState;
  2493. }
  2494. function didThisStepRunBefore($step,$SubStep=''){
  2495. if($step == null) return;
  2496. $upgrade_progress_dir = sugar_cached('upgrades/temp');
  2497. $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
  2498. $currState = '';
  2499. $stepRan = false;
  2500. if(file_exists($upgrade_progress_file)){
  2501. include($upgrade_progress_file);
  2502. if(isset($upgrade_config) && $upgrade_config != null && is_array($upgrade_config) && sizeof($upgrade_config) >0){
  2503. for($i=1;$i<=sizeof($upgrade_config);$i++){
  2504. if(is_array($upgrade_config[$i])){
  2505. foreach($upgrade_config[$i] as $key=>$val){
  2506. if($key==$step){
  2507. if(is_array($upgrade_config[$i][$step])){
  2508. //now process
  2509. foreach ($upgrade_config[$i][$step] as $k=>$v){
  2510. if(is_array($v)){
  2511. foreach($v as $k1=>$v1){
  2512. if($SubStep != null){
  2513. if($SubStep ==$k1 && $v1=='done'){
  2514. $stepRan = true;
  2515. break;
  2516. }
  2517. }
  2518. }//foreach
  2519. }
  2520. elseif($SubStep !=null){
  2521. if($SubStep==$k && $v=='done'){
  2522. $stepRan = true;
  2523. break;
  2524. }
  2525. }
  2526. elseif($step==$k && $v=='done'){
  2527. $stepRan = true;
  2528. break;
  2529. }
  2530. }//foreach
  2531. }
  2532. elseif($val=='done'){
  2533. $stepRan = true;
  2534. }
  2535. }
  2536. }//foreach
  2537. }
  2538. }//for
  2539. }
  2540. }
  2541. return $stepRan;
  2542. }
  2543. //get and set post install status
  2544. function post_install_progress($progArray='',$action=''){
  2545. $upgrade_progress_dir = sugar_cached('upgrades/temp');
  2546. $upgrade_progress_file = $upgrade_progress_dir.'/upgrade_progress.php';
  2547. if($action=='' || $action=='get'){
  2548. //get the state of post install
  2549. $currProg = array();
  2550. if(file_exists($upgrade_progress_file)){
  2551. include($upgrade_progress_file);
  2552. if(is_array($upgrade_config[sizeof($upgrade_config)]['commit']['post_install']) && sizeof($upgrade_config[sizeof($upgrade_config)]['commit']['post_install'])>0){
  2553. foreach($upgrade_config[sizeof($upgrade_config)]['commit']['post_install'] as $k=>$v){
  2554. $currProg[$k]=$v;
  2555. }
  2556. }
  2557. }
  2558. return $currProg;
  2559. }
  2560. elseif($action=='set'){
  2561. if(!is_dir($upgrade_progress_dir)){
  2562. mkdir($upgrade_progress_dir);
  2563. }
  2564. if(file_exists($upgrade_progress_file)){
  2565. include($upgrade_progress_file);
  2566. }
  2567. else{
  2568. fopen($upgrade_progress_file, 'w+');
  2569. }
  2570. if(!is_array($upgrade_config[sizeof($upgrade_config)]['commit']['post_install'])){
  2571. $upgrade_config[sizeof($upgrade_config)]['commit']['post_install']=array();
  2572. $upgrade_config[sizeof($upgrade_config)]['commit']['post_install']['post_install'] = 'in_progress';
  2573. }
  2574. if($progArray != null && is_array($progArray)){
  2575. foreach($progArray as $key=>$val){
  2576. $upgrade_config[sizeof($upgrade_config)]['commit']['post_install'][$key]=$val;
  2577. }
  2578. }
  2579. if(is_writable($upgrade_progress_file) && write_array_to_file( "upgrade_config", $upgrade_config,
  2580. $upgrade_progress_file)) {
  2581. //writing to the file
  2582. }
  2583. }
  2584. }
  2585. function repairDBForUpgrade($execute=false,$path=''){
  2586. global $current_user, $beanFiles;
  2587. global $dictionary;
  2588. set_time_limit(3600);
  2589. $db = &DBManagerFactory::getInstance();
  2590. $sql = '';
  2591. VardefManager::clearVardef();
  2592. require_once('include/ListView/ListView.php');
  2593. foreach ($beanFiles as $bean => $file) {
  2594. require_once ($file);
  2595. $focus = new $bean ();
  2596. $sql .= $db->repairTable($focus, $execute);
  2597. }
  2598. //echo $sql;
  2599. $olddictionary = $dictionary;
  2600. unset ($dictionary);
  2601. include ('modules/TableDictionary.php');
  2602. foreach ($dictionary as $meta) {
  2603. $tablename = $meta['table'];
  2604. $fielddefs = $meta['fields'];
  2605. $indices = $meta['indices'];
  2606. $sql .= $db->repairTableParams($tablename, $fielddefs, $indices, $execute);
  2607. }
  2608. $qry_str = "";
  2609. foreach (explode("\n", $sql) as $line) {
  2610. if (!empty ($line) && substr($line, -2) != "*/") {
  2611. $line .= ";";
  2612. }
  2613. $qry_str .= $line . "\n";
  2614. }
  2615. $sql = str_replace(
  2616. array(
  2617. "\n",
  2618. '&#039;',
  2619. ),
  2620. array(
  2621. '',
  2622. "'",
  2623. ),
  2624. preg_replace('#(/\*.+?\*/\n*)#', '', $qry_str)
  2625. );
  2626. logThis("*******START EXECUTING DB UPGRADE QUERIES***************",$path);
  2627. logThis($sql,$path);
  2628. logThis("*******END EXECUTING DB UPGRADE QUERIES****************",$path);
  2629. if(!$execute){
  2630. return $sql;
  2631. }
  2632. }
  2633. /**
  2634. * upgradeUserPreferences
  2635. * This method updates the user_preferences table and sets the pages/dashlets for users
  2636. * which have ACL access to Trackers so that the Tracker dashlets are set in their user perferences
  2637. *
  2638. */
  2639. function upgradeUserPreferences() {
  2640. global $sugar_config, $sugar_version;
  2641. $uw_strings = return_module_language($GLOBALS['current_language'], 'UpgradeWizard');
  2642. $localization = new Localization();
  2643. $localeCoreDefaults = $localization->getLocaleConfigDefaults();
  2644. // check the current system wide default_locale_name_format and add it to the list if it's not there
  2645. if(empty($sugar_config['name_formats'])) {
  2646. $sugar_config['name_formats'] = $localeCoreDefaults['name_formats'];
  2647. if(!rebuildConfigFile($sugar_config, $sugar_version)) {
  2648. $errors[] = $uw_strings['ERR_UW_CONFIG_WRITE'];
  2649. }
  2650. }
  2651. $currentDefaultLocaleNameFormat = $sugar_config['default_locale_name_format'];
  2652. if ($localization->isAllowedNameFormat($currentDefaultLocaleNameFormat)) {
  2653. upgradeLocaleNameFormat($currentDefaultLocaleNameFormat);
  2654. } else {
  2655. $sugar_config['default_locale_name_format'] = $localeCoreDefaults['default_locale_name_format'];
  2656. if(!rebuildConfigFile($sugar_config, $sugar_version)) {
  2657. $errors[] = $uw_strings['ERR_UW_CONFIG_WRITE'];
  2658. }
  2659. $localization->createInvalidLocaleNameFormatUpgradeNotice();
  2660. }
  2661. $db = &DBManagerFactory::getInstance();
  2662. $result = $db->query("SELECT id FROM users where deleted = '0'");
  2663. while($row = $db->fetchByAssoc($result))
  2664. {
  2665. $current_user = new User();
  2666. $current_user->retrieve($row['id']);
  2667. // get the user's name locale format, check if it's in our list, add it if it's not, keep it as user's default
  2668. $currentUserNameFormat = $current_user->getPreference('default_locale_name_format');
  2669. if ($localization->isAllowedNameFormat($currentUserNameFormat)) {
  2670. upgradeLocaleNameFormat($currentUserNameFormat);
  2671. } else {
  2672. $current_user->setPreference('default_locale_name_format', 's f l', 0, 'global');
  2673. $current_user->savePreferencesToDB();
  2674. }
  2675. } //while
  2676. }
  2677. /**
  2678. * Checks if a locale name format is part of the default list, if not adds it to the config
  2679. * @param $name_format string a local name format string such as 's f l'
  2680. * @return bool true on successful write to config file, false on failure;
  2681. */
  2682. function upgradeLocaleNameFormat($name_format) {
  2683. global $sugar_config, $sugar_version;
  2684. $localization = new Localization();
  2685. $localeConfigDefaults = $localization->getLocaleConfigDefaults();
  2686. $uw_strings = return_module_language($GLOBALS['current_language'], 'UpgradeWizard');
  2687. if(empty($sugar_config['name_formats'])) {
  2688. $sugar_config['name_formats'] = $localeConfigDefaults['name_formats'];
  2689. if(!rebuildConfigFile($sugar_config, $sugar_version)) {
  2690. $errors[] = $uw_strings['ERR_UW_CONFIG_WRITE'];
  2691. }
  2692. }
  2693. if (!in_array($name_format, $sugar_config['name_formats'])) {
  2694. $new_config = sugarArrayMerge($sugar_config['name_formats'], array($name_format=>$name_format));
  2695. $sugar_config['name_formats'] = $new_config;
  2696. if(!rebuildConfigFile($sugar_config, $sugar_version)) {
  2697. $errors[] = $uw_strings['ERR_UW_CONFIG_WRITE'];
  2698. return false;
  2699. }
  2700. }
  2701. return true;
  2702. }
  2703. function add_custom_modules_favorites_search(){
  2704. $module_directories = scandir('modules');
  2705. foreach($module_directories as $module_dir){
  2706. if($module_dir == '.' || $module_dir == '..' || !is_dir("modules/{$module_dir}")){
  2707. continue;
  2708. }
  2709. $matches = array();
  2710. preg_match('/^[a-z0-9]{1,5}_[a-z0-9_]+$/i' , $module_dir, $matches);
  2711. // Make sure the module was created by module builder
  2712. if(empty($matches)){
  2713. continue;
  2714. }
  2715. $full_module_dir = "modules/{$module_dir}/";
  2716. $read_searchdefs_from = "{$full_module_dir}/metadata/searchdefs.php";
  2717. $read_SearchFields_from = "{$full_module_dir}/metadata/SearchFields.php";
  2718. $read_custom_SearchFields_from = "custom/{$full_module_dir}/metadata/SearchFields.php";
  2719. // Studio can possibly override this file, so we check for a custom version of it
  2720. if(file_exists("custom/{$full_module_dir}/metadata/searchdefs.php")){
  2721. $read_searchdefs_from = "custom/{$full_module_dir}/metadata/searchdefs.php";
  2722. }
  2723. if(file_exists($read_searchdefs_from) && file_exists($read_SearchFields_from)){
  2724. $found_sf1 = false;
  2725. $found_sf2 = false;
  2726. require($read_searchdefs_from);
  2727. foreach($searchdefs[$module_dir]['layout']['basic_search'] as $sf_array){
  2728. if(isset($sf_array['name']) && $sf_array['name'] == 'favorites_only'){
  2729. $found_sf1 = true;
  2730. }
  2731. }
  2732. require($read_SearchFields_from);
  2733. if(isset($searchFields[$module_dir]['favorites_only'])){
  2734. $found_sf2 = true;
  2735. }
  2736. if(!$found_sf1 && !$found_sf2){
  2737. $searchdefs[$module_dir]['layout']['basic_search']['favorites_only'] = array('name' => 'favorites_only','label' => 'LBL_FAVORITES_FILTER','type' => 'bool',);
  2738. $searchdefs[$module_dir]['layout']['advanced_search']['favorites_only'] = array('name' => 'favorites_only','label' => 'LBL_FAVORITES_FILTER','type' => 'bool',);
  2739. $searchFields[$module_dir]['favorites_only'] = array(
  2740. 'query_type'=>'format',
  2741. 'operator' => 'subquery',
  2742. 'subquery' => 'SELECT sugarfavorites.record_id FROM sugarfavorites
  2743. WHERE sugarfavorites.deleted=0
  2744. and sugarfavorites.module = \''.$module_dir.'\'
  2745. and sugarfavorites.assigned_user_id = \'{0}\'',
  2746. 'db_field'=>array('id')
  2747. );
  2748. if(!is_dir("custom/{$full_module_dir}/metadata")){
  2749. mkdir_recursive("custom/{$full_module_dir}/metadata");
  2750. }
  2751. $success_sf1 = write_array_to_file('searchdefs', $searchdefs, "custom/{$full_module_dir}/metadata/searchdefs.php");
  2752. $success_sf2 = write_array_to_file('searchFields', $searchFields, "{$full_module_dir}/metadata/SearchFields.php");
  2753. if(!$success_sf1){
  2754. logThis("add_custom_modules_favorites_search failed for searchdefs.php for {$module_dir}");
  2755. }
  2756. if(!$success_sf2){
  2757. logThis("add_custom_modules_favorites_search failed for SearchFields.php for {$module_dir}");
  2758. }
  2759. if($success_sf1 && $success_sf2){
  2760. logThis("add_custom_modules_favorites_search successfully updated searchdefs and searchFields for {$module_dir}");
  2761. }
  2762. }
  2763. }
  2764. }
  2765. }
  2766. /**
  2767. * upgradeModulesForTeamsets
  2768. *
  2769. * This method adds the team_set_id values to the module tables that have the new team_set_id column
  2770. * added through the SugarCRM 5.5.x upgrade process. It also adds the values into the team_sets and
  2771. * team_sets_teams tables.
  2772. *
  2773. * @param filter Array of modules to process; empty by default
  2774. */
  2775. function upgradeModulesForTeamsets($filter=array()) {
  2776. require('include/modules.php');
  2777. foreach($beanList as $moduleName=>$beanName) {
  2778. if(!empty($filter) && array_search($moduleName, $filter) === false) {
  2779. continue;
  2780. }
  2781. if($moduleName == 'TeamMemberships' || $moduleName == 'ForecastOpportunities'){
  2782. continue;
  2783. }
  2784. $bean = loadBean($moduleName);
  2785. if(empty($bean) ||
  2786. empty($bean->table_name)) {
  2787. continue;
  2788. }
  2789. $FieldArray = $GLOBALS['db']->helper->get_columns($bean->table_name);
  2790. if(!isset($FieldArray['team_id'])) {
  2791. continue;
  2792. }
  2793. upgradeTeamColumn($bean, 'team_id');
  2794. } //foreach
  2795. //Upgrade users table
  2796. $bean = loadBean('Users');
  2797. upgradeTeamColumn($bean, 'default_team');
  2798. $result = $GLOBALS['db']->query("SELECT id FROM teams where deleted=0");
  2799. while($row = $GLOBALS['db']->fetchByAssoc($result)) {
  2800. $teamset = new TeamSet();
  2801. $teamset->addTeams($row['id']);
  2802. }
  2803. }
  2804. /**
  2805. * upgradeTeamColumn
  2806. * Helper function to create a team_set_id column and also set team_set_id column
  2807. * to have the value of the $column_name parameter
  2808. *
  2809. * @param $bean SugarBean which we are adding team_set_id column to
  2810. * @param $column_name The name of the column containing the default team_set_id value
  2811. */
  2812. function upgradeTeamColumn($bean, $column_name) {
  2813. //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
  2814. //module that does not use the SugarObjects
  2815. if(empty($bean->field_defs['team_set_id']) && $bean->module_dir != 'Trackers'){
  2816. //at this point we could assume that since we have a team_id defined and not a team_set_id that we need to
  2817. //add that field and the corresponding relationships
  2818. $object = $bean->object_name;
  2819. $module = $bean->module_dir;
  2820. $object_name = $object;
  2821. $_object_name = strtolower($object_name);
  2822. if(!empty($GLOBALS['dictionary'][$object]['table'])){
  2823. $table_name = $GLOBALS['dictionary'][$object]['table'];
  2824. }else{
  2825. $table_name = strtolower($module);
  2826. }
  2827. $path = 'include/SugarObjects/implements/team_security/vardefs.php';
  2828. require($path);
  2829. //go through each entry in the vardefs from team_security and unset anything that is already set in the core module
  2830. //this will ensure we have the proper ordering.
  2831. $fieldDiff = array_diff_assoc($vardefs['fields'], $GLOBALS['dictionary'][$bean->object_name]['fields']);
  2832. $file = 'custom/Extension/modules/' . $bean->module_dir. '/Ext/Vardefs/teams.php';
  2833. $contents = "<?php\n";
  2834. if(!empty($fieldDiff)){
  2835. foreach($fieldDiff as $key => $val){
  2836. $contents .= "\n\$GLOBALS['dictionary']['". $object . "']['fields']['". $key . "']=" . var_export_helper($val) . ";";
  2837. }
  2838. }
  2839. $relationshipDiff = array_diff_assoc($vardefs['relationships'], $GLOBALS['dictionary'][$bean->object_name]['relationships']);
  2840. if(!empty($relationshipDiff)){
  2841. foreach($relationshipDiff as $key => $val){
  2842. $contents .= "\n\$GLOBALS['dictionary']['". $object . "']['relationships']['". $key . "']=" . var_export_helper($val) . ";";
  2843. }
  2844. }
  2845. $indexDiff = array_diff_assoc($vardefs['indices'], $GLOBALS['dictionary'][$bean->object_name]['indices']);
  2846. if(!empty($indexDiff)){
  2847. foreach($indexDiff as $key => $val){
  2848. $contents .= "\n\$GLOBALS['dictionary']['". $object . "']['indices']['". $key . "']=" . var_export_helper($val) . ";";
  2849. }
  2850. }
  2851. if( $fh = @sugar_fopen( $file, 'wt' ) )
  2852. {
  2853. fputs( $fh, $contents);
  2854. fclose( $fh );
  2855. }
  2856. //we have written out the teams.php into custom/Extension/modules/{$module_dir}/Ext/Vardefs/teams.php'
  2857. //now let's merge back into vardefs.ext.php
  2858. require_once('ModuleInstall/ModuleInstaller.php');
  2859. $mi = new ModuleInstaller();
  2860. $mi->merge_files('Ext/Vardefs/', 'vardefs.ext.php');
  2861. VardefManager::loadVardef($bean->module_dir, $bean->object_name, true);
  2862. $bean->field_defs = $GLOBALS['dictionary'][$bean->object_name]['fields'];
  2863. }
  2864. if(isset($bean->field_defs['team_set_id'])) {
  2865. //Create the team_set_id column
  2866. $FieldArray = $GLOBALS['db']->helper->get_columns($bean->table_name);
  2867. if(!isset($FieldArray['team_set_id'])) {
  2868. $GLOBALS['db']->addColumn($bean->table_name, $bean->field_defs['team_set_id']);
  2869. }
  2870. $indexArray = $GLOBALS['db']->helper->get_indices($bean->table_name);
  2871. $indexName = getValidDBName('idx_'.strtolower($bean->table_name).'_tmst_id', true, 34);
  2872. $indexDef = array(
  2873. array(
  2874. 'name' => $indexName,
  2875. 'type' => 'index',
  2876. 'fields' => array('team_set_id')
  2877. )
  2878. );
  2879. if(!isset($indexArray[$indexName])) {
  2880. $GLOBALS['db']->addIndexes($bean->table_name, $indexDef);
  2881. }
  2882. //Update the table's team_set_id column to have the same values as team_id
  2883. $GLOBALS['db']->query("UPDATE {$bean->table_name} SET team_set_id = {$column_name}");
  2884. }
  2885. }
  2886. /**
  2887. * Update the folder subscription table which confirms to the team security mechanism but
  2888. * the class SugarFolders does not extend SugarBean and is therefore never picked up by the
  2889. * upgradeModulesForTeamsets function.
  2890. */
  2891. function upgradeFolderSubscriptionsTeamSetId()
  2892. {
  2893. logThis("In upgradeFolderSubscriptionsTeamSetId()");
  2894. $query = "UPDATE folders SET team_set_id = team_id";
  2895. $result = $GLOBALS['db']->query($query);
  2896. logThis("Finished upgradeFolderSubscriptionsTeamSetId()");
  2897. }
  2898. /**
  2899. * upgradeModulesForTeam
  2900. *
  2901. * This method update the associated_user_id, name, name_2 to the private team records on teams table
  2902. * This function is used for upgrade process from 5.1.x and 5.2.x.
  2903. *
  2904. */
  2905. function upgradeModulesForTeam() {
  2906. logThis("In upgradeModulesForTeam()");
  2907. $result = $GLOBALS['db']->query("SELECT id, user_name, first_name, last_name FROM users where deleted=0");
  2908. while($row = $GLOBALS['db']->fetchByAssoc($result)) {
  2909. $results2 = $GLOBALS['db']->query("SELECT id FROM teams WHERE name = '({$row['user_name']})'");
  2910. $assoc = '';
  2911. if(!$assoc = $GLOBALS['db']->fetchByAssoc($results2)) {
  2912. //if team does not exist, then lets create the team for this user
  2913. $team = new Team();
  2914. $user = new User();
  2915. $user->retrieve($row['id']);
  2916. $team->new_user_created($user);
  2917. $team_id = $team->id;
  2918. }else{
  2919. $team_id =$assoc['id'];
  2920. }
  2921. //upgrade the team
  2922. $name = is_null($row['first_name'])?'':$row['first_name'];
  2923. $name_2 = is_null($row['last_name'])?'':$row['last_name'];
  2924. $associated_user_id = $row['id'];
  2925. //Bug 32914
  2926. //Ensure team->name is not empty by using team->name_2 if available
  2927. if(empty($name) && !empty($name_2)) {
  2928. $name = $name_2;
  2929. $name_2 = '';
  2930. }
  2931. $query = "UPDATE teams SET name = '{$name}', name_2 = '{$name_2}', associated_user_id = '{$associated_user_id}' WHERE id = '{$team_id}'";
  2932. $GLOBALS['db']->query($query);
  2933. } //while
  2934. //Update the team_set_id and default_team columns
  2935. $ce_to_pro_or_ent = (isset($_SESSION['upgrade_from_flavor']) && ($_SESSION['upgrade_from_flavor'] == 'SugarCE to SugarPro' || $_SESSION['upgrade_from_flavor'] == 'SugarCE to SugarEnt' || $_SESSION['upgrade_from_flavor'] == 'SugarCE to SugarCorp' || $_SESSION['upgrade_from_flavor'] == 'SugarCE to SugarUlt'));
  2936. //Update team_set_id
  2937. if($ce_to_pro_or_ent) {
  2938. $GLOBALS['db']->query("update users set team_set_id = (select teams.id from teams where teams.associated_user_id = users.id)");
  2939. $GLOBALS['db']->query("update users set default_team = (select teams.id from teams where teams.associated_user_id = users.id)");
  2940. }
  2941. }
  2942. function addNewSystemTabsFromUpgrade($from_dir){
  2943. global $path;
  2944. if(isset($_SESSION['upgrade_from_flavor'])){
  2945. //check to see if there are any new files that need to be added to systems tab
  2946. //retrieve old modules list
  2947. logThis('check to see if new modules exist',$path);
  2948. $oldModuleList = array();
  2949. $newModuleList = array();
  2950. include($from_dir.'/include/modules.php');
  2951. $oldModuleList = $moduleList;
  2952. include('include/modules.php');
  2953. $newModuleList = $moduleList;
  2954. //include tab controller
  2955. require_once('modules/MySettings/TabController.php');
  2956. $newTB = new TabController();
  2957. //make sure new modules list has a key we can reference directly
  2958. $newModuleList = $newTB->get_key_array($newModuleList);
  2959. $oldModuleList = $newTB->get_key_array($oldModuleList);
  2960. //iterate through list and remove commonalities to get new modules
  2961. foreach ($newModuleList as $remove_mod){
  2962. if(in_array($remove_mod, $oldModuleList)){
  2963. unset($newModuleList[$remove_mod]);
  2964. }
  2965. }
  2966. //new modules list now has left over modules which are new to this install, so lets add them to the system tabs
  2967. logThis('new modules to add are '.var_export($newModuleList,true),$path);
  2968. if(!empty($newModuleList))
  2969. {
  2970. //grab the existing system tabs
  2971. $tabs = $newTB->get_system_tabs();
  2972. //add the new tabs to the array
  2973. foreach($newModuleList as $nm ){
  2974. $tabs[$nm] = $nm;
  2975. }
  2976. $newTB->set_system_tabs($tabs);
  2977. }
  2978. logThis('module tabs updated',$path);
  2979. }
  2980. }
  2981. /**
  2982. * fix_dropdown_list
  2983. * This method attempts to fix dropdown lists that were incorrectly named.
  2984. * There were versions of SugarCRM that did not enforce naming convention rules
  2985. * for the dropdown list field name. This method attempts to resolve that by
  2986. * fixing the language files that may have been affected and then updating the
  2987. * fields_meta_data table accordingly. It also refreshes any vardefs that may
  2988. * have been affected.
  2989. *
  2990. */
  2991. function fix_dropdown_list() {
  2992. if(file_exists('custom/include/language')) {
  2993. $files = array();
  2994. $affected_modules = array();
  2995. $affected_keys = array();
  2996. getFiles($files, 'custom/include/language', '/\.php$/i');
  2997. foreach($files as $file) {
  2998. if(file_exists($file . '.bak')) {
  2999. $bak_mod_time = filemtime($file . '.bak');
  3000. $php_mod_time = filemtime($file);
  3001. //We're saying if the .php file was modified 30 seconds no more than php.bak file then we
  3002. //run these additional cleanup checks
  3003. if($php_mod_time - $bak_mod_time < 30) {
  3004. $app_list_strings = array();
  3005. $GLOBALS['app_list_strings'] = array();
  3006. require($file . '.bak');
  3007. $bak_app_list_strings = array_merge($app_list_strings, $GLOBALS['app_list_strings']);
  3008. $app_list_strings = array();
  3009. $GLOBALS['app_list_strings'] = array();
  3010. require($file);
  3011. $php_app_list_strings = array_merge($app_list_strings, $GLOBALS['app_list_strings']);
  3012. //Get the file contents
  3013. $contents = file_get_contents($file);
  3014. //Now simulate a fix for the file before we compare w/ the .php file
  3015. //we also append to the $contents
  3016. foreach($bak_app_list_strings as $key=>$entry) {
  3017. if(preg_match('/([^A-Za-z_])/', $key, $matches) && is_array($entry)) {
  3018. $new_key = preg_replace('/[^A-Za-z_]/', '_', $key);
  3019. $bak_app_list_strings[$new_key] = $bak_app_list_strings[$key];
  3020. unset($bak_app_list_strings[$key]);
  3021. //Now if the entry doesn't exists in the .php file, then add to contents
  3022. if(!isset($php_app_list_strings[$new_key])) {
  3023. $contents .= "\n\$GLOBALS['app_list_strings']['{$new_key}'] = " . var_export_helper($bak_app_list_strings[$new_key]) . ";";
  3024. }
  3025. } //if
  3026. } //foreach
  3027. //Now load the .php file to do the comparison
  3028. foreach($php_app_list_strings as $key=>$entry) {
  3029. if(isset($bak_app_list_strings[$key])) {
  3030. $diff = array_diff($bak_app_list_strings[$key], $entry);
  3031. if(!empty($diff)) {
  3032. //There is a difference, so copy the $bak_app_list_strings version into the .php file
  3033. $contents .= "\n\$GLOBALS['app_list_strings']['{$key}'] = " . var_export_helper($bak_app_list_strings[$key]) . ";";
  3034. } //if
  3035. } //if
  3036. } //foreach
  3037. //Now write out the file contents
  3038. //Create backup just in case
  3039. copy($file, $file . '.php_bak');
  3040. $fp = @sugar_fopen($file, 'w');
  3041. if($fp) {
  3042. fwrite($fp, $contents);
  3043. fclose($fp);
  3044. } else {
  3045. $GLOBALS['log']->error("Unable to update file contents in fix_dropdown_list for {$file}");
  3046. } //if-else
  3047. }
  3048. }
  3049. unset($GLOBALS['app_strings']);
  3050. unset($GLOBALS['app_list_strings']);
  3051. $app_list_strings = array();
  3052. require($file);
  3053. $touched = false;
  3054. $contents = file_get_contents($file);
  3055. if ( !isset($GLOBALS['app_list_strings']) ) {
  3056. $GLOBALS['app_list_strings'] = $app_list_strings;
  3057. }
  3058. else {
  3059. $GLOBALS['app_list_strings'] = array_merge($app_list_strings, $GLOBALS['app_list_strings']);
  3060. }
  3061. if(isset($GLOBALS['app_list_strings']) && is_array($GLOBALS['app_list_strings'])) {
  3062. foreach($GLOBALS['app_list_strings'] as $key=>$entry) {
  3063. if(preg_match('/([^A-Za-z_])/', $key, $matches) && is_array($entry)) {
  3064. $result = $GLOBALS['db']->query("SELECT custom_module FROM fields_meta_data WHERE ext1 = '{$key}'");
  3065. if(!empty($result)) {
  3066. while($row = $GLOBALS['db']->fetchByAssoc($result)) {
  3067. $custom_module = $row['custom_module'];
  3068. if(!empty($GLOBALS['beanList'][$custom_module])) {
  3069. $affected_modules[$custom_module] = $GLOBALS['beanList'][$custom_module];
  3070. }
  3071. } //while
  3072. }
  3073. //Replace all invalid characters with '_' character
  3074. $new_key = preg_replace('/[^A-Za-z_]/', '_', $key);
  3075. $affected_keys[$key] = $new_key;
  3076. $GLOBALS['app_list_strings'][$new_key] = $GLOBALS['app_list_strings'][$key];
  3077. unset($GLOBALS['app_list_strings'][$key]);
  3078. $pattern_match = "/(\[\s*\'{$key}\'\s*\])/";
  3079. $new_key = "['{$new_key}']";
  3080. $out = preg_replace($pattern_match, $new_key, $contents);
  3081. $contents = $out;
  3082. $touched = true;
  3083. } //if
  3084. } //foreach
  3085. //This is a check for g => h instances where the file contents were incorrectly written
  3086. //and also fixes the scenario where via a UI upgrade, the app_list_strings were incorrectly
  3087. //merged with app_list_strings variables declared elsewhere
  3088. if(!$touched) {
  3089. if(preg_match('/\$GLOBALS\s*\[\s*[\"|\']app_list_strings[\"|\']\s*\]\s*=\s*array\s*\(/', $contents)) {
  3090. //Now also remove all the non-custom labels that were added
  3091. if(preg_match('/language\/([^\.]+)\.lang\.php$/', $file, $matches)) {
  3092. $language = $matches[1];
  3093. $app_list_strings = array();
  3094. if(file_exists("include/language/$language.lang.php")) {
  3095. include("include/language/$language.lang.php");
  3096. }
  3097. if(file_exists("include/language/$language.lang.override.php")) {
  3098. $app_list_strings = _mergeCustomAppListStrings("include/language/$language.lang.override.php" , $app_list_strings) ;
  3099. }
  3100. if(file_exists("custom/application/Ext/Language/$language.ext.lang.php")) {
  3101. $app_list_strings = _mergeCustomAppListStrings("custom/application/Ext/Language/$language.ext.lang.php" , $app_list_strings) ;
  3102. }
  3103. if(file_exists("custom/application/Ext/Language/$language.lang.ext.php")) {
  3104. $app_list_strings = _mergeCustomAppListStrings("custom/application/Ext/Language/$language.lang.ext.php" , $app_list_strings) ;
  3105. }
  3106. $all_non_custom_include_language_strings = $app_strings;
  3107. $all_non_custom_include_language_list_strings = $app_list_strings;
  3108. $unset_keys = array();
  3109. if(!empty($GLOBALS['app_list_strings'])) {
  3110. foreach($GLOBALS['app_list_strings'] as $key=>$value) {
  3111. $diff = array();
  3112. if(isset($all_non_custom_include_language_list_strings[$key])) {
  3113. $diff = array_diff($all_non_custom_include_language_list_strings[$key], $GLOBALS['app_list_strings'][$key]);
  3114. }
  3115. if(!empty($all_non_custom_include_language_list_strings[$key]) && empty($diff)) {
  3116. $unset_keys[] = $key;
  3117. }
  3118. }
  3119. }
  3120. foreach($unset_keys as $key) {
  3121. unset($GLOBALS['app_list_strings'][$key]);
  3122. }
  3123. if(!empty($GLOBALS['app_strings'])) {
  3124. foreach($GLOBALS['app_strings'] as $key=>$value) {
  3125. if(!empty($all_non_custom_include_language_strings[$key])) {
  3126. unset($GLOBALS['app_strings'][$key]);
  3127. }
  3128. }
  3129. }
  3130. } //if(preg_match...)
  3131. $out = "<?php \n";
  3132. if(!empty($GLOBALS['app_strings'])) {
  3133. foreach($GLOBALS['app_strings'] as $key=>$entry) {
  3134. $out .= "\n\$GLOBALS['app_strings']['$key']=" . var_export_helper($entry) . ";";
  3135. }
  3136. }
  3137. foreach($GLOBALS['app_list_strings'] as $key=>$entry) {
  3138. $out .= "\n\$GLOBALS['app_list_strings']['$key']=" . var_export_helper($entry) . ";";
  3139. } //foreach
  3140. $touched = true;
  3141. } //if(preg_match...)
  3142. } //if(!$touched)
  3143. if($touched) {
  3144. //Create a backup just in case
  3145. copy($file, $file . '.bak');
  3146. $fp = @sugar_fopen($file, 'w');
  3147. if($fp) {
  3148. fwrite($fp, $out);
  3149. fclose($fp);
  3150. } else {
  3151. //If we can't update the file, just return
  3152. $GLOBALS['log']->error("Unable to update file contents in fix_dropdown_list.");
  3153. return;
  3154. }
  3155. } //if($touched)
  3156. } //if
  3157. } //foreach($files)
  3158. //Update db entries (the order matters here... need to process database changes first)
  3159. if(!empty($affected_keys)) {
  3160. foreach($affected_keys as $old_key=>$new_key) {
  3161. $GLOBALS['db']->query("UPDATE fields_meta_data SET ext1 = '{$new_key}' WHERE ext1 = '{$old_key}'");
  3162. }
  3163. }
  3164. //Update vardef files for affected modules
  3165. if(!empty($affected_modules)) {
  3166. foreach($affected_modules as $module=>$object) {
  3167. VardefManager::refreshVardefs($module, $object);
  3168. }
  3169. }
  3170. }
  3171. }
  3172. function update_iframe_dashlets(){
  3173. require_once(sugar_cached('dashlets/dashlets.php'));
  3174. $db = DBManagerFactory::getInstance();
  3175. $query = "SELECT id, contents, assigned_user_id FROM user_preferences WHERE deleted = 0 AND category = 'Home'";
  3176. $result = $db->query($query, true, "Unable to update new default dashlets! ");
  3177. while ($row = $db->fetchByAssoc($result)) {
  3178. $content = unserialize(base64_decode($row['contents']));
  3179. $assigned_user_id = $row['assigned_user_id'];
  3180. $record_id = $row['id'];
  3181. $current_user = new User();
  3182. $current_user->retrieve($row['assigned_user_id']);
  3183. if(!empty($content['dashlets']) && !empty($content['pages'])){
  3184. $originalDashlets = $content['dashlets'];
  3185. foreach($originalDashlets as $key => $ds){
  3186. if(!empty($ds['options']['url']) && stristr($ds['options']['url'],'http://www.sugarcrm.com/crm/product/gopro')){
  3187. unset($originalDashlets[$key]);
  3188. }
  3189. }
  3190. $current_user->setPreference('dashlets', $originalDashlets, 0, 'Home');
  3191. }
  3192. }
  3193. }
  3194. /**
  3195. * convertImageToText
  3196. * @deprecated
  3197. * This method attempts to convert date type image to text on Microsoft SQL Server.
  3198. * This method could NOT be used in any other type of datebases.
  3199. */
  3200. function convertImageToText($table_name,$column_name){
  3201. $set_lang = "SET LANGUAGE us_english";
  3202. $GLOBALS['db']->query($set_lang);
  3203. if($GLOBALS['db']->lastError()){
  3204. logThis('An error occurred when performing this query-->'.$set_lang);
  3205. }
  3206. $q="SELECT data_type
  3207. FROM INFORMATION_SCHEMA.Tables T JOIN INFORMATION_SCHEMA.Columns C
  3208. ON T.TABLE_NAME = C.TABLE_NAME where T.TABLE_NAME = '$table_name' and C.COLUMN_NAME = '$column_name'";
  3209. $res= $GLOBALS['db']->query($q);
  3210. if($GLOBALS['db']->lastError()){
  3211. logThis('An error occurred when performing this query-->'.$q);
  3212. }
  3213. $row= $GLOBALS['db']->fetchByAssoc($res);
  3214. if(trim(strtolower($row['data_type'])) == 'image'){
  3215. $addContent_temp = "alter table {$table_name} add {$column_name}_temp text null";
  3216. $GLOBALS['db']->query($addContent_temp);
  3217. if($GLOBALS['db']->lastError()){
  3218. logThis('An error occurred when performing this query-->'.$addContent_temp);
  3219. }
  3220. $qN = "select count=datalength({$column_name}), id, {$column_name} from {$table_name}";
  3221. $result = $GLOBALS['db']->query($qN);
  3222. while($row = $GLOBALS['db']->fetchByAssoc($result)){
  3223. if($row['count'] >8000){
  3224. $contentLength = $row['count'];
  3225. $start = 1;
  3226. $next=8000;
  3227. $convertedContent = '';
  3228. while($contentLength >0){
  3229. $stepsQuery = "select cont=convert(varchar(max), convert(varbinary(8000), substring({$column_name},{$start},{$next}))) from {$table_name} where id= '{$row['id']}'";
  3230. $steContQ = $GLOBALS['db']->query($stepsQuery);
  3231. if($GLOBALS['db']->lastError()){
  3232. logThis('An error occurred when performing this query-->'.$stepsQuery);
  3233. }
  3234. $stepCont = $GLOBALS['db']->fetchByAssoc($steContQ);
  3235. if(isset($stepCont['cont'])){
  3236. $convertedContent = $convertedContent.$stepCont['cont'];
  3237. }
  3238. $start = $start+$next;
  3239. $contentLength = $contentLength - $next;
  3240. }
  3241. $addContentDataText="update {$table_name} set {$column_name}_temp = '{$convertedContent}' where id= '{$row['id']}'";
  3242. $GLOBALS['db']->query($addContentDataText);
  3243. if($GLOBALS['db']->lastError()){
  3244. logThis('An error occurred when performing this query-->'.$addContentDataText);
  3245. }
  3246. }
  3247. else{
  3248. $addContentDataText="update {$table_name} set {$column_name}_temp =
  3249. convert(varchar(max), convert(varbinary(8000), {$column_name})) where id= '{$row['id']}'";
  3250. $GLOBALS['db']->query($addContentDataText);
  3251. if($GLOBALS['db']->lastError()){
  3252. logThis('An error occurred when performing this query-->'.$addContentDataText);
  3253. }
  3254. }
  3255. }
  3256. //drop the contents now and change contents_temp to contents
  3257. $dropColumn = "alter table {$table_name} drop column {$column_name}";
  3258. $GLOBALS['db']->query($dropColumn);
  3259. if($GLOBALS['db']->lastError()){
  3260. logThis('An error occurred when performing this query-->'.$dropColumn);
  3261. }
  3262. $changeColumnName = "EXEC sp_rename '{$table_name}.[{$column_name}_temp]','{$column_name}','COLUMN'";
  3263. $GLOBALS['db']->query($changeColumnName);
  3264. if($GLOBALS['db']->lastError()){
  3265. logThis('An error occurred when performing this query-->'.$changeColumnName);
  3266. }
  3267. }
  3268. }
  3269. /**
  3270. * clearHelpFiles
  3271. * This method attempts to delete all English inline help files.
  3272. * This method was introduced by 5.5.0RC2.
  3273. */
  3274. function clearHelpFiles(){
  3275. $modulePath = clean_path(getcwd() . '/modules');
  3276. $allHelpFiles = array();
  3277. getFiles($allHelpFiles, $modulePath, "/en_us.help.*/");
  3278. foreach( $allHelpFiles as $the_file ){
  3279. if( is_file( $the_file ) ){
  3280. unlink( $the_file );
  3281. logThis("Deleted file: $the_file");
  3282. }
  3283. }
  3284. }
  3285. /**
  3286. * upgradeDateTimeFields
  3287. *
  3288. * This method came from bug: 39757 where the date_end field is a date field and not a datetime field
  3289. * which prevents you from performing timezone offset calculations once the data has been saved.
  3290. *
  3291. * @param path String location to log file, empty by default
  3292. */
  3293. function upgradeDateTimeFields($path)
  3294. {
  3295. //bug: 39757
  3296. global $db;
  3297. $meetingsSql = "UPDATE meetings SET date_end = ".$db->convert("date_start", 'add_time', array('duration_hours', 'duration_minutes'));
  3298. $callsSql = "UPDATE calls SET date_end = ".$db->convert("date_start", 'add_time', array('duration_hours', 'duration_minutes'));
  3299. logThis('upgradeDateTimeFields Meetings SQL:' . $meetingsSql, $path);
  3300. $db->query($meetingsSql);
  3301. logThis('upgradeDateTimeFields Calls SQL:' . $callsSql, $path);
  3302. $db->query($callsSql);
  3303. }
  3304. /**
  3305. * upgradeDocumentTypeFields
  3306. *
  3307. */
  3308. function upgradeDocumentTypeFields($path){
  3309. //bug: 39757
  3310. global $db;
  3311. $documentsSql = "UPDATE documents SET doc_type = 'Sugar' WHERE doc_type IS NULL";
  3312. $meetingsSql = "UPDATE meetings SET type = 'Sugar' WHERE type IS NULL";
  3313. logThis('upgradeDocumentTypeFields Documents SQL:' . $documentsSql, $path);
  3314. $db->query($documentsSql);
  3315. logThis('upgradeDocumentTypeFields Meetings SQL:' . $meetingsSql, $path);
  3316. $db->query($meetingsSql);
  3317. }
  3318. /**
  3319. * merge_config_si_settings
  3320. * This method checks for the presence of a config_si.php file and, if found, merges the configuration
  3321. * settings from the config_si.php file into config.php. If a config_si_location parameter value is not
  3322. * supplied it will attempt to discover the config_si.php file location from where the executing script
  3323. * was invoked.
  3324. *
  3325. * @param write_to_upgrade_log boolean optional value to write to the upgradeWizard.log file
  3326. * @param config_location String optional value to config.php file location
  3327. * @param config_si_location String optional value to config_si.php file location
  3328. * @param path String file of the location of log file to write to
  3329. * @return boolean value indicating whether or not a merge was attempted with config_si.php file
  3330. */
  3331. function merge_config_si_settings($write_to_upgrade_log=false, $config_location='', $config_si_location='', $path='')
  3332. {
  3333. if(!empty($config_location) && !file_exists($config_location))
  3334. {
  3335. if($write_to_upgrade_log)
  3336. {
  3337. logThis('config.php file specified in ' . $config_si_location . ' could not be found. Skip merging', $path);
  3338. }
  3339. return false;
  3340. } else if(empty($config_location)) {
  3341. global $argv;
  3342. //We are assuming this is from the silentUpgrade scripts so argv[3] will point to SugarCRM install location
  3343. if(isset($argv[3]) && is_dir($argv[3]))
  3344. {
  3345. $config_location = $argv[3] . DIRECTORY_SEPARATOR . 'config.php';
  3346. }
  3347. }
  3348. //If config_location is still empty or if the file cannot be found, skip merging
  3349. if(empty($config_location) || !file_exists($config_location))
  3350. {
  3351. if($write_to_upgrade_log)
  3352. {
  3353. logThis('config.php file at (' . $config_location . ') could not be found. Skip merging.', $path);
  3354. }
  3355. return false;
  3356. } else {
  3357. if($write_to_upgrade_log)
  3358. {
  3359. logThis('Loading config.php file at (' . $config_location . ') for merging.', $path);
  3360. }
  3361. include($config_location);
  3362. if(empty($sugar_config))
  3363. {
  3364. if($write_to_upgrade_log)
  3365. {
  3366. logThis('config.php contents are empty. Skip merging.', $path);
  3367. }
  3368. return false;
  3369. }
  3370. }
  3371. if(!empty($config_si_location) && !file_exists($config_si_location))
  3372. {
  3373. if($write_to_upgrade_log)
  3374. {
  3375. logThis('config_si.php file specified in ' . $config_si_location . ' could not be found. Skip merging', $path);
  3376. }
  3377. return false;
  3378. } else if(empty($config_si_location)) {
  3379. if(isset($argv[0]) && is_file($argv[0]))
  3380. {
  3381. $php_file = $argv[0];
  3382. $p_info = pathinfo($php_file);
  3383. $php_dir = (isset($p_info['dirname']) && $p_info['dirname'] != '.') ? $p_info['dirname'] . DIRECTORY_SEPARATOR : '';
  3384. $config_si_location = $php_dir . 'config_si.php';
  3385. }
  3386. }
  3387. //If config_si_location is still empty or if the file cannot be found, skip merging
  3388. if(empty($config_si_location) || !file_exists($config_si_location))
  3389. {
  3390. if($write_to_upgrade_log)
  3391. {
  3392. logThis('config_si.php file at (' . $config_si_location . ') could not be found. Skip merging.', $path);
  3393. }
  3394. return false;
  3395. } else {
  3396. if($write_to_upgrade_log)
  3397. {
  3398. logThis('Loading config_si.php file at (' . $config_si_location . ') for merging.', $path);
  3399. }
  3400. include($config_si_location);
  3401. if(empty($sugar_config_si))
  3402. {
  3403. if($write_to_upgrade_log)
  3404. {
  3405. logThis('config_si.php contents are empty. Skip merging.', $path);
  3406. }
  3407. return false;
  3408. }
  3409. }
  3410. //Now perform the merge operation
  3411. $modified = false;
  3412. foreach($sugar_config_si as $key=>$value)
  3413. {
  3414. if(!preg_match('/^setup_/', $key) && !isset($sugar_config[$key]))
  3415. {
  3416. if($write_to_upgrade_log)
  3417. {
  3418. logThis('Merge key (' . $key . ') with value (' . $value . ')', $path);
  3419. }
  3420. $sugar_config[$key] = $value;
  3421. $modified = true;
  3422. }
  3423. }
  3424. if($modified)
  3425. {
  3426. if($write_to_upgrade_log)
  3427. {
  3428. logThis('Update config.php file with new values', $path);
  3429. }
  3430. if(!write_array_to_file("sugar_config", $sugar_config, $config_location)) {
  3431. if($write_to_upgrade_log)
  3432. {
  3433. logThis('*** ERROR: could not write to config.php', $path);
  3434. }
  3435. return false;
  3436. }
  3437. } else {
  3438. if($write_to_upgrade_log)
  3439. {
  3440. logThis('config.php values are in sync with config_si.php values. Skipped merging.');
  3441. }
  3442. return false;
  3443. }
  3444. if($write_to_upgrade_log)
  3445. {
  3446. logThis('End merge_config_si_settings', $path);
  3447. }
  3448. return true;
  3449. }
  3450. /**
  3451. * upgrade_connectors
  3452. *
  3453. * This function handles support for upgrading connectors it is invoked from both end.php and silentUpgrade_step2.php
  3454. *
  3455. */
  3456. function upgrade_connectors() {
  3457. require_once('include/connectors/utils/ConnectorUtils.php');
  3458. if(!ConnectorUtils::updateMetaDataFiles()) {
  3459. $GLOBALS['log']->fatal('Cannot update metadata files for connectors');
  3460. }
  3461. //Delete the custom connectors.php file if it exists so that it may be properly rebuilt
  3462. if(file_exists('custom/modules/Connectors/metadata/connectors.php'))
  3463. {
  3464. unlink('custom/modules/Connectors/metadata/connectors.php');
  3465. }
  3466. }
  3467. /**
  3468. * Enable the InsideView connector for the four default modules.
  3469. */
  3470. function upgradeEnableInsideViewConnector($path='')
  3471. {
  3472. logThis('Begin upgradeEnableInsideViewConnector', $path);
  3473. // Load up the existing mapping and hand it to the InsideView connector to have it setup the correct logic hooks
  3474. $mapFile = 'modules/Connectors/connectors/sources/ext/rest/insideview/mapping.php';
  3475. if ( file_exists('custom/'.$mapFile) ) {
  3476. logThis('Found CUSTOM mappings', $path);
  3477. require('custom/'.$mapFile);
  3478. } else {
  3479. logThis('Used default mapping', $path);
  3480. require($mapFile);
  3481. }
  3482. require_once('include/connectors/sources/SourceFactory.php');
  3483. $source = SourceFactory::getSource('ext_rest_insideview');
  3484. // $mapping is brought in from the mapping.php file above
  3485. $source->saveMappingHook($mapping);
  3486. require_once('include/connectors/utils/ConnectorUtils.php');
  3487. ConnectorUtils::installSource('ext_rest_insideview');
  3488. // Now time to set the various modules to active, because this part ignores the default config
  3489. require(CONNECTOR_DISPLAY_CONFIG_FILE);
  3490. // $modules_sources come from that config file
  3491. foreach ( $source->allowedModuleList as $module ) {
  3492. $modules_sources[$module]['ext_rest_insideview'] = 'ext_rest_insideview';
  3493. }
  3494. if(!write_array_to_file('modules_sources', $modules_sources, CONNECTOR_DISPLAY_CONFIG_FILE)) {
  3495. //Log error and return empty array
  3496. logThis("Cannot write \$modules_sources to " . CONNECTOR_DISPLAY_CONFIG_FILE,$path);
  3497. }
  3498. logThis('End upgradeEnableInsideViewConnector', $path);
  3499. }
  3500. function repair_long_relationship_names($path='')
  3501. {
  3502. logThis("Begin repair_long_relationship_names", $path);
  3503. require_once 'modules/ModuleBuilder/parsers/relationships/DeployedRelationships.php' ;
  3504. $GLOBALS['mi_remove_tables'] = false;
  3505. $touched = array();
  3506. foreach($GLOBALS['moduleList'] as $module)
  3507. {
  3508. $relationships = new DeployedRelationships ($module) ;
  3509. foreach($relationships->getRelationshipList() as $rel_name)
  3510. {
  3511. if (strlen($rel_name) > 27 && empty($touched[$rel_name]))
  3512. {
  3513. logThis("Rebuilding relationship fields for $rel_name", $path);
  3514. $touched[$rel_name] = true;
  3515. $rel_obj = $relationships->get($rel_name);
  3516. $rel_obj->setReadonly(false);
  3517. $relationships->delete($rel_name);
  3518. $relationships->save();
  3519. $relationships->add($rel_obj);
  3520. $relationships->save();
  3521. $relationships->build () ;
  3522. }
  3523. }
  3524. }
  3525. logThis("End repair_long_relationship_names", $path);
  3526. }
  3527. function removeSilentUpgradeVarsCache(){
  3528. global $silent_upgrade_vars_loaded;
  3529. $cacheFileDir = "{$GLOBALS['sugar_config']['cache_dir']}/silentUpgrader";
  3530. $cacheFile = "{$cacheFileDir}/silentUpgradeCache.php";
  3531. if(file_exists($cacheFile)){
  3532. unlink($cacheFile);
  3533. }
  3534. $silent_upgrade_vars_loaded = array(); // Set to empty to reset it
  3535. return true;
  3536. }
  3537. function loadSilentUpgradeVars(){
  3538. global $silent_upgrade_vars_loaded;
  3539. if(empty($silent_upgrade_vars_loaded)){
  3540. $cacheFile = "{$GLOBALS['sugar_config']['cache_dir']}/silentUpgrader/silentUpgradeCache.php";
  3541. // We have no pre existing vars
  3542. if(!file_exists($cacheFile)){
  3543. // Set the vars array so it's loaded
  3544. $silent_upgrade_vars_loaded = array('vars' => array());
  3545. }
  3546. else{
  3547. require_once($cacheFile);
  3548. $silent_upgrade_vars_loaded = $silent_upgrade_vars_cache;
  3549. }
  3550. }
  3551. return true;
  3552. }
  3553. function writeSilentUpgradeVars(){
  3554. global $silent_upgrade_vars_loaded;
  3555. if(empty($silent_upgrade_vars_loaded)){
  3556. return false; // You should have set some values before trying to write the silent upgrade vars
  3557. }
  3558. $cacheFileDir = "{$GLOBALS['sugar_config']['cache_dir']}/silentUpgrader";
  3559. $cacheFile = "{$cacheFileDir}/silentUpgradeCache.php";
  3560. require_once('include/dir_inc.php');
  3561. if(!mkdir_recursive($cacheFileDir)){
  3562. return false;
  3563. }
  3564. require_once('include/utils/file_utils.php');
  3565. if(!write_array_to_file('silent_upgrade_vars_cache', $silent_upgrade_vars_loaded, $cacheFile, 'w')){
  3566. global $path;
  3567. logThis("WARNING: writeSilentUpgradeVars could not write to {$cacheFile}", $path);
  3568. return false;
  3569. }
  3570. return true;
  3571. }
  3572. function setSilentUpgradeVar($var, $value){
  3573. if(!loadSilentUpgradeVars()){
  3574. return false;
  3575. }
  3576. global $silent_upgrade_vars_loaded;
  3577. $silent_upgrade_vars_loaded['vars'][$var] = $value;
  3578. return true;
  3579. }
  3580. function getSilentUpgradeVar($var){
  3581. if(!loadSilentUpgradeVars()){
  3582. return false;
  3583. }
  3584. global $silent_upgrade_vars_loaded;
  3585. if(!isset($silent_upgrade_vars_loaded['vars'][$var])){
  3586. return null;
  3587. }
  3588. else{
  3589. return $silent_upgrade_vars_loaded['vars'][$var];
  3590. }
  3591. }
  3592. /**
  3593. * add_unified_search_to_custom_modules_vardefs
  3594. *
  3595. * This method calls the repair code to remove the unified_search_modules.php fiel
  3596. *
  3597. */
  3598. function add_unified_search_to_custom_modules_vardefs()
  3599. {
  3600. if(file_exists($cachefile = sugar_cached('modules/unified_search_modules.php')))
  3601. {
  3602. unlink($cachefile);
  3603. }
  3604. }
  3605. /**
  3606. * change from using the older SugarCache in 6.1 and below to the new one in 6.2
  3607. */
  3608. function upgradeSugarCache($file)
  3609. {
  3610. global $sugar_config;
  3611. $cacheUploadUpgradesTemp = mk_temp_dir(sugar_cached('upgrades/temp'));
  3612. unzip($file, $cacheUploadUpgradesTemp);
  3613. if(!file_exists(clean_path("{$cacheUploadUpgradesTemp}/manifest.php"))) {
  3614. logThis("*** ERROR: no manifest file detected while bootstraping upgrade wizard files!");
  3615. return;
  3616. } else {
  3617. include(clean_path("{$cacheUploadUpgradesTemp}/manifest.php"));
  3618. }
  3619. $from_dir = "{$cacheUploadUpgradesTemp}/{$manifest['copy_files']['from_dir']}";
  3620. $allFiles = array();
  3621. if(file_exists("$from_dir/include/SugarCache")) {
  3622. $allFiles = findAllFiles("$from_dir/include/SugarCache", $allFiles);
  3623. }
  3624. if(file_exists("$from_dir/include/database")) {
  3625. $allFiles = findAllFiles("$from_dir/include/database", $allFiles);
  3626. }
  3627. if(file_exists("$from_dir/include/utils/external_cache.php")) {
  3628. $allFiles[] = "$from_dir/include/utils/external_cache.php";
  3629. }
  3630. if(file_exists("$from_dir/include/utils/sugar_file_utils.php")) {
  3631. $allFiles[] = "$from_dir/include/utils/sugar_file_utils.php";
  3632. }
  3633. if(file_exists("$from_dir/include/utils/sugar_file_utils.php")) {
  3634. $allFiles[] = "$from_dir/include/utils/sugar_file_utils.php";
  3635. }
  3636. foreach($allFiles as $k => $file) {
  3637. $destFile = str_replace($from_dir."/", "", $file);
  3638. if(!is_dir(dirname($destFile))) {
  3639. mkdir_recursive(dirname($destFile)); // make sure the directory exists
  3640. }
  3641. if ( stristr($file,'uw_main.tpl') )
  3642. logThis('Skipping "'.$file.'" - file copy will during commit step.');
  3643. else {
  3644. logThis('updating UpgradeWizard code: '.$destFile);
  3645. copy_recursive($file, $destFile);
  3646. }
  3647. }
  3648. }
  3649. /**
  3650. * upgradeDisplayedTabsAndSubpanels
  3651. *
  3652. * @param $version String value of current system version (pre upgrade)
  3653. */
  3654. function upgradeDisplayedTabsAndSubpanels($version)
  3655. {
  3656. if($version < '620')
  3657. {
  3658. logThis('start upgrading system displayed tabs and subpanels');
  3659. require_once('modules/MySettings/TabController.php');
  3660. $tc = new TabController();
  3661. //grab the existing system tabs
  3662. $tabs = $tc->get_tabs_system();
  3663. //add Calls, Meetings, Tasks, Notes, Prospects (Targets) and ProspectLists (Target Lists)
  3664. //to displayed tabs unless explicitly set to hidden
  3665. $modules_to_add = array('Calls', 'Meetings', 'Tasks', 'Notes', 'Prospects', 'ProspectLists');
  3666. $added_tabs = array();
  3667. foreach($modules_to_add as $module)
  3668. {
  3669. $tabs[0][$module] = $module;
  3670. $added_tabs[] = $module;
  3671. }
  3672. logThis('calling set_system_tabs on TabController to add tabs: ' . var_export($added_tabs, true));
  3673. $tc->set_system_tabs($tabs[0]);
  3674. logThis('finish upgrading system displayed tabs and subpanels');
  3675. }
  3676. }
  3677. /**
  3678. * unlinkUpgradeFiles
  3679. * This is a helper function to clean up
  3680. *
  3681. * @param $version String value of current system version (pre upgrade)
  3682. */
  3683. function unlinkUpgradeFiles($version)
  3684. {
  3685. if(!isset($version))
  3686. {
  3687. return;
  3688. }
  3689. //First check if we even have the scripts_for_patch/files_to_remove directory
  3690. require_once('modules/UpgradeWizard/UpgradeRemoval.php');
  3691. /*
  3692. if(empty($_SESSION['unzip_dir']))
  3693. {
  3694. global $sugar_config;
  3695. $base_upgrade_dir = $sugar_config['upload_dir'] . "/upgrades";
  3696. $base_tmp_upgrade_dir = "$base_upgrade_dir/temp";
  3697. $_SESSION['unzip_dir'] = mk_temp_dir( $base_tmp_upgrade_dir );
  3698. }
  3699. */
  3700. if(isset($_SESSION['unzip_dir']) && file_exists($_SESSION['unzip_dir'].'/scripts/files_to_remove'))
  3701. {
  3702. $files_to_remove = glob($_SESSION['unzip_dir'].'/scripts/files_to_remove/*.php');
  3703. foreach($files_to_remove as $script)
  3704. {
  3705. if(preg_match('/UpgradeRemoval(\d+)x\.php/', $script, $matches))
  3706. {
  3707. $checkVersion = $matches[1] + 1; //Increment by one to check everything equal or below the target version
  3708. $upgradeClass = 'UpgradeRemoval' . $matches[1] . 'x';
  3709. require_once($_SESSION['unzip_dir'].'/scripts/files_to_remove/' . $upgradeClass . '.php');
  3710. //Check to make sure we should load and run this UpgradeRemoval instance
  3711. if($checkVersion <= $version && class_exists($upgradeClass))
  3712. {
  3713. $upgradeInstance = new $upgradeClass();
  3714. if($upgradeInstance instanceof UpgradeRemoval)
  3715. {
  3716. logThis('Running UpgradeRemoval instance ' . $upgradeClass);
  3717. logThis('Files will be backed up to custom/backup');
  3718. $files = $upgradeInstance->getFilesToRemove($version);
  3719. foreach($files as $file)
  3720. {
  3721. logThis($file);
  3722. }
  3723. $upgradeInstance->processFilesToRemove($files);
  3724. }
  3725. }
  3726. }
  3727. }
  3728. }
  3729. //Check if we have a custom directory
  3730. if(file_exists('custom/scripts/files_to_remove'))
  3731. {
  3732. //Now find
  3733. $files_to_remove = glob('custom/scripts/files_to_remove/*.php');
  3734. foreach($files_to_remove as $script)
  3735. {
  3736. if(preg_match('/\/files_to_remove\/(.*?)\.php$/', $script, $matches))
  3737. {
  3738. require_once($script);
  3739. $upgradeClass = $matches[1];
  3740. if(!class_exists($upgradeClass))
  3741. {
  3742. continue;
  3743. }
  3744. $upgradeInstance = new $upgradeClass();
  3745. if($upgradeInstance instanceof UpgradeRemoval)
  3746. {
  3747. logThis('Running Custom UpgradeRemoval instance ' . $upgradeClass);
  3748. $files = $upgradeInstance->getFilesToRemove($version);
  3749. foreach($files as $file)
  3750. {
  3751. logThis($file);
  3752. }
  3753. $upgradeInstance->processFilesToRemove($files);
  3754. }
  3755. }
  3756. }
  3757. }
  3758. }
  3759. if (!function_exists("getValidDBName"))
  3760. {
  3761. /*
  3762. * Return a version of $proposed that can be used as a column name in any of our supported databases
  3763. * 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)
  3764. * @param string $name Proposed name for the column
  3765. * @param string $ensureUnique
  3766. * @return string Valid column name trimmed to right length and with invalid characters removed
  3767. */
  3768. function getValidDBName ($name, $ensureUnique = false, $maxLen = 30)
  3769. {
  3770. // first strip any invalid characters - all but alphanumerics and -
  3771. $name = preg_replace ( '/[^\w-]+/i', '', $name ) ;
  3772. $len = strlen ( $name ) ;
  3773. $result = $name;
  3774. if ($ensureUnique)
  3775. {
  3776. $md5str = md5($name);
  3777. $tail = substr ( $name, -11) ;
  3778. $temp = substr($md5str , strlen($md5str)-4 );
  3779. $result = substr ( $name, 0, 10) . $temp . $tail ;
  3780. }else if ($len > ($maxLen - 5))
  3781. {
  3782. $result = substr ( $name, 0, 11) . substr ( $name, 11 - $maxLen + 5);
  3783. }
  3784. return strtolower ( $result ) ;
  3785. }
  3786. }
  3787. /**
  3788. * Get UW directories
  3789. * Provides compatibility with both 6.3 and pre-6.3 setup
  3790. */
  3791. function getUWDirs()
  3792. {
  3793. if(!class_exists('UploadStream')) {
  3794. // we're still running the old code
  3795. global $sugar_config;
  3796. return array($sugar_config['upload_dir'] . "/upgrades", $sugar_config['cache_dir'] . "upload/upgrades/temp");
  3797. } else {
  3798. if(!in_array("upload", stream_get_wrappers())) {
  3799. UploadStream::register(); // just in case file was copied, but not run
  3800. }
  3801. return array("upload://upgrades", sugar_cached("upgrades/temp"));
  3802. }
  3803. }
  3804. /**
  3805. * Whether directory exists within list of directories to skip
  3806. * @param string $dir dir to be checked
  3807. * @param array $skipDirs list with skipped dirs
  3808. * @return boolean
  3809. */
  3810. function whetherNeedToSkipDir($dir, $skipDirs)
  3811. {
  3812. foreach($skipDirs as $skipMe) {
  3813. if(strpos( clean_path($dir), $skipMe ) !== false) {
  3814. return true;
  3815. }
  3816. }
  3817. return false;
  3818. }
  3819. /*
  3820. * rebuildSprites
  3821. * @param silentUpgrade boolean flag indicating whether or not we should treat running the SugarSpriteBuilder as an upgrade operation
  3822. *
  3823. */
  3824. function rebuildSprites($fromUpgrade=true)
  3825. {
  3826. require_once('modules/Administration/SugarSpriteBuilder.php');
  3827. $sb = new SugarSpriteBuilder();
  3828. $sb->cssMinify = true;
  3829. $sb->fromSilentUpgrade = $fromUpgrade;
  3830. $sb->silentRun = $fromUpgrade;
  3831. // add common image directories
  3832. $sb->addDirectory('default', 'include/images');
  3833. $sb->addDirectory('default', 'themes/default/images');
  3834. $sb->addDirectory('default', 'themes/default/images/SugarLogic');
  3835. // add all theme image directories
  3836. if($dh = opendir('themes'))
  3837. {
  3838. while (($dir = readdir($dh)) !== false)
  3839. {
  3840. if ($dir != "." && $dir != ".." && $dir != 'default' && is_dir('themes/'.$dir)) {
  3841. $sb->addDirectory($dir, "themes/{$dir}/images");
  3842. }
  3843. }
  3844. closedir($dh);
  3845. }
  3846. // add all theme custom image directories
  3847. $custom_themes_dir = "custom/themes";
  3848. if (is_dir($custom_themes_dir)) {
  3849. if($dh = opendir($custom_themes_dir))
  3850. {
  3851. while (($dir = readdir($dh)) !== false)
  3852. {
  3853. //Since the custom theme directories don't require an images directory
  3854. // we check for it implicitly
  3855. if ($dir != "." && $dir != ".." && is_dir('custom/themes/'.$dir."/images")) {
  3856. $sb->addDirectory($dir, "custom/themes/{$dir}/images");
  3857. }
  3858. }
  3859. closedir($dh);
  3860. }
  3861. }
  3862. // generate the sprite goodies
  3863. // everything is saved into cache/sprites
  3864. $sb->createSprites();
  3865. }
  3866. /**
  3867. * repairSearchFields
  3868. *
  3869. * This method goes through the list of SearchFields files based and calls TemplateRange::repairCustomSearchFields
  3870. * method on the files in an attempt to ensure the range search attributes are properly set in SearchFields.php.
  3871. *
  3872. * @param $globString String value used for glob search defaults to searching for all SearchFields.php files in modules directory
  3873. * @param $path String value used to point to log file should logging be required. Defaults to empty.
  3874. *
  3875. */
  3876. function repairSearchFields($globString='modules/*/metadata/SearchFields.php', $path='')
  3877. {
  3878. if(!empty($path))
  3879. {
  3880. logThis('Begin repairSearchFields', $path);
  3881. }
  3882. require_once('include/dir_inc.php');
  3883. require_once('modules/DynamicFields/templates/Fields/TemplateRange.php');
  3884. require('include/modules.php');
  3885. global $beanList;
  3886. $searchFieldsFiles = glob($globString);
  3887. foreach($searchFieldsFiles as $file)
  3888. {
  3889. if(preg_match('/modules\/(.*?)\/metadata\/SearchFields\.php/', $file, $matches) && isset($beanList[$matches[1]]))
  3890. {
  3891. $module = $matches[1];
  3892. $beanName = $beanList[$module];
  3893. VardefManager::loadVardef($module, $beanName);
  3894. if(isset($GLOBALS['dictionary'][$beanName]['fields']))
  3895. {
  3896. if(!empty($path))
  3897. {
  3898. logThis('Calling TemplateRange::repairCustomSearchFields for module ' . $module, $path);
  3899. }
  3900. TemplateRange::repairCustomSearchFields($GLOBALS['dictionary'][$beanName]['fields'], $module);
  3901. }
  3902. }
  3903. }
  3904. if(!empty($path))
  3905. {
  3906. logThis('End repairSearchFields', $path);
  3907. }
  3908. }
  3909. /**
  3910. * repairUpgradeHistoryTable
  3911. *
  3912. * This is a helper function used in the upgrade process to fix upgrade_history entries so that the filename column points
  3913. * to the new upload directory location introduced in 6.4 versions
  3914. */
  3915. function repairUpgradeHistoryTable()
  3916. {
  3917. require_once('modules/Configurator/Configurator.php');
  3918. new Configurator();
  3919. global $sugar_config;
  3920. //Now upgrade the upgrade_history table entries
  3921. $results = $GLOBALS['db']->query('SELECT id, filename FROM upgrade_history');
  3922. $upload_dir = $sugar_config['cache_dir'].'upload/';
  3923. //Create regular expression string to
  3924. $match = '/^' . str_replace('/', '\/', $upload_dir) . '(.*?)$/';
  3925. while(($row = $GLOBALS['db']->fetchByAssoc($results)))
  3926. {
  3927. $file = str_replace('//', '/', $row['filename']); //Strip out double-paths that may exist
  3928. if(!empty($file) && preg_match($match, $file, $matches))
  3929. {
  3930. //Update new file location to use the new $sugar_config['upload_dir'] value
  3931. $new_file_location = $sugar_config['upload_dir'] . $matches[1];
  3932. $GLOBALS['db']->query("UPDATE upgrade_history SET filename = '{$new_file_location}' WHERE id = '{$row['id']}'");
  3933. }
  3934. }
  3935. }