annotate forum/Sources/ManageServer.php @ 76:e3e11437ecea website

Add forum code
author Chris Cannam
date Sun, 07 Jul 2013 11:25:48 +0200
parents
children
rev   line source
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.4
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 all the functionality required to be able to edit the
Chris@76 18 core server settings. This includes anything from which an error may result
Chris@76 19 in the forum destroying itself in a firey fury.
Chris@76 20
Chris@76 21 void ModifySettings()
Chris@76 22 - Sets up all the available sub-actions.
Chris@76 23 - Requires the admin_forum permission.
Chris@76 24 - Uses the edit_settings adminIndex.
Chris@76 25 - Sets up all the tabs and selects the appropriate one based on the sub-action.
Chris@76 26 - Redirects to the appropriate function based on the sub-action.
Chris@76 27
Chris@76 28 void ModifyGeneralSettings()
Chris@76 29 - shows an interface for the settings in Settings.php to be changed.
Chris@76 30 - uses the rawdata sub template (not theme-able.)
Chris@76 31 - requires the admin_forum permission.
Chris@76 32 - uses the edit_settings administration area.
Chris@76 33 - contains the actual array of settings to show from Settings.php.
Chris@76 34 - accessed from ?action=admin;area=serversettings;sa=general.
Chris@76 35
Chris@76 36 void ModifyDatabaseSettings()
Chris@76 37 - shows an interface for the settings in Settings.php to be changed.
Chris@76 38 - uses the rawdata sub template (not theme-able.)
Chris@76 39 - requires the admin_forum permission.
Chris@76 40 - uses the edit_settings administration area.
Chris@76 41 - contains the actual array of settings to show from Settings.php.
Chris@76 42 - accessed from ?action=admin;area=serversettings;sa=database.
Chris@76 43
Chris@76 44 void ModifyCookieSettings()
Chris@76 45 // !!!
Chris@76 46
Chris@76 47 void ModifyCacheSettings()
Chris@76 48 // !!!
Chris@76 49
Chris@76 50 void ModifyLoadBalancingSettings()
Chris@76 51 // !!!
Chris@76 52
Chris@76 53 void AddLanguage()
Chris@76 54 // !!!
Chris@76 55
Chris@76 56 void DownloadLanguage()
Chris@76 57 - Uses the ManageSettings template and the download_language sub-template.
Chris@76 58 - Requires a valid download ID ("did") in the URL.
Chris@76 59 - Also handles installing language files.
Chris@76 60 - Attempts to chmod things as needed.
Chris@76 61 - Uses a standard list to display information about all the files and where they'll be put.
Chris@76 62
Chris@76 63 void ManageLanguages()
Chris@76 64 // !!!
Chris@76 65
Chris@76 66 void ModifyLanguages()
Chris@76 67 // !!!
Chris@76 68
Chris@76 69 int list_getNumLanguages()
Chris@76 70 // !!!
Chris@76 71
Chris@76 72 array list_getLanguages()
Chris@76 73 - Callback for $listOptions['get_items']['function'] in ManageLanguageSettings.
Chris@76 74 - Determines which languages are available by looking for the "index.{language}.php" file.
Chris@76 75 - Also figures out how many users are using a particular language.
Chris@76 76
Chris@76 77 void ModifyLanguageSettings()
Chris@76 78 // !!!
Chris@76 79
Chris@76 80 void ModifyLanguage()
Chris@76 81 // !!!
Chris@76 82
Chris@76 83 void prepareServerSettingsContext(array config_vars)
Chris@76 84 // !!!
Chris@76 85
Chris@76 86 void prepareDBSettingContext(array config_vars)
Chris@76 87 // !!!
Chris@76 88
Chris@76 89 void saveSettings(array config_vars)
Chris@76 90 - saves those settings set from ?action=admin;area=serversettings to the
Chris@76 91 Settings.php file and the database.
Chris@76 92 - requires the admin_forum permission.
Chris@76 93 - contains arrays of the types of data to save into Settings.php.
Chris@76 94
Chris@76 95 void saveDBSettings(array config_vars)
Chris@76 96 // !!!
Chris@76 97
Chris@76 98 */
Chris@76 99
Chris@76 100 /* Adding options to one of the setting screens isn't hard. Call prepareDBSettingsContext;
Chris@76 101 The basic format for a checkbox is:
Chris@76 102 array('check', 'nameInModSettingsAndSQL'),
Chris@76 103
Chris@76 104 And for a text box:
Chris@76 105 array('text', 'nameInModSettingsAndSQL')
Chris@76 106 (NOTE: You have to add an entry for this at the bottom!)
Chris@76 107
Chris@76 108 In these cases, it will look for $txt['nameInModSettingsAndSQL'] as the description,
Chris@76 109 and $helptxt['nameInModSettingsAndSQL'] as the help popup description.
Chris@76 110
Chris@76 111 Here's a quick explanation of how to add a new item:
Chris@76 112
Chris@76 113 * A text input box. For textual values.
Chris@76 114 ie. array('text', 'nameInModSettingsAndSQL', 'OptionalInputBoxWidth'),
Chris@76 115
Chris@76 116 * A text input box. For numerical values.
Chris@76 117 ie. array('int', 'nameInModSettingsAndSQL', 'OptionalInputBoxWidth'),
Chris@76 118
Chris@76 119 * A text input box. For floating point values.
Chris@76 120 ie. array('float', 'nameInModSettingsAndSQL', 'OptionalInputBoxWidth'),
Chris@76 121
Chris@76 122 * A large text input box. Used for textual values spanning multiple lines.
Chris@76 123 ie. array('large_text', 'nameInModSettingsAndSQL', 'OptionalNumberOfRows'),
Chris@76 124
Chris@76 125 * A check box. Either one or zero. (boolean)
Chris@76 126 ie. array('check', 'nameInModSettingsAndSQL'),
Chris@76 127
Chris@76 128 * A selection box. Used for the selection of something from a list.
Chris@76 129 ie. array('select', 'nameInModSettingsAndSQL', array('valueForSQL' => $txt['displayedValue'])),
Chris@76 130 Note that just saying array('first', 'second') will put 0 in the SQL for 'first'.
Chris@76 131
Chris@76 132 * A password input box. Used for passwords, no less!
Chris@76 133 ie. array('password', 'nameInModSettingsAndSQL', 'OptionalInputBoxWidth'),
Chris@76 134
Chris@76 135 * A permission - for picking groups who have a permission.
Chris@76 136 ie. array('permissions', 'manage_groups'),
Chris@76 137
Chris@76 138 * A BBC selection box.
Chris@76 139 ie. array('bbc', 'sig_bbc'),
Chris@76 140
Chris@76 141 For each option:
Chris@76 142 type (see above), variable name, size/possible values.
Chris@76 143 OR make type '' for an empty string for a horizontal rule.
Chris@76 144 SET preinput - to put some HTML prior to the input box.
Chris@76 145 SET postinput - to put some HTML following the input box.
Chris@76 146 SET invalid - to mark the data as invalid.
Chris@76 147 PLUS You can override label and help parameters by forcing their keys in the array, for example:
Chris@76 148 array('text', 'invalidlabel', 3, 'label' => 'Actual Label') */
Chris@76 149
Chris@76 150 // This is the main pass through function, it creates tabs and the like.
Chris@76 151 function ModifySettings()
Chris@76 152 {
Chris@76 153 global $context, $txt, $scripturl, $boarddir;
Chris@76 154
Chris@76 155 // This is just to keep the database password more secure.
Chris@76 156 isAllowedTo('admin_forum');
Chris@76 157
Chris@76 158 // Load up all the tabs...
Chris@76 159 $context[$context['admin_menu_name']]['tab_data'] = array(
Chris@76 160 'title' => $txt['admin_server_settings'],
Chris@76 161 'help' => 'serversettings',
Chris@76 162 'description' => $txt['admin_basic_settings'],
Chris@76 163 );
Chris@76 164
Chris@76 165 checkSession('request');
Chris@76 166
Chris@76 167 // The settings are in here, I swear!
Chris@76 168 loadLanguage('ManageSettings');
Chris@76 169
Chris@76 170 $context['page_title'] = $txt['admin_server_settings'];
Chris@76 171 $context['sub_template'] = 'show_settings';
Chris@76 172
Chris@76 173 $subActions = array(
Chris@76 174 'general' => 'ModifyGeneralSettings',
Chris@76 175 'database' => 'ModifyDatabaseSettings',
Chris@76 176 'cookie' => 'ModifyCookieSettings',
Chris@76 177 'cache' => 'ModifyCacheSettings',
Chris@76 178 'loads' => 'ModifyLoadBalancingSettings',
Chris@76 179 );
Chris@76 180
Chris@76 181 // By default we're editing the core settings
Chris@76 182 $_REQUEST['sa'] = isset($_REQUEST['sa']) && isset($subActions[$_REQUEST['sa']]) ? $_REQUEST['sa'] : 'general';
Chris@76 183 $context['sub_action'] = $_REQUEST['sa'];
Chris@76 184
Chris@76 185 // Warn the user if there's any relevant information regarding Settings.php.
Chris@76 186 if ($_REQUEST['sa'] != 'cache')
Chris@76 187 {
Chris@76 188 // Warn the user if the backup of Settings.php failed.
Chris@76 189 $settings_not_writable = !is_writable($boarddir . '/Settings.php');
Chris@76 190 $settings_backup_fail = !@is_writable($boarddir . '/Settings_bak.php') || !@copy($boarddir . '/Settings.php', $boarddir . '/Settings_bak.php');
Chris@76 191
Chris@76 192 if ($settings_not_writable)
Chris@76 193 $context['settings_message'] = '<div class="centertext"><strong>' . $txt['settings_not_writable'] . '</strong></div><br />';
Chris@76 194 elseif ($settings_backup_fail)
Chris@76 195 $context['settings_message'] = '<div class="centertext"><strong>' . $txt['admin_backup_fail'] . '</strong></div><br />';
Chris@76 196
Chris@76 197 $context['settings_not_writable'] = $settings_not_writable;
Chris@76 198 }
Chris@76 199
Chris@76 200 // Call the right function for this sub-action.
Chris@76 201 $subActions[$_REQUEST['sa']]();
Chris@76 202 }
Chris@76 203
Chris@76 204 // General forum settings - forum name, maintenance mode, etc.
Chris@76 205 function ModifyGeneralSettings($return_config = false)
Chris@76 206 {
Chris@76 207 global $scripturl, $context, $txt;
Chris@76 208
Chris@76 209 /* If you're writing a mod, it's a bad idea to add things here....
Chris@76 210 For each option:
Chris@76 211 variable name, description, type (constant), size/possible values, helptext.
Chris@76 212 OR an empty string for a horizontal rule.
Chris@76 213 OR a string for a titled section. */
Chris@76 214 $config_vars = array(
Chris@76 215 array('mbname', $txt['admin_title'], 'file', 'text', 30),
Chris@76 216 '',
Chris@76 217 array('maintenance', $txt['admin_maintain'], 'file', 'check'),
Chris@76 218 array('mtitle', $txt['maintenance_subject'], 'file', 'text', 36),
Chris@76 219 array('mmessage', $txt['maintenance_message'], 'file', 'text', 36),
Chris@76 220 '',
Chris@76 221 array('webmaster_email', $txt['admin_webmaster_email'], 'file', 'text', 30),
Chris@76 222 '',
Chris@76 223 array('enableCompressedOutput', $txt['enableCompressedOutput'], 'db', 'check', null, 'enableCompressedOutput'),
Chris@76 224 array('disableTemplateEval', $txt['disableTemplateEval'], 'db', 'check', null, 'disableTemplateEval'),
Chris@76 225 array('disableHostnameLookup', $txt['disableHostnameLookup'], 'db', 'check', null, 'disableHostnameLookup'),
Chris@76 226 );
Chris@76 227
Chris@76 228 if ($return_config)
Chris@76 229 return $config_vars;
Chris@76 230
Chris@76 231 // Setup the template stuff.
Chris@76 232 $context['post_url'] = $scripturl . '?action=admin;area=serversettings;sa=general;save';
Chris@76 233 $context['settings_title'] = $txt['general_settings'];
Chris@76 234
Chris@76 235 // Saving settings?
Chris@76 236 if (isset($_REQUEST['save']))
Chris@76 237 {
Chris@76 238 saveSettings($config_vars);
Chris@76 239 redirectexit('action=admin;area=serversettings;sa=general;' . $context['session_var'] . '=' . $context['session_id']);
Chris@76 240 }
Chris@76 241
Chris@76 242 // Fill the config array.
Chris@76 243 prepareServerSettingsContext($config_vars);
Chris@76 244 }
Chris@76 245
Chris@76 246 // Basic database and paths settings - database name, host, etc.
Chris@76 247 function ModifyDatabaseSettings($return_config = false)
Chris@76 248 {
Chris@76 249 global $scripturl, $context, $settings, $txt, $boarddir;
Chris@76 250
Chris@76 251 /* If you're writing a mod, it's a bad idea to add things here....
Chris@76 252 For each option:
Chris@76 253 variable name, description, type (constant), size/possible values, helptext.
Chris@76 254 OR an empty string for a horizontal rule.
Chris@76 255 OR a string for a titled section. */
Chris@76 256 $config_vars = array(
Chris@76 257 array('db_server', $txt['database_server'], 'file', 'text'),
Chris@76 258 array('db_user', $txt['database_user'], 'file', 'text'),
Chris@76 259 array('db_passwd', $txt['database_password'], 'file', 'password'),
Chris@76 260 array('db_name', $txt['database_name'], 'file', 'text'),
Chris@76 261 array('db_prefix', $txt['database_prefix'], 'file', 'text'),
Chris@76 262 array('db_persist', $txt['db_persist'], 'file', 'check', null, 'db_persist'),
Chris@76 263 array('db_error_send', $txt['db_error_send'], 'file', 'check'),
Chris@76 264 array('ssi_db_user', $txt['ssi_db_user'], 'file', 'text', null, 'ssi_db_user'),
Chris@76 265 array('ssi_db_passwd', $txt['ssi_db_passwd'], 'file', 'password'),
Chris@76 266 '',
Chris@76 267 array('autoFixDatabase', $txt['autoFixDatabase'], 'db', 'check', false, 'autoFixDatabase'),
Chris@76 268 array('autoOptMaxOnline', $txt['autoOptMaxOnline'], 'db', 'int'),
Chris@76 269 '',
Chris@76 270 array('boardurl', $txt['admin_url'], 'file', 'text', 36),
Chris@76 271 array('boarddir', $txt['boarddir'], 'file', 'text', 36),
Chris@76 272 array('sourcedir', $txt['sourcesdir'], 'file', 'text', 36),
Chris@76 273 array('cachedir', $txt['cachedir'], 'file', 'text', 36),
Chris@76 274 );
Chris@76 275
Chris@76 276 if ($return_config)
Chris@76 277 return $config_vars;
Chris@76 278
Chris@76 279 // Setup the template stuff.
Chris@76 280 $context['post_url'] = $scripturl . '?action=admin;area=serversettings;sa=database;save';
Chris@76 281 $context['settings_title'] = $txt['database_paths_settings'];
Chris@76 282 $context['save_disabled'] = $context['settings_not_writable'];
Chris@76 283
Chris@76 284 // Saving settings?
Chris@76 285 if (isset($_REQUEST['save']))
Chris@76 286 {
Chris@76 287 saveSettings($config_vars);
Chris@76 288 redirectexit('action=admin;area=serversettings;sa=database;' . $context['session_var'] . '=' . $context['session_id']);
Chris@76 289 }
Chris@76 290
Chris@76 291 // Fill the config array.
Chris@76 292 prepareServerSettingsContext($config_vars);
Chris@76 293 }
Chris@76 294
Chris@76 295 // This function basically edits anything which is configuration and stored in the database, except for caching.
Chris@76 296 function ModifyCookieSettings($return_config = false)
Chris@76 297 {
Chris@76 298 global $context, $scripturl, $txt, $sourcedir, $modSettings, $cookiename, $user_settings;
Chris@76 299
Chris@76 300 // Define the variables we want to edit.
Chris@76 301 $config_vars = array(
Chris@76 302 // Cookies...
Chris@76 303 array('cookiename', $txt['cookie_name'], 'file', 'text', 20),
Chris@76 304 array('cookieTime', $txt['cookieTime'], 'db', 'int'),
Chris@76 305 array('localCookies', $txt['localCookies'], 'db', 'check', false, 'localCookies'),
Chris@76 306 array('globalCookies', $txt['globalCookies'], 'db', 'check', false, 'globalCookies'),
Chris@76 307 array('secureCookies', $txt['secureCookies'], 'db', 'check', false, 'secureCookies', 'disabled' => !isset($_SERVER['HTTPS']) || !(strtolower($_SERVER['HTTPS']) == 'on' || strtolower($_SERVER['HTTPS']) == '1')),
Chris@76 308 '',
Chris@76 309 // Sessions
Chris@76 310 array('databaseSession_enable', $txt['databaseSession_enable'], 'db', 'check', false, 'databaseSession_enable'),
Chris@76 311 array('databaseSession_loose', $txt['databaseSession_loose'], 'db', 'check', false, 'databaseSession_loose'),
Chris@76 312 array('databaseSession_lifetime', $txt['databaseSession_lifetime'], 'db', 'int', false, 'databaseSession_lifetime'),
Chris@76 313 );
Chris@76 314
Chris@76 315 if ($return_config)
Chris@76 316 return $config_vars;
Chris@76 317
Chris@76 318 $context['post_url'] = $scripturl . '?action=admin;area=serversettings;sa=cookie;save';
Chris@76 319 $context['settings_title'] = $txt['cookies_sessions_settings'];
Chris@76 320
Chris@76 321 // Saving settings?
Chris@76 322 if (isset($_REQUEST['save']))
Chris@76 323 {
Chris@76 324 saveSettings($config_vars);
Chris@76 325
Chris@76 326 // If the cookie name was changed, reset the cookie.
Chris@76 327 if ($cookiename != $_POST['cookiename'])
Chris@76 328 {
Chris@76 329 $original_session_id = $context['session_id'];
Chris@76 330 include_once($sourcedir . '/Subs-Auth.php');
Chris@76 331
Chris@76 332 // Remove the old cookie.
Chris@76 333 setLoginCookie(-3600, 0);
Chris@76 334
Chris@76 335 // Set the new one.
Chris@76 336 $cookiename = $_POST['cookiename'];
Chris@76 337 setLoginCookie(60 * $modSettings['cookieTime'], $user_settings['id_member'], sha1($user_settings['passwd'] . $user_settings['password_salt']));
Chris@76 338
Chris@76 339 redirectexit('action=admin;area=serversettings;sa=cookie;' . $context['session_var'] . '=' . $original_session_id, $context['server']['needs_login_fix']);
Chris@76 340 }
Chris@76 341
Chris@76 342 redirectexit('action=admin;area=serversettings;sa=cookie;' . $context['session_var'] . '=' . $context['session_id']);
Chris@76 343 }
Chris@76 344
Chris@76 345 // Fill the config array.
Chris@76 346 prepareServerSettingsContext($config_vars);
Chris@76 347 }
Chris@76 348
Chris@76 349 // Simply modifying cache functions
Chris@76 350 function ModifyCacheSettings($return_config = false)
Chris@76 351 {
Chris@76 352 global $context, $scripturl, $txt, $helptxt, $modSettings;
Chris@76 353
Chris@76 354 // Define the variables we want to edit.
Chris@76 355 $config_vars = array(
Chris@76 356 // Only a couple of settings, but they are important
Chris@76 357 array('select', 'cache_enable', array($txt['cache_off'], $txt['cache_level1'], $txt['cache_level2'], $txt['cache_level3'])),
Chris@76 358 array('text', 'cache_memcached'),
Chris@76 359 );
Chris@76 360
Chris@76 361 if ($return_config)
Chris@76 362 return $config_vars;
Chris@76 363
Chris@76 364 // Saving again?
Chris@76 365 if (isset($_GET['save']))
Chris@76 366 {
Chris@76 367 saveDBSettings($config_vars);
Chris@76 368
Chris@76 369 // We have to manually force the clearing of the cache otherwise the changed settings might not get noticed.
Chris@76 370 $modSettings['cache_enable'] = 1;
Chris@76 371 cache_put_data('modSettings', null, 90);
Chris@76 372
Chris@76 373 redirectexit('action=admin;area=serversettings;sa=cache;' . $context['session_var'] . '=' . $context['session_id']);
Chris@76 374 }
Chris@76 375
Chris@76 376 $context['post_url'] = $scripturl . '?action=admin;area=serversettings;sa=cache;save';
Chris@76 377 $context['settings_title'] = $txt['caching_settings'];
Chris@76 378 $context['settings_message'] = $txt['caching_information'];
Chris@76 379
Chris@76 380 // Detect an optimizer?
Chris@76 381 if (function_exists('eaccelerator_put'))
Chris@76 382 $detected = 'eAccelerator';
Chris@76 383 elseif (function_exists('mmcache_put'))
Chris@76 384 $detected = 'MMCache';
Chris@76 385 elseif (function_exists('apc_store'))
Chris@76 386 $detected = 'APC';
Chris@76 387 elseif (function_exists('output_cache_put'))
Chris@76 388 $detected = 'Zend';
Chris@76 389 elseif (function_exists('memcache_set'))
Chris@76 390 $detected = 'Memcached';
Chris@76 391 elseif (function_exists('xcache_set'))
Chris@76 392 $detected = 'XCache';
Chris@76 393 else
Chris@76 394 $detected = 'no_caching';
Chris@76 395
Chris@76 396 $context['settings_message'] = sprintf($context['settings_message'], $txt['detected_' . $detected]);
Chris@76 397
Chris@76 398 // Prepare the template.
Chris@76 399 prepareDBSettingContext($config_vars);
Chris@76 400 }
Chris@76 401
Chris@76 402 function ModifyLoadBalancingSettings($return_config = false)
Chris@76 403 {
Chris@76 404 global $txt, $scripturl, $context, $settings, $modSettings;
Chris@76 405
Chris@76 406 // Setup a warning message, but disabled by default.
Chris@76 407 $disabled = true;
Chris@76 408 $context['settings_message'] = $txt['loadavg_disabled_conf'];
Chris@76 409
Chris@76 410 if (strpos(strtolower(PHP_OS), 'win') === 0)
Chris@76 411 $context['settings_message'] = $txt['loadavg_disabled_windows'];
Chris@76 412 else
Chris@76 413 {
Chris@76 414 $modSettings['load_average'] = @file_get_contents('/proc/loadavg');
Chris@76 415 if (!empty($modSettings['load_average']) && preg_match('~^([^ ]+?) ([^ ]+?) ([^ ]+)~', $modSettings['load_average'], $matches) !== 0)
Chris@76 416 $modSettings['load_average'] = (float) $matches[1];
Chris@76 417 elseif (($modSettings['load_average'] = @`uptime`) !== null && preg_match('~load averages?: (\d+\.\d+), (\d+\.\d+), (\d+\.\d+)~i', $modSettings['load_average'], $matches) !== 0)
Chris@76 418 $modSettings['load_average'] = (float) $matches[1];
Chris@76 419 else
Chris@76 420 unset($modSettings['load_average']);
Chris@76 421
Chris@76 422 if (!empty($modSettings['load_average']))
Chris@76 423 {
Chris@76 424 $context['settings_message'] = sprintf($txt['loadavg_warning'], $modSettings['load_average']);
Chris@76 425 $disabled = false;
Chris@76 426 }
Chris@76 427 }
Chris@76 428
Chris@76 429 // Start with a simple checkbox.
Chris@76 430 $config_vars = array(
Chris@76 431 array('check', 'loadavg_enable'),
Chris@76 432 );
Chris@76 433
Chris@76 434 // Set the default values for each option.
Chris@76 435 $default_values = array(
Chris@76 436 'loadavg_auto_opt' => '1.0',
Chris@76 437 'loadavg_search' => '2.5',
Chris@76 438 'loadavg_allunread' => '2.0',
Chris@76 439 'loadavg_unreadreplies' => '3.5',
Chris@76 440 'loadavg_show_posts' => '2.0',
Chris@76 441 'loadavg_forum' => '40.0',
Chris@76 442 );
Chris@76 443
Chris@76 444 // Loop through the settings.
Chris@76 445 foreach ($default_values as $name => $value)
Chris@76 446 {
Chris@76 447 // Use the default value if the setting isn't set yet.
Chris@76 448 $value = !isset($modSettings[$name]) ? $value : $modSettings[$name];
Chris@76 449 $config_vars[] = array('text', $name, 'value' => $value, 'disabled' => $disabled);
Chris@76 450 }
Chris@76 451
Chris@76 452 if ($return_config)
Chris@76 453 return $config_vars;
Chris@76 454
Chris@76 455 $context['post_url'] = $scripturl . '?action=admin;area=serversettings;sa=loads;save';
Chris@76 456 $context['settings_title'] = $txt['load_balancing_settings'];
Chris@76 457
Chris@76 458 // Saving?
Chris@76 459 if (isset($_GET['save']))
Chris@76 460 {
Chris@76 461 // Stupidity is not allowed.
Chris@76 462 foreach ($_POST as $key => $value)
Chris@76 463 {
Chris@76 464 if (strpos($key, 'loadavg') === 0 || $key === 'loadavg_enable')
Chris@76 465 continue;
Chris@76 466 elseif ($key == 'loadavg_auto_opt' && $value <= 1)
Chris@76 467 $_POST['loadavg_auto_opt'] = '1.0';
Chris@76 468 elseif ($key == 'loadavg_forum' && $value < 10)
Chris@76 469 $_POST['loadavg_forum'] = '10.0';
Chris@76 470 elseif ($value < 2)
Chris@76 471 $_POST[$key] = '2.0';
Chris@76 472 }
Chris@76 473
Chris@76 474 saveDBSettings($config_vars);
Chris@76 475 redirectexit('action=admin;area=serversettings;sa=loads;' . $context['session_var'] . '=' . $context['session_id']);
Chris@76 476 }
Chris@76 477
Chris@76 478 prepareDBSettingContext($config_vars);
Chris@76 479 }
Chris@76 480
Chris@76 481 // This is the main function for the language area.
Chris@76 482 function ManageLanguages()
Chris@76 483 {
Chris@76 484 global $context, $txt, $scripturl, $modSettings;
Chris@76 485
Chris@76 486 loadLanguage('ManageSettings');
Chris@76 487
Chris@76 488 $context['page_title'] = $txt['edit_languages'];
Chris@76 489 $context['sub_template'] = 'show_settings';
Chris@76 490
Chris@76 491 $subActions = array(
Chris@76 492 'edit' => 'ModifyLanguages',
Chris@76 493 'add' => 'AddLanguage',
Chris@76 494 'settings' => 'ModifyLanguageSettings',
Chris@76 495 'downloadlang' => 'DownloadLanguage',
Chris@76 496 'editlang' => 'ModifyLanguage',
Chris@76 497 );
Chris@76 498
Chris@76 499 // By default we're managing languages.
Chris@76 500 $_REQUEST['sa'] = isset($_REQUEST['sa']) && isset($subActions[$_REQUEST['sa']]) ? $_REQUEST['sa'] : 'edit';
Chris@76 501 $context['sub_action'] = $_REQUEST['sa'];
Chris@76 502
Chris@76 503 // Load up all the tabs...
Chris@76 504 $context[$context['admin_menu_name']]['tab_data'] = array(
Chris@76 505 'title' => $txt['language_configuration'],
Chris@76 506 'description' => $txt['language_description'],
Chris@76 507 );
Chris@76 508
Chris@76 509 // Call the right function for this sub-acton.
Chris@76 510 $subActions[$_REQUEST['sa']]();
Chris@76 511 }
Chris@76 512
Chris@76 513 // Interface for adding a new language
Chris@76 514 function AddLanguage()
Chris@76 515 {
Chris@76 516 global $context, $sourcedir, $forum_version, $boarddir, $txt, $smcFunc, $scripturl;
Chris@76 517
Chris@76 518 // Are we searching for new languages courtesy of Simple Machines?
Chris@76 519 if (!empty($_POST['smf_add_sub']))
Chris@76 520 {
Chris@76 521 // Need fetch_web_data.
Chris@76 522 require_once($sourcedir . '/Subs-Package.php');
Chris@76 523
Chris@76 524 $context['smf_search_term'] = htmlspecialchars(trim($_POST['smf_add']));
Chris@76 525
Chris@76 526 // We're going to use this URL.
Chris@76 527 $url = 'http://download.simplemachines.org/fetch_language.php?version=' . urlencode(strtr($forum_version, array('SMF ' => '')));
Chris@76 528
Chris@76 529 // Load the class file and stick it into an array.
Chris@76 530 loadClassFile('Class-Package.php');
Chris@76 531 $language_list = new xmlArray(fetch_web_data($url), true);
Chris@76 532
Chris@76 533 // Check it exists.
Chris@76 534 if (!$language_list->exists('languages'))
Chris@76 535 $context['smf_error'] = 'no_response';
Chris@76 536 else
Chris@76 537 {
Chris@76 538 $language_list = $language_list->path('languages[0]');
Chris@76 539 $lang_files = $language_list->set('language');
Chris@76 540 $context['smf_languages'] = array();
Chris@76 541 foreach ($lang_files as $file)
Chris@76 542 {
Chris@76 543 // Were we searching?
Chris@76 544 if (!empty($context['smf_search_term']) && strpos($file->fetch('name'), $smcFunc['strtolower']($context['smf_search_term'])) === false)
Chris@76 545 continue;
Chris@76 546
Chris@76 547 $context['smf_languages'][] = array(
Chris@76 548 'id' => $file->fetch('id'),
Chris@76 549 'name' => $smcFunc['ucwords']($file->fetch('name')),
Chris@76 550 'version' => $file->fetch('version'),
Chris@76 551 'utf8' => $file->fetch('utf8'),
Chris@76 552 'description' => $file->fetch('description'),
Chris@76 553 'link' => $scripturl . '?action=admin;area=languages;sa=downloadlang;did=' . $file->fetch('id') . ';' . $context['session_var'] . '=' . $context['session_id'],
Chris@76 554 );
Chris@76 555 }
Chris@76 556 if (empty($context['smf_languages']))
Chris@76 557 $context['smf_error'] = 'no_files';
Chris@76 558 }
Chris@76 559 }
Chris@76 560
Chris@76 561 $context['sub_template'] = 'add_language';
Chris@76 562 }
Chris@76 563
Chris@76 564 // Download a language file from the Simple Machines website.
Chris@76 565 function DownloadLanguage()
Chris@76 566 {
Chris@76 567 global $context, $sourcedir, $forum_version, $boarddir, $txt, $smcFunc, $scripturl, $modSettings;
Chris@76 568
Chris@76 569 loadLanguage('ManageSettings');
Chris@76 570 require_once($sourcedir . '/Subs-Package.php');
Chris@76 571
Chris@76 572 // Clearly we need to know what to request.
Chris@76 573 if (!isset($_GET['did']))
Chris@76 574 fatal_lang_error('no_access', false);
Chris@76 575
Chris@76 576 // Some lovely context.
Chris@76 577 $context['download_id'] = $_GET['did'];
Chris@76 578 $context['sub_template'] = 'download_language';
Chris@76 579 $context['menu_data_' . $context['admin_menu_id']]['current_subsection'] = 'add';
Chris@76 580
Chris@76 581 // Can we actually do the installation - and do they want to?
Chris@76 582 if (!empty($_POST['do_install']) && !empty($_POST['copy_file']))
Chris@76 583 {
Chris@76 584 checkSession('get');
Chris@76 585
Chris@76 586 $chmod_files = array();
Chris@76 587 $install_files = array();
Chris@76 588 // Check writable status.
Chris@76 589 foreach ($_POST['copy_file'] as $file)
Chris@76 590 {
Chris@76 591 // Check it's not very bad.
Chris@76 592 if (strpos($file, '..') !== false || (substr($file, 0, 6) != 'Themes' && !preg_match('~agreement\.[A-Za-z-_0-9]+\.txt$~', $file)))
Chris@76 593 fatal_error($txt['languages_download_illegal_paths']);
Chris@76 594
Chris@76 595 $chmod_files[] = $boarddir . '/' . $file;
Chris@76 596 $install_files[] = $file;
Chris@76 597 }
Chris@76 598
Chris@76 599 // Call this in case we have work to do.
Chris@76 600 $file_status = create_chmod_control($chmod_files);
Chris@76 601 $files_left = $file_status['files']['notwritable'];
Chris@76 602
Chris@76 603 // Something not writable?
Chris@76 604 if (!empty($files_left))
Chris@76 605 $context['error_message'] = $txt['languages_download_not_chmod'];
Chris@76 606 // Otherwise, go go go!
Chris@76 607 elseif (!empty($install_files))
Chris@76 608 {
Chris@76 609 $archive_content = read_tgz_file('http://download.simplemachines.org/fetch_language.php?version=' . urlencode(strtr($forum_version, array('SMF ' => ''))) . ';fetch=' . urlencode($_GET['did']), $boarddir, false, true, $install_files);
Chris@76 610 // Make sure the files aren't stuck in the cache.
Chris@76 611 package_flush_cache();
Chris@76 612 $context['install_complete'] = sprintf($txt['languages_download_complete_desc'], $scripturl . '?action=admin;area=languages');
Chris@76 613
Chris@76 614 return;
Chris@76 615 }
Chris@76 616 }
Chris@76 617
Chris@76 618 // Open up the old china.
Chris@76 619 if (!isset($archive_content))
Chris@76 620 $archive_content = read_tgz_file('http://download.simplemachines.org/fetch_language.php?version=' . urlencode(strtr($forum_version, array('SMF ' => ''))) . ';fetch=' . urlencode($_GET['did']), null);
Chris@76 621
Chris@76 622 if (empty($archive_content))
Chris@76 623 fatal_error($txt['add_language_error_no_response']);
Chris@76 624
Chris@76 625 // Now for each of the files, let's do some *stuff*
Chris@76 626 $context['files'] = array(
Chris@76 627 'lang' => array(),
Chris@76 628 'other' => array(),
Chris@76 629 );
Chris@76 630 $context['make_writable'] = array();
Chris@76 631 foreach ($archive_content as $file)
Chris@76 632 {
Chris@76 633 $dirname = dirname($file['filename']);
Chris@76 634 $filename = basename($file['filename']);
Chris@76 635 $extension = substr($filename, strrpos($filename, '.') + 1);
Chris@76 636
Chris@76 637 // Don't do anything with files we don't understand.
Chris@76 638 if (!in_array($extension, array('php', 'jpg', 'gif', 'jpeg', 'png', 'txt')))
Chris@76 639 continue;
Chris@76 640
Chris@76 641 // Basic data.
Chris@76 642 $context_data = array(
Chris@76 643 'name' => $filename,
Chris@76 644 'destination' => $boarddir . '/' . $file['filename'],
Chris@76 645 'generaldest' => $file['filename'],
Chris@76 646 'size' => $file['size'],
Chris@76 647 // Does chmod status allow the copy?
Chris@76 648 'writable' => false,
Chris@76 649 // Should we suggest they copy this file?
Chris@76 650 'default_copy' => true,
Chris@76 651 // Does the file already exist, if so is it same or different?
Chris@76 652 'exists' => false,
Chris@76 653 );
Chris@76 654
Chris@76 655 // Does the file exist, is it different and can we overwrite?
Chris@76 656 if (file_exists($boarddir . '/' . $file['filename']))
Chris@76 657 {
Chris@76 658 if (is_writable($boarddir . '/' . $file['filename']))
Chris@76 659 $context_data['writable'] = true;
Chris@76 660
Chris@76 661 // Finally, do we actually think the content has changed?
Chris@76 662 if ($file['size'] == filesize($boarddir . '/' . $file['filename']) && $file['md5'] == md5_file($boarddir . '/' . $file['filename']))
Chris@76 663 {
Chris@76 664 $context_data['exists'] = 'same';
Chris@76 665 $context_data['default_copy'] = false;
Chris@76 666 }
Chris@76 667 // Attempt to discover newline character differences.
Chris@76 668 elseif ($file['md5'] == md5(preg_replace("~[\r]?\n~", "\r\n", file_get_contents($boarddir . '/' . $file['filename']))))
Chris@76 669 {
Chris@76 670 $context_data['exists'] = 'same';
Chris@76 671 $context_data['default_copy'] = false;
Chris@76 672 }
Chris@76 673 else
Chris@76 674 $context_data['exists'] = 'different';
Chris@76 675 }
Chris@76 676 // No overwrite?
Chris@76 677 else
Chris@76 678 {
Chris@76 679 // Can we at least stick it in the directory...
Chris@76 680 if (is_writable($boarddir . '/' . $dirname))
Chris@76 681 $context_data['writable'] = true;
Chris@76 682 }
Chris@76 683
Chris@76 684 // I love PHP files, that's why I'm a developer and not an artistic type spending my time drinking absinth and living a life of sin...
Chris@76 685 if ($extension == 'php' && preg_match('~\w+\.\w+(?:-utf8)?\.php~', $filename))
Chris@76 686 {
Chris@76 687 $context_data += array(
Chris@76 688 'version' => '??',
Chris@76 689 'cur_version' => false,
Chris@76 690 'version_compare' => 'newer',
Chris@76 691 );
Chris@76 692
Chris@76 693 list ($name, $language) = explode('.', $filename);
Chris@76 694
Chris@76 695 // Let's get the new version, I like versions, they tell me that I'm up to date.
Chris@76 696 if (preg_match('~\s*Version:\s+(.+?);\s*' . preg_quote($name, '~') . '~i', $file['preview'], $match) == 1)
Chris@76 697 $context_data['version'] = $match[1];
Chris@76 698
Chris@76 699 // Now does the old file exist - if so what is it's version?
Chris@76 700 if (file_exists($boarddir . '/' . $file['filename']))
Chris@76 701 {
Chris@76 702 // OK - what is the current version?
Chris@76 703 $fp = fopen($boarddir . '/' . $file['filename'], 'rb');
Chris@76 704 $header = fread($fp, 768);
Chris@76 705 fclose($fp);
Chris@76 706
Chris@76 707 // Find the version.
Chris@76 708 if (preg_match('~(?://|/\*)\s*Version:\s+(.+?);\s*' . preg_quote($name, '~') . '(?:[\s]{2}|\*/)~i', $header, $match) == 1)
Chris@76 709 {
Chris@76 710 $context_data['cur_version'] = $match[1];
Chris@76 711
Chris@76 712 // How does this compare?
Chris@76 713 if ($context_data['cur_version'] == $context_data['version'])
Chris@76 714 $context_data['version_compare'] = 'same';
Chris@76 715 elseif ($context_data['cur_version'] > $context_data['version'])
Chris@76 716 $context_data['version_compare'] = 'older';
Chris@76 717
Chris@76 718 // Don't recommend copying if the version is the same.
Chris@76 719 if ($context_data['version_compare'] != 'newer')
Chris@76 720 $context_data['default_copy'] = false;
Chris@76 721 }
Chris@76 722 }
Chris@76 723
Chris@76 724 // Add the context data to the main set.
Chris@76 725 $context['files']['lang'][] = $context_data;
Chris@76 726 }
Chris@76 727 else
Chris@76 728 {
Chris@76 729 // If we think it's a theme thing, work out what the theme is.
Chris@76 730 if (substr($dirname, 0, 6) == 'Themes' && preg_match('~Themes[\\/]([^\\/]+)[\\/]~', $dirname, $match))
Chris@76 731 $theme_name = $match[1];
Chris@76 732 else
Chris@76 733 $theme_name = 'misc';
Chris@76 734
Chris@76 735 // Assume it's an image, could be an acceptance note etc but rare.
Chris@76 736 $context['files']['images'][$theme_name][] = $context_data;
Chris@76 737 }
Chris@76 738
Chris@76 739 // Collect together all non-writable areas.
Chris@76 740 if (!$context_data['writable'])
Chris@76 741 $context['make_writable'][] = $context_data['destination'];
Chris@76 742 }
Chris@76 743
Chris@76 744 // So, I'm a perfectionist - let's get the theme names.
Chris@76 745 $theme_indexes = array();
Chris@76 746 foreach ($context['files']['images'] as $k => $dummy)
Chris@76 747 $indexes[] = $k;
Chris@76 748
Chris@76 749 $context['theme_names'] = array();
Chris@76 750 if (!empty($indexes))
Chris@76 751 {
Chris@76 752 $value_data = array(
Chris@76 753 'query' => array(),
Chris@76 754 'params' => array(),
Chris@76 755 );
Chris@76 756
Chris@76 757 foreach ($indexes as $k => $index)
Chris@76 758 {
Chris@76 759 $value_data['query'][] = 'value LIKE {string:value_' . $k . '}';
Chris@76 760 $value_data['params']['value_' . $k] = '%' . $index;
Chris@76 761 }
Chris@76 762
Chris@76 763 $request = $smcFunc['db_query']('', '
Chris@76 764 SELECT id_theme, value
Chris@76 765 FROM {db_prefix}themes
Chris@76 766 WHERE id_member = {int:no_member}
Chris@76 767 AND variable = {string:theme_dir}
Chris@76 768 AND (' . implode(' OR ', $value_data['query']) . ')',
Chris@76 769 array_merge($value_data['params'], array(
Chris@76 770 'no_member' => 0,
Chris@76 771 'theme_dir' => 'theme_dir',
Chris@76 772 'index_compare_explode' => 'value LIKE \'%' . implode('\' OR value LIKE \'%', $indexes) . '\'',
Chris@76 773 ))
Chris@76 774 );
Chris@76 775 $themes = array();
Chris@76 776 while ($row = $smcFunc['db_fetch_assoc']($request))
Chris@76 777 {
Chris@76 778 // Find the right one.
Chris@76 779 foreach ($indexes as $index)
Chris@76 780 if (strpos($row['value'], $index) !== false)
Chris@76 781 $themes[$row['id_theme']] = $index;
Chris@76 782 }
Chris@76 783 $smcFunc['db_free_result']($request);
Chris@76 784
Chris@76 785 if (!empty($themes))
Chris@76 786 {
Chris@76 787 // Now we have the id_theme we can get the pretty description.
Chris@76 788 $request = $smcFunc['db_query']('', '
Chris@76 789 SELECT id_theme, value
Chris@76 790 FROM {db_prefix}themes
Chris@76 791 WHERE id_member = {int:no_member}
Chris@76 792 AND variable = {string:name}
Chris@76 793 AND id_theme IN ({array_int:theme_list})',
Chris@76 794 array(
Chris@76 795 'theme_list' => array_keys($themes),
Chris@76 796 'no_member' => 0,
Chris@76 797 'name' => 'name',
Chris@76 798 )
Chris@76 799 );
Chris@76 800 while ($row = $smcFunc['db_fetch_assoc']($request))
Chris@76 801 {
Chris@76 802 // Now we have it...
Chris@76 803 $context['theme_names'][$themes[$row['id_theme']]] = $row['value'];
Chris@76 804 }
Chris@76 805 $smcFunc['db_free_result']($request);
Chris@76 806 }
Chris@76 807 }
Chris@76 808
Chris@76 809 // Before we go to far can we make anything writable, eh, eh?
Chris@76 810 if (!empty($context['make_writable']))
Chris@76 811 {
Chris@76 812 // What is left to be made writable?
Chris@76 813 $file_status = create_chmod_control($context['make_writable']);
Chris@76 814 $context['still_not_writable'] = $file_status['files']['notwritable'];
Chris@76 815
Chris@76 816 // Mark those which are now writable as such.
Chris@76 817 foreach ($context['files'] as $type => $data)
Chris@76 818 {
Chris@76 819 if ($type == 'lang')
Chris@76 820 {
Chris@76 821 foreach ($data as $k => $file)
Chris@76 822 if (!$file['writable'] && !in_array($file['destination'], $context['still_not_writable']))
Chris@76 823 $context['files'][$type][$k]['writable'] = true;
Chris@76 824 }
Chris@76 825 else
Chris@76 826 {
Chris@76 827 foreach ($data as $theme => $files)
Chris@76 828 foreach ($files as $k => $file)
Chris@76 829 if (!$file['writable'] && !in_array($file['destination'], $context['still_not_writable']))
Chris@76 830 $context['files'][$type][$theme][$k]['writable'] = true;
Chris@76 831 }
Chris@76 832 }
Chris@76 833
Chris@76 834 // Are we going to need more language stuff?
Chris@76 835 if (!empty($context['still_not_writable']))
Chris@76 836 loadLanguage('Packages');
Chris@76 837 }
Chris@76 838
Chris@76 839 // This is the list for the main files.
Chris@76 840 $listOptions = array(
Chris@76 841 'id' => 'lang_main_files_list',
Chris@76 842 'title' => $txt['languages_download_main_files'],
Chris@76 843 'get_items' => array(
Chris@76 844 'function' => create_function('', '
Chris@76 845 global $context;
Chris@76 846 return $context[\'files\'][\'lang\'];
Chris@76 847 '),
Chris@76 848 ),
Chris@76 849 'columns' => array(
Chris@76 850 'name' => array(
Chris@76 851 'header' => array(
Chris@76 852 'value' => $txt['languages_download_filename'],
Chris@76 853 ),
Chris@76 854 'data' => array(
Chris@76 855 'function' => create_function('$rowData', '
Chris@76 856 global $context, $txt;
Chris@76 857
Chris@76 858 return \'<strong>\' . $rowData[\'name\'] . \'</strong><br /><span class="smalltext">\' . $txt[\'languages_download_dest\'] . \': \' . $rowData[\'destination\'] . \'</span>\' . ($rowData[\'version_compare\'] == \'older\' ? \'<br />\' . $txt[\'languages_download_older\'] : \'\');
Chris@76 859 '),
Chris@76 860 ),
Chris@76 861 ),
Chris@76 862 'writable' => array(
Chris@76 863 'header' => array(
Chris@76 864 'value' => $txt['languages_download_writable'],
Chris@76 865 ),
Chris@76 866 'data' => array(
Chris@76 867 'function' => create_function('$rowData', '
Chris@76 868 global $txt;
Chris@76 869
Chris@76 870 return \'<span style="color: \' . ($rowData[\'writable\'] ? \'green\' : \'red\') . \';">\' . ($rowData[\'writable\'] ? $txt[\'yes\'] : $txt[\'no\']) . \'</span>\';
Chris@76 871 '),
Chris@76 872 'style' => 'text-align: center',
Chris@76 873 ),
Chris@76 874 ),
Chris@76 875 'version' => array(
Chris@76 876 'header' => array(
Chris@76 877 'value' => $txt['languages_download_version'],
Chris@76 878 ),
Chris@76 879 'data' => array(
Chris@76 880 'function' => create_function('$rowData', '
Chris@76 881 global $txt;
Chris@76 882
Chris@76 883 return \'<span style="color: \' . ($rowData[\'version_compare\'] == \'older\' ? \'red\' : ($rowData[\'version_compare\'] == \'same\' ? \'orange\' : \'green\')) . \';">\' . $rowData[\'version\'] . \'</span>\';
Chris@76 884 '),
Chris@76 885 ),
Chris@76 886 ),
Chris@76 887 'exists' => array(
Chris@76 888 'header' => array(
Chris@76 889 'value' => $txt['languages_download_exists'],
Chris@76 890 ),
Chris@76 891 'data' => array(
Chris@76 892 'function' => create_function('$rowData', '
Chris@76 893 global $txt;
Chris@76 894
Chris@76 895 return $rowData[\'exists\'] ? ($rowData[\'exists\'] == \'same\' ? $txt[\'languages_download_exists_same\'] : $txt[\'languages_download_exists_different\']) : $txt[\'no\'];
Chris@76 896 '),
Chris@76 897 ),
Chris@76 898 ),
Chris@76 899 'copy' => array(
Chris@76 900 'header' => array(
Chris@76 901 'value' => $txt['languages_download_copy'],
Chris@76 902 ),
Chris@76 903 'data' => array(
Chris@76 904 'function' => create_function('$rowData', '
Chris@76 905 return \'<input type="checkbox" name="copy_file[]" value="\' . $rowData[\'generaldest\'] . \'" \' . ($rowData[\'default_copy\'] ? \'checked="checked"\' : \'\') . \' class="input_check" />\';
Chris@76 906 '),
Chris@76 907 'style' => 'text-align: center; width: 4%;',
Chris@76 908 ),
Chris@76 909 ),
Chris@76 910 ),
Chris@76 911 );
Chris@76 912
Chris@76 913 // Kill the cache, as it is now invalid..
Chris@76 914 if (!empty($modSettings['cache_enable']))
Chris@76 915 {
Chris@76 916 cache_put_data('known_languages', null, !empty($modSettings['cache_enable']) && $modSettings['cache_enable'] < 1 ? 86400 : 3600);
Chris@76 917 cache_put_data('known_languages_all', null, !empty($modSettings['cache_enable']) && $modSettings['cache_enable'] < 1 ? 86400 : 3600);
Chris@76 918 }
Chris@76 919
Chris@76 920 require_once($sourcedir . '/Subs-List.php');
Chris@76 921 createList($listOptions);
Chris@76 922
Chris@76 923 $context['default_list'] = 'lang_main_files_list';
Chris@76 924 }
Chris@76 925
Chris@76 926 // This lists all the current languages and allows editing of them.
Chris@76 927 function ModifyLanguages()
Chris@76 928 {
Chris@76 929 global $txt, $context, $scripturl;
Chris@76 930 global $user_info, $smcFunc, $sourcedir, $language, $boarddir, $forum_version;
Chris@76 931
Chris@76 932 // Setting a new default?
Chris@76 933 if (!empty($_POST['set_default']) && !empty($_POST['def_language']))
Chris@76 934 {
Chris@76 935 checkSession();
Chris@76 936
Chris@76 937 getLanguages(true, false);
Chris@76 938 $lang_exists = false;
Chris@76 939 foreach ($context['languages'] as $lang)
Chris@76 940 {
Chris@76 941 if ($_POST['def_language'] == $lang['filename'])
Chris@76 942 {
Chris@76 943 $lang_exists = true;
Chris@76 944 break;
Chris@76 945 }
Chris@76 946 }
Chris@76 947
Chris@76 948 if ($_POST['def_language'] != $language && $lang_exists)
Chris@76 949 {
Chris@76 950 require_once($sourcedir . '/Subs-Admin.php');
Chris@76 951 updateSettingsFile(array('language' => '\'' . $_POST['def_language'] . '\''));
Chris@76 952 $language = $_POST['def_language'];
Chris@76 953 }
Chris@76 954 }
Chris@76 955
Chris@76 956 $listOptions = array(
Chris@76 957 'id' => 'language_list',
Chris@76 958 'items_per_page' => 20,
Chris@76 959 'base_href' => $scripturl . '?action=admin;area=languages',
Chris@76 960 'title' => $txt['edit_languages'],
Chris@76 961 'get_items' => array(
Chris@76 962 'function' => 'list_getLanguages',
Chris@76 963 ),
Chris@76 964 'get_count' => array(
Chris@76 965 'function' => 'list_getNumLanguages',
Chris@76 966 ),
Chris@76 967 'columns' => array(
Chris@76 968 'default' => array(
Chris@76 969 'header' => array(
Chris@76 970 'value' => $txt['languages_default'],
Chris@76 971 ),
Chris@76 972 'data' => array(
Chris@76 973 'function' => create_function('$rowData', '
Chris@76 974 return \'<input type="radio" name="def_language" value="\' . $rowData[\'id\'] . \'" \' . ($rowData[\'default\'] ? \'checked="checked"\' : \'\') . \' onclick="highlightSelected(\\\'list_language_list_\' . $rowData[\'id\'] . \'\\\');" class="input_radio" />\';
Chris@76 975 '),
Chris@76 976 'style' => 'text-align: center; width: 8%;',
Chris@76 977 ),
Chris@76 978 ),
Chris@76 979 'name' => array(
Chris@76 980 'header' => array(
Chris@76 981 'value' => $txt['languages_lang_name'],
Chris@76 982 ),
Chris@76 983 'data' => array(
Chris@76 984 'function' => create_function('$rowData', '
Chris@76 985 global $scripturl, $context;
Chris@76 986
Chris@76 987 return sprintf(\'<a href="%1$s?action=admin;area=languages;sa=editlang;lid=%2$s">%3$s</a>\', $scripturl, $rowData[\'id\'], $rowData[\'name\']);
Chris@76 988 '),
Chris@76 989 ),
Chris@76 990 ),
Chris@76 991 'character_set' => array(
Chris@76 992 'header' => array(
Chris@76 993 'value' => $txt['languages_character_set'],
Chris@76 994 ),
Chris@76 995 'data' => array(
Chris@76 996 'db_htmlsafe' => 'char_set',
Chris@76 997 ),
Chris@76 998 ),
Chris@76 999 'count' => array(
Chris@76 1000 'header' => array(
Chris@76 1001 'value' => $txt['languages_users'],
Chris@76 1002 ),
Chris@76 1003 'data' => array(
Chris@76 1004 'db_htmlsafe' => 'count',
Chris@76 1005 'style' => 'text-align: center',
Chris@76 1006 ),
Chris@76 1007 ),
Chris@76 1008 'locale' => array(
Chris@76 1009 'header' => array(
Chris@76 1010 'value' => $txt['languages_locale'],
Chris@76 1011 ),
Chris@76 1012 'data' => array(
Chris@76 1013 'db_htmlsafe' => 'locale',
Chris@76 1014 ),
Chris@76 1015 ),
Chris@76 1016 ),
Chris@76 1017 'form' => array(
Chris@76 1018 'href' => $scripturl . '?action=admin;area=languages',
Chris@76 1019 ),
Chris@76 1020 'additional_rows' => array(
Chris@76 1021 array(
Chris@76 1022 'position' => 'below_table_data',
Chris@76 1023 'value' => '<input type="hidden" name="' . $context['session_var'] . '" value="' . $context['session_id'] . '" /><input type="submit" name="set_default" value="' . $txt['save'] . '"' . (is_writable($boarddir . '/Settings.php') ? '' : ' disabled="disabled"') . ' class="button_submit" />',
Chris@76 1024 'style' => 'text-align: right;',
Chris@76 1025 ),
Chris@76 1026 ),
Chris@76 1027 // For highlighting the default.
Chris@76 1028 'javascript' => '
Chris@76 1029 var prevClass = "";
Chris@76 1030 var prevDiv = "";
Chris@76 1031 function highlightSelected(box)
Chris@76 1032 {
Chris@76 1033 if (prevClass != "")
Chris@76 1034 prevDiv.className = prevClass;
Chris@76 1035
Chris@76 1036 prevDiv = document.getElementById(box);
Chris@76 1037 prevClass = prevDiv.className;
Chris@76 1038
Chris@76 1039 prevDiv.className = "highlight2";
Chris@76 1040 }
Chris@76 1041 highlightSelected("list_language_list_' . ($language == '' ? 'english' : $language). '");
Chris@76 1042 ',
Chris@76 1043 );
Chris@76 1044
Chris@76 1045 // Display a warning if we cannot edit the default setting.
Chris@76 1046 if (!is_writable($boarddir . '/Settings.php'))
Chris@76 1047 $listOptions['additional_rows'][] = array(
Chris@76 1048 'position' => 'after_title',
Chris@76 1049 'value' => $txt['language_settings_writable'],
Chris@76 1050 'class' => 'smalltext alert',
Chris@76 1051 );
Chris@76 1052
Chris@76 1053 require_once($sourcedir . '/Subs-List.php');
Chris@76 1054 createList($listOptions);
Chris@76 1055
Chris@76 1056 $context['sub_template'] = 'show_list';
Chris@76 1057 $context['default_list'] = 'language_list';
Chris@76 1058 }
Chris@76 1059
Chris@76 1060 // How many languages?
Chris@76 1061 function list_getNumLanguages()
Chris@76 1062 {
Chris@76 1063 global $settings;
Chris@76 1064
Chris@76 1065 // Return how many we have.
Chris@76 1066 return count(getLanguages(true, false));
Chris@76 1067 }
Chris@76 1068
Chris@76 1069 // Fetch the actual language information.
Chris@76 1070 function list_getLanguages()
Chris@76 1071 {
Chris@76 1072 global $settings, $smcFunc, $language, $context, $txt;
Chris@76 1073
Chris@76 1074 $languages = array();
Chris@76 1075 // Keep our old entries.
Chris@76 1076 $old_txt = $txt;
Chris@76 1077 $backup_actual_theme_dir = $settings['actual_theme_dir'];
Chris@76 1078 $backup_base_theme_dir = !empty($settings['base_theme_dir']) ? $settings['base_theme_dir'] : '';
Chris@76 1079
Chris@76 1080 // Override these for now.
Chris@76 1081 $settings['actual_theme_dir'] = $settings['base_theme_dir'] = $settings['default_theme_dir'];
Chris@76 1082 getLanguages(true, false);
Chris@76 1083
Chris@76 1084 // Put them back.
Chris@76 1085 $settings['actual_theme_dir'] = $backup_actual_theme_dir;
Chris@76 1086 if (!empty($backup_base_theme_dir))
Chris@76 1087 $settings['base_theme_dir'] = $backup_base_theme_dir;
Chris@76 1088 else
Chris@76 1089 unset($settings['base_theme_dir']);
Chris@76 1090
Chris@76 1091 // Get the language files and data...
Chris@76 1092 foreach ($context['languages'] as $lang)
Chris@76 1093 {
Chris@76 1094 // Load the file to get the character set.
Chris@76 1095 require($settings['default_theme_dir'] . '/languages/index.' . $lang['filename'] . '.php');
Chris@76 1096
Chris@76 1097 $languages[$lang['filename']] = array(
Chris@76 1098 'id' => $lang['filename'],
Chris@76 1099 'count' => 0,
Chris@76 1100 'char_set' => $txt['lang_character_set'],
Chris@76 1101 'default' => $language == $lang['filename'] || ($language == '' && $lang['filename'] == 'english'),
Chris@76 1102 'locale' => $txt['lang_locale'],
Chris@76 1103 'name' => $smcFunc['ucwords'](strtr($lang['filename'], array('_' => ' ', '-utf8' => ''))),
Chris@76 1104 );
Chris@76 1105 }
Chris@76 1106
Chris@76 1107 // Work out how many people are using each language.
Chris@76 1108 $request = $smcFunc['db_query']('', '
Chris@76 1109 SELECT lngfile, COUNT(*) AS num_users
Chris@76 1110 FROM {db_prefix}members
Chris@76 1111 GROUP BY lngfile',
Chris@76 1112 array(
Chris@76 1113 )
Chris@76 1114 );
Chris@76 1115 while ($row = $smcFunc['db_fetch_assoc']($request))
Chris@76 1116 {
Chris@76 1117 // Default?
Chris@76 1118 if (empty($row['lngfile']) || !isset($languages[$row['lngfile']]))
Chris@76 1119 $row['lngfile'] = $language;
Chris@76 1120
Chris@76 1121 if (!isset($languages[$row['lngfile']]) && isset($languages['english']))
Chris@76 1122 $languages['english']['count'] += $row['num_users'];
Chris@76 1123 elseif (isset($languages[$row['lngfile']]))
Chris@76 1124 $languages[$row['lngfile']]['count'] += $row['num_users'];
Chris@76 1125 }
Chris@76 1126 $smcFunc['db_free_result']($request);
Chris@76 1127
Chris@76 1128 // Restore the current users language.
Chris@76 1129 $txt = $old_txt;
Chris@76 1130
Chris@76 1131 // Return how many we have.
Chris@76 1132 return $languages;
Chris@76 1133 }
Chris@76 1134
Chris@76 1135 // Edit language related settings.
Chris@76 1136 function ModifyLanguageSettings($return_config = false)
Chris@76 1137 {
Chris@76 1138 global $scripturl, $context, $txt, $boarddir, $settings, $smcFunc;
Chris@76 1139
Chris@76 1140 // Warn the user if the backup of Settings.php failed.
Chris@76 1141 $settings_not_writable = !is_writable($boarddir . '/Settings.php');
Chris@76 1142 $settings_backup_fail = !@is_writable($boarddir . '/Settings_bak.php') || !@copy($boarddir . '/Settings.php', $boarddir . '/Settings_bak.php');
Chris@76 1143
Chris@76 1144 /* If you're writing a mod, it's a bad idea to add things here....
Chris@76 1145 For each option:
Chris@76 1146 variable name, description, type (constant), size/possible values, helptext.
Chris@76 1147 OR an empty string for a horizontal rule.
Chris@76 1148 OR a string for a titled section. */
Chris@76 1149 $config_vars = array(
Chris@76 1150 'language' => array('language', $txt['default_language'], 'file', 'select', array(), null, 'disabled' => $settings_not_writable),
Chris@76 1151 array('userLanguage', $txt['userLanguage'], 'db', 'check', null, 'userLanguage'),
Chris@76 1152 );
Chris@76 1153
Chris@76 1154 if ($return_config)
Chris@76 1155 return $config_vars;
Chris@76 1156
Chris@76 1157 // Get our languages. No cache and use utf8.
Chris@76 1158 getLanguages(false, false);
Chris@76 1159 foreach ($context['languages'] as $lang)
Chris@76 1160 $config_vars['language'][4][$lang['filename']] = array($lang['filename'], strtr($lang['name'], array('-utf8' => ' (UTF-8)')));
Chris@76 1161
Chris@76 1162 // Saving settings?
Chris@76 1163 if (isset($_REQUEST['save']))
Chris@76 1164 {
Chris@76 1165 checkSession();
Chris@76 1166 saveSettings($config_vars);
Chris@76 1167 redirectexit('action=admin;area=languages;sa=settings');
Chris@76 1168 }
Chris@76 1169
Chris@76 1170 // Setup the template stuff.
Chris@76 1171 $context['post_url'] = $scripturl . '?action=admin;area=languages;sa=settings;save';
Chris@76 1172 $context['settings_title'] = $txt['language_settings'];
Chris@76 1173 $context['save_disabled'] = $settings_not_writable;
Chris@76 1174
Chris@76 1175 if ($settings_not_writable)
Chris@76 1176 $context['settings_message'] = '<div class="centertext"><strong>' . $txt['settings_not_writable'] . '</strong></div><br />';
Chris@76 1177 elseif ($settings_backup_fail)
Chris@76 1178 $context['settings_message'] = '<div class="centertext"><strong>' . $txt['admin_backup_fail'] . '</strong></div><br />';
Chris@76 1179
Chris@76 1180 // Fill the config array.
Chris@76 1181 prepareServerSettingsContext($config_vars);
Chris@76 1182 }
Chris@76 1183
Chris@76 1184 // Edit a particular set of language entries.
Chris@76 1185 function ModifyLanguage()
Chris@76 1186 {
Chris@76 1187 global $settings, $context, $smcFunc, $txt, $modSettings, $boarddir, $sourcedir, $language;
Chris@76 1188
Chris@76 1189 loadLanguage('ManageSettings');
Chris@76 1190
Chris@76 1191 // Select the languages tab.
Chris@76 1192 $context['menu_data_' . $context['admin_menu_id']]['current_subsection'] = 'edit';
Chris@76 1193 $context['page_title'] = $txt['edit_languages'];
Chris@76 1194 $context['sub_template'] = 'modify_language_entries';
Chris@76 1195
Chris@76 1196 $context['lang_id'] = $_GET['lid'];
Chris@76 1197 list($theme_id, $file_id) = empty($_REQUEST['tfid']) || strpos($_REQUEST['tfid'], '+') === false ? array(1, '') : explode('+', $_REQUEST['tfid']);
Chris@76 1198
Chris@76 1199 // Clean the ID - just in case.
Chris@76 1200 preg_match('~([A-Za-z0-9_-]+)~', $context['lang_id'], $matches);
Chris@76 1201 $context['lang_id'] = $matches[1];
Chris@76 1202
Chris@76 1203 // Get all the theme data.
Chris@76 1204 $request = $smcFunc['db_query']('', '
Chris@76 1205 SELECT id_theme, variable, value
Chris@76 1206 FROM {db_prefix}themes
Chris@76 1207 WHERE id_theme != {int:default_theme}
Chris@76 1208 AND id_member = {int:no_member}
Chris@76 1209 AND variable IN ({string:name}, {string:theme_dir})',
Chris@76 1210 array(
Chris@76 1211 'default_theme' => 1,
Chris@76 1212 'no_member' => 0,
Chris@76 1213 'name' => 'name',
Chris@76 1214 'theme_dir' => 'theme_dir',
Chris@76 1215 )
Chris@76 1216 );
Chris@76 1217 $themes = array(
Chris@76 1218 1 => array(
Chris@76 1219 'name' => $txt['dvc_default'],
Chris@76 1220 'theme_dir' => $settings['default_theme_dir'],
Chris@76 1221 ),
Chris@76 1222 );
Chris@76 1223 while ($row = $smcFunc['db_fetch_assoc']($request))
Chris@76 1224 $themes[$row['id_theme']][$row['variable']] = $row['value'];
Chris@76 1225 $smcFunc['db_free_result']($request);
Chris@76 1226
Chris@76 1227 // This will be where we look
Chris@76 1228 $lang_dirs = array();
Chris@76 1229 // Check we have themes with a path and a name - just in case - and add the path.
Chris@76 1230 foreach ($themes as $id => $data)
Chris@76 1231 {
Chris@76 1232 if (count($data) != 2)
Chris@76 1233 unset($themes[$id]);
Chris@76 1234 elseif (is_dir($data['theme_dir'] . '/languages'))
Chris@76 1235 $lang_dirs[$id] = $data['theme_dir'] . '/languages';
Chris@76 1236
Chris@76 1237 // How about image directories?
Chris@76 1238 if (is_dir($data['theme_dir'] . '/images/' . $context['lang_id']))
Chris@76 1239 $images_dirs[$id] = $data['theme_dir'] . '/images/' . $context['lang_id'];
Chris@76 1240 }
Chris@76 1241
Chris@76 1242 $current_file = $file_id ? $lang_dirs[$theme_id] . '/' . $file_id . '.' . $context['lang_id'] . '.php' : '';
Chris@76 1243
Chris@76 1244 // Now for every theme get all the files and stick them in context!
Chris@76 1245 $context['possible_files'] = array();
Chris@76 1246 foreach ($lang_dirs as $theme => $theme_dir)
Chris@76 1247 {
Chris@76 1248 // Open it up.
Chris@76 1249 $dir = dir($theme_dir);
Chris@76 1250 while ($entry = $dir->read())
Chris@76 1251 {
Chris@76 1252 // We're only after the files for this language.
Chris@76 1253 if (preg_match('~^([A-Za-z]+)\.' . $context['lang_id'] . '\.php$~', $entry, $matches) == 0)
Chris@76 1254 continue;
Chris@76 1255
Chris@76 1256 //!!! Temp!
Chris@76 1257 if ($matches[1] == 'EmailTemplates')
Chris@76 1258 continue;
Chris@76 1259
Chris@76 1260 if (!isset($context['possible_files'][$theme]))
Chris@76 1261 $context['possible_files'][$theme] = array(
Chris@76 1262 'id' => $theme,
Chris@76 1263 'name' => $themes[$theme]['name'],
Chris@76 1264 'files' => array(),
Chris@76 1265 );
Chris@76 1266
Chris@76 1267 $context['possible_files'][$theme]['files'][] = array(
Chris@76 1268 'id' => $matches[1],
Chris@76 1269 'name' => isset($txt['lang_file_desc_' . $matches[1]]) ? $txt['lang_file_desc_' . $matches[1]] : $matches[1],
Chris@76 1270 'selected' => $theme_id == $theme && $file_id == $matches[1],
Chris@76 1271 );
Chris@76 1272 }
Chris@76 1273 $dir->close();
Chris@76 1274 }
Chris@76 1275
Chris@76 1276 // We no longer wish to speak this language.
Chris@76 1277 if (!empty($_POST['delete_main']) && $context['lang_id'] != 'english')
Chris@76 1278 {
Chris@76 1279 checkSession();
Chris@76 1280
Chris@76 1281 // !!! Todo: FTP Controls?
Chris@76 1282 require_once($sourcedir . '/Subs-Package.php');
Chris@76 1283
Chris@76 1284 // First, Make a backup?
Chris@76 1285 if (!empty($modSettings['package_make_backups']) && (!isset($_SESSION['last_backup_for']) || $_SESSION['last_backup_for'] != $context['lang_id'] . '$$$'))
Chris@76 1286 {
Chris@76 1287 $_SESSION['last_backup_for'] = $context['lang_id'] . '$$$';
Chris@76 1288 package_create_backup('backup_lang_' . $context['lang_id']);
Chris@76 1289 }
Chris@76 1290
Chris@76 1291 // Second, loop through the array to remove the files.
Chris@76 1292 foreach ($lang_dirs as $curPath)
Chris@76 1293 {
Chris@76 1294 foreach ($context['possible_files'][1]['files'] as $lang)
Chris@76 1295 if (file_exists($curPath . '/' . $lang['id'] . '.' . $context['lang_id'] . '.php'))
Chris@76 1296 unlink($curPath . '/' . $lang['id'] . '.' . $context['lang_id'] . '.php');
Chris@76 1297
Chris@76 1298 // Check for the email template.
Chris@76 1299 if (file_exists($curPath . '/EmailTemplates.' . $context['lang_id'] . '.php'))
Chris@76 1300 unlink($curPath . '/EmailTemplates.' . $context['lang_id'] . '.php');
Chris@76 1301 }
Chris@76 1302
Chris@76 1303 // Third, the agreement file.
Chris@76 1304 if (file_exists($boarddir . '/agreement.' . $context['lang_id'] . '.txt'))
Chris@76 1305 unlink($boarddir . '/agreement.' . $context['lang_id'] . '.txt');
Chris@76 1306
Chris@76 1307 // Fourth, a related images folder?
Chris@76 1308 foreach ($images_dirs as $curPath)
Chris@76 1309 if (is_dir($curPath))
Chris@76 1310 deltree($curPath);
Chris@76 1311
Chris@76 1312 // Members can no longer use this language.
Chris@76 1313 $smcFunc['db_query']('', '
Chris@76 1314 UPDATE {db_prefix}members
Chris@76 1315 SET lngfile = {string:empty_string}
Chris@76 1316 WHERE lngfile = {string:current_language}',
Chris@76 1317 array(
Chris@76 1318 'empty_string' => '',
Chris@76 1319 'current_language' => $context['lang_id'],
Chris@76 1320 )
Chris@76 1321 );
Chris@76 1322
Chris@76 1323 // Fifth, update getLanguages() cache.
Chris@76 1324 if (!empty($modSettings['cache_enable']))
Chris@76 1325 {
Chris@76 1326 cache_put_data('known_languages', null, !empty($modSettings['cache_enable']) && $modSettings['cache_enable'] < 1 ? 86400 : 3600);
Chris@76 1327 cache_put_data('known_languages_all', null, !empty($modSettings['cache_enable']) && $modSettings['cache_enable'] < 1 ? 86400 : 3600);
Chris@76 1328 }
Chris@76 1329
Chris@76 1330 // Sixth, if we deleted the default language, set us back to english?
Chris@76 1331 if ($context['lang_id'] == $language)
Chris@76 1332 {
Chris@76 1333 require_once($sourcedir . '/Subs-Admin.php');
Chris@76 1334 $language = 'english';
Chris@76 1335 updateSettingsFile(array('language' => '\'' . $language . '\''));
Chris@76 1336 }
Chris@76 1337
Chris@76 1338 // Seventh, get out of here.
Chris@76 1339 redirectexit('action=admin;area=languages;sa=edit;' . $context['session_var'] . '=' . $context['session_id']);
Chris@76 1340 }
Chris@76 1341
Chris@76 1342 // Saving primary settings?
Chris@76 1343 $madeSave = false;
Chris@76 1344 if (!empty($_POST['save_main']) && !$current_file)
Chris@76 1345 {
Chris@76 1346 checkSession();
Chris@76 1347
Chris@76 1348 // Read in the current file.
Chris@76 1349 $current_data = implode('', file($settings['default_theme_dir'] . '/languages/index.' . $context['lang_id'] . '.php'));
Chris@76 1350 // These are the replacements. old => new
Chris@76 1351 $replace_array = array(
Chris@76 1352 '~\$txt\[\'lang_character_set\'\]\s=\s(\'|")[^\r\n]+~' => '$txt[\'lang_character_set\'] = \'' . addslashes($_POST['character_set']) . '\';',
Chris@76 1353 '~\$txt\[\'lang_locale\'\]\s=\s(\'|")[^\r\n]+~' => '$txt[\'lang_locale\'] = \'' . addslashes($_POST['locale']) . '\';',
Chris@76 1354 '~\$txt\[\'lang_dictionary\'\]\s=\s(\'|")[^\r\n]+~' => '$txt[\'lang_dictionary\'] = \'' . addslashes($_POST['dictionary']) . '\';',
Chris@76 1355 '~\$txt\[\'lang_spelling\'\]\s=\s(\'|")[^\r\n]+~' => '$txt[\'lang_spelling\'] = \'' . addslashes($_POST['spelling']) . '\';',
Chris@76 1356 '~\$txt\[\'lang_rtl\'\]\s=\s[A-Za-z0-9]+;~' => '$txt[\'lang_rtl\'] = ' . (!empty($_POST['rtl']) ? 'true' : 'false') . ';',
Chris@76 1357 );
Chris@76 1358 $current_data = preg_replace(array_keys($replace_array), array_values($replace_array), $current_data);
Chris@76 1359 $fp = fopen($settings['default_theme_dir'] . '/languages/index.' . $context['lang_id'] . '.php', 'w+');
Chris@76 1360 fwrite($fp, $current_data);
Chris@76 1361 fclose($fp);
Chris@76 1362
Chris@76 1363 $madeSave = true;
Chris@76 1364 }
Chris@76 1365
Chris@76 1366 // Quickly load index language entries.
Chris@76 1367 $old_txt = $txt;
Chris@76 1368 require($settings['default_theme_dir'] . '/languages/index.' . $context['lang_id'] . '.php');
Chris@76 1369 $context['lang_file_not_writable_message'] = is_writable($settings['default_theme_dir'] . '/languages/index.' . $context['lang_id'] . '.php') ? '' : sprintf($txt['lang_file_not_writable'], $settings['default_theme_dir'] . '/languages/index.' . $context['lang_id'] . '.php');
Chris@76 1370 // Setup the primary settings context.
Chris@76 1371 $context['primary_settings'] = array(
Chris@76 1372 'name' => $smcFunc['ucwords'](strtr($context['lang_id'], array('_' => ' ', '-utf8' => ''))),
Chris@76 1373 'character_set' => $txt['lang_character_set'],
Chris@76 1374 'locale' => $txt['lang_locale'],
Chris@76 1375 'dictionary' => $txt['lang_dictionary'],
Chris@76 1376 'spelling' => $txt['lang_spelling'],
Chris@76 1377 'rtl' => $txt['lang_rtl'],
Chris@76 1378 );
Chris@76 1379
Chris@76 1380 // Restore normal service.
Chris@76 1381 $txt = $old_txt;
Chris@76 1382
Chris@76 1383 // Are we saving?
Chris@76 1384 $save_strings = array();
Chris@76 1385 if (isset($_POST['save_entries']) && !empty($_POST['entry']))
Chris@76 1386 {
Chris@76 1387 checkSession();
Chris@76 1388
Chris@76 1389 // Clean each entry!
Chris@76 1390 foreach ($_POST['entry'] as $k => $v)
Chris@76 1391 {
Chris@76 1392 // Only try to save if it's changed!
Chris@76 1393 if ($_POST['entry'][$k] != $_POST['comp'][$k])
Chris@76 1394 $save_strings[$k] = cleanLangString($v, false);
Chris@76 1395 }
Chris@76 1396 }
Chris@76 1397
Chris@76 1398 // If we are editing a file work away at that.
Chris@76 1399 if ($current_file)
Chris@76 1400 {
Chris@76 1401 $context['entries_not_writable_message'] = is_writable($current_file) ? '' : sprintf($txt['lang_entries_not_writable'], $current_file);
Chris@76 1402
Chris@76 1403 $entries = array();
Chris@76 1404 // We can't just require it I'm afraid - otherwise we pass in all kinds of variables!
Chris@76 1405 $multiline_cache = '';
Chris@76 1406 foreach (file($current_file) as $line)
Chris@76 1407 {
Chris@76 1408 // Got a new entry?
Chris@76 1409 if ($line[0] == '$' && !empty($multiline_cache))
Chris@76 1410 {
Chris@76 1411 preg_match('~\$(helptxt|txt)\[\'(.+)\'\]\s=\s(.+);~', strtr($multiline_cache, array("\n" => '', "\t" => '')), $matches);
Chris@76 1412 if (!empty($matches[3]))
Chris@76 1413 {
Chris@76 1414 $entries[$matches[2]] = array(
Chris@76 1415 'type' => $matches[1],
Chris@76 1416 'full' => $matches[0],
Chris@76 1417 'entry' => $matches[3],
Chris@76 1418 );
Chris@76 1419 $multiline_cache = '';
Chris@76 1420 }
Chris@76 1421 }
Chris@76 1422 $multiline_cache .= $line . "\n";
Chris@76 1423 }
Chris@76 1424 // Last entry to add?
Chris@76 1425 if ($multiline_cache)
Chris@76 1426 {
Chris@76 1427 preg_match('~\$(helptxt|txt)\[\'(.+)\'\]\s=\s(.+);~', strtr($multiline_cache, array("\n" => '', "\t" => '')), $matches);
Chris@76 1428 if (!empty($matches[3]))
Chris@76 1429 $entries[$matches[2]] = array(
Chris@76 1430 'type' => $matches[1],
Chris@76 1431 'full' => $matches[0],
Chris@76 1432 'entry' => $matches[3],
Chris@76 1433 );
Chris@76 1434 }
Chris@76 1435
Chris@76 1436 // These are the entries we can definitely save.
Chris@76 1437 $final_saves = array();
Chris@76 1438
Chris@76 1439 $context['file_entries'] = array();
Chris@76 1440 foreach ($entries as $entryKey => $entryValue)
Chris@76 1441 {
Chris@76 1442 // Ignore some things we set separately.
Chris@76 1443 $ignore_files = array('lang_character_set', 'lang_locale', 'lang_dictionary', 'lang_spelling', 'lang_rtl');
Chris@76 1444 if (in_array($entryKey, $ignore_files))
Chris@76 1445 continue;
Chris@76 1446
Chris@76 1447 // These are arrays that need breaking out.
Chris@76 1448 $arrays = array('days', 'days_short', 'months', 'months_titles', 'months_short');
Chris@76 1449 if (in_array($entryKey, $arrays))
Chris@76 1450 {
Chris@76 1451 // Get off the first bits.
Chris@76 1452 $entryValue['entry'] = substr($entryValue['entry'], strpos($entryValue['entry'], '(') + 1, strrpos($entryValue['entry'], ')') - strpos($entryValue['entry'], '('));
Chris@76 1453 $entryValue['entry'] = explode(',', strtr($entryValue['entry'], array(' ' => '')));
Chris@76 1454
Chris@76 1455 // Now create an entry for each item.
Chris@76 1456 $cur_index = 0;
Chris@76 1457 $save_cache = array(
Chris@76 1458 'enabled' => false,
Chris@76 1459 'entries' => array(),
Chris@76 1460 );
Chris@76 1461 foreach ($entryValue['entry'] as $id => $subValue)
Chris@76 1462 {
Chris@76 1463 // Is this a new index?
Chris@76 1464 if (preg_match('~^(\d+)~', $subValue, $matches))
Chris@76 1465 {
Chris@76 1466 $cur_index = $matches[1];
Chris@76 1467 $subValue = substr($subValue, strpos($subValue, '\''));
Chris@76 1468 }
Chris@76 1469
Chris@76 1470 // Clean up some bits.
Chris@76 1471 $subValue = strtr($subValue, array('"' => '', '\'' => '', ')' => ''));
Chris@76 1472
Chris@76 1473 // Can we save?
Chris@76 1474 if (isset($save_strings[$entryKey . '-+- ' . $cur_index]))
Chris@76 1475 {
Chris@76 1476 $save_cache['entries'][$cur_index] = strtr($save_strings[$entryKey . '-+- ' . $cur_index], array('\'' => ''));
Chris@76 1477 $save_cache['enabled'] = true;
Chris@76 1478 }
Chris@76 1479 else
Chris@76 1480 $save_cache['entries'][$cur_index] = $subValue;
Chris@76 1481
Chris@76 1482 $context['file_entries'][] = array(
Chris@76 1483 'key' => $entryKey . '-+- ' . $cur_index,
Chris@76 1484 'value' => $subValue,
Chris@76 1485 'rows' => 1,
Chris@76 1486 );
Chris@76 1487 $cur_index++;
Chris@76 1488 }
Chris@76 1489
Chris@76 1490 // Do we need to save?
Chris@76 1491 if ($save_cache['enabled'])
Chris@76 1492 {
Chris@76 1493 // Format the string, checking the indexes first.
Chris@76 1494 $items = array();
Chris@76 1495 $cur_index = 0;
Chris@76 1496 foreach ($save_cache['entries'] as $k2 => $v2)
Chris@76 1497 {
Chris@76 1498 // Manually show the custom index.
Chris@76 1499 if ($k2 != $cur_index)
Chris@76 1500 {
Chris@76 1501 $items[] = $k2 . ' => \'' . $v2 . '\'';
Chris@76 1502 $cur_index = $k2;
Chris@76 1503 }
Chris@76 1504 else
Chris@76 1505 $items[] = '\'' . $v2 . '\'';
Chris@76 1506
Chris@76 1507 $cur_index++;
Chris@76 1508 }
Chris@76 1509 // Now create the string!
Chris@76 1510 $final_saves[$entryKey] = array(
Chris@76 1511 'find' => $entryValue['full'],
Chris@76 1512 'replace' => '$' . $entryValue['type'] . '[\'' . $entryKey . '\'] = array(' . implode(', ', $items) . ');',
Chris@76 1513 );
Chris@76 1514 }
Chris@76 1515 }
Chris@76 1516 else
Chris@76 1517 {
Chris@76 1518 // Saving?
Chris@76 1519 if (isset($save_strings[$entryKey]) && $save_strings[$entryKey] != $entryValue['entry'])
Chris@76 1520 {
Chris@76 1521 // !!! Fix this properly.
Chris@76 1522 if ($save_strings[$entryKey] == '')
Chris@76 1523 $save_strings[$entryKey] = '\'\'';
Chris@76 1524
Chris@76 1525 // Set the new value.
Chris@76 1526 $entryValue['entry'] = $save_strings[$entryKey];
Chris@76 1527 // And we know what to save now!
Chris@76 1528 $final_saves[$entryKey] = array(
Chris@76 1529 'find' => $entryValue['full'],
Chris@76 1530 'replace' => '$' . $entryValue['type'] . '[\'' . $entryKey . '\'] = ' . $save_strings[$entryKey] . ';',
Chris@76 1531 );
Chris@76 1532 }
Chris@76 1533
Chris@76 1534 $editing_string = cleanLangString($entryValue['entry'], true);
Chris@76 1535 $context['file_entries'][] = array(
Chris@76 1536 'key' => $entryKey,
Chris@76 1537 'value' => $editing_string,
Chris@76 1538 'rows' => (int) (strlen($editing_string) / 38) + substr_count($editing_string, "\n") + 1,
Chris@76 1539 );
Chris@76 1540 }
Chris@76 1541 }
Chris@76 1542
Chris@76 1543 // Any saves to make?
Chris@76 1544 if (!empty($final_saves))
Chris@76 1545 {
Chris@76 1546 checkSession();
Chris@76 1547
Chris@76 1548 $file_contents = implode('', file($current_file));
Chris@76 1549 foreach ($final_saves as $save)
Chris@76 1550 $file_contents = strtr($file_contents, array($save['find'] => $save['replace']));
Chris@76 1551
Chris@76 1552 // Save the actual changes.
Chris@76 1553 $fp = fopen($current_file, 'w+');
Chris@76 1554 fwrite($fp, $file_contents);
Chris@76 1555 fclose($fp);
Chris@76 1556
Chris@76 1557 $madeSave = true;
Chris@76 1558 }
Chris@76 1559
Chris@76 1560 // Another restore.
Chris@76 1561 $txt = $old_txt;
Chris@76 1562 }
Chris@76 1563
Chris@76 1564 // If we saved, redirect.
Chris@76 1565 if ($madeSave)
Chris@76 1566 redirectexit('action=admin;area=languages;sa=editlang;lid=' . $context['lang_id']);
Chris@76 1567 }
Chris@76 1568
Chris@76 1569 // This function could be two functions - either way it cleans language entries to/from display.
Chris@76 1570 function cleanLangString($string, $to_display = true)
Chris@76 1571 {
Chris@76 1572 global $smcFunc;
Chris@76 1573
Chris@76 1574 // If going to display we make sure it doesn't have any HTML in it - etc.
Chris@76 1575 $new_string = '';
Chris@76 1576 if ($to_display)
Chris@76 1577 {
Chris@76 1578 // Are we in a string (0 = no, 1 = single quote, 2 = parsed)
Chris@76 1579 $in_string = 0;
Chris@76 1580 $is_escape = false;
Chris@76 1581 for ($i = 0; $i < strlen($string); $i++)
Chris@76 1582 {
Chris@76 1583 // Handle ecapes first.
Chris@76 1584 if ($string{$i} == '\\')
Chris@76 1585 {
Chris@76 1586 // Toggle the escape.
Chris@76 1587 $is_escape = !$is_escape;
Chris@76 1588 // If we're now escaped don't add this string.
Chris@76 1589 if ($is_escape)
Chris@76 1590 continue;
Chris@76 1591 }
Chris@76 1592 // Special case - parsed string with line break etc?
Chris@76 1593 elseif (($string{$i} == 'n' || $string{$i} == 't') && $in_string == 2 && $is_escape)
Chris@76 1594 {
Chris@76 1595 // Put the escape back...
Chris@76 1596 $new_string .= $string{$i} == 'n' ? "\n" : "\t";
Chris@76 1597 $is_escape = false;
Chris@76 1598 continue;
Chris@76 1599 }
Chris@76 1600 // Have we got a single quote?
Chris@76 1601 elseif ($string{$i} == '\'')
Chris@76 1602 {
Chris@76 1603 // Already in a parsed string, or escaped in a linear string, means we print it - otherwise something special.
Chris@76 1604 if ($in_string != 2 && ($in_string != 1 || !$is_escape))
Chris@76 1605 {
Chris@76 1606 // Is it the end of a single quote string?
Chris@76 1607 if ($in_string == 1)
Chris@76 1608 $in_string = 0;
Chris@76 1609 // Otherwise it's the start!
Chris@76 1610 else
Chris@76 1611 $in_string = 1;
Chris@76 1612
Chris@76 1613 // Don't actually include this character!
Chris@76 1614 continue;
Chris@76 1615 }
Chris@76 1616 }
Chris@76 1617 // Otherwise a double quote?
Chris@76 1618 elseif ($string{$i} == '"')
Chris@76 1619 {
Chris@76 1620 // Already in a single quote string, or escaped in a parsed string, means we print it - otherwise something special.
Chris@76 1621 if ($in_string != 1 && ($in_string != 2 || !$is_escape))
Chris@76 1622 {
Chris@76 1623 // Is it the end of a double quote string?
Chris@76 1624 if ($in_string == 2)
Chris@76 1625 $in_string = 0;
Chris@76 1626 // Otherwise it's the start!
Chris@76 1627 else
Chris@76 1628 $in_string = 2;
Chris@76 1629
Chris@76 1630 // Don't actually include this character!
Chris@76 1631 continue;
Chris@76 1632 }
Chris@76 1633 }
Chris@76 1634 // A join/space outside of a string is simply removed.
Chris@76 1635 elseif ($in_string == 0 && (empty($string{$i}) || $string{$i} == '.'))
Chris@76 1636 continue;
Chris@76 1637 // Start of a variable?
Chris@76 1638 elseif ($in_string == 0 && $string{$i} == '$')
Chris@76 1639 {
Chris@76 1640 // Find the whole of it!
Chris@76 1641 preg_match('~([\$A-Za-z0-9\'\[\]_-]+)~', substr($string, $i), $matches);
Chris@76 1642 if (!empty($matches[1]))
Chris@76 1643 {
Chris@76 1644 // Come up with some pseudo thing to indicate this is a var.
Chris@76 1645 //!!! Do better than this, please!
Chris@76 1646 $new_string .= '{%' . $matches[1] . '%}';
Chris@76 1647
Chris@76 1648 // We're not going to reparse this.
Chris@76 1649 $i += strlen($matches[1]) - 1;
Chris@76 1650 }
Chris@76 1651
Chris@76 1652 continue;
Chris@76 1653 }
Chris@76 1654 // Right, if we're outside of a string we have DANGER, DANGER!
Chris@76 1655 elseif ($in_string == 0)
Chris@76 1656 {
Chris@76 1657 continue;
Chris@76 1658 }
Chris@76 1659
Chris@76 1660 // Actually add the character to the string!
Chris@76 1661 $new_string .= $string{$i};
Chris@76 1662 // If anything was escaped it ain't any longer!
Chris@76 1663 $is_escape = false;
Chris@76 1664 }
Chris@76 1665
Chris@76 1666 // Unhtml then rehtml the whole thing!
Chris@76 1667 $new_string = htmlspecialchars(un_htmlspecialchars($new_string));
Chris@76 1668 }
Chris@76 1669 else
Chris@76 1670 {
Chris@76 1671 // Keep track of what we're doing...
Chris@76 1672 $in_string = 0;
Chris@76 1673 // This is for deciding whether to HTML a quote.
Chris@76 1674 $in_html = false;
Chris@76 1675 for ($i = 0; $i < strlen($string); $i++)
Chris@76 1676 {
Chris@76 1677 // Handle line breaks!
Chris@76 1678 if ($string{$i} == "\n" || $string{$i} == "\t")
Chris@76 1679 {
Chris@76 1680 // Are we in a string? Is it the right type?
Chris@76 1681 if ($in_string == 1)
Chris@76 1682 {
Chris@76 1683 // Change type!
Chris@76 1684 $new_string .= '\' . "\\' . ($string{$i} == "\n" ? 'n' : 't');
Chris@76 1685 $in_string = 2;
Chris@76 1686 }
Chris@76 1687 elseif ($in_string == 2)
Chris@76 1688 $new_string .= '\\' . ($string{$i} == "\n" ? 'n' : 't');
Chris@76 1689 // Otherwise start one off - joining if required.
Chris@76 1690 else
Chris@76 1691 $new_string .= ($new_string ? ' . ' : '') . '"\\' . ($string{$i} == "\n" ? 'n' : 't');
Chris@76 1692
Chris@76 1693 continue;
Chris@76 1694 }
Chris@76 1695 // We don't do parsed strings apart from for breaks.
Chris@76 1696 elseif ($in_string == 2)
Chris@76 1697 {
Chris@76 1698 $in_string = 0;
Chris@76 1699 $new_string .= '"';
Chris@76 1700 }
Chris@76 1701
Chris@76 1702 // Not in a string yet?
Chris@76 1703 if ($in_string != 1)
Chris@76 1704 {
Chris@76 1705 $in_string = 1;
Chris@76 1706 $new_string .= ($new_string ? ' . ' : '') . '\'';
Chris@76 1707 }
Chris@76 1708
Chris@76 1709 // Is this a variable?
Chris@76 1710 if ($string{$i} == '{' && $string{$i + 1} == '%' && $string{$i + 2} == '$')
Chris@76 1711 {
Chris@76 1712 // Grab the variable.
Chris@76 1713 preg_match('~\{%([\$A-Za-z0-9\'\[\]_-]+)%\}~', substr($string, $i), $matches);
Chris@76 1714 if (!empty($matches[1]))
Chris@76 1715 {
Chris@76 1716 if ($in_string == 1)
Chris@76 1717 $new_string .= '\' . ';
Chris@76 1718 elseif ($new_string)
Chris@76 1719 $new_string .= ' . ';
Chris@76 1720
Chris@76 1721 $new_string .= $matches[1];
Chris@76 1722 $i += strlen($matches[1]) + 3;
Chris@76 1723 $in_string = 0;
Chris@76 1724 }
Chris@76 1725
Chris@76 1726 continue;
Chris@76 1727 }
Chris@76 1728 // Is this a lt sign?
Chris@76 1729 elseif ($string{$i} == '<')
Chris@76 1730 {
Chris@76 1731 // Probably HTML?
Chris@76 1732 if ($string{$i + 1} != ' ')
Chris@76 1733 $in_html = true;
Chris@76 1734 // Assume we need an entity...
Chris@76 1735 else
Chris@76 1736 {
Chris@76 1737 $new_string .= '&lt;';
Chris@76 1738 continue;
Chris@76 1739 }
Chris@76 1740 }
Chris@76 1741 // What about gt?
Chris@76 1742 elseif ($string{$i} == '>')
Chris@76 1743 {
Chris@76 1744 // Will it be HTML?
Chris@76 1745 if ($in_html)
Chris@76 1746 $in_html = false;
Chris@76 1747 // Otherwise we need an entity...
Chris@76 1748 else
Chris@76 1749 {
Chris@76 1750 $new_string .= '&gt;';
Chris@76 1751 continue;
Chris@76 1752 }
Chris@76 1753 }
Chris@76 1754 // Is it a slash? If so escape it...
Chris@76 1755 if ($string{$i} == '\\')
Chris@76 1756 $new_string .= '\\';
Chris@76 1757 // The infamous double quote?
Chris@76 1758 elseif ($string{$i} == '"')
Chris@76 1759 {
Chris@76 1760 // If we're in HTML we leave it as a quote - otherwise we entity it.
Chris@76 1761 if (!$in_html)
Chris@76 1762 {
Chris@76 1763 $new_string .= '&quot;';
Chris@76 1764 continue;
Chris@76 1765 }
Chris@76 1766 }
Chris@76 1767 // A single quote?
Chris@76 1768 elseif ($string{$i} == '\'')
Chris@76 1769 {
Chris@76 1770 // Must be in a string so escape it.
Chris@76 1771 $new_string .= '\\';
Chris@76 1772 }
Chris@76 1773
Chris@76 1774 // Finally add the character to the string!
Chris@76 1775 $new_string .= $string{$i};
Chris@76 1776 }
Chris@76 1777
Chris@76 1778 // If we ended as a string then close it off.
Chris@76 1779 if ($in_string == 1)
Chris@76 1780 $new_string .= '\'';
Chris@76 1781 elseif ($in_string == 2)
Chris@76 1782 $new_string .= '"';
Chris@76 1783 }
Chris@76 1784
Chris@76 1785 return $new_string;
Chris@76 1786 }
Chris@76 1787
Chris@76 1788 // Helper function, it sets up the context for the manage server settings.
Chris@76 1789 function prepareServerSettingsContext(&$config_vars)
Chris@76 1790 {
Chris@76 1791 global $context, $modSettings;
Chris@76 1792
Chris@76 1793 $context['config_vars'] = array();
Chris@76 1794 foreach ($config_vars as $identifier => $config_var)
Chris@76 1795 {
Chris@76 1796 if (!is_array($config_var) || !isset($config_var[1]))
Chris@76 1797 $context['config_vars'][] = $config_var;
Chris@76 1798 else
Chris@76 1799 {
Chris@76 1800 $varname = $config_var[0];
Chris@76 1801 global $$varname;
Chris@76 1802
Chris@76 1803 $context['config_vars'][] = array(
Chris@76 1804 'label' => $config_var[1],
Chris@76 1805 'help' => isset($config_var[5]) ? $config_var[5] : '',
Chris@76 1806 'type' => $config_var[3],
Chris@76 1807 'size' => empty($config_var[4]) ? 0 : $config_var[4],
Chris@76 1808 'data' => isset($config_var[4]) && is_array($config_var[4]) ? $config_var[4] : array(),
Chris@76 1809 'name' => $config_var[0],
Chris@76 1810 'value' => $config_var[2] == 'file' ? htmlspecialchars($$varname) : (isset($modSettings[$config_var[0]]) ? htmlspecialchars($modSettings[$config_var[0]]) : (in_array($config_var[3], array('int', 'float')) ? 0 : '')),
Chris@76 1811 'disabled' => !empty($context['settings_not_writable']) || !empty($config_var['disabled']),
Chris@76 1812 'invalid' => false,
Chris@76 1813 'javascript' => '',
Chris@76 1814 'preinput' => '',
Chris@76 1815 'postinput' => '',
Chris@76 1816 );
Chris@76 1817 }
Chris@76 1818 }
Chris@76 1819 }
Chris@76 1820
Chris@76 1821 // Helper function, it sets up the context for database settings.
Chris@76 1822 function prepareDBSettingContext(&$config_vars)
Chris@76 1823 {
Chris@76 1824 global $txt, $helptxt, $context, $modSettings, $sourcedir;
Chris@76 1825
Chris@76 1826 loadLanguage('Help');
Chris@76 1827
Chris@76 1828 $context['config_vars'] = array();
Chris@76 1829 $inlinePermissions = array();
Chris@76 1830 $bbcChoice = array();
Chris@76 1831 foreach ($config_vars as $config_var)
Chris@76 1832 {
Chris@76 1833 // HR?
Chris@76 1834 if (!is_array($config_var))
Chris@76 1835 $context['config_vars'][] = $config_var;
Chris@76 1836 else
Chris@76 1837 {
Chris@76 1838 // If it has no name it doesn't have any purpose!
Chris@76 1839 if (empty($config_var[1]))
Chris@76 1840 continue;
Chris@76 1841
Chris@76 1842 // Special case for inline permissions
Chris@76 1843 if ($config_var[0] == 'permissions' && allowedTo('manage_permissions'))
Chris@76 1844 $inlinePermissions[] = $config_var[1];
Chris@76 1845 elseif ($config_var[0] == 'permissions')
Chris@76 1846 continue;
Chris@76 1847
Chris@76 1848 // Are we showing the BBC selection box?
Chris@76 1849 if ($config_var[0] == 'bbc')
Chris@76 1850 $bbcChoice[] = $config_var[1];
Chris@76 1851
Chris@76 1852 $context['config_vars'][$config_var[1]] = array(
Chris@76 1853 'label' => isset($config_var['text_label']) ? $config_var['text_label'] : (isset($txt[$config_var[1]]) ? $txt[$config_var[1]] : (isset($config_var[3]) && !is_array($config_var[3]) ? $config_var[3] : '')),
Chris@76 1854 'help' => isset($helptxt[$config_var[1]]) ? $config_var[1] : '',
Chris@76 1855 'type' => $config_var[0],
Chris@76 1856 'size' => !empty($config_var[2]) && !is_array($config_var[2]) ? $config_var[2] : (in_array($config_var[0], array('int', 'float')) ? 6 : 0),
Chris@76 1857 'data' => array(),
Chris@76 1858 'name' => $config_var[1],
Chris@76 1859 'value' => isset($modSettings[$config_var[1]]) ? ($config_var[0] == 'select' ? $modSettings[$config_var[1]] : htmlspecialchars($modSettings[$config_var[1]])) : (in_array($config_var[0], array('int', 'float')) ? 0 : ''),
Chris@76 1860 'disabled' => false,
Chris@76 1861 'invalid' => !empty($config_var['invalid']),
Chris@76 1862 'javascript' => '',
Chris@76 1863 'var_message' => !empty($config_var['message']) && isset($txt[$config_var['message']]) ? $txt[$config_var['message']] : '',
Chris@76 1864 'preinput' => isset($config_var['preinput']) ? $config_var['preinput'] : '',
Chris@76 1865 'postinput' => isset($config_var['postinput']) ? $config_var['postinput'] : '',
Chris@76 1866 );
Chris@76 1867
Chris@76 1868 // If this is a select box handle any data.
Chris@76 1869 if (!empty($config_var[2]) && is_array($config_var[2]))
Chris@76 1870 {
Chris@76 1871 // If we allow multiple selections, we need to adjust a few things.
Chris@76 1872 if ($config_var[0] == 'select' && !empty($config_var['multiple']))
Chris@76 1873 {
Chris@76 1874 $context['config_vars'][$config_var[1]]['name'] .= '[]';
Chris@76 1875 $context['config_vars'][$config_var[1]]['value'] = unserialize($context['config_vars'][$config_var[1]]['value']);
Chris@76 1876 }
Chris@76 1877
Chris@76 1878 // If it's associative
Chris@76 1879 if (isset($config_var[2][0]) && is_array($config_var[2][0]))
Chris@76 1880 $context['config_vars'][$config_var[1]]['data'] = $config_var[2];
Chris@76 1881 else
Chris@76 1882 {
Chris@76 1883 foreach ($config_var[2] as $key => $item)
Chris@76 1884 $context['config_vars'][$config_var[1]]['data'][] = array($key, $item);
Chris@76 1885 }
Chris@76 1886 }
Chris@76 1887
Chris@76 1888 // Finally allow overrides - and some final cleanups.
Chris@76 1889 foreach ($config_var as $k => $v)
Chris@76 1890 {
Chris@76 1891 if (!is_numeric($k))
Chris@76 1892 {
Chris@76 1893 if (substr($k, 0, 2) == 'on')
Chris@76 1894 $context['config_vars'][$config_var[1]]['javascript'] .= ' ' . $k . '="' . $v . '"';
Chris@76 1895 else
Chris@76 1896 $context['config_vars'][$config_var[1]][$k] = $v;
Chris@76 1897 }
Chris@76 1898
Chris@76 1899 // See if there are any other labels that might fit?
Chris@76 1900 if (isset($txt['setting_' . $config_var[1]]))
Chris@76 1901 $context['config_vars'][$config_var[1]]['label'] = $txt['setting_' . $config_var[1]];
Chris@76 1902 elseif (isset($txt['groups_' . $config_var[1]]))
Chris@76 1903 $context['config_vars'][$config_var[1]]['label'] = $txt['groups_' . $config_var[1]];
Chris@76 1904 }
Chris@76 1905
Chris@76 1906 // Set the subtext in case it's part of the label.
Chris@76 1907 // !!! Temporary. Preventing divs inside label tags.
Chris@76 1908 $divPos = strpos($context['config_vars'][$config_var[1]]['label'], '<div');
Chris@76 1909 if ($divPos !== false)
Chris@76 1910 {
Chris@76 1911 $context['config_vars'][$config_var[1]]['subtext'] = preg_replace('~</?div[^>]*>~', '', substr($context['config_vars'][$config_var[1]]['label'], $divPos));
Chris@76 1912 $context['config_vars'][$config_var[1]]['label'] = substr($context['config_vars'][$config_var[1]]['label'], 0, $divPos);
Chris@76 1913 }
Chris@76 1914 }
Chris@76 1915 }
Chris@76 1916
Chris@76 1917 // If we have inline permissions we need to prep them.
Chris@76 1918 if (!empty($inlinePermissions) && allowedTo('manage_permissions'))
Chris@76 1919 {
Chris@76 1920 require_once($sourcedir . '/ManagePermissions.php');
Chris@76 1921 init_inline_permissions($inlinePermissions, isset($context['permissions_excluded']) ? $context['permissions_excluded'] : array());
Chris@76 1922 }
Chris@76 1923
Chris@76 1924 // What about any BBC selection boxes?
Chris@76 1925 if (!empty($bbcChoice))
Chris@76 1926 {
Chris@76 1927 // What are the options, eh?
Chris@76 1928 $temp = parse_bbc(false);
Chris@76 1929 $bbcTags = array();
Chris@76 1930 foreach ($temp as $tag)
Chris@76 1931 $bbcTags[] = $tag['tag'];
Chris@76 1932
Chris@76 1933 $bbcTags = array_unique($bbcTags);
Chris@76 1934 $totalTags = count($bbcTags);
Chris@76 1935
Chris@76 1936 // The number of columns we want to show the BBC tags in.
Chris@76 1937 $numColumns = isset($context['num_bbc_columns']) ? $context['num_bbc_columns'] : 3;
Chris@76 1938
Chris@76 1939 // Start working out the context stuff.
Chris@76 1940 $context['bbc_columns'] = array();
Chris@76 1941 $tagsPerColumn = ceil($totalTags / $numColumns);
Chris@76 1942
Chris@76 1943 $col = 0; $i = 0;
Chris@76 1944 foreach ($bbcTags as $tag)
Chris@76 1945 {
Chris@76 1946 if ($i % $tagsPerColumn == 0 && $i != 0)
Chris@76 1947 $col++;
Chris@76 1948
Chris@76 1949 $context['bbc_columns'][$col][] = array(
Chris@76 1950 'tag' => $tag,
Chris@76 1951 // !!! 'tag_' . ?
Chris@76 1952 'show_help' => isset($helptxt[$tag]),
Chris@76 1953 );
Chris@76 1954
Chris@76 1955 $i++;
Chris@76 1956 }
Chris@76 1957
Chris@76 1958 // Now put whatever BBC options we may have into context too!
Chris@76 1959 $context['bbc_sections'] = array();
Chris@76 1960 foreach ($bbcChoice as $bbc)
Chris@76 1961 {
Chris@76 1962 $context['bbc_sections'][$bbc] = array(
Chris@76 1963 'title' => isset($txt['bbc_title_' . $bbc]) ? $txt['bbc_title_' . $bbc] : $txt['bbcTagsToUse_select'],
Chris@76 1964 'disabled' => empty($modSettings['bbc_disabled_' . $bbc]) ? array() : $modSettings['bbc_disabled_' . $bbc],
Chris@76 1965 'all_selected' => empty($modSettings['bbc_disabled_' . $bbc]),
Chris@76 1966 );
Chris@76 1967 }
Chris@76 1968 }
Chris@76 1969 }
Chris@76 1970
Chris@76 1971 // Helper function. Saves settings by putting them in Settings.php or saving them in the settings table.
Chris@76 1972 function saveSettings(&$config_vars)
Chris@76 1973 {
Chris@76 1974 global $boarddir, $sc, $cookiename, $modSettings, $user_settings;
Chris@76 1975 global $sourcedir, $context, $cachedir;
Chris@76 1976
Chris@76 1977 // Fix the darn stupid cookiename! (more may not be allowed, but these for sure!)
Chris@76 1978 if (isset($_POST['cookiename']))
Chris@76 1979 $_POST['cookiename'] = preg_replace('~[,;\s\.$]+~' . ($context['utf8'] ? 'u' : ''), '', $_POST['cookiename']);
Chris@76 1980
Chris@76 1981 // Fix the forum's URL if necessary.
Chris@76 1982 if (isset($_POST['boardurl']))
Chris@76 1983 {
Chris@76 1984 if (substr($_POST['boardurl'], -10) == '/index.php')
Chris@76 1985 $_POST['boardurl'] = substr($_POST['boardurl'], 0, -10);
Chris@76 1986 elseif (substr($_POST['boardurl'], -1) == '/')
Chris@76 1987 $_POST['boardurl'] = substr($_POST['boardurl'], 0, -1);
Chris@76 1988 if (substr($_POST['boardurl'], 0, 7) != 'http://' && substr($_POST['boardurl'], 0, 7) != 'file://' && substr($_POST['boardurl'], 0, 8) != 'https://')
Chris@76 1989 $_POST['boardurl'] = 'http://' . $_POST['boardurl'];
Chris@76 1990 }
Chris@76 1991
Chris@76 1992 // Any passwords?
Chris@76 1993 $config_passwords = array(
Chris@76 1994 'db_passwd',
Chris@76 1995 'ssi_db_passwd',
Chris@76 1996 );
Chris@76 1997
Chris@76 1998 // All the strings to write.
Chris@76 1999 $config_strs = array(
Chris@76 2000 'mtitle', 'mmessage',
Chris@76 2001 'language', 'mbname', 'boardurl',
Chris@76 2002 'cookiename',
Chris@76 2003 'webmaster_email',
Chris@76 2004 'db_name', 'db_user', 'db_server', 'db_prefix', 'ssi_db_user',
Chris@76 2005 'boarddir', 'sourcedir', 'cachedir',
Chris@76 2006 );
Chris@76 2007 // All the numeric variables.
Chris@76 2008 $config_ints = array(
Chris@76 2009 );
Chris@76 2010 // All the checkboxes.
Chris@76 2011 $config_bools = array(
Chris@76 2012 'db_persist', 'db_error_send',
Chris@76 2013 'maintenance',
Chris@76 2014 );
Chris@76 2015
Chris@76 2016 // Now sort everything into a big array, and figure out arrays and etc.
Chris@76 2017 $new_settings = array();
Chris@76 2018 foreach ($config_passwords as $config_var)
Chris@76 2019 {
Chris@76 2020 if (isset($_POST[$config_var][1]) && $_POST[$config_var][0] == $_POST[$config_var][1])
Chris@76 2021 $new_settings[$config_var] = '\'' . addcslashes($_POST[$config_var][0], '\'\\') . '\'';
Chris@76 2022 }
Chris@76 2023 foreach ($config_strs as $config_var)
Chris@76 2024 {
Chris@76 2025 if (isset($_POST[$config_var]))
Chris@76 2026 $new_settings[$config_var] = '\'' . addcslashes($_POST[$config_var], '\'\\') . '\'';
Chris@76 2027 }
Chris@76 2028 foreach ($config_ints as $config_var)
Chris@76 2029 {
Chris@76 2030 if (isset($_POST[$config_var]))
Chris@76 2031 $new_settings[$config_var] = (int) $_POST[$config_var];
Chris@76 2032 }
Chris@76 2033 foreach ($config_bools as $key)
Chris@76 2034 {
Chris@76 2035 if (!empty($_POST[$key]))
Chris@76 2036 $new_settings[$key] = '1';
Chris@76 2037 else
Chris@76 2038 $new_settings[$key] = '0';
Chris@76 2039 }
Chris@76 2040
Chris@76 2041 // Save the relevant settings in the Settings.php file.
Chris@76 2042 require_once($sourcedir . '/Subs-Admin.php');
Chris@76 2043 updateSettingsFile($new_settings);
Chris@76 2044
Chris@76 2045 // Now loopt through the remaining (database-based) settings.
Chris@76 2046 $new_settings = array();
Chris@76 2047 foreach ($config_vars as $config_var)
Chris@76 2048 {
Chris@76 2049 // We just saved the file-based settings, so skip their definitions.
Chris@76 2050 if (!is_array($config_var) || $config_var[2] == 'file')
Chris@76 2051 continue;
Chris@76 2052
Chris@76 2053 // Rewrite the definition a bit.
Chris@76 2054 $new_settings[] = array($config_var[3], $config_var[0]);
Chris@76 2055 }
Chris@76 2056
Chris@76 2057 // Save the new database-based settings, if any.
Chris@76 2058 if (!empty($new_settings))
Chris@76 2059 saveDBSettings($new_settings);
Chris@76 2060 }
Chris@76 2061
Chris@76 2062 // Helper function for saving database settings.
Chris@76 2063 function saveDBSettings(&$config_vars)
Chris@76 2064 {
Chris@76 2065 global $sourcedir, $context;
Chris@76 2066
Chris@76 2067 $inlinePermissions = array();
Chris@76 2068 foreach ($config_vars as $var)
Chris@76 2069 {
Chris@76 2070 if (!isset($var[1]) || (!isset($_POST[$var[1]]) && $var[0] != 'check' && $var[0] != 'permissions' && ($var[0] != 'bbc' || !isset($_POST[$var[1] . '_enabledTags']))))
Chris@76 2071 continue;
Chris@76 2072
Chris@76 2073 // Checkboxes!
Chris@76 2074 elseif ($var[0] == 'check')
Chris@76 2075 $setArray[$var[1]] = !empty($_POST[$var[1]]) ? '1' : '0';
Chris@76 2076 // Select boxes!
Chris@76 2077 elseif ($var[0] == 'select' && in_array($_POST[$var[1]], array_keys($var[2])))
Chris@76 2078 $setArray[$var[1]] = $_POST[$var[1]];
Chris@76 2079 elseif ($var[0] == 'select' && !empty($var['multiple']) && array_intersect($_POST[$var[1]], array_keys($var[2])) != array())
Chris@76 2080 {
Chris@76 2081 // For security purposes we validate this line by line.
Chris@76 2082 $options = array();
Chris@76 2083 foreach ($_POST[$var[1]] as $invar)
Chris@76 2084 if (in_array($invar, array_keys($var[2])))
Chris@76 2085 $options[] = $invar;
Chris@76 2086
Chris@76 2087 $setArray[$var[1]] = serialize($options);
Chris@76 2088 }
Chris@76 2089 // Integers!
Chris@76 2090 elseif ($var[0] == 'int')
Chris@76 2091 $setArray[$var[1]] = (int) $_POST[$var[1]];
Chris@76 2092 // Floating point!
Chris@76 2093 elseif ($var[0] == 'float')
Chris@76 2094 $setArray[$var[1]] = (float) $_POST[$var[1]];
Chris@76 2095 // Text!
Chris@76 2096 elseif ($var[0] == 'text' || $var[0] == 'large_text')
Chris@76 2097 $setArray[$var[1]] = $_POST[$var[1]];
Chris@76 2098 // Passwords!
Chris@76 2099 elseif ($var[0] == 'password')
Chris@76 2100 {
Chris@76 2101 if (isset($_POST[$var[1]][1]) && $_POST[$var[1]][0] == $_POST[$var[1]][1])
Chris@76 2102 $setArray[$var[1]] = $_POST[$var[1]][0];
Chris@76 2103 }
Chris@76 2104 // BBC.
Chris@76 2105 elseif ($var[0] == 'bbc')
Chris@76 2106 {
Chris@76 2107
Chris@76 2108 $bbcTags = array();
Chris@76 2109 foreach (parse_bbc(false) as $tag)
Chris@76 2110 $bbcTags[] = $tag['tag'];
Chris@76 2111
Chris@76 2112 if (!isset($_POST[$var[1] . '_enabledTags']))
Chris@76 2113 $_POST[$var[1] . '_enabledTags'] = array();
Chris@76 2114 elseif (!is_array($_POST[$var[1] . '_enabledTags']))
Chris@76 2115 $_POST[$var[1] . '_enabledTags'] = array($_POST[$var[1] . '_enabledTags']);
Chris@76 2116
Chris@76 2117 $setArray[$var[1]] = implode(',', array_diff($bbcTags, $_POST[$var[1] . '_enabledTags']));
Chris@76 2118 }
Chris@76 2119 // Permissions?
Chris@76 2120 elseif ($var[0] == 'permissions')
Chris@76 2121 $inlinePermissions[] = $var[1];
Chris@76 2122 }
Chris@76 2123
Chris@76 2124 if (!empty($setArray))
Chris@76 2125 updateSettings($setArray);
Chris@76 2126
Chris@76 2127 // If we have inline permissions we need to save them.
Chris@76 2128 if (!empty($inlinePermissions) && allowedTo('manage_permissions'))
Chris@76 2129 {
Chris@76 2130 require_once($sourcedir . '/ManagePermissions.php');
Chris@76 2131 save_inline_permissions($inlinePermissions);
Chris@76 2132 }
Chris@76 2133 }
Chris@76 2134
Chris@76 2135 ?>