Dont include token in URLs unless show_secrets set in config; All functions that return a URL such as stream urls and thumbnails still include token

This commit is contained in:
Michael Shepanski 2018-01-04 21:44:35 -05:00
parent 68f73e151e
commit 61ede66ad5
9 changed files with 40 additions and 35 deletions

View file

@ -29,7 +29,7 @@ class AlertListener(threading.Thread):
def run(self):
# create the websocket connection
url = self._server.url(self.key).replace('http', 'ws')
url = self._server.url(self.key, includeToken=True).replace('http', 'ws')
log.info('Starting AlertListener: %s', url)
self._ws = websocket.WebSocketApp(url, on_message=self._onMessage,
on_error=self._onError)

View file

@ -45,18 +45,17 @@ class Audio(PlexPartialObject):
def thumbUrl(self):
""" Return url to for the thumbnail image. """
key = self.firstAttr('thumb', 'parentThumb', 'granparentThumb')
return self._server.url(key) if key else None
return self._server.url(key, includeToken=True) if key else None
@property
def artUrl(self):
""" Return the first first art url starting on the most specific for that item."""
""" Return the first art url starting on the most specific for that item."""
art = self.firstAttr('art', 'grandparentArt')
return self._server.url(art) if art else None
return self._server.url(art, includeToken=True) if art else None
def url(self, part):
""" Returns the full URL for something. Typically used for getting a specific image. """
if part:
return self._server.url(part)
""" Returns the full URL for this audio item. Typically used for getting a specific track. """
return self._server.url(part, includeToken=True) if part else None
@utils.registerPlexObject

View file

@ -479,7 +479,7 @@ class Playable(object):
# sort the keys since the randomness fucks with my tests..
sorted_params = sorted(params.items(), key=lambda val: val[0])
return self._server.url('/%s/:/transcode/universal/start.m3u8?%s' %
(streamtype, urlencode(sorted_params)))
(streamtype, urlencode(sorted_params)), includeToken=True)
def iterParts(self):
""" Iterates over the parts of this media item. """
@ -530,9 +530,8 @@ class Playable(object):
download_url = self.getStreamURL(**kwargs)
else:
download_url = self._server.url('%s?download=1' % location.key)
filepath = utils.download(download_url, filename=filename,
savepath=savepath, session=self._server._session)
filepath = utils.download(download_url, self._server._token, filename=filename,
savepath=savepath, session=self._server._session)
if filepath:
filepaths.append(filepath)
return filepaths

View file

@ -65,6 +65,7 @@ class PlexClient(PlexObject):
super(PlexClient, self).__init__(server, data, initpath)
self._baseurl = baseurl.strip('/') if baseurl else None
self._token = logfilter.add_secret(token)
self._showSecrets = CONFIG.get('log.show_secrets', '').lower() == 'true'
server_session = server._session if server else None
self._session = session or server_session or requests.Session()
self._proxyThroughServer = False
@ -193,11 +194,13 @@ class PlexClient(PlexObject):
return self._server.query(key, headers=headers)
return self.query(key, headers=headers)
def url(self, key):
""" Build a URL string with proper token argument. """
def url(self, key, includeToken=False):
""" Build a URL string with proper token argument. Token will be appended to the URL
if either includeToken is True or CONFIG.log.show_secrets is 'true'.
"""
if not self._baseurl:
raise BadRequest('PlexClient object missing baseurl.')
if self._token:
if self._token and (includeToken or self._showSecrets):
delim = '&' if '?' in key else '?'
return '%s%s%sX-Plex-Token=%s' % (self._baseurl, key, delim, self._token)
return '%s%s' % (self._baseurl, key)

View file

@ -94,6 +94,7 @@ class PlexServer(PlexObject):
def __init__(self, baseurl=None, token=None, session=None, timeout=None):
self._baseurl = baseurl or CONFIG.get('auth.server_baseurl', 'http://localhost:32400')
self._token = logfilter.add_secret(token or CONFIG.get('auth.server_token'))
self._showSecrets = CONFIG.get('log.show_secrets', '').lower() == 'true'
self._session = session or requests.Session()
self._library = None # cached library
self._settings = None # cached settings
@ -265,7 +266,7 @@ class PlexServer(PlexObject):
unpack (bool): Unpack the zip file.
"""
url = self.url('/diagnostics/databases')
filepath = utils.download(url, None, savepath, self._session, unpack=unpack)
filepath = utils.download(url, self._token, None, savepath, self._session, unpack=unpack)
return filepath
def downloadLogs(self, savepath=None, unpack=False):
@ -276,7 +277,7 @@ class PlexServer(PlexObject):
unpack (bool): Unpack the zip file.
"""
url = self.url('/diagnostics/logs')
filepath = utils.download(url, None, savepath, self._session, unpack=unpack)
filepath = utils.download(url, self._token, None, savepath, self._session, unpack=unpack)
return filepath
def check_for_update(self, force=True, download=False):
@ -410,11 +411,13 @@ class PlexServer(PlexObject):
if media:
transcode_url = '/photo/:/transcode?height=%s&width=%s&opacity=%s&saturation=%s&url=%s' % (
height, width, opacity, saturation, media)
return self.url(transcode_url)
return self.url(transcode_url, includeToken=True)
def url(self, key):
""" Build a URL string with proper token argument. """
if self._token:
def url(self, key, includeToken=None):
""" Build a URL string with proper token argument. Token will be appended to the URL
if either includeToken is True or CONFIG.log.show_secrets is 'true'.
"""
if self._token and (includeToken or self._showSecrets):
delim = '&' if '?' in key else '?'
return '%s%s%sX-Plex-Token=%s' % (self._baseurl, key, delim, self._token)
return '%s%s' % (self._baseurl, key)

