]> code.delx.au - pymsnt/blobdiff - src/tlib/msn/msn.py
Sensible messages are now sent to both participants if a file is rejected for being...
[pymsnt] / src / tlib / msn / msn.py
index 9e558c9bbddb22e6d639587f6bf7256c60414b45..bcc9aaa04773475e77b0d9a94b65c23d6719f33e 100644 (file)
@@ -101,12 +101,11 @@ from twisted.internet import reactor, task
 from twisted.internet.defer import Deferred
 from twisted.internet.protocol import ClientFactory
 try:
-       from twisted.internet.ssl import ClientContextFactory
+    from twisted.internet.ssl import ClientContextFactory
 except ImportError:
-       print "You must install pycrypto and pyopenssl."
-       raise
+    print "You must install pycrypto and pyopenssl."
+    raise
 from twisted.python import failure, log
-from twisted.xish.domish import unescapeFromXml
 
 # Compat stuff
 from tlib import xmlw
@@ -155,7 +154,7 @@ STATUS_LUNCH   = 'LUN'
 
 PINGSPEED = 50.0
 
-DEBUGALL = False
+DEBUGALL = True
 LINEDEBUG = False
 MESSAGEDEBUG = False
 MSNP2PDEBUG = False
@@ -434,7 +433,7 @@ class MSNMessage:
         self.screenName = screenName
         self.specialMessage = specialMessage
         self.message = message
-        self.headers = {'MIME-Version' : '1.0', 'Content-Type' : 'text/plain'}
+        self.headers = {'MIME-Version' : '1.0', 'Content-Type' : 'text/plain; charset=UTF-8'}
         self.length = length
         self.readPos = 0
 
