コード例 #1
0
ファイル: yahoologinbase.py プロジェクト: niterain/digsby
    def yahoo_v15_auth(self, challenge, password, username, jar=None, callback=None):
        jar = jar if jar is not None else cookielib.CookieJar()
        http_opener = CookieJarHTTPMaster(jar=jar)

        from time import time

        now = int(time())

        def bar(req, resp):
            resp = resp.read()
            log.info("Yahoo response starts: %r", resp[:100])
            if not resp.startswith("0"):
                return callback.error(YahooAuthException(resp))
            token = resp.split("\r\n")[1].split("=")[1]
            url2 = util.net.UrlQuery(
                "https://login.yahoo.com/config/pwtoken_login", src="ymsgr", ts=str(now), token=token
            )
            http_opener.open(
                url2,
                success=lambda req, resp: self.cookie_crumbs_success(resp, jar, callback=callback),
                error=callback.error,
            )

        url_password = util.net.UrlQuery(
            "https://login.yahoo.com/config/pwtoken_get",
            src="ymsgr",
            ts=str(now),
            login=username,
            passwd=password,
            chal=challenge,
        )
        http_opener.open(url_password, success=bar, error=callback.error)
コード例 #2
0
    def init_vars(self):
        self.ClientCounter = 0

        #I kid you not, an 8 digit integer string representation encoded in hex
        # from the last 8 digits of the string representation of the lower word
        # of GetSystemTimeAsFileTime.  Random seems just as good, since that value
        # in units of 100 nanoseconds, 8 digits will cycle every 10 seconds
        #http://forum.sharpdressedcodes.com/index.php?showtopic=589
        #wtfinterns?
        from random import randint
        self.secret = '%08d' % randint(0, int('9' * 8))
        self.Secret = (self.secret).encode('hex')
        self.jar = cookielib.CookieJar()

        self.client_http_opener = CookieJarHTTPMaster(jar=self.jar)
        self.server_http_opener = CookieJarHTTPMaster(jar=self.jar)
コード例 #3
0
    def init_vars(self):
        self.ClientCounter = 0

        #I kid you not, an 8 digit integer string representation encoded in hex
        # from the last 8 digits of the string representation of the lower word
        # of GetSystemTimeAsFileTime.  Random seems just as good, since that value
        # in units of 100 nanoseconds, 8 digits will cycle every 10 seconds
        #http://forum.sharpdressedcodes.com/index.php?showtopic=589
        #wtfinterns?
        from random import randint
        self.secret = '%08d' % randint(0, int('9'*8))
        self.Secret = (self.secret).encode('hex')
        self.jar = cookielib.CookieJar()

        self.client_http_opener = CookieJarHTTPMaster(jar=self.jar)
        self.server_http_opener = CookieJarHTTPMaster(jar=self.jar)
コード例 #4
0
    def yahoo_v15_auth(self,
                       challenge,
                       password,
                       username,
                       jar=None,
                       callback=None):
        jar = jar if jar is not None else cookielib.CookieJar()
        http_opener = CookieJarHTTPMaster(jar=jar)

        from time import time
        now = int(time())

        def bar(req, resp):
            resp = resp.read()
            log.info('Yahoo response starts: %r', resp[:100])
            if not resp.startswith('0'):
                return callback.error(YahooAuthException(resp))
            token = resp.split('\r\n')[1].split('=')[1]
            url2 = util.net.UrlQuery(
                "https://login.yahoo.com/config/pwtoken_login",
                src='ymsgr',
                ts=str(now),
                token=token)
            http_opener.open(
                url2,
                success=lambda req, resp: self.cookie_crumbs_success(
                    resp, jar, callback=callback),
                error=callback.error)

        url_password = util.net.UrlQuery(
            "https://login.yahoo.com/config/pwtoken_get",
            src='ymsgr',
            ts=str(now),
            login=username,
            passwd=password,
            chal=challenge)
        http_opener.open(url_password, success=bar, error=callback.error)
