addtorrents.py :  » Network » Torrent-Swapper » swapper » ABC » Scheduler » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Network » Torrent Swapper 
Torrent Swapper » swapper » ABC » Scheduler » addtorrents.py
import sys
import wx
import os

from shutil import copy2
from string import join
from urlparse import urlsplit,urlunsplit
from urllib import quote,unquote
from sha import sha
from traceback import print_exc,print_stack
#from cStringIO import StringIO

from BitTornado.bencode import bencode,bdecode
from BitTornado.zurllib import urlopen

from ABC.Torrent.abctorrent import ABCTorrent

from Utility.compat import convertOldList
from Utility.constants import *#IGNORE:W0611

#
# Get a .torrent file from a url
#
def getTorrentFromURL(url):
    # Copy file from web and call addnewproc
    #########################################
    btmetafile = None
    try:
        url_splitted = urlsplit(url)
        h = urlopen(urlunsplit([url_splitted[0], url_splitted[1], quote(unquote(url_splitted[2])), url_splitted[3], url_splitted[4]]))
        
        btmetafile = h.read()
        h.close()
    except:
        try:
            h.close()
        except:
            pass

    return btmetafile


################################################################
#
# Class: AddTorrents
#
# Deal with adding torrents to the list
#
################################################################
class AddTorrents:
    def __init__(self, queue):
        self.queue = queue
        self.utility = queue.utility
                  
    def AddTorrentURL(self, url, caller=""):
        # Strip any leading/trailing spaces from the URL
        url = url.strip()
        
        # Copy file from web and call addnewproc
        #########################################
        btmetafile = getTorrentFromURL(url)
        if btmetafile is None:
            if caller != "web":
                #display error can't connect to server
                dialog = wx.MessageDialog(None, self.utility.lang.get('cantgettorrentfromurl') + ":\n" + url, 
                                      self.utility.lang.get('error'), wx.ICON_ERROR)
                dialog.ShowModal()
                dialog.Destroy()
                return
            return "Error=Can't get torrent from URL"

        # Backup metainfo from URL to local directory
        url_splitted = urlsplit(url)
        filename = os.path.split(stjoin([unquote(url_splitted[2]), url_splitted[3]], ''))[1]
        # If the filename is blank, then don't continue
        if not filename:
            if caller != "web":
                dialog = wx.MessageDialog(None, self.utility.lang.get('failedinvalidtorrent') + ":\n" + url, 
                                      self.utility.lang.get('error'), wx.ICON_ERROR)
                dialog.ShowModal()
                dialog.Destroy()
                return
            else:
                return "Error=Invalid torrent file"
            
        torrentsrc = os.path.join(self.utility.getConfigPath(), "torrent", filename)

        fileexists = os.access(torrentsrc, os.R_OK)

        if not fileexists:
            f = open(torrentsrc, "wb")
            f.write(btmetafile)
            f.close()
        
        # Torrent either already existed or should exist now
        dotTorrentDuplicate = True
        
        return self.AddTorrentFromFile(torrentsrc, False, dotTorrentDuplicate, caller = caller)
    
    def AddTorrentLink(self, event = None):
        starturl = ""
        try:
            # See if there's a url in the clipboard
            # If there is, use that as the default for the dialog
            text = None
            if wx.TheClipboard.Open():
                data = wx.TextDataObject()
                gotdata = wx.TheClipboard.GetData(data)
                wx.TheClipboard.Close()
                if gotdata:
                    text = data.GetText()
            if text is not None:
                if text.startswith("http://") and text.endswith(".torrent"):
                    starturl = text
        
            dialog = wx.TextEntryDialog(None, 
                                        self.utility.lang.get('enterurl'), 
                                        self.utility.lang.get('addtorrenturl_short'),
                                        starturl)

            result = dialog.ShowModal()
            btlink = dialog.GetValue()
            dialog.Destroy()

            if result != wx.ID_OK:
                return

            if btlink != "":
                self.AddTorrentURL(btlink)
        except:
            print_exc()

    def AddTorrentNoneDefault(self, event = None):
        self.AddTorrentFile(event, True)
            
    def AddTorrentFile(self, event = None, forceasklocation = False):
        dialog = wx.FileDialog(None, 
                               self.utility.lang.get('choosetorrentfile'), 
                               self.utility.getLastDir("open"), 
                               '', 
                               self.utility.lang.get('torrentfileswildcard') + ' (*.torrent)|*.torrent', 
                               wx.OPEN|wx.MULTIPLE)
        result = dialog.ShowModal()
        dialog.Destroy()
        if result != wx.ID_OK:
            return
        
        filelocation = dialog.GetPaths()

        for filepath in filelocation:
            # Arno: remember last dir
            self.utility.setLastDir("open",os.path.dirname(filepath))
            self.AddTorrentFromFile(filepath, forceasklocation)
           
    def AddTorrentFromFile(self, filepath, forceasklocation = False, dotTorrentDuplicate = False, caller = "", dest = None, caller_data = None):
        if type(filepath) is not unicode:
            filepath = unicode(filepath, sys.getfilesystemencoding())

        # Check to make sure that the source file exists
        sourcefileexists = os.access(filepath, os.R_OK)
        
        
        if not sourcefileexists:
            if caller != "web":
                dlg = wx.MessageDialog(None, 
                                       filepath + '\n' + self.utility.lang.get('failedtorrentmissing'), 
                                       self.utility.lang.get('error'), 
                                       wx.OK|wx.ICON_ERROR)
                result = dlg.ShowModal()
                dlg.Destroy()
            # What do we do if the source file doesn't exist?
            # Just return if the source file doesn't exist?
            return "Error=The source file for this torrent doesn't exist"

        #print "******** add torrent:", filepath
        
        # Make torrent directory if necessary
        self.utility.MakeTorrentDir()
      
        torrentpath = os.path.join(self.utility.getConfigPath(), "torrent")    
        filename     = os.path.split(filepath)[1]
        torrentsrc   = os.path.join(torrentpath, filename)
        dontremove = False

        fileexists = os.access(torrentsrc, os.R_OK)
        
        # If the two files are identical, just point to the
        # .torrent file in the /torrent directory
        sametorrent = self.isSameTorrent(filepath, torrentsrc)
        if sametorrent:
            filepath = torrentsrc
        
        # Is the torrent already present in the list?
        torrentinlist = self.checkForDuplicateInList(src = filepath)
        if torrentinlist:
            self.dupFileInList(filepath, caller)
            return "Error=This torrent is duplicate"
        
        if fileexists and not dotTorrentDuplicate:
            if caller != "web":
                # ignore if the src and dest files are the same
                # this means that files in the torrent directory
                # will only give a duplicate torrent error if
                # they are already loaded in the list
                # (dotTorrentDuplicate stays False and the check to
                #  see if it's in the list is performed in addNewProc)
                ##############################################
                if (filepath == torrentsrc):
                    # If addNewProc finds that the torrent is already in the proctab,
                    # we don't want to remove it otherwise the torrent that is running
                    # will be in trouble
                    dontremove = True
                else:
                    # There is a duplicate .torrent file in /torrent
                    dialog = wx.MessageDialog(None, 
                                              self.utility.lang.get('duplicatetorrentmsg'), 
                                              self.utility.lang.get('duplicatetorrent'), 
                                              wx.YES_NO|wx.ICON_EXCLAMATION)
                    result = dialog.ShowModal()
                    dialog.Destroy()
                    if(result == wx.ID_NO):
                        return "Error=This torrent is duplicate"
                    else:
                        dotTorrentDuplicate = True
            else:
                return "Error=This torrent is duplicate"
        else:
            # Either:
            # dotTorrentDuplicate was False and the file didn't exist (no change)
            # dotTorrentDuplicate was True before when coming from AddTorrentURL (still need to check the list)
            dotTorrentDuplicate = False

        # No need to copy if we're just copying the file onto itself
        if (filepath != torrentsrc):
            copy2(filepath, torrentsrc)
        success, mesg, torrent = self.addNewProc(torrentsrc, 
                                                 dest = dest,
                                                 forceasklocation = forceasklocation, 
                                                 dotTorrentDuplicate = dotTorrentDuplicate, 
                                                 dontremove = dontremove, 
                                                 caller = caller,
                                                 caller_data = caller_data)
        if success:
            return "OK"
        else:
            return "Error=" + mesg


    #
    # Add a torrent to the list
    # Torrents can be added from 3 sources:
    #   from file
    #   from URL
    #   autoadd (command line)
    #
    def addNewProc(self, src, dest = None, forceasklocation = False, dotTorrentDuplicate = False, dontremove = False, caller = "", doupdate = True, caller_data = None):
        #from file, URL maybe down torrent.lst from addProc
        # change at onChooseFile make sure they choose dest
        # dotTorrentDuplicate : To avoid asking the user twice about duplicate (for torrent file name and torrent name)
        #                       True if .torrent is duplicate ; not used if caller==web"

        # Did we succeed in adding the torrent?
        error = None
        ABCTorrentTemp = None
        
        # Check to see the the src file actually exists:
        if not os.access(src, os.R_OK):
            if caller != "web":
                dlg = wx.MessageDialog(None, 
                                       src + '\n' + self.utility.lang.get('failedtorrentmissing'), 
                                       self.utility.lang.get('error'), 
                                       wx.OK|wx.ICON_ERROR)
                result = dlg.ShowModal()
                dlg.Destroy()
                dontremove = True
            error = ".torrent file doesn't exist or can't be read"
        else:
            ABCTorrentTemp = ABCTorrent(self.queue, src, dest = dest, forceasklocation = forceasklocation, caller = caller, caller_data = caller_data )       
            
            if ABCTorrentTemp.metainfo is None:
                if caller != "web":
                    dlg = wx.MessageDialog(None, 
                                           src + '\n' + \
                                           self.utility.lang.get('failedinvalidtorrent') + '\n' + \
                                           self.utility.lang.get('removetorrent'), 
                                           self.utility.lang.get('error'), 
                                           wx.YES_NO|wx.ICON_ERROR)
                    result = dlg.ShowModal()
                    dlg.Destroy()
                    if (result == wx.ID_NO):
                        dontremove = True
                error = "Invalid torrent file"
                    
            # If the torrent doesn't have anywhere to save to, return with an error
            elif ABCTorrentTemp.files.dest is None:
                error = "No destination to save to"
    
            # Search for duplicate torrent name (inside .torrent file) and hash info
            # only if the .torrent is not already a duplicate
            elif not dotTorrentDuplicate:
                torrentInList = self.checkForDuplicateInList(ABCTorrentTemp.infohash, ABCTorrentTemp.src)
                if torrentInList:
                    self.dupFileInList(src, caller)
