# Forban - a simple link-local opportunistic p2p free software # # For more information : http://www.foo.be/forban/ # # Copyright (C) 2009-2010 Alexandre Dulaunoy - http://www.foo.be/ # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . import glob import os.path import sys import string import ConfigParser import socket import re def guesspath(): pp = os.path.realpath(sys.argv[0]) lpath = os.path.split(pp) bis = os.path.split(lpath[0]) return bis[0] config = ConfigParser.RawConfigParser() config.read(os.path.join(guesspath(),"cfg","forban.cfg")) try: forbanpath = config.get('global','path') except ConfigParser.Error: forbanpath = os.path.join(guesspath()) forbandiscoveredloots = os.path.join(forbanpath,"var","loot") try: forbanmode = config.get('global','mode') except ConfigParser.Error: forbanmode = "opportunistic" try: forbanshareroot = config.get('forban','share') except ConfigParser.Error: forbanshareroot = os.path.join(forbanpath,"var","share/") try: disable_ipv6 = config.get('global' , 'ipv6_disabled') except ConfigParser.Error: disable_ipv6 = "0" forbanpathlib = os.path.join (forbanpath,"lib") sys.path.append(forbanpathlib) import index import loot import base64e import tools try: forbanname = config.get('global','name') except ConfigParser.Error: forbanname = tools.guesshostname() try: import cherrypy from cherrypy.lib.static import serve_file except ImportError: libexternal = os.path.join(forbanpath,"lib","ext") sys.path.append(libexternal) import cherrypy from cherrypy.lib.static import serve_file import mimetypes forbanpathlog=os.path.join(forbanpath,"var","log") if not os.path.exists(forbanpathlog): os.mkdir(forbanpathlog) forbanpathlogfile=os.path.join(forbanpathlog,"forban_share_access.log") forbanpathlogfilee=os.path.join(forbanpathlog,"forban_share_error.log") if socket.has_ipv6 and disable_ipv6 == "0" : try: socktest = socket.socket(socket.AF_INET6) bindhost = "::" socktest.close() except: bindhost = "0.0.0.0" else: bindhost = "0.0.0.0" cherrypy.config.update({ 'log.screen': False, 'server.socket_port': 12555 , 'server.socket_host': bindhost, 'tools.static.root':forbanshareroot, 'log.access_file':forbanpathlogfile, 'log.error_file':forbanpathlogfilee, 'request.show_tracebacks': False}) forbanpathcherry = { '/css/style.css': {'tools.staticfile.on': True, 'tools.staticfile.filename':forbanshareroot+'forban/css/x.css'}, '/img/forban-small.png': {'tools.staticfile.on': True, 'tools.staticfile.filename':forbanshareroot+'forban/img/forban-small.png'} } htmlheader = """ """ htmlfooter = """

Forban is free software released under the AGPL. For more information about Forban and source code : foo.be/forban/.

""" htmlnav = """
""" % (forbanname, forbanmode) def mime_type(filename): if re.search('/forban/index',filename): return 'text/plain' else: return mimetypes.guess_type(filename)[0] or 'application/octet-stream' def forban_geturl(uuid=None, filename=None, protocol="v4"): if uuid is None or filename is None: return False discoveredloot = loot.loot(dynpath=os.path.join(forbanpath,"var")) if not discoveredloot.exist(uuid): return False if protocol == "v4": ip = discoveredloot.getipv4(uuid) else: ip = discoveredloot.getipv6(uuid) if protocol == "v4": url = "http://%s:12555/s/?g=%s&f=b64e" % (ip,base64e.encode(filename)) else: url = "http://[%s]:12555/s/?g=%s&f=b64e" % (ip,base64e.encode(filename)) return url class Root: def index(self, directory=forbanshareroot): html = htmlheader html += htmlnav html += """


""" html += """

Search the loot...

""" html += """
""" html += """
""" html += """

Discovered link-local Forban available with their loot in the last 3 minutes

