From acd9aeca8e697b6d1f8f7ac29d7e3afac07b2e8a Mon Sep 17 00:00:00 2001 From: Evgeny Fadeev Date: Sat, 27 Mar 2010 16:06:23 -0400 Subject: removed authentication module to be replaced with a dedicated app, also switched to table layout for openid signin template temporarily so that it works on IE7 and maybe earlier --- TODO | 16 - TODO.rst | 22 + forum/authentication/__init__.py | 27 - forum/authentication/base.py | 44 -- forum/authentication/forms.py | 73 --- .../default/media/jquery-openid/jquery.openid.js | 24 +- forum/skins/default/media/jquery-openid/openid.css | 14 +- .../default/templates/auth/auth_settings.html | 35 -- forum/skins/default/templates/auth/complete.html | 95 ---- .../default/templates/auth/email_validation.html | 20 - forum/skins/default/templates/auth/signin.html | 165 ------ forum/skins/default/templates/auth/signup.html | 32 -- .../default/templates/auth/temp_login_email.html | 20 - .../default/templates/auth/temp_login_request.html | 28 - .../skins/default/templates/authopenid/signin.html | 92 ++-- forum/views/auth.py | 359 ------------- forum_modules/facebookauth/__init__.py | 0 forum_modules/facebookauth/authentication.py | 85 --- forum_modules/facebookauth/settings.py | 3 - forum_modules/facebookauth/templates/button.html | 38 -- .../facebookauth/templates/xd_receiver.html | 1 - forum_modules/facebookauth/urls.py | 9 - forum_modules/facebookauth/views.py | 11 - forum_modules/localauth/__init__.py | 0 forum_modules/localauth/authentication.py | 18 - forum_modules/localauth/forms.py | 77 --- forum_modules/localauth/templates/loginform.html | 31 -- forum_modules/localauth/urls.py | 8 - forum_modules/localauth/views.py | 31 -- forum_modules/oauthauth/__init__.py | 0 forum_modules/oauthauth/authentication.py | 41 -- forum_modules/oauthauth/consumer.py | 87 --- forum_modules/oauthauth/lib/__init__.py | 0 forum_modules/oauthauth/lib/oauth.py | 594 --------------------- forum_modules/oauthauth/settings.py | 3 - forum_modules/openidauth/__init__.py | 0 forum_modules/openidauth/authentication.py | 196 ------- forum_modules/openidauth/consumer.py | 112 ---- forum_modules/openidauth/models.py | 26 - forum_modules/openidauth/settings.py | 9 - forum_modules/openidauth/store.py | 79 --- forum_modules/openidauth/templates/openidurl.html | 20 - 42 files changed, 91 insertions(+), 2454 deletions(-) delete mode 100644 TODO create mode 100644 TODO.rst delete mode 100755 forum/authentication/__init__.py delete mode 100755 forum/authentication/base.py delete mode 100755 forum/authentication/forms.py delete mode 100755 forum/skins/default/templates/auth/auth_settings.html delete mode 100755 forum/skins/default/templates/auth/complete.html delete mode 100755 forum/skins/default/templates/auth/email_validation.html delete mode 100755 forum/skins/default/templates/auth/signin.html delete mode 100755 forum/skins/default/templates/auth/signup.html delete mode 100755 forum/skins/default/templates/auth/temp_login_email.html delete mode 100755 forum/skins/default/templates/auth/temp_login_request.html delete mode 100644 forum/views/auth.py delete mode 100755 forum_modules/facebookauth/__init__.py delete mode 100755 forum_modules/facebookauth/authentication.py delete mode 100755 forum_modules/facebookauth/settings.py delete mode 100755 forum_modules/facebookauth/templates/button.html delete mode 100755 forum_modules/facebookauth/templates/xd_receiver.html delete mode 100755 forum_modules/facebookauth/urls.py delete mode 100755 forum_modules/facebookauth/views.py delete mode 100755 forum_modules/localauth/__init__.py delete mode 100755 forum_modules/localauth/authentication.py delete mode 100755 forum_modules/localauth/forms.py delete mode 100755 forum_modules/localauth/templates/loginform.html delete mode 100755 forum_modules/localauth/urls.py delete mode 100755 forum_modules/localauth/views.py delete mode 100755 forum_modules/oauthauth/__init__.py delete mode 100755 forum_modules/oauthauth/authentication.py delete mode 100755 forum_modules/oauthauth/consumer.py delete mode 100755 forum_modules/oauthauth/lib/__init__.py delete mode 100755 forum_modules/oauthauth/lib/oauth.py delete mode 100755 forum_modules/oauthauth/settings.py delete mode 100755 forum_modules/openidauth/__init__.py delete mode 100755 forum_modules/openidauth/authentication.py delete mode 100755 forum_modules/openidauth/consumer.py delete mode 100755 forum_modules/openidauth/models.py delete mode 100755 forum_modules/openidauth/settings.py delete mode 100755 forum_modules/openidauth/store.py delete mode 100755 forum_modules/openidauth/templates/openidurl.html diff --git a/TODO b/TODO deleted file mode 100644 index d6a4ced1..00000000 --- a/TODO +++ /dev/null @@ -1,16 +0,0 @@ -note: there is also WISH_LIST. Here is only stuff that will be done soon. - -Cleanups -========== -* remove usage of EXTERNAL_LEGACY_LOGIN -* remove forum_modules and replace them with normal Python imports -* pack dependency apps inside 'forum' directory - -Features -=========== -* new login system, please see http://groups.google.com/group/askbot/browse_thread/thread/1916dfcf666dd56c -* forum admin interface, some badge configuration - -Development environment -========================== -* set up environment for closure developmen diff --git a/TODO.rst b/TODO.rst new file mode 100644 index 00000000..6ad2acd3 --- /dev/null +++ b/TODO.rst @@ -0,0 +1,22 @@ +note: there is also WISH_LIST. Here is only stuff that will be done soon. + +Site looks +=========== +* make links within posts blue so that they are visible + +Code Cleanups +============== +* remove usage of EXTERNAL_LEGACY_LOGIN +* remove forum_modules and replace them with normal Python imports +* pack dependency apps inside 'forum' directory + +Features +=========== +* new login system, please see + http://groups.google.com/group/askbot/browse_thread/thread/1916dfcf666dd56c + on a separate branch multi-auth-app, then merge +* forum admin interface, some badge configuration + +Development environment +========================== +* set up environment for closure development diff --git a/forum/authentication/__init__.py b/forum/authentication/__init__.py deleted file mode 100755 index 75099303..00000000 --- a/forum/authentication/__init__.py +++ /dev/null @@ -1,27 +0,0 @@ -import re -from forum.modules import get_modules_script_classes -from forum.authentication.base import AuthenticationConsumer, ConsumerTemplateContext - -class ConsumerAndContext(): - def __init__(self, id, consumer, context): - self.id = id - self.consumer = consumer() - - context.id = id #add extra field to context - self.context = context - -consumers = dict([ - (re.sub('AuthConsumer$', '', name).lower(), cls) for name, cls - in get_modules_script_classes('authentication', AuthenticationConsumer).items() - if not re.search('AbstractAuthConsumer$', name) - ]) - -contexts = dict([ - (re.sub('AuthContext$', '', name).lower(), cls) for name, cls - in get_modules_script_classes('authentication', ConsumerTemplateContext).items() - ]) - -AUTH_PROVIDERS = dict([ - (name, ConsumerAndContext(name, consumers[name], contexts[name])) for name in consumers.keys() - if name in contexts - ]) diff --git a/forum/authentication/base.py b/forum/authentication/base.py deleted file mode 100755 index 99005866..00000000 --- a/forum/authentication/base.py +++ /dev/null @@ -1,44 +0,0 @@ - -class AuthenticationConsumer(object): - - def prepare_authentication_request(self, request, redirect_to): - raise NotImplementedError() - - def process_authentication_request(self, response): - raise NotImplementedError() - - def get_user_data(self, key): - raise NotImplementedError() - - -class ConsumerTemplateContext(object): - """ - Class that provides information about a certain authentication provider context in the signin page. - - class attributes: - - mode - one of BIGICON, SMALLICON, FORM - - human_name - the human readable name of the provider - - extra_js - some providers require us to load extra javascript on the signin page for them to work, - this is the place to add those files in the form of a list - - extra_css - same as extra_js but for css files - """ - mode = '' - weight = 500 - human_name = '' - extra_js = [] - extra_css = [] - show_to_logged_in_user = True - - @classmethod - def readable_key(cls, key): - return key.key - -class InvalidAuthentication(Exception): - def __init__(self, message): - self.message = message - - \ No newline at end of file diff --git a/forum/authentication/forms.py b/forum/authentication/forms.py deleted file mode 100755 index 24e76c08..00000000 --- a/forum/authentication/forms.py +++ /dev/null @@ -1,73 +0,0 @@ -from forum.utils.forms import NextUrlField, UserNameField, UserEmailField, SetPasswordForm -from forum.models import EmailFeedSetting, Question, User -from django.contrib.contenttypes.models import ContentType -from django.utils.translation import ugettext as _ -from django.utils.safestring import mark_safe -from django import forms -from forum.forms import EditUserEmailFeedsForm -import logging - -class SimpleRegistrationForm(forms.Form): - next = NextUrlField() - username = UserNameField() - email = UserEmailField() - -class TemporaryLoginRequestForm(forms.Form): - def __init__(self, data=None): - super(TemporaryLoginRequestForm, self).__init__(data) - self.user_cache = None - - email = forms.EmailField( - required=True, - label=_("Your account email"), - error_messages={ - 'required': _("You cannot leave this field blank"), - 'invalid': _('please enter a valid email address'), - } - ) - - def clean_email(self): - try: - user = User.objects.get(email=self.cleaned_data['email']) - except: - raise forms.ValidationError(_("Sorry, but this email is not on our database.")) - - self.user_cache = user - return self.cleaned_data['email'] - - -class SimpleEmailSubscribeForm(forms.Form): - SIMPLE_SUBSCRIBE_CHOICES = ( - ('y',_('okay, let\'s try!')), - ('n',_('no community email please, thanks')) - ) - subscribe = forms.ChoiceField(widget=forms.widgets.RadioSelect(), \ - error_messages={'required':_('please choose one of the options above')}, - choices=SIMPLE_SUBSCRIBE_CHOICES) - - def save(self,user=None): - EFF = EditUserEmailFeedsForm - if self.cleaned_data['subscribe'] == 'y': - email_settings_form = EFF() - logging.debug('%s wants to subscribe' % user.username) - else: - email_settings_form = EFF(initial=EFF.NO_EMAIL_INITIAL) - email_settings_form.save(user,save_unbound=True) - -class ChangePasswordForm(SetPasswordForm): - """ change password form """ - oldpw = forms.CharField(widget=forms.PasswordInput(attrs={'class':'required'}), - label=mark_safe(_('Current password'))) - - def __init__(self, data=None, user=None, *args, **kwargs): - if user is None: - raise TypeError("Keyword argument 'user' must be supplied") - super(ChangePasswordForm, self).__init__(data, *args, **kwargs) - self.user = user - - def clean_oldpw(self): - """ test old password """ - if not self.user.check_password(self.cleaned_data['oldpw']): - raise forms.ValidationError(_("Old password is incorrect. \ - Please enter the correct password.")) - return self.cleaned_data['oldpw'] diff --git a/forum/skins/default/media/jquery-openid/jquery.openid.js b/forum/skins/default/media/jquery-openid/jquery.openid.js index 8d1cd204..eae7b3ea 100755 --- a/forum/skins/default/media/jquery-openid/jquery.openid.js +++ b/forum/skins/default/media/jquery-openid/jquery.openid.js @@ -36,7 +36,7 @@ $.fn.openid = function() { }; var local = function() { var $li = $(this); - $('#openid_form .providers li').removeClass('highlight'); + $('#openid_form .providers td').removeClass('highlight'); $li.addClass('highlight'); $usrfs.hide(); $idfs.hide(); @@ -47,19 +47,19 @@ $.fn.openid = function() { var direct = function() { var $li = $(this); - $('#openid_form .providers li').removeClass('highlight'); + $('#openid_form .providers td').removeClass('highlight'); $li.addClass('highlight'); $usrfs.fadeOut('slow'); $localfs.fadeOut('slow'); $idfs.fadeOut('slow'); - $id.val($this.find("li.highlight span").text()); + $id.val($this.find("td.highlight span").text()); setTimeout(function(){$('#bsignin').click();},1000); return false; }; var openid = function() { var $li = $(this); - $('#openid_form .providers li').removeClass('highlight'); + $('#openid_form .providers td').removeClass('highlight'); $li.addClass('highlight'); $usrfs.hide(); $localfs.hide(); @@ -71,7 +71,7 @@ $.fn.openid = function() { var username = function() { var $li = $(this); - $('#openid_form .providers li').removeClass('highlight'); + $('#openid_form .providers td').removeClass('highlight'); $li.addClass('highlight'); $idfs.hide(); $localfs.hide(); @@ -84,10 +84,10 @@ $.fn.openid = function() { return false; }; - $this.find('li.local').click(local); - $this.find('li.direct').click(direct); - $this.find('li.openid').click(openid); - $this.find('li.username').click(username); + $this.find('td.local').click(local); + $this.find('td.direct').click(direct); + $this.find('td.openid').click(openid); + $this.find('td.username').click(username); $id.keypress(function(e) { if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) { return submitid(); @@ -98,12 +98,12 @@ $.fn.openid = function() { return submitusr(); } }); - $this.find('li span').hide(); - $this.find('li').css('line-height', 0).css('cursor', 'pointer'); + $this.find('td span').hide(); + $this.find('td').css('line-height', 0).css('cursor', 'pointer'); $usrfs.hide(); $idfs.hide(); $localfs.hide(); - $this.find('li:eq(0)').click(); + $this.find('td:eq(0)').click(); return this; }; diff --git a/forum/skins/default/media/jquery-openid/openid.css b/forum/skins/default/media/jquery-openid/openid.css index 1b7aaf82..307d5624 100755 --- a/forum/skins/default/media/jquery-openid/openid.css +++ b/forum/skins/default/media/jquery-openid/openid.css @@ -1,7 +1,7 @@ fieldset { border-style:none; } img {border-style:none;} -.logo_box {display:inline-block;float:left;width:90px;height:40px;background:white;border:1px solid #dddddd;} +.logo_box {width:90px;height:40px;background:white;border:1px solid #dddddd;} .openid_box img {margin-top:6px;} .aol_box img {margin-top:6px;} .yahoo_box img {margin-top:13px;} @@ -9,13 +9,11 @@ img {border-style:none;} .local_login_box img {margin-top:2px;margin-left:-3px;} form.openid ul{ margin:0;padding:0;text-align:center; list-style-type:none; display:block;} -form.openid ul li {float:left; padding:4px;display:inline-block;} -form.openid ul li div {display:inline-block;} +form.openid ul li {padding:4px;} form.openid ul li span {padding:0 1em 0 3px} form.openid ul li.first_tiny_li {clear:left;} form.openid fieldset {clear:both;padding:10px 0px 0px 0px;} form.openid div+fieldset {display:none} -form.openid label {display:block; font-weight:bold;} input[name=openid_username] {width:8em} input[name=openid_identifier] {width:18em} form.openid ul li.highlight { -moz-border-radius:4px; -webkit-border-radius:4px; background-color: #FD6} @@ -24,7 +22,6 @@ form.openid fieldset div { -webkit-border-radius:4px; background: #DCDCDC; padding:10px; - display:inline-block; float:left; } form.openid p {margin-bottom:4px;} @@ -67,9 +64,16 @@ form.openid ul.errorlist li { float: none; color:blue; } +ul.providers { + clear:left; + float:left; +} #openid_small_providers li { margin-top:4px; } #openid_small_providers li.facebook { margin-top:0px; } +ul.providers { + display: block; +} diff --git a/forum/skins/default/templates/auth/auth_settings.html b/forum/skins/default/templates/auth/auth_settings.html deleted file mode 100755 index 051fb6ba..00000000 --- a/forum/skins/default/templates/auth/auth_settings.html +++ /dev/null @@ -1,35 +0,0 @@ -{% extends "base.html" %} - -{% load i18n %} -{% block head %}{% endblock %} -{% block title %}{% spaceless %}{% trans "Authentication settings" %}{% endspaceless %}{% endblock %} -{% block content %} -
{% trans "Authentication settings" %}
-{% if auth_keys %} -

