]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - modules/UpgradeWizard/uw_ajax.php
Release 6.2.0
[Github/sugarcrm.git] / modules / UpgradeWizard / uw_ajax.php
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-2011 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 /*********************************************************************************
39
40  * Description:
41  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc. All Rights
42  * Reserved. Contributor(s): ______________________________________..
43  * *******************************************************************************/
44
45
46 ////    COMMON
47
48 function ajaxSqlProgress($persistence, $sql, $type) {
49         global $mod_strings;
50
51         // $type is sql_to_check or sql_to_run
52         $whatsLeft = count($persistence[$type]);
53
54         ob_start();
55         $out  = "<b>{$mod_strings['LBL_UW_PREFLIGHT_QUERY']}</b><br />";
56         $out .= round((($persistence['sql_total'] - $whatsLeft) / $persistence['sql_total']) * 100, 1)."%
57                                 {$mod_strings['LBL_UW_DONE']} - {$mod_strings['LBL_UW_PREFLIGHT_QUERIES_LEFT']}: {$whatsLeft}";
58         $out .= "<br /><textarea cols='60' rows='3' DISABLED>{$sql}</textarea>";
59         echo $out;
60         ob_flush();
61
62         if($whatsLeft < 1) {
63                 $persistence['sql_check_done'] = true;
64         }
65
66         return $persistence;
67 }
68
69
70 ///////////////////////////////////////////////////////////////////////////////
71 ////    COMMIT AJAX
72 /**
73  * does post-post-install stuff
74  * @param array persistence
75  * @return array persistence
76  */
77 function commitAjaxFinalTouches($persistence) {
78         global $current_user;
79         global $timedate;
80         global $mod_strings;
81         global $sugar_version;
82
83         if(empty($sugar_version)) {
84                 require('sugar_version.php');
85         }
86
87         // convert to UTF8 if needed
88         if(!empty($persistence['allTables']))
89                 executeConvertTablesSql($GLOBALS['db']->dbType, $persistence['allTables']);
90
91         // rebuild
92         logThis('Performing UWrebuild()...');
93         UWrebuild();
94         logThis('UWrebuild() done.');
95
96         // upgrade history
97         registerUpgrade($persistence);
98
99         // flag to say upgrade has completed
100         $persistence['upgrade_complete'] = true;
101
102         // reminders if needed
103         ///////////////////////////////////////////////////////////////////////////////
104         ////    HANDLE REMINDERS
105         if(count($persistence['skipped_files']) > 0) {
106                 $desc  = $mod_strings['LBL_UW_COMMIT_ADD_TASK_OVERVIEW']."\n\n";
107                 $desc .= $mod_strings['LBL_UW_COMMIT_ADD_TASK_DESC_1'];
108                 $desc .= $persistence['uw_restore_dir']."\n\n";
109                 $desc .= $mod_strings['LBL_UW_COMMIT_ADD_TASK_DESC_2']."\n\n";
110
111                 foreach($persistence['skipped_files'] as $file) {
112                         $desc .= $file."\n";
113                 }
114
115                 //MFH #13468
116                 $nowDate = $timedate->nowDbDate();
117                 $nowTime = $timedate->asDbTime($timedate->getNow());
118                 $nowDateTime = $nowDate.' '.$nowTime;
119
120                 if($_REQUEST['addTaskReminder'] == 'remind') {
121                         logThis('Adding Task for admin for manual merge.');
122
123                         $task = new Task();
124                         $task->name = $mod_strings['LBL_UW_COMMIT_ADD_TASK_NAME'];
125                         $task->description = $desc;
126                         $task->date_due = $nowDate;
127                         $task->time_due = $nowTime;
128                         $task->priority = 'High';
129                         $task->status = 'Not Started';
130                         $task->assigned_user_id = $current_user->id;
131                         $task->created_by = $current_user->id;
132                         $task->date_entered = $nowDateTime;
133                         $task->date_modified = $nowDateTime;
134                         $task->save();
135                 }
136
137                 if($_REQUEST['addEmailReminder'] == 'remind') {
138                         logThis('Sending Reminder for admin for manual merge.');
139
140                         $email = new Email();
141                         $email->assigned_user_id = $current_user->id;
142                         $email->name = $mod_strings['LBL_UW_COMMIT_ADD_TASK_NAME'];
143                         $email->description = $desc;
144                         $email->description_html = nl2br($desc);
145                         $email->from_name = $current_user->full_name;
146                         $email->from_addr = $current_user->email1;
147                         $email->to_addrs_arr = $email->parse_addrs($current_user->email1,'','','');
148                         $email->cc_addrs_arr = array();
149                         $email->bcc_addrs_arr = array();
150                         $email->date_entered = $nowDateTime;
151                         $email->date_modified = $nowDateTime;
152                         $email->send();
153                         $email->save();
154                 }
155         }
156         ////    HANDLE REMINDERS
157         ///////////////////////////////////////////////////////////////////////////////
158
159         // clean up
160         unlinkTempFiles();
161
162         ob_start();
163         echo 'done';
164         ob_flush();
165
166         return $persistence;
167 }
168
169 /**
170  * runs one line of sql
171  * @param array $persistence
172  * @return array $persistence
173  */
174 function commitAjaxRunSql($persistence) {
175         global $db;
176
177         if(!isset($persistence['commit_sql_errors'])) {
178                 $persistence['commit_sql_errors'] = array();
179         }
180
181         // This flag is determined by the preflight check in the installer
182         if($persistence['schema_change'] == 'sugar') {
183
184                 if(isset($persistence['sql_to_run'])
185                         && count($persistence['sql_to_run']) > 0
186                         && !empty($persistence['sql_to_run'])) {
187
188                         $sql = array_shift($persistence['sql_to_run']);
189                         $sql = trim($sql);
190
191                         if(!empty($sql)) {
192                                 logThis("[RUNNING SQL QUERY] {$sql}");
193                                 $db->query($sql);
194
195                                 $error = '';
196                                 switch($db->dbType) {
197                                         case 'mysql':
198                                                 $error = mysql_error();
199                                         break;
200
201                                         case 'oci8':
202                                         break;
203
204                                         case 'mssql':
205
206                                         break;
207                                 }
208
209                                 if(!empty($error)) {
210                                         logThis('************************************************************');
211                                         logThis('*** ERROR: SQL Commit Error!');
212                                         logThis('*** Query: [ '.$sql.' ]');
213                                         logThis('************************************************************');
214                                         $persistence['commit_sql_errors'][] = getFormattedError($error, $sql);
215                                 }
216                                 $persistence = ajaxSqlProgress($persistence, $sql, 'sql_to_run');
217                         }
218
219                 } else {
220                         ob_start();
221                         echo 'done';
222                         ob_flush();
223                 }
224         } else {
225                 ob_start();
226                 echo 'done';
227                 ob_flush();
228         }
229
230         return $persistence;
231 }
232
233 /**
234  * returns errors found during SQL operations
235  * @param array persistence
236  * @return string Error message or empty string on success
237  */
238 function commitAjaxGetSqlErrors($persistence) {
239         global $mod_strings;
240
241         $out = '';
242         if(isset($persistence['commit_sql_errors']) && !empty($persistence['commit_sql_errors'])) {
243                 $out = "<div class='error'>";
244                 foreach($persistence['commit_sql_errors'] as $error) {
245                         $out .= $error;
246                 }
247                 $out .= "</div>";
248         }
249
250         if(empty($out)) {
251                 $out = $mod_strings['LBL_UW_COMMIT_ALL_SQL_SUCCESSFULLY_RUN'];
252         }
253
254         ob_start();
255         echo $out;
256         ob_flush();
257 }
258
259 /**
260  * parses the sql upgrade file for sequential querying
261  * @param array persistence
262  * @return array persistence
263  */
264 function commitAjaxPrepSql($persistence) {
265         return preflightCheckJsonPrepSchemaCheck($persistence, false);
266 }
267
268
269 /**
270  * handles post-install tasks
271  */
272 function commitAjaxPostInstall($persistence) {
273         global $mod_strings;
274         global $sugar_config;
275         global $sugar_version;
276
277         if(empty($sugar_version)) {
278                 require('sugar_version.php');
279         }
280
281         // update versions info
282         if(!updateVersions($sugar_version)) {
283                 echo $mod_strings['ERR_UW_COMMIT_UPDATE_VERSIONS'];
284         }
285
286         logThis('Starting post_install()...');
287         $postInstallResults = "<b>{$mod_strings['LBL_UW_COMMIT_POSTINSTALL_RESULTS']}</b><br />
288                                                         <a href='javascript:toggleNwFiles(\"postInstallResults\");'>{$mod_strings['LBL_UW_SHOW']}</a><br />
289                                                         <div id='postInstallResults' style='display:none'>";
290         $file = $persistence['unzip_dir']. "/" . constant('SUGARCRM_POST_INSTALL_FILE');
291         if(is_file($file)) {
292                 include($file);
293                 ob_start();
294                 post_install();
295         }
296
297         require( "sugar_version.php" );
298
299         if (!rebuildConfigFile($sugar_config, $sugar_version)) {
300                 logThis('*** ERROR: could not write config.php! - upgrade will fail!');
301                 $errors[] = $mod_strings['ERR_UW_CONFIG_WRITE'];
302         }
303
304         $res = ob_get_contents();
305         $postInstallResults .= (empty($res)) ? $mod_strings['LBL_UW_SUCCESS'] : $res;
306         $postInstallResults .= "</div>";
307
308         ob_start();
309         echo $postInstallResults;
310         ob_flush();
311
312         logThis('post_install() done.');
313 }
314 ////    END COMMIT AJAX
315 ///////////////////////////////////////////////////////////////////////////////
316
317
318
319 ///////////////////////////////////////////////////////////////////////////////
320 ////    PREFLIGHT JSON STYLE
321
322 function preflightCheckJsonFindUpgradeFiles($persistence) {
323         global $sugar_config;
324         global $mod_strings;
325
326         unset($persistence['rebuild_relationships']);
327         unset($persistence['rebuild_extensions']);
328
329         // don't bother if are rechecking
330         $manualDiff                     = array();
331         if(!isset($persistence['unzip_dir']) || empty($persistence['unzip_dir'])) {
332                 logThis('unzipping files in upgrade archive...');
333
334                 $errors                                 = array();
335                 $base_upgrade_dir      = $sugar_config['upload_dir'] . "/upgrades";
336                 $base_tmp_upgrade_dir  = "$base_upgrade_dir/temp";
337                 $install_file                   = urldecode( $persistence['install_file'] );
338                 $show_files                             = true;
339                 $unzip_dir                              = clean_path(mk_temp_dir( $base_tmp_upgrade_dir ));
340                 $zip_from_dir                   = ".";
341                 $zip_to_dir                     = ".";
342                 $zip_force_copy                 = array();
343
344                 unzip( $install_file, $unzip_dir );
345
346                 // assumption -- already validated manifest.php at time of upload
347                 include( "$unzip_dir/manifest.php" );
348
349                 if( isset( $manifest['copy_files']['from_dir'] ) && $manifest['copy_files']['from_dir'] != "" ){
350                     $zip_from_dir   = $manifest['copy_files']['from_dir'];
351                 }
352                 if( isset( $manifest['copy_files']['to_dir'] ) && $manifest['copy_files']['to_dir'] != "" ){
353                     $zip_to_dir     = $manifest['copy_files']['to_dir'];
354                 }
355                 if( isset( $manifest['copy_files']['force_copy'] ) && $manifest['copy_files']['force_copy'] != "" ){
356                     $zip_force_copy     = $manifest['copy_files']['force_copy'];
357                 }
358                 if( isset( $manifest['version'] ) ){
359                     $version    = $manifest['version'];
360                 }
361                 if( !is_writable( "config.php" ) ){
362                         logThis('BAD error');
363                         return $mod_strings['ERR_UW_CONFIG'];
364                 }
365
366                 logThis('setting "unzip_dir" to '.$unzip_dir);
367                 $persistence['unzip_dir'] = clean_path($unzip_dir);
368                 $persistence['zip_from_dir'] = clean_path($zip_from_dir);
369
370                 logThis('unzip done.');
371         } else {
372                 $unzip_dir = $persistence['unzip_dir'];
373                 $zip_from_dir = $persistence['zip_from_dir'];
374         }
375
376         $persistence['upgrade_files'] = uwFindAllFiles(clean_path("$unzip_dir/$zip_from_dir"), array(), true, array(), true);
377
378         return $persistence;
379 }
380
381 function preflightCheckJsonDiffFiles($persistence) {
382         global $sugar_version;
383         global $mod_strings;
384
385         if(!isset($sugar_version) || empty($sugar_version)) {
386
387         }
388
389         // get md5 sums
390         $md5_string = array();
391         $finalZipDir = $persistence['unzip_dir'].'/'.$persistence['zip_from_dir'];
392
393         if(is_file(getcwd().'/files.md5'))
394                 require(getcwd().'/files.md5');
395
396         // initialize pass array
397         $manualDiff = array();
398
399         // file preflight checks
400         logThis('verifying md5 checksums for files...');
401         $cache_html_files = findAllFilesRelative( "{$GLOBALS['sugar_config']['cache_dir']}layout", array());
402
403         foreach($persistence['upgrade_files'] as $file) {
404                 if(strpos($file, '.md5'))
405                         continue; // skip md5 file
406
407                 // normalize file paths
408                 $file = clean_path($file);
409
410                 // check that we can move/delete the upgraded file
411                 if(!is_writable($file)) {
412                         $errors[] = $mod_strings['ERR_UW_FILE_NOT_WRITABLE'].": ".$file;
413                 }
414                 // check that destination files are writable
415                 $destFile = getcwd().str_replace($finalZipDir, '', $file);
416
417                 if(is_file($destFile)) { // of course it needs to exist first...
418                         if(!is_writable($destFile)) {
419                                 $errors[] = $mod_strings['ERR_UW_FILE_NOT_WRITABLE'].": ".$destFile;
420                         }
421                 }
422
423                 ///////////////////////////////////////////////////////////////////////
424                 ////    DIFFS
425                 // compare md5s and build up a manual merge list
426                 $targetFile = clean_path(".".str_replace(getcwd(),'',$destFile));
427                 $targetMd5 = '0';
428                 if(is_file($destFile)) {
429                         if(strpos($targetFile, '.php')) {
430                                 // handle PHP files that were hit with the security regex
431                                 $filesize = filesize($destFile);
432                                 if($filesize > 0) {
433                                     $fileContents = file_get_contents($destFile);
434                                         $targetMd5 = md5($fileContents);
435                                 }
436                         } else {
437                                 $targetMd5 = md5_file($destFile);
438                         }
439                 }
440
441                 if(isset($md5_string[$targetFile]) && $md5_string[$targetFile] != $targetMd5) {
442                         logThis('found a file with a differing md5: ['.$targetFile.']');
443                         $manualDiff[] = $destFile;
444                 }
445                 ////    END DIFFS
446                 ///////////////////////////////////////////////////////////////////////
447                 echo ".";
448         }
449         logThis('md5 verification done.');
450
451         $persistence['manual'] = $manualDiff;
452         $persistence['diff_errors'] = $errors;
453
454         return $persistence;
455 }
456
457
458 function preflightCheckJsonGetDiff($persistence) {
459         global $mod_strings;
460         global $current_user;
461
462         $out  = $mod_strings['LBL_UW_PREFLIGHT_TESTS_PASSED'];
463         $stop = false;
464
465         $disableEmail = (empty($current_user->email1)) ? 'DISABLED' : 'CHECKED';
466
467         if(count($persistence['manual']) > 0) {
468                 $preserveFiles = array();
469
470                 $diffs =<<<eoq
471                         <script type="text/javascript" language="Javascript">
472                                 function preflightToggleAll(cb) {
473                                         var checkAll = false;
474                                         var form = document.getElementById('diffs');
475
476                                         if(cb.checked == true) {
477                                                 checkAll = true;
478                                         }
479
480                                         for(i=0; i<form.elements.length; i++) {
481                                                 if(form.elements[i].type == 'checkbox') {
482                                                         form.elements[i].checked = checkAll;
483                                                 }
484                                         }
485                                         return;
486                                 }
487                         </script>
488
489                         <table cellpadding='0' cellspacing='0' border='0'>
490                                 <tr>
491                                         <td valign='top'>
492                                                 <input type='checkbox' name='addTask' id='addTask' CHECKED>
493                                         </td>
494                                         <td valign='top'>
495                                                 {$mod_strings['LBL_UW_PREFLIGHT_ADD_TASK']}
496                                         </td>
497                                 </tr>
498                                 <tr>
499                                         <td valign='top'>
500                                                 <input type='checkbox' name='addEmail' id='addEmail' $disableEmail>
501                                         </td>
502                                         <td valign='top'>
503                                                 {$mod_strings['LBL_UW_PREFLIGHT_EMAIL_REMINDER']}
504                                         </td>
505                                 </tr>
506                         </table>
507
508                         <form name='diffs' id='diffs'>
509                         <p><a href='javascript:void(0); toggleNwFiles("diffsHide");'>{$mod_strings['LBL_UW_SHOW_DIFFS']}</a></p>
510                         <div id='diffsHide' style='display:none'>
511                                 <table cellpadding='0' cellspacing='0' border='0'>
512                                         <tr>
513                                                 <td valign='top' colspan='2'>
514                                                         {$mod_strings['LBL_UW_PREFLIGHT_FILES_DESC']}
515                                                         <br />&nbsp;
516                                                 </td>
517                                         </tr>
518                                         <tr>
519                                                 <td valign='top' colspan='2'>
520                                                         <input type='checkbox' onchange='preflightToggleAll(this);'>&nbsp;<i><b>{$mod_strings['LBL_UW_PREFLIGHT_TOGGLE_ALL']}</b></i>
521                                                         <br />&nbsp;
522                                                 </td>
523                                         </tr>
524 eoq;
525                 foreach($persistence['manual'] as $diff) {
526                         $diff = clean_path($diff);
527                         $persistence['files']['manual'][] = $diff;
528
529                         $checked = (isAutoOverwriteFile($diff)) ? 'CHECKED' : '';
530
531                         if(empty($checked)) {
532                                 $preserveFiles[] = $diff;
533                         }
534
535                         $diffs .= "<tr><td valign='top'>";
536                         $diffs .= "<input type='checkbox' name='diff_files[]' value='{$diff}' $checked>";
537                         $diffs .= "</td><td valign='top'>";
538                         $diffs .= str_replace(getcwd(), '.', $diff);
539                         $diffs .= "</td></tr>";
540                 }
541                 $diffs .= "</table>";
542                 $diffs .= "</div></p>";
543                 $diffs .= "</form>";
544
545                 // list preserved files (templates, etc.)
546                 $preserve = '';
547                 foreach($preserveFiles as $pf) {
548                         if(empty($preserve)) {
549                                 $preserve .= "<table cellpadding='0' cellspacing='0' border='0'><tr><td><b>";
550                                 $preserve .= $mod_strings['LBL_UW_PREFLIGHT_PRESERVE_FILES'];
551                                 $preserve .= "</b></td></tr>";
552                         }
553                         $preserve .= "<tr><td valign='top'><i>".str_replace(getcwd(), '.', $pf)."</i></td></tr>";
554                 }
555                 if(!empty($preserve)) {
556                         $preserve .= '</table><br>';
557                 }
558                 $diffs = $preserve.$diffs;
559         } else { // NO FILE DIFFS REQUIRED
560                 $diffs = $mod_strings['LBL_UW_PREFLIGHT_NO_DIFFS'];
561         }
562
563         echo $diffs;
564
565         return $persistence;
566 }
567
568 /**
569  * loads the sql file into an array
570  * @param array persistence
571  * @param bool preflight Flag to load for Preflight or Commit
572  * @return array persistence
573  */
574 function preflightCheckJsonPrepSchemaCheck($persistence, $preflight=true) {
575         global $mod_strings;
576         global $db;
577         global $sugar_db_version;
578         global $manifest;
579
580         unset($persistence['sql_to_run']);
581
582         $persistence['sql_to_check'] = array();
583         $persistence['sql_to_check_backup'] = array();
584
585         if(isset($persistence['sql_check_done'])) {
586                 // reset flag to not check (on Recheck)
587                 unset($persistence['sql_check_done']);
588                 unset($persistence['sql_errors']);
589         }
590
591         // get schema script if not loaded
592         if($preflight)
593                 logThis('starting schema preflight check...');
594         else
595                 logThis('Preparing SQL statements for sequential execution...');
596
597         if(!isset($sugar_db_version) || empty($sugar_db_version)) {
598                 include('./sugar_version.php');
599         }
600
601         if(!isset($manifest['version']) || empty($manifest['version'])) {
602                 include($persistence['unzip_dir'].'/manifest.php');
603         }
604
605         $current_version = substr(preg_replace("#[^0-9]#", "", $sugar_db_version),0,3);
606         $targetVersion =  substr(preg_replace("#[^0-9]#", "", $manifest['version']),0,3);
607         $sqlScript = $persistence['unzip_dir'].'/scripts/'.$current_version.'_to_'.$targetVersion.'_'.$db->dbType.'.sql';
608
609         $newTables = array();
610
611
612         logThis('looking for schema script at: '.$sqlScript);
613         if(is_file($sqlScript)) {
614                 logThis('found schema upgrade script: '.$sqlScript);
615                 $fp = sugar_fopen($sqlScript, 'r');
616
617                 if(!empty($fp)) {
618                         $completeLine = '';
619                         while($line = fgets($fp)) {
620                                 if(strpos($line, '--') === false) {
621                                         $completeLine .= " ".trim($line);
622                                         if(strpos($line, ';') !== false) {
623                                                 $completeLine = str_replace(';','',$completeLine);
624                                                 $persistence['sql_to_check'][] = $completeLine;
625                                                 $completeLine = ''; //reset for next loop
626                                         }
627                                 }
628                         }
629
630                         $persistence['sql_total'] = count($persistence['sql_to_check']);
631                 } else {
632                         logThis('*** ERROR: could not read schema script: '.$sqlScript);
633                         $persistence['sql_errors'][] = $mod_strings['ERR_UW_FILE_NOT_READABLE'].'::'.$sqlScript;
634                 }
635         }
636
637         // load a new array if for commit
638         if($preflight) {
639                 $persistence['sql_to_check_backup'] = $persistence['sql_to_check'];
640                 $persistence['sql_to_run'] = $persistence['sql_to_check'];
641                 echo "1% ".$mod_strings['LBL_UW_DONE'];
642         } else {
643                 $persistence['sql_to_run'] = $persistence['sql_to_check'];
644                 unset($persistence['sql_to_check']);
645         }
646
647         return $persistence;
648 }
649
650 function preflightCheckJsonSchemaCheck($persistence) {
651         global $mod_strings;
652         global $db;
653
654         if(!isset($persistence['sql_check_done']) || $persistence['sql_check_done'] != true) {
655                 // must keep sql in order
656                 $completeLine = array_shift($persistence['sql_to_check']);
657                 $whatsLeft = count($persistence['sql_to_check']);
658
659                 // populate newTables array to prevent "getting sample data" from non-existent tables
660                 $newTables = array();
661                 if(strtoupper(substr($completeLine,1,5)) == 'CREAT')
662                         $newTables[] = getTableFromQuery($completeLine);
663
664                 $bad = verifySqlStatement(trim($completeLine), $db->dbType, $newTables);
665
666                 if(!empty($bad)) {
667                         logThis('*** ERROR: schema change script has errors: '.$completeLine);
668                         $persistence['sql_errors'][] = $bad;
669                 }
670
671                 $persistence = ajaxSqlProgress($persistence, $completeLine, 'sql_to_check');
672         } else {
673                 $persistence['sql_to_check'] = $persistence['sql_to_check_backup'];
674                 echo 'done';
675         }
676
677         return $persistence;
678 }
679
680
681 function preflightCheckJsonGetSchemaErrors($persistence) {
682         global $mod_strings;
683
684         if(isset($persistence['sql_errors']) && count($persistence['sql_errors'] > 0)) {
685                 $out = "<b class='error'>{$mod_strings['ERR_UW_PREFLIGHT_ERRORS']}:</b> ";
686                 $out .= "<a href='javascript:void(0);toggleNwFiles(\"sqlErrors\");'>{$mod_strings['LBL_UW_SHOW_SQL_ERRORS']}</a><div id='sqlErrors' style='display:none'>";
687                 foreach($persistence['sql_errors'] as $sqlError) {
688                         $out .= "<br><span class='error'>{$sqlError}</span>";
689                 }
690                 $out .= "</div><hr />";
691         } else {
692                 $out = '';
693         }
694
695         // reset errors if Rechecking
696         if(isset($persistence['sql_errors']))
697                 //unset($persistence['sql_errors']);
698
699         echo $out;
700
701         return $persistence;
702 }
703
704
705 function preflightCheckJsonFillSchema() {
706         global $mod_strings;
707         global $persistence;
708         global $sugar_db_version;
709         global $manifest;
710         global $db;
711
712         if(empty($sugar_db_version)) {
713                 include('sugar_version');
714         }
715         if(empty($manifest)) {
716                 include($persistence['unzip_dir'].'/manifest.php');
717         }
718
719         ///////////////////////////////////////////////////////////////////////////////
720         ////    SCHEMA SCRIPT HANDLING
721         $schema = '';
722         $alterTableSchemaOut = '';
723         $current_version = substr(preg_replace("#[^0-9]#", "", $sugar_db_version),0,3);
724         $targetVersion =  substr(preg_replace("#[^0-9]#", "", $manifest['version']),0,3);
725         $sqlScript = $persistence['unzip_dir'].'/scripts/'.$current_version.'_to_'.$targetVersion.'_'.$db->dbType.'.sql';
726         $newTables = array();
727
728         logThis('looking for SQL script for DISPLAY at '.$sqlScript);
729         if(file_exists($sqlScript)) {
730                 $contents = sugar_file_get_contents($sqlScript);
731                 $schema  = "<p><a href='javascript:void(0); toggleNwFiles(\"schemashow\");'>{$mod_strings['LBL_UW_SHOW_SCHEMA']}</a>";
732                 $schema .= "<div id='schemashow' style='display:none;'>";
733                 $schema .= "<textarea readonly cols='80' rows='10'>{$contents}</textarea>";
734                 $schema .= "</div></p>";
735         }
736         ////    END SCHEMA SCRIPT HANDLING
737         ///////////////////////////////////////////////////////////////////////////////
738
739         ob_start();
740         echo $schema;
741         ob_flush();
742 }
743
744
745 function preflightCheckJsonAlterTableCharset() {
746         global $mod_strings;
747         global $sugar_db_version;
748         global $persistence;
749
750         if(empty($sugar_db_version))
751                 include('sugar_version.php');
752
753         $current_version = substr(preg_replace("#[^0-9]#", "", $sugar_db_version),0,3);
754
755         if(version_compare($current_version, '450', "<")) {
756                 if(isset($persistence['allTables']) && !empty($persistence['allTables'])) {
757                         $alterTableContents = printAlterTableSql($persistence['allTables']);
758                         $alterTableSchema  = "<p><a href='javascript:void(0); toggleNwFiles(\"alterTableSchemashow\");'>{$mod_strings['LBL_UW_CHARSET_SCHEMA_CHANGE']}</a>";
759                         $alterTableSchema .= "<div id='alterTableSchemashow' style='display:none;'>";
760                         $alterTableSchema .= "<textarea readonly cols='80' rows='10'>{$alterTableContents}</textarea>";
761                         $alterTableSchema .= "</div></p>";
762                 }
763         } else {
764                 $alterTableSchema = '<i>'.$mod_strings['LBL_UW_PREFLIGHT_NOT_NEEDED'].'</i>';
765         }
766
767         ob_start();
768         echo $alterTableSchema;
769         ob_flush();
770 }
771
772
773 ///////////////////////////////////////////////////////////////////////////////
774 ////    SYSTEMCHECK AJAX FUNCTIONS
775
776 function systemCheckJsonGetFiles($persistence) {
777         global $sugar_config;
778         global $mod_strings;
779
780         // add directories here that should be skipped when doing file permissions checks (cache/upload is the nasty one)
781         $skipDirs = array(
782                 $sugar_config['upload_dir'],
783                 getcwd().'/themes',
784         );
785
786         if(!isset($persistence['dirs_checked'])) {
787                 $the_array = array();
788                 $files = array();
789                 $dir = getcwd();
790                 $d = dir($dir);
791                 while($f = $d->read()) {
792                     if($f == "." || $f == "..") // skip *nix self/parent
793                         continue;
794
795                     if(is_dir("$dir/$f"))
796                                 $the_array[] = clean_path("$dir/$f");
797                         else {
798                                 $files[] = clean_path("$dir/$f");
799                         }
800                 }
801                 $persistence['files_to_check'] = $files;
802                 $persistence['dirs_to_check'] = $the_array;
803                 $persistence['dirs_total']      = count($the_array);
804                 $persistence['dirs_checked'] = false;
805
806                 $out = "1% {$mod_strings['LBL_UW_DONE']}";
807
808                 return $persistence;
809         } elseif($persistence['dirs_checked'] == false) {
810                 $dir = array_pop($persistence['dirs_to_check']);
811
812                 $files = uwFindAllFiles($dir, array(), true, $skipDirs);
813
814                 $persistence['files_to_check'] = array_merge($persistence['files_to_check'], $files);
815
816                 $whatsLeft = count($persistence['dirs_to_check']);
817
818                 if(!isset($persistence['dirs_to_check']) || $whatsLeft < 1) {
819                         $whatsLeft = 0;
820                         $persistence['dirs_checked'] = true;
821                 }
822
823                 $out  = round((($persistence['dirs_total'] - $whatsLeft) / 21) * 100, 1)."% {$mod_strings['LBL_UW_DONE']}";
824                 $out .= " [{$mod_strings['LBL_UW_SYSTEM_CHECK_CHECKING_JSON']} {$dir}]";
825         } else {
826                 $out = "Done";
827         }
828
829         echo trim($out);
830
831         return $persistence;
832 }
833
834
835
836 /**
837  * checks files for permissions
838  * @param array files Array of files with absolute paths
839  * @return string result of check
840  */
841 function systemCheckJsonCheckFiles($persistence) {
842         global $mod_strings;
843         global $persistence;
844
845         $filesNotWritable = array();
846         $i=0;
847         $filesOut = "
848                 <a href='javascript:void(0); toggleNwFiles(\"filesNw\");'>{$mod_strings['LBL_UW_SHOW_NW_FILES']}</a>
849                 <div id='filesNw' style='display:none;'>
850                 <table cellpadding='3' cellspacing='0' border='0'>
851                 <tr>
852                         <th align='left'>{$mod_strings['LBL_UW_FILE']}</th>
853                         <th align='left'>{$mod_strings['LBL_UW_FILE_PERMS']}</th>
854                         <th align='left'>{$mod_strings['LBL_UW_FILE_OWNER']}</th>
855                         <th align='left'>{$mod_strings['LBL_UW_FILE_GROUP']}</th>
856                 </tr>";
857
858         $isWindows = is_windows();
859         foreach($persistence['files_to_check'] as $file) {
860         //      while($file = array_pop($persistence['files_to_check'])) {
861
862                 // admin deletes a bad file mid-check:
863                 if(!file_exists($file))
864                         continue;
865
866                 if($isWindows) {
867                         if(!is_writable_windows($file)) {
868                                 logThis('WINDOWS: File ['.$file.'] not readable - saving for display');
869                                 // don't warn yet - we're going to use this to check against replacement files
870                                 $filesNotWritable[$i] = $file;
871                                 $filesNWPerms[$i] = substr(sprintf('%o',fileperms($file)), -4);
872                                 $filesOut .= "<tr>".
873                                                                 "<td valign='top'><span class='error'>{$file}</span></td>".
874                                                                 "<td valign='top'>{$filesNWPerms[$i]}</td>".
875                                                                 "<td valign='top'>".$mod_strings['ERR_UW_CANNOT_DETERMINE_USER']."</td>".
876                                                                 "<td valign='top'>".$mod_strings['ERR_UW_CANNOT_DETERMINE_GROUP']."</td>".
877                                                           "</tr>";
878                         }
879                 } else {
880                         if(!is_writable($file)) {
881                                 logThis('File ['.$file.'] not writable - saving for display');
882                                 // don't warn yet - we're going to use this to check against replacement files
883                                 $filesNotWritable[$i] = $file;
884                                 $filesNWPerms[$i] = substr(sprintf('%o',fileperms($file)), -4);
885                                 $owner = posix_getpwuid(fileowner($file));
886                                 $group = posix_getgrgid(filegroup($file));
887                                 $filesOut .= "<tr>".
888                                                                 "<td valign='top'><span class='error'>{$file}</span></td>".
889                                                                 "<td valign='top'>{$filesNWPerms[$i]}</td>".
890                                                                 "<td valign='top'>".$owner['name']."</td>".
891                                                                 "<td valign='top'>".$group['name']."</td>".
892                                                           "</tr>";
893                         }
894                 }
895                 $i++;
896         }
897
898         $filesOut .= '</table></div>';
899         // not a stop error
900         $persistence['filesNotWritable'] = (count($filesNotWritable) > 0) ? true : false;
901
902         if(count($filesNotWritable) < 1) {
903                 $filesOut = "{$mod_strings['LBL_UW_FILE_NO_ERRORS']}";
904                 $persistence['step']['systemCheck'] = 'success';
905         }
906
907         echo $filesOut;
908         return $persistence;
909 }
910
911
912 ?>