def test_create_https_certificates(self): """ Test that create_https_certificates successfully generates certificate and private key """ try: import OpenSSL except ImportError: self.skipTest('pyOpenSSL is not installed') return False base_path = os.path.dirname(__file__) cert_path = os.path.abspath(os.path.join(base_path, 'test.crt')) pkey_path = os.path.abspath(os.path.join(base_path, 'test.key')) def removeTestFiles(): try: os.remove(cert_path) os.remove(pkey_path) except OSError: pass removeTestFiles() # always remove existing self.assertTrue(helpers.create_https_certificates( cert_path, pkey_path)) self.assertTrue(os.path.isfile(cert_path)) self.assertTrue(os.path.isfile(pkey_path)) FILETYPE_PEM = OpenSSL.crypto.FILETYPE_PEM try: with open(cert_path, 'rt') as f: cert = OpenSSL.crypto.load_certificate(FILETYPE_PEM, f.read()) except Exception as error: removeTestFiles() self.fail('Unable to load certificate') try: with open(pkey_path, 'rt') as f: pkey = OpenSSL.crypto.load_privatekey(FILETYPE_PEM, f.read()) except Exception as error: removeTestFiles() self.fail('Unable to load private key') context = OpenSSL.SSL.Context(OpenSSL.SSL.TLSv1_METHOD) context.use_privatekey(pkey) context.use_certificate(cert) failed = False try: context.check_privatekey() except OpenSSL.SSL.Error: failed = True finally: removeTestFiles() self.assertFalse(failed, 'private key does not match certificate')
def test_create_https_certificates(self): """ Test that create_https_certificates successfully generates certificate and private key """ try: import OpenSSL except ImportError: self.skipTest('pyOpenSSL is not installed') return False base_path = os.path.dirname(__file__) cert_path = os.path.abspath(os.path.join(base_path, 'test.crt')) pkey_path = os.path.abspath(os.path.join(base_path, 'test.key')) def removeTestFiles(): try: os.remove(cert_path) os.remove(pkey_path) except OSError: pass removeTestFiles() # always remove existing self.assertTrue(helpers.create_https_certificates(cert_path, pkey_path)) self.assertTrue(os.path.isfile(cert_path)) self.assertTrue(os.path.isfile(pkey_path)) FILETYPE_PEM = OpenSSL.crypto.FILETYPE_PEM try: with open(cert_path, 'rt') as f: cert = OpenSSL.crypto.load_certificate(FILETYPE_PEM, f.read()) except Exception as error: removeTestFiles() self.fail('Unable to load certificate') try: with open(pkey_path, 'rt') as f: pkey = OpenSSL.crypto.load_privatekey(FILETYPE_PEM, f.read()) except Exception as error: removeTestFiles() self.fail('Unable to load private key') context = OpenSSL.SSL.Context(OpenSSL.SSL.TLSv1_METHOD) context.use_privatekey(pkey) context.use_certificate(cert) failed = False try: context.check_privatekey() except OpenSSL.SSL.Error: failed = True finally: removeTestFiles() self.assertFalse(failed, 'private key does not match certificate')
def initWebServer(options={}): options.setdefault('port', 8081) options.setdefault('host', '0.0.0.0') options.setdefault('log_dir', None) options.setdefault('username', '') options.setdefault('password', '') options.setdefault('web_root', '/') assert isinstance(options['port'], int) assert 'data_root' in options # tornado setup enable_https = options['enable_https'] https_cert = options['https_cert'] https_key = options['https_key'] if enable_https: # If either the HTTPS certificate or key do not exist, make some self-signed ones. if not (https_cert and os.path.exists(https_cert)) or not (https_key and os.path.exists(https_key)): if not create_https_certificates(https_cert, https_key): logger.log(u"Unable to create CERT/KEY files, disabling HTTPS") sickbeard.ENABLE_HTTPS = False enable_https = False if not (os.path.exists(https_cert) and os.path.exists(https_key)): logger.log(u"Disabled HTTPS because of missing CERT and KEY files", logger.WARNING) sickbeard.ENABLE_HTTPS = False enable_https = False # Load the app app = Application([], debug=False, gzip=True, xheaders=sickbeard.HANDLE_REVERSE_PROXY, cookie_secret='61oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o/Vo=' ) # Main Handler app.add_handlers(".*$", [ (r"%s" % options['web_root'], RedirectHandler, {'url': '%s/home/' % options['web_root']}), (r'%s/api/(.*)(/?)' % options['web_root'], webapi.Api), (r'%s/(.*)(/?)' % options['web_root'], webserve.MainHandler) ]) # Static Path Handler app.add_handlers(".*$", [ (r'%s/(favicon\.ico)' % options['web_root'], MultiStaticFileHandler, {'paths': [os.path.join(options['data_root'], 'images/ico/favicon.ico')]}), (r'%s/%s/(.*)(/?)' % (options['web_root'], 'images'), MultiStaticFileHandler, {'paths': [os.path.join(options['data_root'], 'images'), os.path.join(sickbeard.CACHE_DIR, 'images')]}), (r'%s/%s/(.*)(/?)' % (options['web_root'], 'css'), MultiStaticFileHandler, {'paths': [os.path.join(options['data_root'], 'css')]}), (r'%s/%s/(.*)(/?)' % (options['web_root'], 'js'), MultiStaticFileHandler, {'paths': [os.path.join(options['data_root'], 'js')]}) ]) global server if enable_https: protocol = "https" server = HTTPServer(app, no_keep_alive=True, ssl_options={"certfile": https_cert, "keyfile": https_key}) else: protocol = "http" server = HTTPServer(app, no_keep_alive=True) logger.log(u"Starting SickRage on " + protocol + "://" + str(options['host']) + ":" + str( options['port']) + "/") try: server.listen(options['port'], options['host']) except: pass
def initWebServer(options={}): options.setdefault('port', 8081) options.setdefault('host', '0.0.0.0') options.setdefault('log_dir', None) options.setdefault('username', '') options.setdefault('password', '') options.setdefault('web_root', '/') assert isinstance(options['port'], int) assert 'data_root' in options def http_error_401_hander(status, message, traceback, version): """ Custom handler for 401 error """ if status != "401 Unauthorized": logger.log(u"Tornado caught an error: %s %s" % (status, message), logger.ERROR) logger.log(traceback, logger.DEBUG) return r'''<!DOCTYPE html> <html> <head> <title>%s</title> </head> <body> <br/> <font color="#0000FF">Error %s: You need to provide a valid username and password.</font> </body> </html> ''' % ('Access denied', status) def http_error_404_hander(status, message, traceback, version): """ Custom handler for 404 error, redirect back to main page """ return r'''<!DOCTYPE html> <html> <head> <title>404</title> <script type="text/javascript" charset="utf-8"> <!-- location.href = "%s/home/" //--> </script> </head> <body> <br/> </body> </html> ''' % options['web_root'] # tornado setup enable_https = options['enable_https'] https_cert = options['https_cert'] https_key = options['https_key'] if enable_https: # If either the HTTPS certificate or key do not exist, make some self-signed ones. if not (https_cert and os.path.exists(https_cert)) or not (https_key and os.path.exists(https_key)): if not create_https_certificates(https_cert, https_key): logger.log(u"Unable to create CERT/KEY files, disabling HTTPS") sickbeard.ENABLE_HTTPS = False enable_https = False if not (os.path.exists(https_cert) and os.path.exists(https_key)): logger.log(u"Disabled HTTPS because of missing CERT and KEY files", logger.WARNING) sickbeard.ENABLE_HTTPS = False enable_https = False # Load the app app = Application([], debug=True, gzip=True, autoreload=True, xheaders=False, cookie_secret='61oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o/Vo=', login_url='/login' ) # Index Handler app.add_handlers(".*$", [ (r"/", RedirectHandler, {'url': '/home/'}), (r'/login', webserve.LoginHandler), (r'/api/(.*)(/?)', webapi.Api), (r'%s(.*)(/?)' % options['web_root'], webserve.IndexHandler) ]) # Static Path Handler app.add_handlers(".*$", [ ('%s/%s/(.*)([^/]*)' % (options['web_root'], 'images'), MultiStaticFileHandler, {'paths': [os.path.join(options['data_root'], 'images'), os.path.join(sickbeard.CACHE_DIR, 'images'), os.path.join(sickbeard.CACHE_DIR, 'images', 'thumbnails')]}), ('%s/%s/(.*)([^/]*)' % (options['web_root'], 'css'), MultiStaticFileHandler, {'paths': [os.path.join(options['data_root'], 'css')]}), ('%s/%s/(.*)([^/]*)' % (options['web_root'], 'js'), MultiStaticFileHandler, {'paths': [os.path.join(options['data_root'], 'js')]}) ]) global server if enable_https: protocol = "https" server = HTTPServer(app, no_keep_alive=True, ssl_options={"certfile": https_cert, "keyfile": https_key}) else: protocol = "http" server = HTTPServer(app, no_keep_alive=True) logger.log(u"Starting SickRage on " + protocol + "://" + str(options['host']) + ":" + str( options['port']) + "/") server.listen(options['port'], options['host'])
def __init__(self, options=None): threading.Thread.__init__(self) self.daemon = True self.alive = True self.name = 'TORNADO' self.io_loop = None self.server = None self.options = options or {} self.options.setdefault('port', 8081) self.options.setdefault('host', '0.0.0.0') self.options.setdefault('log_dir', None) self.options.setdefault('username', '') self.options.setdefault('password', '') self.options.setdefault('web_root', None) assert isinstance(self.options['port'], int) assert 'data_root' in self.options # web root self.options['web_root'] = ('/' + self.options['web_root'].lstrip('/')) if self.options['web_root'] else '' # tornado setup self.enable_https = self.options['enable_https'] self.https_cert = self.options['https_cert'] self.https_key = self.options['https_key'] if self.enable_https: make_cert = False update_cfg = False for (attr, ext) in [('https_cert', '.crt'), ('https_key', '.key')]: ssl_path = getattr(self, attr, None) if ssl_path and not os.path.isfile(ssl_path): if not ssl_path.endswith(ext): setattr(self, attr, os.path.join(ssl_path, 'server%s' % ext)) setattr(sickbeard, attr.upper(), 'server%s' % ext) make_cert = True # If either the HTTPS certificate or key do not exist, make some self-signed ones. if make_cert: if not create_https_certificates(self.https_cert, self.https_key): logger.log(u'Unable to create CERT/KEY files, disabling HTTPS') update_cfg |= False is not sickbeard.ENABLE_HTTPS sickbeard.ENABLE_HTTPS = False self.enable_https = False else: update_cfg = True if not (os.path.isfile(self.https_cert) and os.path.isfile(self.https_key)): logger.log(u'Disabled HTTPS because of missing CERT and KEY files', logger.WARNING) update_cfg |= False is not sickbeard.ENABLE_HTTPS sickbeard.ENABLE_HTTPS = False self.enable_https = False if update_cfg: sickbeard.save_config() # Load the app self.app = Application([], debug=True, serve_traceback=True, autoreload=False, compress_response=True, cookie_secret=sickbeard.COOKIE_SECRET, xsrf_cookies=True, login_url='%s/login/' % self.options['web_root']) re_host_pattern = re_valid_hostname() # webui login/logout handlers self.app.add_handlers(re_host_pattern, [ (r'%s/login(/?)' % self.options['web_root'], webserve.LoginHandler), (r'%s/logout(/?)' % self.options['web_root'], webserve.LogoutHandler), ]) # Web calendar handler (Needed because option Unprotected calendar) self.app.add_handlers(re_host_pattern, [ (r'%s/calendar' % self.options['web_root'], webserve.CalendarHandler), ]) # Static File Handlers self.app.add_handlers(re_host_pattern, [ # favicon (r'%s/(favicon\.ico)' % self.options['web_root'], webserve.BaseStaticFileHandler, {'path': os.path.join(self.options['data_root'], 'images/ico/favicon.ico')}), # images (r'%s/images/(.*)' % self.options['web_root'], webserve.BaseStaticFileHandler, {'path': os.path.join(self.options['data_root'], 'images')}), # cached images (r'%s/cache/images/(.*)' % self.options['web_root'], webserve.BaseStaticFileHandler, {'path': os.path.join(sickbeard.CACHE_DIR, 'images')}), # css (r'%s/css/(.*)' % self.options['web_root'], webserve.BaseStaticFileHandler, {'path': os.path.join(self.options['data_root'], 'css')}), # javascript (r'%s/js/(.*)' % self.options['web_root'], webserve.BaseStaticFileHandler, {'path': os.path.join(self.options['data_root'], 'js')}), (r'%s/kodi/(.*)' % self.options['web_root'], webserve.RepoHandler, {'path': os.path.join(sickbeard.CACHE_DIR, 'clients', 'kodi'), 'default_filename': 'index.html'}), ]) # Main Handler self.app.add_handlers(re_host_pattern, [ (r'%s/api/builder(/?)(.*)' % self.options['web_root'], webserve.ApiBuilder), (r'%s/api(/?.*)' % self.options['web_root'], webapi.Api), (r'%s/imagecache(/?.*)' % self.options['web_root'], webserve.CachedImages), (r'%s/cache(/?.*)' % self.options['web_root'], webserve.Cache), (r'%s/config/general(/?.*)' % self.options['web_root'], webserve.ConfigGeneral), (r'%s/config/search(/?.*)' % self.options['web_root'], webserve.ConfigSearch), (r'%s/config/providers(/?.*)' % self.options['web_root'], webserve.ConfigProviders), (r'%s/config/subtitles(/?.*)' % self.options['web_root'], webserve.ConfigSubtitles), (r'%s/config/postProcessing(/?.*)' % self.options['web_root'], webserve.ConfigPostProcessing), (r'%s/config/notifications(/?.*)' % self.options['web_root'], webserve.ConfigNotifications), (r'%s/config/anime(/?.*)' % self.options['web_root'], webserve.ConfigAnime), (r'%s/config(/?.*)' % self.options['web_root'], webserve.Config), (r'%s/errorlogs(/?.*)' % self.options['web_root'], webserve.ErrorLogs), (r'%s/history(/?.*)' % self.options['web_root'], webserve.History), (r'%s/home/is_alive(/?.*)' % self.options['web_root'], webserve.IsAliveHandler), (r'%s/home/addShows(/?.*)' % self.options['web_root'], webserve.NewHomeAddShows), (r'%s/home/postprocess(/?.*)' % self.options['web_root'], webserve.HomePostProcess), (r'%s/home(/?.*)' % self.options['web_root'], webserve.Home), (r'%s/manage/manageSearches(/?.*)' % self.options['web_root'], webserve.ManageSearches), (r'%s/manage/showProcesses(/?.*)' % self.options['web_root'], webserve.showProcesses), (r'%s/manage/(/?.*)' % self.options['web_root'], webserve.Manage), (r'%s/ui(/?.*)' % self.options['web_root'], webserve.UI), (r'%s/browser(/?.*)' % self.options['web_root'], webserve.WebFileBrowser), (r'%s(/?update_watched_state_kodi/?)' % self.options['web_root'], webserve.NoXSRFHandler), (r'%s(/?.*)' % self.options['web_root'], webserve.MainHandler), ])
def __init__(self, options=None): threading.Thread.__init__(self) self.daemon = True self.alive = True self.name = "WEBSERVER" self.options = options or {} self.options.setdefault('port', 8081) self.options.setdefault('host', '0.0.0.0') self.options.setdefault('log_dir', None) self.options.setdefault('username', '') self.options.setdefault('password', '') self.options.setdefault('web_root', '/') assert isinstance(self.options['port'], int) assert 'data_root' in self.options self.server = None # video root if sickbeard.ROOT_DIRS: root_dirs = sickbeard.ROOT_DIRS.split('|') self.video_root = root_dirs[int(root_dirs[0]) + 1] else: self.video_root = None # web root if self.options['web_root']: sickbeard.WEB_ROOT = self.options['web_root'] = ( '/' + self.options['web_root'].lstrip('/').strip('/')) # api root if not sickbeard.API_KEY: sickbeard.API_KEY = generateApiKey() self.options['api_root'] = r'{0}/api/{1}'.format( sickbeard.WEB_ROOT, sickbeard.API_KEY) # tornado setup self.enable_https = self.options['enable_https'] self.https_cert = self.options['https_cert'] self.https_key = self.options['https_key'] if self.enable_https: # If either the HTTPS certificate or key do not exist, make some self-signed ones. if not (self.https_cert and ek(os.path.exists, self.https_cert)) or not ( self.https_key and ek(os.path.exists, self.https_key)): if not create_https_certificates(self.https_cert, self.https_key): logger.log( "Unable to create CERT/KEY files, disabling HTTPS") sickbeard.ENABLE_HTTPS = False self.enable_https = False if not (ek(os.path.exists, self.https_cert) and ek(os.path.exists, self.https_key)): logger.log( "Disabled HTTPS because of missing CERT and KEY files", logger.WARNING) sickbeard.ENABLE_HTTPS = False self.enable_https = False # Load the app self.app = Application( [], debug= False, # enables autoreload, compiled_template_cache, static_hash_cache, serve_traceback - This fixes the 404 page and fixes autoreload for # devs. We could now update without restart possibly if we check DB version hasnt changed! autoreload=False, gzip=sickbeard.WEB_USE_GZIP, cookie_secret=sickbeard.WEB_COOKIE_SECRET, login_url='{0}/login/'.format(self.options['web_root']), static_path=self.options['data_root'], static_url_prefix='{0}/'.format(self.options['web_root']) # default_handler_class=Custom404Handler ) # Static File Handlers self.app.add_handlers( ".*$", [ url(r'{0}/favicon.ico'.format(self.options['web_root']), StaticFileHandler, { "path": ek(os.path.join, self.options['data_root'], 'images/ico/favicon.ico') }, name='favicon'), url(r'{0}/images/(.*)'.format(self.options['web_root']), StaticFileHandler, { "path": ek(os.path.join, self.options['data_root'], 'images') }, name='images'), url(r'{0}/cache/images/(.*)'.format(self.options['web_root']), StaticFileHandler, {"path": ek(os.path.join, sickbeard.CACHE_DIR, 'images')}, name='image_cache'), url(r'{0}/css/(.*)'.format(self.options['web_root']), StaticFileHandler, { "path": ek(os.path.join, self.options['data_root'], 'css') }, name='css'), url(r'{0}/js/(.*)'.format(self.options['web_root']), StaticFileHandler, { "path": ek(os.path.join, self.options['data_root'], 'js') }, name='js'), url(r'{0}/fonts/(.*)'.format(self.options['web_root']), StaticFileHandler, { "path": ek(os.path.join, self.options['data_root'], 'fonts') }, name='fonts') # TODO: WTF is this? # url(r'{0}/videos/(.*)'.format(self.options['web_root']), StaticFileHandler, # {"path": self.video_root}, name='videos') ]) # Main Handlers self.app.add_handlers( '.*$', [ url(r'{0}(/?.*)'.format(self.options['api_root']), ApiHandler, name='api'), url(r'{0}/getkey(/?.*)'.format(self.options['web_root']), KeyHandler, name='get_api_key'), url(r'{0}/api/builder'.format(self.options['web_root']), RedirectHandler, {"url": self.options['web_root'] + '/apibuilder/'}, name='apibuilder'), url(r'{0}/login(/?)'.format(self.options['web_root']), LoginHandler, name='login'), url(r'{0}/logout(/?)'.format(self.options['web_root']), LogoutHandler, name='logout'), url(r'{0}/calendar/?'.format(self.options['web_root']), CalendarHandler, name='calendar'), # routes added by @route decorator # Plus naked index with missing web_root prefix ] + Route.get_routes(self.options['web_root']))
def __init__(self, options=None, io_loop=None): threading.Thread.__init__(self) self.daemon = True self.alive = True self.name = "TORNADO" self.io_loop = io_loop or IOLoop.current() self.options = options or {} self.options.setdefault("port", 8081) self.options.setdefault("host", "0.0.0.0") self.options.setdefault("log_dir", None) self.options.setdefault("username", "") self.options.setdefault("password", "") self.options.setdefault("web_root", "/") assert isinstance(self.options["port"], int) assert "data_root" in self.options self.server = None # video root if sickbeard.ROOT_DIRS: root_dirs = sickbeard.ROOT_DIRS.split("|") self.video_root = root_dirs[int(root_dirs[0]) + 1] else: self.video_root = None # web root if self.options["web_root"]: sickbeard.WEB_ROOT = self.options["web_root"] = "/" + self.options["web_root"].lstrip("/").strip("/") # api root if not sickbeard.API_KEY: sickbeard.API_KEY = generateApiKey() self.options["api_root"] = r"{0}/api/{1}".format(sickbeard.WEB_ROOT, sickbeard.API_KEY) # tornado setup self.enable_https = self.options["enable_https"] self.https_cert = self.options["https_cert"] self.https_key = self.options["https_key"] if self.enable_https: # If either the HTTPS certificate or key do not exist, make some self-signed ones. if not (self.https_cert and ek(os.path.exists, self.https_cert)) or not ( self.https_key and ek(os.path.exists, self.https_key) ): if not create_https_certificates(self.https_cert, self.https_key): logger.log(u"Unable to create CERT/KEY files, disabling HTTPS") sickbeard.ENABLE_HTTPS = False self.enable_https = False if not (ek(os.path.exists, self.https_cert) and ek(os.path.exists, self.https_key)): logger.log(u"Disabled HTTPS because of missing CERT and KEY files", logger.WARNING) sickbeard.ENABLE_HTTPS = False self.enable_https = False # Load the app self.app = Application( [], debug=True, autoreload=False, gzip=sickbeard.WEB_USE_GZIP, xheaders=sickbeard.HANDLE_REVERSE_PROXY, cookie_secret=sickbeard.WEB_COOKIE_SECRET, login_url="{0}/login/".format(self.options["web_root"]), ) # Main Handlers self.app.add_handlers( ".*$", [ # webapi handler (r"{0}(/?.*)".format(self.options["api_root"]), ApiHandler), # webapi key retrieval (r"{0}/getkey(/?.*)".format(self.options["web_root"]), KeyHandler), # webapi builder redirect ( r"{0}/api/builder".format(self.options["web_root"]), RedirectHandler, {"url": self.options["web_root"] + "/apibuilder/"}, ), # webui login/logout handlers (r"{0}/login(/?)".format(self.options["web_root"]), LoginHandler), (r"{0}/logout(/?)".format(self.options["web_root"]), LogoutHandler), # Web calendar handler (Needed because option Unprotected calendar) (r"{0}/calendar".format(self.options["web_root"]), CalendarHandler), # webui handlers ] + route.get_routes(self.options["web_root"]), ) # Static File Handlers self.app.add_handlers( ".*$", [ # favicon ( r"{0}/(favicon\.ico)".format(self.options["web_root"]), StaticFileHandler, {"path": ek(os.path.join, self.options["data_root"], "images/ico/favicon.ico")}, ), # images ( r"{0}/images/(.*)".format(self.options["web_root"]), StaticFileHandler, {"path": ek(os.path.join, self.options["data_root"], "images")}, ), # cached images ( r"{0}/cache/images/(.*)".format(self.options["web_root"]), StaticFileHandler, {"path": ek(os.path.join, sickbeard.CACHE_DIR, "images")}, ), # css ( r"{0}/css/(.*)".format(self.options["web_root"]), StaticFileHandler, {"path": ek(os.path.join, self.options["data_root"], "css")}, ), # javascript ( r"{0}/js/(.*)".format(self.options["web_root"]), StaticFileHandler, {"path": ek(os.path.join, self.options["data_root"], "js")}, ), # fonts ( r"{0}/fonts/(.*)".format(self.options["web_root"]), StaticFileHandler, {"path": ek(os.path.join, self.options["data_root"], "fonts")}, ), # videos (r"{0}/videos/(.*)".format(self.options["web_root"]), StaticFileHandler, {"path": self.video_root}), ], )
def initWebServer(options={}): options.setdefault('port', 8081) options.setdefault('host', '0.0.0.0') options.setdefault('log_dir', None) options.setdefault('username', '') options.setdefault('password', '') options.setdefault('web_root', '/') assert isinstance(options['port'], int) assert 'data_root' in options def http_error_401_hander(status, message, traceback, version): """ Custom handler for 401 error """ if status != "401 Unauthorized": logger.log(u"CherryPy caught an error: %s %s" % (status, message), logger.ERROR) logger.log(traceback, logger.DEBUG) return r'''<!DOCTYPE html> <html> <head> <title>%s</title> </head> <body> <br/> <font color="#0000FF">Error %s: You need to provide a valid username and password.</font> </body> </html> ''' % ('Access denied', status) def http_error_404_hander(status, message, traceback, version): """ Custom handler for 404 error, redirect back to main page """ return r'''<!DOCTYPE html> <html> <head> <title>404</title> <script type="text/javascript" charset="utf-8"> <!-- location.href = "%s/home/" //--> </script> </head> <body> <br/> </body> </html> ''' % options['web_root'] # cherrypy setup enable_https = options['enable_https'] https_cert = options['https_cert'] https_key = options['https_key'] if enable_https: # If either the HTTPS certificate or key do not exist, make some self-signed ones. if not (https_cert and os.path.exists(https_cert)) or not (https_key and os.path.exists(https_key)): if not create_https_certificates(https_cert, https_key): logger.log(u"Unable to create CERT/KEY files, disabling HTTPS") sickbeard.ENABLE_HTTPS = False enable_https = False if not (os.path.exists(https_cert) and os.path.exists(https_key)): logger.log(u"Disabled HTTPS because of missing CERT and KEY files", logger.WARNING) sickbeard.ENABLE_HTTPS = False enable_https = False mime_gzip = ('text/html', 'text/plain', 'text/css', 'text/javascript', 'application/javascript', 'text/x-javascript', 'application/x-javascript', 'text/x-json', 'application/json' ) options_dict = { 'server.socket_port': options['port'], 'server.socket_host': options['host'], 'log.screen': False, 'engine.autoreload.on': False, 'engine.autoreload.frequency': 100, 'engine.reexec_retry': 100, 'tools.gzip.on': True, 'tools.gzip.mime_types': mime_gzip, 'error_page.401': http_error_401_hander, 'error_page.404': http_error_404_hander, } if enable_https: options_dict['server.ssl_certificate'] = https_cert options_dict['server.ssl_private_key'] = https_key protocol = "https" else: protocol = "http" logger.log(u"Starting SickRage on " + protocol + "://" + str(options['host']) + ":" + str(options['port']) + "/") cherrypy.config.update(options_dict) # setup cherrypy logging if options['log_dir'] and os.path.isdir(options['log_dir']): cherrypy.config.update({'log.access_file': os.path.join(options['log_dir'], "cherrypy.log")}) logger.log('Using %s for cherrypy log' % cherrypy.config['log.access_file']) conf = { '/': { 'tools.staticdir.root': options['data_root'], 'tools.encode.on': True, 'tools.encode.encoding': 'utf-8', 'tools.handle_reverse_proxy.on': True, }, '/images': { 'tools.staticdir.on': True, 'tools.staticdir.dir': 'images' }, '/js': { 'tools.staticdir.on': True, 'tools.staticdir.dir': 'js' }, '/css': { 'tools.staticdir.on': True, 'tools.staticdir.dir': 'css' }, } app = cherrypy.tree.mount(WebInterface(), options['web_root'], conf) # auth if options['username'] != "" and options['password'] != "": if sickbeard.CALENDAR_UNPROTECTED: checkpassword = cherrypy.lib.auth_basic.checkpassword_dict({options['username']: options['password']}) app.merge({ '/': { 'tools.auth_basic.on': True, 'tools.auth_basic.realm': 'SickRage', 'tools.auth_basic.checkpassword': checkpassword }, '/api': { 'tools.auth_basic.on': False }, '/calendar': { 'tools.auth_basic.on': False }, '/api/builder': { 'tools.auth_basic.on': True, 'tools.auth_basic.realm': 'SickRage', 'tools.auth_basic.checkpassword': checkpassword } }) else: checkpassword = cherrypy.lib.auth_basic.checkpassword_dict({options['username']: options['password']}) app.merge({ '/': { 'tools.auth_basic.on': True, 'tools.auth_basic.realm': 'SickRage', 'tools.auth_basic.checkpassword': checkpassword }, '/api': { 'tools.auth_basic.on': False }, '/api/builder': { 'tools.auth_basic.on': True, 'tools.auth_basic.realm': 'SickRage', 'tools.auth_basic.checkpassword': checkpassword } }) cherrypy.server.thread_pool = 30 cherrypy.server.start() cherrypy.server.wait()
def initWebServer(options={}): options.setdefault('port', 8081) options.setdefault('host', '0.0.0.0') options.setdefault('log_dir', None) options.setdefault('username', '') options.setdefault('password', '') options.setdefault('web_root', '/') assert isinstance(options['port'], int) assert 'data_root' in options # tornado setup enable_https = options['enable_https'] https_cert = options['https_cert'] https_key = options['https_key'] if enable_https: # If either the HTTPS certificate or key do not exist, make some self-signed ones. if not (https_cert and os.path.exists(https_cert)) or not (https_key and os.path.exists(https_key)): if not create_https_certificates(https_cert, https_key): logger.log(u"Unable to create CERT/KEY files, disabling HTTPS") sickbeard.ENABLE_HTTPS = False enable_https = False if not (os.path.exists(https_cert) and os.path.exists(https_key)): logger.log(u"Disabled HTTPS because of missing CERT and KEY files", logger.WARNING) sickbeard.ENABLE_HTTPS = False enable_https = False # Load the app app = Application([], debug=False, gzip=True, xheaders=sickbeard.HANDLE_REVERSE_PROXY, cookie_secret='61oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o/Vo=' ) # Main Handler app.add_handlers(".*$", [ (r"/", RedirectHandler, {'url': '%s/home/' % options['web_root']}), (r'%s/api/(.*)(/?)' % options['web_root'], webapi.Api), (r'%s/(.*)(/?)' % options['web_root'], webserve.IndexHandler) ]) # Static Path Handler app.add_handlers(".*$", [ (r'%s/(favicon\.ico)' % options['web_root'], MultiStaticFileHandler, {'paths': [os.path.join(options['data_root'], 'images/ico/favicon.ico')]}), (r'%s/%s/(.*)(/?)' % (options['web_root'], 'images'), MultiStaticFileHandler, {'paths': [os.path.join(options['data_root'], 'images'), os.path.join(sickbeard.CACHE_DIR, 'images')]}), (r'%s/%s/(.*)(/?)' % (options['web_root'], 'css'), MultiStaticFileHandler, {'paths': [os.path.join(options['data_root'], 'css')]}), (r'%s/%s/(.*)(/?)' % (options['web_root'], 'js'), MultiStaticFileHandler, {'paths': [os.path.join(options['data_root'], 'js')]}) ]) global server if enable_https: protocol = "https" server = HTTPServer(app, no_keep_alive=True, ssl_options={"certfile": https_cert, "keyfile": https_key}) else: protocol = "http" server = HTTPServer(app, no_keep_alive=True) logger.log(u"Starting SickRage on " + protocol + "://" + str(options['host']) + ":" + str( options['port']) + "/") try: server.listen(options['port'], options['host']) except: pass
def __init__(self, options={}, io_loop=None): threading.Thread.__init__(self) self.name = "TORNADO" self.alive = True self.io_loop = io_loop or IOLoop.current() self.options = options self.options.setdefault('port', 8081) self.options.setdefault('host', '0.0.0.0') self.options.setdefault('log_dir', None) self.options.setdefault('username', '') self.options.setdefault('password', '') self.options.setdefault('web_root', '/') assert isinstance(self.options[b'port'], int) assert 'gui_root' in self.options # video root if sickbeard.ROOT_DIRS: root_dirs = sickbeard.ROOT_DIRS.split('|') self.video_root = root_dirs[int(root_dirs[0]) + 1] else: self.video_root = None # web root if self.options[b'web_root']: sickbeard.WEB_ROOT = self.options[b'web_root'] = ('/' + self.options[b'web_root'].lstrip('/').strip('/')) # api root if not sickbeard.API_KEY: sickbeard.API_KEY = generateApiKey() self.options[b'api_root'] = r'%s/api/%s' % (sickbeard.WEB_ROOT, sickbeard.API_KEY) # tornado setup self.enable_https = self.options[b'enable_https'] self.https_cert = self.options[b'https_cert'] self.https_key = self.options[b'https_key'] if self.enable_https: # If either the HTTPS certificate or key do not exist, make some self-signed ones. if not (self.https_cert and ek(os.path.exists, self.https_cert)) or not ( self.https_key and ek(os.path.exists, self.https_key)): if not create_https_certificates(self.https_cert, self.https_key): logging.info("Unable to create CERT/KEY files, disabling HTTPS") sickbeard.ENABLE_HTTPS = False self.enable_https = False if not (os.path.exists(self.https_cert) and ek(os.path.exists, self.https_key)): logging.warning("Disabled HTTPS because of missing CERT and KEY files") sickbeard.ENABLE_HTTPS = False self.enable_https = False # Load the app self.app = Application([], debug=sickbeard.DEBUG, autoreload=False, gzip=sickbeard.WEB_USE_GZIP, xheaders=sickbeard.HANDLE_REVERSE_PROXY, cookie_secret=sickbeard.WEB_COOKIE_SECRET, login_url='%s/login/' % self.options[b'web_root'], ) # Main Handlers self.app.add_handlers('.*$', [ # webapi handler (r'%s(/?.*)' % self.options[b'api_root'], ApiHandler), # webapi key retrieval (r'%s/getkey(/?.*)' % self.options[b'web_root'], KeyHandler), # webapi builder redirect (r'%s/api/builder' % self.options[b'web_root'], RedirectHandler, {"url": self.options[b'web_root'] + '/apibuilder/'}), # webui login/logout handlers (r'%s/login(/?)' % self.options[b'web_root'], LoginHandler), (r'%s/logout(/?)' % self.options[b'web_root'], LogoutHandler), # webui handlers ] + route.get_routes(self.options[b'web_root'])) # Web calendar handler (Needed because option Unprotected calendar) self.app.add_handlers('.*$', [ (r'%s/calendar' % self.options[b'web_root'], CalendarHandler), ]) # Static File Handlers self.app.add_handlers(".*$", [ # favicon (r'%s/(favicon\.ico)' % self.options[b'web_root'], StaticFileHandler, {"path": ek(os.path.join, self.options[b'gui_root'], 'images/ico/favicon.ico')}), # images (r'%s.*?/images/(.*)' % self.options[b'web_root'], StaticImageHandler, {"path": ek(os.path.join, self.options[b'gui_root'], 'images')}), # css (r'%s/css/(.*)' % self.options[b'web_root'], StaticFileHandler, {"path": ek(os.path.join, self.options[b'gui_root'], 'css')}), # javascript (r'%s/js/(.*)' % self.options[b'web_root'], StaticFileHandler, {"path": ek(os.path.join, self.options[b'gui_root'], 'js')}), # videos ] + [(r'%s/videos/(.*)' % self.options[b'web_root'], StaticFileHandler, {"path": self.video_root})])
def initWebServer(options={}): options.setdefault('port', 8081) options.setdefault('host', '0.0.0.0') options.setdefault('log_dir', None) options.setdefault('username', '') options.setdefault('password', '') options.setdefault('web_root', '/') options.setdefault('ip_whitelist', '') assert isinstance(options['port'], int) assert 'data_root' in options def http_error_401_hander(status, message, traceback, version): """ Custom handler for 401 error """ if status != "401 Unauthorized": logger.log(u"CherryPy caught an error: %s %s" % (status, message), logger.ERROR) logger.log(traceback, logger.DEBUG) return r'''<!DOCTYPE html> <html> <head> <title>%s</title> </head> <body> <br/> <font color="#0000FF">Error %s: You need to provide a valid username and password.</font> </body> </html> ''' % ('Access denied', status) def http_error_404_hander(status, message, traceback, version): """ Custom handler for 404 error, redirect back to main page """ return r'''<!DOCTYPE html> <html> <head> <title>404</title> <script type="text/javascript" charset="utf-8"> <!-- location.href = "%s/home/" //--> </script> </head> <body> <br/> </body> </html> ''' % options['web_root'] # cherrypy setup enable_https = options['enable_https'] https_cert = options['https_cert'] https_key = options['https_key'] if enable_https: # If either the HTTPS certificate or key do not exist, make some self-signed ones. if not (https_cert and os.path.exists(https_cert)) or not (https_key and os.path.exists(https_key)): if not create_https_certificates(https_cert, https_key): logger.log(u"Unable to create CERT/KEY files, disabling HTTPS") sickbeard.ENABLE_HTTPS = False enable_https = False if not (os.path.exists(https_cert) and os.path.exists(https_key)): logger.log(u"Disabled HTTPS because of missing CERT and KEY files", logger.WARNING) sickbeard.ENABLE_HTTPS = False enable_https = False mime_gzip = ('text/html', 'text/plain', 'text/css', 'text/javascript', 'application/javascript', 'text/x-javascript', 'application/x-javascript', 'text/x-json', 'application/json' ) options_dict = { 'server.socket_port': options['port'], 'server.socket_host': options['host'], 'log.screen': False, 'engine.autoreload.on': False, 'engine.autoreload.frequency': 100, 'engine.reexec_retry': 100, 'tools.gzip.on': True, 'tools.gzip.mime_types': mime_gzip, 'error_page.401': http_error_401_hander, 'error_page.404': http_error_404_hander, } if enable_https: options_dict['server.ssl_certificate'] = https_cert options_dict['server.ssl_private_key'] = https_key protocol = "https" else: protocol = "http" logger.log(u"Starting Sick Beard on " + protocol + "://" + str(options['host']) + ":" + str(options['port']) + "/") cherrypy.config.update(options_dict) # setup cherrypy logging if options['log_dir'] and os.path.isdir(options['log_dir']): cherrypy.config.update({ 'log.access_file': os.path.join(options['log_dir'], "cherrypy.log") }) logger.log(u'Using %s for cherrypy log' % cherrypy.config['log.access_file']) conf = { '/': { 'tools.staticdir.root': options['data_root'], 'tools.encode.on': True, 'tools.encode.encoding': 'utf-8', }, '/images': { 'tools.staticdir.on': True, 'tools.staticdir.dir': 'images' }, '/js': { 'tools.staticdir.on': True, 'tools.staticdir.dir': 'js' }, '/css': { 'tools.staticdir.on': True, 'tools.staticdir.dir': 'css' }, } app = cherrypy.tree.mount(WebInterface(), options['web_root'], conf) def addressInNetwork(ip,net): """Is an address in a network. Returns: True - If 'ip' is an address in 'net' which is a string in the format x.x.x.x/y False - If 'ip' not in 'net' or if there is an error.""" if net == "": return False try: ipaddr = struct.unpack('>L',socket.inet_aton(ip))[0] netaddr,bits = net.split('/') ipnet = struct.unpack('>L',socket.inet_aton(netaddr))[0] mask = ((2L<<(int(bits))-1) - 1)<<(32-int(bits)) return ipaddr & mask == ipnet & mask except ValueError: # Will get here if ip_whitelist is incorrectly formatted logger.log(u'Configuration Error: \'ip_whitelist\' option is malformed. Value: %s, assuming no whitelisted hosts until restart.' % net, logger.ERROR ) options['ip_whitelist'] = "" return False def check_ip(): """Will check current request address against 'ip_whitelist' and will disable authentication with those that match. 'ip_whitelist' is a list in the form of 'a.a.a.a/b[,c.c.c.c/d]'""" try: # Iterate through whitelisted networks for whitelist_network in options['ip_whitelist'].split(','): # Check if current network matches remote address if addressInNetwork(cherrypy.request.remote.ip, whitelist_network.strip()): # Search for and remove basic_auth hook from list of hooks to execute old_hooks = cherrypy.request.hooks['before_handler'] new_hooks = [] for hook in old_hooks: if hook.callback != cherrypy.lib.auth_basic.basic_auth: new_hooks.append(hook) cherrypy.request.hooks['before_handler'] = new_hooks # No need to continue checking if already matched once return True except Exception: logger.log(u'webserverInit.py:check_ip() - Error while processing whitelist. ip_whitelist = %s' % options['ip_whitelist'], logger.ERROR) return True if options['ip_whitelist'] != "": checkipaddress = cherrypy.Tool('on_start_resource', check_ip, 1) cherrypy.tools.checkipaddress = checkipaddress app.merge({'/': { 'tools.checkipaddress.on': True } }) # auth if options['username'] != "" and options['password'] != "": checkpassword = cherrypy.lib.auth_basic.checkpassword_dict({options['username']: options['password']}) app.merge({ '/': { 'tools.auth_basic.on': True, 'tools.auth_basic.realm': 'SickBeard', 'tools.auth_basic.checkpassword': checkpassword }, '/api': { 'tools.auth_basic.on': False }, '/api/builder': { 'tools.auth_basic.on': True, 'tools.auth_basic.realm': 'SickBeard', 'tools.auth_basic.checkpassword': checkpassword } }) cherrypy.server.start() cherrypy.server.wait()
def initWebServer(options = {}): options.setdefault('port', 8081) options.setdefault('host', '0.0.0.0') options.setdefault('log_dir', None) options.setdefault('username', '') options.setdefault('password', '') options.setdefault('web_root', '/') assert isinstance(options['port'], int) assert 'data_root' in options def http_error_401_hander(status, message, traceback, version): """ Custom handler for 401 error """ if status != "401 Unauthorized": logger.log(u"CherryPy caught an error: %s %s" % (status, message), logger.ERROR) logger.log(traceback, logger.DEBUG) return r''' <html> <head> <title>%s</title> </head> <body> <br/> <font color="#0000FF">Error %s: You need to provide a valid username and password.</font> </body> </html> ''' % ('Access denied', status) def http_error_404_hander(status, message, traceback, version): """ Custom handler for 404 error, redirect back to main page """ return r''' <html> <head> <title>404</title> <script type="text/javascript" charset="utf-8"> <!-- location.href = "%s" //--> </script> </head> <body> <br/> </body> </html> ''' % '/' # cherrypy setup enable_https = options['enable_https'] https_port = options['https_port'] https_cert = options['https_cert'] https_key = options['https_key'] if enable_https: # If either the HTTPS certificate or key do not exist, make some self-signed ones. if not (https_cert and os.path.exists(https_cert)) or not (https_key and os.path.exists(https_key)): create_https_certificates(https_cert, https_key) if not (os.path.exists(https_cert) and os.path.exists(https_key)): logger.log(u"Disabled HTTPS because of missing CERT and KEY files", logger.WARNING) enable_https = False if enable_https: if https_port: logger.log(u"Starting Sick Beard on http://" + str(options['host']) + ":" + str(options['port']) + "/") # Prepare an extra server for the HTTP port http_server = _cpwsgi_server.CPWSGIServer() http_server.bind_addr = (options['host'], options['port']) #secure_server.ssl_certificate = https_cert #secure_server.ssl_private_key = https_key adapter = _cpserver.ServerAdapter(cherrypy.engine, http_server, http_server.bind_addr) adapter.subscribe() logger.log(u"Starting Sick Beard on https://" + str(options['host']) + ":" + str(https_port) + "/") cherrypy.config.update({ 'server.socket_port': int(https_port), 'server.socket_host': options['host'], 'log.screen': False, 'error_page.401': http_error_401_hander, 'error_page.404': http_error_404_hander, 'server.ssl_certificate' : https_cert, 'server.ssl_private_key' : https_key, }) else: logger.log(u"Starting Sick Beard on https://" + str(options['host']) + ":" + str(options['port']) + "/") cherrypy.config.update({ 'server.socket_port': options['port'], 'server.socket_host': options['host'], 'log.screen': False, 'error_page.401': http_error_401_hander, 'error_page.404': http_error_404_hander, 'server.ssl_certificate' : https_cert, 'server.ssl_private_key' : https_key, }) else: logger.log(u"Starting Sick Beard on http://" + str(options['host']) + ":" + str(options['port']) + "/") cherrypy.config.update({ 'server.socket_port': options['port'], 'server.socket_host': options['host'], 'log.screen': False, 'error_page.401': http_error_401_hander, 'error_page.404': http_error_404_hander, }) # setup cherrypy logging if options['log_dir'] and os.path.isdir(options['log_dir']): cherrypy.config.update({ 'log.access_file': os.path.join(options['log_dir'], "cherrypy.log") }) logger.log('Using %s for cherrypy log' % cherrypy.config['log.access_file']) conf = { '/': { 'tools.staticdir.root': options['data_root'], 'tools.encode.on': True, 'tools.encode.encoding': 'utf-8', }, '/images': { 'tools.staticdir.on': True, 'tools.staticdir.dir': 'images' }, '/js': { 'tools.staticdir.on': True, 'tools.staticdir.dir': 'js' }, '/css': { 'tools.staticdir.on': True, 'tools.staticdir.dir': 'css' }, } app = cherrypy.tree.mount(WebInterface(), options['web_root'], conf) # auth if options['username'] != "" and options['password'] != "": checkpassword = cherrypy.lib.auth_basic.checkpassword_dict({options['username']: options['password']}) app.merge({ '/': { 'tools.auth_basic.on': True, 'tools.auth_basic.realm': 'SickBeard', 'tools.auth_basic.checkpassword': checkpassword }, '/api':{ 'tools.auth_basic.on': False }, '/api/builder':{ 'tools.auth_basic.on': True, 'tools.auth_basic.realm': 'SickBeard', 'tools.auth_basic.checkpassword': checkpassword } }) cherrypy.engine.start() cherrypy.server.wait()
def __init__(self, options={}, io_loop=None): threading.Thread.__init__(self) self.name = "TORNADO" self.alive = True self.io_loop = io_loop or IOLoop.current() self.options = options self.options.setdefault('port', 8081) self.options.setdefault('host', '0.0.0.0') self.options.setdefault('log_dir', None) self.options.setdefault('username', '') self.options.setdefault('password', '') self.options.setdefault('web_root', '/') assert isinstance(self.options[b'port'], int) assert 'gui_root' in self.options # video root if sickbeard.ROOT_DIRS: root_dirs = sickbeard.ROOT_DIRS.split('|') self.video_root = root_dirs[int(root_dirs[0]) + 1] else: self.video_root = None # web root if self.options[b'web_root']: sickbeard.WEB_ROOT = self.options[b'web_root'] = ( '/' + self.options[b'web_root'].lstrip('/').strip('/')) # api root if not sickbeard.API_KEY: sickbeard.API_KEY = generateApiKey() self.options[b'api_root'] = r'%s/api/%s' % (sickbeard.WEB_ROOT, sickbeard.API_KEY) # tornado setup self.enable_https = self.options[b'enable_https'] self.https_cert = self.options[b'https_cert'] self.https_key = self.options[b'https_key'] if self.enable_https: # If either the HTTPS certificate or key do not exist, make some self-signed ones. if not (self.https_cert and ek(os.path.exists, self.https_cert)) or not ( self.https_key and ek(os.path.exists, self.https_key)): if not create_https_certificates(self.https_cert, self.https_key): logging.info( "Unable to create CERT/KEY files, disabling HTTPS") sickbeard.ENABLE_HTTPS = False self.enable_https = False if not (os.path.exists(self.https_cert) and ek(os.path.exists, self.https_key)): logging.warning( "Disabled HTTPS because of missing CERT and KEY files") sickbeard.ENABLE_HTTPS = False self.enable_https = False # Load the app self.app = Application( [], debug=sickbeard.DEBUG, autoreload=False, gzip=sickbeard.WEB_USE_GZIP, xheaders=sickbeard.HANDLE_REVERSE_PROXY, cookie_secret=sickbeard.WEB_COOKIE_SECRET, login_url='%s/login/' % self.options[b'web_root'], ) # Main Handlers self.app.add_handlers( '.*$', [ # webapi handler (r'%s(/?.*)' % self.options[b'api_root'], ApiHandler), # webapi key retrieval (r'%s/getkey(/?.*)' % self.options[b'web_root'], KeyHandler), # webapi builder redirect (r'%s/api/builder' % self.options[b'web_root'], RedirectHandler, { "url": self.options[b'web_root'] + '/apibuilder/' }), # webui login/logout handlers (r'%s/login(/?)' % self.options[b'web_root'], LoginHandler), (r'%s/logout(/?)' % self.options[b'web_root'], LogoutHandler), # webui handlers ] + route.get_routes(self.options[b'web_root'])) # Web calendar handler (Needed because option Unprotected calendar) self.app.add_handlers('.*$', [ (r'%s/calendar' % self.options[b'web_root'], CalendarHandler), ]) # Static File Handlers self.app.add_handlers( ".*$", [ # favicon (r'%s/(favicon\.ico)' % self.options[b'web_root'], StaticFileHandler, { "path": ek(os.path.join, self.options[b'gui_root'], 'images/ico/favicon.ico') }), # images (r'%s.*?/images/(.*)' % self.options[b'web_root'], StaticImageHandler, { "path": ek(os.path.join, self.options[b'gui_root'], 'images') }), # css (r'%s/css/(.*)' % self.options[b'web_root'], StaticFileHandler, { "path": ek(os.path.join, self.options[b'gui_root'], 'css') }), # javascript (r'%s/js/(.*)' % self.options[b'web_root'], StaticFileHandler, { "path": ek(os.path.join, self.options[b'gui_root'], 'js') }), # videos ] + [(r'%s/videos/(.*)' % self.options[b'web_root'], StaticFileHandler, { "path": self.video_root })])
def initWebServer(options={}): options.setdefault("port", 8081) options.setdefault("host", "0.0.0.0") options.setdefault("log_dir", None) options.setdefault("username", "") options.setdefault("password", "") options.setdefault("web_root", "/") assert isinstance(options["port"], int) assert "data_root" in options def http_error_401_hander(status, message, traceback, version): """ Custom handler for 401 error """ if status != "401 Unauthorized": logger.log(u"CherryPy caught an error: %s %s" % (status, message), logger.ERROR) logger.log(traceback, logger.DEBUG) return r""" <html> <head> <title>%s</title> </head> <body> <br/> <font color="#0000FF">Error %s: You need to provide a valid username and password.</font> </body> </html> """ % ( "Access denied", status, ) def http_error_404_hander(status, message, traceback, version): """ Custom handler for 404 error, redirect back to main page """ return ( r""" <html> <head> <title>404</title> <script type="text/javascript" charset="utf-8"> <!-- location.href = "%s" //--> </script> </head> <body> <br/> </body> </html> """ % options["web_root"] ) # cherrypy setup enable_https = options["enable_https"] https_cert = options["https_cert"] https_key = options["https_key"] if enable_https: # If either the HTTPS certificate or key do not exist, make some self-signed ones. if not (https_cert and os.path.exists(https_cert)) or not (https_key and os.path.exists(https_key)): if not create_https_certificates(https_cert, https_key): logger.log(u"Unable to create cert/key files, disabling HTTPS") sickbeard.ENABLE_HTTPS = False enable_https = False if not (os.path.exists(https_cert) and os.path.exists(https_key)): logger.log(u"Disabled HTTPS because of missing CERT and KEY files", logger.WARNING) sickbeard.ENABLE_HTTPS = False enable_https = False mime_gzip = ( "text/html", "text/plain", "text/css", "text/javascript", "application/javascript", "text/x-javascript", "application/x-javascript", "text/x-json", "application/json", ) options_dict = { "server.socket_port": options["port"], "server.socket_host": options["host"], "log.screen": False, "engine.autoreload.on": False, "engine.autoreload.frequency": 100, "engine.reexec_retry": 100, "tools.gzip.on": True, "tools.gzip.mime_types": mime_gzip, "error_page.401": http_error_401_hander, "error_page.404": http_error_404_hander, } if enable_https: options_dict["server.ssl_certificate"] = https_cert options_dict["server.ssl_private_key"] = https_key protocol = "https" else: protocol = "http" logger.log(u"Starting Sick Beard on " + protocol + "://" + str(options["host"]) + ":" + str(options["port"]) + "/") cherrypy.config.update(options_dict) # setup cherrypy logging if options["log_dir"] and os.path.isdir(options["log_dir"]): cherrypy.config.update({"log.access_file": os.path.join(options["log_dir"], "cherrypy.log")}) logger.log(u"Using %s for cherrypy log" % cherrypy.config["log.access_file"]) conf = { "/": {"tools.staticdir.root": options["data_root"], "tools.encode.on": True, "tools.encode.encoding": "utf-8"}, "/images": {"tools.staticdir.on": True, "tools.staticdir.dir": "images"}, "/js": {"tools.staticdir.on": True, "tools.staticdir.dir": "js"}, "/css": {"tools.staticdir.on": True, "tools.staticdir.dir": "css"}, } app = cherrypy.tree.mount(WebInterface(), options["web_root"], conf) # auth if options["username"] != "" and options["password"] != "": checkpassword = cherrypy.lib.auth_basic.checkpassword_dict({options["username"]: options["password"]}) app.merge( { "/": { "tools.auth_basic.on": True, "tools.auth_basic.realm": "SickBeard", "tools.auth_basic.checkpassword": checkpassword, }, "/api": {"tools.auth_basic.on": False}, "/api/builder": { "tools.auth_basic.on": True, "tools.auth_basic.realm": "SickBeard", "tools.auth_basic.checkpassword": checkpassword, }, } ) cherrypy.server.start() cherrypy.server.wait()
def __init__(self, options={}, io_loop=None): threading.Thread.__init__(self) self.daemon = True self.alive = True self.name = "TORNADO" self.io_loop = io_loop or IOLoop.current() self.options = options self.options.setdefault('port', 8081) self.options.setdefault('host', '0.0.0.0') self.options.setdefault('log_dir', None) self.options.setdefault('username', '') self.options.setdefault('password', '') self.options.setdefault('web_root', '/') assert isinstance(self.options['port'], int) assert 'data_root' in self.options # video root if sickbeard.ROOT_DIRS: root_dirs = sickbeard.ROOT_DIRS.split('|') self.video_root = root_dirs[int(root_dirs[0]) + 1] else: self.video_root = None # web root if self.options['web_root']: sickbeard.WEB_ROOT = self.options['web_root'] = ('/' + self.options['web_root'].lstrip('/').strip('/')) # api root if not sickbeard.API_KEY: sickbeard.API_KEY = generateApiKey() self.options['api_root'] = r'%s/api/%s' % (sickbeard.WEB_ROOT, sickbeard.API_KEY) # tornado setup self.enable_https = self.options['enable_https'] self.https_cert = self.options['https_cert'] self.https_key = self.options['https_key'] if self.enable_https: # If either the HTTPS certificate or key do not exist, make some self-signed ones. if not (self.https_cert and os.path.exists(self.https_cert)) or not ( self.https_key and os.path.exists(self.https_key)): if not create_https_certificates(self.https_cert, self.https_key): logger.log(u"Unable to create CERT/KEY files, disabling HTTPS") sickbeard.ENABLE_HTTPS = False self.enable_https = False if not (os.path.exists(self.https_cert) and os.path.exists(self.https_key)): logger.log(u"Disabled HTTPS because of missing CERT and KEY files", logger.WARNING) sickbeard.ENABLE_HTTPS = False self.enable_https = False # Load the app self.app = Application([], debug=True, autoreload=False, gzip=True, xheaders=sickbeard.HANDLE_REVERSE_PROXY, cookie_secret='61oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o/Vo=', login_url='/login/', ) # Main Handlers self.app.add_handlers('.*$', [ # webapi handler (r'%s(/?.*)' % self.options['api_root'], ApiHandler), # webapi key retrieval (r'%s/getkey(/?.*)' % self.options['web_root'], KeyHandler), # webapi builder redirect (r'%s/api/builder' % self.options['web_root'], RedirectHandler, {"url": self.options['web_root'] + '/apibuilder/'}), # webui login/logout handlers (r'%s/login(/?.*)' % self.options['web_root'], LoginHandler), (r'%s/logout(/?.*)' % self.options['web_root'], LogoutHandler), # webui redirect (r'/', RedirectHandler, {"url": self.options['web_root'] + '/home/'}), # webui handlers ] + route.get_routes(self.options['web_root'])) # Static File Handlers self.app.add_handlers(".*$", [ # favicon (r'%s/(favicon\.ico)' % self.options['web_root'], StaticFileHandler, {"path": os.path.join(self.options['data_root'], 'images/ico/favicon.ico')}), # images (r'%s/images/(.*)' % self.options['web_root'], StaticFileHandler, {"path": os.path.join(self.options['data_root'], 'images')}), # cached images (r'%s/cache/images/(.*)' % self.options['web_root'], StaticFileHandler, {"path": os.path.join(sickbeard.CACHE_DIR, 'images')}), # css (r'%s/css/(.*)' % self.options['web_root'], StaticFileHandler, {"path": os.path.join(self.options['data_root'], 'css')}), # javascript (r'%s/js/(.*)' % self.options['web_root'], StaticFileHandler, {"path": os.path.join(self.options['data_root'], 'js')}), # videos ] + [(r'%s/videos/(.*)' % self.options['web_root'], StaticFileHandler, {"path": self.video_root})])
def __init__(self, options={}, io_loop=None): threading.Thread.__init__(self) self.daemon = True self.alive = True self.name = 'TORNADO' self.io_loop = io_loop or IOLoop.current() self.options = options self.options.setdefault('port', 8081) self.options.setdefault('host', '0.0.0.0') self.options.setdefault('log_dir', None) self.options.setdefault('username', '') self.options.setdefault('password', '') self.options.setdefault('web_root', None) assert isinstance(self.options['port'], int) assert 'data_root' in self.options # web root self.options['web_root'] = ('/' + self.options['web_root'].lstrip('/')) if self.options[ 'web_root'] else '' # tornado setup self.enable_https = self.options['enable_https'] self.https_cert = self.options['https_cert'] self.https_key = self.options['https_key'] if self.enable_https: # If either the HTTPS certificate or key do not exist, make some self-signed ones. if not (self.https_cert and os.path.exists(self.https_cert)) or not ( self.https_key and os.path.exists(self.https_key)): if not create_https_certificates(self.https_cert, self.https_key): logger.log(u'Unable to create CERT/KEY files, disabling HTTPS') sickbeard.ENABLE_HTTPS = False self.enable_https = False if not (os.path.exists(self.https_cert) and os.path.exists(self.https_key)): logger.log(u'Disabled HTTPS because of missing CERT and KEY files', logger.WARNING) sickbeard.ENABLE_HTTPS = False self.enable_https = False # Load the app self.app = Application([], debug=True, autoreload=False, gzip=True, xheaders=sickbeard.HANDLE_REVERSE_PROXY, cookie_secret=sickbeard.COOKIE_SECRET, login_url='%s/login/' % self.options['web_root'], ) # Main Handler self.app.add_handlers('.*$', [ (r'%s/api/builder(/?)(.*)' % self.options['web_root'], webserve.ApiBuilder), (r'%s/api(/?.*)' % self.options['web_root'], webapi.Api), (r'%s/cache(/?.*)' % self.options['web_root'], webserve.Cache), (r'%s/config/general(/?.*)' % self.options['web_root'], webserve.ConfigGeneral), (r'%s/config/search(/?.*)' % self.options['web_root'], webserve.ConfigSearch), (r'%s/config/providers(/?.*)' % self.options['web_root'], webserve.ConfigProviders), (r'%s/config/subtitles(/?.*)' % self.options['web_root'], webserve.ConfigSubtitles), (r'%s/config/postProcessing(/?.*)' % self.options['web_root'], webserve.ConfigPostProcessing), (r'%s/config/notifications(/?.*)' % self.options['web_root'], webserve.ConfigNotifications), (r'%s/config/anime(/?.*)' % self.options['web_root'], webserve.ConfigAnime), (r'%s/config(/?.*)' % self.options['web_root'], webserve.Config), (r'%s/errorlogs(/?.*)' % self.options['web_root'], webserve.ErrorLogs), (r'%s/history(/?.*)' % self.options['web_root'], webserve.History), (r'%s/home/is_alive(/?.*)' % self.options['web_root'], webserve.IsAliveHandler), (r'%s/home/addShows(/?.*)' % self.options['web_root'], webserve.NewHomeAddShows), (r'%s/home/postprocess(/?.*)' % self.options['web_root'], webserve.HomePostProcess), (r'%s/home(/?.*)' % self.options['web_root'], webserve.Home), (r'%s/manage/manageSearches(/?.*)' % self.options['web_root'], webserve.ManageSearches), (r'%s/manage/showQueueOverview(/?.*)' % self.options['web_root'], webserve.showQueueOverview), (r'%s/manage/(/?.*)' % self.options['web_root'], webserve.Manage), (r'%s/ui(/?.*)' % self.options['web_root'], webserve.UI), (r'%s/browser(/?.*)' % self.options['web_root'], webserve.WebFileBrowser), (r'%s(/?.*)' % self.options['web_root'], webserve.MainHandler), ]) # webui login/logout handlers self.app.add_handlers('.*$', [ (r'%s/login(/?)' % self.options['web_root'], webserve.LoginHandler), (r'%s/logout(/?)' % self.options['web_root'], webserve.LogoutHandler), ]) # Web calendar handler (Needed because option Unprotected calendar) self.app.add_handlers('.*$', [ (r'%s/calendar' % self.options['web_root'], webserve.CalendarHandler), ]) # Static File Handlers self.app.add_handlers('.*$', [ # favicon (r'%s/(favicon\.ico)' % self.options['web_root'], StaticFileHandler, {'path': os.path.join(self.options['data_root'], 'images/ico/favicon.ico')}), # images (r'%s/images/(.*)' % self.options['web_root'], StaticFileHandler, {'path': os.path.join(self.options['data_root'], 'images')}), # cached images (r'%s/cache/images/(.*)' % self.options['web_root'], StaticFileHandler, {'path': os.path.join(sickbeard.CACHE_DIR, 'images')}), # css (r'%s/css/(.*)' % self.options['web_root'], StaticFileHandler, {'path': os.path.join(self.options['data_root'], 'css')}), # javascript (r'%s/js/(.*)' % self.options['web_root'], StaticFileHandler, {'path': os.path.join(self.options['data_root'], 'js')}), ])
def __init__(self, options={}, io_loop=None): threading.Thread.__init__(self) self.daemon = True self.alive = True self.name = "TORNADO" self.io_loop = io_loop or IOLoop.current() self.options = options self.options.setdefault('port', 8081) self.options.setdefault('host', '0.0.0.0') self.options.setdefault('log_dir', None) self.options.setdefault('username', '') self.options.setdefault('password', '') self.options.setdefault('web_root', None) assert isinstance(self.options['port'], int) assert 'data_root' in self.options # video root if sickbeard.ROOT_DIRS: root_dirs = sickbeard.ROOT_DIRS.split('|') self.video_root = root_dirs[int(root_dirs[0]) + 1] else: self.video_root = None # web root self.options['web_root'] = ('/' + self.options['web_root'].lstrip('/') ) if self.options['web_root'] else '' # tornado setup self.enable_https = self.options['enable_https'] self.https_cert = self.options['https_cert'] self.https_key = self.options['https_key'] if self.enable_https: # If either the HTTPS certificate or key do not exist, make some self-signed ones. if not (self.https_cert and os.path.exists(self.https_cert)) or not ( self.https_key and os.path.exists(self.https_key)): if not create_https_certificates(self.https_cert, self.https_key): logger.log( u"Unable to create CERT/KEY files, disabling HTTPS") sickbeard.ENABLE_HTTPS = False self.enable_https = False if not (os.path.exists(self.https_cert) and os.path.exists(self.https_key)): logger.log( u"Disabled HTTPS because of missing CERT and KEY files", logger.WARNING) sickbeard.ENABLE_HTTPS = False self.enable_https = False # Load the app self.app = Application( [], debug=True, autoreload=False, gzip=True, xheaders=sickbeard.HANDLE_REVERSE_PROXY, cookie_secret='61oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o/Vo=') # Main Handler self.app.add_handlers( ".*$", [(r'%s/api/(.*)(/?)' % self.options['web_root'], webapi.Api), (r'%s/(.*)(/?)' % self.options['web_root'], webserve.MainHandler), (r'(.*)', webserve.MainHandler)]) # Static Path Handler self.app.add_handlers(".*$", [ (r'%s/(favicon\.ico)' % self.options['web_root'], MultiStaticFileHandler, { 'paths': [ os.path.join(self.options['data_root'], 'images/ico/favicon.ico') ] }), (r'%s/%s/(.*)(/?)' % (self.options['web_root'], 'images'), MultiStaticFileHandler, { 'paths': [ os.path.join(self.options['data_root'], 'images'), os.path.join(sickbeard.CACHE_DIR, 'images') ] }), (r'%s/%s/(.*)(/?)' % (self.options['web_root'], 'css'), MultiStaticFileHandler, { 'paths': [os.path.join(self.options['data_root'], 'css')] }), (r'%s/%s/(.*)(/?)' % (self.options['web_root'], 'js'), MultiStaticFileHandler, { 'paths': [os.path.join(self.options['data_root'], 'js')] }), ]) # Static Videos Path if self.video_root: self.app.add_handlers(".*$", [ (r'%s/%s/(.*)' % (self.options['web_root'], 'videos'), MultiStaticFileHandler, { 'paths': [self.video_root] }), ])
def initWebServer(options={}): options.setdefault("port", 8081) options.setdefault("host", "0.0.0.0") options.setdefault("log_dir", None) options.setdefault("username", "") options.setdefault("password", "") options.setdefault("whitelist", "") options.setdefault("web_root", "/") assert isinstance(options["port"], int) assert "data_root" in options def http_error_401_hander(status, message, traceback, version): """ Custom handler for 401 error """ if status != "401 Unauthorized": logger.log(u"CherryPy caught an error: %s %s" % (status, message), logger.ERROR) logger.log(traceback, logger.DEBUG) return r"""<!DOCTYPE html> <html> <head> <title>%s</title> </head> <body> <br/> <font color="#0000FF">Error %s: You need to provide a valid username and password.</font> </body> </html> """ % ( "Access denied", status, ) def http_error_404_hander(status, message, traceback, version): """ Custom handler for 404 error, redirect back to main page """ return ( r"""<!DOCTYPE html> <html> <head> <title>404</title> <script type="text/javascript" charset="utf-8"> <!-- location.href = "%s/home/" //--> </script> </head> <body> <br/> </body> </html> """ % options["web_root"] ) # cherrypy setup enable_https = options["enable_https"] https_cert = options["https_cert"] https_key = options["https_key"] if enable_https: # If either the HTTPS certificate or key do not exist, make some self-signed ones. if not (https_cert and os.path.exists(https_cert)) or not (https_key and os.path.exists(https_key)): if not create_https_certificates(https_cert, https_key): logger.log(u"Unable to create CERT/KEY files, disabling HTTPS") sickbeard.ENABLE_HTTPS = False enable_https = False if not (os.path.exists(https_cert) and os.path.exists(https_key)): logger.log(u"Disabled HTTPS because of missing CERT and KEY files", logger.WARNING) sickbeard.ENABLE_HTTPS = False enable_https = False mime_gzip = ( "text/html", "text/plain", "text/css", "text/javascript", "application/javascript", "text/x-javascript", "application/x-javascript", "text/x-json", "application/json", ) options_dict = { "server.socket_port": options["port"], "server.socket_host": options["host"], "log.screen": False, "engine.autoreload.on": False, "engine.autoreload.frequency": 100, "engine.reexec_retry": 100, "tools.gzip.on": True, "tools.gzip.mime_types": mime_gzip, "error_page.401": http_error_401_hander, "error_page.404": http_error_404_hander, } if enable_https: options_dict["server.ssl_certificate"] = https_cert options_dict["server.ssl_private_key"] = https_key protocol = "https" else: protocol = "http" logger.log(u"Starting Sick Beard on " + protocol + "://" + str(options["host"]) + ":" + str(options["port"]) + "/") cherrypy.config.update(options_dict) # setup cherrypy logging if options["log_dir"] and os.path.isdir(options["log_dir"]): cherrypy.config.update({"log.access_file": os.path.join(options["log_dir"], "cherrypy.log")}) logger.log(u"Using %s for cherrypy log" % cherrypy.config["log.access_file"]) conf = { "/": {"tools.staticdir.root": options["data_root"], "tools.encode.on": True, "tools.encode.encoding": "utf-8"}, "/images": {"tools.staticdir.on": True, "tools.staticdir.dir": "images"}, "/js": {"tools.staticdir.on": True, "tools.staticdir.dir": "js"}, "/css": {"tools.staticdir.on": True, "tools.staticdir.dir": "css"}, } app = cherrypy.tree.mount(WebInterface(), options["web_root"], conf) def addressInNetwork(ip, net): """Is an address in a network. Returns: True - If 'ip' is an address in 'net' which is a string in the format x.x.x.x/y False - If 'ip' not in 'net' or if there is an error.""" if net == "": return False try: ipaddr = struct.unpack(">L", socket.inet_aton(ip))[0] netaddr, bits = net.split("/") ipnet = struct.unpack(">L", socket.inet_aton(netaddr))[0] mask = ((2L << (int(bits)) - 1) - 1) << (32 - int(bits)) return ipaddr & mask == ipnet & mask except ValueError: # Will get here if whitelist is incorrectly formatted logger.log( u"Configuration Error: 'whitelist' option is malformed. Value: %s, assuming no whitelisted hosts until restart." % net, logger.ERROR, ) options["whitelist"] = "" return False def check_ip(): """Will check current request address against 'whitelist' and will disable authentication with those that match. 'whitelist' is a list in the form of 'a.a.a.a/b[,c.c.c.c/d]'""" try: # Iterate through whitelisted networks for whitelist_network in options["whitelist"].split(","): # Check if current network matches remote address if addressInNetwork(cherrypy.request.remote.ip, whitelist_network.strip()): # Search for and remove basic_auth hook from list of hooks to execute old_hooks = cherrypy.request.hooks["before_handler"] new_hooks = [] for hook in old_hooks: if hook.callback != cherrypy.lib.auth_basic.basic_auth: new_hooks.append(hook) cherrypy.request.hooks["before_handler"] = new_hooks # No need to continue checking if already matched once return True except Exception: logger.log( u"webserverInit.py:check_ip() - Error while processing whitelist. whitelist = %s" % options["whitelist"], logger.ERROR, ) return True if options["whitelist"] != "": checkipaddress = cherrypy.Tool("on_start_resource", check_ip, 1) cherrypy.tools.checkipaddress = checkipaddress app.merge({"/": {"tools.checkipaddress.on": True}}) # auth if options["username"] != "" and options["password"] != "": checkpassword = cherrypy.lib.auth_basic.checkpassword_dict({options["username"]: options["password"]}) app.merge( { "/": { "tools.auth_basic.on": True, "tools.auth_basic.realm": "SickBeard", "tools.auth_basic.checkpassword": checkpassword, }, "/api": {"tools.auth_basic.on": False}, "/api/builder": { "tools.auth_basic.on": True, "tools.auth_basic.realm": "SickBeard", "tools.auth_basic.checkpassword": checkpassword, }, } ) cherrypy.server.start() cherrypy.server.wait()
def initWebServer(options={}): options.setdefault('port', 8081) options.setdefault('host', '0.0.0.0') options.setdefault('log_dir', None) options.setdefault('username', '') options.setdefault('password', '') options.setdefault('web_root', '/') assert isinstance(options['port'], int) assert 'data_root' in options def http_error_401_hander(status, message, traceback, version): """ Custom handler for 401 error """ if status != "401 Unauthorized": logger.log(u"CherryPy caught an error: %s %s" % (status, message), logger.ERROR) logger.log(traceback, logger.DEBUG) return r'''<!DOCTYPE html> <html> <head> <title>%s</title> </head> <body> <br/> <font color="#0000FF">Error %s: You need to provide a valid username and password.</font> </body> </html> ''' % ('Access denied', status) def http_error_404_hander(status, message, traceback, version): """ Custom handler for 404 error, redirect back to main page """ return r'''<!DOCTYPE html> <html> <head> <title>404</title> <script type="text/javascript" charset="utf-8"> <!-- location.href = "%s/home/" //--> </script> </head> <body> <br/> </body> </html> ''' % options['web_root'] # cherrypy setup enable_https = options['enable_https'] https_cert = options['https_cert'] https_key = options['https_key'] if enable_https: # If either the HTTPS certificate or key do not exist, make some self-signed ones. if not (https_cert and os.path.exists(https_cert)) or not ( https_key and os.path.exists(https_key)): if not create_https_certificates(https_cert, https_key): logger.log(u"Unable to create CERT/KEY files, disabling HTTPS") sickbeard.ENABLE_HTTPS = False enable_https = False if not (os.path.exists(https_cert) and os.path.exists(https_key)): logger.log(u"Disabled HTTPS because of missing CERT and KEY files", logger.WARNING) sickbeard.ENABLE_HTTPS = False enable_https = False mime_gzip = ('text/html', 'text/plain', 'text/css', 'text/javascript', 'application/javascript', 'text/x-javascript', 'application/x-javascript', 'text/x-json', 'application/json') options_dict = { 'server.socket_port': options['port'], 'server.socket_host': options['host'], 'log.screen': False, 'engine.autoreload.on': False, 'engine.autoreload.frequency': 100, 'engine.reexec_retry': 100, 'tools.gzip.on': True, 'tools.gzip.mime_types': mime_gzip, 'error_page.401': http_error_401_hander, 'error_page.404': http_error_404_hander, } if enable_https: options_dict['server.ssl_certificate'] = https_cert options_dict['server.ssl_private_key'] = https_key protocol = "https" else: protocol = "http" logger.log(u"Starting Sick Beard on " + protocol + "://" + str(options['host']) + ":" + str(options['port']) + "/") cherrypy.config.update(options_dict) # setup cherrypy logging if options['log_dir'] and os.path.isdir(options['log_dir']): cherrypy.config.update({ 'log.access_file': os.path.join(options['log_dir'], "cherrypy.log") }) logger.log('Using %s for cherrypy log' % cherrypy.config['log.access_file']) conf = { '/': { 'tools.staticdir.root': options['data_root'], 'tools.encode.on': True, 'tools.encode.encoding': 'utf-8', }, '/images': { 'tools.staticdir.on': True, 'tools.staticdir.dir': 'images' }, '/js': { 'tools.staticdir.on': True, 'tools.staticdir.dir': 'js' }, '/css': { 'tools.staticdir.on': True, 'tools.staticdir.dir': 'css' }, } app = cherrypy.tree.mount(WebInterface(), options['web_root'], conf) # auth if options['username'] != "" and options['password'] != "": if sickbeard.CALENDAR_PROTECTED: checkpassword = cherrypy.lib.auth_basic.checkpassword_dict( {options['username']: options['password']}) app.merge({ '/': { 'tools.auth_basic.on': True, 'tools.auth_basic.realm': 'SickBeard', 'tools.auth_basic.checkpassword': checkpassword }, '/api': { 'tools.auth_basic.on': False }, '/api/builder': { 'tools.auth_basic.on': True, 'tools.auth_basic.realm': 'SickBeard', 'tools.auth_basic.checkpassword': checkpassword } }) else: checkpassword = cherrypy.lib.auth_basic.checkpassword_dict( {options['username']: options['password']}) app.merge({ '/': { 'tools.auth_basic.on': True, 'tools.auth_basic.realm': 'SickBeard', 'tools.auth_basic.checkpassword': checkpassword }, '/api': { 'tools.auth_basic.on': False }, '/calendar': { 'tools.auth_basic.on': False }, '/api/builder': { 'tools.auth_basic.on': True, 'tools.auth_basic.realm': 'SickBeard', 'tools.auth_basic.checkpassword': checkpassword } }) cherrypy.server.start() cherrypy.server.wait()
def __init__(self, options={}, io_loop=None): threading.Thread.__init__(self) self.daemon = True self.alive = True self.name = "TORNADO" self.io_loop = io_loop or IOLoop.current() self.options = options self.options.setdefault('port', 8081) self.options.setdefault('host', '0.0.0.0') self.options.setdefault('log_dir', None) self.options.setdefault('username', '') self.options.setdefault('password', '') self.options.setdefault('web_root', None) assert isinstance(self.options['port'], int) assert 'data_root' in self.options # video root if sickbeard.ROOT_DIRS: root_dirs = sickbeard.ROOT_DIRS.split('|') self.video_root = root_dirs[int(root_dirs[0]) + 1] else: self.video_root = None # web root self.options['web_root'] = ('/' + self.options['web_root'].lstrip('/')) if self.options[ 'web_root'] else '' # tornado setup self.enable_https = self.options['enable_https'] self.https_cert = self.options['https_cert'] self.https_key = self.options['https_key'] if self.enable_https: # If either the HTTPS certificate or key do not exist, make some self-signed ones. if not (self.https_cert and os.path.exists(self.https_cert)) or not ( self.https_key and os.path.exists(self.https_key)): if not create_https_certificates(self.https_cert, self.https_key): logger.log(u"Unable to create CERT/KEY files, disabling HTTPS") sickbeard.ENABLE_HTTPS = False self.enable_https = False if not (os.path.exists(self.https_cert) and os.path.exists(self.https_key)): logger.log(u"Disabled HTTPS because of missing CERT and KEY files", logger.WARNING) sickbeard.ENABLE_HTTPS = False self.enable_https = False # Load the app self.app = Application([], debug=True, autoreload=False, gzip=True, xheaders=sickbeard.HANDLE_REVERSE_PROXY, cookie_secret='61oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o/Vo=' ) # Main Handler self.app.add_handlers(".*$", [ (r'%s/api/(.*)(/?)' % self.options['web_root'], webapi.Api), (r'%s/(.*)(/?)' % self.options['web_root'], webserve.MainHandler), (r'(.*)', webserve.MainHandler) ]) # Static Path Handler self.app.add_handlers(".*$", [ (r'%s/(favicon\.ico)' % self.options['web_root'], MultiStaticFileHandler, {'paths': [os.path.join(self.options['data_root'], 'images/ico/favicon.ico')]}), (r'%s/%s/(.*)(/?)' % (self.options['web_root'], 'images'), MultiStaticFileHandler, {'paths': [os.path.join(self.options['data_root'], 'images'), os.path.join(sickbeard.CACHE_DIR, 'images')]}), (r'%s/%s/(.*)(/?)' % (self.options['web_root'], 'css'), MultiStaticFileHandler, {'paths': [os.path.join(self.options['data_root'], 'css')]}), (r'%s/%s/(.*)(/?)' % (self.options['web_root'], 'js'), MultiStaticFileHandler, {'paths': [os.path.join(self.options['data_root'], 'js')]}), ]) # Static Videos Path if self.video_root: self.app.add_handlers(".*$", [ (r'%s/%s/(.*)' % (self.options['web_root'], 'videos'), MultiStaticFileHandler, {'paths': [self.video_root]}), ])
def __init__(self, options=None, io_loop=None): threading.Thread.__init__(self) self.daemon = True self.alive = True self.name = "TORNADO" self.io_loop = io_loop or IOLoop.current() self.options = options or {} self.options.setdefault('port', 8081) self.options.setdefault('host', '0.0.0.0') self.options.setdefault('log_dir', None) self.options.setdefault('username', '') self.options.setdefault('password', '') self.options.setdefault('web_root', '/') assert isinstance(self.options['port'], int) assert 'data_root' in self.options self.server = None # video root if sickbeard.ROOT_DIRS: root_dirs = sickbeard.ROOT_DIRS.split('|') self.video_root = root_dirs[int(root_dirs[0]) + 1] else: self.video_root = None # web root if self.options['web_root']: sickbeard.WEB_ROOT = self.options['web_root'] = ('/' + self.options['web_root'].lstrip('/').strip('/')) # api root if not sickbeard.API_KEY: sickbeard.API_KEY = generateApiKey() self.options['api_root'] = r'{0}/api/{1}'.format(sickbeard.WEB_ROOT, sickbeard.API_KEY) # tornado setup self.enable_https = self.options['enable_https'] self.https_cert = self.options['https_cert'] self.https_key = self.options['https_key'] if self.enable_https: # If either the HTTPS certificate or key do not exist, make some self-signed ones. if not (self.https_cert and ek(os.path.exists, self.https_cert)) or not ( self.https_key and ek(os.path.exists, self.https_key)): if not create_https_certificates(self.https_cert, self.https_key): logger.log(u"Unable to create CERT/KEY files, disabling HTTPS") sickbeard.ENABLE_HTTPS = False self.enable_https = False if not (ek(os.path.exists, self.https_cert) and ek(os.path.exists, self.https_key)): logger.log(u"Disabled HTTPS because of missing CERT and KEY files", logger.WARNING) sickbeard.ENABLE_HTTPS = False self.enable_https = False # Load the app self.app = Application( [], debug=True, autoreload=False, gzip=sickbeard.WEB_USE_GZIP, cookie_secret=sickbeard.WEB_COOKIE_SECRET, login_url='{0}/login/'.format(self.options['web_root']), ) # Main Handlers self.app.add_handlers('.*$', [ # webapi handler (r'{0}(/?.*)'.format(self.options['api_root']), ApiHandler), # webapi key retrieval (r'{0}/getkey(/?.*)'.format(self.options['web_root']), KeyHandler), # webapi builder redirect (r'{0}/api/builder'.format(self.options['web_root']), RedirectHandler, {"url": self.options['web_root'] + '/apibuilder/'}), # webui login/logout handlers (r'{0}/login(/?)'.format(self.options['web_root']), LoginHandler), (r'{0}/logout(/?)'.format(self.options['web_root']), LogoutHandler), # Web calendar handler (Needed because option Unprotected calendar) (r'{0}/calendar'.format(self.options['web_root']), CalendarHandler), # webui handlers ] + route.get_routes(self.options['web_root'])) # Static File Handlers self.app.add_handlers(".*$", [ # favicon (r'{0}/(favicon\.ico)'.format(self.options['web_root']), StaticFileHandler, {"path": ek(os.path.join, self.options['data_root'], 'images/ico/favicon.ico')}), # images (r'{0}/images/(.*)'.format(self.options['web_root']), StaticFileHandler, {"path": ek(os.path.join, self.options['data_root'], 'images')}), # cached images (r'{0}/cache/images/(.*)'.format(self.options['web_root']), StaticFileHandler, {"path": ek(os.path.join, sickbeard.CACHE_DIR, 'images')}), # css (r'{0}/css/(.*)'.format(self.options['web_root']), StaticFileHandler, {"path": ek(os.path.join, self.options['data_root'], 'css')}), # javascript (r'{0}/js/(.*)'.format(self.options['web_root']), StaticFileHandler, {"path": ek(os.path.join, self.options['data_root'], 'js')}), # fonts (r'{0}/fonts/(.*)'.format(self.options['web_root']), StaticFileHandler, {"path": ek(os.path.join, self.options['data_root'], 'fonts')}), # videos (r'{0}/videos/(.*)'.format(self.options['web_root']), StaticFileHandler, {"path": self.video_root}) ])
def __init__(self, options=None, io_loop=None): threading.Thread.__init__(self) self.daemon = True self.alive = True self.name = "TORNADO" self.io_loop = io_loop or IOLoop.current() self.options = options or {} self.options.setdefault('port', 8081) self.options.setdefault('host', '0.0.0.0') self.options.setdefault('log_dir', None) self.options.setdefault('username', '') self.options.setdefault('password', '') self.options.setdefault('web_root', '/') assert isinstance(self.options['port'], int) assert 'data_root' in self.options self.server = None # video root if sickbeard.ROOT_DIRS: root_dirs = sickbeard.ROOT_DIRS.split('|') self.video_root = root_dirs[int(root_dirs[0]) + 1] else: self.video_root = None # web root if self.options['web_root']: sickbeard.WEB_ROOT = self.options['web_root'] = ( '/' + self.options['web_root'].lstrip('/').strip('/')) # api root if not sickbeard.API_KEY: sickbeard.API_KEY = generateApiKey() self.options['api_root'] = r'{0}/api/{1}'.format( sickbeard.WEB_ROOT, sickbeard.API_KEY) # tornado setup self.enable_https = self.options['enable_https'] self.https_cert = self.options['https_cert'] self.https_key = self.options['https_key'] if self.enable_https: # If either the HTTPS certificate or key do not exist, make some self-signed ones. if not (self.https_cert and ek(os.path.exists, self.https_cert)) or not ( self.https_key and ek(os.path.exists, self.https_key)): if not create_https_certificates(self.https_cert, self.https_key): logger.log( "Unable to create CERT/KEY files, disabling HTTPS") sickbeard.ENABLE_HTTPS = False self.enable_https = False if not (ek(os.path.exists, self.https_cert) and ek(os.path.exists, self.https_key)): logger.log( "Disabled HTTPS because of missing CERT and KEY files", logger.WARNING) sickbeard.ENABLE_HTTPS = False self.enable_https = False # Load the app self.app = Application( [], debug=True, autoreload=False, gzip=sickbeard.WEB_USE_GZIP, cookie_secret=sickbeard.WEB_COOKIE_SECRET, login_url='{0}/login/'.format(self.options['web_root']), ) # Main Handlers self.app.add_handlers( '.*$', [ # webapi handler (r'{0}(/?.*)'.format(self.options['api_root']), ApiHandler), # webapi key retrieval (r'{0}/getkey(/?.*)'.format( self.options['web_root']), KeyHandler), # webapi builder redirect (r'{0}/api/builder'.format( self.options['web_root']), RedirectHandler, { "url": self.options['web_root'] + '/apibuilder/' }), # webui login/logout handlers (r'{0}/login(/?)'.format( self.options['web_root']), LoginHandler), (r'{0}/logout(/?)'.format( self.options['web_root']), LogoutHandler), # Web calendar handler (Needed because option Unprotected calendar) (r'{0}/calendar'.format( self.options['web_root']), CalendarHandler), # webui handlers ] + route.get_routes(self.options['web_root'])) # Static File Handlers self.app.add_handlers( ".*$", [ # favicon (r'{0}/(favicon\.ico)'.format( self.options['web_root']), StaticFileHandler, { "path": ek(os.path.join, self.options['data_root'], 'images/ico/favicon.ico') }), # images (r'{0}/images/(.*)'.format( self.options['web_root']), StaticFileHandler, { "path": ek(os.path.join, self.options['data_root'], 'images') }), # locale (r'{0}/locale/messages\.json'.format( self.options['web_root']), LocaleFileHandler, { "path": ek(os.path.join, sickbeard.LOCALE_DIR, '{lang_code}/LC_MESSAGES') }), # cached images (r'{0}/cache/images/(.*)'.format( self.options['web_root']), StaticFileHandler, { "path": ek(os.path.join, sickbeard.CACHE_DIR, 'images') }), # css (r'{0}/css/(.*)'.format(self.options['web_root']), StaticFileHandler, { "path": ek(os.path.join, self.options['data_root'], 'css') }), # javascript (r'{0}/js/(.*)'.format(self.options['web_root']), StaticFileHandler, { "path": ek(os.path.join, self.options['data_root'], 'js') }), # fonts (r'{0}/fonts/(.*)'.format( self.options['web_root']), StaticFileHandler, { "path": ek(os.path.join, self.options['data_root'], 'fonts') }), # videos (r'{0}/videos/(.*)'.format( self.options['web_root']), StaticFileHandler, { "path": self.video_root }) ])
def __init__(self, options=None): threading.Thread.__init__(self) self.daemon = True self.alive = True self.name = 'TORNADO' self.io_loop = None self.server = None self.options = options or {} self.options.setdefault('port', 8081) self.options.setdefault('host', '0.0.0.0') self.options.setdefault('log_dir', None) self.options.setdefault('username', '') self.options.setdefault('password', '') self.options.setdefault('web_root', None) assert isinstance(self.options['port'], int) assert 'data_root' in self.options # web root self.options['web_root'] = ('/' + self.options['web_root'].lstrip('/')) if self.options['web_root'] else '' # tornado setup self.enable_https = self.options['enable_https'] self.https_cert = self.options['https_cert'] self.https_key = self.options['https_key'] if self.enable_https: make_cert = False update_cfg = False for (attr, ext) in [('https_cert', '.crt'), ('https_key', '.key')]: ssl_path = getattr(self, attr, None) if ssl_path and not os.path.isfile(ssl_path): if not ssl_path.endswith(ext): setattr(self, attr, os.path.join(ssl_path, 'server%s' % ext)) setattr(sickbeard, attr.upper(), 'server%s' % ext) make_cert = True # If either the HTTPS certificate or key do not exist, make some self-signed ones. if make_cert: if not create_https_certificates(self.https_cert, self.https_key): logger.log(u'Unable to create CERT/KEY files, disabling HTTPS') update_cfg |= False is not sickbeard.ENABLE_HTTPS sickbeard.ENABLE_HTTPS = False self.enable_https = False else: update_cfg = True if not (os.path.isfile(self.https_cert) and os.path.isfile(self.https_key)): logger.log(u'Disabled HTTPS because of missing CERT and KEY files', logger.WARNING) update_cfg |= False is not sickbeard.ENABLE_HTTPS sickbeard.ENABLE_HTTPS = False self.enable_https = False if update_cfg: sickbeard.save_config() # Load the app self.app = MyApplication([], debug=True, serve_traceback=True, autoreload=False, compress_response=True, cookie_secret=sickbeard.COOKIE_SECRET, xsrf_cookies=True, login_url='%s/login/' % self.options['web_root']) self.re_host_pattern = re_valid_hostname() self._add_loading_rules()
def __init__(self, options={}, io_loop=None): threading.Thread.__init__(self) self.daemon = True self.alive = True self.name = "TORNADO" self.io_loop = io_loop or IOLoop.current() self.options = options self.options.setdefault('port', 8081) self.options.setdefault('host', '0.0.0.0') self.options.setdefault('log_dir', None) self.options.setdefault('username', '') self.options.setdefault('password', '') self.options.setdefault('web_root', '/') assert isinstance(self.options['port'], int) assert 'data_root' in self.options # video root if sickbeard.ROOT_DIRS: root_dirs = sickbeard.ROOT_DIRS.split('|') self.video_root = root_dirs[int(root_dirs[0]) + 1] else: self.video_root = None # web root if self.options['web_root']: sickbeard.WEB_ROOT = self.options['web_root'] = ('/' + self.options['web_root'].lstrip('/').strip('/')) # api root if not sickbeard.API_KEY: sickbeard.API_KEY = generateApiKey() self.options['api_root'] = r'%s/api/%s' % (sickbeard.WEB_ROOT, sickbeard.API_KEY) # tornado setup self.enable_https = self.options['enable_https'] self.https_cert = self.options['https_cert'] self.https_key = self.options['https_key'] if self.enable_https: # If either the HTTPS certificate or key do not exist, make some self-signed ones. if not (self.https_cert and os.path.exists(self.https_cert)) or not ( self.https_key and os.path.exists(self.https_key)): if not create_https_certificates(self.https_cert, self.https_key): logger.log(u"Unable to create CERT/KEY files, disabling HTTPS") sickbeard.ENABLE_HTTPS = False self.enable_https = False if not (os.path.exists(self.https_cert) and os.path.exists(self.https_key)): logger.log(u"Disabled HTTPS because of missing CERT and KEY files", logger.WARNING) sickbeard.ENABLE_HTTPS = False self.enable_https = False # Load the app self.app = Application([], debug=True, autoreload=False, gzip=True, xheaders=sickbeard.HANDLE_REVERSE_PROXY, cookie_secret='61oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o/Vo=', login_url='%s/login/' % self.options['web_root'], ) # Main Handlers self.app.add_handlers('.*$', [ # webapi handler (r'%s(/?.*)' % self.options['api_root'], ApiHandler), # webapi key retrieval (r'%s/getkey(/?.*)' % self.options['web_root'], KeyHandler), # webapi builder redirect (r'%s/api/builder' % self.options['web_root'], RedirectHandler, {"url": self.options['web_root'] + '/apibuilder/'}), # webui login/logout handlers (r'%s/login(/?)' % self.options['web_root'], LoginHandler), (r'%s/logout(/?)' % self.options['web_root'], LogoutHandler), # webui handlers ] + route.get_routes(self.options['web_root'])) # Static File Handlers self.app.add_handlers(".*$", [ # favicon (r'%s/(favicon\.ico)' % self.options['web_root'], StaticFileHandler, {"path": os.path.join(self.options['data_root'], 'images/ico/favicon.ico')}), # images (r'%s/images/(.*)' % self.options['web_root'], StaticFileHandler, {"path": os.path.join(self.options['data_root'], 'images')}), # cached images (r'%s/cache/images/(.*)' % self.options['web_root'], StaticFileHandler, {"path": os.path.join(sickbeard.CACHE_DIR, 'images')}), # css (r'%s/css/(.*)' % self.options['web_root'], StaticFileHandler, {"path": os.path.join(self.options['data_root'], 'css')}), # javascript (r'%s/js/(.*)' % self.options['web_root'], StaticFileHandler, {"path": os.path.join(self.options['data_root'], 'js')}), # videos ] + [(r'%s/videos/(.*)' % self.options['web_root'], StaticFileHandler, {"path": self.video_root})])
def initWebServer(options={}): options.setdefault('port', 8081) options.setdefault('host', '0.0.0.0') options.setdefault('log_dir', None) options.setdefault('username', '') options.setdefault('password', '') options.setdefault('web_root', '/') assert isinstance(options['port'], int) assert 'data_root' in options def http_error_401_hander(status, message, traceback, version): """ Custom handler for 401 error """ if status != "401 Unauthorized": logger.log(u"CherryPy caught an error: %s %s" % (status, message), logger.ERROR) logger.log(traceback, logger.DEBUG) return r'''<!DOCTYPE html> <html> <head> <title>%s</title> </head> <body> <br/> <font color="#0000FF">Error %s: You need to provide a valid username and password.</font> </body> </html> ''' % ('Access denied', status) def http_error_404_hander(status, message, traceback, version): """ Custom handler for 404 error, redirect back to main page """ return r'''<!DOCTYPE html> <html> <head> <title>404</title> <script> <!-- location.href = "%s/home/" //--> </script> </head> <body> <br/> </body> </html> ''' % options['web_root'] # cherrypy setup enable_https = options['enable_https'] https_cert = options['https_cert'] https_key = options['https_key'] if enable_https: # If either the HTTPS certificate or key do not exist, make some self-signed ones. if not (https_cert and os.path.exists(https_cert)) or not (https_key and os.path.exists(https_key)): if not create_https_certificates(https_cert, https_key): logger.log(u"Unable to create CERT/KEY files, disabling HTTPS") sickbeard.ENABLE_HTTPS = False enable_https = False if not (os.path.exists(https_cert) and os.path.exists(https_key)): logger.log(u"Disabled HTTPS because of missing CERT and KEY files", logger.WARNING) sickbeard.ENABLE_HTTPS = False enable_https = False mime_gzip = ('text/html', 'text/plain', 'text/css', 'text/javascript', 'application/javascript', 'text/x-javascript', 'application/x-javascript', 'text/x-json', 'application/json' ) options_dict = { 'server.socket_port': options['port'], 'server.socket_host': options['host'], 'log.screen': False, 'engine.autoreload.on': False, 'engine.autoreload.frequency': 100, 'engine.reexec_retry': 100, 'tools.gzip.on': True, 'tools.gzip.mime_types': mime_gzip, 'error_page.401': http_error_401_hander, 'error_page.404': http_error_404_hander, 'tools.autoproxy.on': True, } if enable_https: options_dict['server.ssl_certificate'] = https_cert options_dict['server.ssl_private_key'] = https_key protocol = "https" else: protocol = "http" logger.log(u"Starting Sick Beard on " + protocol + "://" + str(options['host']) + ":" + str(options['port']) + "/") cherrypy.config.update(options_dict) # setup cherrypy logging if options['log_dir'] and os.path.isdir(options['log_dir']): cherrypy.config.update({ 'log.access_file': os.path.join(options['log_dir'], "cherrypy.log") }) logger.log(u'Using %s for cherrypy log' % cherrypy.config['log.access_file']) conf = { '/': { 'tools.staticdir.root': options['data_root'], 'tools.encode.on': True, 'tools.encode.encoding': 'utf-8', }, '/images': { 'tools.staticdir.on': True, 'tools.staticdir.dir': 'images' }, '/js': { 'tools.staticdir.on': True, 'tools.staticdir.dir': 'js' }, '/css': { 'tools.staticdir.on': True, 'tools.staticdir.dir': 'css' }, } app = cherrypy.tree.mount(WebInterface(), options['web_root'], conf) # auth if options['username'] != "" and options['password'] != "": checkpassword = cherrypy.lib.auth_basic.checkpassword_dict({options['username']: options['password']}) app.merge({ '/': { 'tools.auth_basic.on': True, 'tools.auth_basic.realm': 'SickBeard', 'tools.auth_basic.checkpassword': checkpassword }, '/api': { 'tools.auth_basic.on': False }, '/api/builder': { 'tools.auth_basic.on': True, 'tools.auth_basic.realm': 'SickBeard', 'tools.auth_basic.checkpassword': checkpassword } }) # Ensure that when behind a mod_rewrite Apache reverse proxy, # both direct requests and proxied requests are handled properly. def autoproxy( base = None, local = 'X-Forwarded-Host', remote = 'X-Forwarded-For', scheme = 'X-Forwarded-Proto', debug = False, ): """ Apply the CherryPy proxy tool only if the ``local`` header is set. Notice that it maps the parameters to the original proxy tool. Use it as per the usual proxy tool: tools.autoproxy.on: True tools.autoproxy.base: "http://www.mydomain.com" """ # or to look for all of them # h = cherrypy.serving.request.headers # if local in h and remote in h and scheme in h: if local in cherrypy.serving.request.headers: cherrypy.lib.cptools.proxy(base, local, remote, scheme, debug) cherrypy.tools.autoproxy = cherrypy.Tool( 'before_request_body', autoproxy, priority = 30, ) cherrypy.server.start() cherrypy.server.wait()