#!/usr/bin/perl -w
#
# TWiki Collaboration Platform, http://TWiki.org/
#
# Copyright (C) 2000-2003 Peter Thoeny, Peter@Thoeny.com
# Copyright (C) 2001 Klaus Wriessnegger, kw@sap.com
#
# For licensing info read license.txt file in the TWiki root.
# 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 2
# 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, published at
# http://www.gnu.ai.mit.edu/copyleft/gpl.html
#

BEGIN {
    # Set default current working directory
    if( $ENV{"SCRIPT_FILENAME"} && $ENV{"SCRIPT_FILENAME"} =~ /^(.+)\/[^\/]+$/ ) {
        chdir $1;
    }
    # Set library paths in @INC at compile time
    unshift @INC, '.';
    require 'setlib.cfg';

    do "../lib/TWiki.cfg";
}

use vars qw($defaultUrlHost);

use CGI::Carp qw(fatalsToBrowser);
use CGI;
use TWiki;
use TWiki::User;
use TWiki::User::HtPasswdUser;

use Net::SMTP;

my $SMTP_SERVER = "boum.org";

$query= new CGI;
 
&main();
 
sub main
{
    my $wikiName = $query->param( 'username' );

    #initialize
    my $topicName = $query->param( 'TopicName' );
    my $thePathInfo = $query->path_info();
    my $theUrl = $query->url;

    ( $topic, $webName ) =
        &TWiki::initialize( $thePathInfo, $wikiName, $topicName, $theUrl, $query );
 
    my $text = "";
    my $url = "";

    my $theRemoteUser = $query->remote_user();
    my ( $dummy1, $dummy2, $dummy3, $userName ) = 
	&TWiki::initialize( $thePathInfo, $theRemoteUser, $topicName, $theUrl, $query );

    my $action = $query->param("installPasswd");

if ( $action eq "requestReset" ) {
        showPage($webName, $topic);
    } else {
       $url = &TWiki::getOopsUrl( $webName, $topic, "oopsmanage");
       TWiki::redirect( $query, $url );
    }
}

#==============================================
# ($webName, $topic)
sub showPage
{
    my  ($webName, $topic) = @_;

    # get all parameters from the form
    my $wikiName = $query->param( 'username' );

    my $url = "";

    # check if user entry exists
    if(  ( $wikiName )  && (! TWiki::User::UserPasswordExists( $wikiName ) ) ) {
        # PTh 20 Jun 2000: changed to getOopsUrl
        $url = &TWiki::getOopsUrl( $webName, $topic, "oopsnotwikiuser", $wikiName );
        TWiki::redirect( $query, $url );
        return;
    }

    # do the actual work
    resetPassword($webName, $topic);

    # and finally display the reset password page
    $url = &TWiki::getOopsUrl( $webName, $wikiName, "oopsresetpasswd");
    TWiki::redirect( $query, $url );
}

#==============================================
# ($webName, $topic)
sub resetPassword
{
	my ($webName, $topic) = @_;
	my $wikiName = $query->param('username');

	my $url = "";
	
	my $password = gen_random_8chars();
	my $email = get_email($wikiName);

	write_htpasswd($wikiName, $password);
	send_formatted_password($password, $email);
}

sub write_htpasswd
{
        my ($user, $password) = @_;
	my $url = "";
	
	if(TWiki::User::OverwriteUserPassword($user, $password) != "1")
	{
        	$url = &TWiki::getOopsUrl("TWiki", "ResetPassword", "oopsmanage");
	        TWiki::redirect($query, $url);
		return;
	}

	return $old_password;
}

sub send_formatted_password
{
    my ($password, $email) = @_;
    my $smtp_object;
    my $sender = &TWiki::Prefs::getPreferencesValue("WIKIWEBMASTER") || 'root@localhost';
    my $base_url = $defaultUrlHost;
    my $change_password_url = TWiki::getViewUrl("TWiki", "ChangePassword");

    $smtp_object = Net::SMTP->new($SMTP_SERVER,
                                  Debug => 0);

    $smtp_object->mail($sender);
    $smtp_object->to("<$email>");
    $smtp_object->cc($CC_TO);

    $smtp_object->data();

    $smtp_object->datasend("Subject: nouveau mot de passe pour $base_url\n");
    $smtp_object->datasend("To: <$email>\n");
    $smtp_object->datasend("\n");
    $smtp_object->datasend("Ceci est un email envoyé automatiquement.\n");
    $smtp_object->datasend("Tu as demandé la réinitialisation de ton mot de passe sur\n");
    $smtp_object->datasend("$base_url.\n");
    $smtp_object->datasend("\n");
    $smtp_object->datasend("Un nouveau de passe a été généré automatiquement : ");
    $smtp_object->datasend("$password\n");
    $smtp_object->datasend("Tu peux maintenant utiliser ce nouveau mot de passe pour te connecter\n");
    $smtp_object->datasend("avec ton nom d'utilisateurice TWiki habituel.\n");
    $smtp_object->datasend("\n");
    $smtp_object->datasend("ATTENTION: il te faut changer ce mot de passe, après t'être connecté-e.\n");
    $smtp_object->datasend("Tu peux le faire en allant sur la page : \n");
    $smtp_object->datasend("     $change_password_url\n");
    $smtp_object->datasend("\n");

    $smtp_object->dataend();

    $smtp_object->quit;
}

# generate a 8-byte random string by reading /dev/random
# WARNING: I've not done a cryptanalysis of that. normally, if /dev/random
# is secure, this should be also secure, but don't take my word for it.
# the passwords generated are US-ASCII encoded 
sub gen_random_8chars
{
    my $randomstr;
    my @randomnums;
    my @randomchars;
    my $passwd;
    my $tmp;

    if (! open RNDFILE, "/dev/random")
    {
    	$url = &TWiki::getOopsUrl("TWiki", "ResetPassword", "oopsmanage");
	TWiki::redirect($query, $url);
    }
    read RNDFILE, $randomstr, 8;
    close RNDFILE;

    @randomnums = unpack "C*", $randomstr;
    @randomnums = map { 64 + reduceMod($_, 57); } @randomnums;

    $passwd = pack "C*", @randomnums;

    return $passwd;
}

sub reduceMod
{
    my ($nr, $mod) = @_;

        while($nr >= $mod)
        {
	    $nr -= $mod;
        }

    return $nr;
}

sub get_email
{
	my ($username) = @_;
	my $text;
	my $url = "";
	
	if(TWiki::Store::topicExists("Main", $username))
	{
		$text =TWiki::Store::readTopicRaw("Main", $username);
		$text =~ /Email\: +(.*)\@(.*)$/m;
		return "$1\@$2";
	}
	else
	{
                $url = TWiki::getOopsUrl($webName, $topic, "oopsmanage");
		TWiki::redirect($query, $url);
	}
}