""" html += "" html += "" discoveredloot = loot.loot(dynpath=os.path.join(forbanpath,"var")) mysourcev4 = discoveredloot.getipv4(discoveredloot.whoami()) allindex = index.manage(sharedir=forbanshareroot, forbanglobal=forbanpath) for name in discoveredloot.listall(): if (discoveredloot.exist(name) and discoveredloot.lastannounced(name)): allindex.cache(name) if discoveredloot.lastannounced(name): html += "" rname = discoveredloot.getname(name) sourcev4 = discoveredloot.getipv4(name) if sourcev4 is not None: html += """ """ % sourcev4 else: html += """""" sourcev6 = discoveredloot.getipv6(name) if sourcev6 is not None: html += """ """ % sourcev6 else: html += """""" html += "" lastseen = discoveredloot.lastannounced(name) if lastseen is not None: html += """""" % lastseen else: html += "" missingfiles = allindex.howfar(name) totalsize = allindex.totalfilesize(name) html +="" % str(totalsize) if type(missingfiles) is bool: html += "" else: html += "" html += "" html += "
AccessNameLast seenSizeHow many files are missing from yourself?
v4v6"+rname+"%s secs agonever seen%sMissing index from this loot" elif missingfiles is not None: html += "Missing %s files from this loot" % len(missingfiles) else: html += "Missing no files from this loot" if name != discoveredloot.whoami(): html += """ [missing?] """ % (mysourcev4,name) html += """ [browse] """ % (mysourcev4,name) if name == discoveredloot.whoami(): html += """ [browse] """ % (name) html += "yourself
" html += htmlfooter return html def q(self, v=None, r=None): querystring = v mindex = index.manage(sharedir=forbanshareroot, forbanglobal=forbanpath) discoveredloot = loot.loot(dynpath=os.path.join(forbanpath,"var")) searchresult = [] for name in discoveredloot.listall(): if (discoveredloot.exist(name) and discoveredloot.lastannounced(name)): fileavailable = mindex.search( uuid=name, query=querystring) for filefound in fileavailable: searchresult.append((filefound,name)) searchresult.sort() html = htmlheader html += "search results of %s" % (querystring) if r is not None: html += """""" % (r) html += "" html += htmlnav html += """

""" previousfile = None html += "" for foundfiles in searchresult: if foundfiles[0] == previousfile: html += """%s """ % (forban_geturl(uuid=foundfiles[1],filename=filename),discoveredloot.getname(foundfiles[1])) elif previousfile == None: filename = foundfiles[0].rsplit(",",1)[0] html += """
FilenameAvailable on
%s %s """ % (foundfiles[0].rsplit(",",1)[0],forban_geturl(uuid=foundfiles[1],filename=filename),discoveredloot.getname(foundfiles[1])) else: filename = foundfiles[0].rsplit(",",1)[0] html += """
%s %s """ % (foundfiles[0].rsplit(",",1)[0],forban_geturl(uuid=foundfiles[1],filename=filename),discoveredloot.getname(foundfiles[1])) previousfile=foundfiles[0] html += "
" return html def v(self, uuid): mindex = index.manage(sharedir=forbanshareroot, forbanglobal=forbanpath) dloot = loot.loot(dynpath=os.path.join(forbanpath,"var")) missingfiles = mindex.howfar(uuid) html = htmlheader html += """


Missing files on your loot from %s

""" % dloot.getname(uuid) html += htmlnav html += "" if missingfiles is None: html += "You are not missing any files with %s " % dloot.getname(uuid) else: for filemissed in missingfiles: html += "" sourcev4 = dloot.getipv4(uuid) sourcev6 = dloot.getipv6(uuid) html += """ """ % (filemissed,sourcev4,base64e.encode(filemissed)) if sourcev6 is not None: html += """""" % (sourcev6, base64e.encode(filemissed)) html += "" html += "
%sv4v6
" html += htmlfooter return html def l(self, uuid): mindex = index.manage(sharedir=forbanshareroot, forbanglobal=forbanpath) dloot = loot.loot(dynpath=os.path.join(forbanpath,"var")) html = htmlheader html += """


Files available in loot %s

""" % dloot.getname(uuid) html += htmlnav html += "" html += "" tempindex = mindex.search("^((?!forban).)*$", uuid) tempindex.sort(key=string.lower) for fileinindex in tempindex: filei = fileinindex.rsplit(",",1)[0] if re.search('/\.',filei): continue if re.search('^\+\.',filei): continue html += "" sourcev4 = dloot.getipv4(uuid) sourcev6 = dloot.getipv6(uuid) size = tools.convertbytes(mindex.getfilesize(filename=filei,uuid=uuid)) html += """ """ % (filei,size,base64e.encode(filei)) html += "" html += "
FilenameFetch
%s (%s)get
" html += htmlfooter return html index.exposed = True q.exposed = True v.exposed = True l.exposed = True class Download: def index(self, g=None, f=None): if f is not None: g = base64e.decode(g) gs = string.replace(g, "..", "") gs = forbanshareroot + gs mimetypeguessed = mime_type(gs) return serve_file(gs, content_type=mimetypeguessed,disposition=True, name=os.path.basename(gs)) index.exposed = True if __name__ == '__main__': root = Root() favicon_path = os.path.join(forbanshareroot, "forban", "img", "forban-favicon.png") root.favicon_ico = cherrypy.tools.staticfile.handler(filename=favicon_path) root.s = Download() cherrypy.quickstart(root, config=forbanpathcherry)