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)
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)
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()
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()