Dialog: manual PMS entry, part 3

This commit is contained in:
tomkat83 2017-07-27 17:40:18 +02:00
parent 76ca66b38b
commit c1098f22a4
5 changed files with 168 additions and 137 deletions

View file

@ -997,7 +997,7 @@ msgstr ""
# add-on settings # add-on settings
msgctxt "#30500" msgctxt "#30500"
msgid "Verify Host SSL Certificate (more secure)" msgid "Verify SSL Certificate"
msgstr "" msgstr ""
msgctxt "#30501" msgctxt "#30501"

View file

@ -175,36 +175,38 @@ class ConnectionManager(object):
"application/x-www-form-urlencoded") "application/x-www-form-urlencoded")
def requestUrl(self, request): def requestUrl(self, request):
"""
request: dict with the following (optional) keys:
type: GET, POST, ... (mandatory)
url: (mandatory)
timeout
verify: set to False to disable SSL certificate check
if not request: ...and all the other requests settings
raise AttributeError("Request cannot be null") """
self._getHeaders(request) self._getHeaders(request)
request['timeout'] = request.get('timeout') or self.default_timeout request['timeout'] = request.get('timeout') or self.default_timeout
request['verify'] = request.get('ssl') or False
action = request['type'] action = request['type']
request.pop('type', None) request.pop('type', None)
request.pop('ssl', None)
log.debug("ConnectionManager requesting %s" % request) log.debug("Requesting %s" % request)
try: try:
r = self._requests(action, **request) r = self._requests(action, **request)
log.info("ConnectionManager response status: %s" % r.status_code) log.info("ConnectionManager response status: %s" % r.status_code)
r.raise_for_status() r.raise_for_status()
except Exception as e:
except Exception as e: # Elaborate on exceptions? # Elaborate on exceptions?
log.error(e) log.error(e)
raise raise
else: else:
try: try:
return etree.fromstring(r.content) return etree.fromstring(r.content)
except etree.ParseError: except etree.ParseError:
# Read response to release connection # Read response to release connection
r.content r.content
return raise
def _requests(self, action, **kwargs): def _requests(self, action, **kwargs):
@ -284,25 +286,12 @@ class ConnectionManager(object):
GDM.close() GDM.close()
return servers return servers
def _normalizeAddress(self, address): def connectToAddress(self, address, options=None):
# Attempt to correct bad input log.debug('connectToAddress %s with options %s' % (address, options))
address = address.strip()
address = address.lower()
if 'http' not in address:
address = "http://%s" % address
return address
def connectToAddress(self, address, options={}):
if not address:
return False
address = self._normalizeAddress(address)
def _onFail(): def _onFail():
log.error("connectToAddress %s failed" % address) log.error("connectToAddress %s failed with options %s" %
(address, options))
return self._resolveFailure() return self._resolveFailure()
try: try:
@ -310,10 +299,10 @@ class ConnectionManager(object):
except Exception: except Exception:
return _onFail() return _onFail()
else: else:
log.info("connectToAddress %s succeeded" % address)
server = { server = {
'ManualAddress': address, 'ManualAddress': address,
'LastCONNECTIONMODE': CONNECTIONMODE['Manual'] 'LastCONNECTIONMODE': CONNECTIONMODE['Manual'],
'options': options
} }
self._updateServerInfo(server, publicInfo) self._updateServerInfo(server, publicInfo)
server = self.connectToServer(server, options) server = self.connectToServer(server, options)
@ -342,15 +331,15 @@ class ConnectionManager(object):
self._saveUserInfoIntoCredentials(server, result['User']) self._saveUserInfoIntoCredentials(server, result['User'])
self.credentialProvider.getCredentials(credentials) self.credentialProvider.getCredentials(credentials)
def _tryConnect(self, url, timeout=None, options={}): def _tryConnect(self, url, timeout=None, options=None):
url = '%s/identity' % url request = {
log.debug("tryConnect url: %s" % url) 'type': 'GET',
return self.requestUrl({ 'url': '%s/identity' % url,
'type': "GET", 'timeout': timeout
'url': url, }
'timeout': timeout, if options:
'ssl': options.get('ssl') request.update(options)
}) return self.requestUrl(request)
def _addAppInfoToConnectRequest(self): def _addAppInfoToConnectRequest(self):
return "%s/%s" % (self.appName, self.appVersion) return "%s/%s" % (self.appName, self.appVersion)
@ -365,7 +354,7 @@ class ConnectionManager(object):
'type': 'GET', 'type': 'GET',
'headers': {'X-Plex-Token': self.plexToken}, 'headers': {'X-Plex-Token': self.plexToken},
'timeout': 5.0, 'timeout': 5.0,
'ssl': True}) 'verify': True})
try: try:
xml.attrib xml.attrib
except AttributeError: except AttributeError:
@ -528,7 +517,6 @@ class ConnectionManager(object):
return 0 return 0
def connectToServer(self, server, options={}): def connectToServer(self, server, options={}):
log.info("begin connectToServer") log.info("begin connectToServer")
tests = [] tests = []

