import os, sys import uuid, hmac, hashlib, base64, time import xbmc, xbmcgui, xbmcaddon import cookielib, urllib, urllib2, json from urllib2 import URLError, HTTPError class ADOBE(): api_url = 'http://api.auth.adobe.com' base_url = 'http://sp.auth.adobe.com' activate_url = '' requestor_id = '' public_key = '' private_key = '' device_id = '' regcode = '' user_agent = 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.81 Safari/537.36' def __init__(self, service_vars): self.requestor_id = service_vars['requestor_id'] self.public_key = service_vars['public_key'] self.private_key = service_vars['private_key'] self.activate_url = service_vars['activate_url'] self.device_id = self.getDeviceID() def getDeviceID(self): addon_profile_path = xbmc.translatePath(xbmcaddon.Addon().getAddonInfo('profile')) fname = os.path.join(addon_profile_path, 'device.id') #xbmc.log("FILE PATH == "+str(fname)) if not os.path.isfile(fname): if not os.path.exists(addon_profile_path): os.makedirs(addon_profile_path) new_device_id =str(uuid.uuid1()) device_file = open(fname,'w') device_file.write(new_device_id) device_file.close() fname = os.path.join(addon_profile_path, 'device.id') device_file = open(fname,'r') device_id = device_file.readline() device_file.close() return device_id def createAuthorization(self, request_method, request_uri): nonce = str(uuid.uuid4()) epochtime = str(int(time.time() * 1000)) authorization = request_method + " requestor_id="+self.requestor_id+", nonce="+nonce+", signature_method=HMAC-SHA1, request_time="+epochtime+", request_uri="+request_uri signature = hmac.new(self.private_key , authorization, hashlib.sha1) signature = base64.b64encode(signature.digest()) authorization += ", public_key="+self.public_key+", signature="+signature return authorization def registerDevice(self): reggie_url = '/reggie/v1/'+self.requestor_id+'/regcode' authorization = self.createAuthorization('POST',reggie_url) url = self.api_url+reggie_url headers = [ ("Accept", "*/*"), ("Content-type", "application/x-www-form-urlencoded"), ("Authorization", authorization), ("Accept-Language", "en-US"), ("Accept-Encoding", "gzip, deflate"), ("User-Agent", self.user_agent), ("Connection", "Keep-Alive"), ("Pragma", "no-cache") ] body = 'registrationURL='+self.base_url+'/adobe-services' body += '&ttl=2700' body += '&deviceId='+self.device_id body += '&format=json' json_source = self.requestJSON(url, headers, body) msg = '1. Go to [B][COLOR yellow]'+self.activate_url+'[/COLOR][/B][CR]' msg += '2. Select any platform, it does not matter[CR]' msg += '3. Enter [B][COLOR yellow]'+json_source['code']+'[/COLOR][/B] as your activation code' self.regcode = json_source['code'] dialog = xbmcgui.Dialog() ok = dialog.ok('Activate Device', msg) def authorizeDevice(self, resource_id): auth_url = '/api/v1/authorize' authorization = self.createAuthorization('GET',auth_url) url = self.api_url+auth_url url += '?deviceId='+self.device_id url += '&requestor='+self.requestor_id url += '&resource='+urllib.quote(resource_id) url += '&format=json' #req = urllib2.Request(url) headers = [ ("Accept", "*/*"), ("Content-type", "application/x-www-form-urlencoded"), ("Authorization", authorization), ("Accept-Language", "en-US"), ("Accept-Encoding", "deflate"), ("User-Agent", self.user_agent), ("Connection", "Keep-Alive"), ("Pragma", "no-cache") ] json_source = self.requestJSON(url, headers) mvpd = json_source['mvpd'] return mvpd def authenticate(self): auth_url = '/api/v1/authenticate/PL2MVJL' authorization = self.createAuthorization('GET',auth_url) url = self.api_url+auth_url url += '?deviceId='+self.device_id url += '&requestor='+self.requestor_id url += '&deviceType=Win8Universal' #req = urllib2.Request(url) headers = [ ("Accept", "*/*"), ("Content-type", "application/x-www-form-urlencoded"), ("Authorization", authorization), ("Accept-Language", "en-US"), ("Accept-Encoding", "deflate"), ("User-Agent", self.user_agent), ("Connection", "Keep-Alive"), ("Pragma", "no-cache") ] json_source = self.requestJSON(url, headers) def deauthorizeDevice(self): auth_url = '/api/v1/logout' authorization = self.createAuthorization('DELETE',auth_url) url = self.api_url+auth_url url += '?deviceId='+self.device_id url += '&requestor='+self.requestor_id url += '&format=json' #req = urllib2.Request(url) headers = [ ("Accept", "*/*"), ("Content-type", "application/x-www-form-urlencoded"), ("Authorization", authorization), ("Accept-Language", "en-US"), ("Accept-Encoding", "deflate"), ("User-Agent", self.user_agent), ("Connection", "Keep-Alive"), ("Pragma", "no-cache") ] try: json_source = self.requestJSON(url, headers, None, 'DELETE') except: pass def mediaToken(self, resource_id): url = 'http://api.auth.adobe.com/api/v1/tokens/media' url += '?deviceId='+self.device_id url += '&requestor='+self.requestor_id url += '&resource='+urllib.quote(resource_id) url += '&format=json' authorization = self.createAuthorization('GET','/api/v1/tokens/media') headers = [ ("Accept", "*/*"), ("Content-type", "application/x-www-form-urlencoded"), ("Authorization", authorization), ("Accept-Language", "en-US"), ("Accept-Encoding", "deflate"), ("User-Agent", self.user_agent), ("Connection", "Keep-Alive"), ("Pragma", "no-cache") ] json_source = self.requestJSON(url, headers) return json_source['serializedToken'] def requestJSON(self, url, headers, body=None, method=None): addon_profile_path = xbmc.translatePath(xbmcaddon.Addon().getAddonInfo('profile')) cj = cookielib.LWPCookieJar(os.path.join(addon_profile_path, 'cookies.lwp')) try: cj.load(os.path.join(addon_profile_path, 'cookies.lwp'),ignore_discard=True) except: pass opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj)) opener.addheaders = headers json_source = '' try: request = urllib2.Request(url, body) if method == 'DELETE': request.get_method = lambda: method response = opener.open(request) json_source = json.load(response) response.close() self.saveCookie(cj) except HTTPError as e: if e.code == 403: msg = 'Your device is not authorized to view the selected stream.\n Would you like to authorize this device now?' dialog = xbmcgui.Dialog() answer = dialog.yesno('Account Not Authorized', msg) if answer: self.registerDevice() else: sys.exit(0) else: sys.exit(0) return json_source def saveCookie(self, cj): # Cookielib patch for Year 2038 problem # Possibly wrap this in if to check if device is using a 32bit OS for cookie in cj: # Jan, 1 2038 if cookie.expires >= 2145916800: #Jan, 1 2037 cookie.expires = 2114380800 cj.save(ignore_discard=True)