diff --git a/inc/config.php b/inc/config.php index d9210ab5..7850169a 100644 --- a/inc/config.php +++ b/inc/config.php @@ -476,8 +476,8 @@ // Maximum amount of animated GIF frames to resize (more frames can mean more processing power). A value // of "1" means thumbnails will not be animated. Requires $config['thumb_ext'] to be 'gif' (or blank) and - // $config['thumb_method'] to be 'imagick', 'convert', or 'convert+gifsicle'. This value is not respected - // by 'convert'; will just resize all frames if this is > 1. + // $config['thumb_method'] to be 'imagick', 'convert', or 'convert+gifsicle'. This value is not + // respected by 'convert'; will just resize all frames if this is > 1. $config['thumb_keep_animation_frames'] = 1; /* @@ -511,7 +511,7 @@ $config['strip_exif'] = false; // Use the command-line `exiftool` tool to strip EXIF metadata without decompressing/recompressing JPEGs. // Ignored when $config['redraw_image'] is true. This is also used to adjust the Orientation tag when - // $config['strip_exif'] is false and $config['convert_manual_orient'] is true. + // $config['strip_exif'] is false and $config['convert_manual_orient'] is true. $config['use_exiftool'] = false; // Redraw the image to strip any excess data (commonly ZIP archives) WARNING: This might strip the @@ -562,7 +562,7 @@ // Location of thumbnail to use for spoiler images. $config['spoiler_image'] = 'static/spoiler.png'; // Location of thumbnail to use for deleted images. - $config['image_deleted'] = 'static/deleted.png'; + // $config['image_deleted'] = 'static/deleted.png'; // When a thumbnailed image is going to be the same (in dimension), just copy the entire file and use // that as a thumbnail instead of resizing/redrawing. @@ -580,7 +580,7 @@ // Reject duplicate image uploads. $config['image_reject_repost'] = true; // Reject duplicate image uploads within the same thread. Doesn't change anything if - // $config['image_reject_repost'] is true. + // $config['image_reject_repost'] is true. $config['image_reject_repost_in_thread'] = false; // Display the aspect ratio of uploaded files. @@ -607,7 +607,7 @@ $config['threads_preview_sticky'] = 1; // How to display the URI of boards. Usually '/%s/' (/b/, /mu/, etc). This doesn't change the URL. Find - // $config['board_path'] if you wish to change the URL. + // $config['board_path'] if you wish to change the URL. $config['board_abbreviation'] = '/%s/'; // The default name (ie. Anonymous). @@ -914,7 +914,7 @@ // If you want to put images and other dynamic-static stuff on another (preferably cookieless) domain. // This will override $config['root'] and $config['dir']['...'] directives. "%s" will get replaced with - // $board['dir'], which includes a trailing slash. + // $board['dir'], which includes a trailing slash. // $config['uri_thumb'] = 'http://images.example.org/%sthumb/'; // $config['uri_img'] = 'http://images.example.org/%ssrc/'; @@ -988,6 +988,10 @@ // persistent spammers and ban evaders. Again, a little more database load. $config['ban_cidr'] = true; + // How often (minimum) to purge the ban list of expired bans (which have been seen). Only works when + // $config['cache'] is enabled and working. + $config['purge_bans'] = 60 * 60 * 12; // 12 hours + // Do DNS lookups on IP addresses to get their hostname for the moderator IP pages (?/IP/x.x.x.x). $config['mod']['dns_lookup'] = true; // How many recent posts, per board, to show in ?/IP/x.x.x.x. @@ -1188,12 +1192,47 @@ $config['mod']['news_custom'] = ADMIN; // Delete news entries $config['mod']['news_delete'] = ADMIN; - + // Execute un-filtered SQL queries on the database (?/debug/sql) + $config['mod']['debug_sql'] = DISABLED; // Edit the current configuration (via web interface) $config['mod']['edit_config'] = ADMIN; - // Execute un-filtered SQL queries on the database (?/debug/sql) - $config['mod']['debug_sql'] = DISABLED; + // Config editor permissions + $config['mod']['config'] = array( + JANITOR => false, + MOD => false, + ADMIN => false, + DISABLED => false, + ); + + // Disable the following configuration variables from being changed via ?/config. The following default + // banned variables are considered somewhat dangerous. + $config['mod']['config'][DISABLED] = array( + 'mod>config', + 'mod>config_editor_php', + 'convert_args', + 'db>password', + ); + + $config['mod']['config'][JANITOR] = array( + '!', // Allow editing ONLY the variables listed (in this case, nothing). + ); + + $config['mod']['config'][MOD] = array( + '!', // Allow editing ONLY the variables listed (plus that in $config['mod']['config'][JANITOR]). + 'global_message', + ); + + // Example: Disallow ADMIN from editing (and viewing) $config['db']['password']. + // $config['mod']['config'][ADMIN] = array( + // 'db>password', + // ); + + // Example: Allow ADMIN to edit anything other than $config['db'] + // (and $config['mod']['config'][DISABLED]). + // $config['mod']['config'][ADMIN] = array( + // 'db', + // ); /* * ==================== diff --git a/inc/functions.php b/inc/functions.php index 4c3450f3..1dece172 100644 --- a/inc/functions.php +++ b/inc/functions.php @@ -688,9 +688,19 @@ function checkBan($board = 0) { // No reason to keep expired bans in the database (except those that haven't been viewed yet) function purge_bans() { + global $config; + + if ($config['cache']['enabled'] && $last_time_purged = cache::get('purged_bans_last')) { + if (time() - $last_time_purged < $config['purge_bans'] ) + return; + } + $query = prepare("DELETE FROM ``bans`` WHERE `expires` IS NOT NULL AND `expires` < :time AND `seen` = 1"); $query->bindValue(':time', time()); $query->execute() or error(db_error($query)); + + if ($config['cache']['enabled']) + cache::set('purged_bans_last', time()); } function threadLocked($id) { @@ -1922,7 +1932,7 @@ function rDNS($ip_addr) { if (!$config['dns_system']) { $host = gethostbyaddr($ip_addr); } else { - $resp = shell_exec('host -W 1 ' . $ip_addr); + $resp = shell_exec_error('host -W 1 ' . $ip_addr); if (preg_match('/domain name pointer ([^\s]+)$/', $resp, $m)) $host = $m[1]; else @@ -1947,7 +1957,7 @@ function DNS($host) { if ($ip_addr == $host) $ip_addr = false; } else { - $resp = shell_exec('host -W 1 ' . $host); + $resp = shell_exec_error('host -W 1 ' . $host); if (preg_match('/has address ([^\s]+)$/', $resp, $m)) $ip_addr = $m[1]; else @@ -1960,13 +1970,14 @@ function DNS($host) { return $ip_addr; } -function shell_exec_error($command) { +function shell_exec_error($command, $suppress_stdout = false) { global $config, $debug; if ($config['debug']) $start = microtime(true); - $return = trim(shell_exec('PATH="' . escapeshellcmd($config['shell_path']) . ':$PATH";' . $command . ' 2>&1 && echo "TB_SUCCESS"')); + $return = trim(shell_exec('PATH="' . escapeshellcmd($config['shell_path']) . ':$PATH";' . + $command . ' 2>&1 ' . ($suppress_stdout ? '> /dev/null ' : '') . '&& echo "TB_SUCCESS"')); $return = preg_replace('/TB_SUCCESS$/', '', $return); if ($config['debug']) { diff --git a/inc/image.php b/inc/image.php index 39f228a5..920cf8f9 100644 --- a/inc/image.php +++ b/inc/image.php @@ -265,8 +265,8 @@ class ImageConvert extends ImageBase { } $size = $this->get_size($this->src, false); if ($size) { - $this->width = $size[1]; - $this->height = $size[2]; + $this->width = $size[0]; + $this->height = $size[1]; $this->image = true; } else { @@ -321,8 +321,8 @@ class ImageConvert extends ImageBase { if ($this->format == 'gif' && ($config['thumb_ext'] == 'gif' || $config['thumb_ext'] == '') && $config['thumb_keep_animation_frames'] > 1) { if ($this->gifsicle) { if (($error = shell_exec_error("gifsicle -w --unoptimize -O2 --resize {$this->width}x{$this->height} < " . - escapeshellarg($this->src . '') . " \"#0-{$config['thumb_keep_animation_frames']}\" >/dev/null -o " . - escapeshellarg($this->temp))) || !file_exists($this->temp)) + escapeshellarg($this->src . '') . " \"#0-{$config['thumb_keep_animation_frames']}\" -o " . + escapeshellarg($this->temp), true)) || !file_exists($this->temp)) error('Failed to resize image!', null, $error); } else { if ($config['convert_manual_orient'] && ($this->format == 'jpg' || $this->format == 'jpeg')) diff --git a/inc/mod/config-editor.php b/inc/mod/config-editor.php index caca5a0e..27740378 100644 --- a/inc/mod/config-editor.php +++ b/inc/mod/config-editor.php @@ -1,5 +1,43 @@ ', $disabled_var_name); + if (count($disabled_var_name) == 1) + $disabled_var_name = $disabled_var_name[0]; + if ($varname == $disabled_var_name) + return false; + } + } + + $allow_only = false; + // for ($perm = (int)$mod['type']; $perm >= JANITOR; $perm --) { + for ($perm = JANITOR; $perm <= (int)$mod['type']; $perm ++) { + $allow_only = false; + if (is_array($config['mod']['config'][$perm])) { + foreach ($config['mod']['config'][$perm] as $perm_var_name) { + if ($perm_var_name == '!') { + $allow_only = true; + continue; + } + $perm_var_name = explode('>', $perm_var_name); + if ((count($perm_var_name) == 1 && $varname == $perm_var_name[0]) || + (is_array($varname) && array_slice($varname, 0, count($perm_var_name)) == $perm_var_name)) { + if ($allow_only) + return true; + else + return false; + } + } + } + } + + return !$allow_only; +} + function config_vars() { global $config; @@ -77,8 +115,8 @@ function config_vars() { $already_exists = true; } - if (!$already_exists) - $conf[] = $var; + if (!$already_exists && permission_to_edit_config_var($var['name'])) + $conf[] = $var; } } diff --git a/inc/mod/pages.php b/inc/mod/pages.php index 0a9f825b..706d747d 100644 --- a/inc/mod/pages.php +++ b/inc/mod/pages.php @@ -480,7 +480,12 @@ function mod_new_board() { if (!openBoard($_POST['uri'])) error(_("Couldn't open board after creation.")); - query(Element('posts.sql', array('board' => $board['uri']))) or error(db_error()); + $query = Element('posts.sql', array('board' => $board['uri'])); + + if (mysql_version() < 50503) + $query = preg_replace('/(CHARSET=|CHARACTER SET )utf8mb4/', '$1utf8', $query); + + query($query) or error(db_error()); if ($config['cache']['enabled']) cache::delete('all_boards'); diff --git a/install.php b/install.php index 4b3785e0..56055c2e 100644 --- a/install.php +++ b/install.php @@ -626,8 +626,7 @@ if ($step == 0) { $sql = @file_get_contents('install.sql') or error("Couldn't load install.sql."); sql_open(); - if (mysql_version() < 50503) - $sql = preg_replace('/(CHARSET=|CHARACTER SET )utf8mb4/', '$1utf8', $sql); + $mysql_version = mysql_version(); // This code is probably horrible, but what I'm trying // to do is find all of the SQL queires and put them @@ -639,6 +638,8 @@ if ($step == 0) { $sql_errors = ''; foreach ($queries as $query) { + if ($mysql_version < 50503) + $query = preg_replace('/(CHARSET=|CHARACTER SET )utf8mb4/', '$1utf8', $query); $query = preg_replace('/^([\w\s]*)`([0-9a-zA-Z$_\x{0080}-\x{FFFF}]+)`/u', '$1``$2``', $query); if (!query($query)) $sql_errors .= '
  • ' . db_error() . '
  • ';