#!/usr/bin/perl
#####################################################################
# Data import script to migrate from version 1.1's flat file based
# users to version 1.2's central database.
#
# NOTE: This script will die if the user it tries to import is
# tied to a bogus or non-existing dataset/database. The fix
# is to edit the members file and either manually set the right
# database configuration for that user, or delete the user entirely.
#
# If the script makes it through all users it will print:
#
# 'SUCCESS! It seems that every user in the members file was imported!'
#
# If you don't get that output at the end of the script, something
# went wrong in the import.
#
# For help/troubleshooting please join the LedgerSMB users mailing
# list. Info on how to subscribe can be found here:
#
# http://lists.sourceforge.net/mailman/listinfo/ledger-smb-users
#
# Other info on how to get help, including commercial support 
# can be found at:
#
# http://www.ledgersmb.org/help/
#
use LedgerSMB::User;
use LedgerSMB::Form;
use LedgerSMB::Sysconfig;

if($ENV{HTTP_HOST}){
	print "Content-type: text/html\n\n";
	print "<html>\n";
	print "<strong>This script cannot be executed via http. You must run it via the command line.</strong>\n";
	print "</html>\n";
	exit;
}

my $membersfile = $ARGV[0];

if (length($membersfile) < 2){

    print "\nUsage: import_members.pl path/to/members\n\n";
	print "You must supply the path to the members file. Default location\n";
	print "is users/members. In this case do this:\n\n";
	print "  ./import_members.pl users/members\n\n";
	exit;
}

my @users = ();

open(FH, "$membersfile") || die ("Couldn't open members file!");

while (<FH>) {

	chop;

	if (/^\[.*\]/) {
		$login = $_;
		$login =~ s/(\[|\])//g;

		if($login eq 'admin'){

			print "\nIMPORT FAILED: User 'admin' was found.\n\n";
			print "Please change this user's name to something else. In LedgerSMB version 1.2, \n";
			print "'admin' is a reserved user for the administration of the entire system.\n";
			print "To change the user's name, find the line in the members file that looks \n";
			print "like [admin] and change 'admin' to something else (keep the '[' and ']').\n";
			print "Save the file and run this script again.\n\n";
			exit;

		} elsif($login ne 'root login'){
			push @users, $login;
			$member{$login}{'login'} = $login;
		}
		next;
	}

	if($login ne 'root login'){
		if(	($key, $value) = split /=/, $_, 2){
			if($key eq 'dbpasswd'){
				$member{$login}{$key} = unpack 'u', $value;
			} elsif($key eq 'password') {
				$member{$login}{'crypted_password'} = $value;
			} else {
				$member{$login}{$key} = $value;
			}
		}
	}
}

close(FH);

print "\n\nParsing members file completed. Now trying to import user data.\n\n";


foreach (@users) {

	$myUser = $member{$_};
	&save_member($myUser);
	print "Import of user '$_' seems to have succeeded.\n";

}

print "\nSUCCESS! It seems that every user in the members file was imported!\n\n";

