]> code.delx.au - pymsnt/commitdiff
OOB file sending nearly done.
authorjamesbunton <jamesbunton@55fbd22a-6204-0410-b2f0-b6c764c7e90a>
Fri, 20 Jan 2006 07:33:58 +0000 (07:33 +0000)
committerjamesbunton <jamesbunton@55fbd22a-6204-0410-b2f0-b6c764c7e90a>
Fri, 20 Jan 2006 07:33:58 +0000 (07:33 +0000)
git-svn-id: http://delx.cjb.net/svn/pymsnt/trunk@91 55fbd22a-6204-0410-b2f0-b6c764c7e90a

committer: jamesbunton <jamesbunton@55fbd22a-6204-0410-b2f0-b6c764c7e90a>

src/baseproto/glue.py
src/ft.py
src/legacy/glue.py
src/main.py
src/misciq.py
src/tlib/msn/msnw.py
src/utils.py

index 062ce51a8601b622416ac9010e3cf7a9a53cbe1c..3e992696db5023af4442d7422d9aa88910d69830 100644 (file)
@@ -145,6 +145,9 @@ class LegacyConnection:
                """ Called whenever PyTransport wants to send a message to a remote user """
                pass
        
+       def sendFile(self, dest, fileSend):
+               """ Called whenever PyTransport wants to send a file to a remote user. Call accept(fileObj), or reject(). """
+       
        def setStatus(self, nickname, show, status):
                """ Called whenever PyTransport needs to change the status on the legacy service 
                'nickname' is the Jabber nickname, 'show' is a Jabber status description, and status
index 753474fa996d97009650a8986aee13f7e226a5d3..eb13dcd5df978860b282462dc76eb757b5a99ac0 100644 (file)
--- a/src/ft.py
+++ b/src/ft.py
@@ -12,8 +12,63 @@ import utils
 import random
 import sys
 
+
+###########
+# Sending #
+###########
+
+class FTSend:
+       """ For file transfers going from Jabber to MSN. """
+       def __init__(self, startTransfer, filename, filesize):
+               self.startTransfer = startTransfer
+               self.filename = filename
+               self.filesize = filesize
+       
+       def accept(self, legacyFileSend):
+               self.startTransfer(legacyFileSend)
+       
+       def reject(self):
+               del self.startTransfer
+
+
+try:
+       from twisted.web import http
+except ImportError:
+       try:
+               from twisted.protocols import http
+       except ImportError:
+               print "Couldn't find http.HTTPClient. If you're using Twisted 2.0, make sure that you've installed twisted.web"
+               raise
+
+class OOBSendConnector(http.HTTPClient):
+       def connectionMade(self):
+               self.sendCommand("GET", self.factory.path.encode("utf-8"))
+               self.sendHeader("Host", (self.factory.host + ":" + str(self.factory.port)).encode("utf-8"))
+               self.endHeaders()
+               self.first = True
+       
+       def handleResponsePart(self, data):
+               self.factory.consumer.write(data)
+       
+       def handleResponseEnd(self):
+               # This is called once before writing is finished, and once when the
+               # connection closes. We only consumer.close() on the second.
+               if self.first:
+                       self.first = False
+               else:
+                       self.factory.consumer.close()
+                       self.factory.consumer = None
+
+
+
+
+
+#############
+# Receiving #
+#############
+
 class FTReceive:
-       """ Manager for file transfers going from MSN to Jabber. """
+       """ For file transfers going from MSN to Jabber. """
 
        """
        Plan of action for this class:
@@ -268,7 +323,7 @@ from twisted.internet import reactor
 
 from debug import LogEvent, INFO, WARN, ERROR
 
-class Connector:
+class OOBReceiveConnector:
        def __init__(self, ftReceive, ftHttpPush):
                self.ftReceive, self.ftHttpPush = ftReceive, ftHttpPush
                self.ftReceive.legacyftp.accept(self)
@@ -283,7 +338,7 @@ class Connector:
                self.ftHttpPush.finish()
                self.ftReceive.error()
 
-class FileTransferOOB(resource.Resource):
+class FileTransferOOBReceive(resource.Resource):
        def __init__(self, port):
                LogEvent(INFO)
                self.isLeaf = True
@@ -307,7 +362,7 @@ class FileTransferOOB(resource.Resource):
                        file = self.files[filename]
                        request.setHeader("Content-Length", str(file.legacyftp.filesize))
                        request.setHeader("Content-Disposition", "attachment; filename=\"%s\"" % file.legacyftp.filename.encode("utf-8"))
-                       Connector(file, request)
+                       OOBReceiveConnector(file, request)
                        del self.files[filename]
                        return server.NOT_DONE_YET
                else:
index afd80385999ca80692b638169ab3dd0eff3992bc..84d45872f19287ea25f41c02b59f1ec16b9b09ff 100644 (file)
@@ -278,6 +278,22 @@ class LegacyConnection(msn.MSNConnection):
                        self.failedMessage(dest, body)
                        raise
        
+       def sendFile(self, dest, ftSend):
+               dest = jid2msn(dest)
+               def continueSendFile1((msnFileSend, d)):
+                       def continueSendFile2((success, )):
+                               if success:
+                                       ftSend.accept(msnFileSend)
+                               else:
+                                       sendFileFail()
+                       d.addCallbacks(continueSendFile2, sendFileFail)
+       
+               def sendFileFail():
+                       ftSend.reject()
+
+               d = msn.MSNConnection.sendFile(self, dest, ftSend.filename, ftSend.filesize)
+               d.addCallbacks(continueSendFile1, sendFileFail)
+       
        def setStatus(self, nickname, show, status):
                statusCode = presence2state(show, None)
                msn.MSNConnection.changeStatus(self, statusCode, nickname, status)
