# Copyright (C) 2005 JanRain, Inc.
# Copyright (C) 2009, 2010 Canonical Ltd
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import urllib
import urlparse

try:
    from openid.urinorm import urinorm
except ImportError:
    # An OpenID library that does not yet have urinorm. Anything
    # before 2.0 should be in this state. Not normalizing URLs just
    # means that you have to be more careful about what you type when
    # you're listing the authorized URLs.
    from openid.oidutil import normalizeUrl as urinorm

from apache_openid import logging

class Authenticator(object):
    def __init__(self, request, options):
        self.request = request
        self.options = options

    def authenticate(self, openid):
        logging.debug("Checking auth for: %s" % openid)
        return (openid is not None and openid in self.authorized_urls)

    @property
    def authorized_urls(self):
        authorized_urls = []
        if 'authorized-users' in self.options:
            authorized_urls.extend(self.get_authorized_urls_from_options())
        if 'authorized-users-list-url' in self.options:
            url = self.options.get('authorized-users-list-url')
            authorized_urls.extend(self.get_authorized_urls_from_url(url))
        return authorized_urls

    def get_authorized_urls_from_options(self):
        authorized_urls_raw = self.options.get('authorized-users')
        return self.parse_authorized_urls(authorized_urls_raw)

    def get_authorized_urls_from_url(self, url):
        try:
            url_handle = urllib.urlopen(url)
            data = url_handle.read()
            url_handle.close()
            return self.parse_authorized_urls(data)
        except IOError:
            logging.error('Failed to fetch authorized list URL %r', url)
            return []

    def parse_authorized_urls(self, data, force_http=True):
        """Parse and normalize a string containing a whitespace-separated
        list of URLs"""
        urls = []
        for s in data.split():
            url = s.strip()
            if not url or url[0] == '#':
                continue
            if not force_http:
                urls.append(url)
                continue
            parsed = urlparse.urlparse(url)
            if not (parsed[0] and parsed[1]):
                url = 'http://' + url
            urls.append(urinorm(url))
        return urls