{% blocktrans %}These are the external authentication providers currently associated with your account.{% endblocktrans %}

-
- {% for key in auth_keys %} -

{{ key.name }} ({% trans "remove" %})

- {% endfor %} -
-{% endif %} -{% if not auth_keys %} -

{% blocktrans %}You currently have no external authentication provider associated with your account.{% endblocktrans %}

-{% endif %} - -{% if has_password %} -

{% blocktrans %}This is where you can change your password. Make sure you remember it!{% endblocktrans %}

-{% endif %} -{% if not has_password %} -

{% blocktrans %}You can set up a password for your account, so you can login using standard username and password!{% endblocktrans %}

-{% endif %} -
-
-
    - {{form.as_ul}} -
-
-
-
-{% endblock %} - diff --git a/forum/skins/default/templates/auth/complete.html b/forum/skins/default/templates/auth/complete.html deleted file mode 100755 index cb2dc5aa..00000000 --- a/forum/skins/default/templates/auth/complete.html +++ /dev/null @@ -1,95 +0,0 @@ -{% extends "base_content.html" %} - -{% load i18n %} -{% block head %}{% endblock %} -{% block title %}{% spaceless %}{% trans "Connect your OpenID with this site" %}{% endspaceless %}{% endblock %} -{% block content %} -
- {% trans "Connect your OpenID with your account on this site" %} -
-
-
- {% trans "You are here for the first time with " %}{{ provider }} - {% trans "Please create your screen name and save your email address. Saved email address will let you subscribe for the updates on the most interesting questions and will be used to create and retrieve your unique avatar image. " %} -
-

