1
0
mirror of https://github.com/moparisthebest/SickRage synced 2024-11-16 14:25:02 -05:00

Merge branch 'dev' of https://github.com/echel0n/SickRage into pushover-custom_api_key

This commit is contained in:
Mark Rawson 2014-06-18 21:38:44 +01:00
commit 03c9b303e0
9 changed files with 54297 additions and 23395 deletions

View File

@ -18,6 +18,8 @@
# along with SickRage. If not, see <http://www.gnu.org/licenses/>.
# Check needed software dependencies to nudge users to fix their setup
from __future__ import with_statement
import sys
if sys.version_info < (2, 6):
@ -95,35 +97,27 @@ def loadShowsFromDB():
# TODO: update the existing shows if the showlist has something in it
def daemonize():
"""
Fork off as a daemon
"""
# pylint: disable=E1101
# Make a non-session-leader child process
try:
pid = os.fork() # @UndefinedVariable - only available in UNIX
if pid != 0:
os._exit(0)
except OSError, e:
sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror))
pid = os.fork()
if pid > 0:
sys.exit(0)
except OSError:
print "fork() failed"
sys.exit(1)
os.setsid() # unix
os.chdir(sickbeard.PROG_DIR)
os.setsid()
# Make sure I can read my own files and shut out others
prev = os.umask(0)
os.umask(prev and int('077', 8))
prev= os.umask(0)
os.umask(prev and int('077',8))
# Make the child a session-leader by detaching from the terminal
try:
pid = os.fork() # @UndefinedVariable - only available in UNIX
if pid != 0:
os._exit(0)
except OSError, e:
sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror))
pid = os.fork()
if pid > 0:
sys.exit(0)
except OSError:
print "fork() failed"
sys.exit(1)
# Write pid
@ -137,25 +131,14 @@ def daemonize():
u"Unable to write PID file: " + sickbeard.PIDFILE + " Error: " + str(e.strerror) + " [" + str(
e.errno) + "]")
# Redirect all output
sys.stdout.flush()
sys.stderr.flush()
devnull = getattr(os, 'devnull', '/dev/null')
stdin = file(devnull, 'r')
stdout = file(devnull, 'a+')
stderr = file(devnull, 'a+')
os.dup2(stdin.fileno(), sys.stdin.fileno())
os.dup2(stdout.fileno(), sys.stdout.fileno())
os.dup2(stderr.fileno(), sys.stderr.fileno())
dev_null = file('/dev/null', 'r')
os.dup2(dev_null.fileno(), sys.stdin.fileno())
def main():
"""
TV for me
"""
io_loop = IOLoop.current()
# do some preliminary stuff
sickbeard.MY_FULLNAME = os.path.normpath(os.path.abspath(__file__))
sickbeard.MY_NAME = os.path.basename(sickbeard.MY_FULLNAME)
@ -325,12 +308,6 @@ def main():
sickbeard.showList = []
if sickbeard.DAEMON:
daemonize()
# Use this PID for everything
sickbeard.PID = os.getpid()
if forcedPort:
logger.log(u"Forcing web server to port " + str(forcedPort))
startPort = forcedPort
@ -385,6 +362,9 @@ def main():
if forceUpdate or sickbeard.UPDATE_SHOWS_ON_START:
sickbeard.showUpdateScheduler.action.run(force=True) # @UndefinedVariable
# get ioloop
io_loop = IOLoop.current()
# init startup tasks
io_loop.add_timeout(datetime.timedelta(seconds=5), startup)
@ -393,6 +373,12 @@ def main():
if sickbeard.AUTO_UPDATE:
tornado.autoreload.start(io_loop)
if sickbeard.DAEMON:
daemonize()
# Use this PID for everything
sickbeard.PID = os.getpid()
# start IOLoop.
io_loop.start()
sickbeard.saveAndShutdown()

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,8 +153,8 @@ 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:
@ -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)
@ -297,10 +296,11 @@ def filter_params(cmd, args, kwargs):
return curArgs, curKwargs
class ApiCall(Api):
class ApiCall(webserve.IndexHandler):
_help = {"desc": "No help message available. Please tell the devs that a help msg is missing for this cmd"}
def __init__(self, args, kwargs):
# missing
try:
if self._missing:
@ -2104,7 +2104,7 @@ class CMD_ShowGetPoster(ApiCall):
def run(self):
""" get the poster for a show in sickbeard """
return {'outputType': 'image', 'image': webserve.IndexHandler.showPoster(self.indexerid, 'poster')}
return {'outputType': 'image', 'image': self.showPoster(self.indexerid, 'poster')}
class CMD_ShowGetBanner(ApiCall):
@ -2122,7 +2122,7 @@ class CMD_ShowGetBanner(ApiCall):
def run(self):
""" get the banner for a show in sickbeard """
return {'outputType': 'image', 'image': webserve.IndexHandler.showPoster(self.indexerid, 'banner')}
return {'outputType': 'image', 'image': self.showPoster(self.indexerid, 'banner')}
class CMD_ShowPause(ApiCall):

