aboutsummaryrefslogtreecommitdiff
path: root/cgi/weabot.py
diff options
context:
space:
mode:
Diffstat (limited to 'cgi/weabot.py')
-rwxr-xr-xcgi/weabot.py235
1 files changed, 119 insertions, 116 deletions
diff --git a/cgi/weabot.py b/cgi/weabot.py
index 38efa7c..720916d 100755
--- a/cgi/weabot.py
+++ b/cgi/weabot.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python2
+#!/usr/bin/env python3
# coding=utf-8
# Remove the first line to use the env command to locate python
@@ -9,8 +9,8 @@ import datetime
import random
import cgi
import logging
-import _mysql
-from Cookie import SimpleCookie
+from MySQLdb import _mysql
+from http.cookies import SimpleCookie
import tenjin
import manage
@@ -23,7 +23,7 @@ from formatting import *
from post import *
from img import *
-__version__ = "0.8.10"
+__version__ = "0.10.0"
# Set to True to disable weabot's exception routing and enable profiling
_DEBUG = False
@@ -35,7 +35,7 @@ class weabot(object):
def __init__(self, environ, start_response):
global _DEBUG
- logging.basicConfig(filename='weabot.log', format='%(asctime)s %(levelname)s %(message)s', level=logging.INFO)
+ logging.basicConfig(filename='weabot.log', format='%(asctime)s %(levelname)s %(message)s', level=logging.DEBUG)
self.environ = environ
if self.environ["PATH_INFO"].startswith("/weabot.py/"):
@@ -61,9 +61,9 @@ class weabot(object):
else:
try:
self.run()
- except UserError, message:
+ except UserError as message:
self.error(message)
- except Exception, inst:
+ except Exception as inst:
logging.exception(inst)
import sys
@@ -74,11 +74,12 @@ class weabot(object):
self.exception(type(inst), inst, detail)
# close database and finish
- CloseDb()
+ #CloseDb()
def __iter__(self):
self.handleResponse()
self.start("200 OK", self.headers)
+ self.output = self.output.encode('utf-8')
yield self.output
def error(self, message):
@@ -115,7 +116,7 @@ class weabot(object):
def handleResponse(self):
if self._newcookies:
- for newcookie in self._newcookies.values():
+ for newcookie in list(self._newcookies.values()):
self.headers.append(
("Set-Cookie", newcookie.output(header="")))
@@ -129,8 +130,8 @@ class weabot(object):
caught = False
if Settings.FULL_MAINTENANCE:
- raise UserError, _(
- "%s is currently under maintenance. We'll be back.") % Settings.SITE_TITLE
+ raise UserError(_(
+ "%s is currently under maintenance. We'll be back.") % Settings.SITE_TITLE)
if len(path_split) > 1:
if path_split[1] == "post":
@@ -138,7 +139,7 @@ class weabot(object):
caught = True
if 'password' not in self.formdata:
- raise UserError, "El request está incompleto."
+ raise UserError("El request está incompleto.")
# let's get all the POST data we need
ip = self.environ["REMOTE_ADDR"]
@@ -156,7 +157,7 @@ class weabot(object):
oek_file = self.formdata.get('oek_file')
password = self.formdata.get('password', '')
noimage = self.formdata.get('noimage')
- mobile = ("mobile" in self.formdata.keys())
+ mobile = ("mobile" in self.formdata)
# call post function
(post_url, ttaken, unused) = self.make_post(ip, boarddir, parent, trap1, trap2, name,
@@ -202,7 +203,7 @@ class weabot(object):
board = setBoard(path_split[2])
caught = True
if board['board_type'] != '1':
- raise UserError, "No disponible para esta sección."
+ raise UserError("No disponible para esta sección.")
self.output = threadList(0)
elif path_split[1] == "mobile":
OpenDb()
@@ -261,18 +262,15 @@ class weabot(object):
caught = True
# Redirect to ban page if user is banned
- if addressIsBanned(self.environ['REMOTE_ADDR'], board["dir"], blind_only=True):
- raise UserError, '<meta http-equiv="refresh" content="0; url=/cgi/banned/%s">' % board["dir"]
+ if Settings.ENABLE_BANS and addressIsBanned(self.environ['REMOTE_ADDR'], board["dir"], blind_only=True):
+ raise UserError('<meta http-equiv="refresh" content="0; url=/cgi/banned/%s">' % board["dir"])
if len(path_split) > 4 and path_split[4] and board['board_type'] == '1':
- # try:
self.output = dynamicRead(int(path_split[3]), path_split[4], True)
- # except:
- # self.output = threadPage(path_split[3], True)
- elif board['board_type'] == '1':
- self.output = threadPage(0, True, path_split[3])
+ elif board['board_type'] == 1:
+ self.output = threadPage(0, True, int(path_split[3]))
else:
- self.output = threadPage(path_split[3], True)
+ self.output = threadPage(int(path_split[3]), True)
elif path_split[1] == "catalog":
OpenDb()
board = setBoard(path_split[2])
@@ -334,15 +332,15 @@ class weabot(object):
bans = FetchAll("SELECT * FROM `bans` WHERE INET6_ATON('"+self.environ["REMOTE_ADDR"]+"') BETWEEN `ipstart` AND `ipend`")
if bans:
for ban in bans:
- if ban["boards"] != "":
+ if ban["boards"]:
boards = pickle.loads(ban["boards"])
- if ban["boards"] == "" or path_split[2] in boards:
+ if ban["boards"] or path_split[2] in boards:
caught = True
if ban["boards"]:
boards_str = '/' + '/, /'.join(boards) + '/'
else:
boards_str = 'todas'
- if ban["until"] != "0":
+ if ban["until"]:
expire = formatTimestamp(ban["until"])
else:
expire = ""
@@ -374,8 +372,8 @@ class weabot(object):
board = setBoard(path_split[2])
# Redirect to ban page if user is banned
- if addressIsBanned(self.environ['REMOTE_ADDR'], board["dir"], blind_only=True):
- raise UserError, '<meta http-equiv="refresh" content="0; url=/cgi/banned/%s">' % board["dir"]
+ if Settings.ENABLE_BANS and addressIsBanned(self.environ['REMOTE_ADDR'], board["dir"], blind_only=True):
+ raise UserError('<meta http-equiv="refresh" content="0; url=/cgi/banned/%s">' % board["dir"])
self.output = dynamicRead(int(path_split[3]), path_split[4])
elif path_split[1] == "preview":
@@ -386,7 +384,7 @@ class weabot(object):
message = format_post(
self.formdata["message"], self.environ["REMOTE_ADDR"], self.formdata["parentid"])
self.output = message
- except Exception, messagez:
+ except Exception as messagez:
self.output = "Error: " + \
str(messagez) + " : " + str(self.formdata)
elif path_split[1] == "mod":
@@ -400,11 +398,16 @@ class weabot(object):
# Redirect the user back to the front page
self.output += '<html xmlns="http://www.w3.org/1999/xhtml"><body><meta http-equiv="refresh" content="0;url=%s" /><p>--&gt; --&gt; --&gt;</p></body></html>' % Settings.HOME_URL
+ CloseDb()
+
def make_post(self, ip, boarddir, parent, trap1, trap2, name, email, subject, message, file, file_original, spoil, oek_file, password, noimage, mobile):
- _STARTTIME = time.clock() # Comment if not debug
+ _STARTTIME = time.process_time() # Comment if not debug
- if hostIsBanned(ip):
- raise UserError, "Sufijo de host en lista negra."
+ if Settings.PROXY_BANS and ip not in Settings.PROXY_WHITELIST and (boarddir not in Settings.EXCLUDE_GLOBAL_BANS):
+ if addressIsTor(ip) or addressIsProxy(ip) or addressIsBannedCountry(ip) or not addressIsES(ip):
+ raise UserError("Proxy prohibido.")
+ if hostIsBanned(ip):
+ raise UserError("Sufijo de host en lista negra.")
# open database
OpenDb()
@@ -412,25 +415,21 @@ class weabot(object):
# set the board
board = setBoard(boarddir)
- if Settings.PROXY_BAN and (board["dir"] not in Settings.EXCLUDE_GLOBAL_BANS):
- if addressIsTor(ip) or addressIsProxy(ip) or addressIsBannedCountry(ip) or not addressIsES(ip):
- raise UserError, "Proxy prohibido."
-
# check length of fields
if len(name) > 50:
- raise UserError, "El campo de nombre es muy largo."
+ raise UserError("El campo de nombre es muy largo.")
if len(email) > 50:
- raise UserError, "El campo de e-mail es muy largo."
+ raise UserError("El campo de e-mail es muy largo.")
if len(subject) > 100:
- raise UserError, "El campo de asunto es muy largo."
+ raise UserError("El campo de asunto es muy largo.")
if len(message) > 8000:
- raise UserError, "El campo de mensaje es muy largo."
+ raise UserError("El campo de mensaje es muy largo.")
if message.count('\n') > 50:
- raise UserError, "El mensaje tiene muchos saltos de línea."
+ raise UserError("El mensaje tiene muchos saltos de línea.")
# anti-spam trap
if trap1 or trap2:
- raise UserError, "Te quedan tres días de vida."
+ raise UserError("Te quedan tres días de vida.")
# Create a single datetime now so everything syncs up
t = time.time()
@@ -441,14 +440,14 @@ class weabot(object):
regenerateAccess()
# Redirect to ban page if user is banned
- if addressIsBanned(ip, board["dir"]):
- raise UserError, '<meta http-equiv="refresh" content="0; url=/cgi/banned/%s">' % board["dir"]
+ if Settings.ENABLE_BANS and addressIsBanned(ip, board["dir"]):
+ raise UserError('<meta http-equiv="refresh" content="0; url=/cgi/banned/%s">' % board["dir"])
# Disallow posting if the site OR board is in maintenance
if Settings.MAINTENANCE and board["dir"] != 'polka':
- raise UserError, _("%s is currently under maintenance. We'll be back.") % Settings.SITE_TITLE
+ raise UserError(_("%s is currently under maintenance. We'll be back.") % Settings.SITE_TITLE)
if board["locked"] == '1':
- raise UserError, _("This board is closed. You can't post in it.")
+ raise UserError(_("This board is closed. You can't post in it."))
# create post object
post = Post(board["id"])
@@ -465,7 +464,7 @@ class weabot(object):
post["parentid"] = parent_post['id']
post["bumped"] = parent_post['bumped']
if parent_post['locked'] == '1':
- raise UserError, _("The thread is closed. You can't post in it.")
+ raise UserError(_("The thread is closed. You can't post in it."))
# check if the user is flooding
flood_check(t, post, board["id"])
@@ -550,10 +549,10 @@ class weabot(object):
# compatibility : old id function
if 'id' in parent_post["email"]:
- board["useid"] = '3'
+ board["useid"] = 3
if 'id' in post["email"]:
- board["useid"] = '3'
+ board["useid"] = 3
if extend:
try:
@@ -591,35 +590,35 @@ class weabot(object):
tim = post["timestamp"]
# make ID hash
- if board["useid"] != '0':
+ if board["useid"]:
post["timestamp_formatted"] += ' ID:' + iphash(ip, post, tim, board["useid"], mobile,
self.environ["HTTP_USER_AGENT"], cap_id, hide_end, (board["countrycode"] in ['1', '2']))
# use for future file checks
- xfile = (file or oek_file)
+ xfile = (file is not None or oek_file)
# textboard inforcements (change it to settings maybe?)
- if board['board_type'] == '1':
+ if board['board_type'] == 1:
if not post["parentid"] and not post["subject"]:
- raise UserError, _(
- "You must enter a title to create a thread.")
+ raise UserError(_(
+ "You must enter a title to create a thread."))
if not post["message"]:
- raise UserError, _("Please enter a message.")
+ raise UserError(_("Please enter a message."))
else:
if not post["parentid"] and not xfile and not noimage:
- raise UserError, _(
- "You must upload an image first to create a thread.")
+ raise UserError(_(
+ "You must upload an image first to create a thread."))
if not xfile and not post["message"]:
- raise UserError, _(
- "Please enter a message or upload an image to reply.")
+ raise UserError(_(
+ "Please enter a message or upload an image to reply."))
# check if this post is allowed
if post["parentid"]:
- if file and board['allow_image_replies'] == '0':
- raise UserError, _("Image replies not allowed.")
+ if file and not board['allow_image_replies']:
+ raise UserError(_("Image replies not allowed."))
else:
- if file and board['allow_images'] == '0':
- raise UserError, _("No images allowed.")
+ if file and not board['allow_images']:
+ raise UserError(_("No images allowed."))
# use default values when missing / remove sage from wrong fields
if (not post["name"] and not post["tripcode"]) or (post["name"].lower() == 'sage'):
@@ -637,7 +636,7 @@ class weabot(object):
with open(fname, 'rb') as f:
file = f.read()
except:
- raise UserError, "Imposible leer la imagen oekaki."
+ raise UserError("Imposible leer la imagen oekaki.")
if file and not noimage:
post = processImage(post, file, t, file_original,
@@ -700,7 +699,7 @@ class weabot(object):
host = getHost(ip)
if host:
- for k, v in isps.iteritems():
+ for k, v in isps.items():
if k in host:
host_nick = v
break
@@ -708,7 +707,7 @@ class weabot(object):
slips.append(host_nick)
# hash
- if board["slip"] in ['1', '3']:
+ if board["slip"] in [1, 3]:
if hide_end:
slips.append(
'-'.join((getMD5(ip + post["name"])[:4], '****')))
@@ -720,7 +719,7 @@ class weabot(object):
'-'.join((getMD5(ip)[:4], getMD5(self.environ["HTTP_USER_AGENT"])[:4])))
# host
- if board["slip"] == '2':
+ if board["slip"] == 2:
if hide_end:
host = '★'
else:
@@ -743,7 +742,7 @@ class weabot(object):
slips.append(host)
# IP
- if board["slip"] == '3':
+ if board["slip"] == 3:
if hide_end:
host = '[*.*.*.*]'
else:
@@ -755,7 +754,7 @@ class weabot(object):
post["tripcode"] += " (%s)" % ' '.join(slips)
# country code
- if board["countrycode"] == '1':
+ if board["countrycode"] == 1:
if hide_end or addressIsTor(ip):
country = '??'
else:
@@ -763,7 +762,7 @@ class weabot(object):
post["name"] += " <em>[%s]</em>" % country
# set expiration date if necessary
- if board["maxage"] != '0' and not post["parentid"]:
+ if board["maxage"] != 0 and not post["parentid"]:
if board["dir"] == '2d':
date_format = '%m月%d日'
date_format_y = '%Y年%m月'
@@ -784,7 +783,7 @@ class weabot(object):
if board["dir"] == 'noticias':
# check if there's at least one link
if "<a href" not in post["message"]:
- raise UserError, "Al momento de crear un hilo en esta sección necesitas incluír al menos 1 link como fuente en tu mensaje."
+ raise UserError("Al momento de crear un hilo en esta sección necesitas incluír al menos 1 link como fuente en tu mensaje.")
# insert icon if needed
img_src = '<img src="%s" alt="ico" /><br />' % getRandomIco()
@@ -797,11 +796,11 @@ class weabot(object):
trimThreads()
# fix null references when creating thread
- if board["board_type"] == '1' and not post["parentid"]:
+ if board["board_type"] == 1 and not post["parentid"]:
post["message"] = re.compile(r'<a href="/(\w+)/res/0.html/(.+)"').sub(
r'<a href="/\1/res/'+str(postid)+r'.html/\2"', post["message"])
- UpdateDb("UPDATE `posts` SET message = '%s' WHERE boardid = '%s' AND id = '%s'" % (_mysql.escape_string(
- post["message"]), _mysql.escape_string(board["id"]), _mysql.escape_string(str(postid))))
+ UpdateDb("UPDATE `posts` SET message = %s WHERE boardid = %s AND id = %s",
+ (post["message"], board["id"], postid))
# do operations if replying to a thread (bump, autoclose, update cache)
logging.debug("Updating thread")
@@ -812,13 +811,15 @@ class weabot(object):
# bump if not saged
if 'sage' not in post["email"].lower() and parent_post['locked'] != '2':
- UpdateDb("UPDATE `posts` SET bumped = %d WHERE (`id` = '%s' OR `parentid` = '%s') AND `boardid` = '%s'" % (post["timestamp"], post["parentid"], post["parentid"], board["id"]))
+ UpdateDb("UPDATE `posts` SET bumped = %s WHERE (`id` = %s OR `parentid` = %s) AND `boardid` = %s",
+ (post["timestamp"], post["parentid"], post["parentid"], board["id"]))
# check if thread must be closed
autoclose_thread(post["parentid"], t, thread_length)
# update final attributes (length and last post)
- UpdateDb("UPDATE `posts` SET length = %d, last = %d WHERE `id` = '%s' AND `boardid` = '%s'" % (thread_length, post["timestamp"], post["parentid"], board["id"]))
+ UpdateDb("UPDATE `posts` SET length = %s, last = %s WHERE `id` = %s AND `boardid` = %s",
+ (thread_length, post["timestamp"], post["parentid"], board["id"]))
# update cache
threadUpdated(post["parentid"])
@@ -829,13 +830,13 @@ class weabot(object):
regenerateHome()
# make page redirect
- ttaken = timeTaken(_STARTTIME, time.clock())
- noko = 'noko' in email.lower() or (board["board_type"] == '1')
+ ttaken = timeTaken(_STARTTIME, time.process_time())
+ noko = 'noko' in email.lower() or (board["board_type"] == 1)
# get new post url
post_url = make_url(postid, post, parent_post or post, noko, mobile)
- if board['secret'] == '0':
+ if not board['secret']:
# add to recent posts
if Settings.ENABLE_RSS:
latestAdd(post, thread_length, postid, parent_post)
@@ -854,33 +855,33 @@ class weabot(object):
board = setBoard(boarddir)
if board["dir"] == '0':
- raise UserError, "No se pueden eliminar mensajes en esta sección."
+ raise UserError("No se pueden eliminar mensajes en esta sección.")
# check if we have a post id and check it's numeric
if not postid:
- raise UserError, "Selecciona uno o más mensajes a eliminar."
+ raise UserError("Selecciona uno o más mensajes a eliminar.")
# make sure we have a password
if not password:
- raise UserError, _("Please enter a password.")
+ raise UserError(_("Please enter a password."))
to_delete = []
if isinstance(postid, list):
- to_delete = [n.value for n in postid]
+ to_delete = [int(n.value) for n in postid]
else:
- to_delete = [postid]
+ to_delete = [int(postid)]
# delete posts
- if board['board_type'] == '1' and len(to_delete) == 1:
+ if board['board_type'] == 1 and len(to_delete) == 1:
# we should be deleting only one (textboard)
# check if it's the last post and delete permanently if so
- deltype = '0'
+ deltype = 0
post = FetchOne("SELECT `id`, `timestamp`, `parentid` FROM `posts` WHERE `boardid` = %s AND `id` = %s LIMIT 1" % (
board["id"], str(to_delete[0])))
- if post['parentid'] != '0':
+ if post['parentid']:
op = get_parent_post(post['parentid'], board['id'])
if op['last'] != post['timestamp']:
- deltype = '1'
+ deltype = 1
deletePost(to_delete[0], password, deltype, imageonly)
latestRemove(post['id'])
@@ -896,10 +897,10 @@ class weabot(object):
deletePost(pid, password, board['recyclebin'], imageonly)
latestRemove(pid)
deleted += 1
- msgs.append('No.%s: Eliminado' % pid)
- except UserError, message:
+ msgs.append('No.%d: Eliminado' % pid)
+ except UserError as message:
errors += 1
- msgs.append('No.%s: %s' % (pid, message))
+ msgs.append('No.%d: %s' % (pid, message))
# regenerate home
if deleted:
@@ -907,8 +908,8 @@ class weabot(object):
# show errors, if any
if errors:
- raise UserError, 'No todos los mensajes pudieron ser eliminados.<br />' + \
- '<br />'.join(msgs)
+ raise UserError('No todos los mensajes pudieron ser eliminados.<br />' + \
+ '<br />'.join(msgs))
# redirect
if imageonly:
@@ -921,7 +922,7 @@ class weabot(object):
def report(self, ip, boarddir, postid, reason, txt, postshow):
# don't allow if the report system is off
if not Settings.REPORTS_ENABLE:
- raise UserError, _('Report system is deactivated.')
+ raise UserError(_('Report system is deactivated.'))
# if there's not a reason, show the report page
if reason is None:
@@ -931,9 +932,9 @@ class weabot(object):
# check reason
if not reason:
- raise UserError, _("Enter a reason.")
+ raise UserError(_("Enter a reason."))
if len(reason) > 100:
- raise UserError, _("Text too long.")
+ raise UserError(_("Text too long."))
# open database
OpenDb()
@@ -942,14 +943,14 @@ class weabot(object):
board = setBoard(boarddir)
# check if he's banned
- if addressIsBanned(ip, board["dir"]):
- raise UserError, _("You're banned.")
+ if Settings.ENABLE_BANS and addressIsBanned(ip, board["dir"]):
+ raise UserError(_("You're banned."))
# check if post exists
post = FetchOne("SELECT `id`, `parentid`, `ip` FROM `posts` WHERE `id` = '%s' AND `boardid` = '%s'" % (
_mysql.escape_string(str(postid)), _mysql.escape_string(board['id'])))
if not post:
- raise UserError, _("Post doesn't exist.")
+ raise UserError(_("Post doesn't exist."))
# generate link
if board["board_type"] == '1':
@@ -989,33 +990,33 @@ class weabot(object):
OpenDb()
# 1 week = 604800
- query_day = FetchAll("SELECT DATE_FORMAT(FROM_UNIXTIME(FLOOR((timestamp-10800)/86400)*86400+86400), \"%Y-%m-%d\"), COUNT(1), COUNT(IF(parentid=0, 1, NULL)) "
+ query_day = FetchAll("SELECT DATE_FORMAT(FROM_UNIXTIME(FLOOR((timestamp-10800)/86400)*86400+86400), \"%Y-%m-%d\") AS date, COUNT(1) AS count, COUNT(IF(parentid=0, 1, NULL)) AS threads "
"FROM posts "
"WHERE (timestamp-10800) > (UNIX_TIMESTAMP()-604800) AND (IS_DELETED = 0) "
"GROUP BY FLOOR((timestamp-10800)/86400) "
- "ORDER BY FLOOR((timestamp-10800)/86400)", 0)
+ "ORDER BY FLOOR((timestamp-10800)/86400)")
- query_count = FetchOne("SELECT COUNT(1), COUNT(NULLIF(file, '')), VERSION() FROM posts", 0)
- total = int(query_count[0])
- total_files = int(query_count[1])
- mysql_ver = query_count[2]
+ query_count = FetchOne("SELECT COUNT(1) AS posts, COUNT(NULLIF(file, '')) AS files, VERSION() AS version FROM posts")
+ total = query_count["posts"]
+ total_files = query_count["files"]
+ mysql_ver = query_count["version"]
- archive_count = FetchOne("SELECT SUM(length) FROM archive", 0)
- total_archived = int(archive_count[0])
+ archive_count = FetchOne("SELECT SUM(length) AS sum FROM archive")
+ total_archived = int(archive_count["sum"])
days = []
- for date, count, threads in query_day[1:]:
- days.append((date, count, threads))
+ for r in query_day[1:]:
+ days.append((r["date"], r["count"], r["threads"]))
- query_b = FetchAll("SELECT id, dir, name FROM boards WHERE boards.secret = 0", 0)
+ query_b = FetchAll("SELECT id, dir, name FROM boards WHERE boards.secret = 0")
boards = []
totalp = 0
- for id, dir, longname in query_b:
- bposts = FetchOne("SELECT COUNT(1) FROM posts "
- "WHERE '"+str(id)+"' = posts.boardid AND timestamp > ( UNIX_TIMESTAMP(DATE(NOW())) - 2419200 )", 0)
- boards.append((dir, longname, int(bposts[0])))
- totalp += int(bposts[0])
+ for b in query_b:
+ bposts = FetchOne("SELECT COUNT(1) AS count FROM posts "
+ "WHERE posts.boardid = %s AND timestamp > ( UNIX_TIMESTAMP(DATE(NOW())) - 2419200 )", (b['id'],))
+ boards.append((b['dir'], b['name'], bposts["count"]))
+ totalp += bposts["count"]
boards = sorted(boards, key=lambda boards: boards[2], reverse=True)
@@ -1069,7 +1070,7 @@ class weabot(object):
if __name__ == "__main__":
- from fcgi import WSGIServer
+ from flup.server.fcgi import WSGIServer
# Psyco is not required, however it will be used if available
try:
@@ -1084,4 +1085,6 @@ if __name__ == "__main__":
except:
pass
- WSGIServer(weabot).run()
+ app = WSGIServer(weabot, debug=True, forceCGI=False)
+ app.run()
+