sub save_member {

	# a slightly modified version of LegerSBM::User::save_member
	# with special handling of the password -> crypted_password

	my ($self) = @_;

	# replace \r\n with \n
	for (qw(address signature)) { $self->{$_} =~ s/\r?\n/\\n/g }

	# use central db
	my $dbh = ${LedgerSMB::Sysconfig::GLOBALDBH};

	#check to see if the user exists already
	my $userCheck = $dbh->prepare("SELECT id FROM users WHERE username = ?");
	$userCheck->execute($self->{login});
	my ($userID) = $userCheck->fetchrow_array;

	if($userID){
		#got an id, check to see if it's in the users_conf table
		my $userConfCheck = $dbh->prepare("SELECT count(*) FROM users_conf WHERE id = ?");
		$userConfCheck->execute($userID);

		($userConfExists) = $userConfCheck->fetchrow_array;
	}
	else{
		my $userConfAdd = $dbh->prepare("SELECT create_user(?);");
		$userConfAdd->execute($self->{login});
		($userID) = $userConfAdd->fetchrow_array;
	}

	if($userConfExists){

		my $userConfUpdate = $dbh->prepare("UPDATE users_conf
											   SET acs = ?, address = ?, businessnumber = ?,
												   company = ?, countrycode = ?, currency = ?,
												   dateformat = ?, dbdriver = ?,
												   dbhost = ?, dbname = ?, dboptions = ?, 
												   dbpasswd = ?, dbport = ?, dbuser = ?,
												   email = ?, fax = ?, menuwidth = ?,
												   name = ?, numberformat = ?, crypted_password = ?,
												   print = ?, printer = ?, role = ?,
												   sid = ?, signature = ?, stylesheet = ?,
												   tel = ?, templates = ?, timeout = ?,
												   vclimit = ?
											 WHERE id = ?;");

		$userConfUpdate->execute($self->{acs}, $self->{address}, $self->{businessnumber},
								 $self->{company}, $self->{countrycode}, $self->{currency},
								 $self->{dateformat}, $self->{dbdriver},
								 $self->{dbhost}, $self->{dbname}, $self->{dboptions}, 
								 $self->{dbpasswd}, $self->{dbport}, $self->{dbuser}, 
								 $self->{email}, $self->{fax}, $self->{menuwidth},
								 $self->{name}, $self->{numberformat}, $self->{crypted_password}, 
								 $self->{print}, $self->{printer}, $self->{role}, 
								 $self->{sid}, $self->{signature}, $self->{stylesheet},
								 $self->{tel}, $self->{templates}, $self->{timeout}, 
								 $self->{vclimit}, $userID);
	  

	}
	else{

		my $userConfInsert = $dbh->prepare("INSERT INTO users_conf(acs, address, businessnumber,
																   company, countrycode, currency,
																   dateformat, dbdriver,
																   dbhost, dbname, dboptions, dbpasswd,
																   dbport, dbuser, email, fax, menuwidth,
																   name, numberformat, print, printer, role, 
																   sid, signature, stylesheet, tel, templates, 
																   timeout, vclimit, id, crypted_password)
											VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 
												   ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 
												   ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);");

		$userConfInsert->execute($self->{acs}, $self->{address}, $self->{businessnumber},
								 $self->{company}, $self->{countrycode}, $self->{currency},
								 $self->{dateformat}, $self->{dbdriver},
								 $self->{dbhost}, $self->{dbname}, $self->{dboptions}, 
								 $self->{dbpasswd}, $self->{dbport}, $self->{dbuser}, 
								 $self->{email}, $self->{fax}, $self->{menuwidth},
								 $self->{name}, $self->{numberformat}, 
								 $self->{print}, $self->{printer}, $self->{role}, 
								 $self->{sid}, $self->{signature}, $self->{stylesheet},
								 $self->{tel}, $self->{templates}, $self->{timeout}, 
								 $self->{vclimit}, $userID, $self->{crypted_password});
	  
	}

	if (! $self->{'admin'}) {

		$self->{dbpasswd} =~ s/\\'/'/g;
		$self->{dbpasswd} =~ s/\\\\/\\/g;

		# format dbconnect and dboptions string
 		LedgerSMB::User::dbconnect_vars($self, $self->{dbname});

		# check if login is in database
		my $dbh = DBI->connect(
			$self->{dbconnect}, $self->{dbuser}, $self->{dbpasswd}, 
			{AutoCommit => 0}) 
				or $self->error($DBI::errstr);

		# add login to employee table if it does not exist
		my $login = $self->{login};
		$login =~ s/@.*//;
		my $sth = $dbh->prepare("SELECT id FROM employee WHERE login = ?;");
		$sth->execute($login);

		my ($id) = $sth->fetchrow_array;
		$sth->finish;
		my $employeenumber;
		my @values;
		if ($id) {

			$query = qq|UPDATE employee SET
			role = ?,
			email = ?, 
			name = ?
			WHERE login = ?|;

			@values = ($self->{role}, $self->{email}, $self->{name}, $login);

		} else {

			my ($employeenumber) = Form::update_defaults(
				"", \%$self, "employeenumber", $dbh);
			$query = qq|
				INSERT INTO employee 
				            (login, employeenumber, name, 
				            workphone, role, email, sales)
				    VALUES (?, ?, ?, ?, ?, ?, '1')|;
			
			@values = ($login, $employeenumber, $self->{name}, $self->{tel},
			$self->{role}, $self->{email})
		}

		$sth = $dbh->prepare($query);
		$sth->execute(@values);
		$dbh->commit;
		$dbh->disconnect;

	}
}