Skip to content

Instantly share code, notes, and snippets.

@norv
Created May 8, 2012 17:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save norv/2637875 to your computer and use it in GitHub Desktop.
Save norv/2637875 to your computer and use it in GitHub Desktop.
<?php
function updateSettingsFile($config_vars)
{
global $boarddir, $cachedir, $context;
// Updating the db_last_error, then don't mess around with Settings.php
if (count($config_vars) === 1 && isset($config_vars['db_last_error']))
{
updateDbLastError($config_vars['db_last_error']);
return;
}
// When was Settings.php last changed?
$last_settings_change = filemtime($boarddir . '/Settings.php');
// Load the settings file.
$settingsArray = trim(file_get_contents($boarddir . '/Settings.php'));
// Break it up based on \r or \n, and then clean out extra characters.
if (strpos($settingsArray, "\n") !== false)
$settingsArray = explode("\n", $settingsArray);
elseif (strpos($settingsArray, "\r") !== false)
$settingsArray = explode("\r", $settingsArray);
else
return;
// Presumably, the file has to have stuff in it for this function to be called :P.
if (count($settingsArray) < 10)
return;
// remove any /r's that made there way in here
foreach ($settingsArray as $k => $dummy)
$settingsArray[$k] = strtr($dummy, array("\r" => '')) . "\n";
// go line by line and see whats changing
for ($i = 0, $n = count($settingsArray); $i < $n; $i++)
{
// Don't trim or bother with it if it's not a variable.
if (substr($settingsArray[$i], 0, 1) != '$')
continue;
$settingsArray[$i] = trim($settingsArray[$i]) . "\n";
// Look through the variables to set....
foreach ($config_vars as $var => $val)
{
// be sure someone is not updating this with a group
if ($var === 'db_last_error')
{
updateDbLastError($val);
unset($config_vars[$var]);
}
elseif (strncasecmp($settingsArray[$i], '$' . $var, 1 + strlen($var)) == 0)
{
$comment = strstr(substr($settingsArray[$i], strpos($settingsArray[$i], ';')), '#');
$settingsArray[$i] = '$' . $var . ' = ' . $val . ';' . ($comment == '' ? '' : "\t\t" . rtrim($comment)) . "\n";
// This one's been 'used', so to speak.
unset($config_vars[$var]);
}
}
// End of the file ... maybe
if (substr(trim($settingsArray[$i]), 0, 2) == '?' . '>')
$end = $i;
}
// This should never happen, but apparently it is happening.
if (empty($end) || $end < 10)
$end = count($settingsArray) - 1;
// Still more varialbes to go? Then lets add them at the end.
if (!empty($config_vars))
{
if (trim($settingsArray[$end]) == '?' . '>')
$settingsArray[$end++] = '';
else
$end++;
// Add in all the newly defined vars that were passed
foreach ($config_vars as $var => $val)
$settingsArray[$end++] = '$' . $var . ' = ' . $val . ';' . "\n";
$settingsArray[$end] = '?' . '>';
}
else
$settingsArray[$end] = trim($settingsArray[$end]);
// Sanity error checking: the file needs to be at least 12 lines.
if (count($settingsArray) < 12)
return;
// Try to avoid a few pitfalls:
// - like a possible race condition,
// - or a failure to write at low diskspace
//
// Check before you act: if cache is enabled, we can do a simple write test
// to validate that we even write things on this filesystem.
if ((empty($cachedir) || !file_exists($cachedir)) && file_exists($boarddir . '/cache'))
$cachedir = $boarddir . '/cache';
$test_fp = @fopen($cachedir . '/settings_update.tmp', "w+");
if ($test_fp)
{
fclose($test_fp);
$written_bytes = file_put_contents($cachedir . '/settings_update.tmp', 'test', LOCK_EX);
@unlink($cachedir . '/settings_update.tmp');
if ($written_bytes !== 4)
{
// Oops. Low disk space, perhaps. Don't mess with Settings.php then.
// No means no. :P
return;
}
}
// You asked for it...
clearstatcache();
if (filemtime($boarddir . '/Settings.php') === $last_settings_change)
{
$write_settings = implode('', $settingsArray);
$written_bytes = file_put_contents($boarddir . '/Settings.php', $write_settings, LOCK_EX);
if ($written_bytes !== strlen($write_settings))
{
// Well this is not good at all, lets see if we can save this
$context['settings_message'] = 'settings_error';
if (file_exists($boarddir . '/Settings_bak.php'))
@copy($boarddir . '/Settings_bak.php', $boarddir . '/Settings.php');
// @todo fatal lang error if copy failed ?
}
}
}
/**
* Saves the time of the last db error for the error log
* - Done separately from updateSettingsFile to avoid race conditions
* which can occur during a db error
* - If it fails Settings.php will assume 0
*/
function updateDbLastError($time)
{
global $boarddir;
// Write out the db_last_error file with the error timestamp
file_put_contents($boarddir . '/db_last_error.php', "<?php\n$db_last_error = " . $time . ";\n?" . ">\n", LOCK_EX);
@touch($boarddir . '/' . 'Settings.php');
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment