Merge remote-tracking branch 'origin/dev'

This commit is contained in:
echel0n 2014-06-18 08:09:13 -07:00
commit 250a83fbda
7 changed files with 54207 additions and 23278 deletions

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -97,18 +97,8 @@ def change_LOG_DIR(log_dir, web_log):
return False
if sickbeard.WEB_LOG != web_log_value or log_dir_changed == True:
sickbeard.WEB_LOG = web_log_value
if sickbeard.WEB_LOG:
cherry_log = os.path.join(sickbeard.LOG_DIR, "cherrypy.log")
logger.log(u"Change cherry log file to " + cherry_log)
else:
cherry_log = None
logger.log(u"Disable cherry logging")
#cherrypy.config.update({'log.access_file': cherry_log})
return True

View file

@ -76,11 +76,13 @@ class SBRotatingLogHandler(object):
sub_logger = logging.getLogger('subliminal')
imdb_logger = logging.getLogger('imdbpy')
tornado_logger = logging.getLogger('tornado')
feedcache_logger = logging.getLogger('feedcache')
sb_logger.removeHandler(handler)
sub_logger.removeHandler(handler)
imdb_logger.removeHandler(handler)
tornado_logger.removeHandler(handler)
feedcache_logger.removeHandler(handler)
handler.flush()
handler.close()
@ -116,7 +118,9 @@ class SBRotatingLogHandler(object):
'%H:%M:%S'),
'imdbpy': logging.Formatter('%(asctime)s %(levelname)s::IMDBPY :: %(message)s', '%H:%M:%S'),
'tornado.general': logging.Formatter('%(asctime)s %(levelname)s::TORNADO :: %(message)s', '%H:%M:%S'),
'tornado.application': logging.Formatter('%(asctime)s %(levelname)s::TORNADO :: %(message)s', '%H:%M:%S')
'tornado.application': logging.Formatter('%(asctime)s %(levelname)s::TORNADO :: %(message)s', '%H:%M:%S'),
'feedcache.cache': logging.Formatter('%(asctime)s %(levelname)s::FEEDCACHE :: %(message)s',
'%H:%M:%S')
},
logging.Formatter('%(message)s'), ))
@ -126,15 +130,18 @@ class SBRotatingLogHandler(object):
logging.getLogger('tornado.application').addHandler(console)
logging.getLogger('subliminal').addHandler(console)
logging.getLogger('imdbpy').addHandler(console)
logging.getLogger('feedcache').addHandler(console)
self.log_file_path = os.path.join(sickbeard.LOG_DIR, self.log_file)
self.cur_handler = self._config_handler()
logging.getLogger('sickbeard').addHandler(self.cur_handler)
logging.getLogger('tornado.access').addHandler(NullHandler())
logging.getLogger('tornado.general').addHandler(self.cur_handler)
logging.getLogger('tornado.application').addHandler(self.cur_handler)
logging.getLogger('subliminal').addHandler(self.cur_handler)
logging.getLogger('imdbpy').addHandler(self.cur_handler)
logging.getLogger('feedcache').addHandler(self.cur_handler)
logging.getLogger('sickbeard').setLevel(DB)
@ -146,20 +153,20 @@ class SBRotatingLogHandler(object):
logging.getLogger('tornado.application').setLevel(log_level)
logging.getLogger('subliminal').setLevel(log_level)
logging.getLogger('imdbpy').setLevel(log_level)
logging.getLogger('feedcache').setLevel(log_level)
logging.getLogger('tornado.access').addHandler(NullHandler())
# already logging in new log folder, close the old handler
if old_handler:
self.close_log(old_handler)
# old_handler.flush()
# old_handler.close()
# sb_logger = logging.getLogger('sickbeard')
# sub_logger = logging.getLogger('subliminal')
# imdb_logger = logging.getLogger('imdbpy')
# sb_logger.removeHandler(old_handler)
# subli_logger.removeHandler(old_handler)
# imdb_logger.removeHandler(old_handler)
# old_handler.flush()
# old_handler.close()
# sb_logger = logging.getLogger('sickbeard')
# sub_logger = logging.getLogger('subliminal')
# imdb_logger = logging.getLogger('imdbpy')
# sb_logger.removeHandler(old_handler)
# subli_logger.removeHandler(old_handler)
# imdb_logger.removeHandler(old_handler)
def _config_handler(self):
"""
@ -174,7 +181,9 @@ class SBRotatingLogHandler(object):
'%Y-%m-%d %H:%M:%S'),
'imdbpy': logging.Formatter('%(asctime)s %(levelname)-8s IMDBPY :: %(message)s', '%Y-%m-%d %H:%M:%S'),
'tornado.general': logging.Formatter('%(asctime)s %(levelname)-8s TORNADO :: %(message)s', '%Y-%m-%d %H:%M:%S'),
'tornado.application': logging.Formatter('%(asctime)s %(levelname)-8s TORNADO :: %(message)s', '%Y-%m-%d %H:%M:%S')
'tornado.application': logging.Formatter('%(asctime)s %(levelname)-8s TORNADO :: %(message)s', '%Y-%m-%d %H:%M:%S'),
'feedcache.cache': logging.Formatter('%(asctime)s %(levelname)-8s FEEDCACHE :: %(message)s',
'%Y-%m-%d %H:%M:%S')
},
logging.Formatter('%(message)s'), ))
@ -208,6 +217,7 @@ class SBRotatingLogHandler(object):
sub_logger = logging.getLogger('subliminal')
imdb_logger = logging.getLogger('imdbpy')
tornado_logger = logging.getLogger('tornado')
feedcache_logger = logging.getLogger('feedcache')
# delete the old handler
if self.cur_handler:
@ -233,6 +243,7 @@ class SBRotatingLogHandler(object):
sub_logger.addHandler(new_file_handler)
imdb_logger.addHandler(new_file_handler)
tornado_logger.addHandler(new_file_handler)
feedcache_logger.addHandler(new_file_handler)
def log(self, toLog, logLevel=MESSAGE):
@ -257,6 +268,7 @@ class SBRotatingLogHandler(object):
sub_logger = logging.getLogger('subliminal')
imdb_logger = logging.getLogger('imdbpy')
tornado_logger = logging.getLogger('tornado')
feedcache_logger = logging.getLogger('feedcache')
try:
if logLevel == DEBUG:

View file

@ -160,7 +160,6 @@ class Api(webserve.IndexHandler):
return webserve._munge(t)
def _out_as_json(self, dict):
""" set cherrypy response to json """
self.set_header("Content-Type", "application/json")
try:
out = json.dumps(dict, indent=self.intent, sort_keys=True)

View file

@ -80,26 +80,23 @@ except ImportError:
from lib import adba
from Cheetah.Template import Template
from tornado import gen, autoreload
from tornado.web import RequestHandler, RedirectHandler, HTTPError, asynchronous
from tornado.ioloop import IOLoop
from tornado import gen
from tornado.web import RequestHandler, HTTPError, asynchronous
# def _handle_reverse_proxy():
# if sickbeard.HANDLE_REVERSE_PROXY:
# cherrypy.lib.cptools.proxy()
# cherrypy.tools.handle_reverse_proxy = cherrypy.Tool('before_handler', _handle_reverse_proxy)
req_headers = None
def authenticated(handler_class):
def wrap_execute(handler_execute):
def basicauth(handler, transforms, *args, **kwargs):
def _request_basic_auth(handler):
handler.set_status(401)
handler.set_header('WWW-Authenticate', 'Basic realm=Restricted')
handler.set_header('WWW-Authenticate', 'Basic realm=SickRage')
handler._transforms = []
handler.finish()
return False
@ -107,6 +104,9 @@ def authenticated(handler_class):
try:
if not (sickbeard.WEB_USERNAME and sickbeard.WEB_PASSWORD):
return True
elif handler.request.uri.startswith('/calendar') or (
handler.request.uri.startswith('/api') and '/api/builder' not in handler.request.uri):
return True
auth_hdr = handler.request.headers.get('Authorization')
@ -134,6 +134,7 @@ def authenticated(handler_class):
handler_class._execute = wrap_execute(handler_class._execute)
return handler_class
@authenticated
class IndexHandler(RequestHandler):
def __init__(self, application, request, **kwargs):
@ -143,9 +144,35 @@ class IndexHandler(RequestHandler):
sickbeard.REMOTE_IP = self.request.remote_ip
req_headers = self.request.headers
def http_error_401_handler(self):
""" Custom handler for 401 error """
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', 401)
def http_error_404_handler(self):
""" Custom handler for 404 error, redirect back to main page """
self.redirect('/home/')
def write_error(self, status_code, **kwargs):
if status_code == 404:
self.redirect('/home/')
elif status_code == 401:
self.finish(self.http_error_401_handler())
else:
super(IndexHandler, self).write_error(status_code, **kwargs)
def _dispatch(self):
path = self.request.uri.replace(sickbeard.WEB_ROOT,'').split('?')[0]
path = self.request.uri.replace(sickbeard.WEB_ROOT, '').split('?')[0]
method = path.strip('/').split('/')[-1]
if path.startswith('/api'):
@ -185,7 +212,7 @@ class IndexHandler(RequestHandler):
return func(**args)
raise HTTPError(404)
def redirect(self, url, permanent=False, status=None):
self._transforms = []
super(IndexHandler, self).redirect(sickbeard.WEB_ROOT + url, permanent, status)
@ -193,24 +220,12 @@ class IndexHandler(RequestHandler):
@asynchronous
@gen.engine
def get(self, *args, **kwargs):
try:
response = yield gen.Task(self.getresponse, self._dispatch)
self.finish(response)
except Exception as e:
logger.log(ex(e), logger.ERROR)
logger.log(u"Traceback: " + traceback.format_exc(), logger.DEBUG)
response = yield gen.Task(self.getresponse, self._dispatch)
self.finish(response)
@asynchronous
@gen.engine
def post(self, *args, **kwargs):
try:
response = yield gen.Task(self.getresponse, self._dispatch)
self.finish(response)
except Exception as e:
logger.log(ex(e), logger.ERROR)
logger.log(u"Traceback: " + traceback.format_exc(), logger.DEBUG)
return self._dispatch()
def getresponse(self, func, callback):
response = func()
callback(response)
@ -445,7 +460,6 @@ class IndexHandler(RequestHandler):
browser = WebFileBrowser
class PageTemplate(Template):
def __init__(self, *args, **KWs):
KWs['file'] = os.path.join(sickbeard.PROG_DIR, "gui/" + sickbeard.GUI_NAME + "/interfaces/default/",
@ -1463,6 +1477,7 @@ class ConfigGeneral(IndexHandler):
else:
ui.notifications.message('Configuration Saved', ek.ek(os.path.join, sickbeard.CONFIG_FILE))
class ConfigSearch(IndexHandler):
def index(self, *args, **kwargs):
@ -2692,7 +2707,7 @@ class NewHomeAddShows(IndexHandler):
def finishAddShow():
# if there are no extra shows then go home
if not other_shows:
self.redirect('/home/')
return self.redirect('/home/')
# peel off the next one
next_show_dir = other_shows[0]

View file

@ -12,9 +12,11 @@ from tornado.ioloop import IOLoop
server = None
class MultiStaticFileHandler(StaticFileHandler):
def initialize(self, paths, default_filename=None):
self.paths = paths
self.default_filename = default_filename
def get(self, path, include_body=True):
for p in self.paths:
@ -43,41 +45,6 @@ def initWebServer(options={}):
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']
@ -116,14 +83,11 @@ def initWebServer(options={}):
{'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'),
os.path.join(sickbeard.CACHE_DIR, 'images', 'thumbnails')]}),
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'),
os.path.join(options['data_root'], 'js/lib'),
os.path.join(options['data_root'], 'js/fancybox')]})
{'paths': [os.path.join(options['data_root'], 'js')]})
])