View file

@ -6,11 +6,10 @@ from os.path import join
import xbmcgui import xbmcgui
import connect.connectionmanager as connectionmanager import connect.connectionmanager as connectionmanager
from utils import language as lang, tryEncode from utils import language as lang, tryEncode, tryDecode
import variables as v import variables as v
############################################################################### ###############################################################################
log = getLogger("PLEX."+__name__) log = getLogger("PLEX."+__name__)
CONN_STATE = connectionmanager.CONNECTIONSTATE CONN_STATE = connectionmanager.CONNECTIONSTATE
@ -22,24 +21,51 @@ CANCEL = 201
ERROR_TOGGLE = 202 ERROR_TOGGLE = 202
ERROR_MSG = 203 ERROR_MSG = 203
VERIFY_SSL = 204 VERIFY_SSL = 204
HOST_SSL_PATH = 205
PMS_IP = 208
PMS_PORT = 209
ERROR = { ERROR = {
'Invalid': 1, 'Invalid': 1,
'Empty': 2 'Empty': 2
} }
MEDIA = tryEncode(join(v.ADDON_PATH, 'resources', 'skins', 'default', 'media')) MEDIA = tryEncode(join(v.ADDON_PATH, 'resources', 'skins', 'default', 'media'))
############################################################################### ###############################################################################
class ServerManual(xbmcgui.WindowXMLDialog): class ServerManual(xbmcgui.WindowXMLDialog):
_server = None _server = None
error = None error = None
def __init__(self, *args, **kwargs): def onInit(self):
self.connect_button = self.getControl(CONNECT)
self.cancel_button = self.getControl(CANCEL)
self.error_toggle = self.getControl(ERROR_TOGGLE)
self.error_msg = self.getControl(ERROR_MSG)
xbmcgui.WindowXMLDialog.__init__(self, *args, **kwargs) self.host_field = self.getControl(PMS_IP)
self.port_field = self.getControl(PMS_PORT)
self.verify_ssl_radio = self.getControl(VERIFY_SSL)
self.host_ssl_path_radio = self.getControl(HOST_SSL_PATH)
self.port_field.setText('32400')
self.setFocus(self.host_field)
self.verify_ssl_radio.setSelected(True)
self.host_ssl_path_radio.setSelected(False)
self.host_ssl_path = None
self.host_field.controlUp(self.cancel_button)
self.host_field.controlDown(self.port_field)
self.port_field.controlUp(self.host_field)
self.port_field.controlDown(self.verify_ssl_radio)
self.verify_ssl_radio.controlUp(self.port_field)
self.verify_ssl_radio.controlDown(self.host_ssl_path_radio)
self.host_ssl_path_radio.controlUp(self.verify_ssl_radio)
self.host_ssl_path_radio.controlDown(self.connect_button)
self.connect_button.controlUp(self.host_ssl_path_radio)
self.connect_button.controlDown(self.cancel_button)
self.cancel_button.controlUp(self.connect_button)
self.cancel_button.controlDown(self.host_field)
def set_connect_manager(self, connect_manager): def set_connect_manager(self, connect_manager):
self.connect_manager = connect_manager self.connect_manager = connect_manager
@ -50,34 +76,8 @@ class ServerManual(xbmcgui.WindowXMLDialog):
def get_server(self): def get_server(self):
return self._server return self._server
def onInit(self):
self.connect_button = self.getControl(CONNECT)
self.cancel_button = self.getControl(CANCEL)
self.error_toggle = self.getControl(ERROR_TOGGLE)
self.error_msg = self.getControl(ERROR_MSG)
self.host_field = self._add_editcontrol(725, 325, 40, 500)
self.port_field = self._add_editcontrol(725, 450, 40, 500)
# self.ssl_field = self._add_radiobutton(725, 550, 50, 50)
self.ssl_field = self.getControl(VERIFY_SSL)
self.port_field.setText('32400')
self.setFocus(self.host_field)
self.ssl_field.setSelected(True)
self.host_field.controlUp(self.cancel_button)
self.host_field.controlDown(self.port_field)
self.port_field.controlUp(self.host_field)
self.port_field.controlDown(self.ssl_field)
self.ssl_field.controlUp(self.port_field)
self.ssl_field.controlDown(self.connect_button)
self.connect_button.controlUp(self.ssl_field)
self.cancel_button.controlDown(self.host_field)
def onClick(self, control): def onClick(self, control):
if control == CONNECT: if control == CONNECT:
# Sign in to emby connect
self._disable_error() self._disable_error()
server = self.host_field.getText() server = self.host_field.getText()
@ -90,56 +90,42 @@ class ServerManual(xbmcgui.WindowXMLDialog):
elif self._connect_to_server(server, port): elif self._connect_to_server(server, port):
self.close() self.close()
elif control == CANCEL: elif control == CANCEL:
# Remind me later
self.close() self.close()
elif control == HOST_SSL_PATH:
if self.host_ssl_path_radio.isSelected():
# Let the user choose path to the certificate (=file)
self.host_ssl_path = xbmcgui.Dialog().browse(
1, lang(29999), 'files', '', False, False, '', False)
log.debug('Host SSL file path chosen: %s' % self.host_ssl_path)
if not self.host_ssl_path:
self.host_ssl_path_radio.setSelected(False)
else:
self.host_ssl_path = tryDecode(self.host_ssl_path)
else:
# User disabled
# Ensure that we don't have a host certificate set
self.host_ssl_path = None
def onAction(self, action): def onAction(self, action):
if (self.error == ERROR['Empty'] and
if self.error == ERROR['Empty'] and self.host_field.getText() and self.port_field.getText(): self.host_field.getText() and self.port_field.getText()):
self._disable_error() self._disable_error()
if action in (ACTION_BACK, ACTION_PARENT_DIR, ACTION_PREVIOUS_MENU): if action in (ACTION_BACK, ACTION_PARENT_DIR, ACTION_PREVIOUS_MENU):
self.close() self.close()
def _add_editcontrol(self, x, y, height, width):
control = xbmcgui.ControlEdit(
0, 0, 0, 0,
label="User",
font="font10",
textColor="ffc2c2c2",
focusTexture=join(MEDIA, "button-focus.png"),
noFocusTexture=join(MEDIA, "button-focus.png"))
control.setPosition(x, y)
control.setHeight(height)
control.setWidth(width)
self.addControl(control)
return control
def _add_radiobutton(self, x, y, height, width):
control = xbmcgui.ControlRadioButton(
0, 0, 0, 0,
label="",
font="font10",
textColor="ffc2c2c2",
focusOnTexture=join(MEDIA, "radio-on.png"),
noFocusOnTexture=join(MEDIA, "radio-on.png"),
focusOffTexture=join(MEDIA, "radio-off.png"),
noFocusOffTexture=join(MEDIA, "radio-off.png"))
control.setPosition(x, y)
control.setHeight(height)
control.setWidth(width)
self.addControl(control)
return control
def _connect_to_server(self, server, port): def _connect_to_server(self, server, port):
"""Returns True if we could connect, False otherwise"""
server_address = "%s:%s" % (server, port) url = "%s:%s" % (server, port)
self._message("%s %s..." % (lang(30023), server_address)) self._message("%s %s..." % (lang(30023), url))
result = self.connect_manager.connectToAddress(server_address) options = {
'verify': True if self.verify_ssl_radio.isSelected() else False
}
if self.host_ssl_path:
options['cert'] = self.host_ssl_path
result = self.connect_manager.connectToAddress(url, options)
log.debug('Received the following results: %s' % result)
if result['State'] == CONN_STATE['Unavailable']: if result['State'] == CONN_STATE['Unavailable']:
self._message(lang(30204)) self._message(lang(30204))
return False return False
@ -148,17 +134,17 @@ class ServerManual(xbmcgui.WindowXMLDialog):
return True return True
def _message(self, message): def _message(self, message):
"""Displays a message popup just underneath the dialog"""
self.error_msg.setLabel(message) self.error_msg.setLabel(message)
self.error_toggle.setVisibleCondition('True') self.error_toggle.setVisibleCondition('True')
def _error(self, state, message): def _error(self, state, message):
"""Displays an error message just underneath the dialog"""
self.error = state self.error = state
self.error_msg.setLabel(message) self.error_msg.setLabel(message)
self.error_toggle.setVisibleCondition('True') self.error_toggle.setVisibleCondition('True')
def _disable_error(self): def _disable_error(self):
"""Disables the message popup just underneath the dialog"""
self.error = None self.error = None
self.error_toggle.setVisibleCondition('False') self.error_toggle.setVisibleCondition('False')