{% trans "This account already exists, please use another." %}

-
- - {% if form1.errors %} - - {% endif %} - {% comment %} - {% if form2.errors %} -
- {% trans "Sorry, looks like we have some errors:" %}
- -
- {% endif %} - {% endcomment %} - -
-
- {{ form1.next }} -
- - {% if form1.username.errors %} -

{{ form1.username.errors|join:", " }}

- {% endif %} - {{ form1.username }} -
-
- - {% if form1.email.errors %} -

{{ form1.email.errors|join:", " }}

- {% endif %} - {{ form1.email }} -
-

{% trans "receive updates motivational blurb" %}

-
- {{email_feeds_form.subscribe}} - {% if email_feeds_form.errors %} -

{% trans "please select one of the options above" %}

- {% endif %} -
-

{% trans "Tag filter tool will be your right panel, once you log in." %}

-
-
-
- {% comment %} - {% if form2 %} - - {% endif %} - {% endcomment %} -{% endblock %} - diff --git a/forum/skins/default/templates/auth/email_validation.html b/forum/skins/default/templates/auth/email_validation.html deleted file mode 100755 index a4126a69..00000000 --- a/forum/skins/default/templates/auth/email_validation.html +++ /dev/null @@ -1,20 +0,0 @@ -{% extends "email_base.html" %} -{% load i18n %} -{% load extra_tags %} - -{% block content %} -

