diff --git a/resources/language/resource.language.en_gb/strings.po b/resources/language/resource.language.en_gb/strings.po index 453aa50b..4cdd8da2 100644 --- a/resources/language/resource.language.en_gb/strings.po +++ b/resources/language/resource.language.en_gb/strings.po @@ -997,7 +997,7 @@ msgstr "" # add-on settings msgctxt "#30500" -msgid "Verify Host SSL Certificate (more secure)" +msgid "Verify SSL Certificate" msgstr "" msgctxt "#30501" diff --git a/resources/lib/connect/connectionmanager.py b/resources/lib/connect/connectionmanager.py index 625805d4..37a54463 100644 --- a/resources/lib/connect/connectionmanager.py +++ b/resources/lib/connect/connectionmanager.py @@ -175,36 +175,38 @@ class ConnectionManager(object): "application/x-www-form-urlencoded") 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: - raise AttributeError("Request cannot be null") - + ...and all the other requests settings + """ self._getHeaders(request) request['timeout'] = request.get('timeout') or self.default_timeout - request['verify'] = request.get('ssl') or False action = request['type'] request.pop('type', None) - request.pop('ssl', None) - log.debug("ConnectionManager requesting %s" % request) + log.debug("Requesting %s" % request) try: r = self._requests(action, **request) log.info("ConnectionManager response status: %s" % r.status_code) r.raise_for_status() - - except Exception as e: # Elaborate on exceptions? + except Exception as e: + # Elaborate on exceptions? log.error(e) raise - else: try: return etree.fromstring(r.content) except etree.ParseError: # Read response to release connection r.content - return + raise def _requests(self, action, **kwargs): @@ -284,25 +286,12 @@ class ConnectionManager(object): GDM.close() return servers - def _normalizeAddress(self, address): - # Attempt to correct bad input - 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 connectToAddress(self, address, options=None): + log.debug('connectToAddress %s with options %s' % (address, options)) def _onFail(): - log.error("connectToAddress %s failed" % address) + log.error("connectToAddress %s failed with options %s" % + (address, options)) return self._resolveFailure() try: @@ -310,10 +299,10 @@ class ConnectionManager(object): except Exception: return _onFail() else: - log.info("connectToAddress %s succeeded" % address) server = { 'ManualAddress': address, - 'LastCONNECTIONMODE': CONNECTIONMODE['Manual'] + 'LastCONNECTIONMODE': CONNECTIONMODE['Manual'], + 'options': options } self._updateServerInfo(server, publicInfo) server = self.connectToServer(server, options) @@ -342,15 +331,15 @@ class ConnectionManager(object): self._saveUserInfoIntoCredentials(server, result['User']) self.credentialProvider.getCredentials(credentials) - def _tryConnect(self, url, timeout=None, options={}): - url = '%s/identity' % url - log.debug("tryConnect url: %s" % url) - return self.requestUrl({ - 'type': "GET", - 'url': url, - 'timeout': timeout, - 'ssl': options.get('ssl') - }) + def _tryConnect(self, url, timeout=None, options=None): + request = { + 'type': 'GET', + 'url': '%s/identity' % url, + 'timeout': timeout + } + if options: + request.update(options) + return self.requestUrl(request) def _addAppInfoToConnectRequest(self): return "%s/%s" % (self.appName, self.appVersion) @@ -365,7 +354,7 @@ class ConnectionManager(object): 'type': 'GET', 'headers': {'X-Plex-Token': self.plexToken}, 'timeout': 5.0, - 'ssl': True}) + 'verify': True}) try: xml.attrib except AttributeError: @@ -528,7 +517,6 @@ class ConnectionManager(object): return 0 def connectToServer(self, server, options={}): - log.info("begin connectToServer") tests = [] diff --git a/resources/lib/dialogs/servermanual.py b/resources/lib/dialogs/servermanual.py index 20052ac6..861257a8 100644 --- a/resources/lib/dialogs/servermanual.py +++ b/resources/lib/dialogs/servermanual.py @@ -6,11 +6,10 @@ from os.path import join import xbmcgui import connect.connectionmanager as connectionmanager -from utils import language as lang, tryEncode +from utils import language as lang, tryEncode, tryDecode import variables as v ############################################################################### - log = getLogger("PLEX."+__name__) CONN_STATE = connectionmanager.CONNECTIONSTATE @@ -22,24 +21,51 @@ CANCEL = 201 ERROR_TOGGLE = 202 ERROR_MSG = 203 VERIFY_SSL = 204 +HOST_SSL_PATH = 205 +PMS_IP = 208 +PMS_PORT = 209 ERROR = { 'Invalid': 1, 'Empty': 2 } MEDIA = tryEncode(join(v.ADDON_PATH, 'resources', 'skins', 'default', 'media')) - ############################################################################### class ServerManual(xbmcgui.WindowXMLDialog): - _server = 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): self.connect_manager = connect_manager @@ -50,34 +76,8 @@ class ServerManual(xbmcgui.WindowXMLDialog): def get_server(self): 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): - if control == CONNECT: - # Sign in to emby connect self._disable_error() server = self.host_field.getText() @@ -90,56 +90,42 @@ class ServerManual(xbmcgui.WindowXMLDialog): elif self._connect_to_server(server, port): self.close() + elif control == CANCEL: - # Remind me later 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): - - if self.error == ERROR['Empty'] and self.host_field.getText() and self.port_field.getText(): + if (self.error == ERROR['Empty'] and + self.host_field.getText() and self.port_field.getText()): self._disable_error() - if action in (ACTION_BACK, ACTION_PARENT_DIR, ACTION_PREVIOUS_MENU): 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): - - server_address = "%s:%s" % (server, port) - self._message("%s %s..." % (lang(30023), server_address)) - result = self.connect_manager.connectToAddress(server_address) - + """Returns True if we could connect, False otherwise""" + url = "%s:%s" % (server, port) + self._message("%s %s..." % (lang(30023), url)) + 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']: self._message(lang(30204)) return False @@ -148,17 +134,17 @@ class ServerManual(xbmcgui.WindowXMLDialog): return True def _message(self, message): - + """Displays a message popup just underneath the dialog""" self.error_msg.setLabel(message) self.error_toggle.setVisibleCondition('True') def _error(self, state, message): - + """Displays an error message just underneath the dialog""" self.error = state self.error_msg.setLabel(message) self.error_toggle.setVisibleCondition('True') def _disable_error(self): - + """Disables the message popup just underneath the dialog""" self.error = None self.error_toggle.setVisibleCondition('False') diff --git a/resources/skins/default/1080i/script-plex-connect-server-manual.xml b/resources/skins/default/1080i/script-plex-connect-server-manual.xml index 8c0c65fe..0f566d16 100644 --- a/resources/skins/default/1080i/script-plex-connect-server-manual.xml +++ b/resources/skins/default/1080i/script-plex-connect-server-manual.xml @@ -12,7 +12,7 @@ 50% 50% 560 - 560 + 656 white -20 @@ -20,7 +20,7 @@ Background box white.png 600 - 600 + 636 Plex logo @@ -43,47 +43,104 @@ Container for spacing 80 0 - 480 + 400 560 top - font6 50 560 PMS IP address or host name - + + font10 - + 50 560 - font4 https://192.168.1.2, https://myserver.com + font10 50 560 Port Number - + + font10 - + 50 560 - font4 + font10 + + + Advanced + 50 + 560 + + font10 + Verify SSL Certificate 560 - Verify Host SSL Certificate + font10 + + Client SSL certificate + 560 + + font10 + + + + Buttons group + 480 + 50 + 460 + 100 Connect - - 201 + + 50 + 460 + font10 + box.png + box.png + ffa6a6a6 + white + center Cancel - - 200 + + 55 + 50 + 460 + font10 + box.png + box.png + ffa6a6a6 + white + center + + + + 626 + -20 + 600 + False + + Error box + white.png + 100% + 50 + + + Error message + white + font10 + center + center + 50 diff --git a/resources/skins/default/1080i/script-plex-connect-server.xml b/resources/skins/default/1080i/script-plex-connect-server.xml index 241e5654..d9c3c4c0 100644 --- a/resources/skins/default/1080i/script-plex-connect-server.xml +++ b/resources/skins/default/1080i/script-plex-connect-server.xml @@ -80,10 +80,10 @@ - Select server + Select Main PMS ffa6a6a6 - font10 + font12 center top 170 @@ -205,7 +205,7 @@ Toggle plex.tv sign-in box.png box.png - + font10 ffa6a6a6 white @@ -221,7 +221,7 @@ Manually add server box.png box.png - + font10 ffa6a6a6 white @@ -239,7 +239,7 @@ Cancel box.png box.png - + font10 ffa6a6a6 white