tHud Posted October 19, 2012 Share Posted October 19, 2012 (edited) Hello I have been using a certain forum software for many years now on an old php4 server. I recently trialed the software on a php5 server in preparation for upgrading. My forums appeared as plain white pages as soon as I altered any admin feature. I tracked the casue down to a function that locks and writes to the admin file. Whenever this function is called, the admin file gets wiped to zero bytes. // Lock a file, and write if lock was successful function lock_and_write($file, $body, $append = 0) { ignore_user_abort(1); $mode = ($append == 1) ? "a" : "w"; if ($fp = fopen($file, $mode)) { if (flock($fp, LOCK_EX)) { fwrite($fp, $body); flock($fp, LOCK_UN); fclose($fp); ignore_user_abort(0); return ""; } else { fclose($fp); ignore_user_abort(0); return "no_lock"; } } else { ignore_user_abort(0); return "no_write"; } } Can anyone suggest a better way of writing this function? This forum is quite well known and in use on many different platforms, other users are not reporting problems - so I guess I'm an oddity. I will seriously be considering moving to new software whether or not I can resolve this issue. (The new company owner doesn't appear the least bit interested in the product.) Edited October 19, 2012 by tHud Quote Link to comment Share on other sites More sharing options...
PFMaBiSmAd Posted October 19, 2012 Share Posted October 19, 2012 Do you have php's error_reporting set to E_ALL and display_errors set to ON so that php would help you by reporting and displaying all the errors it detects? You likely have a path or permission problem on the newer install of php. Quote Link to comment Share on other sites More sharing options...
tHud Posted October 19, 2012 Author Share Posted October 19, 2012 I'm hosted on a shared server - so I have created this htaccess file. php_flag display_errors on php_value error_reporting E_ALL Hopefully that's ok? However, no errors are being reported. When I update some admin setting the config file is being erased and all I see is a blank (white) screen. Quote Link to comment Share on other sites More sharing options...
DavidAM Posted October 19, 2012 Share Posted October 19, 2012 It is possible that the software is changing the setting in one of the configuration scripts. Try adding the following, as the first lines inside of that function, just long enough to test. error_reporting(E_ALL); ini_set('display_errors', 1); Quote Link to comment Share on other sites More sharing options...
kicken Posted October 19, 2012 Share Posted October 19, 2012 php_value error_reporting -1 You can't use the named constants like E_ALL in .htaccess, you have to use a numerical value. Have you verified that $body contains the proper data? I'd speculate that there is a problem elsewhere causing $body to be blank. Also what OS is this being run on? Some form of linux I am guessing. Quote Link to comment Share on other sites More sharing options...
DavidAM Posted October 19, 2012 Share Posted October 19, 2012 As a side note, once the permission issue (or whatever, is resolved); I would consider rewriting that to use file_get_contents and file_put_contents. Which, unless I am mistaken, are atomic and would not require the LOCKing strategy that is being used. Something like: if ($append == 1) { $body = file_get_contents($file) . $body); } file_put_contents($file, $body); Hmmm, well, file_put_contents() has a flag for APPEND and a flag for LOCK_EX. So, depending on the PHP version you are using, it could possibly be done without the file_get_contents() call. Having said all that; keep in mind, once you start making changes to third party software, upgrading to a future release can become problematic. Quote Link to comment Share on other sites More sharing options...
tHud Posted October 19, 2012 Author Share Posted October 19, 2012 (edited) Hi, .htaccess php_flag display_errors on php_value error_reporting 8191 From PHPinfo PHP Version 5.3.3-1ubuntu9.7 System Linux svr59.XXXXXX.com 2.6.35-22-server #35-Ubuntu SMP Sat Oct 16 22:02:33 UTC 2010 x86_64 I added these lines // Lock a file, and write if lock was successfulfunction lock_and_write($file, $body, $append = 0) { error_reporting(E_ALL); ini_set('display_errors', 1); echo $body; exit; ignore_user_abort(1); $mode = ($append == 1) ? "a" : "w"; if ($fp = fopen($file, $mode)) { if (flock($fp, LOCK_EX)) { fwrite($fp, $body); flock($fp, LOCK_UN); fclose($fp); ignore_user_abort(0); return ""; } else { fclose($fp); ignore_user_abort(0); return "no_lock"; } } else { ignore_user_abort(0); return "no_write"; } } ...and I see that $body contains all the expected data of a config file. Then I removed the echo /exit commands and the script predictably blanked the file again (unfortunately - no error reported). I did try using file_put_contents (just to check - and it worked). By that I mean that wherever another script calls that function - I replaced it with f_p_c - but there are so many calls to that function, I felt it better to ask here first. My inexperience with php meant that I was unable to re-write the original function using file_put_contents ..and of course, as you say - upgrades could be a serious issue ongoing. Edited October 19, 2012 by tHud Quote Link to comment Share on other sites More sharing options...
DavidAM Posted October 19, 2012 Share Posted October 19, 2012 ... My forums appeared as plain white pages ... When you get a blank white page, use the View -> Source feature of the browser to see if there is any "hidden" content. A malformed HTML tag could cause a problem. If there is anything there (in the view->source) show it to us. The function is returning a string indicating success or failure, I wonder what is happening to that string, more specifically, I wonder what string it is returning. Can you show us the code that calls that function in the script you are having trouble with? fopen with the "w" flag will truncate the file, so the indication is that one of the following functions is failing (flock or fwrite). There are no tests to see if the write or subsequent unlock is failing. Just for debugging purposes, try adding some error triggers in the code. See the lines below that are marked with "##": // Lock a file, and write if lock was successful function lock_and_write($file, $body, $append = 0) { error_reporting(E_ALL);## ini_set('display_errors', 1);## ignore_user_abort(1); $mode = ($append == 1) ? "a" : "w"; if ($fp = fopen($file, $mode)) { if (flock($fp, LOCK_EX)) { ##fwrite($fp, $body); if (! fwrite($fp, $body)) trigger_error('fwrite failed', E_USER_WARNING);## ##flock($fp, LOCK_UN); if (! flock($fp, LOCK_UN)) trigger_error('flock failed (unlock)', E_USER_WARNING);## fclose($fp); ignore_user_abort(0); return ""; } else { trigger_error('flock failed (lock)', E_USER_WARNING);## fclose($fp); ignore_user_abort(0); return "no_lock"; } } else { trigger_error('fopen failed', E_USER_WARNING);## ignore_user_abort(0); return "no_write"; } } This should print one or more error (warning) messages. Quote Link to comment Share on other sites More sharing options...
kicken Posted October 19, 2012 Share Posted October 19, 2012 ... but there are so many calls to that function, I felt it better to ask here first. You don't have to replace all the areas that call the lock_and_write function, you would just replace that functions body. function lock_and_write($file, $body, $append = 0){ $flags = LOCK_EX; if ($append){ $flags = $flags|FILE_APPEND; } file_put_contents($file, $body, $flags); } Quote Link to comment Share on other sites More sharing options...
tHud Posted October 19, 2012 Author Share Posted October 19, 2012 I tried replacing the function with the one you posted - and it's the same thing. No errors are reported and a white screen. (Source displays nothing except the #1 which I believe Firefox adds.) Here are some examples of the calls to the function... // Update community intro if necessary$oldintro = @file_get_contents("{$config['FULL_PATH']}/includes/community_intro.php"); $intro_text = get_input("intro_body","post"); if ($intro_text != $oldintro) { $check = lock_and_write("{$config['FULL_PATH']}/includes/community_intro.php",$intro_text); if ($check == "no_write") { $admin->error($ubbt_lang['NO_WRITE_INTRO']); } // end if } // end if // Update the header file if necessary $oldfile = ""; $fd = file("{$config['FULL_PATH']}/includes/header.php"); while (list($linenum,$line) = each($fd)) { $oldfile .= "$line"; } $headerfile = get_input("headerfile","post"); if ($headerfile!= $oldfile) { $check = lock_and_write("{$config['FULL_PATH']}/includes/header.php",$headerfile); if ($check == "no_write") { $admin->error($ubbt_lang['NO_WRITE_HEADER']); } // end if } // end if // Update the footer file if necessary $oldfile = ""; $fd = file("{$config['FULL_PATH']}/includes/footer.php"); while (list($linenum,$line) = each($fd)) { $oldfile .= "$line"; } $footerfile = get_input("footerfile","post"); if ($footerfile!= $oldfile) { $check = lock_and_write("{$config['FULL_PATH']}/includes/footer.php",$footerfile); if ($check == "no_write") { $admin->error($ubbt_lang['NO_WRITE_FOOTER']); } // end if } // end if // Update the insert file if necessary $oldfile = ""; $fd = file("{$config['FULL_PATH']}/includes/header-insert.php"); while (list($linenum,$line) = each($fd)) { $oldfile .= "$line"; } $insertfile = get_input("insertfile","post"); if ($insertfile!= $oldfile) { $check = lock_and_write("{$config['FULL_PATH']}/includes/header-insert.php",$insertfile); if ($check == "no_write") { $admin->error($ubbt_lang['NO_WRITE_INSERT']); } // end if } // end if Quote Link to comment Share on other sites More sharing options...
tHud Posted October 19, 2012 Author Share Posted October 19, 2012 Just for completeness, I should point out the the database connection variables are stored in the blanked file - which clearly will account for the white pages in the admin area. When trying to access the script as a user - there is an error message along the lines of ---- dbase error - contact admin. Quote Link to comment Share on other sites More sharing options...
DavidAM Posted October 19, 2012 Share Posted October 19, 2012 If you did not even get the WARNINGs I put in that last code, my guess is that they have a custom error handler which is trapping and hopefully logging the errors somewhere. You might try to find a log file from the app and see if it contains any recent messages. The code you just posted is checking for the "no write" result, but not for the "no lock" result. So, it would appear that the flock call is failing. However, the file_put_contents() version should not have been affected by that. Of course, we are assuming that you were correct when you stated that this function is the one causing the problems. I can't tell you how many times I've narrowed the problem down to a particular function, only to discover later that I was wrong about where the problem was. Try this version of the function. I changed the trigger_error() calls to print() and added a print of the filesize on entry and exit. See what we can see. // Lock a file, and write if lock was successful function lock_and_write($file, $body, $append = 0) { error_reporting(E_ALL);## ini_set('display_errors', 1);## print('Enter lock_and_write. Filesize = ' . filesize($file) . '<BR>');## ignore_user_abort(1); $mode = ($append == 1) ? "a" : "w"; if ($fp = fopen($file, $mode)) { if (flock($fp, LOCK_EX)) { ##fwrite($fp, $body); if (! fwrite($fp, $body)) print('fwrite failed!<BR>');## ##flock($fp, LOCK_UN); if (! flock($fp, LOCK_UN)) print('flock failed (unlock)!<BR>');## fclose($fp); ignore_user_abort(0); print('Exit lock_and_write (OK). Filesize = ' . filesize($file) . '<BR>');## return ""; } else { print('flock failed (lock)!<BR>');## fclose($fp); ignore_user_abort(0); print('Exit lock_and_write (no lock). Filesize = ' . filesize($file) . '<BR>');## return "no_lock"; } } else { print('fopen failed!<BR>');## ignore_user_abort(0); print('Exit lock_and_write (no write). Filesize = ' . filesize($file) . '<BR>');## return "no_write"; } } Quote Link to comment Share on other sites More sharing options...
tHud Posted October 19, 2012 Author Share Posted October 19, 2012 Of course, we are assuming that you were correct when you stated that this function is the one causing the problems. I can't tell you how many times I've narrowed the problem down to a particular function, only to discover later that I was wrong about where the problem was. ha ha yes! In younger days I was an electronics engineer and I certainly know that feeling Well, the screen flashed briefly before going blank but eventually I managed to copy these messages. Enter lock_and_write. Filesize = 7316 flock failed (lock)! Exit lock_and_write (no lock). Filesize = 7316 Enter lock_and_write. Filesize = 0 flock failed (lock)! Exit lock_and_write (no lock). Filesize = 0 Enter lock_and_write. Filesize = 0 flock failed (lock)! Exit lock_and_write (no lock). Filesize = 0 Enter lock_and_write. Filesize = 0 flock failed (lock)! Exit lock_and_write (no lock). Filesize = 0 Enter lock_and_write. Filesize = 0 flock failed (lock)! Exit lock_and_write (no lock). Filesize = 0 Enter lock_and_write. Filesize = 0 flock failed (lock)! Exit lock_and_write (no lock). Filesize = 0 Enter lock_and_write. Filesize = 0 flock failed (lock)! Exit lock_and_write (no lock). Filesize = 0 Enter lock_and_write. Filesize = 0 flock failed (lock)! Exit lock_and_write (no lock). Filesize = 0 Enter lock_and_write. Filesize = 0 flock failed (lock)! Exit lock_and_write (no lock). Filesize = 0 Enter lock_and_write. Filesize = 0 flock failed (lock)! Exit lock_and_write (no lock). Filesize = 0 Enter lock_and_write. Filesize = 0 flock failed (lock)! Exit lock_and_write (no lock). Filesize = 0 Enter lock_and_write. Filesize = 0 flock failed (lock)! Exit lock_and_write (no lock). Filesize = 0 Enter lock_and_write. Filesize = 0 flock failed (lock)! Exit lock_and_write (no lock). Filesize = 0 Enter lock_and_write. Filesize = 0 flock failed (lock)! Exit lock_and_write (no lock). Filesize = 0 Enter lock_and_write. Filesize = 0 flock failed (lock)! Exit lock_and_write (no lock). Filesize = 0 Enter lock_and_write. Filesize = 0 flock failed (lock)! Exit lock_and_write (no lock). Filesize = 0 Enter lock_and_write. Filesize = 0 flock failed (lock)! Exit lock_and_write (no lock). Filesize = 0 Enter lock_and_write. Filesize = 0 flock failed (lock)! Exit lock_and_write (no lock). Filesize = 0 Enter lock_and_write. Filesize = 0 flock failed (lock)! Exit lock_and_write (no lock). Filesize = 0 Enter lock_and_write. Filesize = 0 flock failed (lock)! Exit lock_and_write (no lock). Filesize = 0 Enter lock_and_write. Filesize = 0 flock failed (lock)! Exit lock_and_write (no lock). Filesize = 0 Enter lock_and_write. Filesize = 0 flock failed (lock)! Exit lock_and_write (no lock). Filesize = 0 Enter lock_and_write. Filesize = 0 flock failed (lock)! Exit lock_and_write (no lock). Filesize = 0 Enter lock_and_write. Filesize = 0 flock failed (lock)! Exit lock_and_write (no lock). Filesize = 0 Enter lock_and_write. Filesize = 0 flock failed (lock)! Exit lock_and_write (no lock). Filesize = 0 I have to tell you that I really appreciate every-bodies help. It's already more than the new owner of the software is prepared to do. Thank you! Quote Link to comment Share on other sites More sharing options...
tHud Posted October 23, 2012 Author Share Posted October 23, 2012 Hi - just wondering if anyone could point me in the right direction with the script above Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.