{% trans "Greetings from the Q&A forum" %},

- -

{% trans "To make use of the Forum, please follow the link below:" %}

- - {% fullurl auth_validate_email user=user.id,code=validation_code %} - -

{% trans "Following the link above will help us verify your email address." %}

- -

{% blocktrans %}If you beleive that this message was sent in mistake - - no further action is needed. Just ingore this email, we apologize - for any inconvenience{% endblocktrans %}

- -

{% blocktrans %}Sincerely,
- Forum Administrator{% endblocktrans %}

-{% endblock %} diff --git a/forum/skins/default/templates/auth/signin.html b/forum/skins/default/templates/auth/signin.html deleted file mode 100755 index 78e6c76d..00000000 --- a/forum/skins/default/templates/auth/signin.html +++ /dev/null @@ -1,165 +0,0 @@ -{% extends "base.html" %} - -{% load i18n %} -{% load extra_tags %} - -{% block forejs %} - - {% for provider in all_providers %} - {% for location in provider.extra_css %} - - {% endfor %} - {% endfor %} -{% endblock %} - -{% block content %} - {% for provider in all_providers %} - {% if provider.pre_code %} - {{ provider.pre_code|safe }} - {% endif %} - {% endfor %} -
- {% trans "User login" %} -
- {% if msg %} -