コード例 #5
0
class YahooHTTPConnection(YahooConnectionBase, YahooLoginBase):
    def __init__(self, yahoo, server):
        YahooConnectionBase.__init__(self, yahoo)
        YahooLoginBase.__init__(self, yahoo)
        self.server = server
        self.init_vars()
        self.handle_connect()

    def init_vars(self):
        self.ClientCounter = 0

        #I kid you not, an 8 digit integer string representation encoded in hex
        # from the last 8 digits of the string representation of the lower word
        # of GetSystemTimeAsFileTime.  Random seems just as good, since that value
        # in units of 100 nanoseconds, 8 digits will cycle every 10 seconds
        #http://forum.sharpdressedcodes.com/index.php?showtopic=589
        #wtfinterns?
        from random import randint
        self.secret = '%08d' % randint(0, int('9' * 8))
        self.Secret = (self.secret).encode('hex')
        self.jar = cookielib.CookieJar()

        self.client_http_opener = CookieJarHTTPMaster(jar=self.jar)
        self.server_http_opener = CookieJarHTTPMaster(jar=self.jar)

    def close(self):
        self._close_server()
        #if we don't inform the server that we're leaving, we won't appear offline until
        # it decides we have timed-out.
        if self.client_http_opener is not None:
            self._push_cb(self.yahoo.yahoo_packet('logoff', 'available'),
                          success=self._close_client,
                          error=self._close_client)

    def _close_server(self, *a):
        self.server_http_opener, sho = None, self.server_http_opener

        if sho is not None:
            sho.close_all()

    def _close_client(self, *a):
        self.client_http_opener, cho = None, self.client_http_opener

        if cho is not None:
            cho.close_all()

    @classmethod
    def to_ydict(cls, d):
        if not d:
            return ''

        def to_ydict_entry(k, v):
            try:
                n = int(k)
            except ValueError:
                try:
                    n = ykeys[k]
                except:
                    log.warning(
                        'to_ydict got a dict with a non number key: %s', k)
                    return ''

            try:
                v = str(v)
            except UnicodeEncodeError:
                v = unicode(v).encode('utf-8')

            return ''.join([str(n), argsep, encode_caret(v), argsep])

        # find some way to iterate
        if hasattr(d, 'iteritems'): item_iterator = d.iteritems()
        elif isinstance(d, (list, tuple)):
            item_iterator = izip(d[::2], d[1::2])

        return ''.join(to_ydict_entry(k, v) for k, v in item_iterator)

    @classmethod
    def from_ydict(cls, data):
        d = {}
        for k, v in cls.from_ydict_iter(data):
            if k in d:
                log.warning('duplicate %s: %s', k, v)
                #raise AssertionError()
            d[k] = v
        return d

    @classmethod
    def from_ydict_iter(cls, data):
        rval = None
        retval = []
        for val in parser_re.split(data):
            if odd_caret_dollar_re.match(val) is not None:
                if rval is None:
                    retval.append(decode_caret(val[:-2]))
                else:
                    retval.append(decode_caret(rval + val[:-2]))
                rval = None
            else:
                if rval is None:
                    rval = val
                else:
                    rval += val

        keys, values = retval[::2], retval[1::2]

        # see note in yahooutil:from_ydict_iter
        values = [from_utf8(v) for v in values]

        return izip(keys, values)

    def ypacket_pack(self, command, status, version, data):
        data = self.to_ydict(data)
        return Ymsg(command,
                    status,
                    version,
                    data,
                    vendor_id='0',
                    session=self)

    def push(self, packet, count=0):
        self._push_cb(packet,
                      success=self.recieve_response,
                      error=lambda *a: self.handle_client_stream_error(
                          packet=packet, count=count, *a))

    @callsback
    def _push_cb(self, packet, callback=None):
        http, to_send = self.wrap_packet(packet)
        self._client_send(http, to_send, callback=callback)

    def wrap_packet(self, packet):
        is_auth = getattr(packet, '_yahoo_auth', False)
        http = 'http'
        if is_auth:
            http = 'https'
            assert self.ClientCounter == 0
            to_send = SessionWrapper(packet, self)
        else:
            to_send = SessionWrapper(packet, self)
        self.ClientCounter += 1
        return http, to_send

    @callsback
    def _client_send(self, http, to_send, callback=None):
        if self.client_http_opener is None:
            callback.error(Exception("Not connected"))
            if self.yahoo:
                self.yahoo.set_disconnected(self.yahoo.Reasons.CONN_LOST)
            return

        log.debug_s('yahoo sending\n%r', str(to_send))
        self.client_http_opener.open(http + '://' + self.server + '/',
                                     str(to_send),
                                     callback=callback)
        #if request already in progress, wait, let responses go first?  keep order separate until actually sending.

    def server_update(self):
        to_send = SessionWrapper(None, self, server=True)
        self.ClientCounter += 1
        log.debug_s('yahoo sending\n%r', str(to_send))
        self.server_http_opener.open('http://' + self.server + '/',
                                     str(to_send),
                                     success=self.server_response,
                                     error=self.handle_server_stream_error)
        #wait for list15 "online" to start this chain.
        #SessionWrapper(None, self, server=True), send on server connection.
        #wait for response, send again.

    def server_response(self, req, resp=None):
        try:
            self.recieve_response(req, resp)
        except Exception:
            pass
        self.server_update()

    def handle_server_stream_error(self, req, resp=None, *a, **k):
        log.error('handle_server_stream_error %r, %r, %r, %r', req, resp, a, k)
        if isinstance(resp, RESPONSE_TYPES):
            return self.server_response(req, resp)
        if isinstance(req, HTTPError) or isinstance(resp, HTTPError):
            return self.server_response(req, resp)
        import traceback
        traceback.print_exc()
        self.close()
        if self.yahoo:
            self.yahoo.set_disconnected(self.yahoo.Reasons.CONN_LOST)

    def handle_client_stream_error(self,
                                   req,
                                   resp=None,
                                   packet=None,
                                   count=0,
                                   *a,
                                   **k):
        log.error('handle_client_stream_error %r, %r, %r, %r, %r, %r', req,
                  resp, packet, count, a, k)
        if resp is None:  #urllib compatibility
            resp = req
            del req
        #it's not going to be a 200 if we're in the error handler, no need to check that here.

        if isinstance(resp, RESPONSE_TYPES) or isinstance(resp, HTTPError):
            if count < 3:
                return self.push(packet, count + 1)

        self.close()
        if self.yahoo:
            self.yahoo.set_disconnected(self.yahoo.Reasons.CONN_LOST)

    def handle_connect(self):
        return self.async_proc(self.logon())

    def send_auth_req(self, user):
        cmd, wait, pkt = super(YahooHTTPConnection, self).send_auth_req(user)
        pkt._yahoo_auth = True
        return cmd, wait, pkt

    def recieve_response(self, req, resp=None):
        if resp is None:  #urllib compatibility
            resp = req
            del req
        #should probably all be treated the same, who knows what can come back from where, nor should we care.
        data = resp.read()

        log.debug_s('yahoo recieved\n%r', data)

        Session = tag(data)
        #deal with sequence numbers
        if Session['Payload'] == 'yes':
            ymsg = Session.Ymsg
            if not isinstance(ymsg, list):
                ymsg = [ymsg]
            for pkt in ymsg:
                self.handle_packet(pkt, Session)
        try:
            self.ServerSeqno = Session['ServerSeqno']
        except KeyError:
            pass

    def handle_packet(self, pkt, session):
        from util import Storage
        header = Storage()
        header.command = int(pkt['Command'])
        header.status = int(pkt['Status'])
        account_id, session_id = session['SessionId'].split('-', 1)
        self.account_id = account_id
        header.session_id = self.session_id = int(session_id)
        data = pkt._cdata.strip().encode('utf-8')
        YahooConnectionBase.handle_packet(self, header, data)
        if header.command == 241 and header.status == 0:
            self.server_update()
