diff options
Diffstat (limited to 'module')
| -rw-r--r-- | module/network/Browser.py | 7 | ||||
| -rw-r--r-- | module/network/FTPBase.py | 3 | ||||
| -rw-r--r-- | module/network/HTTPDownload.py | 2 | ||||
| -rw-r--r-- | module/network/XDCCBase.py | 290 | 
4 files changed, 300 insertions, 2 deletions
diff --git a/module/network/Browser.py b/module/network/Browser.py index b749a8338..90502b298 100644 --- a/module/network/Browser.py +++ b/module/network/Browser.py @@ -2,6 +2,7 @@ from HTTPBase import HTTPBase  from HTTPDownload import HTTPDownload  from os.path import exists +from randowm import randint  import zlib  from cookielib import CookieJar @@ -66,6 +67,12 @@ class Browser():          d = dwnld.download(resume=resume)          return d +     +    def xdccDownload(self, server, port, channel, bot, pack, filename, nick="pyload_%d" % randint(1000,9999), ident="pyload", real="pyloadreal"): +        dwnld = XDCCDownload(server, port, channel, bot, pack, nick, ident, real, filename, bucket=self.bucket, interface=self.interface, proxies=self.proxies) +         +        d = dwnld.download() +        return d  if __name__ == "__main__":      browser = Browser(proxies={"socks5": "localhost:5000"}) diff --git a/module/network/FTPBase.py b/module/network/FTPBase.py index 4d27585a1..da67573a3 100644 --- a/module/network/FTPBase.py +++ b/module/network/FTPBase.py @@ -133,6 +133,7 @@ class FTPDownload():                  break              self.fh.write(data) +        self.fh.close()          conn.close()          self.endTime = inttime()          if not self.abort: @@ -142,7 +143,7 @@ class FTPDownload():          if self.abort:              self.deferred.error("abort")          elif self.size is None or self.size == self.arrived: -            self.deferred.callback(resp) #@TODO resp = unresolved? +            self.deferred.callback()          else:              self.deferred.error("wrong content lenght") diff --git a/module/network/HTTPDownload.py b/module/network/HTTPDownload.py index d0e2eeb1f..1be1a4552 100644 --- a/module/network/HTTPDownload.py +++ b/module/network/HTTPDownload.py @@ -272,7 +272,7 @@ if __name__ == "__main__":      from Bucket import Bucket      bucket = Bucket()      bucket.setRate(200*1024) -    bucket = None +    #bucket = None      url = "http://speedtest.netcologne.de/test_100mb.bin" diff --git a/module/network/XDCCBase.py b/module/network/XDCCBase.py new file mode 100644 index 000000000..b242c8f27 --- /dev/null +++ b/module/network/XDCCBase.py @@ -0,0 +1,290 @@ +#!/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 +""" + +import socket +import socks +import re + +from os.path import getsize +from urlparse import urlparse +from urllib2 import _parse_proxy + +from helper import * +from time import sleep + +import struct +from select import select + +class XDCCError(Exception): +    pass + +class XDCCDownload(): +    def __init__(self, server, port, channel, bot, pack, nick, ident, real, filename, timeout=30, bucket=None, interface=None, proxies={}): +        self.server = server +        self.port = port +        self.channel = channel +        self.bot = bot +        self.pack = pack +        self.nick = nick +        self.ident = ident +        self.real = real +        self.filename = filename +        self.bucket = bucket +        self.interface = interface +        self.proxies = proxies +        self.timeout = timeout +        self.debug = 2 +         +        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.fh = None +     +    def createSocket(self): +        proxytype = None +        proxy = None +        if self.proxies.has_key("socks5"): +            proxytype = socks.PROXY_TYPE_SOCKS5 +            proxy = self.proxies["socks5"] +        elif self.proxies.has_key("socks4"): +            proxytype = socks.PROXY_TYPE_SOCKS4 +            proxy = self.proxies["socks4"] +        if proxytype: +            sock = socks.socksocket() +            t = _parse_proxy(proxy) +            sock.setproxy(proxytype, addr=t[3].split(":")[0], port=int(t[3].split(":")[1]), username=t[1], password=t[2]) +        else: +            sock = socket.socket() +        return sock +     +    def _download(self, ip, port): +        startTime = inttime() +         +        dccsock = self.createSocket() +         +        dccsock.settimeout(self.timeout) +        dccsock.bind(self.sourceAddress) +        dccsock.connect((ip, port)) +         +        # recv loop for dcc socket +        while True: +            if self.abort: +                break +            count = 4096 +            if self.bucket: +                count = self.bucket.add(count) +                if count < 4096: +                    sleep(0.01) +                    continue +             +            try: +                data = dccsock.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) +             +            # acknowledge data by sending number of recceived bytes +            dccsock.send(struct.pack('!I', self.arrived)) +         +        dccsock.close() +        self.fh.close() +         +        self.endTime = inttime() +        if self.abort: +            self.deferred.error("abort") +        elif self.size is None or self.size == self.arrived: +            self.deferred.callback() +        else: +            self.deferred.error("wrong content lenght") +     +    def download(self): +        self.fh = open(self.filename, "wb") +         +        def debug(s): +            print "XDCC:", s +         +        sock = self.createSocket() +        print self.server, self.port +        sock.connect((self.server, int(self.port))) +        _realsend = sock.send +        def send(s): +            if self.debug == 2: +                print s +            _realsend(s) +        sock.send = send +         +        sock.send("NICK %s\r\n" % self.nick) +        sock.send("USER %s %s bla :%s\r\n" % (self.ident, self.server, self.real)) +        sleep(3) +        sock.send("JOIN #%s\r\n" % self.channel) +        sock.send("PRIVMSG %s :xdcc send #%s\r\n" % (self.bot, self.pack)) +         +        # IRC recv loop +        readbuffer = "" +        dlTime = inttime() +        done = False +        retry = None +        while True: +            # done is set if we got our real link +            if done: break +             +            if retry: +                if inttime() > retry: +                    retry = None +                    dlTime = inttime() +                    sock.send("PRIVMSG %s :xdcc send #%s\r\n" % (self.bot, self.pack)) + +            else: +                if (dlTime + self.timeout) < inttime(): +                    sock.send("QUIT :byebye\r\n") +                    sock.close() +                    raise XDCCError("XDCC Bot did not answer") + + +            fdset = select([sock], [], [], 0) +            if sock not in fdset[0]: +                continue +                 +            readbuffer += sock.recv(1024) +            temp = readbuffer.split("\n") +            readbuffer = temp.pop() + +            for line in temp: +                if self.debug is 2: print "*> " + line +                line  = line.rstrip() +                first = line.split() + +                if(first[0] == "PING"): +                    sock.send("PONG %s\r\n" % first[1]) +                     +                if first[0] == "ERROR": +                    raise XDCCError("IRC-Error: %s" % line) +                     +                msg = line.split(None, 3) +                if len(msg) != 4: +                    continue +                     +                msg = { \ +                    "origin":msg[0][1:], \ +                    "action":msg[1], \ +                    "target":msg[2], \ +                    "text"  :msg[3][1:] \ +                } + + +                if self.nick == msg["target"][0:len(self.nick)] and "PRIVMSG" == msg["action"]: +                    if msg["text"] == "\x01VERSION\x01": +                        debug("XDCC: Sending CTCP VERSION.") +                        sock.send("NOTICE %s :%s\r\n" % (msg['origin'], "pyLoad! IRC Interface")) +                    elif msg["text"] == "\x01TIME\x01": +                        debug("Sending CTCP TIME.") +                        sock.send("NOTICE %s :%d\r\n" % (msg['origin'], inttime())) +                    elif msg["text"] == "\x01LAG\x01": +                        pass # don't know how to answer +                 +                if not (self.bot == msg["origin"][0:len(self.bot)]  +                    and self.nick == msg["target"][0:len(self.nick)]  +                    and msg["action"] in ("PRIVMSG", "NOTICE")): +                    continue +                     +                if self.debug is 1: +                    print "%s: %s" % (msg["origin"], msg["text"]) +                     +                if "You already requested that pack" in msg["text"]: +                    retry = inttime() + 300 +                     +                if "you must be on a known channel to request a pack" in msg["text"]: +                    raise XDCCError("Wrong channel") +             +                m = re.match('\x01DCC SEND (.*?) (\d+) (\d+)(?: (\d+))?\x01', msg["text"]) +                if m != None: +                    done = True +                 +        # get connection data +        ip = socket.inet_ntoa(struct.pack('L', socket.ntohl(int(m.group(2))))) +        port = int(m.group(3)) +        self.realfilename = m.group(1) +         +        if len(m.groups()) > 3: +            self.size = int(m.group(4)) +         +        debug("XDCC: Downloading %s from %s:%d" % (packname, ip, port)) +         +        self._download(ip, port) +        return self.deferred + +if __name__ == "__main__": +    import sys +    from Bucket import Bucket +    bucket = Bucket() +    #bucket.setRate(200*1000) +    bucket = None +     +    finished = False +    def err(*a, **b): +        print a, b +    def callb(*a, **b): +        global finished +        finished = True +        print a, b +     +    print "starting" +    dwnld = XDCCDownload("<server>", 6667, "<chan>", "<bot>", "<pack>", "<nick>", "<ident>", "<real>", "<filename>") +    d = dwnld.download() +    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()  | 
