# HG changeset patch # User paulb # Date 1202069084 0 # Node ID 55aed8b4c61f51c0a24c7dd079758fe00ceb756d # Parent 972ceefc7dfcbb5a18a9953c656460fc004ea587 [project @ 2008-02-03 20:04:44 by paulb] Updated encoding usage in the Web resources. Introduced support for all OpenID activities. diff -r 972ceefc7dfc -r 55aed8b4c61f XSLForms/Resources/OpenIDInitiation.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/XSLForms/Resources/OpenIDInitiation.py Sun Feb 03 20:04:44 2008 +0000 @@ -0,0 +1,210 @@ +#!/usr/bin/env python + +""" +OpenID initiation resources for XSLForms applications. These resources use +"root" attributes on transaction objects, and therefore should be defined within +the appropriate resources in site maps. + +Copyright (C) 2006, 2007, 2008 Paul Boddie + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU Lesser General Public License as published by the Free +Software Foundation; either version 3 of the License, or (at your option) any +later version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +details. + +You should have received a copy of the GNU Lesser General Public License along +with this program. If not, see . +""" + +from WebStack.Generic import ContentType, EndOfResponse +from WebStack.Resources.OpenIDInitiation import OpenIDInitiationUtils +from XSLForms.Resources.WebResources import XSLFormsResource + +class OpenIDInitiationResource(XSLFormsResource, OpenIDInitiationUtils): + + """ + An initiation screen resource which should be modified or subclassed to + define the following attributes: + + * resource_dir + * template_resources - including an "initiation" entry for the initiation + screen and a "success" entry for a screen + indicating successful redirection to a provider + (used when redirects are not in use) + * document_resources - including a "translations" entry + + The latter attribute is optional. + + The initiation template must define an "initiation" action, and provide a + document structure where the identity credentials can be found through this + class's 'path_to_identity_element' attribute (which can be overridden or + modified). Such a structure would be as follows for the default + configuration: + + + + The success template must provide a document structure where the location of + the application can be found through this class's 'path_to_success_element' + attribute (which can be overridden or modified). Such a structure would be + as follows for the default configuration: + + + """ + + path_to_initiation_element = "/initiation" + path_to_success_element = "/success" + + def __init__(self, openid_mode=None, use_redirect=1): + + """ + Initialise the resource. + + The optional 'openid_mode' parameter may be set to "checkid_immediate" + or "checkid_setup" (the default). + + If the optional 'use_redirect' flag is set to a false value (which is + not the default), a confirmation screen is given instead of immediately + redirecting the user to the OpenID provider. + + To get the root of the application, this resource needs an attribute on + the transaction called "root". + """ + + OpenIDInitiationUtils.__init__(self, openid_mode, use_redirect) + + def select_activity(self, trans, form): + form.set_activity("initiation") + + def respond_to_input(self, trans, form): + parameters = form.get_parameters() + + if parameters.has_key("app"): + app = parameters["app"] + else: + app = trans.get_fields_from_path().get("app", [""])[0] + + if parameters.has_key("initiate"): + self.check_identity(trans, form, app) + # The above method does not return. + + # Otherwise, show the initiation form. + + self.show_initiation(trans, form, app) + + # Methods called by the OpenID logic. + + def check_identity(self, trans, form, app): + + """ + Check the identity found through 'trans' and 'fields', using 'app' and + discovered information about the identity to redirect to the provider. + """ + + doc = form.get_document() + parameters = form.get_parameters() + + initelem = doc.xpath(self.path_to_initiation_element)[0] + identity = initelem.getAttribute("identity") or parameters.get("identity", [""])[0] + claimed_identifier, provider, local_identifier = self.get_provider_url(trans, identity) + + if provider is not None: + self.redirect_to_provider(trans, form, app, claimed_identifier, provider, local_identifier) + + def redirect_to_provider(self, trans, form, app, claimed_identifier, provider, local_identifier): + + """ + Redirect the client using 'trans', 'form' and the given 'app', + 'claimed_identifier', 'provider' and 'local_identifier' details. + + See: + http://openid.net/specs/openid-authentication-2_0-12.html#rfc.section.5.2 + http://openid.net/specs/openid-authentication-2_0-12.html#rfc.section.9 + """ + + url = self.get_redirect_url(trans, app, claimed_identifier, provider, local_identifier) + + # Show the success page anyway. + # Offer a POST-based form for redirection. + + self.show_success(trans, form, provider, app, claimed_identifier, local_identifier) + + # Redirect to the OpenID provider URL. + + if self.use_redirect: + trans.redirect(url) + else: + raise WebStack.Generic.EndOfResponse + + def show_initiation(self, trans, form, app): + + """ + Writes a initiation screen using the transaction 'trans' and 'form', + including details of the 'app' which the client was attempting to + access. + """ + + doc = form.get_document() + parameters = form.get_parameters() + + initelem = doc.xpath(self.path_to_initiation_element)[0] + identity = initelem.getAttribute("identity") or parameters.get("identity", [""])[0] + app = initelem.getAttribute("app") or parameters.get("app", [""])[0] + + initelem = doc.xpath(self.path_to_initiation_element)[0] + initelem.setAttribute("identity", identity) + initelem.setAttribute("app", app) + + def show_success(self, trans, form, provider, app, claimed_identifier, local_identifier): + + """ + Writes a success screen using the transaction 'trans' and 'form', + including details of the OpenID 'provider', the 'app' URL, + 'claimed_identifier' and 'local_identifier'. + """ + + # Switch to the success activity. + + form.set_activity("success") + doc = form.new_instance("success") + successelem = doc.xpath(self.path_to_success_element)[0] + successelem.setAttribute("provider", provider) + successelem.setAttribute("ns", self.openid_ns) + successelem.setAttribute("mode", self.openid_mode) + successelem.setAttribute("return_to", app) + successelem.setAttribute("claimed_id", claimed_identifier) + successelem.setAttribute("identity", local_identifier) + + form.set_document(doc) + + # Output preparation. + + def create_output(self, trans, form): + attributes = trans.get_attributes() + + stylesheet_parameters = {} + references = {} + + # Set up translations. + + if self.document_resources.has_key("translations"): + translations_xml = self.prepare_document("translations") + + try: + language = trans.get_content_languages()[0] + except IndexError: + language = "en" + + stylesheet_parameters["locale"] = language + references["translations"] = translations_xml + + # Complete the response. + + stylesheet_parameters["root"] = attributes["root"] + XSLFormsResource.create_output(self, trans, form, stylesheet_parameters=stylesheet_parameters, references=references) + +# vim: tabstop=4 expandtab shiftwidth=4 diff -r 972ceefc7dfc -r 55aed8b4c61f XSLForms/Resources/OpenIDLogin.py --- a/XSLForms/Resources/OpenIDLogin.py Sun Feb 03 00:13:42 2008 +0000 +++ b/XSLForms/Resources/OpenIDLogin.py Sun Feb 03 20:04:44 2008 +0000 @@ -1,7 +1,7 @@ #!/usr/bin/env python """ -OpenID Login resources for XSLForms applications. These resources use "root" +OpenID login resources for XSLForms applications. These resources use "root" attributes on transaction objects, and therefore should be defined within the appropriate resources in site maps. @@ -22,11 +22,9 @@ """ from WebStack.Generic import ContentType, EndOfResponse -from WebStack.Resources.OpenIDLogin import OpenIDLoginUtils +from WebStack.Resources.OpenIDLogin import OpenIDLoginUtils, Authenticator from XSLForms.Resources.WebResources import XSLFormsResource -import WebStack.Resources.OpenIDRedirect # LoginRedirectResource - class OpenIDLoginResource(XSLFormsResource, OpenIDLoginUtils): """ @@ -76,9 +74,7 @@ the transaction called "root". """ - OpenIDLoginUtils.__init__(self, associations, use_redirect) - self.app_url = app_url - self.authenticator = authenticator + OpenIDLoginUtils.__init__(self, app_url, authenticator, associations, use_redirect) def select_activity(self, trans, form): form.set_activity("login") diff -r 972ceefc7dfc -r 55aed8b4c61f XSLForms/Resources/OpenIDRedirect.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/XSLForms/Resources/OpenIDRedirect.py Sun Feb 03 20:04:44 2008 +0000 @@ -0,0 +1,59 @@ +#!/usr/bin/env python + +""" +OpenID redirection resources for XSLForms applications. These resources use +"root" attributes on transaction objects, and therefore should be defined within +the appropriate resources in site maps. + +Copyright (C) 2006, 2007, 2008 Paul Boddie + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU Lesser General Public License as published by the Free +Software Foundation; either version 3 of the License, or (at your option) any +later version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +details. + +You should have received a copy of the GNU Lesser General Public License along +with this program. If not, see . +""" + +import WebStack.Resources.OpenIDRedirect # OpenIDRedirectResource + +OpenIDRedirectAuthenticator = WebStack.Resources.OpenIDRedirect.OpenIDRedirectAuthenticator + +class OpenIDRedirectResource(WebStack.Resources.OpenIDRedirect.OpenIDRedirectResource): + + "A redirect resource which uses dynamic knowledge about the URL space." + + def __init__(self, host, path_to_login, *args, **kw): + + """ + Initialise the resource with the 'host', 'path_to_login' (the path from + the root of the application to the login screen), and other + LoginRedirectResource details. + + To get the root of the application, this resource needs an attribute on + the transaction called "root". + + Examples of 'path_to_login' with "root" attribute and result: + + "login", "/" -> "/login" + "login", "/app/" -> "/app/login" + "app/login", "/" -> "/app/login" + """ + + self.host = host + self.path_to_login = path_to_login + WebStack.Resources.OpenIDRedirect.OpenIDRedirectResource.__init__(self, *args, **kw) + + def get_app_url(self, trans): + return self.host + + def get_login_url(self, trans): + return self.host + trans.get_attributes()["root"] + self.path_to_login + +# vim: tabstop=4 expandtab shiftwidth=4 diff -r 972ceefc7dfc -r 55aed8b4c61f XSLForms/Resources/PyQtWebResources.py --- a/XSLForms/Resources/PyQtWebResources.py Sun Feb 03 00:13:42 2008 +0000 +++ b/XSLForms/Resources/PyQtWebResources.py Sun Feb 03 20:04:44 2008 +0000 @@ -208,7 +208,10 @@ # Output is produced. - trans.set_content_type(WebStack.Generic.ContentType("application/xhtml+xml", self.encoding)) + attributes = trans.get_attributes() + encoding = attributes.get("encoding") or self.encoding or trans.default_charset + + trans.set_content_type(WebStack.Generic.ContentType("application/xhtml+xml", encoding)) design_xsl = self.prepare_output(self.default_design) self.send_output(trans, [design_xsl], doc._node) diff -r 972ceefc7dfc -r 55aed8b4c61f XSLForms/Resources/WebResources.py --- a/XSLForms/Resources/WebResources.py Sun Feb 03 00:13:42 2008 +0000 +++ b/XSLForms/Resources/WebResources.py Sun Feb 03 20:04:44 2008 +0000 @@ -418,7 +418,7 @@ # Start the response. - encoding = attributes.get("encoding") or self.encoding + encoding = attributes.get("encoding") or self.encoding or trans.default_charset content_type = content_type or WebStack.Generic.ContentType("application/xhtml+xml", encoding) trans.set_content_type(content_type)