{{ msg }}

- {% endif %} - -
- {% trans "Click to sign in through any of these services." %} -
- {% if request.user.is_anonymous %} -
- - {% trans "Take the oppurtunity to validate my email next to the external provider I choose." %} -
- {% endif %} -
- {% for provider in bigicon_providers %} - - {% endfor %} -
-
- {% for provider in smallicon_providers %} - - {% endfor %} -
-
-
- -
- {% for provider in stackitem_providers %} -

{% trans 'Or...' %}

-
- {% include provider.stack_item_template %} - -
- {% endfor %} -

{% trans 'Or...' %}

-
- {% trans 'Click' %} here {% trans "if you're having troubles signing in." %} -
- - -{% endblock %} - -{% block sidebar %} -
-

{% trans "Why use OpenID?" %}

- - -
-{% endblock%} \ No newline at end of file diff --git a/forum/skins/default/templates/auth/signup.html b/forum/skins/default/templates/auth/signup.html deleted file mode 100755 index ac5eb241..00000000 --- a/forum/skins/default/templates/auth/signup.html +++ /dev/null @@ -1,32 +0,0 @@ -{% extends "base_content.html" %} - -{% load i18n %} -{% block title %}{% spaceless %}{% trans "Signup" %}{% endspaceless %}{% endblock %} - -{% block content %} -
- {% trans "Create login name and password" %} -
-

