/* ======================================================================
   Parts Copyright 2006 University of Leeds, Oxford University, University of the Highlands and Islands.

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

====================================================================== */

package org.bodington.servlet;

import java.io.IOException;
import java.util.Properties;

import javax.servlet.http.HttpServletRequest;

import org.bodington.server.BuildingServerException;
import org.bodington.server.NavigationSession;
import org.bodington.util.Base64Decoder;

/**
 * Class that handles session initialization via basic authentication.
 * @author Alexis O'Connor
 */
class BasicSessionInitializer extends AbstractSessionInitializer
{
    private static Base64Decoder base64decoder = new Base64Decoder();
    
    /**
     * Look for a session associated with the request. If no session can be
     * found, this method returns <code>null</code>. The implementation of
     * this method attempts to find the session by calling the method in its
     * superclass and then going via the <code>authorization</code> header in
     * the request.
     * @param request the request to be examined.
     * @return a session associated with the request.
     */
    protected HttpSession findHttpSession( Request request )
    {
        HttpSession session = super.findHttpSession( request );
        if ( session != null ) 
            return session;

        // Check if a basic user name and password are present.
        String authorization = request.getHeader( "Authorization" );
        if (authorization == null)
            return null;

        if ( authorization.toLowerCase().startsWith( "basic " ) )
        {
            // If there was a successful previous login the auth string must be
            // same and so we can just pick up the session keyed against it.
            session = HttpSession.findSessionByAuthenticationString( authorization );

            // If this auth string has not been seen before start a new session
            // and make sure that it is keyed against the auth string for later
            // requests.
            if ( session == null )
            {
                session = 
                    (org.bodington.servlet.HttpSession)request.getSession( true );
                session.setAuthenticationString( authorization );
            }
        }

        return session;
    }

    protected boolean initialize( Request request,
        HttpSession session, NavigationSession navigation )
    {
        try
        {
            String authorization = request.getHeader( "Authorization" );

            if ( authorization == null
                || !authorization.toLowerCase().startsWith( "basic " ) )
            {
                return false;
            }

            authorization = authorization.substring( 6 ).trim();
            synchronized ( base64decoder )
            {
                try
                {
                    authorization = base64decoder.decodeBuffer( authorization,
                        "UTF-8" );
                }
                catch ( IOException ioex )
                {
                    authorization = "";
                }
            }
            if ( authorization.indexOf( ':' ) >= 0 )
            {
                String userName = authorization.substring( 0, 
                    authorization.indexOf( ':' ) );
                String password = authorization.substring( 
                    authorization.indexOf( ':' ) + 1 );

                Properties props = new Properties();
                props.setProperty( "user_name", userName );
                props.setProperty( "pass_phrase", password );
                navigation.setAuthenticationCredentials( props,
                    "standard_pass_phrase" );
                return true;
            }
        }
        catch ( BuildingServerException e )
        {
        }

        return false;
    }

    protected void postInitialize( HttpSession session, Request request )
    {
        super.postInitialize( session, request );
        session.setAuthType( HttpServletRequest.BASIC_AUTH );
    }
}
