Chris@76
|
1 <?php
|
Chris@76
|
2
|
Chris@76
|
3 /**
|
Chris@76
|
4 * Simple Machines Forum (SMF)
|
Chris@76
|
5 *
|
Chris@76
|
6 * @package SMF
|
Chris@76
|
7 * @author Simple Machines http://www.simplemachines.org
|
Chris@76
|
8 * @copyright 2011 Simple Machines
|
Chris@76
|
9 * @license http://www.simplemachines.org/about/smf/license.php BSD
|
Chris@76
|
10 *
|
Chris@76
|
11 * @version 2.0
|
Chris@76
|
12 */
|
Chris@76
|
13
|
Chris@76
|
14 if (!defined('SMF'))
|
Chris@76
|
15 die('Hacking attempt...');
|
Chris@76
|
16
|
Chris@76
|
17 /* This file contains functions that are specifically done by administrators.
|
Chris@76
|
18 The most important function in this file for mod makers happens to be the
|
Chris@76
|
19 updateSettingsFile() function, but it shouldn't be used often anyway.
|
Chris@76
|
20
|
Chris@76
|
21 void getServerVersions(array checkFor)
|
Chris@76
|
22 - get a list of versions that are currently installed on the server.
|
Chris@76
|
23
|
Chris@76
|
24 void getFileVersions(array versionOptions)
|
Chris@76
|
25 - get detailed version information about the physical SMF files on the
|
Chris@76
|
26 server.
|
Chris@76
|
27 - the input parameter allows to set whether to include SSI.php and
|
Chris@76
|
28 whether the results should be sorted.
|
Chris@76
|
29 - returns an array containing information on source files, templates
|
Chris@76
|
30 and language files found in the default theme directory (grouped by
|
Chris@76
|
31 language).
|
Chris@76
|
32
|
Chris@76
|
33 void updateSettingsFile(array config_vars)
|
Chris@76
|
34 - updates the Settings.php file with the changes in config_vars.
|
Chris@76
|
35 - expects config_vars to be an associative array, with the keys as the
|
Chris@76
|
36 variable names in Settings.php, and the values the varaible values.
|
Chris@76
|
37 - does not escape or quote values.
|
Chris@76
|
38 - preserves case, formatting, and additional options in file.
|
Chris@76
|
39 - writes nothing if the resulting file would be less than 10 lines
|
Chris@76
|
40 in length (sanity check for read lock.)
|
Chris@76
|
41
|
Chris@76
|
42 void updateAdminPreferences()
|
Chris@76
|
43 - saves the admins current preferences to the database.
|
Chris@76
|
44
|
Chris@76
|
45 void emailAdmins(string $template, array $replacements = array(), additional_recipients = array())
|
Chris@76
|
46 - loads all users who are admins or have the admin forum permission.
|
Chris@76
|
47 - uses the email template and replacements passed in the parameters.
|
Chris@76
|
48 - sends them an email.
|
Chris@76
|
49
|
Chris@76
|
50 bool updateLastDatabaseError()
|
Chris@76
|
51 - attempts to use the backup file first, to store the last database error
|
Chris@76
|
52 - and only update Settings.php if the first was successful.
|
Chris@76
|
53
|
Chris@76
|
54 */
|
Chris@76
|
55
|
Chris@76
|
56 function getServerVersions($checkFor)
|
Chris@76
|
57 {
|
Chris@76
|
58 global $txt, $db_connection, $_PHPA, $smcFunc, $memcached, $modSettings;
|
Chris@76
|
59
|
Chris@76
|
60 loadLanguage('Admin');
|
Chris@76
|
61
|
Chris@76
|
62 $versions = array();
|
Chris@76
|
63
|
Chris@76
|
64 // Is GD available? If it is, we should show version information for it too.
|
Chris@76
|
65 if (in_array('gd', $checkFor) && function_exists('gd_info'))
|
Chris@76
|
66 {
|
Chris@76
|
67 $temp = gd_info();
|
Chris@76
|
68 $versions['gd'] = array('title' => $txt['support_versions_gd'], 'version' => $temp['GD Version']);
|
Chris@76
|
69 }
|
Chris@76
|
70
|
Chris@76
|
71 // Now lets check for the Database.
|
Chris@76
|
72 if (in_array('db_server', $checkFor))
|
Chris@76
|
73 {
|
Chris@76
|
74 db_extend();
|
Chris@76
|
75 if (!isset($db_connection) || $db_connection === false)
|
Chris@76
|
76 trigger_error('getServerVersions(): you need to be connected to the database in order to get its server version', E_USER_NOTICE);
|
Chris@76
|
77 else
|
Chris@76
|
78 {
|
Chris@76
|
79 $versions['db_server'] = array('title' => sprintf($txt['support_versions_db'], $smcFunc['db_title']), 'version' => '');
|
Chris@76
|
80 $versions['db_server']['version'] = $smcFunc['db_get_version']();
|
Chris@76
|
81 }
|
Chris@76
|
82 }
|
Chris@76
|
83
|
Chris@76
|
84 // If we're using memcache we need the server info.
|
Chris@76
|
85 if (empty($memcached) && function_exists('memcache_get') && isset($modSettings['cache_memcached']) && trim($modSettings['cache_memcached']) != '')
|
Chris@76
|
86 get_memcached_server();
|
Chris@76
|
87
|
Chris@76
|
88 // Check to see if we have any accelerators installed...
|
Chris@76
|
89 if (in_array('mmcache', $checkFor) && defined('MMCACHE_VERSION'))
|
Chris@76
|
90 $versions['mmcache'] = array('title' => 'Turck MMCache', 'version' => MMCACHE_VERSION);
|
Chris@76
|
91 if (in_array('eaccelerator', $checkFor) && defined('EACCELERATOR_VERSION'))
|
Chris@76
|
92 $versions['eaccelerator'] = array('title' => 'eAccelerator', 'version' => EACCELERATOR_VERSION);
|
Chris@76
|
93 if (in_array('phpa', $checkFor) && isset($_PHPA))
|
Chris@76
|
94 $versions['phpa'] = array('title' => 'ionCube PHP-Accelerator', 'version' => $_PHPA['VERSION']);
|
Chris@76
|
95 if (in_array('apc', $checkFor) && extension_loaded('apc'))
|
Chris@76
|
96 $versions['apc'] = array('title' => 'Alternative PHP Cache', 'version' => phpversion('apc'));
|
Chris@76
|
97 if (in_array('memcache', $checkFor) && function_exists('memcache_set'))
|
Chris@76
|
98 $versions['memcache'] = array('title' => 'Memcached', 'version' => empty($memcached) ? '???' : memcache_get_version($memcached));
|
Chris@76
|
99 if (in_array('xcache', $checkFor) && function_exists('xcache_set'))
|
Chris@76
|
100 $versions['xcache'] = array('title' => 'XCache', 'version' => XCACHE_VERSION);
|
Chris@76
|
101 if (in_array('php', $checkFor))
|
Chris@76
|
102 $versions['php'] = array('title' => 'PHP', 'version' => PHP_VERSION);
|
Chris@76
|
103
|
Chris@76
|
104 if (in_array('server', $checkFor))
|
Chris@76
|
105 $versions['server'] = array('title' => $txt['support_versions_server'], 'version' => $_SERVER['SERVER_SOFTWARE']);
|
Chris@76
|
106
|
Chris@76
|
107 return $versions;
|
Chris@76
|
108 }
|
Chris@76
|
109
|
Chris@76
|
110 // Search through source, theme and language files to determine their version.
|
Chris@76
|
111 function getFileVersions(&$versionOptions)
|
Chris@76
|
112 {
|
Chris@76
|
113 global $boarddir, $sourcedir, $settings;
|
Chris@76
|
114
|
Chris@76
|
115 // Default place to find the languages would be the default theme dir.
|
Chris@76
|
116 $lang_dir = $settings['default_theme_dir'] . '/languages';
|
Chris@76
|
117
|
Chris@76
|
118 $version_info = array(
|
Chris@76
|
119 'file_versions' => array(),
|
Chris@76
|
120 'default_template_versions' => array(),
|
Chris@76
|
121 'template_versions' => array(),
|
Chris@76
|
122 'default_language_versions' => array(),
|
Chris@76
|
123 );
|
Chris@76
|
124
|
Chris@76
|
125 // Find the version in SSI.php's file header.
|
Chris@76
|
126 if (!empty($versionOptions['include_ssi']) && file_exists($boarddir . '/SSI.php'))
|
Chris@76
|
127 {
|
Chris@76
|
128 $fp = fopen($boarddir . '/SSI.php', 'rb');
|
Chris@76
|
129 $header = fread($fp, 4096);
|
Chris@76
|
130 fclose($fp);
|
Chris@76
|
131
|
Chris@76
|
132 // The comment looks rougly like... that.
|
Chris@76
|
133 if (preg_match('~\*\s@version\s+(.+)[\s]{2}~i', $header, $match) == 1)
|
Chris@76
|
134 $version_info['file_versions']['SSI.php'] = $match[1];
|
Chris@76
|
135 // Not found! This is bad.
|
Chris@76
|
136 else
|
Chris@76
|
137 $version_info['file_versions']['SSI.php'] = '??';
|
Chris@76
|
138 }
|
Chris@76
|
139
|
Chris@76
|
140 // Do the paid subscriptions handler?
|
Chris@76
|
141 if (!empty($versionOptions['include_subscriptions']) && file_exists($boarddir . '/subscriptions.php'))
|
Chris@76
|
142 {
|
Chris@76
|
143 $fp = fopen($boarddir . '/subscriptions.php', 'rb');
|
Chris@76
|
144 $header = fread($fp, 4096);
|
Chris@76
|
145 fclose($fp);
|
Chris@76
|
146
|
Chris@76
|
147 // Found it?
|
Chris@76
|
148 if (preg_match('~\*\s@version\s+(.+)[\s]{2}~i', $header, $match) == 1)
|
Chris@76
|
149 $version_info['file_versions']['subscriptions.php'] = $match[1];
|
Chris@76
|
150 // If we haven't how do we all get paid?
|
Chris@76
|
151 else
|
Chris@76
|
152 $version_info['file_versions']['subscriptions.php'] = '??';
|
Chris@76
|
153 }
|
Chris@76
|
154
|
Chris@76
|
155 // Load all the files in the Sources directory, except this file and the redirect.
|
Chris@76
|
156 $sources_dir = dir($sourcedir);
|
Chris@76
|
157 while ($entry = $sources_dir->read())
|
Chris@76
|
158 {
|
Chris@76
|
159 if (substr($entry, -4) === '.php' && !is_dir($sourcedir . '/' . $entry) && $entry !== 'index.php')
|
Chris@76
|
160 {
|
Chris@76
|
161 // Read the first 4k from the file.... enough for the header.
|
Chris@76
|
162 $fp = fopen($sourcedir . '/' . $entry, 'rb');
|
Chris@76
|
163 $header = fread($fp, 4096);
|
Chris@76
|
164 fclose($fp);
|
Chris@76
|
165
|
Chris@76
|
166 // Look for the version comment in the file header.
|
Chris@76
|
167 if (preg_match('~\*\s@version\s+(.+)[\s]{2}~i', $header, $match) == 1)
|
Chris@76
|
168 $version_info['file_versions'][$entry] = $match[1];
|
Chris@76
|
169 // It wasn't found, but the file was... show a '??'.
|
Chris@76
|
170 else
|
Chris@76
|
171 $version_info['file_versions'][$entry] = '??';
|
Chris@76
|
172 }
|
Chris@76
|
173 }
|
Chris@76
|
174 $sources_dir->close();
|
Chris@76
|
175
|
Chris@76
|
176 // Load all the files in the default template directory - and the current theme if applicable.
|
Chris@76
|
177 $directories = array('default_template_versions' => $settings['default_theme_dir']);
|
Chris@76
|
178 if ($settings['theme_id'] != 1)
|
Chris@76
|
179 $directories += array('template_versions' => $settings['theme_dir']);
|
Chris@76
|
180
|
Chris@76
|
181 foreach ($directories as $type => $dirname)
|
Chris@76
|
182 {
|
Chris@76
|
183 $this_dir = dir($dirname);
|
Chris@76
|
184 while ($entry = $this_dir->read())
|
Chris@76
|
185 {
|
Chris@76
|
186 if (substr($entry, -12) == 'template.php' && !is_dir($dirname . '/' . $entry))
|
Chris@76
|
187 {
|
Chris@76
|
188 // Read the first 768 bytes from the file.... enough for the header.
|
Chris@76
|
189 $fp = fopen($dirname . '/' . $entry, 'rb');
|
Chris@76
|
190 $header = fread($fp, 768);
|
Chris@76
|
191 fclose($fp);
|
Chris@76
|
192
|
Chris@76
|
193 // Look for the version comment in the file header.
|
Chris@76
|
194 if (preg_match('~\*\s@version\s+(.+)[\s]{2}~i', $header, $match) == 1)
|
Chris@76
|
195 $version_info[$type][$entry] = $match[1];
|
Chris@76
|
196 // It wasn't found, but the file was... show a '??'.
|
Chris@76
|
197 else
|
Chris@76
|
198 $version_info[$type][$entry] = '??';
|
Chris@76
|
199 }
|
Chris@76
|
200 }
|
Chris@76
|
201 $this_dir->close();
|
Chris@76
|
202 }
|
Chris@76
|
203
|
Chris@76
|
204 // Load up all the files in the default language directory and sort by language.
|
Chris@76
|
205 $this_dir = dir($lang_dir);
|
Chris@76
|
206 while ($entry = $this_dir->read())
|
Chris@76
|
207 {
|
Chris@76
|
208 if (substr($entry, -4) == '.php' && $entry != 'index.php' && !is_dir($lang_dir . '/' . $entry))
|
Chris@76
|
209 {
|
Chris@76
|
210 // Read the first 768 bytes from the file.... enough for the header.
|
Chris@76
|
211 $fp = fopen($lang_dir . '/' . $entry, 'rb');
|
Chris@76
|
212 $header = fread($fp, 768);
|
Chris@76
|
213 fclose($fp);
|
Chris@76
|
214
|
Chris@76
|
215 // Split the file name off into useful bits.
|
Chris@76
|
216 list ($name, $language) = explode('.', $entry);
|
Chris@76
|
217
|
Chris@76
|
218 // Look for the version comment in the file header.
|
Chris@76
|
219 if (preg_match('~(?://|/\*)\s*Version:\s+(.+?);\s*' . preg_quote($name, '~') . '(?:[\s]{2}|\*/)~i', $header, $match) == 1)
|
Chris@76
|
220 $version_info['default_language_versions'][$language][$name] = $match[1];
|
Chris@76
|
221 // It wasn't found, but the file was... show a '??'.
|
Chris@76
|
222 else
|
Chris@76
|
223 $version_info['default_language_versions'][$language][$name] = '??';
|
Chris@76
|
224 }
|
Chris@76
|
225 }
|
Chris@76
|
226 $this_dir->close();
|
Chris@76
|
227
|
Chris@76
|
228 // Sort the file versions by filename.
|
Chris@76
|
229 if (!empty($versionOptions['sort_results']))
|
Chris@76
|
230 {
|
Chris@76
|
231 ksort($version_info['file_versions']);
|
Chris@76
|
232 ksort($version_info['default_template_versions']);
|
Chris@76
|
233 ksort($version_info['template_versions']);
|
Chris@76
|
234 ksort($version_info['default_language_versions']);
|
Chris@76
|
235
|
Chris@76
|
236 // For languages sort each language too.
|
Chris@76
|
237 foreach ($version_info['default_language_versions'] as $language => $dummy)
|
Chris@76
|
238 ksort($version_info['default_language_versions'][$language]);
|
Chris@76
|
239 }
|
Chris@76
|
240 return $version_info;
|
Chris@76
|
241 }
|
Chris@76
|
242
|
Chris@76
|
243 // Update the Settings.php file.
|
Chris@76
|
244 function updateSettingsFile($config_vars)
|
Chris@76
|
245 {
|
Chris@76
|
246 global $boarddir, $cachedir;
|
Chris@76
|
247
|
Chris@76
|
248 // When is Settings.php last changed?
|
Chris@76
|
249 $last_settings_change = filemtime($boarddir . '/Settings.php');
|
Chris@76
|
250
|
Chris@76
|
251 // Load the file. Break it up based on \r or \n, and then clean out extra characters.
|
Chris@76
|
252 $settingsArray = trim(file_get_contents($boarddir . '/Settings.php'));
|
Chris@76
|
253 if (strpos($settingsArray, "\n") !== false)
|
Chris@76
|
254 $settingsArray = explode("\n", $settingsArray);
|
Chris@76
|
255 elseif (strpos($settingsArray, "\r") !== false)
|
Chris@76
|
256 $settingsArray = explode("\r", $settingsArray);
|
Chris@76
|
257 else
|
Chris@76
|
258 return;
|
Chris@76
|
259
|
Chris@76
|
260 // Make sure we got a good file.
|
Chris@76
|
261 if (count($config_vars) == 1 && isset($config_vars['db_last_error']))
|
Chris@76
|
262 {
|
Chris@76
|
263 $temp = trim(implode("\n", $settingsArray));
|
Chris@76
|
264 if (substr($temp, 0, 5) != '<?php' || substr($temp, -2) != '?' . '>')
|
Chris@76
|
265 return;
|
Chris@76
|
266 if (strpos($temp, 'sourcedir') === false || strpos($temp, 'boarddir') === false || strpos($temp, 'cookiename') === false)
|
Chris@76
|
267 return;
|
Chris@76
|
268 }
|
Chris@76
|
269
|
Chris@76
|
270 // Presumably, the file has to have stuff in it for this function to be called :P.
|
Chris@76
|
271 if (count($settingsArray) < 10)
|
Chris@76
|
272 return;
|
Chris@76
|
273
|
Chris@76
|
274 foreach ($settingsArray as $k => $dummy)
|
Chris@76
|
275 $settingsArray[$k] = strtr($dummy, array("\r" => '')) . "\n";
|
Chris@76
|
276
|
Chris@76
|
277 for ($i = 0, $n = count($settingsArray); $i < $n; $i++)
|
Chris@76
|
278 {
|
Chris@76
|
279 // Don't trim or bother with it if it's not a variable.
|
Chris@76
|
280 if (substr($settingsArray[$i], 0, 1) != '$')
|
Chris@76
|
281 continue;
|
Chris@76
|
282
|
Chris@76
|
283 $settingsArray[$i] = trim($settingsArray[$i]) . "\n";
|
Chris@76
|
284
|
Chris@76
|
285 // Look through the variables to set....
|
Chris@76
|
286 foreach ($config_vars as $var => $val)
|
Chris@76
|
287 {
|
Chris@76
|
288 if (strncasecmp($settingsArray[$i], '$' . $var, 1 + strlen($var)) == 0)
|
Chris@76
|
289 {
|
Chris@76
|
290 $comment = strstr(substr($settingsArray[$i], strpos($settingsArray[$i], ';')), '#');
|
Chris@76
|
291 $settingsArray[$i] = '$' . $var . ' = ' . $val . ';' . ($comment == '' ? '' : "\t\t" . rtrim($comment)) . "\n";
|
Chris@76
|
292
|
Chris@76
|
293 // This one's been 'used', so to speak.
|
Chris@76
|
294 unset($config_vars[$var]);
|
Chris@76
|
295 }
|
Chris@76
|
296 }
|
Chris@76
|
297
|
Chris@76
|
298 if (substr(trim($settingsArray[$i]), 0, 2) == '?' . '>')
|
Chris@76
|
299 $end = $i;
|
Chris@76
|
300 }
|
Chris@76
|
301
|
Chris@76
|
302 // This should never happen, but apparently it is happening.
|
Chris@76
|
303 if (empty($end) || $end < 10)
|
Chris@76
|
304 $end = count($settingsArray) - 1;
|
Chris@76
|
305
|
Chris@76
|
306 // Still more? Add them at the end.
|
Chris@76
|
307 if (!empty($config_vars))
|
Chris@76
|
308 {
|
Chris@76
|
309 if (trim($settingsArray[$end]) == '?' . '>')
|
Chris@76
|
310 $settingsArray[$end++] = '';
|
Chris@76
|
311 else
|
Chris@76
|
312 $end++;
|
Chris@76
|
313
|
Chris@76
|
314 foreach ($config_vars as $var => $val)
|
Chris@76
|
315 $settingsArray[$end++] = '$' . $var . ' = ' . $val . ';' . "\n";
|
Chris@76
|
316 $settingsArray[$end] = '?' . '>';
|
Chris@76
|
317 }
|
Chris@76
|
318 else
|
Chris@76
|
319 $settingsArray[$end] = trim($settingsArray[$end]);
|
Chris@76
|
320
|
Chris@76
|
321 // Sanity error checking: the file needs to be at least 12 lines.
|
Chris@76
|
322 if (count($settingsArray) < 12)
|
Chris@76
|
323 return;
|
Chris@76
|
324
|
Chris@76
|
325 // Try to avoid a few pitfalls:
|
Chris@76
|
326 // like a possible race condition,
|
Chris@76
|
327 // or a failure to write at low diskspace
|
Chris@76
|
328
|
Chris@76
|
329 // Check before you act: if cache is enabled, we can do a simple test
|
Chris@76
|
330 // Can we even write things on this filesystem?
|
Chris@76
|
331 if ((empty($cachedir) || !file_exists($cachedir)) && file_exists($boarddir . '/cache'))
|
Chris@76
|
332 $cachedir = $boarddir . '/cache';
|
Chris@76
|
333 $test_fp = @fopen($cachedir . '/settings_update.tmp', "w+");
|
Chris@76
|
334 if ($test_fp)
|
Chris@76
|
335 {
|
Chris@76
|
336 fclose($test_fp);
|
Chris@76
|
337
|
Chris@76
|
338 $test_fp = @fopen($cachedir . '/settings_update.tmp', 'r+');
|
Chris@76
|
339 $written_bytes = fwrite($test_fp, "test");
|
Chris@76
|
340 fclose($test_fp);
|
Chris@76
|
341 @unlink($cachedir . '/settings_update.tmp');
|
Chris@76
|
342
|
Chris@76
|
343 if ($written_bytes !== strlen("test"))
|
Chris@76
|
344 {
|
Chris@76
|
345 // Oops. Low disk space, perhaps. Don't mess with Settings.php then.
|
Chris@76
|
346 // No means no. :P
|
Chris@76
|
347 return;
|
Chris@76
|
348 }
|
Chris@76
|
349 }
|
Chris@76
|
350
|
Chris@76
|
351 // Protect me from what I want! :P
|
Chris@76
|
352 clearstatcache();
|
Chris@76
|
353 if (filemtime($boarddir . '/Settings.php') === $last_settings_change)
|
Chris@76
|
354 {
|
Chris@76
|
355 // You asked for it...
|
Chris@76
|
356 // Blank out the file - done to fix a oddity with some servers.
|
Chris@76
|
357 $fp = @fopen($boarddir . '/Settings.php', 'w');
|
Chris@76
|
358
|
Chris@76
|
359 // Is it even writable, though?
|
Chris@76
|
360 if ($fp)
|
Chris@76
|
361 {
|
Chris@76
|
362 fclose($fp);
|
Chris@76
|
363
|
Chris@76
|
364 $fp = fopen($boarddir . '/Settings.php', 'r+');
|
Chris@76
|
365 foreach ($settingsArray as $line)
|
Chris@76
|
366 fwrite($fp, strtr($line, "\r", ''));
|
Chris@76
|
367 fclose($fp);
|
Chris@76
|
368 }
|
Chris@76
|
369 }
|
Chris@76
|
370 }
|
Chris@76
|
371
|
Chris@76
|
372 function updateAdminPreferences()
|
Chris@76
|
373 {
|
Chris@76
|
374 global $options, $context, $smcFunc, $settings, $user_info;
|
Chris@76
|
375
|
Chris@76
|
376 // This must exist!
|
Chris@76
|
377 if (!isset($context['admin_preferences']))
|
Chris@76
|
378 return false;
|
Chris@76
|
379
|
Chris@76
|
380 // This is what we'll be saving.
|
Chris@76
|
381 $options['admin_preferences'] = serialize($context['admin_preferences']);
|
Chris@76
|
382
|
Chris@76
|
383 // Just check we haven't ended up with something theme exclusive somehow.
|
Chris@76
|
384 $smcFunc['db_query']('', '
|
Chris@76
|
385 DELETE FROM {db_prefix}themes
|
Chris@76
|
386 WHERE id_theme != {int:default_theme}
|
Chris@76
|
387 AND variable = {string:admin_preferences}',
|
Chris@76
|
388 array(
|
Chris@76
|
389 'default_theme' => 1,
|
Chris@76
|
390 'admin_preferences' => 'admin_preferences',
|
Chris@76
|
391 )
|
Chris@76
|
392 );
|
Chris@76
|
393
|
Chris@76
|
394 // Update the themes table.
|
Chris@76
|
395 $smcFunc['db_insert']('replace',
|
Chris@76
|
396 '{db_prefix}themes',
|
Chris@76
|
397 array('id_member' => 'int', 'id_theme' => 'int', 'variable' => 'string-255', 'value' => 'string-65534'),
|
Chris@76
|
398 array($user_info['id'], 1, 'admin_preferences', $options['admin_preferences']),
|
Chris@76
|
399 array('id_member', 'id_theme', 'variable')
|
Chris@76
|
400 );
|
Chris@76
|
401
|
Chris@76
|
402 // Make sure we invalidate any cache.
|
Chris@76
|
403 cache_put_data('theme_settings-' . $settings['theme_id'] . ':' . $user_info['id'], null, 0);
|
Chris@76
|
404 }
|
Chris@76
|
405
|
Chris@76
|
406 // Send all the administrators a lovely email.
|
Chris@76
|
407 function emailAdmins($template, $replacements = array(), $additional_recipients = array())
|
Chris@76
|
408 {
|
Chris@76
|
409 global $smcFunc, $sourcedir, $language, $modSettings;
|
Chris@76
|
410
|
Chris@76
|
411 // We certainly want this.
|
Chris@76
|
412 require_once($sourcedir . '/Subs-Post.php');
|
Chris@76
|
413
|
Chris@76
|
414 // Load all groups which are effectively admins.
|
Chris@76
|
415 $request = $smcFunc['db_query']('', '
|
Chris@76
|
416 SELECT id_group
|
Chris@76
|
417 FROM {db_prefix}permissions
|
Chris@76
|
418 WHERE permission = {string:admin_forum}
|
Chris@76
|
419 AND add_deny = {int:add_deny}
|
Chris@76
|
420 AND id_group != {int:id_group}',
|
Chris@76
|
421 array(
|
Chris@76
|
422 'add_deny' => 1,
|
Chris@76
|
423 'id_group' => 0,
|
Chris@76
|
424 'admin_forum' => 'admin_forum',
|
Chris@76
|
425 )
|
Chris@76
|
426 );
|
Chris@76
|
427 $groups = array(1);
|
Chris@76
|
428 while ($row = $smcFunc['db_fetch_assoc']($request))
|
Chris@76
|
429 $groups[] = $row['id_group'];
|
Chris@76
|
430 $smcFunc['db_free_result']($request);
|
Chris@76
|
431
|
Chris@76
|
432 $request = $smcFunc['db_query']('', '
|
Chris@76
|
433 SELECT id_member, member_name, real_name, lngfile, email_address
|
Chris@76
|
434 FROM {db_prefix}members
|
Chris@76
|
435 WHERE (id_group IN ({array_int:group_list}) OR FIND_IN_SET({raw:group_array_implode}, additional_groups) != 0)
|
Chris@76
|
436 AND notify_types != {int:notify_types}
|
Chris@76
|
437 ORDER BY lngfile',
|
Chris@76
|
438 array(
|
Chris@76
|
439 'group_list' => $groups,
|
Chris@76
|
440 'notify_types' => 4,
|
Chris@76
|
441 'group_array_implode' => implode(', additional_groups) != 0 OR FIND_IN_SET(', $groups),
|
Chris@76
|
442 )
|
Chris@76
|
443 );
|
Chris@76
|
444 $emails_sent = array();
|
Chris@76
|
445 while ($row = $smcFunc['db_fetch_assoc']($request))
|
Chris@76
|
446 {
|
Chris@76
|
447 // Stick their particulars in the replacement data.
|
Chris@76
|
448 $replacements['IDMEMBER'] = $row['id_member'];
|
Chris@76
|
449 $replacements['REALNAME'] = $row['member_name'];
|
Chris@76
|
450 $replacements['USERNAME'] = $row['real_name'];
|
Chris@76
|
451
|
Chris@76
|
452 // Load the data from the template.
|
Chris@76
|
453 $emaildata = loadEmailTemplate($template, $replacements, empty($row['lngfile']) || empty($modSettings['userLanguage']) ? $language : $row['lngfile']);
|
Chris@76
|
454
|
Chris@76
|
455 // Then send the actual email.
|
Chris@76
|
456 sendmail($row['email_address'], $emaildata['subject'], $emaildata['body'], null, null, false, 1);
|
Chris@76
|
457
|
Chris@76
|
458 // Track who we emailed so we don't do it twice.
|
Chris@76
|
459 $emails_sent[] = $row['email_address'];
|
Chris@76
|
460 }
|
Chris@76
|
461 $smcFunc['db_free_result']($request);
|
Chris@76
|
462
|
Chris@76
|
463 // Any additional users we must email this to?
|
Chris@76
|
464 if (!empty($additional_recipients))
|
Chris@76
|
465 foreach ($additional_recipients as $recipient)
|
Chris@76
|
466 {
|
Chris@76
|
467 if (in_array($recipient['email'], $emails_sent))
|
Chris@76
|
468 continue;
|
Chris@76
|
469
|
Chris@76
|
470 $replacements['IDMEMBER'] = $recipient['id'];
|
Chris@76
|
471 $replacements['REALNAME'] = $recipient['name'];
|
Chris@76
|
472 $replacements['USERNAME'] = $recipient['name'];
|
Chris@76
|
473
|
Chris@76
|
474 // Load the template again.
|
Chris@76
|
475 $emaildata = loadEmailTemplate($template, $replacements, empty($recipient['lang']) || empty($modSettings['userLanguage']) ? $language : $recipient['lang']);
|
Chris@76
|
476
|
Chris@76
|
477 // Send off the email.
|
Chris@76
|
478 sendmail($recipient['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 1);
|
Chris@76
|
479 }
|
Chris@76
|
480 }
|
Chris@76
|
481
|
Chris@76
|
482 function updateLastDatabaseError()
|
Chris@76
|
483 {
|
Chris@76
|
484 global $boarddir;
|
Chris@76
|
485
|
Chris@76
|
486 // Find out this way if we can even write things on this filesystem.
|
Chris@76
|
487 // In addition, store things first in the backup file
|
Chris@76
|
488
|
Chris@76
|
489 $last_settings_change = @filemtime($boarddir . '/Settings.php');
|
Chris@76
|
490
|
Chris@76
|
491 // Make sure the backup file is there...
|
Chris@76
|
492 $file = $boarddir . '/Settings_bak.php';
|
Chris@76
|
493 if ((!file_exists($file) || filesize($file) == 0) && !copy($boarddir . '/Settings.php', $file))
|
Chris@76
|
494 return false;
|
Chris@76
|
495
|
Chris@76
|
496 // ...and writable!
|
Chris@76
|
497 if (!is_writable($file))
|
Chris@76
|
498 {
|
Chris@76
|
499 chmod($file, 0755);
|
Chris@76
|
500 if (!is_writable($file))
|
Chris@76
|
501 {
|
Chris@76
|
502 chmod($file, 0775);
|
Chris@76
|
503 if (!is_writable($file))
|
Chris@76
|
504 {
|
Chris@76
|
505 chmod($file, 0777);
|
Chris@76
|
506 if (!is_writable($file))
|
Chris@76
|
507 return false;
|
Chris@76
|
508 }
|
Chris@76
|
509 }
|
Chris@76
|
510 }
|
Chris@76
|
511
|
Chris@76
|
512 // Put the new timestamp.
|
Chris@76
|
513 $data = file_get_contents($file);
|
Chris@76
|
514 $data = preg_replace('~\$db_last_error = \d+;~', '$db_last_error = ' . time() . ';', $data);
|
Chris@76
|
515
|
Chris@76
|
516 // Open the backup file for writing
|
Chris@76
|
517 if ($fp = @fopen($file, 'w'))
|
Chris@76
|
518 {
|
Chris@76
|
519 // Reset the file buffer.
|
Chris@76
|
520 set_file_buffer($fp, 0);
|
Chris@76
|
521
|
Chris@76
|
522 // Update the file.
|
Chris@76
|
523 $t = flock($fp, LOCK_EX);
|
Chris@76
|
524 $bytes = fwrite($fp, $data);
|
Chris@76
|
525 flock($fp, LOCK_UN);
|
Chris@76
|
526 fclose($fp);
|
Chris@76
|
527
|
Chris@76
|
528 // Was it a success?
|
Chris@76
|
529 // ...only relevant if we're still dealing with the same good ole' settings file.
|
Chris@76
|
530 clearstatcache();
|
Chris@76
|
531 if (($bytes == strlen($data)) && (filemtime($boarddir . '/Settings.php') === $last_settings_change))
|
Chris@76
|
532 {
|
Chris@76
|
533 // This is our new Settings file...
|
Chris@76
|
534 // At least this one is an atomic operation
|
Chris@76
|
535 @copy($file, $boarddir . '/Settings.php');
|
Chris@76
|
536 return true;
|
Chris@76
|
537 }
|
Chris@76
|
538 else
|
Chris@76
|
539 {
|
Chris@76
|
540 // Oops. Someone might have been faster
|
Chris@76
|
541 // or we have no more disk space left, troubles, troubles...
|
Chris@76
|
542 // Copy the file back and run for your life!
|
Chris@76
|
543 @copy($boarddir . '/Settings.php', $file);
|
Chris@76
|
544 }
|
Chris@76
|
545 }
|
Chris@76
|
546
|
Chris@76
|
547 return false;
|
Chris@76
|
548 }
|
Chris@76
|
549
|
Chris@76
|
550 ?> |