# coding=utf-8 import string import cgi import os import re import pickle import time import _mysql from database import * from framework import * from post import regenerateAccess #from xhtml_clean import Cleaner from settings import Settings def format_post(message, ip, parentid, parent_timestamp=0): """ Formats posts using the specified format """ board = Settings._.BOARD using_markdown = False # Escape any HTML if user is not using Markdown or HTML if not Settings.USE_HTML: message = cgi.escape(message) # Strip text message = message.rstrip()[0:8000] # Treat HTML if Settings.USE_MARKDOWN: message = markdown(message) using_markdown = True if Settings.USE_HTML: message = onlyAllowedHTML(message) # [code] tag if board["dir"] == "tech": message = re.compile(r"\[code\](.+)\[/code\]", re.DOTALL | re.IGNORECASE).sub(r"
\1
", message)
if board["allow_spoilers"]:
message = re.compile(r"\[spoiler\](.+)\[/spoiler\]", re.DOTALL |
re.IGNORECASE).sub(r'\1', message)
if Settings.VIDEO_THUMBS:
(message, affected) = videoThumbs(message)
# if affected:
# message = close_html(message)
message = clickableURLs(message)
message = checkRefLinks(message, parentid, parent_timestamp)
message = checkWordfilters(message, ip, board["dir"])
# If not using markdown quotes must be created and \n changed for HTML line breaks
if not using_markdown:
message = re.compile(r"^(\n)+").sub('', message)
message = checkQuotes(message)
message = message.replace("\n", "in posts, along with the special""" message = sanitize_html(message) #message = re.compile(r"\[aa\](.+?)\[/aa\]", re.DOTALL | re.IGNORECASE).sub("\\1", message) return message def close_html(message): """ Old retarded version of sanitize_html, it just closes open tags. """ import BeautifulSoup message = message.encode('utf-8') soup = BeautifulSoup.BeautifulSoup(message) return unicode(soup).replace(' ', '').encode('utf-8') def sanitize_html(message, decode=True): """ Clean the code and allow only a few safe tags. """ import BeautifulSoup # Decode message from utf-8 if required if decode: message = message.decode('utf-8', 'replace') # Create HTML Cleaner with our allowed tags whitelist_tags = ["a", "b", "br", "blink", "code", "del", "em", "i", "marquee", "root", "strike", "strong", "sub", "sup", "u"] whitelist_attr = ["href"] soup = BeautifulSoup.BeautifulSoup(message) # Remove tags that aren't allowed for tag in soup.findAll(): if not tag.name.lower() in whitelist_tags: tag.name = "span" tag.attrs = [] else: for attr in [attr for attr in tag.attrs if attr not in whitelist_attr]: del tag[attr] # We export the soup into a correct XHTML string string = unicode(soup).encode('utf-8') # We remove some anomalies we don't want string = string.replace('
', '
').replace(' ', '') return string def markdown(message): import markdown if message.strip() != "": # return markdown.markdown(message).rstrip("\n").rstrip("
") return markdown.markdown(message, extras=["cuddled-lists", "code-friendly"]).encode('utf-8') else: return "" def checkWordfilters(message, ip, board): wordfilters = FetchAll( "SELECT * FROM `filters` WHERE `type` = '0' ORDER BY `id` ASC") for wordfilter in wordfilters: if wordfilter["boards"] != "": boards = pickle.loads(wordfilter["boards"]) if wordfilter["boards"] == "" or board in boards: 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': message = re.compile(wordfilter['from'], re.DOTALL | re.IGNORECASE).sub( wordfilter['to'], message) 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'])) else: 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'])+"')") regenerateAccess() raise UserError, wordfilter['reason'] 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 def checkNamefilters(name, tripcode, ip, board): namefilters = FetchAll("SELECT * FROM `filters` WHERE `type` = '1'") for namefilter in namefilters: if namefilter["boards"] != "": boards = pickle.loads(namefilter["boards"]) if namefilter["boards"] == "" or board in boards: # check if this filter applies match = False if namefilter['from'] and namefilter['from_trip']: # both name and trip filter if re.search(namefilter['from'], name, re.DOTALL | re.IGNORECASE) and tripcode == namefilter['from_trip']: match = True elif namefilter['from'] and not namefilter['from_trip']: # name filter if re.search(namefilter['from'], name, re.DOTALL | re.IGNORECASE): match = True elif not namefilter['from'] and namefilter['from_trip']: # trip filter if tripcode == namefilter['from_trip']: match = True if match: # do action if namefilter['action'] == '0': raise UserError, namefilter['reason'] elif namefilter['action'] == '1': name = namefilter['to'] tripcode = '' return name, tripcode elif namefilter['action'] == '2': # Ban if namefilter['seconds'] != '0': until = str(timestamp() + int(namefilter['seconds'])) else: until = '0' InsertDb("INSERT INTO `bans` (`ip`, `boards`, `added`, `until`, `staff`, `reason`, `note`, `blind`) VALUES (" + "'" + _mysql.escape_string(ip) + "', '" + _mysql.escape_string(namefilter['boards']) + "', " + str(timestamp()) + ", " + until + ", 'System', '" + _mysql.escape_string(namefilter['reason']) + "', 'Name Auto-ban', '"+_mysql.escape_string(namefilter['blind'])+"')") regenerateAccess() raise UserError, namefilter['reason'] elif namefilter['action'] == '3': raise UserError, '%s' % (namefilter['redirect_time'], namefilter['redirect_url'], namefilter['reason']) return name, tripcode