# ==================================================================
# Gossamer Links - enhanced directory management system
#
#   Website  : http://gossamer-threads.com/
#   Support  : http://gossamer-threads.com/scripts/support/
#   CVS Info : 087,071,086,086,085      
#   Revision : $Id: Login.pm,v 1.19 2005/05/08 09:56:44 brewt Exp $
#
# Copyright (c) 2004 Gossamer Threads Inc.  All Rights Reserved.
# Redistribution in part or in whole strictly prohibited. Please
# see LICENSE file for full details.
# ==================================================================

package Links::User::Login;
# ==================================================================
use strict;
use Links qw/:objects/;
use Links::Build;
use Links::SiteHTML;

sub handle {
# -------------------------------------------------------------------
# Determine what to do.
#
    my $input = $IN->get_hash;
    my $mtl = Links::Build::build('title', Links::language('LINKS_LOGIN'), "$CFG->{db_cgi_url}/user.cgi");
    if ($input->{login}) {
        $PLG->dispatch('user_login', \&login_user);
    }
    elsif ($input->{signup_user}) {
        $PLG->dispatch('user_signup', \&signup_user);
    }
    elsif ($input->{validate_user}) {
        $PLG->dispatch('user_validate', \&validate_user);
    }
    elsif ($input->{send_validate}) {
        $PLG->dispatch('user_validate_email', \&send_validate);
    }
    elsif ($input->{send_pass} and $CFG->{user_allow_pass}) {
        $PLG->dispatch('user_pass_email', \&send_pass);
    }
    elsif ($input->{signup_form}) {
        print $IN->header();
        print Links::SiteHTML::display('signup_form', { Username => $IN->param('Username') || '', Password => '', Email => $IN->param('Email') || '', main_title_loop => Links::Build::build('title', Links::language('LINKS_SIGNUP'), "$CFG->{db_cgi_url}/user.cgi?signup_form=1") });
    }
    elsif ($input->{validate}) {
        print $IN->header();
        print Links::SiteHTML::display('validate_form', { main_title_loop => Links::Build::build('title', Links::language('LINKS_VALIDATE'), "$CFG->{db_cgi_url}/user.cgi?validate=1") });
    }
    elsif ($input->{logout}) {
        Links::Authenticate::auth('delete_session');
        $USER = undef;
        print $IN->header();
        print Links::SiteHTML::display('login', { Username => '', Password => '', Email => '', error => Links::language('USER_LOGOUT'), main_title_loop => $mtl });
    }
    elsif ($input->{email_pass} and $CFG->{user_allow_pass}) {
        print $IN->header();
        print Links::SiteHTML::display('login_email', { main_title_loop => Links::Build::build('title', Links::language('LINKS_EMAILPASS'), "$CFG->{db_cgi_url}/user.cgi?email_pass=1") });
    }
    else {
        print $IN->header();
        print Links::SiteHTML::display('login', { Username => $IN->param('Username') || '', main_title_loop => $mtl });
    }
}
# ==============================================================

sub login_user {
# --------------------------------------------------------          
# Logs a user in, and creates a session ID.
#
    my $username = $IN->param('Username') || shift;
    my $password = $IN->param('Password') || shift;
    my $goto     = shift || 'login_success';

    my $mtl = Links::Build::build('title', Links::language('LINKS_LOGIN'), "$CFG->{db_cgi_url}/user.cgi");

# Make sure we have both a username and password.
    if (!$username or !$password) {
        print $IN->header();
        print Links::SiteHTML::display('login', { error => Links::language('USER_BADLOGIN'), Username => $username, main_title_loop => $mtl });
        return;
    }

# Check that the user exists, and that the password is valid.
    my $user = Links::init_user($username, $password);
    if (!$user) {
        print $IN->header();
        require Links::Authenticate;
        if (Links::Authenticate::auth_valid_user({ Username => $username, Password => $password })) {
            print Links::SiteHTML::display('login', { error => Links::language('USER_NOTVAL', $user->{Email}), Username => $user->{Username}, main_title_loop => $mtl });
        }
        else {
            print Links::SiteHTML::display('login', { error => Links::language('USER_BADLOGIN'), main_title_loop => $mtl });
        }
        return;
    }

# Store the session in either a cookie or url based.
    my $results = Links::Authenticate::auth('create_session', { Username => $user->{Username} });
    return if $results->{redirect};

# Get the $USER information.
    $USER = Links::Authenticate::auth('get_user', { Username => $username, Password => $password, auto_create => 1 });

    print $IN->header(); # In case the session didn't print it.
    print Links::SiteHTML::display($goto, { %$user, main_title_loop => $mtl });
}