index de1165b4db9646513ca3c11360de774d3e7bdb82..76ca79600d5aebc25677971e93ec94a071d8b5b2 100644 (file)
@@ -61,7 +61,9 @@ class PyTransport(component.Service):
                self.iqAvatarFactor = misciq.IqAvatarFactory(self)
                self.connectUsers = misciq.ConnectUsers(self)
                if config.ftJabberPort: self.ftSOCKS5 = ft.Proxy65(int(config.ftJabberPort))
-               if config.ftOOBPort: self.ftOOB = ft.FileTransferOOB(int(config.ftOOBPort))
+               if config.ftOOBPort:
+                       self.ftOOBReceive = ft.FileTransferOOBReceive(int(config.ftOOBPort))
+                       self.ftOOBSend = misciq.FileTransferOOBSend(self)
                self.statistics = misciq.Statistics(self)
                self.startTime = int(time.time())
 
index 732912054b56053ab7bb742fe7c2e1dcb0c409e3..685cdc7d3548c9b48730f15a5c39f28ec6011b28 100644 (file)
@@ -2,7 +2,7 @@
 # Licensed for distribution under the GPL version 2, check COPYING for details
 
 import utils
-from twisted.internet import reactor, task
+from twisted.internet import reactor, task, protocol
 from tlib.xmlw import Element, jid
 from debug import LogEvent, INFO, WARN, ERROR
 import jabw
@@ -10,8 +10,9 @@ import legacy
 import disco
 import config
 import lang
+import ft
 import base64
-import sys
+import sys, urllib
 
 
 class ConnectUsers:
@@ -455,4 +456,68 @@ class VersionTeller:
                self.pytrans.send(iq)
 
 
+class FileTransferOOBSend:
+       def __init__(self, pytrans):
+               self.pytrans = pytrans
+               self.pytrans.discovery.addFeature(disco.IQOOB, self.incomingOOB, "USER")
+       
+       def incomingOOB(self, el):
+               errOut = lambda: self.pytrans.discovery.sendIqError(to=el.getAttribute("from"), fro=el.getAttribute("to"), ID=el.getAttribute("id"), xmlns=disco.IQOOB, etype="cancel", condition="feature-not-implemented")
+               if el.attributes["type"] != "set":
+                       return errOut()
+               for child in el.elements():
+                       if child.name == "query":
+                               query = child
+                               break
+               else:
+                       return errOut()
+               for child in query.elements():
+                       if child.name == "url":
+                               url = child.__str__()
+                               break
+               else:
+                       return errOut()
+
+               froj = jid.intern(el.getAttribute("from"))
+               toj = jid.intern(el.getAttribute("to"))
+               session = self.pytrans.sessions.get(froj.userhost(), None)
+               if not session:
+                       return errOut()
+               
+               res = utils.getURLBits(url, "http")
+               if not res:
+                       return errOut()
+               host, port, path, filename = res
+               
+
+               def sendResult():
+                       iq = Element((None, "iq"))
+                       iq.attributes["to"] = froj.full()
+                       iq.attributes["from"] = to.full()
+                       iq.attributes["type"] = "result"
+                       iq.addElement("query").attributes["xmlns"] = "jabber:iq:oob"
+                       self.pytrans.send(iq)
+
+               def startTransfer(consumer):
+                       factory = protocol.ClientFactory()
+                       factory.protocol = ft.OOBSendConnector
+                       factory.path = path
+                       factory.host = host
+                       factory.port = port
+                       factory.consumer = consumer
+                       reactor.connectTCP(host, port, factory)
+               session.legacycon.sendFile(toj.userhost(), ft.FTSend(startTransfer, filename, 1024))
+
+
+class Socks5FileTransfer:
+       def __init__(self, pytrans):
+               self.pytrans = pytrans
+               self.pytrans.discovery.addFeature(disco.SI, self.incomingSI, "USER")
+               self.pytrans.discovery.addFeature(disco.S5B, self.incomingS5B, "USER")
+       
+       def incomingSI(self, el):
+               pass
+       
+       def incomingS5B(self, el):
+               pass
 
index 0199bcebbf2ad268c62f9d3387143b2c64af4895..ace11f148c4e9f471dec9877f4fb316ebdfbdcd2 100644 (file)
@@ -142,7 +142,7 @@ class MSNConnection:
         
                @return: A Deferred, which will fire with an argument of:
                         (fileSend, d) A FileSend object and a Deferred.
-                        The Deferred will pass one argument in a tuple,
+                        The new Deferred will pass one argument in a tuple,
                         whether or not the transfer is accepted. If you
                         receive a True, then you can call write() on the
                         fileSend object to send your file. Call close()
index c27d5365df163f8a7acdec7958be0c8e8d8929f1..28181fcf68b2d3ae66b4376d956aed64cb61a8fd 100644 (file)
@@ -12,6 +12,18 @@ def socks5Hash(sid, initiator, target):
        return sha.new("%s%s%s" % (sid, initiator, target)).hexdigest()
 
 
+import urllib
+import os.path
+def getURLBits(url, assumedType=None):
+       type, rest = urllib.splittype(url)
+       if assumedType and type != assumedType:
+               return
+       hostport, path = urllib.splithost(rest)
+       host, port = urllib.splitnport(hostport, 80)
+       filename = os.path.basename(path)
+       return host, port, path, filename
+
+
 try:
        import Image
        import StringIO