diff --git a/resources/language/English/strings.xml b/resources/language/English/strings.xml
index ad00d419..02e39ff8 100644
--- a/resources/language/English/strings.xml
+++ b/resources/language/English/strings.xml
@@ -363,7 +363,7 @@
[COLOR red]Partial or full reset of Database and PKC[/COLOR]
[COLOR yellow]Cache all images to Kodi texture cache[/COLOR]
[COLOR yellow]Sync Emby Theme Media to Kodi[/COLOR]
- (local)
+ local
Failed to authenticate. Did you login to plex.tv?
[COLOR yellow]Reset PMS and plex.tv connections to re-login[/COLOR]
Automatically log into plex.tv on startup
@@ -396,6 +396,8 @@
Wait before sync new/changed PMS item [s]
Background Sync
Do a full library sync every x minutes
+ remote
+ Searching for Plex Server
diff --git a/resources/language/German/strings.xml b/resources/language/German/strings.xml
index d00087d6..f0393e33 100644
--- a/resources/language/German/strings.xml
+++ b/resources/language/German/strings.xml
@@ -301,7 +301,7 @@
[COLOR red]Datenbank und auf Wunsch PKC zurücksetzen[/COLOR]
[COLOR yellow]Alle Plex Bilder in Kodi zwischenspeichern[/COLOR]
[COLOR yellow]Plex Themes zu Kodi synchronisieren[/COLOR]
- (lokal)
+ lokal
Plex Media Server Authentifizierung fehlgeschlagen. Haben Sie sich bei plex.tv eingeloggt?
[COLOR yellow]PMS und plex.tv Verbindungen zurücksetzen für erneuten Login[/COLOR]
Automatisch beim Starten bei plex.tv einloggen
@@ -334,6 +334,8 @@
Warten bevor neue/geänderte PMS Einträge gesynct werden [s]
Hintergrund-Synchronisation
Kompletten Scan aller Bibliotheken alle x Minuten durchführen
+ remote
+ Suche Plex Server
diff --git a/resources/lib/PlexAPI.py b/resources/lib/PlexAPI.py
index 96bbe544..0e52015f 100644
--- a/resources/lib/PlexAPI.py
+++ b/resources/lib/PlexAPI.py
@@ -29,18 +29,12 @@ http://stackoverflow.com/questions/2407126/python-urllib2-basic-auth-problem
http://stackoverflow.com/questions/111945/is-there-any-way-to-do-http-put-in-python
(and others...)
"""
-import struct
import time
import urllib2
-import httplib
import socket
-import StringIO
-import gzip
from threading import Thread
-import traceback
import requests
import xml.etree.ElementTree as etree
-from uuid import uuid4
import re
import json
@@ -232,15 +226,15 @@ class PlexAPI():
try:
temp_token = xml.find('auth_token').text
except:
- self.logMsg("Error: Could not find token in plex.tv answer.", -1)
+ self.logMsg("Could not find token in plex.tv answer.", -1)
return False
self.logMsg("temp token from plex.tv is: %s" % temp_token, 2)
if not temp_token:
return False
# Use temp token to get the final plex credentials
- xml = self.doUtils('https://plex.tv/users/account?X-Plex-Token=%s'
- % temp_token,
+ xml = self.doUtils('https://plex.tv/users/account',
authenticate=False,
+ parameters={'X-Plex-Token': temp_token},
type="GET")
return xml
@@ -320,66 +314,63 @@ class PlexAPI():
return False
return xml
- def CheckConnection(self, url, token=None):
+ def CheckConnection(self, url, token=None, verifySSL=None):
"""
Checks connection to a Plex server, available at url. Can also be used
to check for connection with plex.tv.
Will check up to 3x until reply with False
+ Override SSL to skip the check by setting verifySSL=False
+ if 'None', SSL will be checked (standard requests setting)
+ if 'True', SSL settings from file settings are used (False/True)
+
Input:
url URL to Plex server (e.g. https://192.168.1.1:32400)
token appropriate token to access server. If None is passed,
the current token is used
Output:
False if server could not be reached or timeout occured
- e.g. 200 if connection was successfull
+ 200 if connection was successfull
int or other HTML status codes as received from the server
"""
# Add '/clients' to URL because then an authentication is necessary
# If a plex.tv URL was passed, this does not work.
- header = clientinfo.ClientInfo().getXArgsDeviceInfo()
- if token:
- header['X-Plex-Token'] = token
- sslverify = utils.settings('sslverify')
- if sslverify == "true":
- sslverify = True
- else:
- sslverify = False
- self.logMsg("Checking connection to server %s with sslverify=%s"
- % (url, sslverify), 1)
- timeout = (3, 10)
+ headerOptions = None
+ if token is not None:
+ headerOptions = {'X-Plex-Token': token}
+ if verifySSL is True:
+ verifySSL = None if utils.settings('sslverify') == 'true' \
+ else False
if 'plex.tv' in url:
url = 'https://plex.tv/api/home/users'
else:
url = url + '/library/onDeck'
- # Check up to 3 times before giving up - this sometimes happens when
- # PKC was just started
+ self.logMsg("Checking connection to server %s with verifySSL=%s"
+ % (url, verifySSL), 1)
+ # Check up to 3 times before giving up
count = 0
while count < 3:
+ answer = self.doUtils(url,
+ authenticate=False,
+ headerOptions=headerOptions,
+ verifySSL=verifySSL)
+ if answer is False:
+ self.logMsg("Could not connect to %s" % url, 0)
+ count += 1
+ xbmc.sleep(500)
+ continue
try:
- answer = requests.get(url,
- headers={},
- params=header,
- verify=sslverify,
- timeout=timeout)
- except requests.exceptions.ConnectionError as e:
- self.logMsg("Server is offline or cannot be reached. Url: %s "
- "Header: %s Error message: %s"
- % (url, header, e), 0)
- count += 1
- xbmc.sleep(1000)
- continue
- except requests.exceptions.ReadTimeout:
- self.logMsg("Server timeout reached for Url %s with header %s"
- % (url, header), 0)
- count += 1
- xbmc.sleep(1000)
- continue
+ answer.attrib
+ except:
+ pass
else:
- result = answer.status_code
- self.logMsg("Result was: %s" % result, 1)
- return result
- self.logMsg('Failed to connect to %s too many times.' % url, -1)
+ # Success - we downloaded an xml!
+ answer = 200
+ self.logMsg("Checking connection successfull. Answer: %s"
+ % answer, 1)
+ return answer
+ self.logMsg('Failed to connect to %s too many times. PMS is dead'
+ % url, 0)
return False
def GetgPMSKeylist(self):
@@ -455,73 +446,45 @@ class PlexAPI():
addon.setSetting('serverlist', serverlist)
return
- def declarePMS(self, ATV_udid, uuid, name, scheme, ip, port):
+ def declarePMS(self, uuid, name, scheme, ip, port):
"""
Plex Media Server handling
parameters:
- ATV_udid
uuid - PMS ID
name, scheme, ip, port, type, owned, token
"""
- # store PMS information in g_PMS database
- if ATV_udid not in self.g_PMS:
- self.g_PMS[ATV_udid] = {}
-
address = ip + ':' + port
baseURL = scheme+'://'+ip+':'+port
- self.g_PMS[ATV_udid][uuid] = { 'name': name,
- 'scheme':scheme, 'ip': ip , 'port': port,
- 'address': address,
- 'baseURL': baseURL,
- 'local': '1',
- 'owned': '1',
- 'accesstoken': '',
- 'enableGzip': False
- }
+ self.g_PMS[uuid] = {
+ 'name': name,
+ 'scheme': scheme,
+ 'ip': ip,
+ 'port': port,
+ 'address': address,
+ 'baseURL': baseURL,
+ 'local': '1',
+ 'owned': '1',
+ 'accesstoken': '',
+ 'enableGzip': False
+ }
- def updatePMSProperty(self, ATV_udid, uuid, tag, value):
+ def updatePMSProperty(self, uuid, tag, value):
# set property element of PMS by UUID
- if not ATV_udid in self.g_PMS:
- return '' # no server known for this aTV
- if not uuid in self.g_PMS[ATV_udid]:
- return '' # requested PMS not available
-
- self.g_PMS[ATV_udid][uuid][tag] = value
+ try:
+ self.g_PMS[uuid][tag] = value
+ except:
+ self.logMsg('%s has not yet been declared ' % uuid, -1)
+ return False
- def getPMSProperty(self, ATV_udid, uuid, tag):
+ def getPMSProperty(self, uuid, tag):
# get name of PMS by UUID
- if not ATV_udid in self.g_PMS:
- return '' # no server known for this aTV
- if not uuid in self.g_PMS[ATV_udid]:
- return '' # requested PMS not available
-
- return self.g_PMS[ATV_udid][uuid].get(tag, '')
-
- def getPMSFromAddress(self, ATV_udid, address):
- # find PMS by IP, return UUID
- if not ATV_udid in self.g_PMS:
- return '' # no server known for this aTV
-
- for uuid in self.g_PMS[ATV_udid]:
- if address in self.g_PMS[ATV_udid][uuid].get('address', None):
- return uuid
- return '' # IP not found
-
- def getPMSAddress(self, ATV_udid, uuid, data):
- # get address of PMS by UUID
- if not ATV_udid in data:
- return '' # no server known for this aTV
- if not uuid in data[ATV_udid]:
- return '' # requested PMS not available
- return data[ATV_udid][uuid]['ip'] + ':' + data[ATV_udid][uuid]['port']
-
- def getPMSCount(self, ATV_udid):
- # get count of discovered PMS by UUID
- if not ATV_udid in self.g_PMS:
- return 0 # no server known for this aTV
-
- return len(self.g_PMS[ATV_udid])
+ try:
+ answ = self.g_PMS[uuid].get(tag, '')
+ except:
+ self.logMsg('%s not found in PMS catalogue' % uuid, -1)
+ answ = False
+ return answ
def PlexGDM(self):
"""
@@ -532,25 +495,23 @@ class PlexAPI():
result:
PMS_list - dict() of PMSs found
"""
+ import struct
+
IP_PlexGDM = '239.0.0.250' # multicast to PMS
Port_PlexGDM = 32414
Msg_PlexGDM = 'M-SEARCH * HTTP/1.0'
- # dprint(__name__, 0, "***")
- # dprint(__name__, 0, "PlexGDM - looking up Plex Media Server")
- # dprint(__name__, 0, "***")
-
+
# setup socket for discovery -> multicast message
GDM = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- GDM.settimeout(1.0)
-
- # Set the time-to-live for messages to 1 for local network
- ttl = struct.pack('b', 1)
+ GDM.settimeout(2.0)
+
+ # Set the time-to-live for messages to 2 for local network
+ ttl = struct.pack('b', 2)
GDM.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, ttl)
-
+
returnData = []
try:
# Send data to the multicast group
- # dprint(__name__, 1, "Sending discovery message: {0}", Msg_PlexGDM)
GDM.sendto(Msg_PlexGDM, (IP_PlexGDM, Port_PlexGDM))
# Look for responses from all recipients
@@ -559,126 +520,109 @@ class PlexAPI():
data, server = GDM.recvfrom(1024)
# dprint(__name__, 1, "Received data from {0}", server)
# dprint(__name__, 1, "Data received:\n {0}", data)
- returnData.append( { 'from' : server,
- 'data' : data } )
+ returnData.append({'from': server,
+ 'data': data})
except socket.timeout:
break
finally:
GDM.close()
- discovery_complete = True
+ pmsList = {}
- PMS_list = {}
- if returnData:
- for response in returnData:
- update = { 'ip' : response.get('from')[0] }
-
- # Check if we had a positive HTTP response
- if "200 OK" in response.get('data'):
- for each in response.get('data').split('\n'):
- # decode response data
- update['discovery'] = "auto"
- #update['owned']='1'
- #update['master']= 1
- #update['role']='master'
-
- if "Content-Type:" in each:
- update['content-type'] = each.split(':')[1].strip()
- elif "Resource-Identifier:" in each:
- update['uuid'] = each.split(':')[1].strip()
- elif "Name:" in each:
- update['serverName'] = each.split(':')[1].strip().decode('utf-8', 'replace') # store in utf-8
- elif "Port:" in each:
- update['port'] = each.split(':')[1].strip()
- elif "Updated-At:" in each:
- update['updated'] = each.split(':')[1].strip()
- elif "Version:" in each:
- update['version'] = each.split(':')[1].strip()
-
- PMS_list[update['uuid']] = update
-
- # if PMS_list=={}:
- # dprint(__name__, 0, "GDM: No servers discovered")
- # else:
- # dprint(__name__, 0, "GDM: Servers discovered: {0}", len(PMS_list))
- # for uuid in PMS_list:
- # dprint(__name__, 1, "{0} {1}:{2}", PMS_list[uuid]['serverName'], PMS_list[uuid]['ip'], PMS_list[uuid]['port'])
-
- return PMS_list
+ self.logMsg('returndata is: %s' % returnData)
+ for response in returnData:
+ update = {'ip': response.get('from')[0]}
+ # Check if we had a positive HTTP response
+ if "200 OK" in response.get('data'):
+ for each in response.get('data').split('\n'):
+ # decode response data
+ update['discovery'] = "auto"
+ # update['owned']='1'
+ # update['master']= 1
+ # update['role']='master'
- def discoverPMS(self, ATV_udid, CSettings, IP_self, tokenDict={}):
+ if "Content-Type:" in each:
+ update['content-type'] = each.split(':')[1].strip()
+ elif "Resource-Identifier:" in each:
+ update['uuid'] = each.split(':')[1].strip()
+ elif "Name:" in each:
+ update['serverName'] = each.split(':')[1].strip().decode('utf-8', 'replace')
+ elif "Port:" in each:
+ update['port'] = each.split(':')[1].strip()
+ elif "Updated-At:" in each:
+ update['updated'] = each.split(':')[1].strip()
+ elif "Version:" in each:
+ update['version'] = each.split(':')[1].strip()
+ pmsList[update['uuid']] = update
+
+ return pmsList
+
+ def discoverPMS(self, IP_self, plexToken=None):
"""
- discoverPMS
-
parameters:
- ATV_udid
- CSettings - for manual PMS configuration. this one looks strange.
- IP_self
+ IP_self Own IP
optional:
- tokenDict - dictionary of tokens for MyPlex, PlexHome
+ plexToken token for plex.tv
result:
- self.g_PMS dictionary for ATV_udid
+ self.g_PMS dict set
"""
- self.g_PMS[ATV_udid] = {}
+ self.g_PMS = {}
+ xbmcgui.Dialog().notification(
+ heading=self.addonName,
+ message=self.__language__(39055),
+ icon="special://home/addons/plugin.video.plexkodiconnect/icon.png",
+ time=3000,
+ sound=False)
- # install plex.tv "virtual" PMS - for myPlex, PlexHome
- self.declarePMS(ATV_udid, 'plex.tv', 'plex.tv', 'https', 'plex.tv', '443')
- self.updatePMSProperty(ATV_udid, 'plex.tv', 'local', '-')
- self.updatePMSProperty(ATV_udid, 'plex.tv', 'owned', '-')
- self.updatePMSProperty(ATV_udid, 'plex.tv', 'accesstoken', tokenDict.get('MyPlexToken', ''))
-
- if 'PlexHomeToken' in tokenDict:
- authtoken = tokenDict.get('PlexHomeToken')
- else:
- authtoken = tokenDict.get('MyPlexToken', '')
-
- if authtoken == '':
- # not logged into myPlex
- # local PMS
- # PlexGDM
- PMS_list = self.PlexGDM()
- for uuid_id in PMS_list:
- PMS = PMS_list[uuid_id]
- self.declarePMS(ATV_udid, PMS['uuid'], PMS['serverName'], 'http', PMS['ip'], PMS['port']) # dflt: token='', local, owned
- else:
- # MyPlex servers
- self.getPMSListFromMyPlex(ATV_udid, authtoken)
- # Delete plex.tv again
- del self.g_PMS[ATV_udid]['plex.tv']
- # all servers - update enableGzip
- for uuid_id in self.g_PMS.get(ATV_udid, {}):
+ # Look first for local PMS in the LAN
+ pmsList = self.PlexGDM()
+ self.logMsg('pmslist: %s' % pmsList, 1)
+ for uuid in pmsList:
+ PMS = pmsList[uuid]
+ self.declarePMS(PMS['uuid'], PMS['serverName'], 'http',
+ PMS['ip'], PMS['port'])
+ self.updatePMSProperty(PMS['uuid'], 'owned', '-')
# Ping to check whether we need HTTPs or HTTP
- url = (self.getPMSProperty(ATV_udid, uuid_id, 'ip') + ':'
- + self.getPMSProperty(ATV_udid, uuid_id, 'port'))
+ url = '%s:%s' % (PMS['ip'], PMS['port'])
https = PMSHttpsEnabled(url)
if https is None:
- # Error contacting url
+ # Error contacting url. Skip for now
continue
- elif https:
- self.updatePMSProperty(ATV_udid, uuid_id, 'scheme', 'https')
+ elif https is True:
+ self.updatePMSProperty(PMS['uuid'], 'scheme', 'https')
+ self.updatePMSProperty(
+ PMS['uuid'],
+ 'baseURL',
+ 'https://%s:%s' % (PMS['ip'], PMS['port']))
else:
- self.updatePMSProperty(ATV_udid, uuid_id, 'scheme', 'http')
- # enable Gzip if not on same host, local&remote PMS depending
- # on setting
- enableGzip = (not self.getPMSProperty(ATV_udid, uuid_id, 'ip') == IP_self) \
- and (
- (self.getPMSProperty(ATV_udid, uuid_id, 'local') == '1'
- and False)
- or
- (self.getPMSProperty(ATV_udid, uuid_id, 'local') == '0'
- and True) == 'True'
- )
- self.updatePMSProperty(ATV_udid, uuid_id, 'enableGzip', enableGzip)
+ # Already declared with http
+ pass
- def getPMSListFromMyPlex(self, ATV_udid, authtoken):
+ if not plexToken:
+ self.logMsg('No plex.tv token supplied, checked LAN for PMS', 0)
+ return
+
+ # install plex.tv "virtual" PMS - for myPlex, PlexHome
+ # self.declarePMS('plex.tv', 'plex.tv', 'https', 'plex.tv', '443')
+ # self.updatePMSProperty('plex.tv', 'local', '-')
+ # self.updatePMSProperty('plex.tv', 'owned', '-')
+ # self.updatePMSProperty(
+ # 'plex.tv', 'accesstoken', plexToken)
+ # (remote and local) servers from plex.tv
+
+ # Get PMS from plex.tv. This will overwrite any PMS we already found
+ self.getPMSListFromMyPlex(plexToken)
+
+ def getPMSListFromMyPlex(self, token):
"""
getPMSListFromMyPlex
get Plex media Server List from plex.tv/pms/resources
"""
- xml = self.doUtils('https://plex.tv/api/resources?includeHttps=1',
+ xml = self.doUtils('https://plex.tv/api/resources',
authenticate=False,
- headerOptions={'X-Plex-Token': authtoken})
+ parameters={'includeHttps': 1},
+ headerOptions={'X-Plex-Token': token})
try:
xml.attrib
except:
@@ -699,36 +643,43 @@ class PlexAPI():
PMS = {}
PMS['name'] = Dir.get('name')
infoAge = time.time() - int(Dir.get('lastSeenAt'))
- oneDayInSec = 2*60*60*24
- if infoAge > 1*oneDayInSec:
- self.logMsg("Server %s not seen for 1 day - "
+ oneDayInSec = 60*60*24
+ if infoAge > 2*oneDayInSec:
+ self.logMsg("Server %s not seen for 2 days - "
"skipping." % PMS['name'], 0)
continue
PMS['uuid'] = Dir.get('clientIdentifier')
- PMS['token'] = Dir.get('accessToken', authtoken)
+ PMS['token'] = Dir.get('accessToken', token)
PMS['owned'] = Dir.get('owned', '0')
PMS['local'] = Dir.get('publicAddressMatches')
PMS['ownername'] = Dir.get('sourceTitle', '')
PMS['path'] = '/'
PMS['options'] = None
- # flag to set first connection, possibly overwrite later with
- # more suitable
- PMS['baseURL'] = ""
+ # If PMS seems (!!) local, try a local connection first
+ # Backup to remote connection, if that failes
+ PMS['baseURL'] = ''
for Con in Dir.iter(tag='Connection'):
- if (PMS['baseURL'] == "" or
- Con.get('local') == PMS['local']):
+ localConn = Con.get('local')
+ if ((PMS['local'] == '1' and localConn == '1') or
+ (PMS['local'] == '0' and localConn == '0')):
+ # Either both local or both remote
PMS['protocol'] = Con.get('protocol')
PMS['ip'] = Con.get('address')
PMS['port'] = Con.get('port')
- PMS['baseURL'] = Con.get('baseURL')
- # todo: handle unforeseen - like we get multiple suitable
- # connections. how to choose one?
+ PMS['baseURL'] = Con.get('uri')
+ elif PMS['local'] == '1' and localConn == '0':
+ # Backup connection if local one did not work
+ PMS['backup'] = {}
+ PMS['backup']['protocol'] = Con.get('protocol')
+ PMS['backup']['ip'] = Con.get('address')
+ PMS['backup']['port'] = Con.get('port')
+ PMS['backup']['baseURL'] = Con.get('uri')
# poke PMS, own thread for each poke
t = Thread(target=self.pokePMS,
- args=(PMS['baseURL'], PMS['token'], PMS, queue))
+ args=(PMS, queue))
t.start()
threads.append(t)
@@ -739,45 +690,49 @@ class PlexAPI():
# declare new PMSs
while not queue.empty():
PMS = queue.get()
- self.declarePMS(ATV_udid, PMS['uuid'], PMS['name'],
+ self.declarePMS(PMS['uuid'], PMS['name'],
PMS['protocol'], PMS['ip'], PMS['port'])
# dflt: token='', local, owned - updated later
self.updatePMSProperty(
- ATV_udid, PMS['uuid'], 'accesstoken', PMS['token'])
+ PMS['uuid'], 'accesstoken', PMS['token'])
self.updatePMSProperty(
- ATV_udid, PMS['uuid'], 'owned', PMS['owned'])
+ PMS['uuid'], 'owned', PMS['owned'])
self.updatePMSProperty(
- ATV_udid, PMS['uuid'], 'local', PMS['local'])
+ PMS['uuid'], 'local', PMS['local'])
# set in declarePMS, overwrite for https encryption
self.updatePMSProperty(
- ATV_udid, PMS['uuid'], 'baseURL', PMS['baseURL'])
+ PMS['uuid'], 'baseURL', PMS['baseURL'])
self.updatePMSProperty(
- ATV_udid, PMS['uuid'], 'ownername', PMS['ownername'])
+ PMS['uuid'], 'ownername', PMS['ownername'])
queue.task_done()
- def pokePMS(self, url, token, PMS, queue):
- xml = self.doUtils(url,
+ def pokePMS(self, PMS, queue):
+ # Ignore SSL certificates for now
+ xml = self.doUtils(PMS['baseURL'],
authenticate=False,
- headerOptions={'X-Plex-Token': token})
+ headerOptions={'X-Plex-Token': PMS['token']},
+ verifySSL=False)
try:
xml.attrib
except:
- return
+ # Connection failed
+ # retry with remote connection if we just tested local one.
+ if PMS['local'] == '1' and PMS.get('backup'):
+ self.logMsg('Couldnt talk to local PMS locally.'
+ 'Trying again remotely.', 0)
+ PMS['protocol'] = PMS['backup']['protocol']
+ PMS['ip'] = PMS['backup']['ip']
+ PMS['port'] = PMS['backup']['port']
+ PMS['baseURL'] = PMS['backup']['baseURL']
+ PMS['local'] = '0'
+ # Try again
+ self.pokePMS(PMS, queue)
+ else:
+ return
else:
+ # Connection successful, process later
queue.put(PMS)
- def getURL(self, baseURL, path, key):
- if key.startswith('http://') or key.startswith('https://'): # external server
- URL = key
- elif key.startswith('/'): # internal full path.
- URL = baseURL + key
- elif key == '': # internal path
- URL = baseURL + path
- else: # internal path, add-on
- URL = baseURL + path + '/' + key
-
- return URL
-
def MyPlexSignIn(self, username, password, options):
"""
MyPlex Sign In, Sign Out
@@ -1226,13 +1181,12 @@ class PlexAPI():
return path
- def returnServerList(self, ATV_udid, data):
+ def returnServerList(self, data):
"""
Returns a nicer list of all servers found in data, where data is in
g_PMS format, for the client device with unique ID ATV_udid
Input:
- ATV_udid Unique client ID
data e.g. self.g_PMS
Output: List of all servers, with an entry of the form:
@@ -1247,21 +1201,23 @@ class PlexAPI():
'machineIdentifier': id, Plex server machine identifier
'accesstoken': token Access token to this server
'baseURL': baseURL scheme://ip:port
+ 'ownername' Plex username of PMS owner
}
"""
serverlist = []
- for key, value in data[ATV_udid].items():
+ for key, value in data.items():
serverlist.append({
- 'name': value['name'],
- 'address': value['address'],
- 'ip': value['ip'],
- 'port': value['port'],
- 'scheme': value['scheme'],
- 'local': value['local'],
- 'owned': value['owned'],
+ 'name': value.get('name'),
+ 'address': value.get('address'),
+ 'ip': value.get('ip'),
+ 'port': value.get('port'),
+ 'scheme': value.get('scheme'),
+ 'local': value.get('local'),
+ 'owned': value.get('owned'),
'machineIdentifier': key,
- 'accesstoken': value['accesstoken'],
- 'baseURL': value['baseURL']
+ 'accesstoken': value.get('accesstoken'),
+ 'baseURL': value.get('baseURL'),
+ 'ownername': value.get('ownername')
})
return serverlist
@@ -2001,6 +1957,7 @@ class API():
return url
# For Direct Streaming or Transcoding
+ from uuid import uuid4
# Path/key to VIDEO item of xml PMS response is needed, not part
path = self.item.attrib['key']
transcodePath = self.server + \
diff --git a/resources/lib/PlexFunctions.py b/resources/lib/PlexFunctions.py
index 1c6fed10..db977784 100644
--- a/resources/lib/PlexFunctions.py
+++ b/resources/lib/PlexFunctions.py
@@ -410,47 +410,38 @@ def getPlexRepeat(kodiRepeat):
def PMSHttpsEnabled(url):
"""
- Returns True if the PMS wants to talk https, False otherwise. None if error
- occured, e.g. the connection timed out
+ Returns True if the PMS can talk https, False otherwise.
+ None if error occured, e.g. the connection timed out
- With with e.g. url=192.168.0.1:32400 (NO http/https)
+ Call with e.g. url='192.168.0.1:32400' (NO http/https)
This is done by GET /identity (returns an error if https is enabled and we
are trying to use http)
Prefers HTTPS over HTTP
"""
- # True if https, False if http
- answer = True
+ doUtils = downloadutils.DownloadUtils().downloadUrl
+ res = doUtils('https://%s/identity' % url,
+ authenticate=False,
+ verifySSL=False)
try:
- # Don't use downloadutils here, otherwise we may get un-authorized!
- res = requests.get('https://%s/identity' % url,
- headers={},
- verify=False,
- timeout=(3, 10))
- # Don't verify SSL since we can connect for sure then!
- except requests.exceptions.ConnectionError as e:
+ res.attrib
+ except:
# Might have SSL deactivated. Try with http
+ res = doUtils('http://%s/identity' % url,
+ authenticate=False,
+ verifySSL=False)
try:
- res = requests.get('http://%s/identity' % url,
- headers={},
- timeout=(3, 10))
- except requests.exceptions.ConnectionError as e:
- logMsg(title, "Server is offline or cannot be reached. Url: %s"
- ", Error message: %s" % (url, e), -1)
- return None
- except requests.exceptions.ReadTimeout:
- logMsg(title, "Server timeout reached for Url %s" % url, -1)
+ res.attrib
+ except:
+ logMsg(title, "Could not contact PMS %s" % url, -1)
return None
else:
- answer = False
- except requests.exceptions.ReadTimeout:
- logMsg(title, "Server timeout reached for Url %s" % url, -1)
- return None
- if res.status_code == requests.codes.ok:
- return answer
+ # Received a valid XML. Server wants to talk HTTP
+ return False
else:
- return None
+ # Received a valid XML. Server wants to talk HTTPS
+ return True
def GetMachineIdentifier(url):
diff --git a/resources/lib/downloadutils.py b/resources/lib/downloadutils.py
index be34ac3b..c1c6ce30 100644
--- a/resources/lib/downloadutils.py
+++ b/resources/lib/downloadutils.py
@@ -5,9 +5,7 @@
import requests
import xml.etree.ElementTree as etree
-import xbmcgui
-
-import utils
+from utils import logging, settings, window
import clientinfo
###############################################################################
@@ -20,382 +18,258 @@ requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
###############################################################################
-@utils.logging
+@logging
class DownloadUtils():
+ """
+ Manages any up/downloads with PKC. Careful to initiate correctly
+ Use startSession() to initiate.
+ If not initiated, e.g. SSL check will fallback to False
+ """
# Borg - multiple instances, shared state
_shared_state = {}
# Requests session
- s = None
timeout = 30
def __init__(self):
self.__dict__ = self._shared_state
def setUsername(self, username):
- # Reserved for userclient only
+ """
+ Reserved for userclient only
+ """
self.username = username
- self.logMsg("Set username: %s" % username, 2)
+ self.logMsg("Set username: %s" % username, 0)
def setUserId(self, userId):
- # Reserved for userclient only
+ """
+ Reserved for userclient only
+ """
self.userId = userId
- self.logMsg("Set userId: %s" % userId, 2)
+ self.logMsg("Set userId: %s" % userId, 0)
def setServer(self, server):
- # Reserved for userclient only
+ """
+ Reserved for userclient only
+ """
self.server = server
- self.logMsg("Set server: %s" % server, 2)
+ self.logMsg("Set server: %s" % server, 0)
def setToken(self, token):
- # Reserved for userclient only
+ """
+ Reserved for userclient only
+ """
self.token = token
- self.logMsg("Set token: xxxxxxx", 2)
-
- def setSSL(self, ssl, sslclient):
- # Reserved for userclient only
- self.sslverify = ssl
- self.sslclient = sslclient
- self.logMsg("Verify SSL host certificate: %s" % ssl, 2)
- self.logMsg("SSL client side certificate: %s" % sslclient, 2)
-
- def postCapabilities(self, deviceId):
-
- # Post settings to session
- url = "{server}/emby/Sessions/Capabilities/Full?format=json"
- data = {
-
- 'PlayableMediaTypes': "Audio,Video",
- 'SupportsMediaControl': True,
- 'SupportedCommands': (
-
- "MoveUp,MoveDown,MoveLeft,MoveRight,Select,"
- "Back,ToggleContextMenu,ToggleFullscreen,ToggleOsdMenu,"
- "GoHome,PageUp,NextLetter,GoToSearch,"
- "GoToSettings,PageDown,PreviousLetter,TakeScreenshot,"
- "VolumeUp,VolumeDown,ToggleMute,SendString,DisplayMessage,"
- "SetAudioStreamIndex,SetSubtitleStreamIndex,"
-
- "Mute,Unmute,SetVolume,"
- "Play,Playstate,PlayNext"
- )
- }
-
- self.logMsg("Capabilities URL: %s" % url, 2)
- self.logMsg("Postdata: %s" % data, 2)
-
- self.downloadUrl(url, postBody=data, type="POST")
- self.logMsg("Posted capabilities to %s" % self.server, 2)
-
- # Attempt at getting sessionId
- url = "{server}/emby/Sessions?DeviceId=%s&format=json" % deviceId
- result = self.downloadUrl(url)
- try:
- sessionId = result[0]['Id']
-
- except (KeyError, TypeError):
- self.logMsg("Failed to retrieve sessionId.", 1)
-
+ if token == '':
+ self.logMsg('Set token: empty token!', 0)
else:
- self.logMsg("Session: %s" % result, 2)
- self.logMsg("SessionId: %s" % sessionId, 1)
- utils.window('emby_sessionId', value=sessionId)
-
- # Post any permanent additional users
- # additionalUsers = utils.settings('additionalUsers')
- # if additionalUsers:
-
- # additionalUsers = additionalUsers.split(',')
- # self.logMsg(
- # "List of permanent users added to the session: %s"
- # % additionalUsers, 1)
+ self.logMsg("Set token: xxxxxxx", 0)
- # # Get the user list from server to get the userId
- # url = "{server}/emby/Users?format=json"
- # result = self.downloadUrl(url)
+ def setSSL(self, verifySSL=None, certificate=None):
+ """
+ Reserved for userclient only
- # for additional in additionalUsers:
- # addUser = additional.decode('utf-8').lower()
+ verifySSL must be 'true' to enable certificate validation
- # # Compare to server users to list of permanent additional users
- # for user in result:
- # username = user['Name'].lower()
-
- # if username in addUser:
- # userId = user['Id']
- # url = (
- # "{server}/emby/Sessions/%s/Users/%s?format=json"
- # % (sessionId, userId)
- # )
- # self.downloadUrl(url, postBody={}, type="POST")
+ certificate must be path to certificate or 'None'
+ """
+ if verifySSL is None:
+ verifySSL = settings('sslverify')
+ if certificate is None:
+ certificate = settings('sslcert')
+ self.logMsg("Verify SSL certificates set to: %s" % verifySSL, 0)
+ self.logMsg("SSL client side certificate set to: %s" % certificate, 0)
+ if verifySSL != 'true':
+ self.s.verify = False
+ if certificate != 'None':
+ self.s.cert = certificate
def startSession(self):
- # User should be authenticated when this method is called
- client = clientinfo.ClientInfo()
-
- self.deviceId = client.getDeviceId()
- verify = False
-
- # If user enabled host certificate verification
- try:
- verify = self.sslverify
- if self.sslclient is not None:
- verify = self.sslclient
- except:
- self.logMsg("Could not load SSL settings.", -1)
+ """
+ User should be authenticated when this method is called (via
+ userclient)
+ """
# Start session
self.s = requests.Session()
+
+ client = clientinfo.ClientInfo()
+ self.deviceId = client.getDeviceId()
# Attach authenticated header to the session
self.s.headers = client.getXArgsDeviceInfo()
- self.s.verify = verify
+ self.s.encoding = 'utf-8'
+ # Set SSL settings
+ self.setSSL()
+
+ # Set other stuff
+ self.setServer(window('pms_server'))
+ self.setToken(window('pms_token'))
+ self.setUserId(window('currUserId'))
+ self.setUsername(window('plex_username'))
+
# Retry connections to the server
self.s.mount("http://", requests.adapters.HTTPAdapter(max_retries=1))
self.s.mount("https://", requests.adapters.HTTPAdapter(max_retries=1))
- self.logMsg("Requests session started on: %s" % self.server, 1)
+ self.logMsg("Requests session started on: %s" % self.server, 0)
def stopSession(self):
try:
self.s.close()
except:
- self.logMsg("Requests session could not be terminated.", 1)
+ self.logMsg("Requests session could not be terminated.", 0)
+ try:
+ del self.s
+ except:
+ pass
+ self.logMsg('Request session stopped', 0)
def getHeader(self, options=None):
- try:
- header = self.s.headers.copy()
- except:
- header = clientinfo.ClientInfo().getXArgsDeviceInfo()
+ header = clientinfo.ClientInfo().getXArgsDeviceInfo()
if options is not None:
header.update(options)
return header
- def downloadUrl(self, url, postBody=None, type="GET", parameters=None,
- authenticate=True, headerOptions=None):
- timeout = self.timeout
- default_link = ""
+ def __doDownload(self, s, type, **kwargs):
+ if type == "GET":
+ r = s.get(**kwargs)
+ elif type == "POST":
+ r = s.post(**kwargs)
+ elif type == "DELETE":
+ r = s.delete(**kwargs)
+ elif type == "OPTIONS":
+ r = s.options(**kwargs)
+ elif type == "PUT":
+ r = s.put(**kwargs)
+ return r
+ def downloadUrl(self, url, type="GET", postBody=None, parameters=None,
+ authenticate=True, headerOptions=None, verifySSL=True):
+ """
+ Override SSL check with verifySSL=False
+
+ If authenticate=True, existing request session will be used/started
+ Otherwise, 'empty' request will be made
+
+ Returns:
+ False If an error occured
+ True If connection worked but no body was received
+ 401, ... integer if PMS answered with HTTP error 401
+ (unauthorized) or other http error codes
+ xml xml etree root object, if applicable
+ JSON json() object, if applicable
+ """
+ kwargs = {}
+ if authenticate:
+ # Get requests session
+ try:
+ s = self.s
+ except AttributeError:
+ self.logMsg("Request session does not exist: start one", 0)
+ self.startSession()
+ s = self.s
+ # Replace for the real values
+ url = url.replace("{server}", self.server)
+ else:
+ # User is not (yet) authenticated. Used to communicate with
+ # plex.tv and to check for PMS servers
+ s = requests
+ headerOptions = self.getHeader(options=headerOptions)
+ kwargs['timeout'] = self.timeout
+ if settings('sslcert') != 'None':
+ kwargs['cert'] = settings('sslcert')
+
+ # Set the variables we were passed (fallback to request session
+ # otherwise - faster)
+ kwargs['url'] = url
+ if verifySSL is False:
+ kwargs['verify'] = False
+ if headerOptions is not None:
+ kwargs['headers'] = headerOptions
+ if postBody is not None:
+ kwargs['data'] = postBody
+ if parameters is not None:
+ kwargs['params'] = parameters
+
+ # ACTUAL DOWNLOAD HAPPENING HERE
try:
- # If user is authenticated
- if (authenticate):
- # Get requests session
- try:
- s = self.s
- # Replace for the real values
- url = url.replace("{server}", self.server)
- url = url.replace("{UserId}", self.userId)
- header = self.getHeader(options=headerOptions)
- # Prepare request
- if type == "GET":
- r = s.get(url, json=postBody, params=parameters, timeout=timeout, headers=header)
- elif type == "POST":
- r = s.post(url, json=postBody, timeout=timeout, headers=header)
- elif type == "DELETE":
- r = s.delete(url, json=postBody, timeout=timeout, headers=header)
- elif type == "OPTIONS":
- r = s.options(url, json=postBody, timeout=timeout, headers=header)
- # For Plex Companion
- elif type == "POSTXML":
- r = s.post(url, postBody, timeout=timeout, headers=header)
- elif type == "PUT":
- r = s.put(url, timeout=timeout, headers=header)
-
- except AttributeError:
- # request session does not exists
- self.logMsg("Request session does not exist: start one", 1)
- # Get user information
- self.userId = utils.window('currUserId')
- self.server = utils.window('pms_server')
- self.token = utils.window('pms_token')
- header = self.getHeader(options=headerOptions)
- verifyssl = False
- cert = None
-
- # IF user enables ssl verification
- if utils.settings('sslverify') == "true":
- verifyssl = True
- if utils.settings('sslcert') != "None":
- verifyssl = utils.settings('sslcert')
-
- # Replace for the real values
- url = url.replace("{server}", self.server)
- url = url.replace("{UserId}", self.userId)
-
- # Prepare request
- if type == "GET":
- r = requests.get(url,
- json=postBody,
- params=parameters,
- headers=header,
- timeout=timeout,
- verify=verifyssl)
-
- elif type == "POST":
- r = requests.post(url,
- json=postBody,
- headers=header,
- timeout=timeout,
- verify=verifyssl)
-
- elif type == "DELETE":
- r = requests.delete(url,
- json=postBody,
- headers=header,
- timeout=timeout,
- verify=verifyssl)
-
- elif type == "OPTIONS":
- r = requests.options(url,
- json=postBody,
- headers=header,
- timeout=timeout,
- cert=cert,
- verify=verifyssl)
-
- elif type == "PUT":
- r = requests.put(url,
- json=postBody,
- headers=header,
- timeout=timeout,
- cert=cert,
- verify=verifyssl)
- # If user is not authenticated
- elif not authenticate:
-
- header = self.getHeader(options=headerOptions)
-
- # If user enables ssl verification
- try:
- verifyssl = self.sslverify
- if self.sslclient is not None:
- verifyssl = self.sslclient
- except AttributeError:
- if utils.settings('sslverify') == "true":
- verifyssl = True
- else:
- verifyssl = False
- self.logMsg("Set SSL verification to: %s" % verifyssl, 2)
- # Prepare request
- if type == "GET":
- r = requests.get(url,
- json=postBody,
- params=parameters,
- headers=header,
- timeout=timeout,
- verify=verifyssl)
-
- elif type == "POST":
- r = requests.post(url,
- json=postBody,
- headers=header,
- timeout=timeout,
- verify=verifyssl)
-
- elif type == "PUT":
- r = requests.put(url,
- json=postBody,
- headers=header,
- timeout=timeout,
- verify=verifyssl)
- ##### THE RESPONSE #####
- # self.logMsg(r.url, 2)
- if r.status_code == 204:
- # No body in the response
- # self.logMsg("====== 204 Success ======", 2)
- pass
-
- elif r.status_code == requests.codes.ok:
-
- try:
- # Allow for xml responses
- r = etree.fromstring(r.content)
- # self.logMsg("====== 200 Success ======", 2)
- # self.logMsg("Received an XML response for: %s" % url, 2)
-
- return r
-
- except:
- try:
- # UNICODE - JSON object
- r = r.json()
- # self.logMsg("====== 200 Success ======", 2)
- # self.logMsg("Response: %s" % r, 2)
- return r
- except:
- try:
- if r.text == '' and r.status_code == 200:
- # self.logMsg("====== 200 Success ======", 2)
- # self.logMsg("Answer from PMS does not contain a body", 2)
- pass
- # self.logMsg("Unable to convert the response for: %s" % url, 2)
- # self.logMsg("Content-type was: %s" % r.headers['content-type'], 2)
- except:
- self.logMsg("Unable to convert the response for: %s" % url, 2)
- self.logMsg("Content-type was: %s" % r.headers['content-type'], 2)
- else:
- r.raise_for_status()
-
- ##### EXCEPTIONS #####
+ r = self.__doDownload(s, type, **kwargs)
+ # THE EXCEPTIONS
except requests.exceptions.ConnectionError as e:
+ # Connection error
+ self.logMsg("Server unreachable at: %s" % url, -1)
+ self.logMsg(e, 2)
# Make the addon aware of status
- if utils.window('emby_online') != "false":
- self.logMsg("Server unreachable at: %s" % url, -1)
- self.logMsg(e, 2)
- utils.window('emby_online', value="false")
+ window('emby_online', value="false")
+ return False
except requests.exceptions.ConnectTimeout as e:
- self.logMsg("Server timeout at: %s" % url, 0)
- self.logMsg(e, 1)
+ self.logMsg("Server timeout at: %s" % url, -1)
+ self.logMsg(e, 2)
+ return False
except requests.exceptions.HTTPError as e:
-
- if r.status_code == 401:
+ r = r.status_code
+ if r == 401:
# Unauthorized
- status = utils.window('emby_serverStatus')
-
- if 'X-Application-Error-Code' in r.headers:
- # Emby server errors
- if r.headers['X-Application-Error-Code'] == "ParentalControl":
- # Parental control - access restricted
- self.logMsg('Setting emby_serverStatus to restricted')
- utils.window('emby_serverStatus', value="restricted")
- xbmcgui.Dialog().notification(
- heading=self.addonName,
- message="Access restricted.",
- icon=xbmcgui.NOTIFICATION_ERROR,
- time=5000)
- return False
-
- elif r.headers['X-Application-Error-Code'] == "UnauthorizedAccessException":
- # User tried to do something his emby account doesn't allow
- pass
-
- elif status not in ("401", "Auth"):
- # Tell userclient token has been revoked.
- self.logMsg('Error 401 contacting %s' % url, 0)
- self.logMsg('Setting emby_serverStatus to 401', 0)
- utils.window('emby_serverStatus', value="401")
- self.logMsg("HTTP Error: %s" % e, 0)
- xbmcgui.Dialog().notification(
- heading=self.addonName,
- message="Error connecting: Unauthorized.",
- icon=xbmcgui.NOTIFICATION_ERROR)
- return 401
-
- elif r.status_code in (301, 302):
+ self.logMsg('Error 401 contacting %s' % url, -1)
+ elif r in (301, 302):
# Redirects
- pass
- elif r.status_code == 400:
+ self.logMsg('HTTP redirect error %s at %s' % (r, url), -1)
+ elif r == 400:
# Bad requests
- pass
+ self.logMsg('Bad request at %s' % url, -1)
+ else:
+ self.logMsg('HTTP Error %s at %s' % (r, url), -1)
+ self.logMsg(e, 2)
+ return r
except requests.exceptions.SSLError as e:
- self.logMsg("Invalid SSL certificate for: %s" % url, 0)
- self.logMsg(e, 1)
+ self.logMsg("Invalid SSL certificate for: %s" % url, -1)
+ self.logMsg(e, 2)
+ return False
except requests.exceptions.RequestException as e:
- self.logMsg("Unknown error connecting to: %s" % url, 0)
- self.logMsg(e, 1)
+ self.logMsg("Unknown error connecting to: %s" % url, -1)
+ self.logMsg("Error message: %s" % e, 2)
+ return False
- return default_link
+ except:
+ self.logMsg('Unknown requests error', -1)
+ import traceback
+ self.logMsg(traceback.format_exc(), 0)
+ return False
+
+ # THE RESPONSE #####
+ if r.status_code == 204:
+ # No body in the response
+ return True
+
+ elif r.status_code in (200, 201):
+ # 200: OK
+ # 201: Created
+ try:
+ # xml response
+ r = etree.fromstring(r.content)
+ return r
+ except:
+ r.encoding = 'utf-8'
+ if r.text == '':
+ # Answer does not contain a body (even though it should)
+ return True
+ try:
+ # UNICODE - JSON object
+ r = r.json()
+ return r
+ except:
+ self.logMsg("Unable to convert the response for: %s"
+ % url, -1)
+ self.logMsg("Received headers were: %s" % r.headers, -1)
+ return False
+ else:
+ self.logMsg('Unknown answer from PMS %s with status code %s. '
+ 'Message:' % (url, r.status_code), -1)
+ r.encoding = 'utf-8'
+ self.logMsg(r.text, -1)
+ return True
diff --git a/resources/lib/initialsetup.py b/resources/lib/initialsetup.py
index 224b2bf5..c592f6c4 100644
--- a/resources/lib/initialsetup.py
+++ b/resources/lib/initialsetup.py
@@ -36,7 +36,6 @@ class InitialSetup():
# SERVER INFO #####
self.logMsg("Initial setup called.", 0)
server = self.userClient.getServer()
- clientId = self.clientInfo.getDeviceId()
serverid = utils.settings('plex_machineIdentifier')
# Get Plex credentials from settings file, if they exist
plexdict = self.plx.GetPlexLoginFromSettings()
@@ -54,8 +53,15 @@ class InitialSetup():
if (plexToken and myplexlogin == 'true' and forcePlexTV is False
and chooseServer is False):
chk = self.plx.CheckConnection('plex.tv', plexToken)
+ try:
+ chk.attrib
+ except:
+ pass
+ else:
+ # Success - we downloaded an xml!
+ chk = 200
# HTTP Error: unauthorized. Token is no longer valid
- if chk == 401 or chk == 403:
+ if chk in (401, 403):
self.logMsg('plex.tv connection returned HTTP %s' % chk, 0)
# Delete token in the settings
utils.settings('plexToken', value='')
@@ -113,18 +119,13 @@ class InitialSetup():
httpsUpdated = False
while True:
if httpsUpdated is False:
- tokenDict = {'MyPlexToken': plexToken} if plexToken else {}
# Populate g_PMS variable with the found Plex servers
- self.plx.discoverPMS(clientId,
- None,
- xbmc.getIPAddress(),
- tokenDict=tokenDict)
- self.logMsg("Result of setting g_PMS variable: %s"
- % self.plx.g_PMS, 1)
+ self.plx.discoverPMS(xbmc.getIPAddress(),
+ plexToken=plexToken)
isconnected = False
- serverlist = self.plx.returnServerList(clientId,
- self.plx.g_PMS)
- self.logMsg('PMS serverlist: %s' % serverlist)
+ self.logMsg('g_PMS: %s' % self.plx.g_PMS, 1)
+ serverlist = self.plx.returnServerList(self.plx.g_PMS)
+ self.logMsg('PMS serverlist: %s' % serverlist, 2)
# Let user pick server from a list
# Get a nicer list
dialoglist = []
@@ -138,11 +139,20 @@ class InitialSetup():
for server in serverlist:
if server['local'] == '1':
# server is in the same network as client. Add "local"
- dialoglist.append(
- server['name']
- + string(39022))
+ msg = string(39022)
else:
- dialoglist.append(server['name'])
+ # Add 'remote'
+ msg = string(39054)
+ if server.get('ownername'):
+ # Display username if its not our PMS
+ dialoglist.append('%s (%s, %s)'
+ % (server['name'],
+ server['ownername'],
+ msg))
+ else:
+ dialoglist.append('%s (%s)'
+ % (server['name'],
+ msg))
resp = dialog.select(string(39012), dialoglist)
server = serverlist[resp]
activeServer = server['machineIdentifier']
@@ -154,15 +164,20 @@ class InitialSetup():
else:
url = server['baseURL']
# Deactive SSL verification if the server is local!
+ # Watch out - settings is cached by Kodi - use dedicated var!
if server['local'] == '1':
utils.settings('sslverify', 'false')
self.logMsg("Setting SSL verify to false, because server is "
"local", 1)
+ verifySSL = False
else:
utils.settings('sslverify', 'true')
self.logMsg("Setting SSL verify to true, because server is "
"not local", 1)
- chk = self.plx.CheckConnection(url, server['accesstoken'])
+ verifySSL = None
+ chk = self.plx.CheckConnection(url,
+ server['accesstoken'],
+ verifySSL=verifySSL)
if chk == 504 and httpsUpdated is False:
# Not able to use HTTP, try HTTPs for now
serverlist[resp]['scheme'] = 'https'
@@ -221,19 +236,6 @@ class InitialSetup():
% (activeServer, server['ip'], server['port'],
server['scheme']), 0)
- # ADDITIONAL PROMPTS #####
- # directPaths = dialog.yesno(
- # heading="%s: Playback Mode" % self.addonName,
- # line1=(
- # "Caution! If you choose Native mode, you "
- # "will probably lose access to certain Plex "
- # "features."),
- # nolabel="Addon (Default)",
- # yeslabel="Native (Direct Paths)")
- # if directPaths:
- # self.logMsg("User opted to use direct paths.", 1)
- # utils.settings('useDirectPaths', value="1")
-
if forcePlexTV is True or chooseServer is True:
return
diff --git a/resources/lib/plexbmchelper/subscribers.py b/resources/lib/plexbmchelper/subscribers.py
index b742a21d..9c4caf10 100644
--- a/resources/lib/plexbmchelper/subscribers.py
+++ b/resources/lib/plexbmchelper/subscribers.py
@@ -278,9 +278,8 @@ class Subscriber:
Threaded POST request, because they stall due to PMS response missing
the Content-Length header :-(
"""
- response = self.download.downloadUrl(
- url,
- postBody=msg,
- type="POSTXML")
+ response = self.download.downloadUrl(url,
+ postBody=msg,
+ type="POST")
if response in [False, None, 401]:
self.subMgr.removeSubscriber(self.uuid)
diff --git a/resources/lib/userclient.py b/resources/lib/userclient.py
index 842bcf87..0f520354 100644
--- a/resources/lib/userclient.py
+++ b/resources/lib/userclient.py
@@ -106,29 +106,12 @@ class UserClient(threading.Thread):
def getSSLverify(self):
# Verify host certificate
- settings = utils.settings
-
- s_sslverify = settings('sslverify')
- if settings('altip') == "true":
- s_sslverify = settings('secondsslverify')
-
- if s_sslverify == "true":
- return True
- else:
- return False
+ return None if utils.settings('sslverify') == 'true' else False
def getSSL(self):
# Client side certificate
- settings = utils.settings
-
- s_cert = settings('sslcert')
- if settings('altip') == "true":
- s_cert = settings('secondsslcert')
-
- if s_cert == "None":
- return None
- else:
- return s_cert
+ return None if utils.settings('sslcert') == 'None' \
+ else utils.settings('sslcert')
def setUserPref(self):
self.logMsg('Setting user preferences', 0)
@@ -183,8 +166,9 @@ class UserClient(threading.Thread):
if authenticated is False:
self.logMsg('Testing validity of current token', 0)
- res = PlexAPI.PlexAPI().CheckConnection(
- self.currServer, self.currToken)
+ res = PlexAPI.PlexAPI().CheckConnection(self.currServer,
+ token=self.currToken,
+ verifySSL=self.ssl)
if res is False:
self.logMsg('Answer from PMS is not as expected. Retrying', -1)
return False
@@ -227,13 +211,6 @@ class UserClient(threading.Thread):
window('remapSMB%sOrg' % item, value=org)
window('remapSMB%sNew' % item, value=new)
- # Set DownloadUtils values
- doUtils.setUsername(username)
- doUtils.setUserId(self.currUserId)
- doUtils.setServer(self.currServer)
- doUtils.setToken(self.currToken)
- doUtils.setSSL(self.ssl, self.sslcert)
-
# Start DownloadUtils session
doUtils.startSession()
# self.getAdditionalUsers()
diff --git a/service.py b/service.py
index 6749450e..754037fa 100644
--- a/service.py
+++ b/service.py
@@ -233,7 +233,7 @@ class Service():
if server is False:
# No server info set in add-on settings
pass
- elif plx.CheckConnection(server) is False:
+ elif plx.CheckConnection(server, verifySSL=True) is False:
# Server is offline or cannot be reached
# Alert the user and suppress future warning
if self.server_online: