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-2013 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 (empty($sugar_version))
374 require('sugar_version.php');
378 $md5_string = array();
379 $finalZipDir = $persistence['unzip_dir'].'/'.$persistence['zip_from_dir'];
381 if(is_file(getcwd().'/files.md5'))
382 require(getcwd().'/files.md5');
384 // initialize pass array
385 $manualDiff = array();
387 // file preflight checks
388 logThis('verifying md5 checksums for files...');
389 $cache_html_files = findAllFilesRelative(sugar_cached("layout"), array());
391 foreach($persistence['upgrade_files'] as $file) {
392 if(strpos($file, '.md5'))
393 continue; // skip md5 file
395 // normalize file paths
396 $file = clean_path($file);
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;
402 // check that destination files are writable
403 $destFile = getcwd().str_replace($finalZipDir, '', $file);
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;
411 ///////////////////////////////////////////////////////////////////////
413 // compare md5s and build up a manual merge list
414 $targetFile = clean_path(".".str_replace(getcwd(),'',$destFile));
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);
421 $fileContents = file_get_contents($destFile);
422 $targetMd5 = md5($fileContents);
425 $targetMd5 = md5_file($destFile);
429 if(isset($md5_string[$targetFile]) && $md5_string[$targetFile] != $targetMd5) {
430 logThis('found a file with a differing md5: ['.$targetFile.']');
431 $manualDiff[] = $destFile;
434 ///////////////////////////////////////////////////////////////////////
437 logThis('md5 verification done.');
439 $persistence['manual'] = $manualDiff;
440 $persistence['diff_errors'] = $errors;
446 function preflightCheckJsonGetDiff($persistence) {
448 global $current_user;
450 $out = $mod_strings['LBL_UW_PREFLIGHT_TESTS_PASSED'];
453 $disableEmail = (empty($current_user->email1)) ? 'DISABLED' : 'CHECKED';
455 if(count($persistence['manual']) > 0) {
456 $preserveFiles = array();
459 <script type="text/javascript" language="Javascript">
460 function preflightToggleAll(cb) {
461 var checkAll = false;
462 var form = document.getElementById('diffs');
464 if(cb.checked == true) {
468 for(i=0; i<form.elements.length; i++) {
469 if(form.elements[i].type == 'checkbox') {
470 form.elements[i].checked = checkAll;
477 <table cellpadding='0' cellspacing='0' border='0'>
480 <input type='checkbox' name='addTask' id='addTask' CHECKED>
483 {$mod_strings['LBL_UW_PREFLIGHT_ADD_TASK']}
488 <input type='checkbox' name='addEmail' id='addEmail' $disableEmail>
491 {$mod_strings['LBL_UW_PREFLIGHT_EMAIL_REMINDER']}
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'>
501 <td valign='top' colspan='2'>
502 {$mod_strings['LBL_UW_PREFLIGHT_FILES_DESC']}
507 <td valign='top' colspan='2'>
508 <input type='checkbox' onchange='preflightToggleAll(this);'> <i><b>{$mod_strings['LBL_UW_PREFLIGHT_TOGGLE_ALL']}</b></i>
513 foreach($persistence['manual'] as $diff) {
514 $diff = clean_path($diff);
515 $persistence['files']['manual'][] = $diff;
517 $checked = (isAutoOverwriteFile($diff)) ? 'CHECKED' : '';
519 if(empty($checked)) {
520 $preserveFiles[] = $diff;
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>";
529 $diffs .= "</table>";
530 $diffs .= "</div></p>";
533 // list preserved files (templates, etc.)
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>";
541 $preserve .= "<tr><td valign='top'><i>".str_replace(getcwd(), '.', $pf)."</i></td></tr>";
543 if(!empty($preserve)) {
544 $preserve .= '</table><br>';
546 $diffs = $preserve.$diffs;
547 } else { // NO FILE DIFFS REQUIRED
548 $diffs = $mod_strings['LBL_UW_PREFLIGHT_NO_DIFFS'];
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
562 function preflightCheckJsonPrepSchemaCheck($persistence, $preflight=true) {
565 global $sugar_db_version;
568 unset($persistence['sql_to_run']);
570 $persistence['sql_to_check'] = array();
571 $persistence['sql_to_check_backup'] = array();
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']);
579 // get schema script if not loaded
581 logThis('starting schema preflight check...');
583 logThis('Preparing SQL statements for sequential execution...');
585 if (empty($sugar_db_version))
587 include('sugar_version.php');
590 if(!isset($manifest['version']) || empty($manifest['version'])) {
591 include($persistence['unzip_dir'].'/manifest.php');
594 $origVersion = implodeVersion($sugar_db_version);
595 $destVersion = implodeVersion($manifest['version']);
597 $script_name = $db->getScriptType();
598 $sqlScript = $persistence['unzip_dir']."/scripts/{$origVersion}_to_{$destVersion}_{$script_name}.sql";
600 $newTables = array();
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');
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
620 $persistence['sql_total'] = count($persistence['sql_to_check']);
622 logThis('*** ERROR: could not read schema script: '.$sqlScript);
623 $persistence['sql_errors'][] = $mod_strings['ERR_UW_FILE_NOT_READABLE'].'::'.$sqlScript;
627 // load a new array if for commit
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'];
633 $persistence['sql_to_run'] = $persistence['sql_to_check'];
634 unset($persistence['sql_to_check']);
640 function preflightCheckJsonSchemaCheck($persistence) {
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']);
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);
654 logThis('Verifying statement: '.$completeLine);
655 $bad = $db->verifySQLStatement($completeLine, $newTables);
658 logThis('*** ERROR: schema change script has errors: '.$completeLine);
659 logThis('*** '.$bad);
660 $persistence['sql_errors'][] = getFormattedError($bad, $completeLine);
663 $persistence = ajaxSqlProgress($persistence, $completeLine, 'sql_to_check');
665 $persistence['sql_to_check'] = $persistence['sql_to_check_backup'];
673 function preflightCheckJsonGetSchemaErrors($persistence) {
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>";
682 $out .= "</div><hr />";
687 // reset errors if Rechecking
688 if(isset($persistence['sql_errors']))
689 //unset($persistence['sql_errors']);
697 function preflightCheckJsonFillSchema() {
700 global $sugar_db_version;
704 if (empty($sugar_db_version))
706 include('sugar_version.php');
708 if(empty($manifest)) {
709 include($persistence['unzip_dir'].'/manifest.php');
712 ///////////////////////////////////////////////////////////////////////////////
713 //// SCHEMA SCRIPT HANDLING
715 $alterTableSchemaOut = '';
717 $origVersion = implodeVersion($sugar_db_version);
718 $destVersion = implodeVersion($manifest['version']);
720 $script_name = $db->getScriptType();
721 $sqlScript = $persistence['unzip_dir']."/scripts/{$origVersion}_to_{$destVersion}_{$script_name}.sql";
722 $newTables = array();
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>";
732 //// END SCHEMA SCRIPT HANDLING
733 ///////////////////////////////////////////////////////////////////////////////
741 function preflightCheckJsonAlterTableCharset() {
743 global $sugar_db_version;
746 if(empty($sugar_db_version))
747 include('sugar_version.php');
749 $alterTableSchema = '<i>'.$mod_strings['LBL_UW_PREFLIGHT_NOT_NEEDED'].'</i>';
752 echo $alterTableSchema;
757 ///////////////////////////////////////////////////////////////////////////////
758 //// SYSTEMCHECK AJAX FUNCTIONS
760 function systemCheckJsonGetFiles($persistence) {
761 global $sugar_config;
764 // add directories here that should be skipped when doing file permissions checks (cache/upload is the nasty one)
766 $sugar_config['upload_dir'],
770 if(!isset($persistence['dirs_checked'])) {
771 $the_array = array();
775 while($f = $d->read()) {
776 if($f == "." || $f == "..") // skip *nix self/parent
779 if(is_dir("$dir/$f"))
780 $the_array[] = clean_path("$dir/$f");
782 $files[] = clean_path("$dir/$f");
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;
790 $out = "1% {$mod_strings['LBL_UW_DONE']}";
793 } elseif($persistence['dirs_checked'] == false) {
794 $dir = array_pop($persistence['dirs_to_check']);
796 $files = uwFindAllFiles($dir, array(), true, $skipDirs);
798 $persistence['files_to_check'] = array_merge($persistence['files_to_check'], $files);
800 $whatsLeft = count($persistence['dirs_to_check']);
802 if(!isset($persistence['dirs_to_check']) || $whatsLeft < 1) {
804 $persistence['dirs_checked'] = true;
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}]";
821 * checks files for permissions
822 * @param array files Array of files with absolute paths
823 * @return string result of check
825 function systemCheckJsonCheckFiles($persistence) {
829 $filesNotWritable = array();
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'>
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>
842 $isWindows = is_windows();
843 foreach($persistence['files_to_check'] as $file) {
844 // while($file = array_pop($persistence['files_to_check'])) {
846 // admin deletes a bad file mid-check:
847 if(!file_exists($file))
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);
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>".
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));
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>".
882 $filesOut .= '</table></div>';
884 $persistence['filesNotWritable'] = (count($filesNotWritable) > 0) ? true : false;
886 if(count($filesNotWritable) < 1) {
887 $filesOut = "{$mod_strings['LBL_UW_FILE_NO_ERRORS']}";
888 $persistence['step']['systemCheck'] = 'success';