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.
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.
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
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
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.
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.
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 ********************************************************************************/
38 /*********************************************************************************
41 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc. All Rights
42 * Reserved. Contributor(s): ______________________________________..
43 * *******************************************************************************/
48 function ajaxSqlProgress($persistence, $sql, $type) {
51 // $type is sql_to_check or sql_to_run
52 $whatsLeft = count($persistence[$type]);
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>";
63 $persistence['sql_check_done'] = true;
70 ///////////////////////////////////////////////////////////////////////////////
73 * does post-post-install stuff
74 * @param array persistence
75 * @return array persistence
77 function commitAjaxFinalTouches($persistence) {
81 global $sugar_version;
83 if(empty($sugar_version)) {
84 require('sugar_version.php');
87 // convert to UTF8 if needed
88 if(!empty($persistence['allTables']))
89 executeConvertTablesSql($persistence['allTables']);
92 logThis('Performing UWrebuild()...');
94 logThis('UWrebuild() done.');
97 registerUpgrade($persistence);
99 // flag to say upgrade has completed
100 $persistence['upgrade_complete'] = true;
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";
111 foreach($persistence['skipped_files'] as $file) {
116 $nowDate = $timedate->nowDbDate();
117 $nowTime = $timedate->asDbTime($timedate->getNow());
118 $nowDateTime = $nowDate.' '.$nowTime;
120 if($_REQUEST['addTaskReminder'] == 'remind') {
121 logThis('Adding Task for admin for manual merge.');
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;
137 if($_REQUEST['addEmailReminder'] == 'remind') {
138 logThis('Sending Reminder for admin for manual merge.');
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;
156 //// HANDLE REMINDERS
157 ///////////////////////////////////////////////////////////////////////////////
170 * runs one line of sql
171 * @param array $persistence
172 * @return array $persistence
174 function commitAjaxRunSql($persistence) {
177 if(!isset($persistence['commit_sql_errors'])) {
178 $persistence['commit_sql_errors'] = array();
181 // This flag is determined by the preflight check in the installer
182 if($persistence['schema_change'] == 'sugar') {
184 if(isset($persistence['sql_to_run'])
185 && count($persistence['sql_to_run']) > 0
186 && !empty($persistence['sql_to_run'])) {
188 $sql = array_shift($persistence['sql_to_run']);
192 logThis("[RUNNING SQL QUERY] {$sql}");
195 $error = $db->lastError();
197 logThis('************************************************************');
198 logThis('*** ERROR: SQL Commit Error!');
199 logThis('*** Query: [ '.$sql.' ]');
200 logThis('************************************************************');
201 $persistence['commit_sql_errors'][] = getFormattedError($error, $sql);
203 $persistence = ajaxSqlProgress($persistence, $sql, 'sql_to_run');
221 * returns errors found during SQL operations
222 * @param array persistence
223 * @return string Error message or empty string on success
225 function commitAjaxGetSqlErrors($persistence) {
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) {
238 $out = $mod_strings['LBL_UW_COMMIT_ALL_SQL_SUCCESSFULLY_RUN'];
247 * parses the sql upgrade file for sequential querying
248 * @param array persistence
249 * @return array persistence
251 function commitAjaxPrepSql($persistence) {
252 return preflightCheckJsonPrepSchemaCheck($persistence, false);
257 * handles post-install tasks
259 function commitAjaxPostInstall($persistence) {
261 global $sugar_config;
262 global $sugar_version;
264 if(empty($sugar_version)) {
265 require('sugar_version.php');
268 // update versions info
269 if(!updateVersions($sugar_version)) {
270 echo $mod_strings['ERR_UW_COMMIT_UPDATE_VERSIONS'];
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');
284 require( "sugar_version.php" );
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'];
291 $res = ob_get_contents();
292 $postInstallResults .= (empty($res)) ? $mod_strings['LBL_UW_SUCCESS'] : $res;
293 $postInstallResults .= "</div>";
296 echo $postInstallResults;
299 logThis('post_install() done.');
302 ///////////////////////////////////////////////////////////////////////////////
306 ///////////////////////////////////////////////////////////////////////////////
307 //// PREFLIGHT JSON STYLE
309 function preflightCheckJsonFindUpgradeFiles($persistence) {
310 global $sugar_config;
313 unset($persistence['rebuild_relationships']);
314 unset($persistence['rebuild_extensions']);
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...');
322 $base_upgrade_dir = "upload://upgrades";
323 $base_tmp_upgrade_dir = sugar_cached("upgrades/temp");
324 $install_file = urldecode( $persistence['install_file'] );
326 $unzip_dir = mk_temp_dir( $base_tmp_upgrade_dir );
329 $zip_force_copy = array();
331 unzip( $install_file, $unzip_dir );
333 // assumption -- already validated manifest.php at time of upload
334 include( "$unzip_dir/manifest.php" );
336 if( isset( $manifest['copy_files']['from_dir'] ) && $manifest['copy_files']['from_dir'] != "" ){
337 $zip_from_dir = $manifest['copy_files']['from_dir'];
339 if( isset( $manifest['copy_files']['to_dir'] ) && $manifest['copy_files']['to_dir'] != "" ){
340 $zip_to_dir = $manifest['copy_files']['to_dir'];
342 if( isset( $manifest['copy_files']['force_copy'] ) && $manifest['copy_files']['force_copy'] != "" ){
343 $zip_force_copy = $manifest['copy_files']['force_copy'];
345 if( isset( $manifest['version'] ) ){
346 $version = $manifest['version'];
348 if( !is_writable( "config.php" ) ){
349 logThis('BAD error');
350 return $mod_strings['ERR_UW_CONFIG'];
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);
357 logThis('unzip done.');
359 $unzip_dir = $persistence['unzip_dir'];
360 $zip_from_dir = $persistence['zip_from_dir'];
363 $persistence['upgrade_files'] = uwFindAllFiles(clean_path("$unzip_dir/$zip_from_dir"), array(), true, array(), true);
368 function preflightCheckJsonDiffFiles($persistence) {
369 global $sugar_version;
372 if(!isset($sugar_version) || empty($sugar_version)) {
377 $md5_string = array();
378 $finalZipDir = $persistence['unzip_dir'].'/'.$persistence['zip_from_dir'];
380 if(is_file(getcwd().'/files.md5'))
381 require(getcwd().'/files.md5');
383 // initialize pass array
384 $manualDiff = array();
386 // file preflight checks
387 logThis('verifying md5 checksums for files...');
388 $cache_html_files = findAllFilesRelative(sugar_cached("layout"), array());
390 foreach($persistence['upgrade_files'] as $file) {
391 if(strpos($file, '.md5'))
392 continue; // skip md5 file
394 // normalize file paths
395 $file = clean_path($file);
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;
401 // check that destination files are writable
402 $destFile = getcwd().str_replace($finalZipDir, '', $file);
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;
410 ///////////////////////////////////////////////////////////////////////
412 // compare md5s and build up a manual merge list
413 $targetFile = clean_path(".".str_replace(getcwd(),'',$destFile));
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);
420 $fileContents = file_get_contents($destFile);
421 $targetMd5 = md5($fileContents);
424 $targetMd5 = md5_file($destFile);
428 if(isset($md5_string[$targetFile]) && $md5_string[$targetFile] != $targetMd5) {
429 logThis('found a file with a differing md5: ['.$targetFile.']');
430 $manualDiff[] = $destFile;
433 ///////////////////////////////////////////////////////////////////////
436 logThis('md5 verification done.');
438 $persistence['manual'] = $manualDiff;
439 $persistence['diff_errors'] = $errors;
445 function preflightCheckJsonGetDiff($persistence) {
447 global $current_user;
449 $out = $mod_strings['LBL_UW_PREFLIGHT_TESTS_PASSED'];
452 $disableEmail = (empty($current_user->email1)) ? 'DISABLED' : 'CHECKED';
454 if(count($persistence['manual']) > 0) {
455 $preserveFiles = array();
458 <script type="text/javascript" language="Javascript">
459 function preflightToggleAll(cb) {
460 var checkAll = false;
461 var form = document.getElementById('diffs');
463 if(cb.checked == true) {
467 for(i=0; i<form.elements.length; i++) {
468 if(form.elements[i].type == 'checkbox') {
469 form.elements[i].checked = checkAll;
476 <table cellpadding='0' cellspacing='0' border='0'>
479 <input type='checkbox' name='addTask' id='addTask' CHECKED>
482 {$mod_strings['LBL_UW_PREFLIGHT_ADD_TASK']}
487 <input type='checkbox' name='addEmail' id='addEmail' $disableEmail>
490 {$mod_strings['LBL_UW_PREFLIGHT_EMAIL_REMINDER']}
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'>
500 <td valign='top' colspan='2'>
501 {$mod_strings['LBL_UW_PREFLIGHT_FILES_DESC']}
506 <td valign='top' colspan='2'>
507 <input type='checkbox' onchange='preflightToggleAll(this);'> <i><b>{$mod_strings['LBL_UW_PREFLIGHT_TOGGLE_ALL']}</b></i>
512 foreach($persistence['manual'] as $diff) {
513 $diff = clean_path($diff);
514 $persistence['files']['manual'][] = $diff;
516 $checked = (isAutoOverwriteFile($diff)) ? 'CHECKED' : '';
518 if(empty($checked)) {
519 $preserveFiles[] = $diff;
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>";
528 $diffs .= "</table>";
529 $diffs .= "</div></p>";
532 // list preserved files (templates, etc.)
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>";
540 $preserve .= "<tr><td valign='top'><i>".str_replace(getcwd(), '.', $pf)."</i></td></tr>";
542 if(!empty($preserve)) {
543 $preserve .= '</table><br>';
545 $diffs = $preserve.$diffs;
546 } else { // NO FILE DIFFS REQUIRED
547 $diffs = $mod_strings['LBL_UW_PREFLIGHT_NO_DIFFS'];
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
561 function preflightCheckJsonPrepSchemaCheck($persistence, $preflight=true) {
564 global $sugar_db_version;
567 unset($persistence['sql_to_run']);
569 $persistence['sql_to_check'] = array();
570 $persistence['sql_to_check_backup'] = array();
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']);
578 // get schema script if not loaded
580 logThis('starting schema preflight check...');
582 logThis('Preparing SQL statements for sequential execution...');
584 if(!isset($sugar_db_version) || empty($sugar_db_version)) {
585 include('./sugar_version.php');
588 if(!isset($manifest['version']) || empty($manifest['version'])) {
589 include($persistence['unzip_dir'].'/manifest.php');
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";
597 $newTables = array();
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');
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
617 $persistence['sql_total'] = count($persistence['sql_to_check']);
619 logThis('*** ERROR: could not read schema script: '.$sqlScript);
620 $persistence['sql_errors'][] = $mod_strings['ERR_UW_FILE_NOT_READABLE'].'::'.$sqlScript;
624 // load a new array if for commit
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'];
630 $persistence['sql_to_run'] = $persistence['sql_to_check'];
631 unset($persistence['sql_to_check']);
637 function preflightCheckJsonSchemaCheck($persistence) {
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']);
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);
651 logThis('Verifying statement: '.$completeLine);
652 $bad = $db->verifySQLStatement($completeLine, $newTables);
655 logThis('*** ERROR: schema change script has errors: '.$completeLine);
656 logThis('*** '.$bad);
657 $persistence['sql_errors'][] = getFormattedError($bad, $completeLine);
660 $persistence = ajaxSqlProgress($persistence, $completeLine, 'sql_to_check');
662 $persistence['sql_to_check'] = $persistence['sql_to_check_backup'];
670 function preflightCheckJsonGetSchemaErrors($persistence) {
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>";
679 $out .= "</div><hr />";
684 // reset errors if Rechecking
685 if(isset($persistence['sql_errors']))
686 //unset($persistence['sql_errors']);
694 function preflightCheckJsonFillSchema() {
697 global $sugar_db_version;
701 if(empty($sugar_db_version)) {
702 include('sugar_version');
704 if(empty($manifest)) {
705 include($persistence['unzip_dir'].'/manifest.php');
708 ///////////////////////////////////////////////////////////////////////////////
709 //// SCHEMA SCRIPT HANDLING
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();
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>";
726 //// END SCHEMA SCRIPT HANDLING
727 ///////////////////////////////////////////////////////////////////////////////
735 function preflightCheckJsonAlterTableCharset() {
737 global $sugar_db_version;
740 if(empty($sugar_db_version))
741 include('sugar_version.php');
743 $current_version = substr(preg_replace("#[^0-9]#", "", $sugar_db_version),0,3);
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>";
754 $alterTableSchema = '<i>'.$mod_strings['LBL_UW_PREFLIGHT_NOT_NEEDED'].'</i>';
758 echo $alterTableSchema;
763 ///////////////////////////////////////////////////////////////////////////////
764 //// SYSTEMCHECK AJAX FUNCTIONS
766 function systemCheckJsonGetFiles($persistence) {
767 global $sugar_config;
770 // add directories here that should be skipped when doing file permissions checks (cache/upload is the nasty one)
772 $sugar_config['upload_dir'],
776 if(!isset($persistence['dirs_checked'])) {
777 $the_array = array();
781 while($f = $d->read()) {
782 if($f == "." || $f == "..") // skip *nix self/parent
785 if(is_dir("$dir/$f"))
786 $the_array[] = clean_path("$dir/$f");
788 $files[] = clean_path("$dir/$f");
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;
796 $out = "1% {$mod_strings['LBL_UW_DONE']}";
799 } elseif($persistence['dirs_checked'] == false) {
800 $dir = array_pop($persistence['dirs_to_check']);
802 $files = uwFindAllFiles($dir, array(), true, $skipDirs);
804 $persistence['files_to_check'] = array_merge($persistence['files_to_check'], $files);
806 $whatsLeft = count($persistence['dirs_to_check']);
808 if(!isset($persistence['dirs_to_check']) || $whatsLeft < 1) {
810 $persistence['dirs_checked'] = true;
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}]";
827 * checks files for permissions
828 * @param array files Array of files with absolute paths
829 * @return string result of check
831 function systemCheckJsonCheckFiles($persistence) {
835 $filesNotWritable = array();
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'>
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>
848 $isWindows = is_windows();
849 foreach($persistence['files_to_check'] as $file) {
850 // while($file = array_pop($persistence['files_to_check'])) {
852 // admin deletes a bad file mid-check:
853 if(!file_exists($file))
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);
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>".
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));
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>".
888 $filesOut .= '</table></div>';
890 $persistence['filesNotWritable'] = (count($filesNotWritable) > 0) ? true : false;
892 if(count($filesNotWritable) < 1) {
893 $filesOut = "{$mod_strings['LBL_UW_FILE_NO_ERRORS']}";
894 $persistence['step']['systemCheck'] = 'success';