diff -aur cherrypy-upstream/cherrypy/_cpwsgi.py cherrypy/_cpwsgi.py --- cherrypy-upstream/cherrypy/_cpwsgi.py 2015-10-22 17:41:38.867808321 -0400 +++ cherrypy/_cpwsgi.py 2015-10-22 17:43:40.297744600 -0400 @@ -376,6 +376,10 @@ You probably shouldn't call this; call self.__call__ instead, so that any WSGI middleware in self.pipeline can run first. """ + # Changed by Kovid as the routes dispatcher cannot handle an empty + # PATH_INFO + if not environ.get('PATH_INFO', True): + environ['PATH_INFO'] = '/' return self.response_class(environ, start_response, self.cpapp) def __call__(self, environ, start_response): diff -aur cherrypy-upstream/cherrypy/lib/auth_digest.py cherrypy/lib/auth_digest.py --- cherrypy-upstream/cherrypy/lib/auth_digest.py 2015-10-09 11:26:01.726495960 -0400 +++ cherrypy/lib/auth_digest.py 2015-10-22 17:44:05.977730224 -0400 @@ -33,7 +33,8 @@ qop_auth_int = 'auth-int' valid_qops = (qop_auth, qop_auth_int) -valid_algorithms = ('MD5', 'MD5-sess') +valid_algorithms = ('MD5', 'MD5-sess', 'md5', 'md5-sess') # Changed by Kovid to + # add lowercase def TRACE(msg): @@ -67,7 +68,7 @@ argument to digest_auth(). """ def get_ha1(realm, username): - return user_ha1_dict.get(user) + return user_ha1_dict.get(username) # Changed by Kovid to fix typo return get_ha1 diff -aur cherrypy-upstream/cherrypy/lib/httpauth.py cherrypy/lib/httpauth.py --- cherrypy-upstream/cherrypy/lib/httpauth.py 2015-10-09 11:22:25.717666180 -0400 +++ cherrypy/lib/httpauth.py 2015-10-22 17:44:27.931051025 -0400 @@ -67,7 +67,7 @@ AUTH = "auth" AUTH_INT = "auth-int" -SUPPORTED_ALGORITHM = (MD5, MD5_SESS) +SUPPORTED_ALGORITHM = ('md5', MD5, MD5_SESS) # Changed by Kovid SUPPORTED_QOP = (AUTH, AUTH_INT) ################################################################################ @@ -75,6 +75,7 @@ # DIGEST_AUTH_ENCODERS = { MD5: lambda val: md5(ntob(val)).hexdigest(), + 'md5': lambda val:md5(val).hexdigest(), # Added by Kovid MD5_SESS: lambda val: md5(ntob(val)).hexdigest(), # SHA: lambda val: sha.new(ntob(val)).hexdigest (), } @@ -216,7 +217,7 @@ algorithm = params.get ("algorithm", MD5) H = DIGEST_AUTH_ENCODERS[algorithm] - if algorithm == MD5: + if algorithm in (MD5, 'md5'): # Changed by Kovid # If the "algorithm" directive's value is "MD5" or is # unspecified, then A1 is: # A1 = unq(username-value) ":" unq(realm-value) ":" passwd diff -aur cherrypy-upstream/cherrypy/lib/sessions.py cherrypy/lib/sessions.py --- cherrypy-upstream/cherrypy/lib/sessions.py 2015-10-09 11:23:11.340752352 -0400 +++ cherrypy/lib/sessions.py 2015-10-22 17:44:42.811042405 -0400 @@ -86,7 +86,6 @@ import datetime import os -import random import time import threading import types @@ -536,7 +535,7 @@ for k, v in kwargs.items(): setattr(cls, k, v) - self.db = self.get_db() + cls.db = cls.get_db() setup = classmethod(setup) def __del__(self): @@ -849,7 +848,8 @@ # save it to disk and the session is lost if people close # the browser. So we have to use the old "expires" ... sigh ... ## cookie[name]['max-age'] = timeout * 60 - if timeout: + if False and timeout: # Changed by Kovid, we want the user to have to + # re-authenticate on browser restart e = time.time() + (timeout * 60) cookie[name]['expires'] = httputil.HTTPDate(e) if domain is not None: diff -aur cherrypy-upstream/cherrypy/process/servers.py cherrypy/process/servers.py --- cherrypy-upstream/cherrypy/process/servers.py 2015-10-09 11:26:28.053020003 -0400 +++ cherrypy/process/servers.py 2015-08-30 01:40:00.401843019 -0400 @@ -387,7 +387,7 @@ # Feel free to increase these defaults on slow systems: -free_port_timeout = 0.1 +free_port_timeout = 0.2 # Changed by Kovid occupied_port_timeout = 1.0 def wait_for_free_port(host, port, timeout=None): diff -aur cherrypy-upstream/cherrypy/process/wspbus.py cherrypy/process/wspbus.py --- cherrypy-upstream/cherrypy/process/wspbus.py 2015-10-09 11:26:43.099605156 -0400 +++ cherrypy/process/wspbus.py 2015-08-29 23:12:40.413066683 -0400 @@ -268,7 +268,11 @@ # Assume it's been logged and just die. os._exit(70) # EX_SOFTWARE - if exitstate == states.STARTING: + # Changed by Kovid, we cannot have all of calibre being quit + # Also we want to catch the port blocked/busy error and try listening only on + # the external ip + # See https://bitbucket.org/cherrypy/cherrypy/issue/1017/exit-behavior-is-not-good-when-running-in + if False and exitstate == states.STARTING: # exit() was called before start() finished, possibly due to # Ctrl-C because a start listener got stuck. In this case, # we could get stuck in a loop where Ctrl-C never exits the Only in cherrypy-upstream/cherrypy/: test Only in cherrypy-upstream/cherrypy/: tutorial