public static function new_ban($mask, $reason, $length = false, $ban_board = false, $mod_id = false, $post = false) { global $mod, $pdo, $board; if ($mod_id === false) { $mod_id = isset($mod['id']) ? $mod['id'] : -1; } $range = self::parse_range($mask); $mask = self::range_to_string($range); $query = prepare("INSERT INTO ``bans`` VALUES (NULL, :ipstart, :ipend, :time, :expires, :board, :mod, :reason, 0, :post)"); $query->bindValue(':ipstart', $range[0]); if ($range[1] !== false && $range[1] != $range[0]) { $query->bindValue(':ipend', $range[1]); } else { $query->bindValue(':ipend', null, PDO::PARAM_NULL); } $query->bindValue(':mod', $mod_id); $query->bindValue(':time', time()); if ($reason !== '') { $reason = escape_markup_modifiers($reason); markup($reason); $query->bindValue(':reason', $reason); } else { $query->bindValue(':reason', null, PDO::PARAM_NULL); } if ($length) { if (is_int($length) || ctype_digit($length)) { $length = time() + $length; } else { $length = self::parse_time($length); } $query->bindValue(':expires', $length); } else { $query->bindValue(':expires', null, PDO::PARAM_NULL); } if ($ban_board) { $query->bindValue(':board', $ban_board); } else { $query->bindValue(':board', null, PDO::PARAM_NULL); } if ($post) { $post['board'] = $board['uri']; $query->bindValue(':post', json_encode($post)); } else { $query->bindValue(':post', null, PDO::PARAM_NULL); } $query->execute() or error(db_error($query)); if (isset($mod['id']) && $mod['id'] == $mod_id) { modLog('Created a new ' . ($length > 0 ? preg_replace('/^(\\d+) (\\w+?)s?$/', '$1-$2', until($length)) : 'permanent') . ' ban on ' . ($ban_board ? '/' . $ban_board . '/' : 'all boards') . ' for ' . (filter_var($mask, FILTER_VALIDATE_IP) !== false ? "<a href=\"?/IP/{$mask}\">{$mask}</a>" : $mask) . ' (<small>#' . $pdo->lastInsertId() . '</small>)' . ' with ' . ($reason ? 'reason: ' . utf8tohtml($reason) . '' : 'no reason')); } return $pdo->lastInsertId(); }
function ban($mask, $reason, $length, $board) { global $mod, $pdo; $query = prepare("INSERT INTO `bans` VALUES (NULL, :ip, :mod, :time, :expires, :reason, :board)"); $query->bindValue(':ip', $mask); $query->bindValue(':mod', $mod['id']); $query->bindValue(':time', time()); if ($reason !== '') { markup($reason); $query->bindValue(':reason', $reason); } else { $query->bindValue(':reason', null, PDO::PARAM_NULL); } if ($length > 0) { $query->bindValue(':expires', $length); } else { $query->bindValue(':expires', null, PDO::PARAM_NULL); } if ($board) { $query->bindValue(':board', $board); } else { $query->bindValue(':board', null, PDO::PARAM_NULL); } $query->execute() or error(db_error($query)); modLog('Created a new ' . ($length > 0 ? preg_replace('/^(\\d+) (\\w+?)s?$/', '$1-$2', until($length)) : 'permanent') . ' ban (<small>#' . $pdo->lastInsertId() . '</small>) for ' . (filter_var($mask, FILTER_VALIDATE_IP) !== false ? "<a href=\"?/IP/{$mask}\">{$mask}</a>" : utf8tohtml($mask)) . ' with ' . ($reason ? 'reason: ' . utf8tohtml($reason) . '' : 'no reason')); }
function Element($templateFile, array $options) { global $config, $debug, $twig; if (!$twig) { load_twig(); } if (function_exists('create_pm_header') && (isset($options['mod']) && $options['mod'] || isset($options['__mod']))) { $options['pm'] = create_pm_header(); } if (isset($options['body']) && $config['debug']) { if (isset($debug['start'])) { $debug['time'] = '~' . round((microtime(true) - $debug['start']) * 1000, 2) . 'ms'; unset($debug['start']); } $debug['included'] = get_included_files(); $debug['memory'] = round(memory_get_usage(true) / (1024 * 1024), 2) . ' MiB'; $options['body'] .= '<h3>Debug</h3><pre style="white-space: pre-wrap;font-size: 10px;">' . str_replace("\n", '<br/>', utf8tohtml(print_r($debug, true))) . '</pre>'; } // Read the template file if (@file_get_contents("{$config['dir']['template']}/{$templateFile}")) { $body = $twig->render($templateFile, $options); if ($config['minify_html'] && preg_match('/\\.html$/', $templateFile)) { $body = trim(preg_replace("/[\t\r\n]/", '', $body)); } return $body; } else { throw new Exception("Template file '{$templateFile}' does not exist or is empty in '{$config['dir']['template']}'!"); } }
function Element($templateFile, array $options) { global $config, $debug, $loader; if (function_exists('create_pm_header') && (isset($options['mod']) && $options['mod'] || isset($options['__mod']))) { $options['pm'] = create_pm_header(); } if (isset($options['body']) && $config['debug']) { if (isset($debug['start'])) { $debug['time'] = '~' . round((microtime(true) - $debug['start']) * 1000, 2) . 'ms'; unset($debug['start']); } $options['body'] .= '<h3>Debug</h3><pre style="white-space: pre-wrap;font-size: 10px;">' . str_replace("\n", '<br/>', utf8tohtml(print_r($debug, true))) . '</pre>'; } $loader->setPaths($config['dir']['template']); $twig = new Twig_Environment($loader, array('autoescape' => false, 'cache' => "{$config['dir']['template']}/cache", 'debug' => $config['debug'] ? true : false)); $twig->addExtension(new Twig_Extensions_Extension_Tinyboard()); $twig->addExtension(new Twig_Extensions_Extension_I18n()); // Read the template file if (@file_get_contents("{$config['dir']['template']}/{$templateFile}")) { $body = $twig->render($templateFile, $options); if ($config['minify_html'] && preg_match('/\\.html$/', $templateFile)) { $body = trim(preg_replace("/[\t\r\n]/", '', $body)); } return $body; } else { throw new Exception("Template file '{$templateFile}' does not exist or is empty in '{$config['dir']['template']}'!"); } }
function recentposts_install($settings) { if (!is_numeric($settings['limit_images']) || $settings['limit_images'] < 0) { return array(false, '<strong>' . utf8tohtml($settings['limit_images']) . '</strong> is not a non-negative integer.'); } if (!is_numeric($settings['limit_posts']) || $settings['limit_posts'] < 0) { return array(false, '<strong>' . utf8tohtml($settings['limit_posts']) . '</strong> is not a non-negative integer.'); } }
// Check if thread is locked // but allow mods to post if (!$OP && !hasPermission($config['mod']['postinlocked'], $board['uri'])) { if ($thread['locked']) { error($config['error']['locked']); } } if ($post['has_file']) { $size = $_FILES['file']['size']; if ($size > $config['max_filesize']) { error(sprintf3($config['error']['filesize'], array('sz' => commaize($size), 'filesz' => commaize($size), 'maxsz' => commaize($config['max_filesize'])))); } } if ($mod && $mod['type'] >= MOD && preg_match('/^((.+) )?## (.+)$/', $post['name'], $match)) { if ($mod['type'] == MOD && $match[3] == 'Mod' || $mod['type'] >= ADMIN) { $post['capcode'] = utf8tohtml($match[3]); $post['name'] = $match[2] != '' ? $match[2] : $config['anonymous']; } } else { $post['capcode'] = false; } $trip = generate_tripcode($post['name']); $post['name'] = $trip[0]; $post['trip'] = isset($trip[1]) ? $trip[1] : ''; if (strtolower($post['email']) == 'noko') { $noko = true; $post['email'] = ''; } else { $noko = false; } if ($post['has_file']) {
function mod_config($board_config = false) { global $config, $mod, $board; if ($board_config && !openBoard($board_config)) { error($config['error']['noboard']); } if (!hasPermission($config['mod']['edit_config'], $board_config)) { error($config['error']['noaccess']); } $config_file = $board_config ? $board['dir'] . 'config.php' : 'inc/instance-config.php'; if ($config['mod']['config_editor_php']) { $readonly = !(is_file($config_file) ? is_writable($config_file) : is_writable(dirname($config_file))); if (!$readonly && isset($_POST['code'])) { $code = $_POST['code']; // Save previous instance_config if php_check_syntax fails $old_code = file_get_contents($config_file); file_put_contents($config_file, $code); $resp = shell_exec_error('php -l ' . $config_file); if (preg_match('/No syntax errors detected/', $resp)) { header('Location: ?/config' . ($board_config ? '/' . $board_config : ''), true, $config['redirect_http']); return; } else { file_put_contents($config_file, $old_code); error($config['error']['badsyntax'] . $resp); } } $instance_config = @file_get_contents($config_file); if ($instance_config === false) { $instance_config = "<?php\n\n// This file does not exist yet. You are creating it."; } $instance_config = str_replace("\n", '
', utf8tohtml($instance_config)); mod_page(_('Config editor'), 'mod/config-editor-php.html', array('php' => $instance_config, 'readonly' => $readonly, 'boards' => listBoards(), 'board' => $board_config, 'file' => $config_file, 'token' => make_secure_link_token('config' . ($board_config ? '/' . $board_config : '')))); return; } require_once 'inc/mod/config-editor.php'; $conf = config_vars(); foreach ($conf as &$var) { if (is_array($var['name'])) { $c =& $config; foreach ($var['name'] as $n) { $c =& $c[$n]; } } else { $c = @$config[$var['name']]; } $var['value'] = $c; } unset($var); if (isset($_POST['save'])) { $config_append = ''; foreach ($conf as $var) { $field_name = 'cf_' . (is_array($var['name']) ? implode('/', $var['name']) : $var['name']); if ($var['type'] == 'boolean') { $value = isset($_POST[$field_name]); } elseif (isset($_POST[$field_name])) { $value = $_POST[$field_name]; } else { continue; } // ??? if (!settype($value, $var['type'])) { continue; } // invalid if ($value != $var['value']) { // This value has been changed. $config_append .= '$config'; if (is_array($var['name'])) { foreach ($var['name'] as $name) { $config_append .= '[' . var_export($name, true) . ']'; } } else { $config_append .= '[' . var_export($var['name'], true) . ']'; } $config_append .= ' = '; if (@$var['permissions'] && isset($config['mod']['groups'][$value])) { $config_append .= $config['mod']['groups'][$value]; } else { $config_append .= var_export($value, true); } $config_append .= ";\n"; } } if (!empty($config_append)) { $config_append = "\n// Changes made via web editor by \"" . $mod['username'] . "\" @ " . date('r') . ":\n" . $config_append . "\n"; if (!is_file($config_file)) { $config_append = "<?php\n\n{$config_append}"; } if (!@file_put_contents($config_file, $config_append, FILE_APPEND)) { $config_append = htmlentities($config_append); if ($config['minify_html']) { $config_append = str_replace("\n", '
', $config_append); } $page = array(); $page['title'] = 'Cannot write to file!'; $page['config'] = $config; $page['body'] = ' <p style="text-align:center">Tinyboard could not write to <strong>' . $config_file . '</strong> with the ammended configuration, probably due to a permissions error.</p> <p style="text-align:center">You may proceed with these changes manually by copying and pasting the following code to the end of <strong>' . $config_file . '</strong>:</p> <textarea style="width:700px;height:370px;margin:auto;display:block;background:white;color:black" readonly>' . $config_append . '</textarea> '; echo Element('page.html', $page); exit; } } header('Location: ?/config' . ($board_config ? '/' . $board_config : ''), true, $config['redirect_http']); exit; } mod_page(_('Config editor') . ($board_config ? ': ' . sprintf($config['board_abbreviation'], $board_config) : ''), 'mod/config-editor.html', array('boards' => listBoards(), 'board' => $board_config, 'conf' => $conf, 'file' => $config_file, 'token' => make_secure_link_token('config' . ($board_config ? '/' . $board_config : '')))); }
echo ' <div id="container" style="width: ' . $wugWidth . 'px; height: ' . $wugHeight . 'px;"> </div> <div id="new-window"> <a href="' . fixAmp(fixGet("i&w=" . $wugWinW . "&h=" . $wugWinH)) . '" target="_blank" title="' . $TopenNp . '" onmouseover="Tip(\'' . $TopenNp . '\')" onmouseout="UnTip()"><img src="./images/win.png" alt="new window" width="42"></a> </div>'; } if ($langSwitch && $winFlag) { $thLang = $_GET['lang'] ? $_GET['lang'] : $_COOKIE['cookie_lang']; $langsw = '<div id="lang-switch" style="position: absolute; right: 155px; top: 16px; z-index: 50;"> <form name="languages" action="#" style="font-size: 14px;"> Language: <select name="langSelect" onchange="location.href=\'' . $_SERVER["PHP_SELF"] . '?lang=\'+document.languages.langSelect.value;">'; include './languages/langlist.php'; foreach ($langList as $key => $val) { $selectedL = $thLang == $key ? ' selected' : ''; $langsw .= '<option value="' . $key . '"' . $selectedL . '>' . utf8tohtml($val) . '</option>'; } $langsw .= '</select> </form> </div>'; } else { $langsw = ''; } $disable_picker = $type == 'hour' ? 'xx' : ''; echo ' <a href="' . fixAmp($thisPage . $refreshLink) . '" onmouseover="Tip(\'' . $Trefresh . '\')" onmouseout="UnTip()"> <img id="refresh-button" src="./images/refresh.png" alt="refresh"> </a> <div id="info-icon" onmouseover="Tip(\'' . $TinfoIcon . '\',TITLE,\'' . $TinfoIconTitle . '\', LEFT, true)" onmouseout="UnTip()"><img src="./images/info.png" width="40" height="40" alt="info"></div>
public function __construct($id, $subject, $email, $name, $trip, $capcode, $body, $time, $thumb, $thumbx, $thumby, $file, $filex, $filey, $filesize, $filename, $ip, $sticky, $locked, $bumplocked, $embed, $root = null, $mod = false, $hr = true) { global $config; if (!isset($root)) { $root =& $config['root']; } $this->id = $id; $this->subject = utf8tohtml($subject); $this->email = $email; $this->name = utf8tohtml($name); $this->trip = $trip; $this->capcode = $capcode; $this->body = $body; $this->time = $time; $this->thumb = $thumb; $this->thumbx = $thumbx; $this->thumby = $thumby; $this->file = $file; $this->filex = $filex; $this->filey = $filey; $this->filesize = $filesize; $this->filename = $filename; $this->omitted = 0; $this->omitted_images = 0; $this->posts = array(); $this->ip = $ip; $this->sticky = $sticky; $this->locked = $locked; $this->bumplocked = $bumplocked; $this->embed = $embed; $this->root = $root; $this->mod = $mod; $this->hr = $hr; if ($this->mod) { // Fix internal links // Very complicated regex $this->body = preg_replace('/<a(([a-zA-Z]+="[^"]+")|[a-zA-Z]+=[a-zA-Z]+|\\s)*href="' . preg_quote($config['root'], '/') . '(' . sprintf(preg_quote($config['board_path'], '/'), '\\w+') . ')/', '<a href="?/$3', $this->body); } }
if ($langSwitch) { $thLang = $_GET['lang'] ? $_GET['lang'] : $_COOKIE['cookie_lang']; echo '<div id="lang-switch" style="text-align: right; /*margin-top: 0px; float: right*/ position:absolute; right:0; top:0px;"> <form name="languages" action="#" style="font-size: 14px;"> Language: <select name="langSelect" onchange="location.href=\'' . $_SERVER["PHP_SELF"] . '?lang=\'+document.languages.langSelect.value;">'; include './wxwugraphs/languages/langlist.php'; foreach ($langList as $key => $val) { $selectedL = $thLang == $key ? ' selected' : ''; echo '<option value="' . $key . '"' . $selectedL . '>' . utf8tohtml($val) . '</option>'; } echo '</select> </form> </div>'; } echo ' <ul style="/*height:25px;*/"> ' . $hrTab . ' <li><a href="./wxwugraphs/WUG-tabsd.php?lang=' . $scLang . '"><span>' . utf8tohtml($Tdaily) . '</span></a></li> <li><a href="./wxwugraphs/WUG-tabsm.php?lang=' . $scLang . '"><span>' . utf8tohtml($Tmonthly) . '</span></a></li> <li><a href="./wxwugraphs/WUG-tabsy.php?lang=' . $scLang . '"><span>' . utf8tohtml($Tyearly) . '</span></a></li> </ul> </div> </td></tr> <tr><td style="vertical-align:bottom;"><div id="WUG-foot"> '; require_once './wxwugraphs/WUG-ver.php'; echo ' </div></td></tr> </table> </div>'; echo $errWUGlang; #chdir ('./weather2/');
function build_install($settings) { if (!is_numeric($settings['no_recent']) || $settings['no_recent'] < 0) { return array(false, '<strong>' . utf8tohtml($settings['no_recent']) . '</strong> is not a non-negative integer.'); } }
$unicode = (15 & $ascii) * 262144 + (63 & $ascii1) * 4096 + (63 & $ascii2) * 64 + (63 & $ascii3); $result .= "&#{$unicode};"; $i += 3; } } } } } } return $result; } } // utf-8 convert $thisPage = substr($_SERVER["SCRIPT_NAME"], strrpos($_SERVER["SCRIPT_NAME"], "/") + 1); if ($thisPage == 'wxwugraphs.php') { $TWUsource = utf8tohtml($TWUsource); } if ($dataSource == 'mysql') { $sourceString = ''; } else { $sourceString = ' ' . $TWUsource . ' <a href="http://www.wunderground.com/weatherstation/WXDailyHistory.asp?ID=' . $WUID . '" target="_blank" onmouseover="Tip(\'<img src="' . $mainDir . 'images/wunder-long.png" alt="Wunderground Logo" width="230" height="33" />\',TITLE,\'Weather Undeground server\')" onmouseout="UnTip()">Wunderground.com (' . $WUID . ')</a>'; } $uvarg = isset($winFlag) ? $winFlag : false; if ($uvarg || $tabFlag) { echo ' <table style="width: 100%; color: #bbb;" id="WUGcInfo"> <tr><td class="c-lside"> <div>WU-Graphs <span' . $redVer . ' onmouseover="Tip(\'' . $tooltipVer . '\',ABOVE, true)" onmouseout="UnTip()"> v ' . VERSION . '</span></div> © 2010 <a href="http://pocasi.hovnet.cz/wxwug.php?lang=en" target="_blank" onmouseover="Tip(\'Author\\\'s weather Web site with more information about this software.\',TITLE,\'Weather station Hovezi - Czech Republic\')" onmouseout="UnTip()">Radomir Luza</a>. Powered by <a href="http://www.highcharts.com" target="_blank" rel="nofollow" onmouseover="Tip(\'<div style="width:190px;"><img src="' . $mainDir . 'images/higcharts-logo.png" alt="Highcharts Logo" width="175" height="33" /></div>\',TITLE,\'JS charts for your webpages\', TEXTALIGN, \'center\')" onmouseout="UnTip()">HighCharts</a> & <a href="http://www.jquery.com" target="_blank" rel="nofollow" onmouseover="Tip(\'<div style="width:190px;"><img src="' . $mainDir . 'images/jquery-logo.png" alt="jQuery Logo" width="152" height="33" /></div>\',TITLE,\'jQuery - write less, do more\', TEXTALIGN, \'center\')" onmouseout="UnTip()">jQuery UI</a></td> <td class="c-rside" style="text-align: right; font-weight: bold; vertical-align: bottom; ">' . $sourceString . '</td></tr> </table>
} } else { error(_('Unrecognized file size determination method.')); } if ($size > $config['max_filesize']) { error(sprintf3($config['error']['filesize'], array('sz' => number_format($size), 'filesz' => number_format($size), 'maxsz' => number_format($config['max_filesize'])))); } $post['filesize'] = $size; } $post['capcode'] = false; if ($mod && preg_match('/^((.+) )?## (.+)$/', $post['name'], $matches)) { $name = $matches[2] != '' ? $matches[2] : $config['anonymous']; $cap = $matches[3]; if (isset($config['mod']['capcode'][$mod['type']])) { if ($config['mod']['capcode'][$mod['type']] === true || is_array($config['mod']['capcode'][$mod['type']]) && in_array($cap, $config['mod']['capcode'][$mod['type']])) { $post['capcode'] = utf8tohtml($cap); $post['name'] = $name; } } } $trip = generate_tripcode($post['name']); $post['name'] = $trip[0]; $post['trip'] = isset($trip[1]) ? $trip[1] : ''; $noko = false; if (strtolower($post['email']) == 'noko') { $noko = true; $post['email'] = ''; } elseif (strtolower($post['email']) == 'nonoko') { $noko = false; $post['email'] = ''; } else {
function markup(&$body, $track_cites = false) { global $board, $config, $markup_urls; $modifiers = extract_modifiers($body); $body = preg_replace('@<tinyboard (?!escape )([\\w\\s]+)>(.+?)</tinyboard>@us', '', $body); $body = preg_replace('@<(tinyboard) escape ([\\w\\s]+)>@i', '<$1 $2>', $body); if (isset($modifiers['raw html']) && $modifiers['raw html'] == '1') { return array(); } $body = str_replace("\r", '', $body); $body = utf8tohtml($body); if (mysql_version() < 50503) { $body = mb_encode_numericentity($body, array(0x10000, 0xffffff, 0, 0xffffff), 'UTF-8'); } if ($config['markup_code']) { $code_markup = array(); $body = preg_replace_callback($config['markup_code'], function ($matches) use(&$code_markup) { $d = count($code_markup); $code_markup[] = $matches; return "<code {$d}>"; }, $body); } foreach ($config['markup'] as $markup) { if (is_string($markup[1])) { $body = preg_replace($markup[0], $markup[1], $body); } elseif (is_callable($markup[1])) { $body = preg_replace_callback($markup[0], $markup[1], $body); } } if ($config['markup_urls']) { $markup_urls = array(); $body = preg_replace_callback('/((?:https?:\\/\\/|ftp:\\/\\/|irc:\\/\\/)[^\\s<>()"]+?(?:\\([^\\s<>()"]*?\\)[^\\s<>()"]*?)*)((?:\\s|<|>|"|\\.||\\]|!|\\?|,|,|")*(?:[\\s<>()"]|$))/', 'markup_url', $body, -1, $num_links); if ($num_links > $config['max_links']) { error($config['error']['toomanylinks']); } } if ($config['markup_repair_tidy']) { $body = str_replace(' ', ' ', $body); } if ($config['auto_unicode']) { $body = unicodify($body); if ($config['markup_urls']) { foreach ($markup_urls as &$url) { $body = str_replace(unicodify($url), $url, $body); } } } $tracked_cites = array(); // Cites if (isset($board) && preg_match_all('/(^|\\s)>>(\\d+?)([\\s,.)?]|$)/m', $body, $cites, PREG_SET_ORDER | PREG_OFFSET_CAPTURE)) { if (count($cites[0]) > $config['max_cites']) { error($config['error']['toomanycites']); } $skip_chars = 0; $body_tmp = $body; $search_cites = array(); foreach ($cites as $matches) { $search_cites[] = '`id` = ' . $matches[2][0]; } $search_cites = array_unique($search_cites); $query = query(sprintf('SELECT `thread`, `id` FROM ``posts_%s`` WHERE ' . implode(' OR ', $search_cites), $board['uri'])) or error(db_error()); $cited_posts = array(); while ($cited = $query->fetch(PDO::FETCH_ASSOC)) { $cited_posts[$cited['id']] = $cited['thread'] ? $cited['thread'] : false; } foreach ($cites as $matches) { $cite = $matches[2][0]; // preg_match_all is not multibyte-safe foreach ($matches as &$match) { $match[1] = mb_strlen(substr($body_tmp, 0, $match[1])); } if (isset($cited_posts[$cite])) { $replacement = '<a onclick="highlightReply(\'' . $cite . '\');" href="' . $config['root'] . $board['dir'] . $config['dir']['res'] . link_for(array('id' => $cite, 'thread' => $cited_posts[$cite])) . '#' . $cite . '">' . '>>' . $cite . '</a>'; $body = mb_substr_replace($body, $matches[1][0] . $replacement . $matches[3][0], $matches[0][1] + $skip_chars, mb_strlen($matches[0][0])); $skip_chars += mb_strlen($matches[1][0] . $replacement . $matches[3][0]) - mb_strlen($matches[0][0]); if ($track_cites && $config['track_cites']) { $tracked_cites[] = array($board['uri'], $cite); } } } } // Cross-board linking if (preg_match_all('/(^|\\s)>>>\\/(' . $config['board_regex'] . 'f?)\\/(\\d+)?([\\s,.)?]|$)/um', $body, $cites, PREG_SET_ORDER | PREG_OFFSET_CAPTURE)) { if (count($cites[0]) > $config['max_cites']) { error($config['error']['toomanycross']); } $skip_chars = 0; $body_tmp = $body; if (isset($cited_posts)) { // Carry found posts from local board >>X links foreach ($cited_posts as $cite => $thread) { $cited_posts[$cite] = $config['root'] . $board['dir'] . $config['dir']['res'] . ($thread ? $thread : $cite) . '.html#' . $cite; } $cited_posts = array($board['uri'] => $cited_posts); } else { $cited_posts = array(); } $crossboard_indexes = array(); $search_cites_boards = array(); foreach ($cites as $matches) { $_board = $matches[2][0]; $cite = @$matches[3][0]; if (!isset($search_cites_boards[$_board])) { $search_cites_boards[$_board] = array(); } $search_cites_boards[$_board][] = $cite; } $tmp_board = $board['uri']; foreach ($search_cites_boards as $_board => $search_cites) { $clauses = array(); foreach ($search_cites as $cite) { if (!$cite || isset($cited_posts[$_board][$cite])) { continue; } $clauses[] = '`id` = ' . $cite; } $clauses = array_unique($clauses); if ($board['uri'] != $_board) { if (!openBoard($_board)) { continue; } // Unknown board } if (!empty($clauses)) { $cited_posts[$_board] = array(); $query = query(sprintf('SELECT `thread`, `id`, `slug` FROM ``posts_%s`` WHERE ' . implode(' OR ', $clauses), $board['uri'])) or error(db_error()); while ($cite = $query->fetch(PDO::FETCH_ASSOC)) { $cited_posts[$_board][$cite['id']] = $config['root'] . $board['dir'] . $config['dir']['res'] . link_for($cite) . '#' . $cite['id']; } } $crossboard_indexes[$_board] = $config['root'] . $board['dir'] . $config['file_index']; } // Restore old board if ($board['uri'] != $tmp_board) { openBoard($tmp_board); } foreach ($cites as $matches) { $_board = $matches[2][0]; $cite = @$matches[3][0]; // preg_match_all is not multibyte-safe foreach ($matches as &$match) { $match[1] = mb_strlen(substr($body_tmp, 0, $match[1])); } if ($cite) { if (isset($cited_posts[$_board][$cite])) { $link = $cited_posts[$_board][$cite]; $replacement = '<a ' . ($_board == $board['uri'] ? 'onclick="highlightReply(\'' . $cite . '\');" ' : '') . 'href="' . $link . '">' . '>>>/' . $_board . '/' . $cite . '</a>'; $body = mb_substr_replace($body, $matches[1][0] . $replacement . $matches[4][0], $matches[0][1] + $skip_chars, mb_strlen($matches[0][0])); $skip_chars += mb_strlen($matches[1][0] . $replacement . $matches[4][0]) - mb_strlen($matches[0][0]); if ($track_cites && $config['track_cites']) { $tracked_cites[] = array($_board, $cite); } } } elseif (isset($crossboard_indexes[$_board])) { $replacement = '<a href="' . $crossboard_indexes[$_board] . '">' . '>>>/' . $_board . '/' . '</a>'; $body = mb_substr_replace($body, $matches[1][0] . $replacement . $matches[4][0], $matches[0][1] + $skip_chars, mb_strlen($matches[0][0])); $skip_chars += mb_strlen($matches[1][0] . $replacement . $matches[4][0]) - mb_strlen($matches[0][0]); } } } $tracked_cites = array_unique($tracked_cites, SORT_REGULAR); $body = preg_replace("/^\\s*>.*\$/m", '<span class="quote">$0</span>', $body); if ($config['strip_superfluous_returns']) { $body = preg_replace('/\\s+$/', '', $body); } $body = preg_replace("/\n/", '<br/>', $body); // Fix code markup if ($config['markup_code']) { foreach ($code_markup as $id => $val) { $code = isset($val[2]) ? $val[2] : $val[1]; $code_lang = isset($val[2]) ? $val[1] : ""; $code = "<pre class='code lang-{$code_lang}'>" . str_replace(array("\n", "\t"), array(" ", "	"), htmlspecialchars($code)) . "</pre>"; $body = str_replace("<code {$id}>", $code, $body); } } if ($config['markup_repair_tidy']) { $tidy = new tidy(); $body = str_replace("\t", '	', $body); $body = $tidy->repairString($body, array('doctype' => 'omit', 'bare' => true, 'literal-attributes' => true, 'indent' => false, 'show-body-only' => true, 'wrap' => 0, 'output-bom' => false, 'output-html' => true, 'newline' => 'LF', 'quiet' => true), 'utf8'); $body = str_replace("\n", '', $body); } // replace tabs with 8 spaces $body = str_replace("\t", ' ', $body); return $tracked_cites; }
function mod_edit_page($id) { global $config, $mod, $board; $query = prepare('SELECT * FROM ``pages`` WHERE `id` = :id'); $query->bindValue(':id', $id); $query->execute() or error(db_error($query)); $page = $query->fetch(); if (!$page) { error(_('Could not find the page you are trying to edit.')); } if (!$page['board'] && $mod['boards'][0] !== '*') { error($config['error']['noaccess']); } if (!hasPermission($config['mod']['edit_pages'], $page['board'])) { error($config['error']['noaccess']); } if ($page['board'] && !openBoard($page['board'])) { error($config['error']['noboard']); } if (isset($_POST['method'], $_POST['content'])) { $content = $_POST['content']; $method = $_POST['method']; $page['type'] = $method; if (!in_array($method, array('markdown', 'html', 'infinity'))) { error(_('Unrecognized page markup method.')); } switch ($method) { case 'markdown': $write = purify_html(markdown($content)); break; case 'html': if (hasPermission($config['mod']['rawhtml'])) { $write = $content; } else { $write = purify_html($content); } break; case 'infinity': $c = $content; markup($content); $write = $content; $content = $c; } if (!isset($write) or !$write) { error(_('Failed to mark up your input for some reason...')); } $query = prepare('UPDATE ``pages`` SET `type` = :method, `content` = :content WHERE `id` = :id'); $query->bindValue(':method', $method); $query->bindValue(':content', $content); $query->bindValue(':id', $id); $query->execute() or error(db_error($query)); $fn = ($board['uri'] ? $board['uri'] . '/' : '') . $page['name'] . '.html'; $body = "<div class='ban'>{$write}</div>"; $html = Element('page.html', array('config' => $config, 'body' => $body, 'title' => utf8tohtml($page['title']))); file_write($fn, $html); modLog("Edited page {$page['name']} <span class='unimportant'>(#{$page['id']})</span>"); } if (!isset($content)) { $query = prepare('SELECT `content` FROM ``pages`` WHERE `id` = :id'); $query->bindValue(':id', $id); $query->execute() or error(db_error($query)); $content = $query->fetchColumn(); } mod_page(sprintf(_('Editing static page: %s'), $page['name']), 'mod/edit_page.html', array('page' => $page, 'token' => make_secure_link_token("edit_page/{$id}"), 'content' => prettify_textarea($content), 'board' => $board)); }
public function html($count = false) { global $config; $elements = array('<input type="hidden" name="%name%" value="%value%">', '<input type="hidden" value="%value%" name="%name%">', '<input style="display:none" type="text" name="%name%" value="%value%">', '<input style="display:none" type="text" value="%value%" name="%name%">', '<span style="display:none"><input type="text" name="%name%" value="%value%"></span>', '<div style="display:none"><input type="text" name="%name%" value="%value%"></div>', '<div style="display:none"><input type="text" name="%name%" value="%value%"></div>', '<textarea style="display:none" name="%name%">%value%</textarea>', '<textarea name="%name%" style="display:none">%value%</textarea>'); $html = ''; if ($count === false) { $count = rand(1, count($this->inputs) / 15); } if ($count === true) { // all elements $inputs = array_slice($this->inputs, $this->index); } else { $inputs = array_slice($this->inputs, $this->index, $count); } $this->index += count($inputs); foreach ($inputs as $name => $value) { $element = false; while (!$element) { $element = $elements[array_rand($elements)]; if (strpos($element, 'textarea') !== false && $value == '') { // There have been some issues with mobile web browsers and empty <textarea>'s. $element = false; } } $element = str_replace('%name%', utf8tohtml($name), $element); if (rand(0, 2) == 0) { $value = $this->make_confusing($value); } else { $value = utf8tohtml($value); } if (strpos($element, 'textarea') === false) { $value = str_replace('"', '"', $value); } $element = str_replace('%value%', $value, $element); $html .= $element; } return $html; }
function mod_new_pm($username) { global $config, $mod; if (!hasPermission($config['mod']['create_pm'])) { error($config['error']['noaccess']); } $query = prepare("SELECT `id` FROM `mods` WHERE `username` = :username"); $query->bindValue(':username', $username); $query->execute() or error(db_error($query)); if (!($id = $query->fetchColumn(0))) { // Old style ?/PM: by user ID $query = prepare("SELECT `username` FROM `mods` WHERE `id` = :username"); $query->bindValue(':username', $username); $query->execute() or error(db_error($query)); if ($username = $query->fetchColumn(0)) { header('Location: ?/new_PM/' . $username, true, $config['redirect_http']); } else { error($config['error']['404']); } } if (isset($_POST['message'])) { markup($_POST['message']); $query = prepare("INSERT INTO `pms` VALUES (NULL, :me, :id, :message, :time, 1)"); $query->bindValue(':me', $mod['id']); $query->bindValue(':id', $id); $query->bindValue(':message', $_POST['message']); $query->bindValue(':time', time()); $query->execute() or error(db_error($query)); if ($config['cache']['enabled']) { cache::delete('pm_unread_' . $id); cache::delete('pm_unreadcount_' . $id); } modLog('Sent a PM to ' . utf8tohtml($username)); header('Location: ?/', true, $config['redirect_http']); } mod_page(sprintf('%s %s', _('New PM for'), $username), 'mod/new_pm.html', array('username' => $username, 'id' => $id)); }
public static function new_ban($mask, $reason, $length = false, $ban_board = false, $mod_id = false, $post = false) { global $config, $mod, $pdo, $board; if ($mod_id === false) { $mod_id = isset($mod['id']) ? $mod['id'] : -1; } if (!in_array($ban_board, $mod['boards']) && $mod['boards'][0] != '*') { error($config['error']['noaccess']); } $range = self::parse_range($mask); $mask = self::range_to_string($range); $query = prepare("INSERT INTO ``bans`` VALUES (NULL, :ipstart, :ipend, :time, :expires, :board, :mod, :reason, 0, :post)"); $query->bindValue(':ipstart', $range[0]); if ($range[1] !== false && $range[1] != $range[0]) { $query->bindValue(':ipend', $range[1]); } else { $query->bindValue(':ipend', null, PDO::PARAM_NULL); } $query->bindValue(':mod', $mod_id); $query->bindValue(':time', time()); if ($reason !== '') { $reason = escape_markup_modifiers($reason); markup($reason); $query->bindValue(':reason', $reason); } else { $query->bindValue(':reason', null, PDO::PARAM_NULL); } if ($length) { if (is_int($length) || ctype_digit($length)) { $length = time() + $length; } else { $length = self::parse_time($length); } $query->bindValue(':expires', $length); } else { $query->bindValue(':expires', null, PDO::PARAM_NULL); } if ($ban_board) { $query->bindValue(':board', $ban_board); } else { $query->bindValue(':board', null, PDO::PARAM_NULL); } if ($post) { $post['board'] = $board['uri']; $match_urls = '(?xi)\\b((?:https?://|www\\d{0,3}[.]|[a-z0-9.\\-]+[.][a-z]{2,4}/)(?:[^\\s()<>]+|\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\))+(?:\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\)|[^\\s`!()\\[\\]{};:\'".,<>?«»“”‘’]))'; $matched = array(); preg_match_all("#{$match_urls}#im", $post['body_nomarkup'], $matched); if (isset($matched[0]) && $matched[0]) { $post['body'] = str_replace($matched[0], '###Link-Removed###', $post['body']); $post['body_nomarkup'] = str_replace($matched[0], '###Link-Removed###', $post['body_nomarkup']); } $query->bindValue(':post', json_encode($post)); } else { $query->bindValue(':post', null, PDO::PARAM_NULL); } $query->execute() or error(db_error($query)); if (isset($mod['id']) && $mod['id'] == $mod_id) { modLog('Created a new ' . ($length > 0 ? preg_replace('/^(\\d+) (\\w+?)s?$/', '$1-$2', until($length)) : 'permanent') . ' ban on ' . ($ban_board ? '/' . $ban_board . '/' : 'all boards') . ' for ' . (filter_var($mask, FILTER_VALIDATE_IP) !== false ? "<a href=\"?/IP/{$mask}\">{$mask}</a>" : $mask) . ' (<small>#' . $pdo->lastInsertId() . '</small>)' . ' with ' . ($reason ? 'reason: ' . utf8tohtml($reason) . '' : 'no reason')); } if (!$config['cron_bans']) { rebuildThemes('bans'); } return $pdo->lastInsertId(); }
function markup(&$body, $track_cites = false) { global $board, $config, $markup_urls; $body = str_replace("\r", '', $body); $body = utf8tohtml($body); foreach ($config['markup'] as $markup) { if (is_string($markup[1])) { $body = preg_replace($markup[0], $markup[1], $body); } elseif (is_callable($markup[1])) { $body = preg_replace_callback($markup[0], $markup[1], $body); } } if ($config['markup_urls']) { $markup_urls = array(); $body = preg_replace_callback('/((?:https?:\\/\\/|ftp:\\/\\/|irc:\\/\\/)[^\\s<>()"]+?(?:\\([^\\s<>()"]*?\\)[^\\s<>()"]*?)*)((?:\\s|<|>|"|\\.||\\]|!|\\?|,|,|")*(?:[\\s<>()"]|$))/', 'markup_url', $body, -1, $num_links); if ($num_links > $config['max_links']) { error($config['error']['toomanylinks']); } } if ($config['auto_unicode']) { $body = unicodify($body); if ($config['markup_urls']) { foreach ($markup_urls as &$url) { $body = str_replace(unicodify($url), $url, $body); } } } // replace tabs with 8 spaces $body = str_replace("\t", ' ', $body); $tracked_cites = array(); // Cites if (isset($board) && preg_match_all('/(^|\\s)>>(\\d+?)([\\s,.)?]|$)/m', $body, $cites)) { if (count($cites[0]) > $config['max_cites']) { error($config['error']['toomanycites']); } for ($index = 0; $index < count($cites[0]); $index++) { $cite = $cites[2][$index]; $query = prepare(sprintf("SELECT `thread`,`id` FROM `posts_%s` WHERE `id` = :id LIMIT 1", $board['uri'])); $query->bindValue(':id', $cite); $query->execute() or error(db_error($query)); if ($post = $query->fetch()) { $replacement = '<a onclick="highlightReply(\'' . $cite . '\');" href="' . $config['root'] . $board['dir'] . $config['dir']['res'] . ($post['thread'] ? $post['thread'] : $post['id']) . '.html#' . $cite . '">' . '>>' . $cite . '</a>'; $body = str_replace($cites[0][$index], $cites[1][$index] . $replacement . $cites[3][$index], $body); if ($track_cites && $config['track_cites']) { $tracked_cites[] = array($board['uri'], $post['id']); } } } } // Cross-board linking if (preg_match_all('/(^|\\s)>>>\\/(\\w+?)\\/(\\d+)?([\\s,.)?]|$)/m', $body, $cites)) { if (count($cites[0]) > $config['max_cites']) { error($config['error']['toomanycross']); } for ($index = 0; $index < count($cites[0]); $index++) { $_board = $cites[2][$index]; $cite = @$cites[3][$index]; // Temporarily store board information because it will be overwritten $tmp_board = $board['uri']; // Check if the board exists, and load settings if (openBoard($_board)) { if ($cite) { $query = prepare(sprintf("SELECT `thread`,`id` FROM `posts_%s` WHERE `id` = :id LIMIT 1", $board['uri'])); $query->bindValue(':id', $cite); $query->execute() or error(db_error($query)); if ($post = $query->fetch()) { $replacement = '<a onclick="highlightReply(\'' . $cite . '\');" href="' . $config['root'] . $board['dir'] . $config['dir']['res'] . ($post['thread'] ? $post['thread'] : $post['id']) . '.html#' . $cite . '">' . '>>>/' . $_board . '/' . $cite . '</a>'; $body = str_replace($cites[0][$index], $cites[1][$index] . $replacement . $cites[4][$index], $body); if ($track_cites && $config['track_cites']) { $tracked_cites[] = array($board['uri'], $post['id']); } } } else { $replacement = '<a href="' . $config['root'] . $board['dir'] . $config['file_index'] . '">' . '>>>/' . $_board . '/' . '</a>'; $body = str_replace($cites[0][$index], $cites[1][$index] . $replacement . $cites[4][$index], $body); } } // Restore main board settings openBoard($tmp_board); } } $body = preg_replace("/^\\s*>.*\$/m", '<span class="quote">$0</span>', $body); if ($config['strip_superfluous_returns']) { $body = preg_replace('/\\s+$/', '', $body); } $body = preg_replace("/\n/", '<br/>', $body); return $tracked_cites; }
if (!is_readable($upload)) { error($config['error']['nomove']); } $md5cmd = $config['bsd_md5'] ? 'md5 -r' : 'md5sum'; if (($output = shell_exec_error("cat " . escapeshellarg($upload) . " | {$md5cmd}")) !== false) { $explodedvar = explode(' ', $output); $hash = $explodedvar[0]; } else { $hash = md5_file($upload); } // filter files by MD5 $query = prepare('SELECT * FROM ``filters`` WHERE `type` = "md5" and `value` = :value'); $query->bindValue(':value', $hash); $result = $query->execute() or error(db_error()); if ($row = $query->fetch()) { $reason = utf8tohtml($row['reason']); error("Sorry, cannot upload. Matched MD5 of disallowed file. Reason: {$reason}"); } $file['hash'] = $hash; $allhashes .= $hash; } if (count($post['files']) == 1) { $post['filehash'] = $hash; } else { $post['filehash'] = md5($allhashes); } } if (!hasPermission($config['mod']['bypass_filters'], $board['uri'])) { require_once 'inc/filters.php'; do_filters($post); }
function mod_8_settings($b) { global $config, $mod; //if ($b === 'infinity' && $mod['type'] !== ADMIN) // error('Settings temporarily disabled for this board.'); if (!in_array($b, $mod['boards']) and $mod['boards'][0] != '*') { error($config['error']['noaccess']); } if (!hasPermission($config['mod']['edit_settings'], $b)) { error($config['error']['noaccess']); } if (!openBoard($b)) { error("Could not open board!"); } $possible_languages = array_diff(scandir('inc/locale/'), array('..', '.', '.tx', 'README.md')); if ($_SERVER['REQUEST_METHOD'] == 'POST') { $board_type = $_POST['board_type']; $imgboard = $board_type == 'imgboard'; $txtboard = $board_type == 'txtboard'; $fileboard = $board_type == 'fileboard'; $title = $_POST['title']; $subtitle = $_POST['subtitle']; $country_flags = isset($_POST['country_flags']) ? 'true' : 'false'; $field_disable_name = isset($_POST['field_disable_name']) ? 'true' : 'false'; $enable_embedding = isset($_POST['enable_embedding']) ? 'true' : 'false'; $force_image_op = $imgboard && isset($_POST['force_image_op']) ? 'true' : 'false'; $disable_images = $txtboard ? 'true' : 'false'; $poster_ids = isset($_POST['poster_ids']) ? 'true' : 'false'; $show_sages = isset($_POST['show_sages']) ? 'true' : 'false'; $auto_unicode = isset($_POST['auto_unicode']) ? 'true' : 'false'; $strip_combining_chars = isset($_POST['strip_combining_chars']) ? 'true' : 'false'; $allow_roll = isset($_POST['allow_roll']) ? 'true' : 'false'; $image_reject_repost = isset($_POST['image_reject_repost']) ? 'true' : 'false'; $image_reject_repost_in_thread = isset($_POST['image_reject_repost_in_thread']) ? 'true' : 'false'; $early_404 = isset($_POST['early_404']) ? 'true' : 'false'; $allow_delete = isset($_POST['allow_delete']) ? 'true' : 'false'; $allow_flash = $imgboard && isset($_POST['allow_flash']) ? '$config[\'allowed_ext_files\'][] = \'swf\';' : ''; $allow_pdf = $imgboard && isset($_POST['allow_pdf']) ? '$config[\'allowed_ext_files\'][] = \'pdf\';' : ''; $code_tags = isset($_POST['code_tags']) ? '$config[\'additional_javascript\'][] = \'js/code_tags/run_prettify.js\';$config[\'markup\'][] = array("/\\[code\\](.+?)\\[\\/code\\]/ms", "<code><pre class=\'prettyprint\' style=\'display:inline-block\'>\\$1</pre></code>");' : ''; $katex = isset($_POST['katex']) ? '$config[\'katex\'] = true;$config[\'additional_javascript\'][] = \'js/katex/katex.min.js\'; $config[\'markup\'][] = array("/\\[tex\\](.+?)\\[\\/tex\\]/ms", "<span class=\'tex\'>\\$1</span>"); $config[\'additional_javascript\'][] = \'js/katex-enable.js\';' : ''; $user_flags = isset($_POST['user_flags']) ? "if (file_exists('{$b}/flags.php')) { include 'flags.php'; }\n" : ''; $captcha = isset($_POST['captcha']) ? 'true' : 'false'; $force_subject_op = isset($_POST['force_subject_op']) ? 'true' : 'false'; $force_flag = isset($_POST['force_flag']) ? 'true' : 'false'; $tor_posting = isset($_POST['tor_posting']) ? 'true' : 'false'; $tor_image_posting = isset($_POST['tor_image_posting']) ? 'true' : 'false'; $robot_enable = isset($_POST['robot_enable']) ? 'true' : 'false'; $new_thread_capt = isset($_POST['new_thread_capt']) ? 'true' : 'false'; $oekaki = ($imgboard || $fileboard) && isset($_POST['oekaki']) ? 'true' : 'false'; $view_bumplock = isset($_POST['view_bumplock']) ? '-1' : 'MOD'; if ($tor_image_posting === 'true' && isset($_POST['meta_noindex'])) { error('Please index your board to enable this.'); } if ($_POST['locale'] !== 'en' && in_array($_POST['locale'], $possible_languages)) { $locale = "\$config['locale'] = '{$_POST['locale']}.UTF-8';"; } else { $locale = ''; } if (isset($_POST['max_images']) && (int) $_POST['max_images'] && (int) $_POST['max_images'] <= 5) { $_POST['max_images'] = (int) $_POST['max_images']; $multiimage = "\$config['max_images'] = {$_POST['max_images']};\n\t\t\t\t\t \$config['additional_javascript'][] = 'js/multi-image.js';"; } else { $multiimage = ''; } if (isset($_POST['custom_assets'])) { $assets = "\$config['custom_assets'] = true;\n\t\t\t\t \$config['spoiler_image'] = 'static/assets/{$b}/spoiler.png';\n\t\t\t\t \$config['image_deleted'] = 'static/assets/{$b}/deleted.png';\n\t\t\t\t \$config['no_file_image'] = 'static/assets/{$b}/no-file.png';\n\t\t\t\t"; } else { $assets = ''; } $file_board = ''; if ($fileboard) { $force_image_op = true; $file_board = "\$config['threads_per_page'] = 30;\n\t\t\t\t\t \$config['file_board'] = true;\n\t\t\t\t\t \$config['threads_preview'] = 0;\n\t\t\t\t \$config['threads_preview_sticky'] = 0;\n\t\t\t\t\t \$config['allowed_ext_files'] = array();\n"; if (isset($_POST['allowed_type'])) { foreach ($_POST['allowed_type'] as $val) { if (in_array($val, $config['fileboard_allowed_types'])) { $file_board .= "\$config['allowed_ext_files'][] = '{$val}';\n"; } } } if (isset($_POST['allowed_ext_op'])) { $file_board .= "\$config['allowed_ext_op'] = \$config['allowed_ext_files'];\n"; if (isset($_POST['allowed_ext_op_video'])) { $file_board .= "\$config['allowed_ext_op'][] = 'webm';\n\t\t\t\t\t\t\t\t\$config['allowed_ext_op'][] = 'mp4';\n"; } } if (isset($_POST['tag_id'])) { $file_board .= "\$config['allowed_tags'] = array();\n"; foreach ($_POST['tag_id'] as $id => $v) { $file_board .= "\$config['allowed_tags']["; $file_board .= 'base64_decode("'; $file_board .= base64_encode($_POST['tag_id'][$id]); $file_board .= '")'; $file_board .= "] = "; $file_board .= 'base64_decode("'; $file_board .= base64_encode($_POST['tag_desc'][$id]); $file_board .= '")'; $file_board .= ";\n"; } } } $anal_filenames = $fileboard && isset($_POST['anal_filenames']) ? "\$config['filename_func'] = 'filename_func';\n" : ''; $anonymous = base64_encode($_POST['anonymous']); $blotter = base64_encode(purify_html(html_entity_decode($_POST['blotter']))); $add_to_config = @file_get_contents($b . '/extra_config.php'); $replace = ''; if (isset($_POST['replace'])) { if (sizeof($_POST['replace']) > 200 || sizeof($_POST['with']) > 200) { error(_('Sorry, max 200 wordfilters allowed.')); } if (count($_POST['replace']) == count($_POST['with'])) { foreach ($_POST['replace'] as $i => $r) { if ($r !== '') { $w = $_POST['with'][$i]; if (strlen($w) > 255) { error(sprintf(_('Sorry, %s is too long. Max replacement is 255 characters'), utf8tohtml($w))); } $replace .= '$config[\'wordfilters\'][] = array(base64_decode(\'' . base64_encode($r) . '\'), base64_decode(\'' . base64_encode($w) . '\'));'; } } } if (is_billion_laughs($_POST['replace'], $_POST['with'])) { error(_('Wordfilters may not wordfilter previous wordfilters. For example, if a filters to bb and b filters to cc, that is not allowed.')); } } if (isset($_POST['hour_max_threads']) && (int) $_POST['hour_max_threads'] > 0 && (int) $_POST['hour_max_threads'] < 101) { $hour_max_threads = (int) $_POST['hour_max_threads']; } else { $hour_max_threads = 'false'; } if (isset($_POST['max_pages'])) { $mp = (int) $_POST['max_pages']; if ($mp > 25 || $mp < 1) { $max_pages = 15; } else { $max_pages = $mp; } } else { $max_pages = 15; } if (isset($_POST['reply_limit'])) { $rl = (int) $_POST['reply_limit']; if ($rl > 750 || $rl < 250 || $rl % 25) { $reply_limit = 250; } else { $reply_limit = $rl; } } else { $reply_limit = 250; } if (isset($_POST['max_newlines'])) { $mn = (int) $_POST['max_newlines']; if ($mn < 20 || $mn > 300) { $max_newlines = 0; } else { $max_newlines = $mn; } } else { $max_newlines = 0; } if (isset($_POST['min_body'])) { $mb = (int) $_POST['min_body']; if ($mb < 0 || $mb > 1024) { $min_body = 0; } else { $min_body = $mb; } } else { $min_body = 0; } if (!(strlen($title) < 40)) { error('Invalid title'); } if (!(strlen($subtitle) < 200)) { error('Invalid subtitle'); } $query = prepare('UPDATE ``boards`` SET `title` = :title, `subtitle` = :subtitle, `indexed` = :indexed, `public_bans` = :public_bans, `public_logs` = :public_logs, `8archive` = :8archive WHERE `uri` = :uri'); $query->bindValue(':title', $title); $query->bindValue(':subtitle', $subtitle); $query->bindValue(':uri', $b); $query->bindValue(':indexed', !isset($_POST['meta_noindex'])); $query->bindValue(':public_bans', isset($_POST['public_bans'])); $query->bindValue(':public_logs', (int) $_POST['public_logs']); $query->bindValue(':8archive', isset($_POST['8archive'])); $query->execute() or error(db_error($query)); $config_file = <<<EOT <?php \$config['country_flags'] = {$country_flags}; \$config['field_disable_name'] = {$field_disable_name}; \$config['enable_embedding'] = {$enable_embedding}; \$config['force_image_op'] = {$force_image_op}; \$config['disable_images'] = {$disable_images}; \$config['poster_ids'] = {$poster_ids}; \$config['show_sages'] = {$show_sages}; \$config['auto_unicode'] = {$auto_unicode}; \$config['strip_combining_chars'] = {$strip_combining_chars}; \$config['allow_roll'] = {$allow_roll}; \$config['image_reject_repost'] = {$image_reject_repost}; \$config['image_reject_repost_in_thread'] = {$image_reject_repost_in_thread}; \$config['early_404'] = {$early_404}; \$config['allow_delete'] = {$allow_delete}; \$config['anonymous'] = base64_decode('{$anonymous}'); \$config['blotter'] = base64_decode('{$blotter}'); \$config['stylesheets']['Custom'] = 'board/{$b}.css'; \$config['default_stylesheet'] = array('Custom', \$config['stylesheets']['Custom']); \$config['captcha']['enabled'] = {$captcha}; \$config['force_subject_op'] = {$force_subject_op}; \$config['force_flag'] = {$force_flag}; \$config['tor_posting'] = {$tor_posting}; \$config['tor_image_posting'] = {$tor_image_posting}; \$config['robot_enable'] = {$robot_enable}; \$config['new_thread_capt'] = {$new_thread_capt}; \$config['hour_max_threads'] = {$hour_max_threads}; \$config['reply_limit'] = {$reply_limit}; \$config['max_pages'] = {$max_pages}; \$config['max_newlines'] = {$max_newlines}; \$config['oekaki'] = {$oekaki}; \$config['min_body'] = {$min_body}; \$config['mod']['view_bumplock'] = {$view_bumplock}; {$code_tags} {$katex} {$replace} {$multiimage} {$allow_flash} {$allow_pdf} {$user_flags} {$assets} {$locale} {$anal_filenames} {$file_board} if (\$config['disable_images']) \t\$config['max_pages'] = 10000; {$add_to_config} EOT; // Clean up our CSS...no more expression() or off-site URLs. $clean_css = preg_replace('/expression\\s*\\(/', '', $_POST['css']); $matched = array(); preg_match_all("#{$config['link_regex']}#im", $clean_css, $matched); if (isset($matched[0])) { foreach ($matched[0] as $match) { $match_okay = false; foreach ($config['allowed_offsite_urls'] as $allowed_url) { if (strpos($match, $allowed_url) !== false && strpos($match, '#') === false && strpos($match, '?') === false && strpos($match, ';') === false) { $match_okay = true; } } if ($match_okay !== true) { error(sprintf(_("Off-site link \"%s\" is not allowed in the board stylesheet"), $match)); } } } //Filter out imports from sites with potentially unsafe content $match_imports = '@import[^;]*'; $matched = array(); preg_match_all("#{$match_imports}#im", $clean_css, $matched); $unsafe_import_urls = array('https://a.pomf.se/'); if (isset($matched[0])) { foreach ($matched[0] as $match) { $match_okay = true; foreach ($unsafe_import_urls as $unsafe_import_url) { if (strpos($match, $unsafe_import_url) !== false && strpos($match, '#') === false) { $match_okay = false; } } if ($match_okay !== true) { error(sprintf(_("Potentially unsafe import \"%s\" is not allowed in the board stylesheet"), $match)); } } } $query = query('SELECT `uri`, `title`, `subtitle` FROM ``boards`` WHERE `8archive` = TRUE'); file_write('8archive.json', json_encode($query->fetchAll(PDO::FETCH_ASSOC))); file_write($b . '/config.php', $config_file); file_write('stylesheets/board/' . $b . '.css', $clean_css); $_config = $config; unset($config['wordfilters']); // Faster than openBoard and bypasses cache...we're trusting the PHP output // to be safe enough to run with every request, we can eval it here. eval(str_replace('flags.php', "{$b}/flags.php", preg_replace('/^\\<\\?php$/m', '', $config_file))); // czaks: maybe reconsider using it, now that config is cached? // be smarter about rebuilds...only some changes really require us to rebuild all threads if ($_config['captcha']['enabled'] != $config['captcha']['enabled'] || $_config['new_thread_capt'] != $config['new_thread_capt'] || $_config['captcha']['extra'] != $config['captcha']['extra'] || $_config['blotter'] != $config['blotter'] || $_config['field_disable_name'] != $config['field_disable_name'] || $_config['show_sages'] != (isset($config['show_sages']) && $config['show_sages'])) { buildIndex(); $query = query(sprintf("SELECT `id` FROM ``posts_%s`` WHERE `thread` IS NULL", $b)) or error(db_error()); while ($post = $query->fetch(PDO::FETCH_ASSOC)) { buildThread($post['id']); } } modLog('Edited board settings', $b); } $query = prepare('SELECT * FROM boards WHERE uri = :board'); $query->bindValue(':board', $b); $query->execute() or error(db_error($query)); $board = $query->fetchAll()[0]; // Clean the cache if ($config['cache']['enabled']) { cache::delete('board_' . $board['uri']); cache::delete('all_boards'); cache::delete('config_' . $board['uri']); cache::delete('events_' . $board['uri']); unlink('tmp/cache/locale_' . $board['uri']); } $css = @file_get_contents('stylesheets/board/' . $board['uri'] . '.css'); mod_page(_('Board configuration'), 'mod/settings.html', array('board' => $board, 'css' => prettify_textarea($css), 'token' => make_secure_link_token('settings/' . $board['uri']), 'languages' => $possible_languages, 'allowed_urls' => $config['allowed_offsite_urls'])); }
function do_array_part($array, $prefix = '') { global $data, $config; foreach ($array as $name => $value) { if (is_array($value)) { do_array_part($value, $prefix . $name . ' → '); } else { if ($config['mod']['never_reveal_password'] && $prefix == 'db → ' && $name == 'password') { $value = '<em>hidden</em>'; } elseif (gettype($value) == 'boolean') { $value = $value ? '<span style="color:green;">On</span>' : '<span style="color:red;">Off</span>'; } elseif (gettype($value) == 'string') { if (empty($value)) { $value = '<em>empty</em>'; } else { $value = '<span style="color:maroon;">' . utf8tohtml(substr($value, 0, 110) . (mb_strlen($value) > 110 ? '…' : '')) . '</span>'; } } elseif (gettype($value) == 'integer') { $value = '<span style="color:black;">' . $value . '</span>'; } elseif (is_object($value) && get_class($value) == 'Closure') { $value = '[callback]'; } $data .= '<tr><th style="text-align:left;">' . $prefix . (gettype($name) == 'integer' ? '[]' : utf8tohtml($name)) . '</th><td>' . $value . '</td></tr>'; } } }
<?php require 'inc/functions.php'; if (!$config['search']['enable']) { die(_("Post search is disabled")); } $queries_per_minutes = $config['search']['queries_per_minutes']; $queries_per_minutes_all = $config['search']['queries_per_minutes_all']; $search_limit = $config['search']['search_limit']; if (isset($config['search']['boards'])) { $boards = $config['search']['boards']; } else { $boards = listBoards(TRUE); } $body = Element('search_form.html', array('boards' => $boards, 'b' => isset($_GET['board']) ? $_GET['board'] : false, 'search' => isset($_GET['search']) ? str_replace('"', '"', utf8tohtml($_GET['search'])) : false)); if (isset($_GET['search']) && !empty($_GET['search']) && isset($_GET['board']) && in_array($_GET['board'], $boards)) { $phrase = $_GET['search']; $_body = ''; $query = prepare("SELECT COUNT(*) FROM ``search_queries`` WHERE `ip` = :ip AND `time` > :time"); $query->bindValue(':ip', $_SERVER['REMOTE_ADDR']); $query->bindValue(':time', time() - $queries_per_minutes[1] * 60); $query->execute() or error(db_error($query)); if ($query->fetchColumn() > $queries_per_minutes[0]) { error(_('Wait a while before searching again, please.')); } $query = prepare("SELECT COUNT(*) FROM ``search_queries`` WHERE `time` > :time"); $query->bindValue(':time', time() - $queries_per_minutes_all[1] * 60); $query->execute() or error(db_error($query)); if ($query->fetchColumn() > $queries_per_minutes_all[0]) { error(_('Wait a while before searching again, please.')); }
public function __construct($post, $root = null, $mod = false, $hr = true) { global $config; if (!isset($root)) { $root =& $config['root']; } foreach ($post as $key => $value) { $this->{$key} = $value; } $this->subject = utf8tohtml($this->subject); $this->name = utf8tohtml($this->name); $this->mod = $mod; $this->root = $root; $this->hr = $hr; $this->posts = array(); $this->omitted = 0; $this->omitted_images = 0; if ($this->embed) { $this->embed = embed_html($this->embed); } $this->modifiers = extract_modifiers($this->body_nomarkup); if ($config['always_regenerate_markup']) { $this->body = $this->body_nomarkup; markup($this->body); } if ($this->mod) { // Fix internal links // Very complicated regex $this->body = preg_replace('/<a((([a-zA-Z]+="[^"]+")|[a-zA-Z]+=[a-zA-Z]+|\\s)*)href="' . preg_quote($config['root'], '/') . '(' . sprintf(preg_quote($config['board_path'], '/'), $config['board_regex']) . ')/u', '<a $1href="?/$4', $this->body); } }
/** * Script to make a nice textual image, vertical writing. */ function gd_text_script() { if (!function_exists('imagefontwidth')) { return; } $text = get_param('text'); if (get_magic_quotes_gpc()) { $text = stripslashes($text); } $font_size = array_key_exists('size', $_GET) ? intval($_GET['size']) : 8; $font = get_param('font', get_file_base() . '/data/fonts/' . filter_naughty(get_param('font', 'FreeMonoBoldOblique')) . '.ttf'); if (!function_exists('imagettftext') || !array_key_exists('FreeType Support', gd_info()) || @imagettfbbox(26.0, 0.0, get_file_base() . '/data/fonts/Vera.ttf', 'test') === false || strlen($text) == 0) { $pfont = 4; $height = intval(imagefontwidth($pfont) * strlen($text) * 1.05); $width = imagefontheight($pfont); $baseline_offset = 0; } else { $scale = 4; list(, , $height, , , , , $width) = imagettfbbox(floatval($font_size * $scale), 0.0, $font, $text); $baseline_offset = 8 * intval(ceil(floatval($font_size) / 8.0)); $width = max($width, -$width); $width += $baseline_offset; $height += $font_size * $scale; // This is just due to inaccuracy in imagettfbbox, possibly due to italics not being computed correctly list(, , $real_height, , , , , $real_width) = imagettfbbox(floatval($font_size), 0.0, $font, $text); $real_width = max($real_width, -$real_width); $real_width += $baseline_offset / $scale; $real_height += 2; } if ($width == 0) { $width = 1; } if ($height == 0) { $height = 1; } $trans_color = array_key_exists('color', $_GET) ? $_GET['color'] : 'FF00FF'; $img = imagecreatetruecolor($width, $height + $baseline_offset); imagealphablending($img, false); $black_color = array_key_exists('fgcolor', $_GET) ? $_GET['fgcolor'] : '000000'; $black = imagecolorallocate($img, hexdec(substr($black_color, 0, 2)), hexdec(substr($black_color, 2, 2)), hexdec(substr($black_color, 4, 2))); if (!function_exists('imagettftext') || !array_key_exists('FreeType Support', gd_info()) || @imagettfbbox(26.0, 0.0, get_file_base() . '/data/fonts/Vera.ttf', 'test') === false || strlen($text) == 0) { $trans = imagecolorallocate($img, hexdec(substr($trans_color, 0, 2)), hexdec(substr($trans_color, 2, 2)), hexdec(substr($trans_color, 4, 2))); imagefill($img, 0, 0, $trans); imagecolortransparent($img, $trans); imagestringup($img, $pfont, 0, $height - 1 - intval($height * 0.02), $text, $black); } else { if (function_exists('imagecolorallocatealpha')) { $trans = imagecolorallocatealpha($img, hexdec(substr($trans_color, 0, 2)), hexdec(substr($trans_color, 2, 2)), hexdec(substr($trans_color, 4, 2)), 127); } else { $trans = imagecolorallocate($img, hexdec(substr($trans_color, 0, 2)), hexdec(substr($trans_color, 2, 2)), hexdec(substr($trans_color, 4, 2))); } imagefilledrectangle($img, 0, 0, $width, $height, $trans); if (@$_GET['angle'] != 90) { require_code('character_sets'); $text = utf8tohtml(convert_to_internal_encoding($text, strtolower(get_param('charset', get_charset())), 'utf-8')); if (strpos($text, '&#') === false) { $previous = mixed(); $nxpos = 0; for ($i = 0; $i < strlen($text); $i++) { if (!is_null($previous)) { list(, , $rx1, , $rx2) = imagettfbbox(floatval($font_size * $scale), 0.0, $font, $previous); $nxpos += max($rx1, $rx2) + 3; } imagettftext($img, floatval($font_size * $scale), 270.0, $baseline_offset, $nxpos, $black, $font, $text[$i]); $previous = $text[$i]; } } else { imagettftext($img, floatval($font_size * $scale), 270.0, 4, 0, $black, $font, $text); } } else { imagettftext($img, floatval($font_size * $scale), 90.0, $width - $baseline_offset, $height, $black, $font, $text); } $dest_img = imagecreatetruecolor($real_width + intval(ceil(floatval($baseline_offset) / floatval($scale))), $real_height); imagealphablending($dest_img, false); imagecopyresampled($dest_img, $img, 0, 0, 0, 0, $real_width + intval(ceil(floatval($baseline_offset) / floatval($scale))), $real_height, $width, $height); // Sizes down, for simple antialiasing-like effect imagedestroy($img); $img = $dest_img; if (function_exists('imagesavealpha')) { imagesavealpha($img, true); } } header('Content-Type: image/png'); imagepng($img); imagedestroy($img); }
function markup(&$body, $track_cites = false, $op = false) { global $board, $config, $markup_urls; $modifiers = extract_modifiers($body); $body = preg_replace('@<tinyboard (?!escape )([\\w\\s]+)>(.+?)</tinyboard>@us', '', $body); $body = preg_replace('@<(tinyboard) escape ([\\w\\s]+)>@i', '<$1 $2>', $body); if (isset($modifiers['raw html']) && $modifiers['raw html'] == '1') { return array(); } $body = str_replace("\r", '', $body); $body = utf8tohtml($body); if (mysql_version() < 50503) { $body = mb_encode_numericentity($body, array(0x10000, 0xffffff, 0, 0xffffff), 'UTF-8'); } foreach ($config['markup'] as $markup) { if (is_string($markup[1])) { $body = preg_replace($markup[0], $markup[1], $body); } elseif (is_callable($markup[1])) { $body = preg_replace_callback($markup[0], $markup[1], $body); } } if ($config['markup_urls']) { $markup_urls = array(); $body = preg_replace_callback('/((?:https?:\\/\\/|ftp:\\/\\/|irc:\\/\\/)[^\\s<>()"]+?(?:\\([^\\s<>()"]*?\\)[^\\s<>()"]*?)*)((?:\\s|<|>|"|\\.||\\]|!|\\?|,|,|")*(?:[\\s<>()"]|$))/', 'markup_url', $body, -1, $num_links); if ($num_links > $config['max_links']) { error($config['error']['toomanylinks']); } if ($num_links < $config['min_links'] && $op) { error(sprintf($config['error']['notenoughlinks'], $config['min_links'])); } } if ($config['markup_repair_tidy']) { $body = str_replace(' ', ' ', $body); } if ($config['auto_unicode']) { $body = unicodify($body); if ($config['markup_urls']) { foreach ($markup_urls as &$url) { $body = str_replace(unicodify($url), $url, $body); } } } $tracked_cites = array(); // Cites if (isset($board) && preg_match_all('/(^|\\s)>>(\\d+?)([\\s,.)?]|$)/m', $body, $cites, PREG_SET_ORDER | PREG_OFFSET_CAPTURE)) { if (count($cites[0]) > $config['max_cites']) { error($config['error']['toomanycites']); } $skip_chars = 0; $body_tmp = $body; $search_cites = array(); foreach ($cites as $matches) { $search_cites[] = '`id` = ' . $matches[2][0]; } $search_cites = array_unique($search_cites); $query = query(sprintf('SELECT `thread`, `id` FROM ``posts_%s`` WHERE ' . implode(' OR ', $search_cites), $board['uri'])) or error(db_error()); $cited_posts = array(); while ($cited = $query->fetch(PDO::FETCH_ASSOC)) { $cited_posts[$cited['id']] = $cited['thread'] ? $cited['thread'] : false; } foreach ($cites as $matches) { $cite = $matches[2][0]; // preg_match_all is not multibyte-safe foreach ($matches as &$match) { $match[1] = mb_strlen(substr($body_tmp, 0, $match[1])); } if (isset($cited_posts[$cite])) { $replacement = '<a onclick="highlightReply(\'' . $cite . '\', event);" href="' . $config['root'] . $board['dir'] . $config['dir']['res'] . ($cited_posts[$cite] ? $cited_posts[$cite] : $cite) . '.html#' . $cite . '">' . '>>' . $cite . '</a>'; $body = mb_substr_replace($body, $matches[1][0] . $replacement . $matches[3][0], $matches[0][1] + $skip_chars, mb_strlen($matches[0][0])); $skip_chars += mb_strlen($matches[1][0] . $replacement . $matches[3][0]) - mb_strlen($matches[0][0]); if ($track_cites && $config['track_cites']) { $tracked_cites[] = array($board['uri'], $cite); } } } } // Cross-board linking if (preg_match_all('/(^|\\s)>>>\\/(' . $config['board_regex'] . 'f?)\\/(\\d+)?([\\s,.)?]|$)/um', $body, $cites, PREG_SET_ORDER | PREG_OFFSET_CAPTURE)) { if (count($cites[0]) > $config['max_cites']) { error($config['error']['toomanycross']); } $skip_chars = 0; $body_tmp = $body; if (isset($cited_posts)) { // Carry found posts from local board >>X links foreach ($cited_posts as $cite => $thread) { $cited_posts[$cite] = $config['root'] . $board['dir'] . $config['dir']['res'] . ($thread ? $thread : $cite) . '.html#' . $cite; } $cited_posts = array($board['uri'] => $cited_posts); } else { $cited_posts = array(); } $crossboard_indexes = array(); $search_cites_boards = array(); foreach ($cites as $matches) { $_board = $matches[2][0]; $cite = @$matches[3][0]; if (!isset($search_cites_boards[$_board])) { $search_cites_boards[$_board] = array(); } $search_cites_boards[$_board][] = $cite; } $tmp_board = $board['uri']; foreach ($search_cites_boards as $_board => $search_cites) { $clauses = array(); foreach ($search_cites as $cite) { if (!$cite || isset($cited_posts[$_board][$cite])) { continue; } $clauses[] = '`id` = ' . $cite; } $clauses = array_unique($clauses); if ($board['uri'] != $_board) { if (!openBoard($_board)) { continue; } // Unknown board } if (!empty($clauses)) { $cited_posts[$_board] = array(); $query = query(sprintf('SELECT `thread`, `id` FROM ``posts_%s`` WHERE ' . implode(' OR ', $clauses), $board['uri'])) or error(db_error()); while ($cite = $query->fetch(PDO::FETCH_ASSOC)) { $cited_posts[$_board][$cite['id']] = $config['root'] . $board['dir'] . $config['dir']['res'] . ($cite['thread'] ? $cite['thread'] : $cite['id']) . '.html#' . $cite['id']; } } $crossboard_indexes[$_board] = $config['root'] . $board['dir'] . $config['file_index']; } // Restore old board if (!$tmp_board) { unset($GLOBALS['board']); } elseif ($board['uri'] != $tmp_board) { openBoard($tmp_board); } foreach ($cites as $matches) { $_board = $matches[2][0]; $cite = @$matches[3][0]; // preg_match_all is not multibyte-safe foreach ($matches as &$match) { $match[1] = mb_strlen(substr($body_tmp, 0, $match[1])); } if ($cite) { if (isset($cited_posts[$_board][$cite])) { $link = $cited_posts[$_board][$cite]; $replacement = '<a ' . ($_board == $board['uri'] ? 'onclick="highlightReply(\'' . $cite . '\', event);" ' : '') . 'href="' . $link . '">' . '>>>/' . $_board . '/' . $cite . '</a>'; $body = mb_substr_replace($body, $matches[1][0] . $replacement . $matches[4][0], $matches[0][1] + $skip_chars, mb_strlen($matches[0][0])); $skip_chars += mb_strlen($matches[1][0] . $replacement . $matches[4][0]) - mb_strlen($matches[0][0]); if ($track_cites && $config['track_cites']) { $tracked_cites[] = array($_board, $cite); } } } elseif (isset($crossboard_indexes[$_board])) { $replacement = '<a href="' . $crossboard_indexes[$_board] . '">' . '>>>/' . $_board . '/' . '</a>'; $body = mb_substr_replace($body, $matches[1][0] . $replacement . $matches[4][0], $matches[0][1] + $skip_chars, mb_strlen($matches[0][0])); $skip_chars += mb_strlen($matches[1][0] . $replacement . $matches[4][0]) - mb_strlen($matches[0][0]); } } } $tracked_cites = array_unique($tracked_cites, SORT_REGULAR); if ($config['strip_superfluous_returns']) { $body = preg_replace('/\\s+$/', '', $body); } if ($config['markup_paragraphs']) { $paragraphs = explode("\n", $body); $bodyNew = ""; $tagsOpen = false; // Matches <a>, <a href="" title="">, but not <img/> and returns a $matchOpen = "#<([A-Z][A-Z0-9]*)+(?:(?:\\s+\\w+(?:\\s*=\\s*(?:\".*?\"|'.*?'|[^'\">\\s]+))?)+\\s*|\\s*)>#i"; // Matches </a> returns a $matchClose = "#</([A-Z][A-Z0-9]*/?)>#i"; $tagsOpened = array(); $tagsClosed = array(); foreach ($paragraphs as $paragraph) { // Determine if RTL based on content of line. if (strlen(trim($paragraph)) > 0) { $paragraphDirection = is_rtl($paragraph) ? "rtl" : "ltr"; } else { $paragraphDirection = "empty"; } // Add in a quote class for >quotes. if (strpos($paragraph, ">") === 0) { $quoteClass = "quote"; } else { $quoteClass = ""; } // If tags are closed, start a new line. if ($tagsOpen === false) { $bodyNew .= "<p class=\"body-line {$paragraphDirection} {$quoteClass}\">"; } // If tags are open, add the paragraph to our temporary holder instead. if ($tagsOpen !== false) { $tagsOpen .= $paragraph; // Recheck tags to see if we've formed a complete tag with this latest line. if (preg_match_all($matchOpen, $tagsOpen, $tagsOpened) === preg_match_all($matchClose, $tagsOpen, $tagsClosed)) { sort($tagsOpened[1]); sort($tagsClosed[1]); // Double-check to make sure these are the same tags. if (count(array_diff_assoc($tagsOpened[1], $tagsClosed[1])) === 0) { // Tags are closed! \o/ $bodyNew .= $tagsOpen; $tagsOpen = false; } } } else { if (preg_match_all($matchOpen, $paragraph, $tagsOpened) === preg_match_all($matchClose, $paragraph, $tagsClosed)) { sort($tagsOpened[1]); sort($tagsClosed[1]); // Double-check to make sure these are the same tags. if (count(array_diff_assoc($tagsOpened[1], $tagsClosed[1])) === 0) { $bodyNew .= $paragraph; } } else { // Tags are open! $tagsOpen = $paragraph; } } // If tags are open, do not close it. if (!$tagsOpen) { $bodyNew .= "</p>"; } else { if ($tagsOpen !== false) { $tagsOpen .= "<br />"; } } } if ($tagsOpen !== false) { $bodyNew .= $tagsOpen; } $body = $bodyNew; } else { $body = preg_replace("/^\\s*>.*\$/m", '<span class="quote">$0</span>', $body); $body = preg_replace("/\n/", '<br/>', $body); } if ($config['markup_repair_tidy']) { $tidy = new tidy(); $body = str_replace("\t", '	', $body); $body = $tidy->repairString($body, array('doctype' => 'omit', 'bare' => true, 'literal-attributes' => true, 'indent' => false, 'show-body-only' => true, 'wrap' => 0, 'output-bom' => false, 'output-html' => true, 'newline' => 'LF', 'quiet' => true), 'utf8'); $body = str_replace("\n", '', $body); } // replace tabs with 8 spaces $body = str_replace("\t", '	', $body); return $tracked_cites; }
function markup(&$body, $track_cites = false) { global $board, $config, $markup_urls; $body = utf8tohtml($body); if ($config['wiki_markup']) { $body = preg_replace("/(^|\n)==(.+?)==\n?/m", "<span class=\"heading\">\$2</span>", $body); $body = preg_replace("/'''(.+?)'''/m", "<strong>\$1</strong>", $body); $body = preg_replace("/''(.+?)''/m", "<em>\$1</em>", $body); $body = preg_replace("/\\*\\*(.+?)\\*\\*/m", "<span class=\"spoiler\">\$1</span>", $body); } if ($config['markup_urls']) { $markup_urls = array(); $body = preg_replace_callback($config['url_regex'], 'markup_url', $body, -1, $num_links); if ($num_links > $config['max_links']) { error($config['error']['toomanylinks']); } } if ($config['auto_unicode']) { $body = unicodify($body); foreach ($markup_urls as &$url) { $body = str_replace(unicodify($url), $url, $body); } } // replace tabs with 8 spaces $body = str_replace("\t", ' ', $body); $tracked_cites = array(); // Cites if (isset($board) && preg_match_all('/(^|\\s)>>(\\d+?)([\\s,.)?]|$)/', $body, $cites)) { if (count($cites[0]) > $config['max_cites']) { error($config['error']['toomanycites']); } for ($index = 0; $index < count($cites[0]); $index++) { $cite = $cites[2][$index]; $query = prepare(sprintf("SELECT `thread`,`id` FROM `posts_%s` WHERE `id` = :id LIMIT 1", $board['uri'])); $query->bindValue(':id', $cite); $query->execute() or error(db_error($query)); if ($post = $query->fetch()) { $replacement = '<a onclick="highlightReply(\'' . $cite . '\');" href="' . $config['root'] . $board['dir'] . $config['dir']['res'] . ($post['thread'] ? $post['thread'] : $post['id']) . '.html#' . $cite . '">' . '>>' . $cite . '</a>'; $body = str_replace($cites[0][$index], $cites[1][$index] . $replacement . $cites[3][$index], $body); if ($track_cites && $config['track_cites']) { $tracked_cites[] = array($board['uri'], $post['id']); } } } } // Cross-board linking if (preg_match_all('/(^|\\s)>>>\\/(\\w+?)\\/(\\d+)?([\\s,.)?]|$)/', $body, $cites)) { if (count($cites[0]) > $config['max_cites']) { error($config['error']['toomanycross']); } for ($index = 0; $index < count($cites[0]); $index++) { $_board = $cites[2][$index]; $cite = @$cites[3][$index]; // Temporarily store board information because it will be overwritten $tmp_board = $board['uri']; // Check if the board exists, and load settings if (openBoard($_board)) { if ($cite) { $query = prepare(sprintf("SELECT `thread`,`id` FROM `posts_%s` WHERE `id` = :id LIMIT 1", $board['uri'])); $query->bindValue(':id', $cite); $query->execute() or error(db_error($query)); if ($post = $query->fetch()) { $replacement = '<a onclick="highlightReply(\'' . $cite . '\');" href="' . $config['root'] . $board['dir'] . $config['dir']['res'] . ($post['thread'] ? $post['thread'] : $post['id']) . '.html#' . $cite . '">' . '>>>/' . $_board . '/' . $cite . '</a>'; $body = str_replace($cites[0][$index], $cites[1][$index] . $replacement . $cites[4][$index], $body); if ($track_cites && $config['track_cites']) { $tracked_cites[] = array($board['uri'], $post['id']); } } } else { $replacement = '<a href="' . $config['root'] . $board['dir'] . $config['file_index'] . '">' . '>>>/' . $_board . '/' . '</a>'; $body = str_replace($cites[0][$index], $cites[1][$index] . $replacement . $cites[4][$index], $body); } } // Restore main board settings openBoard($tmp_board); } } $body = str_replace("\r", '', $body); $body = preg_replace("/(^|\n)([\\s]+)?(>)([^\n]+)?(\$|\n)/m", '$1$2<span class="quote">$3$4</span>$5', $body); if ($config['strip_superfluous_returns']) { $body = preg_replace('/\\s+$/', '', $body); } $body = preg_replace("/\n/", '<br/>', $body); return $tracked_cites; }