#! /usr/bin/perl -w

#
# Copyright (c) 2006,2007,2008 SUSE LINUX Products GmbH, Nuernberg, Germany.
# Copyright (c) 2011 SUSE LINUX Products GmbH, Nuernberg, Germany.
#

#BEGIN
#{
#    unshift @INC, ".";
#}

use strict;
use Data::Dumper;
use Getopt::Long;
use Encode;
use Time::HiRes qw(gettimeofday tv_interval);
use Sys::Syslog;
use SUSE_SMG::SuseRegister;
use File::Copy;

my $time = 0;
my $programStartTime = [gettimeofday];

my $locale          = undef;
my $interactive     = 0;
my $listParams      = 0;
my $xmlout          = 0;
my $nooptional      = 0;
my $forcereg        = 0;
my $nohwdata        = 0;
my $batch           = 0;
my $logfile         = undef;
my $browser         = undef;
my $noproxy         = 0;
my $norefresh       = 0;
my $help            = 0;
my $debug           = 0;
my $printnodebug    = 0;
my $reqMirrCreds    = 0;
my $erase           = 0;

my %args          = (
                     processor => undef,
                     platform => undef,
                     timezone => undef,
                    );
my @extraCurlOption = ();

my $restoreRepos    = 0;

sub logPrintExit
{
    my $ctx = shift;
    my $message = shift || "";
    my $code    = shift || 42;

    if(exists $ctx->{args}->{password})
    {
        $ctx->{args}->{password}->{value} = "secret";
    }
    if(exists $ctx->{args}->{passwd})
    {
        $ctx->{args}->{passwd}->{value} = "secret";
    }
    if(exists $ctx->{args}->{secret})
    {
        $ctx->{args}->{secret}->{value} = "secret";
    }
    my $cmdtxt = "Commandline params: no-optional:$ctx->{nooptional}  forceregistration:$ctx->{forcereg}  ";
    $cmdtxt .= "no-hw-data:$ctx->{nohwdata} batch:$ctx->{batch} ";

    syslog("err", $cmdtxt);
    syslog("err", "Argument Dump: ".Data::Dumper->Dump([$ctx->{args}]));
    syslog("err", "Products Dump: ".Data::Dumper->Dump([$ctx->{products}]));
    syslog("err", "$message($code)");
    print STDERR "$message($code)\n";

    closelog;
    close $ctx->{LOGDESCR} if(defined $ctx->{LOGDESCR});


    if($batch)
    {
        mailToRoot($ctx, "Error during registration", $message);
    }

    print STDERR "total time: ".(tv_interval($ctx->{programStartTime}))."\n" if($ctx->{time});

    exit $code;
}

sub mailToRoot
{
    my $ctx     = shift;
    my $subject = shift || undef;
    my $message = shift || undef;

    if( ! -e "/usr/bin/mail")
    {
        return;
    }

    if(!defined $subject || $subject eq ""||
       !defined $message || $message eq "")
    {
        return;
    }

    if($subject =~ /^[a-zA-Z0-9\s._-]+$/)
    {
        my @cmdArgs = ("-s", "$subject", "root");
        open(MAIL, "|-", "/usr/bin/mail", @cmdArgs) or return;

        print MAIL $message;

        close MAIL;
    }
}


sub usage
{
    print STDERR "usage: suse_register.pl [-i [-b <path>]] [-n] [--xml-output] [-a <key>=<value> -a ...] [-L <file>] \n";
    print STDERR "       suse_register.pl -p [--xml-output] [--locale=<locale>] [-L <file>]\n";
    print STDERR "       suse_register.pl --erase-local-regdata [-L <file>]\n";
    print STDERR "       suse_register.pl -h\n\n";
    print STDERR "Options:\n";
    print STDERR "         -i [--interactive]        enable interactive mode\n";
    print STDERR "         -n [--no-optional]        do not send optional data\n";
    print STDERR "         -f [--force-registration] mark all required parameters mandatory\n";
    print STDERR "                                   for registration even though registration itself\n";
    print STDERR "                                   might be optional\n";
    print STDERR "             --no-hw-data          do not send hardware data, even if they are mandatory\n";
    print STDERR "         -r [--restore-repos]      restore all repositories, also deleted once by the user\n";
    print STDERR "             --no-refresh          Do not refresh libzypp\n";
    print STDERR "      -h -? [--help]               show this help\n";
    print STDERR "         -a [--arg] <key>=<value>  provide an additional argument 'key'\n";
    print STDERR "                                   with the value 'value'\n";
    print STDERR "                                   You can use this option multiple times.\n";
    print STDERR "         -b [--browser] <path>     path to the browser to use for interactive mode\n";
    print STDERR "                                   if <path> is 'default', it tries to start your\n";
    print STDERR "                                   default browser.\n";
    print STDERR "\n";
    print STDERR "         -p [--list-parameters]    show list of parameters\n\n";
    print STDERR "             --xml-output          print XML output\n";
    print STDERR "         -L [--log] <file>         write log messages to <file> (default: \$HOME/.suse_register.log)\n";
    print STDERR "            [--no-proxy]           do not use proxies\n";
    print STDERR "             --locale=<locale>     define a locale e.g. en-US.utf-8\n";
    print STDERR "         -E  --erase-local-regdata Erase all local files created from a previous executed registration\n";
    print STDERR "                                   This option make the system look like never registered\n\n";

    print STDERR "Example:\n\n";
    print STDERR " suse_register.pl -n -a email=company\@example.com -a regcode-sles=03474hdkndg3934957340\n";
    print STDERR "\n";
    exit 2;
}

