From b09e855283b8521caa35e1aa0762cf8e986559d4 Mon Sep 17 00:00:00 2001
From: neptune
Date: Fri, 25 Nov 2022 17:59:09 -0300
Subject: Actualizado repo
---
cgi/formatting.py | 54 +-
cgi/framework.py | 10 +
cgi/manage.py | 90 +-
cgi/oekaki.py | 2 +-
cgi/post.py | 88 +-
cgi/templates/board.html | 6 +-
cgi/templates/board.jp.html | 6 +-
cgi/templates/home.html | 2 +
cgi/templates/mobile/board.html | 12 +-
cgi/templates/mobile/txt_thread.html | 2 +-
cgi/templates/paint.html | 8 +-
cgi/weabot.py | 51 +-
static/js/paintbbs/PaintBBS-1.5.15.css | 655 +++
static/js/paintbbs/PaintBBS-1.5.15.js | 9111 ++++++++++++++++++++++++++++++++
static/js/shobon.js | 3 +-
15 files changed, 9948 insertions(+), 152 deletions(-)
create mode 100644 static/js/paintbbs/PaintBBS-1.5.15.css
create mode 100644 static/js/paintbbs/PaintBBS-1.5.15.js
diff --git a/cgi/formatting.py b/cgi/formatting.py
index 97f44a6..33495a3 100644
--- a/cgi/formatting.py
+++ b/cgi/formatting.py
@@ -317,12 +317,23 @@ def close_html(message):
"""
Old retarded version of sanitize_html, it just closes open tags.
"""
- import BeautifulSoup
+ #import BeautifulSoup
- message = message.encode('utf-8')
- soup = BeautifulSoup.BeautifulSoup(message)
+ #message = message.encode('utf-8')
+ #soup = BeautifulSoup.BeautifulSoup(message)
+
+ #return str(soup).replace('
', '').encode('utf-8')
- return str(soup).replace('
', '').encode('utf-8')
+ try:
+ l = message.rindex('<')
+ except ValueError:
+ return message
+ test = message[l:]
+ try:
+ r = test.rindex('>')
+ return message
+ except ValueError:
+ return message[:l]
def sanitize_html(message, decode=True):
@@ -375,27 +386,26 @@ def checkWordfilters(message, ip, board):
if wordfilter["boards"]:
boards = str2boards(wordfilter["boards"])
if not wordfilter["boards"] or board in boards:
- if wordfilter['action'] == '0':
+ if wordfilter['action'] == 0:
if not re.search(wordfilter['from'], message, re.DOTALL | re.IGNORECASE) is None:
raise UserError(wordfilter['reason'])
- elif wordfilter['action'] == '1':
+ elif wordfilter['action'] == 1:
message = re.compile(wordfilter['from'], re.DOTALL | re.IGNORECASE).sub(
wordfilter['to'], message)
- elif wordfilter['action'] == '2':
+ elif wordfilter['action'] == 2:
# Ban
if not re.search(wordfilter['from'], message, re.DOTALL | re.IGNORECASE) is None:
- if wordfilter['seconds'] != '0':
- until = str(timestamp() + int(wordfilter['seconds']))
+ if wordfilter['seconds']:
+ until = timestamp() + int(wordfilter['seconds'])
else:
- until = '0'
+ until = 0
- InsertDb("INSERT INTO `bans` (`ip`, `boards`, `added`, `until`, `staff`, `reason`, `note`, `blind`) VALUES (" +
- "INET6_ATON('" + str(ip) + "'), '" + _mysql.escape_string(wordfilter['boards']) +
- "', " + str(timestamp()) + ", " + until + ", 'System', '" + _mysql.escape_string(wordfilter['reason']) +
- "', 'Word Auto-ban', '"+_mysql.escape_string(wordfilter['blind'])+"')")
+ sql_query = "INSERT INTO `bans` (`ipstart`, `ipend`, `ipstr`, `boards`, `added`, `until`, `staff`, `reason`, `note`, `blind`) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)"
+ sql_params = (ip, ip, ip, wordfilter['boards'], timestamp(), until, "System", wordfilter['reason'], "Filter auto-ban", wordfilter['blind'])
+ InsertDb(sql_query, sql_params)
regenerateAccess()
raise UserError(wordfilter['reason'])
- elif wordfilter['action'] == '3':
+ elif wordfilter['action'] == 3:
if not re.search(wordfilter['from'], message, re.DOTALL | re.IGNORECASE) is None:
raise UserError('%s' % (wordfilter['redirect_time'], wordfilter['redirect_url'], wordfilter['reason']))
return message
@@ -426,18 +436,18 @@ def checkNamefilters(name, tripcode, ip, board):
if match:
# do action
- if namefilter['action'] == '0':
+ if namefilter['action'] == 0:
raise UserError(namefilter['reason'])
- elif namefilter['action'] == '1':
+ elif namefilter['action'] == 1:
name = namefilter['to']
tripcode = ''
return name, tripcode
- elif namefilter['action'] == '2':
+ elif namefilter['action'] == 2:
# Ban
- if namefilter['seconds'] != '0':
- until = str(timestamp() + int(namefilter['seconds']))
+ if namefilter['seconds']:
+ until = timestamp() + int(namefilter['seconds'])
else:
- until = '0'
+ until = 0
InsertDb("INSERT INTO `bans` (`ip`, `boards`, `added`, `until`, `staff`, `reason`, `note`, `blind`) VALUES (" +
"'" + _mysql.escape_string(ip) + "', '" + _mysql.escape_string(namefilter['boards']) +
@@ -445,6 +455,6 @@ def checkNamefilters(name, tripcode, ip, board):
"', 'Name Auto-ban', '"+_mysql.escape_string(namefilter['blind'])+"')")
regenerateAccess()
raise UserError(namefilter['reason'])
- elif namefilter['action'] == '3':
+ elif namefilter['action'] == 3:
raise UserError('%s' % (namefilter['redirect_time'], namefilter['redirect_url'], namefilter['reason']))
return name, tripcode
diff --git a/cgi/framework.py b/cgi/framework.py
index 38ba2ad..1a2d78e 100644
--- a/cgi/framework.py
+++ b/cgi/framework.py
@@ -128,6 +128,16 @@ def getCountry(ip):
return "??"
+def clearCache():
+ if Settings._.CONN:
+ Settings._.CONN.close()
+ Settings._.CONN = None
+
+ Settings._.BOARD = None
+ Settings._.IS_TOR = None
+ Settings._.HOST = None
+
+
def getHost(ip):
if Settings._.HOST is None:
try:
diff --git a/cgi/manage.py b/cgi/manage.py
index 02eaf41..93a9921 100644
--- a/cgi/manage.py
+++ b/cgi/manage.py
@@ -274,23 +274,18 @@ def manage(self, path_split):
if not moderator:
return
- try:
- action_taken = True
- member = FetchOne(
- 'SELECT `username` FROM `staff` WHERE `id` = ' + _mysql.escape_string(path_split[4]) + ' LIMIT 1')
- if member:
- UpdateDb('DELETE FROM `staff` WHERE `id` = ' +
- _mysql.escape_string(path_split[4]) + ' LIMIT 1')
- message = 'Staff member deleted.'
- template_filename = "message.html"
- logAction(staff_account['username'], _(
- 'Deleted staff account for %s') % member['username'])
- else:
- message = _(
- 'Unable to locate a staff account with that ID.')
- template_filename = "message.html"
- except:
- pass
+ action_taken = True
+ member = FetchOne('SELECT `username` FROM `staff` WHERE `id` = %s LIMIT 1', (path_split[4],))
+ if member:
+ UpdateDb('DELETE FROM `staff` WHERE `id` = %s LIMIT 1', (path_split[4],))
+ message = 'Staff member deleted.'
+ template_filename = "message.html"
+ logAction(staff_account['username'], _(
+ 'Deleted staff account for %s') % member['username'])
+ else:
+ message = _(
+ 'Unable to locate a staff account with that ID.')
+ template_filename = "message.html"
if not action_taken:
staff = FetchAll('SELECT * FROM `staff` ORDER BY `rights`')
@@ -353,7 +348,7 @@ def manage(self, path_split):
if imageonly:
message = 'Archivo de post /%s/%s eliminado.' % (
board['dir'], post['id'])
- elif permanently or post["parentid"] == '0':
+ elif permanently or post["parentid"] == 0:
message = 'Post /%s/%s eliminado permanentemente.' % (
board['dir'], post['id'])
else:
@@ -384,7 +379,7 @@ def manage(self, path_split):
message = _('Post is not a thread opener.')
template_filename = "message.html"
else:
- if not post['locked']:
+ if post['locked'] == 0:
# Cerrar si esta abierto
setLocked = 1
else:
@@ -392,7 +387,7 @@ def manage(self, path_split):
setLocked = 0
UpdateDb("UPDATE `posts` SET `locked` = %s WHERE `boardid` = %s AND `id` = %s LIMIT 1",
- (setLocked, board["id"], postid))
+ (setLocked, board["id"], post["id"]))
threadUpdated(postid)
if setLocked == 1:
message = _('Thread successfully closed.')
@@ -732,7 +727,7 @@ def manage(self, path_split):
else:
message = _('Ban successfully placed.')
action = 'Banned ' + ip
- if until != '0':
+ if until != 0:
action += ' until ' + \
formatTimestamp(until)
else:
@@ -997,16 +992,16 @@ def manage(self, path_split):
if path_split[4] == 'restore':
board = setBoard(path_split[5])
- post = FetchOne('SELECT `parentid` FROM `posts` WHERE `boardid` = ' +
- board['id'] + ' AND `id` = \'' + _mysql.escape_string(path_split[6]) + '\' LIMIT 1')
+ post = FetchOne('SELECT `parentid` FROM `posts` WHERE `boardid` = %s AND `id` = %s LIMIT 1',
+ (board['id'], path_split[6]))
if not post:
message = _(
'Unable to locate a post with that ID.') + '
'
template_filename = "message.html"
else:
- UpdateDb('UPDATE `posts` SET `IS_DELETED` = 0 WHERE `boardid` = ' +
- board['id'] + ' AND `id` = \'' + _mysql.escape_string(path_split[6]) + '\' LIMIT 1')
- if post['parentid'] != '0':
+ UpdateDb('UPDATE `posts` SET `IS_DELETED` = 0 WHERE `boardid` = %s AND `id` = %s LIMIT 1',
+ (board['id'], path_split[6]))
+ if post['parentid'] != 0:
threadUpdated(post['parentid'])
else:
regenerateFrontPages()
@@ -1485,8 +1480,7 @@ def manage(self, path_split):
elif filter_action == 1:
# Change to
if len(self.formdata["changeto"]) > 0:
- filter_to = _mysql.escape_string(
- self.formdata["changeto"])
+ filter_to = self.formdata["changeto"]
sql_query = "INSERT INTO `filters` (`id`, `boards`, `type`, `action`, `from`, `from_trip`, `reason`, `to`, `added`, `staff`) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)"
sql_params = (edit_id, where, filter_type, filter_action, filter_from, filter_tripcode, filter_reason, filter_to, timestamp(), staff_account['username'])
else:
@@ -1495,27 +1489,24 @@ def manage(self, path_split):
return
elif filter_action == 2:
# Ban
- filter_seconds = '0'
+ filter_seconds = 0
if len(self.formdata["seconds"]) > 0:
- filter_seconds = _mysql.escape_string(
- self.formdata["seconds"])
- if "blind" in self.formdata and self.formdata["blind"] == '1':
- filter_blind = '1'
+ filter_seconds = int(self.formdata["seconds"])
+ if "blind" in self.formdata and self.formdata["blind"] == 1:
+ filter_blind = 1
else:
- filter_blind = '2'
+ filter_blind = 2
- sql_query = "INSERT INTO `filters` (`id`, `boards`, `type`, `action`, `from`, `from_trip`, `reason`, `seconds`, `blind`, `added`, `staff`) VALUES (%d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s')" % \
- (edit_id, where, str(filter_type), str(filter_action), filter_from, filter_tripcode, filter_reason,
- filter_seconds, filter_blind, str(timestamp()), _mysql.escape_string(staff_account['username']))
+ sql_query = "INSERT INTO `filters` (`id`, `boards`, `type`, `action`, `from`, `from_trip`, `reason`, `seconds`, `blind`, `added`, `staff`) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)"
+ sql_params = (edit_id, where, filter_type, filter_action, filter_from, filter_tripcode, filter_reason,
+ filter_seconds, filter_blind, timestamp(), staff_account['username'])
elif filter_action == 3:
# Redirect URL
if len(self.formdata['redirect_url']) > 0:
- redirect_url = _mysql.escape_string(
- self.formdata['redirect_url'])
+ redirect_url = self.formdata['redirect_url']
redirect_time = 0
try:
- redirect_time = int(
- self.formdata['redirect_time'])
+ redirect_time = int(self.formdata['redirect_time'])
except:
pass
else:
@@ -1523,20 +1514,17 @@ def manage(self, path_split):
_("You must enter a URL to redirect to."))
return
- sql_query = "INSERT INTO `filters` (`id`, `boards`, `type`, `action`, `from`, `from_trip`, `reason`, `redirect_url`, `redirect_time`, `added`, `staff`) VALUES (%d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s')" % \
- (edit_id, where, str(filter_type), str(filter_action), filter_from, filter_tripcode, filter_reason, redirect_url, str(
- redirect_time), str(timestamp()), _mysql.escape_string(staff_account['username']))
+ sql_query = "INSERT INTO `filters` (`id`, `boards`, `type`, `action`, `from`, `from_trip`, `reason`, `redirect_url`, `redirect_time`, `added`, `staff`) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)"
+ sql_params = (edit_id, where, filter_type, filter_action, filter_from, filter_tripcode, filter_reason, redirect_url, redirect_time, timestamp(), staff_account['username'])
# DO QUERY!
if edit_id > 0:
- UpdateDb(
- "DELETE FROM `filters` WHERE `id` = %s" % str(edit_id))
- UpdateDb(sql_query)
+ UpdateDb("DELETE FROM `filters` WHERE `id` = %s", (edit_id,))
+ UpdateDb(sql_query, sql_params)
message = 'Filter edited.'
else:
- filt = FetchOne("SELECT `id` FROM `filters` WHERE `boards` = '%s' AND `type` = '%s' AND `from` = '%s'" % (
- where, str(filter_type), filter_from))
+ filt = FetchOne("SELECT `id` FROM `filters` WHERE `boards` = %s AND `type` = %s AND `from` = %s", (where, filter_type, filter_from))
if not filt:
- UpdateDb(sql_query)
+ UpdateDb(sql_query, sql_params)
message = 'Filter added.'
else:
message = 'This filter already exists here:' + ' limit:
message_shortened = message_shortened[:limit]
- #message_shortened = formatting.close_html(message_shortened)
+ message_shortened = formatting.close_html(message_shortened)
return True, message_shortened
else:
@@ -722,12 +723,14 @@ def deletePost(postid, password, deltype=0, imageonly=False, quick=False):
if not post["parentid"]:
deleteReplies(post)
- logging.info("Deleting post " + str(postid))
+ logging.info("Deleting post %d - parentid: %d" % (post["id"], post["parentid"]))
if deltype != 0 and post["parentid"]:
# Soft delete (recycle bin)
+ logging.info("Soft delete")
UpdateDb("UPDATE `posts` SET `IS_DELETED` = %s WHERE `boardid` = %s AND `id` = %s LIMIT 1", (deltype, board["id"], post["id"]))
else:
# Hard delete
+ logging.info("Hard delete")
if post["file"]:
deleteFile(post)
@@ -745,10 +748,16 @@ def deletePost(postid, password, deltype=0, imageonly=False, quick=False):
(newlast["timestamp"], threadNumReplies(post["parentid"]), post["parentid"], board["id"]))
if not post['parentid']:
+ logging.info("Unlinking html")
if board['board_type'] == 1:
- os.unlink(Settings.ROOT_DIR + str(board["dir"]) + "/res/" + str(post["timestamp"]) + ".html")
+ fname = Settings.ROOT_DIR + str(board["dir"]) + "/res/" + str(post["timestamp"]) + ".html"
else:
- os.unlink(Settings.ROOT_DIR + str(board["dir"]) + "/res/" + str(post["id"]) + ".html")
+ fname = Settings.ROOT_DIR + str(board["dir"]) + "/res/" + str(post["id"]) + ".html"
+
+ try:
+ os.unlink(fname)
+ except FileNotFoundError:
+ logging.warn("Thread HTML (%s) didn't exist! Continuing..." % fname)
regenerateHome()
@@ -907,7 +916,7 @@ def autoclose_thread(parentid, t, replies):
notice_post["bumped"] = get_parent_post(parentid, board["id"])["bumped"]
notice_post["timestamp_formatted"] = str(replylimit) + " mensajes"
notice_post.insert()
- UpdateDb("UPDATE `posts` SET `locked` = 1 WHERE `boardid` = '%s' AND `id` = '%s' LIMIT 1" % (board["id"], _mysql.escape_string(parentid)))
+ UpdateDb("UPDATE `posts` SET `locked` = 1 WHERE `boardid` = %s AND `id` = %s LIMIT 1", (board["id"], parentid))
def pageNavigator(page_num, page_count, is_omitted=False):
"""
@@ -972,10 +981,12 @@ def flood_check(t,post,boardid):
if not post["parentid"]:
maxtime = round(t - int(board['threadsecs']))
- #lastpost = FetchOne("SELECT COUNT(*) FROM `posts` WHERE `ip` = INET6_ATON('%s') and `parentid` = 0 and `boardid` = '%s' and IS_DELETED = 0 AND timestamp > %d" % (str(post["ip"]), boardid, int(maxtime)), 0)
+ lastpost = FetchOne("SELECT `timestamp` FROM `posts` WHERE `ip` = INET6_ATON(%s) and `parentid` = 0 and `boardid` = %s and IS_DELETED = 0 AND timestamp > %s",
+ (post["ip"], boardid, maxtime))
# NO MATTER THE IP
- lastpost = FetchOne("SELECT `timestamp` FROM `posts` WHERE `parentid` = 0 and `boardid` = %s and IS_DELETED = 0 AND timestamp > %s",
+ if not lastpost:
+ lastpost = FetchOne("SELECT `timestamp` FROM `posts` WHERE `parentid` = 0 and `boardid` = %s and IS_DELETED = 0 AND timestamp > %s",
(boardid, maxtime))
else:
maxtime = round(t - int(board['postsecs']))
@@ -990,11 +1001,10 @@ def flood_check(t,post,boardid):
wait = int(int(board['threadsecs']) - (t - int(lastpost["timestamp"])))
raise UserError("Espera " + str(wait) + " segundos antes de crear otro hilo.")
-def cut_home_msg(message, boardlength=0):
+def cut_msg(message, limit):
short_message = message.replace("
", " ")
short_message = short_message.split("
")[0]
short_message = re.compile(r"<[^>]*?>", re.DOTALL | re.IGNORECASE).sub("", short_message) # Removes HTML tags
- limit = Settings.HOME_LASTPOSTS_LENGTH - boardlength
if len(short_message) > limit:
if isinstance(short_message, str):
@@ -1002,6 +1012,9 @@ def cut_home_msg(message, boardlength=0):
short_message = re.compile(r"&(.(?!;))*$", re.DOTALL | re.IGNORECASE).sub("", short_message) # Removes incomplete HTML
return short_message
+def cut_home_msg(message, boardlength=0):
+ return cut_msg(message, Settings.HOME_LASTPOSTS_LENGTH - boardlength)
+
def getLastAge(board_type, limit):
threads = []
sql = "SELECT posts.id, boards.name AS board_fulln, boards.subname AS board_name, board_type, boards.dir, timestamp, bumped, last, length, thumb, CASE WHEN posts.subject = boards.subject THEN posts.message ELSE posts.subject END AS content FROM posts INNER JOIN boards ON boardid = boards.id WHERE parentid = 0 AND IS_DELETED = 0 AND boards.secret = 0 AND posts.locked < 3 AND boards.board_type = %s ORDER BY bumped DESC LIMIT %s"
@@ -1209,12 +1222,13 @@ def latestAdd(post, postnum, postid, parent_post):
else:
url = '/%s/res/%s.html#%s' % (board['dir'], parentid, postid)
- sql = "INSERT INTO last (id, boardid, board_name, timestamp, timestamp_formatted, content, url) VALUES ('%s', '%s', '%s', '%s', '%s', '%s', '%s')" % (str(postid), board['id'], _mysql.escape_string(board['name']), post['timestamp'], _mysql.escape_string(timestamp_formatted), _mysql.escape_string(content), _mysql.escape_string(url))
- UpdateDb(sql)
+ sql = "INSERT INTO last (id, boardid, board_name, timestamp, timestamp_formatted, content, url) VALUES (%s, %s, %s, %s, %s, %s, %s)"
+ params = (postid, board['id'], board['name'], post['timestamp'], timestamp_formatted, content, url)
+ UpdateDb(sql, params)
def latestRemove(postid):
board = Settings._.BOARD
- UpdateDb("DELETE FROM last WHERE id = %s AND boardid = %s" % (str(postid), board['id']))
+ UpdateDb("DELETE FROM last WHERE id = %s AND boardid = %s", (postid, board['id']))
def archiveThread(postid):
import json
@@ -1271,7 +1285,7 @@ def magic_ball():
return string
-def discord_hook(post, url):
+def discord_hook(post, parent_post, url):
if not Settings.DISCORD_HOOK_URL:
return
@@ -1280,23 +1294,31 @@ def discord_hook(post, url):
board = Settings._.BOARD
- #data = {"embeds": [{
- # "title": post['subject'],
- # "description": cut_home_msg(post['message'], 30),
- # "url": "https://bienvenidoainternet.org" + url, # TODO: Parametrizar.
- # "color": 11910504,
- # "timestamp": datetime.datetime.utcfromtimestamp(post['timestamp']).isoformat(),
- # "footer": { "text": board['name'] },
- # "thumbnail": { "url": "%s%s/thumb/%s" % (Settings.HOME_URL, board['dir'], post['thumb']) },
- # "author": {
- # "name": "Nuevo hilo",
- # "icon_url": "%s0/junk/w/shobon.gif" % Settings.HOME_URL
- # }}]
- #}
- data = {"content": "test"}
- jsondata = json.dumps(data, separators=(',',':'))
-
- opener = urllib.request.build_opener()
- #opener.addheaders = [('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0')]
- response = opener.open(Settings.DISCORD_HOOK_URL, jsondata, 6)
- the_page = response.read()
+ if parent_post:
+ ptitle = "Nueva respuesta en {} ({})".format(html.unescape(parent_post["subject"]), parent_post["length"]+1)
+ else:
+ ptitle = "Nuevo hilo: {}".format(html.unescape(post['subject']))
+
+ data = {"embeds": [{
+ "type": "rich",
+ "title": ptitle,
+ "description": html.unescape(cut_msg(post['message'], 200)),
+ "color": 11910504,
+ "url": "https://bienvenidoainternet.org" + url, # TODO: Parametrizar.
+ "timestamp": datetime.datetime.utcfromtimestamp(post['timestamp']).isoformat(),
+ "footer": { "text": board['name'] },
+ }]
+ }
+ if post['thumb']:
+ data["embeds"][0]["thumbnail"] = {"url": "%s%s/thumb/%s" % (Settings.HOME_URL, board['dir'], post['thumb'])}
+ jsondata = json.dumps(data, separators=(',',':')).encode('utf-8')
+
+ try:
+ req = urllib.request.Request(Settings.DISCORD_HOOK_URL)
+ req.add_header('Content-Type', 'application/json')
+ req.add_header('Content-Length', len(jsondata))
+ req.add_header('User-Agent', "weabot/0.1")
+ response = urllib.request.urlopen(req, jsondata)
+ except urllib.error.HTTPError as e:
+ raise Exception(e.read())
+
diff --git a/cgi/templates/board.html b/cgi/templates/board.html
index 70718b8..3732ba9 100644
--- a/cgi/templates/board.html
+++ b/cgi/templates/board.html
@@ -241,11 +241,11 @@