#!/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);
        $dbh->{pg_enable_utf8} = 1;

        # 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;

    }
}