diff --git a/inc/config.php b/inc/config.php index d3f43224..2ddbe905 100644 --- a/inc/config.php +++ b/inc/config.php @@ -66,7 +66,10 @@ // Use `host` via shell_exec() to lookup hostnames, avoiding query timeouts. May not work on your system. // Requires safe_mode to be disabled. $config['dns_system'] = false; - + + // Check validity of the reverse DNS of IP addresses. Highly recommended. + $config['fcrdns'] = true; + // When executing most command-line tools (such as `convert` for ImageMagick image processing), add this // to the environment path (seperated by :). $config['shell_path'] = '/usr/local/bin'; diff --git a/inc/functions.php b/inc/functions.php index f9c09085..1b77c191 100644 --- a/inc/functions.php +++ b/inc/functions.php @@ -681,36 +681,38 @@ function listBoards($just_uri = false) { function until($timestamp) { $difference = $timestamp - time(); - if ($difference < 60) { + switch(TRUE){ + case ($difference < 60): return $difference . ' ' . ngettext('second', 'seconds', $difference); - } elseif ($difference < 60*60) { + case ($difference < 3600): //60*60 = 3600 return ($num = round($difference/(60))) . ' ' . ngettext('minute', 'minutes', $num); - } elseif ($difference < 60*60*24) { - return ($num = round($difference/(60*60))) . ' ' . ngettext('hour', 'hours', $num); - } elseif ($difference < 60*60*24*7) { - return ($num = round($difference/(60*60*24))) . ' ' . ngettext('day', 'days', $num); - } elseif ($difference < 60*60*24*365) { - return ($num = round($difference/(60*60*24*7))) . ' ' . ngettext('week', 'weeks', $num); + case ($difference < 86400): //60*60*24 = 86400 + return ($num = round($difference/(3600))) . ' ' . ngettext('hour', 'hours', $num); + case ($difference < 604800): //60*60*24*7 = 604800 + return ($num = round($difference/(86400))) . ' ' . ngettext('day', 'days', $num); + case ($difference < 31536000): //60*60*24*365 = 31536000 + return ($num = round($difference/(604800))) . ' ' . ngettext('week', 'weeks', $num); + default: + return ($num = round($difference/(31536000))) . ' ' . ngettext('year', 'years', $num); } - - return ($num = round($difference/(60*60*24*365))) . ' ' . ngettext('year', 'years', $num); } function ago($timestamp) { $difference = time() - $timestamp; - if ($difference < 60) { + switch(TRUE){ + case ($difference < 60) : return $difference . ' ' . ngettext('second', 'seconds', $difference); - } elseif ($difference < 60*60) { + case ($difference < 3600): //60*60 = 3600 return ($num = round($difference/(60))) . ' ' . ngettext('minute', 'minutes', $num); - } elseif ($difference < 60*60*24) { - return ($num = round($difference/(60*60))) . ' ' . ngettext('hour', 'hours', $num); - } elseif ($difference < 60*60*24*7) { - return ($num = round($difference/(60*60*24))) . ' ' . ngettext('day', 'days', $num); - } elseif ($difference < 60*60*24*365) { - return ($num = round($difference/(60*60*24*7))) . ' ' . ngettext('week', 'weeks', $num); + case ($difference < 86400): //60*60*24 = 86400 + return ($num = round($difference/(3600))) . ' ' . ngettext('hour', 'hours', $num); + case ($difference < 604800): //60*60*24*7 = 604800 + return ($num = round($difference/(86400))) . ' ' . ngettext('day', 'days', $num); + case ($difference < 31536000): //60*60*24*365 = 31536000 + return ($num = round($difference/(604800))) . ' ' . ngettext('week', 'weeks', $num); + default: + return ($num = round($difference/(31536000))) . ' ' . ngettext('year', 'years', $num); } - - return ($num = round($difference/(60*60*24*365))) . ' ' . ngettext('year', 'years', $num); } function displayBan($ban) { @@ -2267,6 +2269,12 @@ function rDNS($ip_addr) { $host = $ip_addr; } + $isip = filter_var($host, FILTER_VALIDATE_IP); + + if ($config['fcrdns'] && !$isip && DNS($host) != $ip_addr) { + $host = $ip_addr; + } + if ($config['cache']['enabled']) cache::set('rdns_' . $ip_addr, $host); diff --git a/inc/instance-config.php b/inc/instance-config.php index 56babbc8..cd9ff574 100644 --- a/inc/instance-config.php +++ b/inc/instance-config.php @@ -127,6 +127,7 @@ $config['additional_javascript'][] = 'js/mobile-style.js'; $config['additional_javascript'][] = 'js/id_highlighter.js'; $config['additional_javascript'][] = 'js/id_colors.js'; + $config['additional_javascript'][] = 'js/threadscroll.js'; $config['font_awesome_css'] = '/netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css'; diff --git a/js/inline.js b/js/inline.js new file mode 100644 index 00000000..1ce0edc3 --- /dev/null +++ b/js/inline.js @@ -0,0 +1,139 @@ +;(function() { + var App = { + cache: {}, + get: function(url, cb) { + var $page = App.cache[url] + if ($page) + return cb($page) + + $.get(url, function(data) { + var $page = $(data) + App.cache[url] = $page + cb($page) + }) + }, + options: { + add: function(key, description, tab) { + tab || (tab = 'general') + + var checked = App.options.get(key) + var $el = $( + '
' + + '' + + '
') + + $el + .find('input') + .prop('checked', checked) + .on('change', App.options.check(key)) + + window.Options.extend_tab(tab, $el) + }, + get: function(key) { + if (localStorage[key]) + return JSON.parse(localStorage[key]) + }, + check: function(key) { + return function(e) { + var val = this.checked + localStorage[key] = JSON.stringify(val) + } + } + } + } + + var inline = function(e) { + e.preventDefault() + + var $root = $(this).closest('.post') + var targetNum = this.textContent.slice(2) + + var srcOP = $root.closest('[id^=thread]').attr('id').match(/\d+/)[0] + + var node, targetOP + var isBacklink = !!this.className + if (isBacklink) { + node = $root.find('> .intro') + targetOP = srcOP + } else { + node = $(this) + targetOP = this.pathname.match(/(\d+).html/)[1] + } + + var link = { + id: 'inline_' + targetNum, + isBacklink: isBacklink, + node: node + } + + var selector = targetNum === targetOP + ? '#op_' + srcOP + : '#reply_' + targetNum + + var $clone = $root.find('#inline_' + targetNum) + if ($clone.length) { + $clone.remove() + $(selector) + .show() + .next() + .show() + return + } + + if (srcOP === targetOP) { + if (targetNum === targetOP) + link.node = link.node.next()// bypass `(OP)` + + var $target = $(selector) + if ($target.length) + return add(link, $target) + } + + var $loading = $('
loading...
') + .attr('id', link.id) + .insertAfter(link.node) + + App.get(this.pathname, function($page) { + $loading.remove() + var $target = $page.find(selector) + add(link, $target) + }) + } + + var add = function(link, $target) { + var $clone = $target.clone(true) + + if (link.isBacklink && App.options.get('hidePost')) + $target + .hide() + .next() + .hide() + + $clone.find('.inline').remove() + $clone.attr({ + "class": 'inline post', + id: link.id, + style: null// XXX remove post hover styling + }) + $clone.insertAfter(link.node) + } + + App.options.add('hidePost', 'Hide inlined backlinked posts') + + $('head').append( + '') + + // don't attach to outbound links + $('.body a:not([rel]), .mentioned a') + .attr('onclick', null)// XXX disable highlightReply + .click(inline) +})() diff --git a/post.php b/post.php index cff1e01c..080891ad 100644 --- a/post.php +++ b/post.php @@ -193,20 +193,6 @@ if (isset($_POST['delete'])) { if (!openBoard($post['board'])) error($config['error']['noboard']); - if (!(($post['op'] && $_POST['post'] == $config['button_newtopic']) || - (!$post['op'] && $_POST['post'] == $config['button_reply']))) - //error($config['error']['bot']); - - // Check the referrer - if ($config['referer_match'] !== false && - (!isset($_SERVER['HTTP_REFERER']) || !preg_match($config['referer_match'], rawurldecode($_SERVER['HTTP_REFERER'])))) - error($config['error']['referer']); - - checkDNSBL(); - - // Check if banned - checkBan($board['uri']); - // Check for CAPTCHA right after opening the board so the "return" link is in there if ($config['recaptcha']) { if (!isset($_POST['recaptcha_challenge_field']) || !isset($_POST['recaptcha_response_field'])) @@ -220,7 +206,21 @@ if (isset($_POST['delete'])) { error($config['error']['captcha']); } } + + if (!(($post['op'] && $_POST['post'] == $config['button_newtopic']) || + (!$post['op'] && $_POST['post'] == $config['button_reply']))) + error($config['error']['bot']); + // Check the referrer + if ($config['referer_match'] !== false && + (!isset($_SERVER['HTTP_REFERER']) || !preg_match($config['referer_match'], rawurldecode($_SERVER['HTTP_REFERER'])))) + error($config['error']['referer']); + + checkDNSBL(); + + // Check if banned + checkBan($board['uri']); + if ($post['mod'] = isset($_POST['mod']) && $_POST['mod']) { require 'inc/mod/auth.php'; if (!$mod) { diff --git a/stylesheets/style.css b/stylesheets/style.css index 2fcc0dd9..da1d99db 100644 --- a/stylesheets/style.css +++ b/stylesheets/style.css @@ -8,10 +8,6 @@ body { padding-right: 4px; } -table * { - margin: 1px; -} - a,a:visited { text-decoration: underline; color: #34345C; @@ -289,6 +285,7 @@ div.post.reply { border-style: none solid solid none; border-color: #B7C5D9; display: inline-block; + max-width: 94%!important; } span.trip { @@ -893,16 +890,21 @@ div.thread:hover { cursor: pointer; } -code > pre { +pre { /* Better code tags */ - background:black; max-width:inherit; + word-wrap:normal; + overflow:auto; + display: block!important; + font-size:9pt; + font-family:monospace; } -code > pre > span.pln { - color: grey; +span.pln { + color:grey; } + @media screen and (min-width: 768px) { p.intro { clear: none;