Hello friend. I haven't read a post from #{IP}, and I only remember for a few months, so:
-#{captcha_q}
- - -EOF - exit 0 -end - - -def fail(msg) - if DEBUG and msg - puts "Content-type: text/plain\n\n" - puts msg - else - redir - end - exit 0 -end - -def redir - File.write('/tmp/x', GOTO) - puts 'Status: 302 Found' - puts "Location: #{GOTO}#comment-section\n\n" - exit(0) -end - - -def bn(*args) - File.basename *args -end - - -###### begin error checking & arg parsing ###### -cgi = CGI.new -IP = cgi.remote_addr - -if cgi.has_key?('goto') - GOTO = cgi['goto'] -else - GOTO = '/' - fail['redir to /'] -end - -if (cgi.has_key?('url') && cgi['url'] != "") || ! cgi.has_key?('comment') - fail["comment not in form or url in form. cgi.params: #{cgi.params}"] -end - -COMMENT_TXT = cgi["comment"] - - -if COMMENT_TXT.length > 1000 or GOTO.length > 150 - fail['length of comment or goto is too great'] -end - - -captchad = false -if cgi.has_key?('answer') && cgi.has_key?('question') - if cgi['answer'].downcase !~ /^#{CAPTCHA.to_h[cgi['question']]}$/ - do_captcha - end - captchad = true -end - - --> { - found = false - Dir.foreach('blog') do |entry| - next if ['.','..'].any? { |f| f == entry } - if GOTO == 'blog/' + entry - found = true - break - end - end - fail['goto entry not found'] unless found -}[] -######### end error checking & arg parsing ######## - - -$db = db_init -state = nil -WHITELIST_CUTOFF = NOW - 4*DAY - - -####### begin: state for ips we've seen before ####### -[[5, 60], # 1 min - [10, 60*5], # 5 min - [20, 60*60], # 60 min - [30, 60*60*24], # 1 day - [60, 60*60*24*7]] # 1 week - .each do |max_posts, date| - - if $db.execute(<<-SQL, [NOW - date])[0][0] > max_posts - select count(*) from c - where date > ? and ip = '#{IP}' -SQL - state = 'rate_limited' - end -end - -state ||= 'suspect' if $db.execute(<<-SQL)[0][0] > 0 - select count(*) from c - where ip = '#{IP}' and ( -state = 'banned' or -state = 'rate_limited') -SQL - -unless state - older_date = NOW - DAY*2 - last_moderated = $db.execute(<<-SQL, [older_date])[-1][0] - select date from c - where ip = '#{IP}' and ( - state = 'moderated' or - (date < ? and (state = 'timed' or state = 'known'))) -SQL - last_good = $db.execute(<<-SQL, [older_date])[-1][0] - select date from c - where ip = '#{IP}' and ( - state = 'picked' or - (date < ? and (state = 'timed' or state = 'known'))) -SQL - if last_moderated && last_good - if last_good > last_moderated - state = 'known' - else - # these 2 waiting conditions are not actually needed, - # since waiting is the default, but meh. - state = 'waiting' - end - elsif last_moderated - state = 'waiting' - elsif last_good - state = 'known' - end -end -####### end: state for ips we've seen before ####### - -####### begin: whitelist checking ######### -glob = "../blog/#{'?'*'YYYY-MM-DD-'.length}#{bn GOTO, '.*'}.md" -md_file = Dir[glob][0] -unless state - b = bn(md_file,'.*') - post_date = Time.parse(b[0..DATE_LEN]).to_i - if post_date > WHITELIST_CUTOFF - state = 'timed' - end -end -###### end: whitelist checking ######## - -state ||= 'waiting' - -if state != 'known' && ! captchad - do_captcha -end - - -# states: -# timed -# # was posted a whitelist period, so automatically posted. -# # whitelist periods are per page times when legit comments are -# # much more likely than spam, so we automatically let comments through. - -# known -# # ip posted good comment before: either, one in picked state, or -# # a timed/known comment which is over 2 days old (I saw it and didn't remove -# # it) - -# picked -# # manually marked as a good comment, so publish it. - -# rate_limited -# # posting too much, consider them a spammer. - -# moderated -# # bad comment, but don't ban them - -# banned -# # all comments from this ip dead, new comment's dont even go into the db. - -# waiting -# # waiting for manual moderation, get's posted automatically if there -# # is none in 24 hours - -# suspect -# # had a bad post in the past. does not -# # automatically get posted in time without moderation. - - -# any of the manual states -date = $db.execute(<<-SQL)[0][0] -select max(date) from c where -state = 'moderated' or -state = 'banned' or -state = 'picked' -SQL - -# not the bad automatic states -query = <<-SQL -select count(*) from c where -state != 'rate_limited' and -state != 'suspect' -SQL - - -if date - new_count = $db.execute(query + 'and date > ?',date) -else - new_count = $db.execute(query) -end - -if new_count == 1 - require 'net/smtp' - def send_email(opts={}) - opts[:to] ||= ENV['USER'] - opts[:server] ||= 'localhost' - opts[:from] ||= ENV['USER'] - opts[:from_alias] ||= ENV['USER'] - opts[:subject] ||= "test subject" - opts[:body] ||= "" - - msg = <