View file

@ -12,7 +12,7 @@
<centerleft>50%</centerleft> <centerleft>50%</centerleft>
<centertop>50%</centertop> <centertop>50%</centertop>
<width>560</width> <width>560</width>
<height>560</height> <height>656</height>
<textcolor>white</textcolor> <textcolor>white</textcolor>
<control type="image"> <control type="image">
<top>-20</top> <top>-20</top>
@ -20,7 +20,7 @@
<description>Background box</description> <description>Background box</description>
<texture colordiffuse="ff111111">white.png</texture> <texture colordiffuse="ff111111">white.png</texture>
<width>600</width> <width>600</width>
<height>600</height> <height>636</height>
</control> </control>
<control type="image"> <control type="image">
<description>Plex logo</description> <description>Plex logo</description>
@ -43,47 +43,104 @@
<description>Container for spacing</description> <description>Container for spacing</description>
<top>80</top> <top>80</top>
<left>0</left> <left>0</left>
<height>480</height> <height>400</height>
<width>560</width> <width>560</width>
<aligny>top</aligny> <aligny>top</aligny>
<font>font6</font>
<control type="label"> <control type="label">
<height>50</height> <height>50</height>
<width>560</width> <width>560</width>
<description>PMS IP address or host name</description> <description>PMS IP address or host name</description>
<label>$ADDON[plugin.video.plexkodiconnect 30019]</label> <label>$ADDON[plugin.video.plexkodiconnect 30019]:</label>
<font>font10</font>
</control> </control>
<control type="edit" id="1"> <control type="edit" id="208">
<height>50</height> <height>50</height>
<width>560</width> <width>560</width>
<font>font4</font>
<hinttext>https://192.168.1.2, https://myserver.com</hinttext> <hinttext>https://192.168.1.2, https://myserver.com</hinttext>
<font>font10</font>
</control> </control>
<control type="label"> <control type="label">
<height>50</height> <height>50</height>
<width>560</width> <width>560</width>
<description>Port Number</description> <description>Port Number</description>
<label>$ADDON[plugin.video.plexkodiconnect 30030]</label> <label>$ADDON[plugin.video.plexkodiconnect 30030]:</label>
<font>font10</font>
</control> </control>
<control type="edit" id="2"> <control type="edit" id="209">
<height>50</height> <height>50</height>
<width>560</width> <width>560</width>
<font>font4</font> <font>font10</font>
</control>
<control type="label">
<description>Advanced</description>
<height>50</height>
<width>560</width>
<label>$ADDON[plugin.video.plexkodiconnect 30022]:</label>
<font>font10</font>
</control> </control>
<control type="radiobutton" id="204"> <control type="radiobutton" id="204">
<description>Verify SSL Certificate</description>
<width>560</width> <width>560</width>
<description>Verify Host SSL Certificate</description>
<label>$ADDON[plugin.video.plexkodiconnect 30500]</label> <label>$ADDON[plugin.video.plexkodiconnect 30500]</label>
<font>font10</font>
</control> </control>
<control type="radiobutton" id="205">
<description>Client SSL certificate</description>
<width>560</width>
<label>$ADDON[plugin.video.plexkodiconnect 30501]</label>
<font>font10</font>
</control>
</control>
<control type="group">
<description>Buttons group</description>
<top>480</top>
<left>50</left>
<width>460</width>
<height>100</height>
<control type="button" id="200"> <control type="button" id="200">
<description>Connect</description> <description>Connect</description>
<label>$ADDON[plugin.video.plexkodiconnect 30020]</label> <label>[UPPERCASE][B]$ADDON[plugin.video.plexkodiconnect 30020][/UPPERCASE][/B]</label>
<ondown>201</ondown> <height>50</height>
<width>460</width>
<font>font10</font>
<texturenofocus border="5" colordiffuse="ff464646">box.png</texturenofocus>
<texturefocus border="5" colordiffuse="ff525252">box.png</texturefocus>
<textcolor>ffa6a6a6</textcolor>
<focusedcolor>white</focusedcolor>
<align>center</align>
</control> </control>
<control type="button" id="201"> <control type="button" id="201">
<description>Cancel</description> <description>Cancel</description>
<label>$ADDON[plugin.video.plexkodiconnect 30602]</label> <label>[UPPERCASE][B]$ADDON[plugin.video.plexkodiconnect 30602][/UPPERCASE][/B]</label>
<onup>200</onup> <top>55</top>
<height>50</height>
<width>460</width>
<font>font10</font>
<texturenofocus border="5" colordiffuse="ff464646">box.png</texturenofocus>
<texturefocus border="5" colordiffuse="ff525252">box.png</texturefocus>
<textcolor>ffa6a6a6</textcolor>
<focusedcolor>white</focusedcolor>
<align>center</align>
</control>
</control>
<control type="group" id="202">
<top>626</top>
<left>-20</left>
<width>600</width>
<visible>False</visible>
<control type="image">
<description>Error box</description>
<texture colordiffuse="ff222222">white.png</texture>
<width>100%</width>
<height>50</height>
</control>
<control type="label" id="203">
<description>Error message</description>
<textcolor>white</textcolor>
<font>font10</font>
<aligny>center</aligny>
<align>center</align>
<height>50</height>
</control> </control>
</control> </control>
</control> </control>