{% trans "Traditional signup info" %}

-
- -

{% trans "receive updates motivational blurb" %}

-
- {{ email_feeds_form.subscribe }} - {% if email_feeds_form.errors %} -

{% trans "please select one of the options above" %}

- {% endif %} -
- {% comment %} - {{form.recaptcha}}{% endcomment %} - -
-{% endblock %} - diff --git a/forum/skins/default/templates/auth/temp_login_email.html b/forum/skins/default/templates/auth/temp_login_email.html deleted file mode 100755 index 063608fe..00000000 --- a/forum/skins/default/templates/auth/temp_login_email.html +++ /dev/null @@ -1,20 +0,0 @@ -{% extends "email_base.html" %} -{% load i18n %} -{% load extra_tags %} - -{% block content %} -

{% trans "Greetings from the Q&A forum" %},

- -

{% trans "You're seeing this because someone requested a temporary login link" %}

- - {% fullurl auth_tempsignin user=user.id,code=temp_login_code %} - -

{% trans "Following the link above will give you access to your account." %}

- -

{% blocktrans %}If you beleive that this message was sent in mistake - - no further action is needed. Just ingore this email, we apologize - for any inconvenience{% endblocktrans %}

- -

{% blocktrans %}Sincerely,
- Forum Administrator{% endblocktrans %}

-{% endblock %} diff --git a/forum/skins/default/templates/auth/temp_login_request.html b/forum/skins/default/templates/auth/temp_login_request.html deleted file mode 100755 index 772f18fb..00000000 --- a/forum/skins/default/templates/auth/temp_login_request.html +++ /dev/null @@ -1,28 +0,0 @@ -{% extends "base.html" %} - -{% load i18n %} -{% block head %}{% endblock %} -{% block title %}{% spaceless %}{% trans "Request temporary login key" %}{% endspaceless %}{% endblock %} -{% block content %} -
{% trans "Account: request temporary login key" %}
-

{% blocktrans %} - If you're experiencing problems accessing your account, or if you forgot your password, - here you can request a temporary login key. Fill out your account email and we'll send you a temporary access link that - will enable you to access your account. This token is valid only once and for a limited period of time. - {% endblocktrans %}

-
- {% if form.errors %} - - {% endif %} -
-
    - {{form.as_ul}} -
-
-
-
-{% endblock %} \ No newline at end of file diff --git a/forum/skins/default/templates/authopenid/signin.html b/forum/skins/default/templates/authopenid/signin.html index 04e58255..66ef2f78 100755 --- a/forum/skins/default/templates/authopenid/signin.html +++ b/forum/skins/default/templates/authopenid/signin.html @@ -38,10 +38,10 @@ {% endif %}
-
+
{% trans "Click to sign in through any of these services." %}
-
    + {% comment %}
  • {% endcomment %} -
  • -
    - icon - http://username -
    -
  • -
  • -
    - iconhttps://www.google.com/accounts/o8/id -
    -
  • -
  • -
    - iconhttp://yahoo.com/ -
    -
  • -
  • -
    - iconhttp://openid.aol.com/username -
    -
  • - -
      +
    + + + + + +
    +
    + icon + http://username +
    +
    +
    + iconhttps://www.google.com/accounts/o8/id +
    +
    +
    + iconhttp://yahoo.com/ +
    +
    +
    + iconhttp://openid.aol.com/username +
    +
    + +