]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - modules/UpgradeWizard/uw_ajax.php
Release 6.5.9
[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-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 /*********************************************************************************
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 (empty($sugar_version))
373     {
374         require('sugar_version.php');
375     }
376
377         // get md5 sums
378         $md5_string = array();
379         $finalZipDir = $persistence['unzip_dir'].'/'.$persistence['zip_from_dir'];
380
381         if(is_file(getcwd().'/files.md5'))
382                 require(getcwd().'/files.md5');
383
384         // initialize pass array
385         $manualDiff = array();
386
387         // file preflight checks
388         logThis('verifying md5 checksums for files...');
389         $cache_html_files = findAllFilesRelative(sugar_cached("layout"), array());
390
391         foreach($persistence['upgrade_files'] as $file) {
392                 if(strpos($file, '.md5'))
393                         continue; // skip md5 file
394
395                 // normalize file paths
396                 $file = clean_path($file);
397
398                 // check that we can move/delete the upgraded file
399                 if(!is_writable($file)) {
400                         $errors[] = $mod_strings['ERR_UW_FILE_NOT_WRITABLE'].": ".$file;
401                 }
402                 // check that destination files are writable
403                 $destFile = getcwd().str_replace($finalZipDir, '', $file);
404
405                 if(is_file($destFile)) { // of course it needs to exist first...
406                         if(!is_writable($destFile)) {
407                                 $errors[] = $mod_strings['ERR_UW_FILE_NOT_WRITABLE'].": ".$destFile;
408                         }
409                 }
410
411                 ///////////////////////////////////////////////////////////////////////
412                 ////    DIFFS
413                 // compare md5s and build up a manual merge list
414                 $targetFile = clean_path(".".str_replace(getcwd(),'',$destFile));
415                 $targetMd5 = '0';
416                 if(is_file($destFile)) {
417                         if(strpos($targetFile, '.php')) {
418                                 // handle PHP files that were hit with the security regex
419                                 $filesize = filesize($destFile);
420                                 if($filesize > 0) {
421                                     $fileContents = file_get_contents($destFile);
422                                         $targetMd5 = md5($fileContents);
423                                 }
424                         } else {
425                                 $targetMd5 = md5_file($destFile);
426                         }
427                 }
428
429                 if(isset($md5_string[$targetFile]) && $md5_string[$targetFile] != $targetMd5) {
430                         logThis('found a file with a differing md5: ['.$targetFile.']');
431                         $manualDiff[] = $destFile;
432                 }
433                 ////    END DIFFS
434                 ///////////////////////////////////////////////////////////////////////
435                 echo ".";
436         }
437         logThis('md5 verification done.');
438
439         $persistence['manual'] = $manualDiff;
440         $persistence['diff_errors'] = $errors;
441
442         return $persistence;
443 }
444
445
446 function preflightCheckJsonGetDiff($persistence) {
447         global $mod_strings;
448         global $current_user;
449
450         $out  = $mod_strings['LBL_UW_PREFLIGHT_TESTS_PASSED'];
451         $stop = false;
452
453         $disableEmail = (empty($current_user->email1)) ? 'DISABLED' : 'CHECKED';
454
455         if(count($persistence['manual']) > 0) {
456                 $preserveFiles = array();
457
458                 $diffs =<<<eoq
459                         <script type="text/javascript" language="Javascript">
460                                 function preflightToggleAll(cb) {
461                                         var checkAll = false;
462                                         var form = document.getElementById('diffs');
463
464                                         if(cb.checked == true) {
465                                                 checkAll = true;
466                                         }
467
468                                         for(i=0; i<form.elements.length; i++) {
469                                                 if(form.elements[i].type == 'checkbox') {
470                                                         form.elements[i].checked = checkAll;
471                                                 }
472                                         }
473                                         return;
474                                 }
475                         </script>
476
477                         <table cellpadding='0' cellspacing='0' border='0'>
478                                 <tr>
479                                         <td valign='top'>
480                                                 <input type='checkbox' name='addTask' id='addTask' CHECKED>
481                                         </td>
482                                         <td valign='top'>
483                                                 {$mod_strings['LBL_UW_PREFLIGHT_ADD_TASK']}
484                                         </td>
485                                 </tr>
486                                 <tr>
487                                         <td valign='top'>
488                                                 <input type='checkbox' name='addEmail' id='addEmail' $disableEmail>
489                                         </td>
490                                         <td valign='top'>
491                                                 {$mod_strings['LBL_UW_PREFLIGHT_EMAIL_REMINDER']}
492                                         </td>
493                                 </tr>
494                         </table>
495
496                         <form name='diffs' id='diffs'>
497                         <p><a href='javascript:void(0); toggleNwFiles("diffsHide");'>{$mod_strings['LBL_UW_SHOW_DIFFS']}</a></p>
498                         <div id='diffsHide' style='display:none'>
499                                 <table cellpadding='0' cellspacing='0' border='0'>
500                                         <tr>
501                                                 <td valign='top' colspan='2'>
502                                                         {$mod_strings['LBL_UW_PREFLIGHT_FILES_DESC']}
503                                                         <br />&nbsp;
504                                                 </td>
505                                         </tr>
506                                         <tr>
507                                                 <td valign='top' colspan='2'>
508                                                         <input type='checkbox' onchange='preflightToggleAll(this);'>&nbsp;<i><b>{$mod_strings['LBL_UW_PREFLIGHT_TOGGLE_ALL']}</b></i>
509                                                         <br />&nbsp;
510                                                 </td>
511                                         </tr>
512 eoq;
513                 foreach($persistence['manual'] as $diff) {
514                         $diff = clean_path($diff);
515                         $persistence['files']['manual'][] = $diff;
516
517                         $checked = (isAutoOverwriteFile($diff)) ? 'CHECKED' : '';
518
519                         if(empty($checked)) {
520                                 $preserveFiles[] = $diff;
521                         }
522
523                         $diffs .= "<tr><td valign='top'>";
524                         $diffs .= "<input type='checkbox' name='diff_files[]' value='{$diff}' $checked>";
525                         $diffs .= "</td><td valign='top'>";
526                         $diffs .= str_replace(getcwd(), '.', $diff);
527                         $diffs .= "</td></tr>";
528                 }
529                 $diffs .= "</table>";
530                 $diffs .= "</div></p>";
531                 $diffs .= "</form>";
532
533                 // list preserved files (templates, etc.)
534                 $preserve = '';
535                 foreach($preserveFiles as $pf) {
536                         if(empty($preserve)) {
537                                 $preserve .= "<table cellpadding='0' cellspacing='0' border='0'><tr><td><b>";
538                                 $preserve .= $mod_strings['LBL_UW_PREFLIGHT_PRESERVE_FILES'];
539                                 $preserve .= "</b></td></tr>";
540                         }
541                         $preserve .= "<tr><td valign='top'><i>".str_replace(getcwd(), '.', $pf)."</i></td></tr>";
542                 }
543                 if(!empty($preserve)) {
544                         $preserve .= '</table><br>';
545                 }
546                 $diffs = $preserve.$diffs;
547         } else { // NO FILE DIFFS REQUIRED
548                 $diffs = $mod_strings['LBL_UW_PREFLIGHT_NO_DIFFS'];
549         }
550
551         echo $diffs;
552
553         return $persistence;
554 }
555
556 /**
557  * loads the sql file into an array
558  * @param array persistence
559  * @param bool preflight Flag to load for Preflight or Commit
560  * @return array persistence
561  */
562 function preflightCheckJsonPrepSchemaCheck($persistence, $preflight=true) {
563         global $mod_strings;
564         global $db;
565         global $sugar_db_version;
566         global $manifest;
567
568         unset($persistence['sql_to_run']);
569
570         $persistence['sql_to_check'] = array();
571         $persistence['sql_to_check_backup'] = array();
572
573         if(isset($persistence['sql_check_done'])) {
574                 // reset flag to not check (on Recheck)
575                 unset($persistence['sql_check_done']);
576                 unset($persistence['sql_errors']);
577         }
578
579         // get schema script if not loaded
580         if($preflight)
581                 logThis('starting schema preflight check...');
582         else
583                 logThis('Preparing SQL statements for sequential execution...');
584
585     if (empty($sugar_db_version))
586     {
587         include('sugar_version.php');
588     }
589
590         if(!isset($manifest['version']) || empty($manifest['version'])) {
591                 include($persistence['unzip_dir'].'/manifest.php');
592         }
593
594     $origVersion = implodeVersion($sugar_db_version);
595     $destVersion = implodeVersion($manifest['version']);
596
597     $script_name = $db->getScriptType();
598     $sqlScript = $persistence['unzip_dir']."/scripts/{$origVersion}_to_{$destVersion}_{$script_name}.sql";
599
600         $newTables = array();
601
602         logThis('looking for schema script at: '.$sqlScript);
603         if(is_file($sqlScript)) {
604                 logThis('found schema upgrade script: '.$sqlScript);
605                 $fp = sugar_fopen($sqlScript, 'r');
606
607                 if(!empty($fp)) {
608                         $completeLine = '';
609                         while($line = fgets($fp)) {
610                                 if(strpos($line, '--') === false) {
611                                         $completeLine .= " ".trim($line);
612                                         if(strpos($line, ';') !== false) {
613                                                 $completeLine = str_replace(';','',$completeLine);
614                                                 $persistence['sql_to_check'][] = $completeLine;
615                                                 $completeLine = ''; //reset for next loop
616                                         }
617                                 }
618                         }
619
620                         $persistence['sql_total'] = count($persistence['sql_to_check']);
621                 } else {
622                         logThis('*** ERROR: could not read schema script: '.$sqlScript);
623                         $persistence['sql_errors'][] = $mod_strings['ERR_UW_FILE_NOT_READABLE'].'::'.$sqlScript;
624                 }
625         }
626
627         // load a new array if for commit
628         if($preflight) {
629                 $persistence['sql_to_check_backup'] = $persistence['sql_to_check'];
630                 $persistence['sql_to_run'] = $persistence['sql_to_check'];
631                 echo "1% ".$mod_strings['LBL_UW_DONE'];
632         } else {
633                 $persistence['sql_to_run'] = $persistence['sql_to_check'];
634                 unset($persistence['sql_to_check']);
635         }
636
637         return $persistence;
638 }
639
640 function preflightCheckJsonSchemaCheck($persistence) {
641         global $mod_strings;
642         global $db;
643
644         if(!isset($persistence['sql_check_done']) || $persistence['sql_check_done'] != true) {
645                 // must keep sql in order
646                 $completeLine = array_shift($persistence['sql_to_check']);
647                 $whatsLeft = count($persistence['sql_to_check']);
648
649                 // populate newTables array to prevent "getting sample data" from non-existent tables
650                 $newTables = array();
651                 if(strtoupper(substr($completeLine,1,5)) == 'CREAT')
652                         $newTables[] = getTableFromQuery($completeLine);
653
654         logThis('Verifying statement: '.$completeLine);
655                 $bad = $db->verifySQLStatement($completeLine, $newTables);
656
657                 if(!empty($bad)) {
658                         logThis('*** ERROR: schema change script has errors: '.$completeLine);
659             logThis('*** '.$bad);
660                         $persistence['sql_errors'][] = getFormattedError($bad, $completeLine);
661                 }
662
663                 $persistence = ajaxSqlProgress($persistence, $completeLine, 'sql_to_check');
664         } else {
665                 $persistence['sql_to_check'] = $persistence['sql_to_check_backup'];
666                 echo 'done';
667         }
668
669         return $persistence;
670 }
671
672
673 function preflightCheckJsonGetSchemaErrors($persistence) {
674         global $mod_strings;
675
676         if(isset($persistence['sql_errors']) && count($persistence['sql_errors'] > 0)) {
677                 $out = "<b class='error'>{$mod_strings['ERR_UW_PREFLIGHT_ERRORS']}:</b> ";
678                 $out .= "<a href='javascript:void(0);toggleNwFiles(\"sqlErrors\");'>{$mod_strings['LBL_UW_SHOW_SQL_ERRORS']}</a><div id='sqlErrors' style='display:none'>";
679                 foreach($persistence['sql_errors'] as $sqlError) {
680                         $out .= "<br><span class='error'>{$sqlError}</span>";
681                 }
682                 $out .= "</div><hr />";
683         } else {
684                 $out = '';
685         }
686
687         // reset errors if Rechecking
688         if(isset($persistence['sql_errors']))
689                 //unset($persistence['sql_errors']);
690
691         echo $out;
692
693         return $persistence;
694 }
695
696
697 function preflightCheckJsonFillSchema() {
698         global $mod_strings;
699         global $persistence;
700         global $sugar_db_version;
701         global $manifest;
702         global $db;
703
704     if (empty($sugar_db_version))
705     {
706         include('sugar_version.php');
707     }
708         if(empty($manifest)) {
709                 include($persistence['unzip_dir'].'/manifest.php');
710         }
711
712         ///////////////////////////////////////////////////////////////////////////////
713         ////    SCHEMA SCRIPT HANDLING
714         $schema = '';
715         $alterTableSchemaOut = '';
716
717     $origVersion = implodeVersion($sugar_db_version);
718     $destVersion = implodeVersion($manifest['version']);
719
720     $script_name = $db->getScriptType();
721     $sqlScript = $persistence['unzip_dir']."/scripts/{$origVersion}_to_{$destVersion}_{$script_name}.sql";
722         $newTables = array();
723
724         logThis('looking for SQL script for DISPLAY at '.$sqlScript);
725         if(file_exists($sqlScript)) {
726                 $contents = sugar_file_get_contents($sqlScript);
727                 $schema  = "<p><a href='javascript:void(0); toggleNwFiles(\"schemashow\");'>{$mod_strings['LBL_UW_SHOW_SCHEMA']}</a>";
728                 $schema .= "<div id='schemashow' style='display:none;'>";
729                 $schema .= "<textarea readonly cols='80' rows='10'>{$contents}</textarea>";
730                 $schema .= "</div></p>";
731         }
732         ////    END SCHEMA SCRIPT HANDLING
733         ///////////////////////////////////////////////////////////////////////////////
734
735         ob_start();
736         echo $schema;
737         ob_flush();
738 }
739
740
741 function preflightCheckJsonAlterTableCharset() {
742         global $mod_strings;
743         global $sugar_db_version;
744         global $persistence;
745
746         if(empty($sugar_db_version))
747                 include('sugar_version.php');
748
749     $alterTableSchema = '<i>'.$mod_strings['LBL_UW_PREFLIGHT_NOT_NEEDED'].'</i>';
750
751         ob_start();
752         echo $alterTableSchema;
753         ob_flush();
754 }
755
756
757 ///////////////////////////////////////////////////////////////////////////////
758 ////    SYSTEMCHECK AJAX FUNCTIONS
759
760 function systemCheckJsonGetFiles($persistence) {
761         global $sugar_config;
762         global $mod_strings;
763
764         // add directories here that should be skipped when doing file permissions checks (cache/upload is the nasty one)
765         $skipDirs = array(
766                 $sugar_config['upload_dir'],
767                 'themes',
768         );
769
770         if(!isset($persistence['dirs_checked'])) {
771                 $the_array = array();
772                 $files = array();
773                 $dir = getcwd();
774                 $d = dir($dir);
775                 while($f = $d->read()) {
776                     if($f == "." || $f == "..") // skip *nix self/parent
777                         continue;
778
779                     if(is_dir("$dir/$f"))
780                                 $the_array[] = clean_path("$dir/$f");
781                         else {
782                                 $files[] = clean_path("$dir/$f");
783                         }
784                 }
785                 $persistence['files_to_check'] = $files;
786                 $persistence['dirs_to_check'] = $the_array;
787                 $persistence['dirs_total']      = count($the_array);
788                 $persistence['dirs_checked'] = false;
789
790                 $out = "1% {$mod_strings['LBL_UW_DONE']}";
791
792                 return $persistence;
793         } elseif($persistence['dirs_checked'] == false) {
794                 $dir = array_pop($persistence['dirs_to_check']);
795
796                 $files = uwFindAllFiles($dir, array(), true, $skipDirs);
797
798                 $persistence['files_to_check'] = array_merge($persistence['files_to_check'], $files);
799
800                 $whatsLeft = count($persistence['dirs_to_check']);
801
802                 if(!isset($persistence['dirs_to_check']) || $whatsLeft < 1) {
803                         $whatsLeft = 0;
804                         $persistence['dirs_checked'] = true;
805                 }
806
807                 $out  = round((($persistence['dirs_total'] - $whatsLeft) / 21) * 100, 1)."% {$mod_strings['LBL_UW_DONE']}";
808                 $out .= " [{$mod_strings['LBL_UW_SYSTEM_CHECK_CHECKING_JSON']} {$dir}]";
809         } else {
810                 $out = "Done";
811         }
812
813         echo trim($out);
814
815         return $persistence;
816 }
817
818
819
820 /**
821  * checks files for permissions
822  * @param array files Array of files with absolute paths
823  * @return string result of check
824  */
825 function systemCheckJsonCheckFiles($persistence) {
826         global $mod_strings;
827         global $persistence;
828
829         $filesNotWritable = array();
830         $i=0;
831         $filesOut = "
832                 <a href='javascript:void(0); toggleNwFiles(\"filesNw\");'>{$mod_strings['LBL_UW_SHOW_NW_FILES']}</a>
833                 <div id='filesNw' style='display:none;'>
834                 <table cellpadding='3' cellspacing='0' border='0'>
835                 <tr>
836                         <th align='left'>{$mod_strings['LBL_UW_FILE']}</th>
837                         <th align='left'>{$mod_strings['LBL_UW_FILE_PERMS']}</th>
838                         <th align='left'>{$mod_strings['LBL_UW_FILE_OWNER']}</th>
839                         <th align='left'>{$mod_strings['LBL_UW_FILE_GROUP']}</th>
840                 </tr>";
841
842         $isWindows = is_windows();
843         foreach($persistence['files_to_check'] as $file) {
844         //      while($file = array_pop($persistence['files_to_check'])) {
845
846                 // admin deletes a bad file mid-check:
847                 if(!file_exists($file))
848                         continue;
849
850                 if($isWindows) {
851                         if(!is_writable_windows($file)) {
852                                 logThis('WINDOWS: File ['.$file.'] not readable - saving for display');
853                                 // don't warn yet - we're going to use this to check against replacement files
854                                 $filesNotWritable[$i] = $file;
855                                 $filesNWPerms[$i] = substr(sprintf('%o',fileperms($file)), -4);
856                                 $filesOut .= "<tr>".
857                                                                 "<td valign='top'><span class='error'>{$file}</span></td>".
858                                                                 "<td valign='top'>{$filesNWPerms[$i]}</td>".
859                                                                 "<td valign='top'>".$mod_strings['ERR_UW_CANNOT_DETERMINE_USER']."</td>".
860                                                                 "<td valign='top'>".$mod_strings['ERR_UW_CANNOT_DETERMINE_GROUP']."</td>".
861                                                           "</tr>";
862                         }
863                 } else {
864                         if(!is_writable($file)) {
865                                 logThis('File ['.$file.'] not writable - saving for display');
866                                 // don't warn yet - we're going to use this to check against replacement files
867                                 $filesNotWritable[$i] = $file;
868                                 $filesNWPerms[$i] = substr(sprintf('%o',fileperms($file)), -4);
869                                 $owner = posix_getpwuid(fileowner($file));
870                                 $group = posix_getgrgid(filegroup($file));
871                                 $filesOut .= "<tr>".
872                                                                 "<td valign='top'><span class='error'>{$file}</span></td>".
873                                                                 "<td valign='top'>{$filesNWPerms[$i]}</td>".
874                                                                 "<td valign='top'>".$owner['name']."</td>".
875                                                                 "<td valign='top'>".$group['name']."</td>".
876                                                           "</tr>";
877                         }
878                 }
879                 $i++;
880         }
881
882         $filesOut .= '</table></div>';
883         // not a stop error
884         $persistence['filesNotWritable'] = (count($filesNotWritable) > 0) ? true : false;
885
886         if(count($filesNotWritable) < 1) {
887                 $filesOut = "{$mod_strings['LBL_UW_FILE_NO_ERRORS']}";
888                 $persistence['step']['systemCheck'] = 'success';
889         }
890
891         echo $filesOut;
892         return $persistence;
893 }