home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2009 June / maximum-cd-2009-06.iso / DiscContents / digsby_setup.exe / lib / oscar / rendezvous / directim.pyo (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2009-02-26  |  9.7 KB  |  229 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.5)
  3.  
  4. from __future__ import with_statement
  5. from util import strlist, lookup_table, bitflags_enabled, myip, callsback
  6. from util.packable import Packable
  7. from oscar.rendezvous.peer import OscarPeer
  8. from oscar.rendezvous.rendezvous import rendezvous_tlvs
  9. from oscar.OscarUtil import tlv_list
  10. import oscar
  11. import common
  12. import time
  13. import struct
  14. from logging import getLogger
  15. log = getLogger('oscar.directim')
  16. info = log.info
  17. import os.path as os
  18. import wx
  19. from util.BeautifulSoup import BeautifulSoup
  20. from functools import partial
  21. from oscar import OscarException
  22. from common.Protocol import StateMixin
  23.  
  24. def directconnect(protocol, screenname):
  25.     if not isinstance(screenname, str):
  26.         raise TypeError('screenname must be a str')
  27.     
  28.     
  29.     ostrip = lambda s: s.lower().replace(' ', '')
  30.     if ostrip(screenname) == ostrip(protocol.self_buddy.name):
  31.         raise OscarException('You cannot direct connect with yourself.')
  32.     
  33.     cookie = int(time.time() ** 2)
  34.     protocol.rdv_sessions[cookie] = dim = OscarDirectIM(protocol, screenname, cookie)
  35.     dim.request()
  36.     return dim
  37.  
  38.  
  39. class ODCHeader(Packable):
  40.     fmt = strlist('\n        version    4s      # always ODC2\n        hdrlen     H       # length of header\n        one        H       # 1\n        six        H       # 6\n        zero       H       # 0\n        cookie     Q       # sixteen byte rendezvous cookie\n        null       Q\n        length     I\n        encoding   H\n        subset     H\n        flags      I\n        zero       I\n        screenname 16s\n        null2      16s ')
  41.     
  42.     def make(cls, *a, **k):
  43.         k.update(dict(version = 'ODC2', static = 76, one = 1, six = 6, zero = 0, null = 0, null2 = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'))
  44.         return cls(*a, **k)
  45.  
  46.     make = classmethod(make)
  47.     bitflags = lookup_table({
  48.         1: 'autoresponse',
  49.         2: 'typingpacket',
  50.         4: 'typed',
  51.         8: 'typing',
  52.         32: 'confirmation',
  53.         64: 'mac_confirmation' })
  54.     invars = [
  55.         (lambda o: o.version == 'ODC2')]
  56.  
  57.  
  58. class OscarDirectIM(OscarPeer, StateMixin):
  59.     
  60.     class Statuses:
  61.         DISCONNECTED = 'Disconnected'
  62.         CONNECTING = 'Connecting'
  63.         ERROR = 'Error'
  64.         CONNECTED = 'Connected'
  65.         OFFLINE = DISCONNECTED
  66.  
  67.     
  68.     class Reasons:
  69.         NONE = 'None'
  70.  
  71.     
  72.     def __init__(self, protocol, screenname, cookie):
  73.         StateMixin.__init__(self, self.Statuses.CONNECTING)
  74.         direct_im_cap = oscar.capabilities.by_name['direct_im']
  75.         OscarPeer.__init__(self, protocol, screenname, cookie, direct_im_cap)
  76.         self.buddy = protocol.buddies[screenname]
  77.  
  78.     
  79.     def accept(self):
  80.         info('%r accepted', self)
  81.         self.establish_dc()
  82.  
  83.     
  84.     def handle_request(self, rendtlvs):
  85.         self.send_rdv('cancel')
  86.  
  87.     
  88.     def setup_convo(self):
  89.         self.convo = self.protocol.convo_for(self.screenname)
  90.         self.convo.setnotifyif('type', 'dc')
  91.         self.convo.dc = self
  92.         self.change_state(self.Statuses.CONNECTED)
  93.  
  94.     
  95.     def on_odc_connection(self):
  96.         self.socket.receive_next(ODCHeader, self.odc_header_received)
  97.         self.setup_convo()
  98.         self.send_odc(flags = 96)
  99.  
  100.     
  101.     def odc_header_received(self, data):
  102.         (packet, data) = ODCHeader.unpack(data)
  103.         flags = bitflags_enabled(ODCHeader.bitflags, packet.flags)
  104.         info('incoming ODC header - enabled flags: %s', ', '.join(flags))
  105.         typeset = partial(self.convo.set_typing_status, self.screenname)
  106.         if 'typingpacket' in flags:
  107.             if 'typing' in flags:
  108.                 typeset('typing')
  109.             elif 'typed' in flags:
  110.                 typeset('typed')
  111.             else:
  112.                 typeset(None)
  113.         
  114.         next = self.socket.receive_next
  115.         leftover = packet.hdrlen - ODCHeader._struct.size
  116.         if leftover:
  117.             next(leftover, self.read_leftover(packet.length))
  118.         elif packet.length > 0:
  119.             next(packet.length, self.odc_body_received)
  120.         else:
  121.             next(ODCHeader, self.odc_header_received)
  122.  
  123.     
  124.     def read_leftover(self, paklen):
  125.         info('read %d leftover bytes', paklen)
  126.         next = self.socket.receive_next
  127.         
  128.         def callback(data):
  129.             if paklen > 0:
  130.                 next(paklen, self.odc_body_received)
  131.             else:
  132.                 next(ODCHeader, self.odc_header_received)
  133.  
  134.         return callback
  135.  
  136.     
  137.     def odc_body_received(self, data):
  138.         info('odc_body_received')
  139.         assetdir = wx.StandardPaths.Get().GetUserDataDir()
  140.         if '<BINARY>' in data:
  141.             j = data.find('<BINARY>')
  142.             soup = BeautifulSoup(data[:j])
  143.             for img in soup.html.body('img'):
  144.                 imgdata = data[j:]
  145.                 findme = ' ID="%s" SIZE="%s">' % (str(img['id']), str(img['datasize']))
  146.                 i = imgdata.find(findme)
  147.                 imgbytes = imgdata[i + len(findme):int(img['datasize']) + 33]
  148.                 imgpath = os.path.join(assetdir, os.path.split(img['src'])[1])
  149.                 img['src'] = imgpath
  150.                 del img['width']
  151.                 del img['height']
  152.                 
  153.                 try:
  154.                     f = _[2]
  155.                     f.write(imgbytes)
  156.                 finally:
  157.                     pass
  158.  
  159.             
  160.             msg = unicode(soup.html)
  161.         else:
  162.             msg = data
  163.         self.convo.incoming_message(self.screenname, msg)
  164.         self.socket.receive_next(ODCHeader, self.odc_header_received)
  165.  
  166.     
  167.     def send_odc(self, data = '', flags = 0):
  168.         bname = self.protocol.self_buddy.name
  169.         packet = ODCHeader.make(cookie = self.cookie, screenname = bname)
  170.         packet.flags = flags
  171.         if isinstance(data, list):
  172.             packet.length = sum((lambda .0: for d in .0:
  173. len(d))(data))
  174.             info('send_odc got a list, summed length is %d', packet.length)
  175.         else:
  176.             packet.length = len(data)
  177.             info('send_odc got a string, length is %d', packet.length)
  178.         packet.hdrlen = len(packet)
  179.         info('sending ODC header to screenname %s (%d bytes of %r)', bname, len(packet), str(type(packet)))
  180.         if isinstance(data, list):
  181.             self.socket.push(packet.pack() + ''.join(data))
  182.         else:
  183.             self.socket.push(packet.pack() + data)
  184.  
  185.     
  186.     def send_typing(self, status):
  187.         flag = {
  188.             'typing': 8,
  189.             'typed': 4,
  190.             None: 0 }[status]
  191.         self.send_odc(flags = 2 | flag)
  192.  
  193.     
  194.     def request(self):
  195.         self.establish_out_dc()
  196.  
  197.     
  198.     def ch2accept(self, data):
  199.         info('incoming dIM got channel 2 accept')
  200.  
  201.     
  202.     def send_message(self, message):
  203.         self.send_odc(message)
  204.  
  205.     
  206.     def decline(self):
  207.         self.send_rdv('cancel')
  208.  
  209.     
  210.     def ch2cancel(self, data):
  211.         info('%r cancelled', self)
  212.         if hasattr(self, 'convo'):
  213.             self.convo.setnotifyif('type', 'im')
  214.         
  215.         self.change_state(self.Statuses.DISCONNECTED)
  216.  
  217.     
  218.     def disconnect(self):
  219.         self.socket.close()
  220.         del self.convo.dc
  221.         self.convo.setnotifyif('type', 'im')
  222.         self.change_state(self.Statuses.DISCONNECTED)
  223.  
  224.     
  225.     def __repr__(self):
  226.         return '<OscarDirectIM with %s>' % self.screenname
  227.  
  228.  
  229.