Add a more secure netDb app.
This commit is contained in:
203
netdb.i2p2/fixedapp.py
Normal file
203
netdb.i2p2/fixedapp.py
Normal file
@ -0,0 +1,203 @@
|
||||
#
|
||||
# Required software:
|
||||
# sqlite3 3.6.23.1 or newer
|
||||
# http://www.sqlite.org/
|
||||
# unixodbc
|
||||
# http://www.unixodbc.org/
|
||||
# pyodbc-3.0.6 or newer
|
||||
# http://www.ch-werner.de/sqliteodbc/
|
||||
# werkzeug
|
||||
# http://werkzeug.pocoo.org/
|
||||
# python 2.6 or 2.7
|
||||
# http://python.org/
|
||||
#
|
||||
|
||||
|
||||
# Modify as needed, or use a symlink.
|
||||
netdbdir = 'netdb'
|
||||
database = 'Driver=SQLite;DATABASE=I2PnetDb'
|
||||
|
||||
|
||||
from werkzeug import BaseRequest, BaseResponse, ETagResponseMixin, escape, SharedDataMiddleware
|
||||
from werkzeug.exceptions import HTTPException
|
||||
import os
|
||||
from time import time, gmtime
|
||||
import calendar
|
||||
#import time
|
||||
from random import choice
|
||||
import pyodbc
|
||||
|
||||
|
||||
#
|
||||
# Not needed?
|
||||
#
|
||||
#import sha
|
||||
|
||||
|
||||
# db format
|
||||
#
|
||||
# table client ipaddress, time of access, file list index
|
||||
#
|
||||
# table html index, time of creation, html
|
||||
|
||||
|
||||
#
|
||||
# Init database if it does not exist.
|
||||
#
|
||||
|
||||
def checkdatabase():
|
||||
cnxn = pyodbc.connect(database)
|
||||
cur = cnxn.cursor()
|
||||
|
||||
try:
|
||||
cur.execute("select * from client")
|
||||
except pyodbc.Error:
|
||||
#cur.execute("create table peer (ip string, time string, index string)")
|
||||
print ("Creating new table 'client'")
|
||||
cur.execute("create table client (ip string, whn float)")
|
||||
cnxn.commit()
|
||||
try:
|
||||
cur.execute("select * from entry")
|
||||
except pyodbc.Error:
|
||||
#cur.execute("create table peer (ip string, time string, index string)")
|
||||
print ("Creating new table 'entry'")
|
||||
cur.execute("create table entry (whn float, wht string)")
|
||||
cnxn.commit()
|
||||
cnxn.close()
|
||||
|
||||
|
||||
|
||||
|
||||
# try:
|
||||
# cur.execute("select * from html")
|
||||
# except pyodbc.Error:
|
||||
# cur.execute("create table client (index, time, html)")
|
||||
|
||||
|
||||
# cur.execute("insert into foo values(1, 'Me')")
|
||||
# cnxn.commit()
|
||||
# cur.execute("select * from foo")
|
||||
# cnxn.close()
|
||||
|
||||
class Request(BaseRequest):
|
||||
"""Useful subclass of the default request that knows how to build urls."""
|
||||
|
||||
def __init__(self, environ):
|
||||
BaseRequest.__init__(self, environ)
|
||||
|
||||
|
||||
class Response(BaseResponse, ETagResponseMixin):
|
||||
"""Subclass of base response that has a default mimetype of text/html."""
|
||||
default_mimetype = 'text/html'
|
||||
|
||||
def app(environ, start_response):
|
||||
"""The WSGI application that connects all together."""
|
||||
req = Request(environ)
|
||||
remote = req.remote_addr
|
||||
now = time()
|
||||
old = now - 3600
|
||||
oldest = now - 7200
|
||||
t = gmtime(now)
|
||||
nowtag = calendar.timegm((t.tm_year, t.tm_mon, t.tm_mday, t.tm_hour, 0, 0, t.tm_wday, t.tm_yday, t.tm_isdst))
|
||||
|
||||
cnxn = pyodbc.connect(database)
|
||||
cur = cnxn.cursor()
|
||||
#
|
||||
# Prune database from peers that are over 1 hour old
|
||||
#
|
||||
cur.execute("delete from client where whn < ?", old)
|
||||
cnxn.commit()
|
||||
#
|
||||
# Prune database from entries that are over 2 hours old
|
||||
#
|
||||
cur.execute("delete from entry where whn < ?", oldest)
|
||||
cnxn.commit()
|
||||
|
||||
#
|
||||
# Get peer info
|
||||
#
|
||||
cur.execute("select * from client where ip = ?", remote)
|
||||
info = cur.fetchall()
|
||||
# page
|
||||
path = req.path[1:]
|
||||
|
||||
|
||||
if path == '':
|
||||
page = u'<html><head><title>NetDB</title></head><body><ul>%s</ul></body></html>'
|
||||
|
||||
if len(info) == 0:
|
||||
# tag the ip as new
|
||||
cur.execute("insert into client values (?, ?)", (remote, now))
|
||||
# see if we have a list already, and use that
|
||||
# generate links
|
||||
entries = os.listdir(netdbdir)
|
||||
if len(entries) > 150:
|
||||
# select some randomly
|
||||
new = []
|
||||
for i in range(100):
|
||||
while True:
|
||||
sel = choice(entries)
|
||||
if not sel.startswith('routerInfo-'):
|
||||
continue
|
||||
if sel not in new:
|
||||
new.append(sel)
|
||||
cur.execute("insert into entry values (?, ?)", (nowtag, sel))
|
||||
break
|
||||
entries = new
|
||||
else:
|
||||
# use old list based on date in database, i.e. sends the same as before.
|
||||
junk, last = info[0]
|
||||
t = gmtime(last)
|
||||
oldtag = calendar.timegm((t.tm_year, t.tm_mon, t.tm_mday, t.tm_hour, 0, 0, t.tm_wday, t.tm_yday, t.tm_isdst))
|
||||
cur.execute("select * from entry where whn = ?", oldtag)
|
||||
stuff = cur.fetchall()
|
||||
entries = []
|
||||
for junk,sel in stuff:
|
||||
entries.append(sel)
|
||||
|
||||
res = ''
|
||||
for entry in entries:
|
||||
if not entry.startswith('routerInfo-'):
|
||||
continue
|
||||
res += '<li><a href="%s">%s</a></li>' % (entry, entry)
|
||||
resp = Response(page % res, mimetype='text/html')
|
||||
resp.add_etag()
|
||||
|
||||
elif path == 'robots.txt':
|
||||
dat = u"User-agent: *\nDisallow: /routerInfo-*.dat$\n"
|
||||
resp = Response(dat, mimetype='text/plain')
|
||||
resp.add_etag()
|
||||
|
||||
else:
|
||||
if len(info) == 0:
|
||||
# 404 This is to prevent cross seed site scrapes
|
||||
resp = Response("Hi! Having fun?", status=403, mimetype='text/plain')
|
||||
else:
|
||||
#
|
||||
# zap badness from path
|
||||
#
|
||||
chkpath = path.replace("'","").replace("/","")
|
||||
# check to see if we have this entry in the database at all.
|
||||
cur.execute("select * from entry where wht = ?", chkpath)
|
||||
chk = cur.fetchall()
|
||||
if len(chk) == 0:
|
||||
resp = Response("Do you not have anything better to do?", status=400, mimetype='text/plain')
|
||||
else:
|
||||
try:
|
||||
# load file
|
||||
f = open(os.path.join(netdbdir, path), 'rb')
|
||||
resp = Response(f.read(), mimetype='application/octet-stream')
|
||||
f.close()
|
||||
resp.add_etag()
|
||||
except IOError:
|
||||
# 404
|
||||
resp = Response("Owch! Could not find file!", status=404, mimetype='text/plain')
|
||||
cnxn.commit()
|
||||
cnxn.close()
|
||||
return resp(environ, start_response)
|
||||
|
||||
checkdatabase()
|
||||
|
||||
if __name__ == '__main__':
|
||||
from werkzeug import run_simple
|
||||
run_simple('localhost', 5007, app)
|
Reference in New Issue
Block a user