View file

@ -223,13 +223,14 @@ def downloadSessionImages(server, filename=None, height=150, width=150,
return info
def download(url, filename=None, savepath=None, session=None, chunksize=4024,
def download(url, token, filename=None, savepath=None, session=None, chunksize=4024,
unpack=False, mocked=False, showstatus=False):
""" Helper to download a thumb, videofile or other media item. Returns the local
path to the downloaded file.
Parameters:
url (str): URL where the content be reached.
token (str): Plex auth token to include in headers.
filename (str): Filename of the downloaded file, default None.
savepath (str): Defaults to current working dir.
chunksize (int): What chunksize read/write at the time.
@ -245,7 +246,8 @@ def download(url, filename=None, savepath=None, session=None, chunksize=4024,
from plexapi import log
# fetch the data to be saved
session = session or requests.Session()
response = session.get(url, stream=True)
headers = {'X-Plex-Token': token}
response = session.get(url, headers=headers, stream=True)
# make sure the savepath directory exists
savepath = savepath or os.getcwd()
compat.makedirs(savepath, exist_ok=True)

View file

@ -53,18 +53,17 @@ class Video(PlexPartialObject):
the most specific thumbnail for that item.
"""
thumb = self.firstAttr('thumb', 'parentThumb', 'granparentThumb')
return self._server.url(thumb) if thumb else None
return self._server.url(thumb, includeToken=True) if thumb else None
@property
def artUrl(self):
""" Return the first first art url starting on the most specific for that item."""
art = self.firstAttr('art', 'grandparentArt')
return self._server.url(art) if art else None
return self._server.url(art, includeToken=True) if art else None
def url(self, part):
""" Returns the full url for something. Typically used for getting a specific image. """
if part:
return self._server.url(part)
return self._server.url(part, includeToken=True) if part else None
def markWatched(self):
""" Mark video as watched. """
@ -193,10 +192,10 @@ class Movie(Video, Playable):
url = self.getStreamURL(**kwargs)
else:
self._server.url('%s?download=1' % location.key)
filepath = utils.download(url, filename=name, savepath=savepath, session=self._server._session)
filepath = utils.download(url, self._server._token, filename=name,
savepath=savepath, session=self._server._session)
if filepath:
filepaths.append(filepath)
return filepaths

View file

@ -58,9 +58,9 @@ def test_server_transcodeImage(tmpdir, plex, show):
width, height = 500, 500
imgurl = plex.transcodeImage(show.banner, height, width)
gray = imgurl = plex.transcodeImage(show.banner, height, width, saturation=0)
resized_img = download(imgurl, savepath=str(tmpdir), filename='resize_image')
original_img = download(show._server.url(show.banner), savepath=str(tmpdir), filename='original_img')
grayscale_img = download(gray, savepath=str(tmpdir), filename='grayscale_img')
resized_img = download(imgurl, plex._token, savepath=str(tmpdir), filename='resize_image')
original_img = download(show._server.url(show.banner), plex._token, savepath=str(tmpdir), filename='original_img')
grayscale_img = download(gray, plex._token, savepath=str(tmpdir), filename='grayscale_img')
with Image.open(resized_img) as image:
assert width, height == image.size
with Image.open(original_img) as image:

View file

@ -60,10 +60,10 @@ def test_utils_cast():
bool_str = utils.cast(bool, 'kek')
def test_utils_download(episode):
def test_utils_download(plex, episode):
url = episode.getStreamURL()
locations = episode.locations[0]
session = episode._server._session
assert utils.download(url, filename=locations, mocked=True)
assert utils.download(url, filename=locations, session=session, mocked=True)
assert utils.download(episode.thumbUrl, filename=episode.title, mocked=True)
assert utils.download(url, plex._token, filename=locations, mocked=True)
assert utils.download(url, plex._token, filename=locations, session=session, mocked=True)
assert utils.download(episode.thumbUrl, plex._token, filename=episode.title, mocked=True)