#                    if caller != "web":
#                        message = src + '\n\n' + self.utility.lang.get('duplicatetorrentinlist')
#                        dlg = wx.MessageDialog(None, 
#                                               message, 
#                                               self.utility.lang.get('duplicatetorrent'), 
#                                               wx.OK|wx.ICON_ERROR)
#                        dlg.ShowModal()
#                        dlg.Destroy()
                    error = "Duplicate torrent"

        # We encountered an error somewhere in the process
        if error is not None:
            # Don't remove if the torrent file is already being used by an existing process
            # Removing will cause problems with the other process
            if not dontremove:
                try:
                    os.remove(src)
                except:
                    pass
            ABCTorrentTemp = None
            return False, error, ABCTorrentTemp
       
        if doupdate and ABCTorrentTemp is not None:
            ABCTorrentTemp.postInitTasks()
            
            # Update torrent.list
            ABCTorrentTemp.torrentconfig.writeSrc(False)
            self.utility.torrentconfig.Flush()
            
            self.queue.updateAndInvoke()
        
        return True, self.utility.lang.get('ok'), ABCTorrentTemp
        
    #
    # Add a torrent that's already been loaded into the list
    #
    def addOldProc(self, src):       
        # Torrent information
        filename = os.path.join(self.utility.getConfigPath(), "torrent", src)
        
        success, error, ABCTorrentTemp = self.addNewProc(filename, dest = None, doupdate = False)
        
        if not success:
            # Didn't get a valid ABCTorrent object
            return False
        
        ABCTorrentTemp.postInitTasks()
        
        return True
             
    #
    # Load torrents from the torrent.list file
    #
    def readTorrentList(self):
        # Convert list in older format if necessary
        convertOldList(self.utility)
        
        numbackups = 3
        
        # Manage backups
        filenames = [ os.path.join(self.utility.getConfigPath(), "torrent.list") ]
        for i in range(1, numbackups + 1):
            filenames.append(filenames[0] + ".backup" + str(i))
            
        for i in range (numbackups, 0, -1):
            if os.access(filenames[i-1], os.R_OK):
                copy2(filenames[i-1], filenames[i])
        
        oldprocs = []
        for index, src in self.utility.torrentconfig.Items():
            try:
                index = int(index)
                oldprocs.append((index, src))
            except:
                pass
        oldprocs.sort()
        
        for index, src in oldprocs:
            self.addOldProc(src)
            
        self.queue.updateAndInvoke()

    #
    # Compare two torrents to see if they are the same
    #
    def isSameTorrent(self, torrent1src, torrent2src):
        # Same location
        if torrent1src == torrent2src:
            return True

        metainfo1 = self.utility.getMetainfo(torrent1src)
        if metainfo1 is None:
            return False
        
        metainfo2 = self.utility.getMetainfo(torrent2src)
        if metainfo2 is None:
            return False
        
        metainfo_hash1 = sha(bencode(metainfo1)).hexdigest()
        metainfo_hash2 = sha(bencode(metainfo2)).hexdigest()
        
        # Hash values for both torrents are the same
        if metainfo_hash1 == metainfo_hash2:
            return True
            
        return False

    #
    # Duplicate file error
    #
    def dupFileInList(self, src, caller = ""):
        if caller != "web":
            message = src + '\n\n' + self.utility.lang.get('duplicatetorrentinlist')
            dlg = wx.MessageDialog(None, 
                                   message, 
                                   self.utility.lang.get('duplicatetorrent'), 
                                   wx.OK|wx.ICON_ERROR)
            dlg.ShowModal()
            dlg.Destroy()

    #
    # See if a torrent already in the list has the same infohash
    #
    def checkForDuplicateInList(self, infohash = None, src = None):
        for torrent in self.utility.torrents["all"]:
            if (src is not None and src == torrent.src) or \
               (infohash is not None and infohash == torrent.infohash):
                return True
        return False
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.