+++ /dev/null
-#!/usr/bin/python
-
-import hashlib
-import logging
-import os
-import re
-import urllib
-import urlparse
-
-import tracker
-
-from databases import Databases
-from misc import Singleton
-from settings import Settings
-
-class File(object):
- def __init__(self, release, id):
- self.id = id
- self._release = release
-
- # get all data from database
- self.__data = None
-
- @property
- def db(self):
- return Databases().webapp
-
- @property
- def tracker(self):
- return self.release.tracker
-
- @property
- def data(self):
- if self.__data is None:
- self.__data = self.db.get("SELECT * FROM files WHERE id = %s", self.id)
- assert self.__data
-
- return self.__data
-
- @property
- def release(self):
- if not self._release:
- release_id = self.data.get("releases")
- self._release = Release(release_id)
-
- return self._release
-
- @property
- def type(self):
- filename = self.filename
-
- if filename.endswith(".iso"):
- return "iso"
-
- elif filename.endswith(".torrent"):
- return "torrent"
-
- elif "xen" in filename:
- return "xen"
-
- elif "sources" in filename:
- return "source"
-
- elif "usb-fdd" in filename:
- return "usbfdd"
-
- elif "usb-hdd" in filename:
- return "usbhdd"
-
- elif "armv5tel" in filename and "scon" in filename:
- return "armv5tel-scon"
-
- elif "armv5tel" in filename:
- return "armv5tel"
-
- elif "scon" in filename:
- return "alix"
-
- elif filename.endswith(".img.gz"):
- return "flash"
-
- else:
- return "unknown"
-
- @property
- def url(self):
- baseurl = Settings().get("download_url")
-
- return urlparse.urljoin(baseurl, self.filename)
-
- @property
- def desc(self):
- _ = lambda x: x
-
- descriptions = {
- "armv5tel" : _("Image for the armv5tel architecture"),
- "armv5tel-scon" : _("armv5tel image for boards with serial console"),
- "iso" : _("Installable CD image"),
- "torrent" : _("Torrent file"),
- "flash" : _("Flash image"),
- "alix" : _("Alix image"),
- "usbfdd" : _("USB FDD Image"),
- "usbhdd" : _("USB HDD Image"),
- "xen" : _("Pregenerated Xen image"),
- }
-
- try:
- return descriptions[self.type]
- except KeyError:
- return _("Unknown image type")
-
- @property
- def prio(self):
- priorities = {
- "iso" : 10,
- "torrent" : 20,
- "flash" : 40,
- "alix" : 41,
- "usbfdd" : 31,
- "usbhdd" : 30,
- "armv5tel" : 40,
- "armv5tel-scon" : 41,
- "xen" : 50,
- }
-
- try:
- return priorities[self.type]
- except KeyError:
- return 999
-
- @property
- def rem(self):
- _ = lambda x: x
-
- remarks = {
- "armv5tel" : _("This image runs on many ARM-based boards"),
- "armv5tel-scon" : _("This image runs on ARM boards with a serial console"),
- "iso" : _("Use this image to burn a CD and install IPFire from it."),
- "torrent" : _("Download the CD image from the torrent network."),
- "flash" : _("An image that is meant to run on embedded devices."),
- "alix" : _("Flash image where a serial console is enabled by default."),
- "usbfdd" : _("Install IPFire from a floppy-formated USB key."),
- "usbhdd" : _("If the floppy image doesn't work, use this image instead."),
- "xen" : _("A ready-to-run image for Xen."),
- }
-
- try:
- return remarks[self.type]
- except KeyError:
- return _("Unknown image type")
-
- @property
- def sha1(self):
- return self.data.get("sha1")
-
- @property
- def filename(self):
- return self.data.get("filename")
-
- @property
- def basename(self):
- return os.path.basename(self.filename)
-
- @property
- def size(self):
- return self.data.get("filesize")
-
- @property
- def arch(self):
- known_arches = ("i586", "arm")
-
- for arch in known_arches:
- if arch in self.basename:
- return arch
-
- return "N/A"
-
- @property
- def torrent_hash(self):
- return self.data.get("torrent_hash", None)
-
- @property
- def magnet_link(self):
- # Don't return anything if we have no torrent hash.
- if self.torrent_hash is None:
- return
-
- s = "magnet:?xt=urn:btih:%s" % self.torrent_hash
-
- #s += "&xl=%d" % self.size
- s += "&dn=%s" % urllib.quote(self.basename)
-
- # Add our tracker.
- s += "&tr=http://tracker.ipfire.org:6969/announce"
-
- return s
-
- @property
- def seeders(self):
- if not self.torrent_hash:
- return
-
- return self.tracker.get_seeds(self.torrent_hash)
-
- @property
- def peers(self):
- if not self.torrent_hash:
- return
-
- return self.tracker.get_peers(self.torrent_hash)
-
- @property
- def completed(self):
- if not self.torrent_hash:
- return
-
- return self.tracker.complete(self.torrent_hash)
-
-
-class Release(object):
- @property
- def db(self):
- return Releases().db
-
- @property
- def tracker(self):
- return tracker.Tracker()
-
- def __init__(self, id):
- self.id = id
-
- # get all data from database
- self.__data = \
- self.db.get("SELECT * FROM releases WHERE id = %s", self.id)
- assert self.__data
-
- self.__files = []
-
- def __repr__(self):
- return "<%s %s>" % (self.__class__.__name__, self.name)
-
- @property
- def files(self):
- if not self.__files:
- files = self.db.query("SELECT id, filename FROM files WHERE releases = %s \
- AND loadable = 'Y' AND NOT filename LIKE '%%.torrent'", self.id)
-
- self.__files = [File(self, f.id) for f in files]
- self.__files.sort(lambda a, b: cmp(a.prio, b.prio))
-
- return self.__files
-
- @property
- def torrents(self):
- torrents = []
-
- for file in self.files:
- if not file.torrent_hash:
- continue
-
- torrents.append(file)
-
- return torrents
-
- @property
- def name(self):
- return self.__data.get("name")
-
- @property
- def stable(self):
- return self.__data.get("stable") == "Y"
-
- @property
- def published(self):
- return self.__data.get("published") == "Y"
-
- @property
- def date(self):
- return self.__data.get("date")
-
- @property
- def path(self):
- return self.__data.get("path")
-
- def get_file(self, type):
- for file in self.files:
- if file.type == type:
- return file
-
- def __file_hash(self, filename):
- sha1 = hashlib.sha1()
-
- with open(filename) as f:
- buf_size = 1024
- buf = f.read(buf_size)
- while buf:
- sha1.update(buf)
- buf = f.read(buf_size)
-
- return sha1.hexdigest()
-
- def scan_files(self, basepath="/srv/mirror0"):
- if not self.path:
- return
-
- path = os.path.join(basepath, self.path)
- if not os.path.exists(path):
- return
-
- files = self.db.query("SELECT filename FROM files WHERE releases = %s", self.id)
- files = [f.filename for f in files]
-
- # Make files that do not exists not loadable.
- for filename in files:
- _filename = os.path.join(basepath, filename)
- if not os.path.exists(_filename):
- self.db.execute("UPDATE files SET loadable='N' WHERE filename = %s", filename)
-
- for filename in os.listdir(path):
- filename = os.path.join(path, filename)
-
- if os.path.isdir(filename):
- continue
-
- _filename = re.match(".*(releases/.*)", filename).group(1)
- if _filename in files:
- continue
-
- if filename.endswith(".md5"):
- continue
-
- filehash = self.__file_hash(filename)
- filesize = os.path.getsize(filename)
-
- # Check if there is a torrent download available for this file:
- torrent_hash = ""
- torrent_file = "%s.torrent" % filename
- if os.path.exists(torrent_file):
- torrent_hash = self.torrent_read_hash(torrent_file)
-
- self.db.execute("INSERT INTO files(releases, filename, filesize, \
- sha1, torrent_hash) VALUES(%s, %s, %s, %s, %s)",
- self.id, _filename, filesize, filehash, torrent_hash)
-
- # Search for all files that miss a torrent hash.
- files = self.db.query("SELECT id, filename FROM files \
- WHERE releases = %s AND torrent_hash IS NULL", self.id)
-
- for file in files:
- path = os.path.join(basepath, file.filename)
-
- torrent_file = "%s.torrent" % path
- if os.path.exists(torrent_file):
- torrent_hash = self.torrent_read_hash(torrent_file)
-
- self.db.execute("UPDATE files SET torrent_hash = %s WHERE id = %s",
- torrent_hash, file.id)
-
- def torrent_read_hash(self, filename):
- f = None
- try:
- f = open(filename, "rb")
-
- metainfo = tracker.bdecode(f.read())
- metainfo = tracker.bencode(metainfo["info"])
-
- hash = hashlib.sha1()
- hash.update(metainfo)
-
- return hash.hexdigest()
-
- finally:
- if f:
- f.close()
-
-
-class Releases(object):
- __metaclass__ = Singleton
-
- @property
- def db(self):
- return Databases().webapp
-
- def list(self):
- return [Release(r.id) for r in self.db.query("SELECT id FROM releases ORDER BY date DESC")]
-
- def get_by_id(self, id):
- id = int(id)
- if id in [r.id for r in self.db.query("SELECT id FROM releases")]:
- return Release(id)
-
- def get_latest(self, stable=1):
- query = "SELECT id FROM releases WHERE published='Y' AND"
- if stable:
- query += " stable='Y'"
- else:
- query += " stable='N'"
-
- query += " ORDER BY date DESC LIMIT 1"
-
- release = self.db.get(query)
- if release:
- return Release(release.id)
-
- def get_stable(self):
- releases = self.db.query("""SELECT id FROM releases
- WHERE published='Y' AND stable='Y'
- ORDER BY date DESC""")
-
- return [Release(r.id) for r in releases]
-
- def get_unstable(self):
- releases = self.db.query("""SELECT id FROM releases
- WHERE published='Y' AND stable='N'
- ORDER BY date DESC""")
-
- return [Release(r.id) for r in releases]
-
- def get_all(self):
- releases = self.db.query("""SELECT id FROM releases
- WHERE published='Y' ORDER BY date DESC""")
-
- return [Release(r.id) for r in releases]
-
- def get_file_for_torrent_hash(self, torrent_hash):
- file = self.db.get("SELECT id, releases FROM files WHERE torrent_hash = %s LIMIT 1",
- torrent_hash)
-
- if not file:
- return
-
- release = Release(file.releases)
- file = File(release, file.id)
-
- return file
-
-
-if __name__ == "__main__":
- r = Releases()
-
- for release in r.get_all():
- print release.name
-
- print r.get_latest()