#!/usr/bin/perl -wT
#
# TWiki Collaboration Platform, http://TWiki.org/
#
# Copyright (C) 2001 Klaus Wriessnegger, kw@sap.com
# Copyright (C) 2001 Andrea Sterbini, a.sterbini@flashnet.it
# Copyright (C) 2001-2003 Peter Thoeny, peter@thoeny.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
#
# 26-5-01 Password installation (only by the $superAdminGroup)
# 15-12-2003 moved requesting a passwd reset from passwd (as it is also htpasswd specific)
#

#NOTE:  InstallPassword code is protected from anonymous use, but it is still risky 
#(anyone who has a valid htpasswd entry can call it by hand 

#WARNING: this script only works when using htpasswd files.
#usage example:
#
#I n s t a l l
#
#</form>
#<form name="passwd" action="/%SCRIPTURLPATH%/installpasswd%SCRIPTSUFFIX%/%WEB%/">
#Username:EncryptedPW <input type="text" name="encryptedpassword" value="" size="16" /> <br />
#<input type="submit" name="passwd" />
#<input type="hidden" name="installPasswd" value="on" />
#</form>
#
# this code is here for symetery only - the actual usable bit is in the passwd script
#R e s e t
#
#<form name="passwd" action="/%SCRIPTURLPATH%/installpasswd%SCRIPTSUFFIX%/%WEB%/">
#Username     <input type="text" name="username" value="" size="16" /> <br />
#New password <input type="password" name="password" size="16" />
#retype New password <input type="password" name="passwordA" size="16" />
#<input type="hidden" name="installPasswd" value="requestReset" />
#<input type="submit" name="passwd" />
#
#
 
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';
}

use CGI::Carp qw(fatalsToBrowser);
use CGI;
use TWiki;
use TWiki::User;
use TWiki::User::HtPasswdUser;
 
&main();
 
sub main
{ 
   my %configHash; 
   my $config = \%configHash;
   my $twikiUri = $ENV{"SCRIPT_FILENAME"};
   $twikiUri =~ s!/+!/!g ; # remove multiple'/' 
   my @twikiUriItem = split ( '/' , $twikiUri ) ;
   $config->{fileConfig} = $ENV{"SERVER_NAME"} . "Port" . $ENV{"SERVER_PORT"} . $twikiUriItem[$#twikiUriItem - 2 ];
   $config->{TWiki}=TWiki->new( $config );
   $config->{TWiki}->init_config();

    my $query= new CGI;
    my $wikiName = $query->param( 'username' );

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

    ( $topic, $webName ) =
        $config->{TWiki}->initialize ( $thePathInfo, $wikiName, $topicName, $theUrl, $query );
 
    my $text = "";
    my $url = "";

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

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

    if ( $action eq "on" ) {
        installEncryptedPasswd ( $config, $webName, $topic, $userName, $query);
    } elsif ( $action eq "requestReset" ) {
        showEncryptedPasswd ( $config, $webName, $topic, $query);
    } else {
       $url = $config->{TWiki}->getOopsUrl ( $webName, $topic, "oopsmanage");
       $config->{TWiki}->redirect ( $query, $url );
    }
}

#==============================================
# ($webName, $topic)
sub showEncryptedPasswd
{ 
   my $config = shift;

    my  ($webName, $topic, $query) = @_;

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

    my $url = "";

    # check if required fields are filled in
    if( ! $wikiName || ! $passwordA ) {
        $url = $config->{TWiki}->getOopsUrl ( $webName, $topic, "oopsregrequ", );
        $config->{TWiki}->redirect ( $query, $url );
        return;
    }
 
    # check if user entry exists
    if(  ( $wikiName )  && (! $config->{TWiki}->{User}->UserPasswordExists ( $wikiName ) ) ) {
        # PTh 20 Jun 2000: changed to getOopsUrl
        $url = $config->{TWiki}->getOopsUrl ( $webName, $topic, "oopsnotwikiuser", $wikiName );
        $config->{TWiki}->redirect ( $query, $url );
        return;
    }

    # check if passwords are identical
    if( $passwordA ne $passwordB ) {
        $url = $config->{TWiki}->getOopsUrl ( $webName, $topic, "oopsregpasswd" );
        $config->{TWiki}->redirect ( $query, $url );
        return;
    }

    my $theCryptPassword = $config->{TWiki}->{User}->{HtPasswdUser}->_htpasswdGeneratePasswd ( $wikiName,  $passwordA );

    # and finally display the reset password page
    $url = $config->{TWiki}->getOopsUrl ( $webName, $wikiName, "oopsresetpasswd", $wikiName.":".$theCryptPassword );
    $config->{TWiki}->redirect ( $query, $url );
}

#==============================================
sub installEncryptedPasswd
{ 
   my $config = shift;

    my  ($webName, $topic, $userName, $query) = @_;

    my $wikiUserName = $config->{TWiki}->userToWikiName ( $userName );

    if( ! $config->{TWiki}->{Access}->userIsInGroup ( $wikiUserName, $config->{TWiki}->{superAdminGroup} ) ) {
    	# user has no permission to install the password
    	my $url = $config->{TWiki}->getOopsUrl ( $webName, $topic, "oopsaccessgroup", "$config->{TWiki}->{mainWebname}.$config->{TWiki}->{superAdminGroup}" );
    	$config->{TWiki}->redirect ( $query, $url );
    	return;
    }

    my $theCryptPassword = $query->param( 'encryptedPassword' ) || '';
    if ( ! $theCryptPassword ) {
	# missing username:encryptedpassword
    	$url = $config->{TWiki}->getOopsUrl ( $webName, $topic, "oopsregrequ", );
        $config->{TWiki}->redirect ( $query, $url );
        return;
    }
	
    # TODO: I18N fix here once basic auth problem with 8-bit user names is
    # solved
    if ( $theCryptPassword =~ m/^([A-Z][a-zA-Z]+[A-Z][a-zA-Z]*)\:.{13}$/ ) {
	$wikiName = $1;
    } else {
	# bad format
    	$url = $config->{TWiki}->getOopsUrl ( $webName, $topic, "oopsbadpwformat", $theCryptPassword);
        $config->{TWiki}->redirect ( $query, $url );
        return;
    }

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

#this bit is specific to the TWiki::User::HtPasswdUser module
    # old password
    my $oldcrypt = $config->{TWiki}->{User}->{HtPasswdUser}->_htpasswdReadPasswd ( $wikiName );
    # OK - password may be changed
    my $oldCryptPassword = "$wikiName\:$oldcrypt";
    $config->{TWiki}->{User}->{HtPasswdUser}->htpasswdUpdateUser ( $wikiName, $oldCryptPassword, $theCryptPassword );

    # OK - password changed
    $url = $config->{TWiki}->getOopsUrl ( $webName, $topic, "oopschangepasswd" );
    $config->{TWiki}->redirect ( $query, $url );
    return; 
}

