# coding=utf-8
import os
import cgi
import datetime
import time
import hashlib
import pickle
import socket
import _mysql
import urllib
import re
from Cookie import SimpleCookie
from settings import Settings
from database import *
def setBoard(dir):
"""
Sets the board which the script is operating on by filling Settings._.BOARD
with the data from the db.
"""
if not dir:
raise UserError, _("The specified board is invalid.")
logTime("Seteando el board " + dir)
board = FetchOne(
"SELECT * FROM `boards` WHERE `dir` = '%s' LIMIT 1" % _mysql.escape_string(dir))
if not board:
raise UserError, _("The specified board is invalid.")
board["filetypes"] = FetchAll(
"SELECT * FROM `boards_filetypes` INNER JOIN `filetypes` ON filetypes.id = boards_filetypes.filetypeid WHERE `boardid` = %s ORDER BY `ext` ASC" % _mysql.escape_string(board['id']))
board["filetypes_ext"] = [filetype['ext']
for filetype in board['filetypes']]
logTime("Board seteado.")
Settings._.BOARD = board
return board
def cleanDir(path, ext=None):
if ext:
filelist = [f for f in os.listdir(path) if f.endswith("." + ext)]
else:
filelist = os.listdir(path)
for f in filelist:
os.remove(os.path.join(path, f))
def addressIsBanned(ip, board):
bans = FetchAll("SELECT * FROM `bans` WHERE INET6_ATON('"+str(ip)+"') BETWEEN `ipstart` AND `ipend`")
for ban in bans:
if ban["boards"] != "":
boards = pickle.loads(ban["boards"])
if ban["boards"] == "" or board in boards:
if board not in Settings.EXCLUDE_GLOBAL_BANS:
return True
return False
def addressIsTor(ip):
if Settings._.IS_TOR is None:
res = False
nodes = []
if ip == '127.0.0.1': # Tor proxy address
res = True
else:
with open('tor.txt') as f:
nodes = [line.rstrip() for line in f]
if ip in nodes:
res = True
Settings._.IS_TOR = res
return res
else:
return Settings._.IS_TOR
def addressIsProxy(ip):
if Settings._.IS_PROXY is None:
res = False
proxies = []
with open('proxy.txt') as f:
proxies = [line.rstrip() for line in f]
if ip in proxies:
res = True
Settings._.IS_PROXY = res
return res
else:
return Settings._.IS_PROXY
def addressIsES(ip):
ES = ['AR', 'BO', 'CL', 'CO', 'CR', 'CU', 'EC', 'ES', 'GF',
'GY', 'GT', 'HN', 'MX', 'NI', 'PA', 'PE', 'PY', 'PR', 'SR', 'UY', 'VE'] # 'BR',
return getCountry(ip) in ES
def addressIsUS(ip):
return getCountry(ip) == 'US'
def getCountry(ip):
import geoip
return geoip.country(ip)
def getHost(ip):
if Settings._.HOST is None:
try:
Settings._.HOST = socket.gethostbyaddr(ip)[0]
return Settings._.HOST
except socket.herror:
return None
else:
return Settings._.HOST
def hostIsBanned(ip):
host = getHost(ip)
if host:
for banned_host in Settings.BANNED_HOSTS:
if host.endswith(banned_host):
return True
return False
def updateBoardSettings():
"""
Pickle the board's settings and store it in the configuration field
"""
board = Settings._.BOARD
#UpdateDb("UPDATE `boards` SET `configuration` = '%s' WHERE `id` = %s LIMIT 1" % (_mysql.escape_string(configuration), board["id"]))
del board["filetypes"]
del board["filetypes_ext"]
post_values = ["`" + _mysql.escape_string(str(key)) + "` = '" + _mysql.escape_string(
str(value)) + "'" for key, value in board.iteritems()]
UpdateDb("UPDATE `boards` SET %s WHERE `id` = '%s' LIMIT 1" %
(", ".join(post_values), board["id"]))
def timestamp(t=None):
"""
Create MySQL-safe timestamp from the datetime t if provided, otherwise create
the timestamp from datetime.now()
"""
if not t:
t = datetime.datetime.now()
return int(time.mktime(t.timetuple()))
def formatDate(t=None, home=False):
"""
Format a datetime to a readable date
"""
if not t:
t = datetime.datetime.now()
days = {'en': ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun'],
'es': ['lun', 'mar', 'mie', 'jue', 'vie', 'sab', 'dom'],
'jp': ['月', '火', '水', '木', '金', '土', '日']}
daylist = days[Settings.LANG]
format = "%d/%m/%y(%a)%H:%M:%S"
if not home:
try:
board = Settings._.BOARD
if board["dir"] == 'world':
daylist = days['en']
elif board["dir"] == '2d':
daylist = days['jp']
except:
pass
t = t.strftime(format)
t = re.compile(r"mon", re.DOTALL | re.IGNORECASE).sub(daylist[0], t)
t = re.compile(r"tue", re.DOTALL | re.IGNORECASE).sub(daylist[1], t)
t = re.compile(r"wed", re.DOTALL | re.IGNORECASE).sub(daylist[2], t)
t = re.compile(r"thu", re.DOTALL | re.IGNORECASE).sub(daylist[3], t)
t = re.compile(r"fri", re.DOTALL | re.IGNORECASE).sub(daylist[4], t)
t = re.compile(r"sat", re.DOTALL | re.IGNORECASE).sub(daylist[5], t)
t = re.compile(r"sun", re.DOTALL | re.IGNORECASE).sub(daylist[6], t)
return t
def formatTimestamp(t, home=False):
"""
Format a timestamp to a readable date
"""
return formatDate(datetime.datetime.fromtimestamp(int(t)), home)
def timeTaken(time_start, time_finish):
return str(round(time_finish - time_start, 3))
def parseIsoPeriod(t_str):
m = re.match('P(?:(\d+)D)?T(?:(\d+)H)?(?:(\d+)M)?(\d+)S', t_str)
if m:
grps = [x for x in m.groups() if x]
if len(grps) == 1:
grps.insert(0, '0')
grps[-1] = grps[-1].zfill(2)
return ':'.join(grps)
else:
return '???'
def getFormData(self):
"""
Process input sent to WSGI through a POST method and output it in an easy to
retrieve format: dictionary of dictionaries in the format of {key: value}
"""
# This must be done to avoid a bug in cgi.FieldStorage
self.environ.setdefault("QUERY_STRING", "")
if self.environ["QUERY_STRING"] == "rawpost":
return None
wsgi_input = self.environ["wsgi.input"]
post_form = self.environ.get("wsgi.post_form")
if (post_form is not None
and post_form[0] is wsgi_input):
return post_form[2]
fs = cgi.FieldStorage(fp=wsgi_input,
environ=self.environ,
keep_blank_values=1)
new_input = InputProcessed()
post_form = (new_input, wsgi_input, fs)
self.environ["wsgi.post_form"] = post_form
self.environ["wsgi.input"] = new_input
try:
formdata = {}
for key in dict(fs):
try:
formdata.update({key: fs[key].value})
if key == "file":
formdata.update(
{"file_original": secure_filename(fs[key].filename)})
except AttributeError:
formdata.update({key: fs[key]})
return formdata
except TypeError:
return fs
class InputProcessed(object):
def read(self):
raise EOFError("El stream de wsgi.input ya se ha consumido.")
readline = readlines = __iter__ = read
class UserError(Exception):
pass
def secure_filename(path):
split = re.compile(r'[\0%s]' % re.escape(
''.join([os.path.sep, os.path.altsep or ''])))
return cgi.escape(split.sub('', path))
def getMD5(data):
m = hashlib.md5()
m.update(data)
return m.hexdigest()
def nullstr(len): return "\0" * len
def hide_data(data, length, key, secret):
"""
Encrypts data, useful for tripcodes and IDs
"""
crypt = rc4(nullstr(length), rc4(
nullstr(32), key + secret) + data).encode('base64')
return crypt.rstrip('\n')
def rc4(data, key):
"""
rc4 implementation
"""
x = 0
box = range(256)
for i in range(256):
x = (x + box[i] + ord(key[i % len(key)])) % 256
box[i], box[x] = box[x], box[i]
x = 0
y = 0
out = []
for char in data:
x = (x + 1) % 256
y = (y + box[x]) % 256
box[x], box[y] = box[y], box[x]
out.append(chr(ord(char) ^ box[(box[x] + box[y]) % 256]))
return ''.join(out)
def getRandomLine(filename):
import random
f = open(filename, 'r')
lines = f.readlines()
num = random.randint(0, len(lines) - 1)
return lines[num]
def getRandomIco():
from glob import glob
from random import choice
icons = glob("../static/ico/*")
if icons:
return choice(icons).lstrip('..')
else:
return ''
def N_(message): return message
def getCookie(self, value=""):
try:
return urllib.unquote_plus(self._cookies[value].value)
except KeyError:
return None
def reCookie(self, key, value=""):
board = Settings._.BOARD
setCookie(self, key, value)
def setCookie(self, key, value="", max_age=None, expires=None, path="/", domain=None, secure=None):
"""
Copied from Colubrid
"""
if self._newcookies is None:
self._newcookies = SimpleCookie()
self._newcookies[key] = urllib.quote_plus(value)
if not max_age is None:
self._newcookies[key]["max-age"] = max_age
if not expires is None:
if isinstance(expires, basestring):
self._newcookies[key]["expires"] = expires
expires = None
elif isinstance(expires, datetime):
expires = expires.utctimetuple()
elif not isinstance(expires, (int, long)):
expires = datetime.datetime.gmtime(expires)
else:
raise ValueError("Se requiere de un entero o un datetime")
if not expires is None:
now = datetime.datetime.gmtime()
month = _([N_("Jan"), N_("Feb"), N_("Mar"), N_("Apr"), N_("May"), N_("Jun"), N_("Jul"),
N_("Aug"), N_("Sep"), N_("Oct"), N_("Nov"), N_("Dec")][now.tm_mon - 1])
day = _([N_("Monday"), N_("Tuesday"), N_("Wednesday"), N_("Thursday"),
N_("Friday"), N_("Saturday"), N_("Sunday")][expires.tm_wday])
date = "%02d-%s-%s" % (
now.tm_mday, month, str(now.tm_year)[-2:]
)
d = "%s, %s %02d:%02d:%02d GMT" % (day, date, now.tm_hour,
now.tm_min, now.tm_sec)
self._newcookies[key]["expires"] = d
if not path is None:
self._newcookies[key]["path"] = path
if not domain is None:
if domain != "THIS":
self._newcookies[key]["domain"] = domain
if not secure is None:
self._newcookies[key]["secure"] = secure
def deleteCookie(self, key):
"""
Copied from Colubrid
"""
if key not in self._cookies:
return # Cookie doesn't exist
if self._newcookies is None:
self._newcookies = SimpleCookie()
self._newcookies[key] = ""
if self._cookies[key]["path"]:
self._newcookies[key]["path"] = self._cookies[key]["path"]
else:
self._newcookies[key]["path"] = "/"
self._newcookies[key]["domain"] = self._cookies[key]["domain"]
self._newcookies[key]["expires"] = "Thu, 01 Jan 1970 00:00:00 GMT"
def elapsed_time(seconds, suffixes=['y', 'w', 'd', 'h', 'm', 's'], add_s=False, separator=' '):
"""
Takes an amount of seconds and turns it into a human-readable amount of time.
"""
# the formatted time string to be returned
time = []
# the pieces of time to iterate over (days, hours, minutes, etc)
# - the first piece in each tuple is the suffix (d, h, w)
# - the second piece is the length in seconds (a day is 60s * 60m * 24h)
parts = [(suffixes[0], 60 * 60 * 24 * 7 * 52),
(suffixes[1], 60 * 60 * 24 * 7),
(suffixes[2], 60 * 60 * 24),
(suffixes[3], 60 * 60),
(suffixes[4], 60),
(suffixes[5], 1)]
# for each time piece, grab the value and remaining seconds, and add it to
# the time string
for suffix, length in parts:
value = seconds / length
if value > 0:
seconds = seconds % length
time.append('%s%s' % (str(value),
(suffix, (suffix, suffix + 's')[value > 1])[add_s]))
if seconds < 1:
break
return separator.join(time)
def inet_aton(ip_string):
import socket
import struct
return struct.unpack('!L', socket.inet_aton(ip_string))[0]
def inet_ntoa(packed_ip):
import socket
import struct
return socket.inet_ntoa(struct.pack('!L', packed_ip))
def is_bad_proxy(pip):
import urllib2
import socket
socket.setdefaulttimeout(3)
try:
proxy_handler = urllib2.ProxyHandler({'http': pip})
opener = urllib2.build_opener(proxy_handler)
opener.addheaders = [('User-agent', 'Mozilla/5.0')]
urllib2.install_opener(opener)
req = urllib2.Request('http://bienvenidoainternet.org')
sock = urllib2.urlopen(req)
except urllib2.HTTPError, e:
return e.code
except Exception, detail:
return True
return False
def send_mail(subject, srcmsg):
import smtplib
from email.mime.text import MIMEText
msg = MIMEText(srcmsg)
me = 'weabot@bienvenidoainternet.org'
you = 'burocracia@bienvenidoainternet.org'
msg['Subject'] = 'The contents of %s' % textfile
msg['From'] = me
msg['To'] = you
s = smtplib.SMTP('localhost')
s.sendmail(me, [you], msg.as_string())
s.quit()
class weabotLogger:
def __init__(self):
self.times = []
def log(self, message):
self.times.append([time.time(), message])
def allTimes(self):
output = "Time Logged action\n--------------------------\n"
start = self.times[0][0]
for time in self.times:
difference = str(time[0] - start)
difference_split = difference.split(".")
if len(difference_split[0]) < 2:
difference_split[0] = "0" + difference_split[0]
if len(difference_split[1]) < 7:
difference_split[1] = (
"0" * (7 - len(difference_split[1]))) + difference_split[1]
elif len(difference_split[1]) > 7:
difference_split[1] = difference_split[1][:7]
output += ".".join(difference_split) + " " + time[1] + "\n"
return output
logger = weabotLogger()
def logTime(message):
global logger
logger.log(message)
def logTimes():
global logger
return logger.allTimes()