| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166 |
- # The contents of this file are subject to the BitTorrent Open Source License
- # Version 1.1 (the License). You may not copy or use this file, in either
- # source code or executable form, except in compliance with the License. You
- # may obtain a copy of the License at http://www.bittorrent.com/license/.
- #
- # Software distributed under the License is distributed on an AS IS basis,
- # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- # for the specific language governing rights and limitations under the
- # License.
- # GetTorrent -- abstraction which can get a .torrent file from multiple
- # sources: local file, url, etc.
- # written by Matt Chisholm and David Harrison
- import os
- import re
- from BitTorrent import zurllib
- from BTL.translation import _
- from BTL.bencode import bdecode, bencode
- from BTL.ConvertedMetainfo import ConvertedMetainfo
- from BTL.platform import get_cache_dir
- urlpat = re.compile('^\w+://')
- urlpat_torrent = re.compile('^torrent://')
- urlpat_bittorrent = re.compile('^bittorrent://')
- class GetTorrentException(Exception):
- pass
- class UnknownArgument(GetTorrentException):
- pass
- class URLException(GetTorrentException):
- pass
- class FileException(GetTorrentException):
- pass
- class MetainfoException(GetTorrentException):
- pass
- def get_quietly(arg):
- """Wrapper for GetTorrent.get() which works around an IE bug. If
- there's an error opening a file from the IE cache, act like we
- simply didn't get a file (because we didn't). This happens when
- IE passes us a path to a file in its cache that has already been
- deleted because it came from a website which set Pragma:No-Cache
- on it.
- """
- try:
- data = get(arg)
- except FileException, e:
- cache = get_cache_dir()
- if (cache is not None) and (cache in unicode(e.args[0])):
- data = None
- else:
- raise
- return data
- def _get(arg):
- """Obtains the contents of the .torrent metainfo file either from
- the local filesystem or from a remote server. 'arg' is either
- a filename or an URL.
- Returns data, the raw contents of the .torrent file. Any
- exception raised while obtaining the .torrent file or parsing
- its contents is caught and wrapped in one of the following
- errors: GetTorrent.URLException, GetTorrent.FileException,
- GetTorrent.MetainfoException, or GetTorrent.UnknownArgument.
- (All have the base class GetTorrent.GetTorrentException)
- """
- data = None
- arg_stripped = arg.strip()
- if os.access(arg, os.F_OK):
- data = get_file(arg)
- elif urlpat.match(arg_stripped):
- data = get_url(arg_stripped)
- else:
- raise UnknownArgument(_('Could not read "%s", it is neither a file nor a URL.') % arg)
- return data
- def get(arg):
- """Obtains the contents of the .torrent metainfo file either from
- the local filesystem or from a remote server. 'arg' is either
- a filename or an URL.
- Returns a ConvertedMetainfo object which is the parsed metainfo
- from the contents of the .torrent file. Any exception raised
- while obtaining the .torrent file or parsing its contents is
- caught and wrapped in one of the following errors:
- GetTorrent.URLException, GetTorrent.FileException,
- GetTorrent.MetainfoException, or GetTorrent.UnknownArgument.
- (All have the base class GetTorrent.GetTorrentException)
- """
- data = _get(arg)
- metainfo = None
- try:
- b = bdecode(data)
- metainfo = ConvertedMetainfo(b)
- except Exception, e:
- raise MetainfoException(
- (_('"%s" is not a valid torrent file (%s).') % (arg, unicode(e)))
- )
- return metainfo
- def get_url(url):
- """Downloads the .torrent metainfo file specified by the passed
- URL and returns data, the raw contents of the metainfo file.
- Any exception raised while trying to obtain the metainfo file
- is caught and GetTorrent.URLException is raised instead.
- """
- data = None
- err_str = ((_('Could not download or open "%s"')% url) + '\n' +
- _("Try using a web browser to download the torrent file."))
- u = None
- # pending protocol changes, convert:
- # torrent://http://path.to/file
- # and:
- # bittorrent://http://path.to/file
- # to:
- # http://path.to/file
- url = urlpat_torrent.sub('', url)
- url = urlpat_bittorrent.sub('', url)
-
- try:
- u = zurllib.urlopen(url)
- data = u.read()
- u.close()
- except Exception, e:
- if u is not None:
- u.close()
- raise URLException(err_str + "\n(%s)" % e)
- else:
- if u is not None:
- u.close()
- return data
-
- def get_file(filename):
- """Reads the .torrent metainfo file specified by the passed
- filename and returns data, the raw contents of the metainfo file.
- Any exception raised while trying to obtain the metainfo file is
- caught and GetTorrent.FileException is raised instead.
- """
- data = None
- f = None
- try:
- f = file(filename, 'rb')
- data = f.read()
- f.close()
- except Exception, e:
- if f is not None:
- f.close()
- raise FileException((_("Could not read %s") % filename) + (': %s' % unicode(e.args[0])))
- return data
|