#########################################################
### Main Program
#########################################################

####################################################################
# dropped options
####################################################################
#                         "product=s"         => \@comlineProducts,
#                         "dumpfile=s"        => \$dumpfilehack,
#                         "dumpxmlfile=s"     => \$dumpxmlfilehack,
#                         "nozypp"            => \$nozypp,
#                         "norug"             => \$norug,
#                         "nozypper"          => \$nozypper,
#                         "maxmirrors=i"      => \$mirrorCount,
#                         "rip"               => \$registerinpatch

my $result = GetOptions ("interactive|i"     => \$interactive,
                         "list-parameters|p" => \$listParams,
                         "xml-output"        => \$xmlout,
                         "batch"             => \$batch,
                         "no-optional|n"     => \$nooptional,
                         "force-registration|f" => \$forcereg,
                         "no-hw-data"        => \$nohwdata,
                         "restore-repos|r"   => \$restoreRepos,
                         "log|L=s"           => \$logfile,
                         "locale=s"          => \$locale,
                         "browser|b=s"       => \$browser,
                         "no-proxy"          => \$noproxy,
                         "no-refresh"        => \$norefresh,
                         "help|?|h"          => \$help,
                         "debug|d=i"         => \$debug,
                         "arg|a=s"           => \%args,
                         "extra-curl-options=s" => \@extraCurlOption,
                         "t"                 => \$time,
                         "request-mirrorcredentials" => \$reqMirrCreds,
                         "printnodebug"      => \$printnodebug,
                         "erase-local-regdata|E" => \$erase
                        );

if ($help)
{
    usage();
}


$ENV{'PATH'} = '/bin:/usr/bin:/sbin:/usr/sbin:/opt/kde3/bin:/opt/gnome/bin';

my $data = {};
$data->{xmlout} = $xmlout;
$data->{nooptional} = $nooptional;
$data->{nohwdata} = $nohwdata;
$data->{logfile} = $logfile;
$data->{locale} = $locale;
$data->{forcereg} = $forcereg;
$data->{restoreRepos} = $restoreRepos;
$data->{batch} = $batch;
$data->{noproxy} = $noproxy;
$data->{norefresh} = $norefresh;
$data->{debug} = $debug;
$data->{args} = \%args;
$data->{extraCurlOption} = \@extraCurlOption;
$data->{time} = $time;
$data->{printnodebug} = $printnodebug;
$data->{reqmirrcreds} = $reqMirrCreds;
$data->{erase} = $erase;

if($batch)
{
    $interactive = 0;
}

$data->{interactive} = $interactive;


my $ctx = SUSE_SMG::SuseRegister::init_ctx($data);
if($ctx->{errorcode} != 0)
{
    logPrintExit($ctx, $ctx->{errormsg}, $ctx->{errorcode});
}

$ctx->{programStartTime} = $programStartTime;

