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