Skip to content

Commit

Permalink
Merge pull request #714 from CastagnaIT/misc_updates
Browse files Browse the repository at this point in the history
Changes to fix high resolutions on ARM devices
  • Loading branch information
CastagnaIT authored Jun 25, 2020
2 parents 69f2594 + 45d2b26 commit 89f3808
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 20 deletions.
9 changes: 8 additions & 1 deletion resources/lib/api/website.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from __future__ import absolute_import, division, unicode_literals

import json
from re import compile as recompile, DOTALL, sub
from re import search, compile as recompile, DOTALL, sub

from future.utils import iteritems

Expand Down Expand Up @@ -183,6 +183,13 @@ def extract_session_data(content, validate=False, update_profiles=False):
if not g.LOCAL_DB.get_value('esn', table=TABLE_SESSION):
g.LOCAL_DB.set_value('esn', common.generate_android_esn() or user_data['esn'], TABLE_SESSION)
g.LOCAL_DB.set_value('locale_id', user_data.get('preferredLocale').get('id', 'en-US'))
# Extract the client version from assets core
result = search(r'-([0-9\.]+)\.js$', api_data.pop('asset_core'))
if not result:
common.error('It was not possible to extract the client version!')
api_data['client_version'] = '6.0023.976.011'
else:
api_data['client_version'] = result.groups()[0]
# Save api urls
for key, path in list(api_data.items()):
g.LOCAL_DB.set_value(key, path, TABLE_SESSION)
Expand Down
4 changes: 2 additions & 2 deletions resources/lib/common/device_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ def get_user_agent(enable_android_mediaflag_fix=False):
# the Windows UA is not limited, so we can use it to get the right video media flags.
system = 'windows'

chrome_version = 'Chrome/78.0.3904.92'
chrome_version = 'Chrome/83.0.4103.112'
base = 'Mozilla/5.0 '
base += '%PL% '
base += 'AppleWebKit/537.36 (KHTML, like Gecko) '
Expand All @@ -128,7 +128,7 @@ def get_user_agent(enable_android_mediaflag_fix=False):
# ARM based Linux
if get_machine().startswith('arm'):
# Last number is the platform version of Chrome OS
return base.replace('%PL%', '(X11; CrOS armv7l 12371.89.0)')
return base.replace('%PL%', '(X11; CrOS armv7l 13020.82.0)')
# x86 Linux
return base.replace('%PL%', '(X11; Linux x86_64)')

Expand Down
8 changes: 7 additions & 1 deletion resources/lib/services/msl/android_crypto.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,16 @@ def key_request_data(self):
raise MSLError('Widevine CryptoSession getKeyRequest failed!')

common.debug('Widevine CryptoSession getKeyRequest successful. Size: {}', len(key_request))

# Save the key request (challenge data) required for manifest requests
# Todo: to be implemented if/when it becomes mandatory
key_request = base64.standard_b64encode(key_request).decode('utf-8')
# g.LOCAL_DB.set_value('drm_session_challenge', key_request, TABLE_SESSION)

return [{
'scheme': 'WIDEVINE',
'keydata': {
'keyrequest': base64.standard_b64encode(key_request).decode('utf-8')
'keyrequest': key_request
}
}]

Expand Down
9 changes: 4 additions & 5 deletions resources/lib/services/msl/default_crypto.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def key_request_data(self):
'keydata': {
'publickey': public_key.decode('utf-8'),
'mechanism': 'JWK_RSA',
'keypairid': 'superKeyPair'
'keypairid': 'rsaKeypairId'
}}]

