summaryrefslogtreecommitdiffstats
path: root/module/network/FTPBase.py
diff options
context:
space:
mode:
authorGravatar mkaay <mkaay@mkaay.de> 2010-12-19 14:12:03 +0100
committerGravatar mkaay <mkaay@mkaay.de> 2010-12-19 14:12:03 +0100
commit5120d1a26cac79ab283f38db8d7f18c9c010e786 (patch)
tree219f8874869ac6f9c1656fea9df8db17b55ce034 /module/network/FTPBase.py
parentacc manager fix (diff)
downloadpyload-5120d1a26cac79ab283f38db8d7f18c9c010e786.tar.xz
new experimental backend, new gui status (unfinished)
Diffstat (limited to 'module/network/FTPBase.py')
-rw-r--r--module/network/FTPBase.py200
1 files changed, 200 insertions, 0 deletions
diff --git a/module/network/FTPBase.py b/module/network/FTPBase.py
new file mode 100644
index 000000000..9bcb9b45e
--- /dev/null
+++ b/module/network/FTPBase.py
@@ -0,0 +1,200 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+ @author: mkaay
+"""
+
+from ftplib import FTP
+
+import socket
+import socks
+
+from os.path import getsize
+from urlparse import urlparse
+from urllib2 import _parse_proxy
+
+from helper import *
+
+class FTPBase(FTP):
+ sourceAddress = ('', 0)
+
+ def setSourceAddress(self, host):
+ self.sourceAddress = (host, 0)
+
+ def connect(self, host='', port=0, timeout=30, proxies={}):
+ if host != '':
+ self.host = host
+ if port > 0:
+ self.port = port
+ self.timeout = timeout
+
+ proxytype = None
+ proxy = None
+ if proxies.has_key("socks5"):
+ proxytype = socks.PROXY_TYPE_SOCKS5
+ proxy = proxies["socks5"]
+ elif proxies.has_key("socks4"):
+ proxytype = socks.PROXY_TYPE_SOCKS4
+ proxy = proxies["socks4"]
+ if proxytype:
+ self.sock = socks.socksocket()
+ t = _parse_proxy(proxy)
+ self.sock.setproxy(proxytype, addr=t[3].split(":")[0], port=int(t[3].split(":")[1]), username=t[1], password=t[2])
+ else:
+ self.sock = socket.socket()
+ self.sock.settimeout(self.timeout)
+ self.sock.bind(self.sourceAddress)
+ self.sock.connect((self.host, self.port))
+ self.af = self.sock.family
+ self.file = self.sock.makefile('rb')
+ self.welcome = self.getresp()
+ return self.welcome
+
+class FTPDownload():
+ def __init__(self, url, filename, interface=None, bucket=None, proxies={}):
+ self.url = url
+ self.filename = filename
+
+ self.bucket = bucket
+ self.interface = interface
+ self.proxies = proxies
+
+ self.deferred = Deferred()
+
+ self.finished = False
+ self.size = None
+
+ self.speed = 0
+
+ self.abort = False
+
+ self.arrived = 0
+
+ self.startTime = None
+ self.endTime = None
+
+ self.speed = 0 #byte/sec
+ self.speedCalcTime = None
+ self.speedCalcLen = 0
+
+ self.bufferSize = 16*1024 #tune if performance is poor
+
+ self.ftp = FTPBase()
+ self.fh = None
+
+ @threaded
+ def _download(self, offset):
+ remotename = self.url.split("/")[-1]
+ cmd = "RETR %s" % remotename
+
+ self.startTime = inttime()
+ self.arrived = offset
+ conn, size = self.ftp.ntransfercmd(cmd, None if offset == 0 else offset) #explicit None
+ if size:
+ self.size = size + offset
+ while True:
+ if self.abort:
+ self.ftp.abort()
+ break
+ count = self.bufferSize
+ if self.bucket:
+ count = self.bucket.add(count)
+ if count == 0:
+ sleep(0.01)
+ continue
+
+ try:
+ data = conn.recv(count)
+ except:
+ self.deferred.error("timeout")
+
+ if self.speedCalcTime < inttime():
+ self.speed = self.speedCalcLen
+ self.speedCalcTime = inttime()
+ self.speedCalcLen = 0
+ size = len(data)
+ self.speedCalcLen += size
+ self.arrived += size
+
+ if not data:
+ break
+
+ self.fh.write(data)
+ conn.close()
+ self.endTime = inttime()
+ if not self.abort:
+ print self.ftp.voidresp() #debug
+
+ self.ftp.quit()
+ if self.abort:
+ self.deferred.error("abort")
+ elif self.size is None or self.size == self.arrived:
+ self.deferred.callback(resp)
+ else:
+ self.deferred.error("wrong content lenght")
+
+ def download(self, resume=False):
+ self.fh = open("%s.part" % self.filename, "ab" if resume else "wb")
+ offset = 0
+ if resume:
+ offset = getsize("%s.part" % self.filename)
+
+ up = urlparse(self.url)
+
+ self.ftp.connect(up.hostname, up.port if up.port else 21, proxies=self.proxies)
+ self.ftp.login(up.username, up.password)
+ self.ftp.cwd("/".join(up.path.split("/")[:-1]))
+ self.ftp.voidcmd('TYPE I')
+ self.size = self.ftp.size(self.url.split("/")[-1])
+
+ self._download(offset)
+ return self.deferred
+
+if __name__ == "__main__":
+ import sys
+ from Bucket import Bucket
+ bucket = Bucket()
+ bucket.setRate(200*1000)
+ #bucket = None
+
+ url = "ftp://mirror.sov.uk.goscomb.net/ubuntu-releases/maverick/ubuntu-10.10-desktop-i386.iso"
+
+ finished = False
+ def err(*a, **b):
+ print a, b
+ def callb(*a, **b):
+ global finished
+ finished = True
+ print a, b
+
+ print "starting"
+
+ dwnld = FTPDownload(url, "ubuntu_ftp.iso")
+ d = dwnld.download(resume=True)
+ d.addCallback(callb)
+ d.addErrback(err)
+
+ try:
+ while True:
+ if not dwnld.finished:
+ print dwnld.speed/1024, "kb/s", "size", dwnld.arrived, "/", dwnld.size#, int(float(dwnld.arrived)/dwnld.size*100), "%"
+ if finished:
+ print "- finished"
+ break
+ sleep(1)
+ except KeyboardInterrupt:
+ dwnld.abort = True
+ sys.exit()