my $ret = 0;
if ($erase)
{
    print "NOTE: The erase command do not delete this client from the registration server.\n";
    $ret = SUSE_SMG::SuseRegister::eraseRegistrationData($ctx);
    if($ctx->{errorcode} != 0)
    {
        logPrintExit($ctx, $ctx->{errormsg}, $ctx->{errorcode});
    }
    else
    {
        print "Successfully erased local registration data.\n";
    }
}
elsif ($listParams)
{
    $ret = SUSE_SMG::SuseRegister::listParams($ctx);
    if($ctx->{errorcode} != 0)
    {
        logPrintExit($ctx, $ctx->{errormsg}, $ctx->{errorcode});
    }

    print $ret;
}
else
{
    $ctx->{lastResponse} = "";
    do
    {
        $ret = SUSE_SMG::SuseRegister::register($ctx);
        if($ctx->{errorcode} != 0)
        {
            logPrintExit($ctx, $ctx->{errormsg}, $ctx->{errorcode});
        }

        if($ret == 4)
        {
            if(!$interactive)
            {
                if($xmlout == 1 &&
                   exists $ctx->{xmloutput} &&
                   defined $ctx->{xmloutput})
                {
                    print STDERR $ctx->{xmloutput};
                }
                elsif($batch)
                {
                    mailToRoot($ctx, "Manual registration required",
                               join("", @{$ctx->{registerReadableText}})."\n");
                }
                else
                {
                    print STDERR join("", @{$ctx->{registerReadableText}})."\n";
                }
                exit 4;
            }
            else
            {
                my @url = ();

                push @url, $ctx->{registerManuallyURL};


                if (@url == 0)
                {
                    logPrintExit($ctx, "Missing URL.\n", 14);
                }

                if (defined $browser)
                {
                    if($browser eq "default")
                    {
                        print STDERR "search for default browser\n" if($debug >=2);
                        # some magic to find the default browser
                        if(exists $ENV{DESKTOP_LAUNCH} &&
                           defined $ENV{DESKTOP_LAUNCH})
                        {
                            $browser = SUSE_SMG::SuseRegister::fullpathOf($ctx, $ENV{DESKTOP_LAUNCH});
                        }
                        else
                        {
                            if(exists $ENV{DISPLAY}  &&
                               defined $ENV{DISPLAY} &&
                               $ENV{DISPLAY} ne "" )
                            {
                                # GUI Browser

                                $browser = SUSE_SMG::SuseRegister::fullpathOf($ctx, "firefox");

                                if(!defined $browser)
                                {
                                    $browser = SUSE_SMG::SuseRegister::fullpathOf($ctx, "konqueror");
                                }
                            }
                            else
                            {
                                $browser = SUSE_SMG::SuseRegister::fullpathOf($ctx, "lynx");

                                if(!defined $browser)
                                {
                                    $browser = SUSE_SMG::SuseRegister::fullpathOf($ctx, "w3m");
                                }
                            }
                        }
                    }
                    print STDERR "Want to call browser: $browser\n" if($debug);

                    if(defined $browser && -e $browser)
                    {
                        system($browser, @url);
                        if( ($?>>8) != 0)
                        {
                            print STDERR "Starting browser '$browser' failed. Disable interactive mode\n";
                            $interactive = 0;
                            $ctx->{lastResponse} = "";
                        }
                        else
                        {
                            logPrintExit($ctx, "When you have finished your registration, ".
                                         "start suse_register\n".
                                         "again to get the current configuration for ".
                                         "the update mechanism.\n", 0);
                        }
                    }
                    else
                    {
                        print STDERR "Browser not found. Disable interactive mode\n";
                        $interactive  = 0;
                        $ctx->{lastResponse} = "";
                    }
                }
                else
                {
                    my @defBrowser = ("lynx", "w3m");
                    my $foundBrowser = 0;

                    foreach my $b (@defBrowser)
                    {
                        my $fullpath = SUSE_SMG::SuseRegister::fullpathOf($ctx, $b);
                        if (defined $fullpath && $fullpath ne "")
                        {
                            system($fullpath, @url);
                            if( ($?>>8) == 0)
                            {
                                $foundBrowser = 1;
                                last;
                            }
                        }
                    }
                    if(!$foundBrowser)
                    {
                        print STDERR "Starting browser failed. Disable interactive mode\n";
                        $interactive = 0;
                    }
                }
                # FIXME: other logic?
                #
                # do not ask for interactive optional again,
                # because then optional become mandatory
                $ctx->{acceptmand} = 1;

                # browser was called, so reset force-registration
                $ctx->{forcereg}   = 0;
                $ret = 1;
            }
        }
    } while ($ret == 1);

    if($ret == 0)
    {
        if($xmlout == 1 &&
           exists $ctx->{xmloutput} &&
           defined $ctx->{xmloutput})
        {
            print STDERR $ctx->{xmloutput};
            exit 0;
        }

        SUSE_SMG::SuseRegister::manageUpdateSources($ctx);
        if($ctx->{errorcode} != 0)
        {
            logPrintExit($ctx, $ctx->{errormsg}, $ctx->{errorcode});
        }

        #
        # Call a final refresh to get repos from services enabled.
        # This can make trouble if somebody else has the zypp lock
        # (bnc#536554)
        #
        if(!$ctx->{norefresh})
        {
            my ($code, $message) = SUSE_SMG::SRPrivate::zyppRefresh( $ctx );
            if($code != 0)
            {
                print STDERR "WARNING: Refresh failed. You may want to call 'zypper refresh --service' manually.\n";
                # we do not exit here.
            }
        }

        if($ctx->{warnUnrestoredRepos})
        {
            print STDERR "WARNING: Some repositories were manually disabled. They are not restored.\n";
            print STDERR "         If you want to restore them, call suse_register with the --restore-repos parameter.\n";
        }

        my $m = 0;
        if( ref($ctx->{registerStatus}) eq "HASH")
        {
          foreach my $key (keys %{$ctx->{registerStatus}})
          {
            if( $ctx->{registerStatus}->{$key}->{result} eq "error" &&
                $ctx->{registerStatus}->{$key}->{message} ne "")
            {
              print STDERR "ERROR: ".$ctx->{registerStatus}->{$key}->{message}."\n";
              $m++;
            }
          }
        }
        if($m == 0)
        {
          print "Registration finished successfully\n";
        }
        else
        {
          logPrintExit($ctx, "Registration failed.", 99);
        }
        #print Data::Dumper->Dump([$ctx])."\n";

    }
    else
    {
        logPrintExit($ctx, $ctx->{errormsg}, $ret);
    }
}

print STDERR "total time: ".(tv_interval($programStartTime))."\n" if($ctx->{time});

exit 0;

