import cgi
import openid
import urllib
import os
import oauth.oauth as oauth

import common

from openid.consumer import consumer
from openid.extensions import ax

'''
' Class: Implementacja notacji kropki
' Description: Dodaje do słownika mechanizm obsługi notacji kropki
'''
class dotdict(dict):
    def __getattr__(self, attr):
        return self.get(attr, None)
    __setattr__= dict.__setitem__
    __delattr__= dict.__delitem__

'''
' Function: Main
' Description: Kończy proces uwierzytelniania OpenID i wyświetla wyniki
'''
def main():
    # tworzy bazowy obiekt konsumenta
    oidconsumer = consumer.Consumer({}, None)
    
    # wyświetla typ treści strony
    print 'Content-Type: text/plain'
    print ''
    
    # wyodrębnia i umieszcza w słowniku parametry łańcucha zapytania
    params = {}
    string_split = [s for s in os.environ['QUERY_STRING'].split('&') if s]
    for item in string_split:
        key,value = item.split('=')
        if key != 'domain_unverified':
            params[key] = urllib.unquote(value)
    
    # kończy proces uwierzytelniania OpenID i uzyskuje identyfikator
    info = oidconsumer.complete(params, common.return_to)
    display_identifier = info.getDisplayIdentifier()
    
    # buduje obiekt odpowiedzi rozszerzenia attribute exchange
    ax_response = ax.FetchResponse.fromSuccessResponse(info)
    if ax_response:
        ax_items = {
            'email': ax_response.get('http://axschema.org/contact/email'),
            'picture': ax_response.get('http://axschema.org/media/image/default')
        }
        
        # wyświetla obiekt odpowiedzi rozszerzenia attribute exchange
        print 'Obiekt odpowiedzi rozszerzenia Attribute Exchange:'
        print ax_items
    
    # wyświetla identyfikator wyświetlania openid
    print '\n\nIdentyfikator wyświetlania OpenID: \n' + display_identifier
    
    # sprawdza status zwrócony przez openid
    if info.status == consumer.FAILURE and display_identifier:
        message = "\n\nOdpowiedź OpenID:\nWeryfikacja zakończona niepowodzeniem"
    elif info.status == consumer.CANCEL:
        message = "\n\nOdpowiedź OpenID:\nWeryfikacja anulowana"
    elif info.status == consumer.SETUP_NEEDED:
        message = "\n\nOdpowiedź OpenID:\nPotrzebna konfiguracja"
    elif info.status == consumer.SUCCESS:
        message = "\n\nOdpowiedź OpenID:\nSukces"
        
        # konstruuje bazowy obiekt konsumenta z kluczami oauth i podpisem (przy użyciu algorytmu HMAC-SHA1)
        base_consumer = oauth.OAuthConsumer(common.consumer_key, common.consumer_secret)
        signature_method_hmac_sha1 = oauth.OAuthSignatureMethod_HMAC_SHA1()
        
        # konstruuje słownik wstępnie autoryzowanego tokenu żądania i pustego klucza tajnego, które zostaną wymienione na klucz dostępu
        req_token = dotdict({'key': params['openid.oauth.request_token'], 'secret': ''})
        
        # tworzy nowe żądanie oauth i podpisuje je, stosując algorytm HMAC-SHA1, aby wymienić token żądania na token dostępu w punkcie końcowym tokenu dostępu
        oauth_request = oauth.OAuthRequest.from_consumer_and_token(base_consumer, token=req_token, verifier=None, http_url=common.oauth_access_token_endpoint)
        oauth_request.sign_request(signature_method_hmac_sha1, base_consumer, req_token)
        
        # wysyła żądanie wymiany tokenu żądania na łańcuch tokenu dostępu
        token_read = urllib.urlopen(oauth_request.to_url())
        token_string = token_read.read()
        
        # wyodrębnia parametry i identyfikator GUID użytkownika z łańcucha tokenu dostępu
        token_params = cgi.parse_qs(token_string)
        guid = token_params['xoauth_yahoo_guid'][0]
        
        # tworzy nowy obiekt tokenu dostępu, aby wysyłać dalsze żądania
        access_token = oauth.OAuthToken.from_string(token_string)
        
        # tworzy adres URL serwerów Yahoo!, aby uzyskać dostęp do profilu użytkownika
        url = 'http://%s/v1/user/%s/profile' % ('social.yahooapis.com', guid)
        
        # tworzy nowe żądanie oauth i podpisuje je przy użyciu algorytmu HMAC-SHA1, aby uzyskać profil autoryzowanego użytkownika
        oauth_request = oauth.OAuthRequest.from_consumer_and_token(base_consumer, token=access_token, http_method='GET', http_url=url)
        oauth_request.sign_request(signature_method_hmac_sha1, base_consumer, access_token)
        
        # wysyła żądanie pobrania profilu użytkownika
        profile_read = urllib.urlopen(oauth_request.to_url())
        profile_string = profile_read.read()
        
        # wyświetla obiekt odpowiedzi na żądanie profilu
        message += '\n\nObiekt odpowiedzi:\n' + profile_string
    else:
        message = '\n\nOdpowiedź OpenID:\nWeryfikacja nie powiodła się.'
    print message

if __name__ == '__main__':
    main()