2.1 --- a/WebStack/Resources/Login.py Thu Aug 25 18:20:19 2005 +0000
2.2 +++ b/WebStack/Resources/Login.py Thu Aug 25 18:21:49 2005 +0000
2.3 @@ -28,67 +28,95 @@
2.4
2.5 "A resource providing a login screen."
2.6
2.7 - def __init__(self, authenticator, use_redirect=1):
2.8 + encoding = "utf-8"
2.9 +
2.10 + def __init__(self, authenticator, use_redirect=1, urlencoding=None):
2.11
2.12 """
2.13 Initialise the resource with an 'authenticator'.
2.14
2.15 - If the optional 'use_redirect' flag is set to 0, a confirmation screen is given
2.16 - instead of redirecting the user back to the original application.
2.17 + If the optional 'use_redirect' flag is set to 0, a confirmation screen
2.18 + is given instead of redirecting the user back to the original
2.19 + application.
2.20 +
2.21 + The optional 'urlencoding' parameter allows a special encoding to be
2.22 + used in producing the redirection path.
2.23 """
2.24
2.25 self.authenticator = authenticator
2.26 self.use_redirect = use_redirect
2.27 + self.urlencoding = urlencoding
2.28
2.29 def respond(self, trans):
2.30
2.31 "Respond using the transaction 'trans'."
2.32
2.33 - fields_path = trans.get_fields_from_path()
2.34 - fields_body = trans.get_fields_from_body()
2.35 + fields_path = trans.get_fields_from_path(self.urlencoding)
2.36 + fields_body = trans.get_fields_from_body(self.encoding)
2.37
2.38 # NOTE: Handle missing redirects better.
2.39
2.40 - if fields_body.has_key("redirect"):
2.41 - redirects = fields_body["redirect"]
2.42 - redirect = redirects[0]
2.43 - elif fields_path.has_key("redirect"):
2.44 - redirects = fields_path["redirect"]
2.45 - redirect = redirects[0]
2.46 + if fields_body.has_key("app"):
2.47 + apps = fields_body["app"]
2.48 + app = apps[0]
2.49 + elif fields_path.has_key("app"):
2.50 + apps = fields_path["app"]
2.51 + app = apps[0]
2.52 else:
2.53 - redirect = ""
2.54 + app = u""
2.55 +
2.56 + if fields_body.has_key("path"):
2.57 + paths = fields_body["path"]
2.58 + path = paths[0]
2.59 + elif fields_path.has_key("path"):
2.60 + paths = fields_path["path"]
2.61 + path = paths[0]
2.62 + else:
2.63 + path = u""
2.64 +
2.65 + if fields_body.has_key("qs"):
2.66 + qss = fields_body["qs"]
2.67 + qs = qss[0]
2.68 + elif fields_path.has_key("qs"):
2.69 + qss = fields_path["qs"]
2.70 + qs = qss[0]
2.71 + else:
2.72 + qs = u""
2.73
2.74 # Check for a submitted login form.
2.75
2.76 if fields_body.has_key("login"):
2.77 if self.authenticator.authenticate(trans):
2.78 - self._redirect(trans, redirect)
2.79 + self._redirect(trans, app, path, qs)
2.80 return
2.81
2.82 # Otherwise, show the login form.
2.83
2.84 - self._show_login(trans, redirect)
2.85 + self._show_login(trans, app, path, qs)
2.86 +
2.87 + def _redirect(self, trans, app, path, qs):
2.88
2.89 - def _redirect(self, trans, redirect):
2.90 -
2.91 - "Redirect the client using 'trans' and the given 'redirect' URL."
2.92 + """
2.93 + Redirect the client using 'trans' and the given 'app', 'path' and 'qs'
2.94 + details.
2.95 + """
2.96
2.97 if self.use_redirect:
2.98 - trans.set_header_value("Location", redirect)
2.99 + trans.set_header_value("Location", app + trans.encode_path(path, self.urlencoding) + qs)
2.100 trans.set_response_code(302) # was 307
2.101
2.102 # Show the success page anyway.
2.103
2.104 - self._show_success(trans, redirect)
2.105 + self._show_success(trans, app, path, qs)
2.106
2.107 - def _show_login(self, trans, redirect):
2.108 + def _show_login(self, trans, app, path, qs):
2.109
2.110 """
2.111 Writes a login screen using the transaction 'trans', including details of the
2.112 - 'redirect' URL which the client was attempting to access.
2.113 + 'app', 'path' and 'qs' which the client was attempting to access.
2.114 """
2.115
2.116 - trans.set_content_type(WebStack.Generic.ContentType("text/html"))
2.117 + trans.set_content_type(WebStack.Generic.ContentType("text/html", self.encoding))
2.118 out = trans.get_response_stream()
2.119 out.write("""
2.120 <html>
2.121 @@ -101,18 +129,20 @@
2.122 <p>Username: <input name="username" type="text" size="12"/></p>
2.123 <p>Password: <input name="password" type="text" size="12"/></p>
2.124 <p><input name="login" type="submit" value="Login"/></p>
2.125 - <input name="redirect" type="hidden" value="%s"/>
2.126 + <input name="app" type="hidden" value="%s"/>
2.127 + <input name="path" type="hidden" value="%s"/>
2.128 + <input name="qs" type="hidden" value="%s"/>
2.129 </form>
2.130 </body>
2.131 </html>
2.132 -""" % redirect)
2.133 +""" % (app, path, qs))
2.134
2.135 - def _show_success(self, trans, redirect):
2.136 + def _show_success(self, trans, app, path, qs):
2.137
2.138 # When authentication fails or is yet to take place, show the login
2.139 # screen.
2.140
2.141 - trans.set_content_type(WebStack.Generic.ContentType("text/html"))
2.142 + trans.set_content_type(WebStack.Generic.ContentType("text/html", self.encoding))
2.143 out = trans.get_response_stream()
2.144 out.write("""
2.145 <html>
2.146 @@ -121,16 +151,10 @@
2.147 </head>
2.148 <body>
2.149 <h1>Login Successful</h1>
2.150 - <p>Please proceed <a href="%s">to the application</a>.</p>
2.151 + <p>Please proceed <a href="%s%s%s">to the application</a>.</p>
2.152 </body>
2.153 </html>
2.154 -""" % redirect)
2.155 -
2.156 - def _decode(self, url):
2.157 -
2.158 - "Decode the given 'url' for redirection purposes."
2.159 -
2.160 - return url.replace("%3f", "?").replace("%26", "&")
2.161 +""" % (app, trans.encode_path(path, self.urlencoding), qs))
2.162
2.163 class LoginAuthenticator:
2.164
3.1 --- a/WebStack/Resources/LoginRedirect.py Thu Aug 25 18:20:19 2005 +0000
3.2 +++ b/WebStack/Resources/LoginRedirect.py Thu Aug 25 18:21:49 2005 +0000
3.3 @@ -30,23 +30,28 @@
3.4
3.5 def __init__(self, login_url, app_url, resource, authenticator, anonymous_parameter_name=None,
3.6 anonymous_username="anonymous", logout_parameter_name=None, logout_url="/",
3.7 - use_logout_redirect=1):
3.8 + use_logout_redirect=1, urlencoding=None):
3.9
3.10 """
3.11 - Initialise the resource with a 'login_url', an 'app_url' where the 'resource' for
3.12 - the application being protected should be reachable, and an 'authenticator'.
3.13 + Initialise the resource with a 'login_url', an 'app_url' where the
3.14 + 'resource' for the application being protected should be reachable, and
3.15 + an 'authenticator'.
3.16 +
3.17 + If the optional 'anonymous_parameter_name' is set, clients providing a
3.18 + parameter of that name in the URL will not be authenticated, but then
3.19 + such clients will get a predefined user identity associated with them,
3.20 + configurable using the optional 'anonymous_username'.
3.21
3.22 - If the optional 'anonymous_parameter_name' is set, clients providing a parameter
3.23 - of that name in the URL will not be authenticated, but then such clients will get
3.24 - a predefined user identity associated with them, configurable using the optional
3.25 - 'anonymous_username'.
3.26 + If the optional 'logout_parameter_name' is set, clients providing a
3.27 + parameter of that name in the URL will become logged out. After logging
3.28 + out, clients are redirected to a location which can be configured by the
3.29 + optional 'logout_url'.
3.30
3.31 - If the optional 'logout_parameter_name' is set, clients providing a parameter of
3.32 - that name in the URL will become logged out. After logging out, clients are
3.33 - redirected to a location which can be configured by the optional 'logout_url'.
3.34 + If the optional 'use_logout_redirect' flag is set to 0, a confirmation
3.35 + screen is given instead of redirecting the user to the 'logout_url'.
3.36
3.37 - If the optional 'use_logout_redirect' flag is set to 0, a confirmation screen is
3.38 - given instead of redirecting the user to the 'logout_url'.
3.39 + The optional 'urlencoding' parameter allows a special encoding to be
3.40 + used in producing the redirection path.
3.41 """
3.42
3.43 self.login_url = login_url
3.44 @@ -58,12 +63,13 @@
3.45 self.logout_parameter_name = logout_parameter_name
3.46 self.logout_url = logout_url
3.47 self.use_logout_redirect = use_logout_redirect
3.48 + self.urlencoding = urlencoding
3.49
3.50 def respond(self, trans):
3.51
3.52 "Respond using the given transaction 'trans'."
3.53
3.54 - fields_path = trans.get_fields_from_path()
3.55 + fields_path = trans.get_fields_from_path(self.urlencoding)
3.56
3.57 # Check for the logout parameter, if appropriate.
3.58
3.59 @@ -104,17 +110,19 @@
3.60
3.61 # Redirect to the login URL.
3.62
3.63 - trans.set_header_value("Location", "%s?redirect=%s%s" % (
3.64 - self.login_url, self.app_url, self._encode(trans.get_path()))
3.65 + path = trans.get_path_without_query(self.urlencoding)
3.66 + qs = trans.get_query_string()
3.67 + if qs:
3.68 + qs = "?" + qs
3.69 +
3.70 + trans.set_header_value("Location", "%s?app=%s&path=%s&qs=%s" % (
3.71 + self.login_url,
3.72 + trans.encode_path(self.app_url, self.urlencoding),
3.73 + trans.encode_path(path, self.urlencoding),
3.74 + trans.encode_path(qs, self.urlencoding))
3.75 )
3.76 trans.set_response_code(302) # was 307
3.77
3.78 - def _encode(self, url):
3.79 -
3.80 - "Encode the given 'url' for redirection purposes."
3.81 -
3.82 - return url.replace("?", "%3f").replace("&", "%26")
3.83 -
3.84 def _show_logout(self, trans, redirect):
3.85
3.86 """