sub signup_user {
# --------------------------------------------------------
# Signs a new user up.
#
    my $username = $IN->param('Username');
    my $password = $IN->param('Password');
    my $email    = $IN->param('Email');

    my $mtl = Links::Build::build('title', Links::language('LINKS_SIGNUP'), "$CFG->{db_cgi_url}/user.cgi?signup_form=1");

    if (!$username or !$password or !$email) {
        print $IN->header();
        print Links::SiteHTML::display('signup_form', { error => Links::language('USER_INVALIDSIGNUP'), main_title_loop => $mtl });
        return;
    }
    unless ($email =~ /.\@.+\../) {
        print $IN->header();
        print Links::SiteHTML::display('signup_form', { error => Links::language('USER_INVALIDEMAIL', $email), main_title_loop => $mtl });
        return;
    }

# Check that the username doesn't already exist.
    my $db   = $DB->table('Users');
    my $user = $db->get($username);
    if ($user) {
        print $IN->header();
        print Links::SiteHTML::display( 'signup_form', { error => Links::language('USER_NAMETAKEN', $username), main_title_loop => $mtl });
        return;
    }

# Check that the email address doesn't already exist.
    my $hits = $db->count({ Email => $email });
    if ($hits) {
        print $IN->header();
        print Links::SiteHTML::display('signup_form', { error => Links::language('USER_EMAILTAKEN', $email), main_title_loop => $mtl });
        return;
    }
    my ($code, $msg);

# Add the user in, set defaults for fields not specified.
    $user = $IN->get_hash();
    my $def = $db->default || {};
    foreach (keys %$def) {
        $user->{$_} = $def->{$_} unless (exists $user->{$_});
    }

# Send validation email if needed.
    if ($CFG->{user_validation}) {
        my $code = time . $$ . int rand 1000;
        $user->{Status} = "Not Validated";
        $user->{Validation} = $code;
        my $ret = $db->add($user);
        if (!$ret) {
            print $IN->header();
            print Links::SiteHTML::display('signup_form', { error => $db->error, main_title_loop => $mtl });
            return;
        }
    }
    else {
        $user->{Status} = "Registered";
        $user->{Validation} = 0;
        my $ret = $db->add($user);
        if (!$ret) {
            print $IN->header();
            print Links::SiteHTML::display('signup_form', { error => $db->error, main_title_loop => $mtl });
            return;
        }
    }
# Print the welcome screen.
    if ($CFG->{user_validation}) {
        print $IN->header();
        print Links::SiteHTML::display('signup_success', { %$user, main_title_loop => $mtl });
        Links::send_email('validate.eml', $user) or die "Unable to send message: $GT::Mail::error";
    }
    else {
        my $results = Links::Authenticate::auth('create_session', { Username => $user->{Username} });
        $USER = Links::Authenticate::auth('get_user', { Username => $user->{Username}, Password => $user->{Password}, auto_create => 1 });
        print $IN->header();
        print Links::SiteHTML::display('signup_success', { %$user, main_title_loop => $mtl });
    }
}

sub validate_user {
# --------------------------------------------------------
# Validates a user.
#
    my $code = $IN->param('code');
    $code =~ s/^\s*|\s*$//g;

    my $mtl = Links::Build::build('title', Links::language('LINKS_VALIDATE'), "$CFG->{db_cgi_url}/user.cgi?validate=1");

    if (!$code) {
        print $IN->header;
        print Links::SiteHTML::display('validate_form', { error => Links::language('USER_INVALIDVAL'), main_title_loop => $mtl });
        return;
    }
    my $db   = $DB->table('Users');
    my $sth  = $db->select({ Validation => $code });
    my $user = $sth->fetchrow_hashref;

    if (! $user) {
        print $IN->header;
        print Links::SiteHTML::display('validate_form', { error => Links::language('USER_INVALIDVAL'), main_title_loop => $mtl });
        return;
    }
    $db->update({ Status => 'Registered' }, { Username => $user->{Username} });
    login_user($user->{Username}, $user->{Password}, 'validate_success');
}

sub send_pass {
# -------------------------------------------------------------------
# Sends the user a password reminder email.
#
    my $email = $IN->param('Email');
    my $user_db = $DB->table('Users');
    my $sth = $user_db->select( { Email => $email } );
    print $IN->header();
    my $user = $sth->fetchrow_hashref;
    if ($user and $email =~ /.+\@.+\..+/) {
        Links::send_email('password.eml', { %$user, %ENV }) or die "Unable to send message: $GT::Mail::error";
        print Links::SiteHTML::display('login', { error => Links::language('USER_PASSSENT'), Username => '', Password => '', main_title_loop => Links::Build::build('title', Links::language('LINKS_LOGIN'), "$CFG->{db_cgi_url}/user.cgi") });
    }
    else {
        print Links::SiteHTML::display('login_email', { error => Links::language('USER_NOEMAIL'), main_title_loop => Links::Build::build('title', Links::language('LINKS_EMAILPASS'), "$CFG->{db_cgi_url}/user.cgi?email_pass=1") });
    }
}

sub send_validate {
# -------------------------------------------------------------------
# Sends the validation email if the user needs another one.
#
    my $email = $IN->param('Email');
    my $user_db = $DB->table('Users');
    my $sth = $user_db->select( { Email => $email } );
    print $IN->header();
    if ($sth->rows) {
# Prepare the message.
        my $user = $sth->fetchrow_hashref;

# Make sure there is a validation code.
        if (! $user->{Validation}) {
            $user->{Validation} = (time) . ($$) . (int rand(1000));
            $user_db->modify($user);
        }
        Links::send_email('validate.eml', $user) or die "Unable to send message: $GT::Mail::error";

        print Links::SiteHTML::display('login', { error => Links::language('USER_VALSENT'), Username => '', Password => '', main_title_loop => Links::Build::build('title', Links::language('LINKS_LOGIN'), "$CFG->{db_cgi_url}/user.cgi") });
    }
    else {
        print Links::SiteHTML::display('login_email', { error => Links::language('USER_NOEMAIL'), main_title_loop => Links::Build::build('title', Links::language('LINKS_EMAILPASS'), "$CFG->{db_cgi_url}/user.cgi?email_pass=1") });
    }
}

1;