@@ -445,6 +444,11 @@ class MSNMessage:
         """
         return reduce(operator.add, [len(x[0]) + len(x[1]) + 4  for x in self.headers.items()]) + len(self.message) + 2
 
+    def delHeader(self, header):
+        """ delete the desired header """
+        if self.headers.has_key(header):
+            del self.headers[header]
+
     def setHeader(self, header, value):
         """ set the desired header """
         self.headers[header] = value
@@ -843,9 +847,8 @@ class MSNEventBase(LineReceiver):
                 self.setLineMode(extra)
                 return
         except Exception, e:
-            log.msg("Traceback - ERROR in checkMessage: " + str(e))
             self.setLineMode(extra)
-            return
+            raise
         self.gotMessage(m)
         self.setLineMode(extra)
 
@@ -1055,7 +1058,7 @@ class NotificationClient(MSNEventBase):
         p1 = lm.find("<psm>") + 5
         p2 = lm.find("</psm>")
         if p1 >= 0 and p2 >= 0:
-            personal = unescapeFromXml(message.message[p1:p2])
+            personal = xmlw.unescapeFromXml(message.message[p1:p2])
             msnContact.personal = personal
             self.contactPersonalChanged(message.userHandle, personal)
         else:
@@ -2113,14 +2116,16 @@ class SwitchboardClient(MSNEventBase):
         if not message.getHeader("P2P-Dest") == self.userHandle: return
         packet = message.message
         binaryFields = BinaryFields(packet=packet)
-        if binaryFields[0] != 0:
+        if binaryFields[5] == BinaryFields.BYEGOT:
+            pass # Ignore the ACKs to SLP messages
+        elif binaryFields[0] != 0:
             slpLink = self.slpLinks.get(binaryFields[0])
             if not slpLink:
                 # Link has been killed. Ignore
                 return
             if slpLink.remoteUser == message.userHandle:
                 slpLink.handlePacket(packet)
-        if binaryFields[5] == BinaryFields.ACK or binaryFields[5] == BinaryFields.BYEGOT:
+        elif binaryFields[5] == BinaryFields.ACK:
             pass # Ignore the ACKs to SLP messages
         else:
             slpMessage = MSNSLPMessage(packet)
@@ -2332,11 +2337,13 @@ class SwitchboardClient(MSNEventBase):
         else: id, d = self._createIDMapping()
         if message.length == 0: message.length = message._calcMessageLen()
         self.sendLine("MSG %s %s %s" % (id, message.ack, message.length))
-        # apparently order matters with at least MIME-Version and Content-Type
-        self.sendLine('MIME-Version: %s' % message.getHeader('MIME-Version'))
-        self.sendLine('Content-Type: %s' % message.getHeader('Content-Type'))
+        # Apparently order matters with these
+        orderMatters = ("MIME-Version", "Content-Type", "Message-ID")
+        for header in orderMatters:
+            if message.hasHeader(header):
+                self.sendLine("%s: %s" % (header, message.getHeader(header)))
         # send the rest of the headers
-        for header in [h for h in message.headers.items() if h[0].lower() not in ('mime-version','content-type')]:
+        for header in [h for h in message.headers.items() if h[0] not in orderMatters]:
             self.sendLine("%s: %s" % (header[0], header[1]))
         self.transport.write("\r\n")
         self.transport.write(message.message)
@@ -2713,7 +2720,9 @@ class SLPLink:
         self.seqID = SeqID()
 
     def killLink(self):
+        if MSNP2PDEBUG: log.msg("killLink")
         def kill():
+            if MSNP2PDEBUG: log.msg("killLink - kill()")
             if not self.switchboard: return
             del self.switchboard.slpLinks[self.sessionID]
             self.switchboard = None
@@ -2856,7 +2865,7 @@ class SLPLink_FileSend(SLPLink_Send):
         else:
             if slpMessage.status == "603":
                 self.acceptDeferred.callback((False,))
-            # SLPLink is over due to decline, error or BYE
+            if MSNP2PDEBUG: log.msg("SLPLink is over due to decline, error or BYE")
             self.killLink()
 
     def wait_data_ack(self, packet):
@@ -2885,7 +2894,8 @@ class SLPLink_AvatarSend(SLPLink_Send):
         self.handlePacket = lambda packet: None
 
     def handleSLPMessage(self, slpMessage):
-        self.killLink() # BYE or error
+        if MSNP2PDEBUG: log.msg("BYE or error")
+        self.killLink()
 
     def close(self):
         SLPLink_Send.close(self)
@@ -2966,12 +2976,15 @@ class SLPLink_FileReceive(SLPLink_Receive, FileReceive):
 
     def reject(self):
         # Send a 603 decline
+        if not self.switchboard: return
         self.sendSLPMessage("603", "application/x-msnmsgr-sessionreqbody", {"SessionID":self.sessionID}, branch=self.initialBranch)
         self.killLink()
 
     def accept(self, consumer):
         FileReceive.accept(self, consumer)
+        if not self.switchboard: return
         self.sendSLPMessage("200", "application/x-msnmsgr-sessionreqbody", {"SessionID":self.sessionID}, branch=self.initialBranch)
+        self.handlePacket = self.wait_data # Moved here because sometimes the second INVITE seems to be skipped
 
     def handleSLPMessage(self, slpMessage):
         if slpMessage.method == "INVITE": # The second invite
@@ -2979,9 +2992,10 @@ class SLPLink_FileReceive(SLPLink_Receive, FileReceive):
                     "Listening"   : "false",\
                     "Hashed-Nonce": "{00000000-0000-0000-0000-000000000000}"}
             self.sendSLPMessage("200", "application/x-msnmsgr-transrespbody", data, branch=slpMessage.branch)
-            self.handlePacket = self.wait_data
+#            self.handlePacket = self.wait_data # Moved up
         else:
-            self.killLink() # It's either a BYE or an error
+            if MSNP2PDEBUG: log.msg("It's either a BYE or an error")
+            self.killLink()
             # FIXME, do some error handling if it was an error
 
     def doFinished(self):
@@ -3004,7 +3018,7 @@ class SLPLink_AvatarReceive(SLPLink_Receive):
         if slpMessage.status == "200":
             self.handlePacket = self.wait_dataprep
         else:
-            # SLPLink is over due to error or BYE
+            if MSNP2PDEBUG: log.msg("SLPLink is over due to error or BYE")
             self.killLink()
 
     def doFinished(self):