View File

@ -80,26 +80,16 @@ except ImportError:
from lib import adba
from Cheetah.Template import Template
from tornado import gen, autoreload
from tornado import gen
from tornado.web import RequestHandler, HTTPError, asynchronous
from tornado.ioloop import IOLoop
# 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 +97,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')
@ -135,13 +128,8 @@ def authenticated(handler_class):
return handler_class
class RedirectHandler(RequestHandler):
def get(self, path, **kwargs):
self.redirect(path, permanent=True)
@authenticated
class IndexHandler(RedirectHandler):
class IndexHandler(RequestHandler):
def __init__(self, application, request, **kwargs):
super(IndexHandler, self).__init__(application, request, **kwargs)
global req_headers
@ -149,22 +137,35 @@ class IndexHandler(RedirectHandler):
sickbeard.REMOTE_IP = self.request.remote_ip
req_headers = self.request.headers
def delist_arguments(self, args):
"""
Takes a dictionary, 'args' and de-lists any single-item lists then
returns the resulting dictionary.
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)
In other words, {'foo': ['bar']} would become {'foo': 'bar'}
"""
for arg, value in args.items():
if len(value) == 1:
args[arg] = value[0]
return args
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):
args = None
path = self.request.uri.split('?')[0]
path = self.request.uri.replace(sickbeard.WEB_ROOT, '').split('?')[0]
method = path.strip('/').split('/')[-1]
if path.startswith('/api'):
@ -185,8 +186,10 @@ class IndexHandler(RedirectHandler):
if klass and not method.startswith('_'):
# Sanitize argument lists:
if self.request.arguments:
args = self.delist_arguments(self.request.arguments)
args = self.request.arguments
for arg, value in args.items():
if len(value) == 1:
args[arg] = value[0]
# Regular method handler for classes
func = getattr(klass, method, None)
@ -199,30 +202,29 @@ class IndexHandler(RedirectHandler):
func = getattr(klass, 'index', None)
if func:
if args:
return func(**args)
else:
return func()
raise HTTPError(404)
@asynchronous
def get(self, *args, **kwargs):
try:
resp = self._dispatch()
if resp:
self.finish(resp)
except Exception as e:
logger.log(ex(e), logger.ERROR)
logger.log(u"Traceback: " + traceback.format_exc(), logger.DEBUG)
def redirect(self, url, permanent=False, status=None):
self._transforms = []
super(IndexHandler, self).redirect(sickbeard.WEB_ROOT + url, permanent, status)
@asynchronous
@gen.engine
def get(self, *args, **kwargs):
response = yield gen.Task(self.getresponse, self._dispatch)
self.finish(response)
@asynchronous
@gen.engine
def post(self, *args, **kwargs):
try:
self.finish(self._dispatch())
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)
def getresponse(self, func, callback):
response = func()
callback(response)
def robots_txt(self, *args, **kwargs):
""" Keep web crawlers out """
@ -264,7 +266,7 @@ class IndexHandler(RedirectHandler):
sickbeard.HOME_LAYOUT = layout
self.redirect("/home/")
return self.redirect("/home/")
def setHistoryLayout(self, layout):
@ -273,13 +275,13 @@ class IndexHandler(RedirectHandler):
sickbeard.HISTORY_LAYOUT = layout
self.redirect("/history/")
return self.redirect("/history/")
def toggleDisplayShowSpecials(self, show):
sickbeard.DISPLAY_SHOW_SPECIALS = not sickbeard.DISPLAY_SHOW_SPECIALS
self.redirect("/home/displayShow?show=" + show)
return self.redirect("/home/displayShow?show=" + show)
def setComingEpsLayout(self, layout):
if layout not in ('poster', 'banner', 'list'):
@ -287,13 +289,13 @@ class IndexHandler(RedirectHandler):
sickbeard.COMING_EPS_LAYOUT = layout
self.redirect("/comingEpisodes/")
return self.redirect("/comingEpisodes/")
def toggleComingEpsDisplayPaused(self, *args, **kwargs):
sickbeard.COMING_EPS_DISPLAY_PAUSED = not sickbeard.COMING_EPS_DISPLAY_PAUSED
self.redirect("/comingEpisodes/")
return self.redirect("/comingEpisodes/")
def setComingEpsSort(self, sort):
if sort not in ('date', 'network', 'show'):
@ -301,7 +303,7 @@ class IndexHandler(RedirectHandler):
sickbeard.COMING_EPS_SORT = sort
self.redirect("/comingEpisodes/")
return self.redirect("/comingEpisodes/")
def comingEpisodes(self, layout="None"):
@ -454,7 +456,6 @@ class IndexHandler(RedirectHandler):
browser = WebFileBrowser
class PageTemplate(Template):
def __init__(self, *args, **KWs):
KWs['file'] = os.path.join(sickbeard.PROG_DIR, "gui/" + sickbeard.GUI_NAME + "/interfaces/default/",
@ -506,7 +507,7 @@ class IndexerWebUI(IndexHandler):
showDirList = ""
for curShowDir in self.config['_showDir']:
showDirList += "showDir=" + curShowDir + "&"
self.redirect("/home/addShows/addShow?" + showDirList + "seriesList=" + searchList)
return self.redirect("/home/addShows/addShow?" + showDirList + "seriesList=" + searchList)
def _munge(string):
@ -585,7 +586,7 @@ class ManageSearches(IndexHandler):
logger.log(u"Backlog search forced")
ui.notifications.message('Backlog search started')
self.redirect("/manage/manageSearches/")
return self.redirect("/manage/manageSearches/")
def forceSearch(self, *args, **kwargs):
@ -596,7 +597,7 @@ class ManageSearches(IndexHandler):
logger.log(u"Daily search forced")
ui.notifications.message('Daily search started')
self.redirect("/manage/manageSearches/")
return self.redirect("/manage/manageSearches/")
def forceFindPropers(self, *args, **kwargs):
@ -607,7 +608,7 @@ class ManageSearches(IndexHandler):
logger.log(u"Find propers search forced")
ui.notifications.message('Find propers search started')
self.redirect("/manage/manageSearches/")
return self.redirect("/manage/manageSearches/")
def pauseBacklog(self, paused=None):
@ -616,7 +617,7 @@ class ManageSearches(IndexHandler):
else:
sickbeard.searchQueueScheduler.action.unpause_backlog() # @UndefinedVariable
self.redirect("/manage/manageSearches/")
return self.redirect("/manage/manageSearches/")
class Manage(IndexHandler):
@ -729,7 +730,7 @@ class Manage(IndexHandler):
Home.setStatus(cur_indexer_id, '|'.join(to_change[cur_indexer_id]), newStatus, direct=True)
self.redirect('/manage/episodeStatuses/')
return self.redirect('/manage/episodeStatuses/')
def showSubtitleMissed(self, indexer_id, whichSubs):
@ -837,7 +838,7 @@ class Manage(IndexHandler):
show = sickbeard.helpers.findCertainShow(sickbeard.showList, int(cur_indexer_id))
subtitles = show.getEpisode(int(season), int(episode)).downloadSubtitles()
self.redirect('/manage/subtitleMissed/')
return self.redirect('/manage/subtitleMissed/')
def backlogShow(self, indexer_id):
@ -847,7 +848,7 @@ class Manage(IndexHandler):
if show_obj:
sickbeard.backlogSearchScheduler.action.searchBacklog([show_obj]) # @UndefinedVariable
self.redirect("/manage/backlogOverview/")
return self.redirect("/manage/backlogOverview/")
def backlogOverview(self, *args, **kwargs):
@ -897,7 +898,7 @@ class Manage(IndexHandler):
t.submenu = ManageMenu()
if not toEdit:
self.redirect("/manage/")
return self.redirect("/manage/")
showIDs = toEdit.split("|")
showList = []
@ -1062,7 +1063,7 @@ class Manage(IndexHandler):
ui.notifications.error('%d error%s while saving changes:' % (len(errors), "" if len(errors) == 1 else "s"),
" ".join(errors))
self.redirect("/manage/")
return self.redirect("/manage/")
def massUpdate(self, toUpdate=None, toRefresh=None, toRename=None, toDelete=None, toMetadata=None, toSubtitle=None):
@ -1171,7 +1172,7 @@ class Manage(IndexHandler):
ui.notifications.message("The following actions were queued:",
messageDetail)
self.redirect("/manage/")
return self.redirect("/manage/")
def manageTorrents(self, *args, **kwargs):
@ -1303,7 +1304,7 @@ class History(IndexHandler):
myDB.action("DELETE FROM history WHERE 1=1")
ui.notifications.message('History cleared')
self.redirect("/history/")
return self.redirect("/history/")
def trimHistory(self, *args, **kwargs):
@ -1313,7 +1314,7 @@ class History(IndexHandler):
(datetime.datetime.today() - datetime.timedelta(days=30)).strftime(history.dateFormat)))
ui.notifications.message('Removed history entries greater than 30 days old')
self.redirect("/history/")
return self.redirect("/history/")
ConfigMenu = [
@ -2461,7 +2462,7 @@ class HomePostProcess(IndexHandler):
if sickbeard.versionCheckScheduler.action.check_for_new_version(force=True):
logger.log(u"Forcing version check")
self.redirect("/home/")
return self.redirect("/home/")
def processEpisode(self, dir=None, nzbName=None, jobName=None, quiet=None, process_method=None, force=None,
is_priority=None, failed="0", type="auto"):
@ -2482,7 +2483,7 @@ class HomePostProcess(IndexHandler):
is_priority = False
if not dir:
self.redirect("/home/postprocess/")
return self.redirect("/home/postprocess/")
else:
result = processTV.processDir(dir, nzbName, process_method=process_method, force=force,
is_priority=is_priority, failed=failed, type=type)
@ -2703,7 +2704,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]
@ -2728,7 +2729,7 @@ class NewHomeAddShows(IndexHandler):
logger.log("Unable to add show due to show selection. Not anough arguments: %s" % (repr(series_pieces)),
logger.ERROR)
ui.notifications.error("Unknown error. Unable to add show due to problem with show selection.")
self.redirect('/home/addShows/existingShows/')
return self.redirect('/home/addShows/existingShows/')
indexer = int(series_pieces[1])
indexer_id = int(series_pieces[3])
show_name = series_pieces[4]
@ -2750,7 +2751,7 @@ class NewHomeAddShows(IndexHandler):
# blanket policy - if the dir exists you should have used "add existing show" numbnuts
if ek.ek(os.path.isdir, show_dir) and not fullShowPath:
ui.notifications.error("Unable to add show", "Folder " + show_dir + " exists already")
self.redirect('/home/addShows/existingShows/')
return self.redirect('/home/addShows/existingShows/')
# don't create show dir if config says not to
if sickbeard.ADD_SHOWS_WO_DIR:
@ -2761,7 +2762,7 @@ class NewHomeAddShows(IndexHandler):
logger.log(u"Unable to create the folder " + show_dir + ", can't add the show", logger.ERROR)
ui.notifications.error("Unable to add show",
"Unable to create the folder " + show_dir + ", can't add the show")
self.redirect("/home/")
return self.redirect("/home/")
else:
helpers.chmodAsParent(show_dir)
@ -2866,7 +2867,7 @@ class NewHomeAddShows(IndexHandler):
# if we're done then go home
if not dirs_only:
self.redirect('/home/')
return self.redirect('/home/')
# for the remaining shows we need to prompt for each one, so forward this on to the newShow page
return self.newShow(dirs_only[0], dirs_only[1:])
@ -2889,7 +2890,7 @@ class ErrorLogs(IndexHandler):
def clearerrors(self, *args, **kwargs):
classes.ErrorViewer.clear()
self.redirect("/errorlogs/")
return self.redirect("/errorlogs/")
def viewlog(self, minLevel=logger.MESSAGE, maxLines=500):
@ -3260,7 +3261,7 @@ class Home(IndexHandler):
def shutdown(self, pid=None):
if str(pid) != str(sickbeard.PID):
self.redirect("/home/")
return self.redirect("/home/")
threading.Timer(2, sickbeard.invoke_shutdown).start()
@ -3272,7 +3273,7 @@ class Home(IndexHandler):
def restart(self, pid=None):
if str(pid) != str(sickbeard.PID):
self.redirect("/home/")
return self.redirect("/home/")
t = PageTemplate(file="restart.tmpl")
t.submenu = HomeMenu()
@ -3286,16 +3287,14 @@ class Home(IndexHandler):
def update(self, pid=None):
if str(pid) != str(sickbeard.PID):
self.redirect("/home/")
# auto-reload
tornado.autoreload.start(IOLoop.current())
return self.redirect("/home/")
updated = sickbeard.versionCheckScheduler.action.update() # @UndefinedVariable
if updated:
# do a hard restart
#threading.Timer(2, sickbeard.invoke_restart, [False]).start()
if not sickbeard.AUTO_UPDATE:
threading.Timer(2, sickbeard.invoke_restart, [False]).start()
t = PageTemplate(file="restart_bare.tmpl")
return _munge(t)
else:
@ -3709,7 +3708,7 @@ class Home(IndexHandler):
ui.notifications.error('%d error%s while saving changes:' % (len(errors), "" if len(errors) == 1 else "s"),
'<ul>' + '\n'.join(['<li>%s</li>' % error for error in errors]) + "</ul>")
self.redirect("/home/displayShow?show=" + show)
return self.redirect("/home/displayShow?show=" + show)
def deleteShow(self, show=None):
@ -3729,7 +3728,7 @@ class Home(IndexHandler):
showObj.deleteShow()
ui.notifications.message('<b>%s</b> has been deleted' % showObj.name)
self.redirect("/home/")
return self.redirect("/home/")
def refreshShow(self, show=None):
@ -3751,7 +3750,7 @@ class Home(IndexHandler):
time.sleep(cpu_presets[sickbeard.CPU_PRESET])
self.redirect("/home/displayShow?show=" + str(showObj.indexerid))
return self.redirect("/home/displayShow?show=" + str(showObj.indexerid))
def updateShow(self, show=None, force=0):
@ -3774,7 +3773,7 @@ class Home(IndexHandler):
# just give it some time
time.sleep(cpu_presets[sickbeard.CPU_PRESET])
self.redirect("/home/displayShow?show=" + str(showObj.indexerid))
return self.redirect("/home/displayShow?show=" + str(showObj.indexerid))
def subtitleShow(self, show=None, force=0):
@ -3792,7 +3791,7 @@ class Home(IndexHandler):
time.sleep(cpu_presets[sickbeard.CPU_PRESET])
self.redirect("/home/displayShow?show=" + str(showObj.indexerid))
return self.redirect("/home/displayShow?show=" + str(showObj.indexerid))
def updateXBMC(self, showName=None):
@ -3808,7 +3807,7 @@ class Home(IndexHandler):
ui.notifications.message("Library update command sent to XBMC host(s): " + host)
else:
ui.notifications.error("Unable to contact one or more XBMC host(s): " + host)
self.redirect('/home/')
return self.redirect('/home/')
def updatePLEX(self, *args, **kwargs):
@ -3817,7 +3816,7 @@ class Home(IndexHandler):
"Library update command sent to Plex Media Server host: " + sickbeard.PLEX_SERVER_HOST)
else:
ui.notifications.error("Unable to contact Plex Media Server host: " + sickbeard.PLEX_SERVER_HOST)
self.redirect('/home/')
return self.redirect('/home/')
def setStatus(self, show=None, eps=None, status=None, direct=False):
@ -3931,7 +3930,7 @@ class Home(IndexHandler):
if direct:
return json.dumps({'result': 'success'})
else:
self.redirect("/home/displayShow?show=" + show)
return self.redirect("/home/displayShow?show=" + show)
def testRename(self, show=None):
@ -3998,7 +3997,7 @@ class Home(IndexHandler):
return _genericMessage("Error", "Can't rename episodes when the show dir is missing.")
if eps is None:
self.redirect("/home/displayShow?show=" + show)
return self.redirect("/home/displayShow?show=" + show)
with db.DBConnection() as myDB:
for curEp in eps.split('|'):
@ -4025,7 +4024,7 @@ class Home(IndexHandler):
root_ep_obj.rename()
self.redirect("/home/displayShow?show=" + show)
return self.redirect("/home/displayShow?show=" + show)
def searchEpisode(self, show=None, season=None, episode=None):

View File

@ -16,6 +16,7 @@ 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:
@ -44,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']
@ -101,25 +67,24 @@ def initWebServer(options={}):
app = Application([],
debug=sickbeard.DEBUG,
gzip=True,
xheaders=True,
xheaders=sickbeard.HANDLE_REVERSE_PROXY,
cookie_secret='61oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o/Vo='
)
# Index Handler
# Main Handler
app.add_handlers(".*$", [
(r"/", RedirectHandler, {'url': '/home/'}),
(r'/api/(.*)(/?)', webapi.Api),
(r'%s(.*)(/?)' % options['web_root'], webserve.IndexHandler)
(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'/(favicon\.ico)', MultiStaticFileHandler,
{'paths': '%s/%s' % (options['web_root'], 'images/ico/favicon.ico')}),
(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'),
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,

View File

@ -630,6 +630,7 @@ class RequestHandler(object):
self.set_status(status)
self.set_header("Location", urlparse.urljoin(utf8(self.request.uri),
utf8(url)))
self.finish()
def write(self, chunk):