コード例 #6
0
class YahooHTTPConnection(YahooConnectionBase, YahooLoginBase):
    def __init__(self, yahoo, server):
        YahooConnectionBase.__init__(self, yahoo)
        YahooLoginBase.__init__(self, yahoo)
        self.server = server
        self.init_vars()
        self.handle_connect()

    def init_vars(self):
        self.ClientCounter = 0

        #I kid you not, an 8 digit integer string representation encoded in hex
        # from the last 8 digits of the string representation of the lower word
        # of GetSystemTimeAsFileTime.  Random seems just as good, since that value
        # in units of 100 nanoseconds, 8 digits will cycle every 10 seconds
        #http://forum.sharpdressedcodes.com/index.php?showtopic=589
        #wtfinterns?
        from random import randint
        self.secret = '%08d' % randint(0, int('9'*8))
        self.Secret = (self.secret).encode('hex')
        self.jar = cookielib.CookieJar()

        self.client_http_opener = CookieJarHTTPMaster(jar=self.jar)
        self.server_http_opener = CookieJarHTTPMaster(jar=self.jar)

    def close(self):
        self._close_server()
        #if we don't inform the server that we're leaving, we won't appear offline until
        # it decides we have timed-out.
        if self.client_http_opener is not None:
            self._push_cb(self.yahoo.yahoo_packet('logoff', 'available'),
                         success = self._close_client,
                         error   = self._close_client)

    def _close_server(self, *a):
        self.server_http_opener, sho = None, self.server_http_opener

        if sho is not None:
            sho.close_all()

    def _close_client(self, *a):
        self.client_http_opener, cho = None, self.client_http_opener

        if cho  is not None:
            cho.close_all()

    @classmethod
    def to_ydict(cls, d):
        if not d:
            return ''

        def to_ydict_entry(k, v):
            try: n = int(k)
            except ValueError:
                try:
                    n = ykeys[k]
                except:
                    log.warning('to_ydict got a dict with a non number key: %s', k)
                    return ''

            try:
                v = str(v)
            except UnicodeEncodeError:
                v = unicode(v).encode('utf-8')

            return ''.join([str(n), argsep, encode_caret(v), argsep])

        # find some way to iterate
        if hasattr(d, 'iteritems'):        item_iterator = d.iteritems()
        elif isinstance(d, (list, tuple)): item_iterator = izip(d[::2],d[1::2])

        return ''.join(to_ydict_entry(k,v) for k,v in item_iterator)

    @classmethod
    def from_ydict(cls, data):
        d = {}
        for k, v in cls.from_ydict_iter(data):
            if k in d:
                log.warning('duplicate %s: %s', k, v)
                #raise AssertionError()
            d[k] = v
        return d

    @classmethod
    def from_ydict_iter(cls, data):
        rval = None
        retval = []
        for val in parser_re.split(data):
            if odd_caret_dollar_re.match(val) is not None:
                if rval is None:
                    retval.append(decode_caret(val[:-2]))
                else:
                    retval.append(decode_caret(rval+val[:-2]))
                rval = None
            else:
                if rval is None:
                    rval = val
                else:
                    rval += val

        keys, values = retval[::2], retval[1::2]

        # see note in yahooutil:from_ydict_iter
        values = [from_utf8(v) for v in values]

        return izip(keys, values)

    def ypacket_pack(self, command, status, version, data):
        data = self.to_ydict(data)
        return Ymsg(command, status, version, data, vendor_id='0', session=self)

    def push(self, packet, count=0):
        self._push_cb(packet,
                     success = self.recieve_response,
                     error = lambda *a: self.handle_client_stream_error(packet=packet, count=count, *a))

    @callsback
    def _push_cb(self, packet, callback=None):
        http, to_send = self.wrap_packet(packet)
        self._client_send(http, to_send, callback=callback)

    def wrap_packet(self, packet):
        is_auth = getattr(packet, '_yahoo_auth', False)
        http = 'http'
        if is_auth:
            http = 'https'
            assert self.ClientCounter == 0
            to_send = SessionWrapper(packet, self)
        else:
            to_send = SessionWrapper(packet, self)
        self.ClientCounter += 1
        return http, to_send

    @callsback
    def _client_send(self, http, to_send, callback=None):
        if self.client_http_opener is None:
            callback.error(Exception("Not connected"))
            if self.yahoo:
                self.yahoo.set_disconnected(self.yahoo.Reasons.CONN_LOST)
            return

        log.debug_s('yahoo sending\n%r', str(to_send))
        self.client_http_opener.open(http + '://' + self.server + '/', str(to_send),
                                     callback=callback)
        #if request already in progress, wait, let responses go first?  keep order separate until actually sending.

    def server_update(self):
        to_send = SessionWrapper(None, self, server=True)
        self.ClientCounter += 1
        log.debug_s('yahoo sending\n%r', str(to_send))
        self.server_http_opener.open('http://' + self.server + '/', str(to_send),
                                                success = self.server_response,
                                                error = self.handle_server_stream_error)
        #wait for list15 "online" to start this chain.
        #SessionWrapper(None, self, server=True), send on server connection.
        #wait for response, send again.

    def server_response(self, req, resp=None):
        try:
            self.recieve_response(req, resp)
        except Exception:
            pass
        self.server_update()

    def handle_server_stream_error(self, req, resp=None, *a, **k):
        log.error('handle_server_stream_error %r, %r, %r, %r', req, resp, a, k)
        if isinstance(resp, RESPONSE_TYPES):
            return self.server_response(req, resp)
        if isinstance(req, HTTPError) or isinstance(resp, HTTPError):
            return self.server_response(req, resp)
        import traceback;traceback.print_exc()
        self.close()
        if self.yahoo:
            self.yahoo.set_disconnected(self.yahoo.Reasons.CONN_LOST)

    def handle_client_stream_error(self, req, resp=None, packet=None, count=0, *a, **k):
        log.error('handle_client_stream_error %r, %r, %r, %r, %r, %r', req, resp, packet, count, a, k)
        if resp is None: #urllib compatibility
            resp = req
            del req
        #it's not going to be a 200 if we're in the error handler, no need to check that here.

        if isinstance(resp, RESPONSE_TYPES) or isinstance(resp, HTTPError):
            if count < 3:
                return self.push(packet, count + 1)

        self.close()
        if self.yahoo:
            self.yahoo.set_disconnected(self.yahoo.Reasons.CONN_LOST)

    def handle_connect(self):
        return self.async_proc(self.logon())

    def send_auth_req(self, user):
        cmd, wait, pkt = super(YahooHTTPConnection, self).send_auth_req(user)
        pkt._yahoo_auth = True
        return cmd, wait, pkt

    def recieve_response(self, req, resp=None):
        if resp is None: #urllib compatibility
            resp = req
            del req
        #should probably all be treated the same, who knows what can come back from where, nor should we care.
        data = resp.read()

        log.debug_s('yahoo recieved\n%r', data)

        Session = tag(data)
        #deal with sequence numbers
        if Session['Payload'] == 'yes':
            ymsg = Session.Ymsg
            if not isinstance(ymsg, list):
                ymsg = [ymsg]
            for pkt in ymsg:
                self.handle_packet(pkt, Session)
        try:
            self.ServerSeqno = Session['ServerSeqno']
        except KeyError:
            pass

    def handle_packet(self, pkt, session):
        from util import Storage
        header = Storage()
        header.command = int(pkt['Command'])
        header.status  = int(pkt['Status'])
        account_id, session_id = session['SessionId'].split('-', 1)
        self.account_id = account_id
        header.session_id = self.session_id = int(session_id)
        data = pkt._cdata.strip().encode('utf-8')
        YahooConnectionBase.handle_packet(self, header, data)
        if header.command == 241 and header.status == 0:
            self.server_update()