View file

@ -80,10 +80,10 @@
</control> </control>
<control type="label"> <control type="label">
<description>Select server</description> <description>Select Main PMS</description>
<textcolor>ffa6a6a6</textcolor> <textcolor>ffa6a6a6</textcolor>
<label>$ADDON[plugin.video.plexkodiconnect 30607]</label> <label>$ADDON[plugin.video.plexkodiconnect 30607]</label>
<font>font10</font> <font>font12</font>
<align>center</align> <align>center</align>
<aligny>top</aligny> <aligny>top</aligny>
<top>170</top> <top>170</top>
@ -205,7 +205,7 @@
<description>Toggle plex.tv sign-in</description> <description>Toggle plex.tv sign-in</description>
<texturenofocus border="5" colordiffuse="ff464646">box.png</texturenofocus> <texturenofocus border="5" colordiffuse="ff464646">box.png</texturenofocus>
<texturefocus border="5" colordiffuse="ff525252">box.png</texturefocus> <texturefocus border="5" colordiffuse="ff525252">box.png</texturefocus>
<label>$ADDON[plugin.video.plexkodiconnect 30600]</label> <label>[UPPERCASE][B]$ADDON[plugin.video.plexkodiconnect 30600][/UPPERCASE][/B]</label>
<font>font10</font> <font>font10</font>
<textcolor>ffa6a6a6</textcolor> <textcolor>ffa6a6a6</textcolor>
<focusedcolor>white</focusedcolor> <focusedcolor>white</focusedcolor>
@ -221,7 +221,7 @@
<description>Manually add server</description> <description>Manually add server</description>
<texturenofocus border="5" colordiffuse="ff464646">box.png</texturenofocus> <texturenofocus border="5" colordiffuse="ff464646">box.png</texturenofocus>
<texturefocus border="5" colordiffuse="ff525252">box.png</texturefocus> <texturefocus border="5" colordiffuse="ff525252">box.png</texturefocus>
<label>$ADDON[plugin.video.plexkodiconnect 30601]</label> <label>[UPPERCASE][B]$ADDON[plugin.video.plexkodiconnect 30601][/UPPERCASE][/B]</label>
<font>font10</font> <font>font10</font>
<textcolor>ffa6a6a6</textcolor> <textcolor>ffa6a6a6</textcolor>
<focusedcolor>white</focusedcolor> <focusedcolor>white</focusedcolor>
@ -239,7 +239,7 @@
<description>Cancel</description> <description>Cancel</description>
<texturenofocus border="5" colordiffuse="ff464646">box.png</texturenofocus> <texturenofocus border="5" colordiffuse="ff464646">box.png</texturenofocus>
<texturefocus border="5" colordiffuse="ff525252">box.png</texturefocus> <texturefocus border="5" colordiffuse="ff525252">box.png</texturefocus>
<label>$ADDON[plugin.video.plexkodiconnect 30602]</label> <label>[UPPERCASE][B]$ADDON[plugin.video.plexkodiconnect 30602][/UPPERCASE][/B]</label>
<font>font10</font> <font>font10</font>
<textcolor>ffa6a6a6</textcolor> <textcolor>ffa6a6a6</textcolor>
<focusedcolor>white</focusedcolor> <focusedcolor>white</focusedcolor>