def encrypt(self, plaintext, esn):
Expand All @@ -78,15 +78,14 @@ def encrypt(self, plaintext, esn):
"""
init_vector = get_random_bytes(16)
cipher = AES.new(self.encryption_key, AES.MODE_CBC, init_vector)
ciphertext = base64.standard_b64encode(
cipher.encrypt(Padding.pad(plaintext.encode('utf-8'), 16))).decode('utf-8')
encryption_envelope = {
'ciphertext': '',
'ciphertext': ciphertext,
'keyid': '_'.join((esn, str(self.sequence_number))),
'sha256': 'AA==',
'iv': base64.standard_b64encode(init_vector).decode('utf-8')
}
encryption_envelope['ciphertext'] = base64.standard_b64encode(
cipher.encrypt(Padding.pad(plaintext.encode('utf-8'), 16))).decode('utf-8')

return json.dumps(encryption_envelope)

def decrypt(self, init_vector, ciphertext):
Expand Down
51 changes: 46 additions & 5 deletions resources/lib/services/msl/msl_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,34 @@ class MSLHandler(object):
licenses_session_id = []
licenses_xid = []
licenses_release_url = []
manifest_challenge = ('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')

def __init__(self):
super(MSLHandler, self).__init__()
Expand Down Expand Up @@ -183,16 +211,16 @@ def _load_manifest(self, viewable_id, esn):
'isUIAutoPlay': False,
'useHttpsStreams': True,
'imageSubtitleHeight': 1080,
'uiVersion': 'shakti-v1b8c742f',
'uiVersion': g.LOCAL_DB.get_value('ui_version', '', table=TABLE_SESSION),
'uiPlatform': 'SHAKTI',
'clientVersion': '6.0023.473.011',
'clientVersion': g.LOCAL_DB.get_value('client_version', '', table=TABLE_SESSION),
'desiredVmaf': 'plus_lts', # phone_plus_exp can be used to mobile, not tested
'supportsPreReleasePin': True,
'supportsWatermark': True,
'supportsUnequalizedDownloadables': True,
'showAllSubDubTracks': False,
'titleSpecificData': {
viewable_id: {
unicode(viewable_id): {
'unletterboxed': True
}
},
Expand All @@ -205,7 +233,18 @@ def _load_manifest(self, viewable_id, esn):
'preferAssistiveAudio': False
}

manifest = self.msl_requests.chunked_request(ENDPOINTS['manifest'],
if 'linux' in common.get_system_platform() and 'arm' in common.get_machine():
# 24/06/2020 To get until to 1080P resolutions under arm devices (ChromeOS), android excluded,
# is mandatory to add the widevine challenge data (key request) to the manifest request.
# Is not possible get the key request from the default_crypto, is needed to implement
# the wv crypto (used for android) but currently InputStreamAdaptive support this interface only
# under android OS.
# As workaround: Initially we pass an hardcoded challenge data needed to play the first video,
# then when ISA perform the license callback we replace it with the fresh license challenge data.
params['challenge'] = self.manifest_challenge

endpoint_url = ENDPOINTS['manifest'] + '?reqAttempt=1&reqPriority=0&reqName=prefetch/manifest'
manifest = self.msl_requests.chunked_request(endpoint_url,
self.msl_requests.build_request_data('/manifest', params),
esn,
disable_msl_switch=False)
Expand Down Expand Up @@ -239,7 +278,9 @@ def get_license(self, challenge, sid):
'challengeBase64': challenge,
'xid': xid
}]
response = self.msl_requests.chunked_request(ENDPOINTS['license'],
self.manifest_challenge = challenge
endpoint_url = ENDPOINTS['license'] + '?reqAttempt=1&reqPriority=0&reqName=prefetch/license'
response = self.msl_requests.chunked_request(endpoint_url,
self.msl_requests.build_request_data(self.last_license_url,
params,
'drmSessionId'),
Expand Down
7 changes: 1 addition & 6 deletions resources/lib/services/msl/msl_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@

import json
import random
import re
import time
from functools import wraps

Expand Down Expand Up @@ -160,11 +159,7 @@ def generate_logblobs_params():
screen_size = str(xbmcgui.getScreenWidth()) + 'x' + str(xbmcgui.getScreenHeight())
timestamp_utc = time.time()
timestamp = int(timestamp_utc * 1000)
client_ver = g.LOCAL_DB.get_value('asset_core', '', table=TABLE_SESSION)
app_id = int(time.time()) * 10000 + random.randint(1, 10001) # Should be used with all log requests
if client_ver:
result = re.search(r'-([0-9\.]+)\.js$', client_ver)
client_ver = result.groups()[0]

# Here you have to enter only the real data, falsifying the data would cause repercussions in netflix server logs
# therefore since it is possible to exclude data, we avoid entering data that we do not have
Expand All @@ -190,7 +185,7 @@ def generate_logblobs_params():
'type': 'startup',
'sev': 'info',
'devmod': 'chrome-cadmium',
'clver': client_ver, # e.g. '6.0021.220.051'
'clver': g.LOCAL_DB.get_value('client_version', '', table=TABLE_SESSION), # e.g. '6.0021.220.051'
'osplatform': g.LOCAL_DB.get_value('browser_info_os_name', '', table=TABLE_SESSION),
'osver': g.LOCAL_DB.get_value('browser_info_os_version', '', table=TABLE_SESSION),
'browsername': 'Chrome',
Expand Down

0 comments on commit 89f3808

Please sign in to comment.