#!/usr/bin/perl # Drakwizard # Copyright (C) 2002 MandrakeSoft Mael Dodin (mdodin@mandrakesoft.com) # # 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, 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. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. use lib qw(/usr/lib/libDrakX); use strict; use vars qw($Wizard_title $Wizard_pix_up $lib_script $perl_module %variable $in $rpm %chooser_hash $welcome $perl_module_name $verbose %description $summary $summary_func %disabled $current_page %bool); use XML::Parser; use standalone; use interactive; #use MDK::Common::Func; use common; use Data::Dumper; #- I18N. push @::textdomains, 'drakwizard'; my $in = 'interactive'->vnew('su', 'default'); $::direct = /-direct/; $::Wizard_no_previous = 1; $::Wizard_title = "Drakwizard"; my $standalone = 1; ! -r '/etc/sysconfig/network-scripts/drakconnect_conf' && ( -r '/etc/sysconfig/network-scripts/draknet_conf' || die "no drakconnect conf file found, install drakconnect and try again") && MDK::Common::cp_af('/etc/sysconfig/network-scripts/draknet_conf', '/etc/sysconfig/network-scripts/drakconnect_conf'); if (!defined($ARGV[0])) { my $prefix = "/usr/share/wizards/"; my %wiz = ( 1 => [$prefix."web_wizard/web.wiz", "Apache"], 2 => [$prefix."dhcp_wizard/dhcp.wiz", "Dhcp"], 3 => [$prefix."dns_wizard/dns.wiz", "Dns (configuration)"], 4 => [$prefix."client_wizard/client.wiz", "Dns (add client)"], 5 => [$prefix."news_wizard/news.wiz", "News"], 6 => [$prefix."nfs_wizard/nfs.wiz", "NFS"], 7 => [$prefix."postfix_wizard/postfix.wiz", "Postfix"], 8 => [$prefix."ftp_wizard/ftp.wiz", "Proftpd"], 9 => [$prefix."samba_wizard/samba.wiz", "Samba"], 10 => [$prefix."proxy_wizard/proxy.wiz", "Squid"], 11 => [$prefix."time_wizard/time.wiz", "Time"] ); $in->ask_from( N("Drakwizard wizard selection"), N("Please select a wizard"), [{ val => \$ARGV[0], list => [sort keys %wiz], format => sub { $wiz{$_[0]}[1] }}] ); $ARGV[0] = $wiz{$ARGV[0]}[0]; } my $o = []; my $o2 = []; my $xmltree = XML::Parser->new(Style => 'Tree')->parsefile($ARGV[0]); local $_ = join '', @ARGV; if (/-debug/) { $::verbose = 1; } $::isWizard = 1; if (/-summary/) { $::isSummary = 1; get_parameter($o2, $xmltree); $::Wizard_finished = 1; get_summary($o2, $xmltree); is_disabled_summary($_[0], $o2->[0]); my $data = map_freetext($summary->{freetext}); # workaround to get get the scrollbar while ($::isSummary--) { push @$data, ''; } $in->ask_from("summary", "", $data) && $::{$perl_module_name."::"}{"$summary_func"}->(); } else { get_parameter($o, $xmltree); if (!$::verbose) { no warnings; navigation($o, $o->[0]); } else { navigation($o, $o->[0]) }; } $in->exit; sub member { my $e = shift; foreach (@_) { $e eq $_ and return 1 } 0 } sub xml_text { $_[0] =~ s/\\\'/\'/g; $_[0] =~ s/\\q/\"/g; $_[0] =~ s/\\a/\&/g; $_[0] =~ s/\\n/\n/g; $_[0]; } sub load_wizard { ($Wizard_title, $lib_script, $perl_module, $rpm, $Wizard_pix_up, $summary_func) = @_; if ($rpm) { if (!$in->do_pkgs->is_installed($rpm)) { if ($in->ask_okcancel("error", N("%s is not installed\nClick \"Next\" to install or \"Cancel\" to quit", c::from_utf8($rpm)))) { if (!$in->do_pkgs->install($rpm eq 'bind' ? 'bind-9' : $rpm)) { $::Wizard_finished = 1; $in->ask_okcancel("error", N("installation failed")); $in->exit; } } else { $in->exit } } } if ($perl_module) { ($::perl_module_name) = ($perl_module =~ /.*\/(.*)\.pm/); require $perl_module; } } sub map_freetext { my @liste; my $valeur; my @data = map { my $toto = $_->{variableName}; my $page = $_; if ($_->{fillScript}) { $ENV{$variable{$_->{variableName}}} = `. $lib_script && $_->{fillScript}`; } if ($_->{main_order} eq 'entry') { if (!$ENV{$variable{$_->{variableName}}} && $_->{fillfunc}) { $ENV{$variable{$_->{variableName}}} = $::{$perl_module_name."::"}{"$_->{fillfunc}"}->(); } { label => N($_->{helpText}), val => \$ENV{$variable{$_->{variableName}}}, type => $_->{main_order}, disabled => $disabled{$_->{variableName}}, help => $_->{help}} } elsif ($_->{main_order} eq 'field' && $_->{fillfunc}) { { label => N($_->{helpText}), val => $::{$perl_module_name."::"}{"$_->{fillfunc}"}->(), type => $_->{main_order}, disabled => $disabled{$_->{variableName}}, help => $_->{help}} } elsif ($_->{main_order} eq 'bool') { if (!$ENV{$variable{$_->{variableName}}} && $_->{fillfunc}) { $ENV{$variable{$_->{variableName}}} = $::{$perl_module_name."::"}{"$_->{fillfunc}"}->(); } if ($_->{listfunc}) { my @checklist = $::{$perl_module_name."::"}{"$_->{listfunc}"}->(); my $i = 21 - scalar @checklist; # workaround to get get the scrollbar if (!$::isSummary) { while ($i--) { push @checklist, ''; } } else { while ($i--) { $::isSummary++; } } # map { if (length($_)) { $disabled{$toto} = sub { callback($toto)}; { val => \$bool{$_}, label => "", type => 'bool', text => "$_", help => "", disabled => $disabled{$toto} } } } @checklist; } else { { val => \$ENV{$variable{$_->{variableName}}}, label => "", type => $_->{main_order}, text => translate($_->{helpText}), disabled => $disabled{$_->{variableName}}, help => $_->{help} } } } elsif ($_->{main_order} eq 'combo') { if($_->{fillScript}){ @liste = (); $valeur = `. $lib_script && $_->{fillScript}`; while( $valeur =~ /(.+)\n/g){ push @liste, $1; $chooser_hash{$1} = $1; } } elsif ($_->{fillfunc}){ @liste = $::{$perl_module_name."::"}{"$_->{fillfunc}"}->(); } else { @liste = @{$_->{Option}}; } { label => N($_->{helpText}), val => \$ENV{$variable{$_->{variableName}}}, list => [@liste], type => $_->{main_order}, disabled => $disabled{$_->{variableName}} }} elsif ($_->{main_order} eq 'field') { { val => $description{$ENV{$variable{$_->{variableName}}}}? $description{$ENV{$variable{$_->{variableName}}}} : $ENV{$variable{$_->{variableName}}}, label => $_->{helpText}, help => $_->{help}} } } @{$_[0]}; \@data; } sub get_parameter { my ($o, $tree, $tag ,$page) = @_; foreach my $leaf (@$tree) { if (ref($leaf) eq 'ARRAY') { $page = get_parameter($o, $leaf, $tag, $page); } elsif (ref($leaf) eq 'HASH') { my $common_freetext_chooser; my %actions = ( Wizard => sub { load_wizard(@{$leaf}{qw(wizardTitle libScript perlModule rpm defaultImage)}) },, Variable => sub { $variable{$leaf->{name}} = $leaf->{shellVariable}; $ENV{$variable{$leaf->{name}}} = $leaf->{defaultValue}; $disabled{$leaf->{name}} = sub { callback($leaf->{name})}; }, Page => sub { !$welcome and $welcome = $page; my $old_page = $page; push @$o, $page = { %$leaf }; $old_page->{next_page} = $page; if ($leaf->{canBack} =~ /.*false.*/) { $page->{no_prev} = 1} if ($leaf->{canCancel} =~ /.*false.*/) { $page->{no_cancel} = 1} if ($leaf->{nextFinish} =~ /.*true.*/) { $page->{finish} = 1} }, Target => sub { $page->{Target}->{jumpIndex}->{$leaf->{jumpIndex}} = $leaf->{targetName}; }, Info => sub { # This is to avoid monospaced text to be interpolated $leaf->{helpText} = translate($leaf->{helpText}); if ($leaf->{fontName} eq "Monospaced") { chomp($leaf->{helpText}); $leaf->{helpText} = $leaf->{helpText} ? "$leaf->{helpText}\n$leaf->{helpText}" : "$leaf->{helpText}\n"; } $page->{info} = xml_text($leaf->{helpText} ? "$page->{info}\n$leaf->{helpText}" : "$page->{info}\n"); $page->{info} = c::from_utf8($page->{info}); $page->{info} .= translate(`source $lib_script; $leaf->{fillScript}`) if ($leaf->{fillScript}) }, Freetext => $common_freetext_chooser = sub { my $main_order = ($tag eq 'Chooser') ? 'combo' : ($tag eq 'Boolean') ? 'bool' : ($leaf->{editable} eq 'true') ? 'entry' : 'field'; push @{$page->{freetext}}, {%$leaf, main_order => $main_order, help => xml_text($leaf->{help})} if $main_order ne 'hidden'; }, Chooser => \&$common_freetext_chooser, Boolean => \&$common_freetext_chooser, Option => sub { push @{${$page->{freetext}}[-1]->{Option}}, $leaf->{description}; $chooser_hash{$leaf->{description}} = $leaf->{value}; $description{$leaf->{value}} = $leaf->{description}; $disabled{$leaf->{description}} = sub { callback($leaf->{description})}; }); $actions{$tag} and &{$actions{$tag}}; } elsif($leaf=~ /\w\D/) { $tag = $leaf; } } $page; } sub find_page { my ($o, $name) = @_; $_->{name} eq $name and return $_ foreach @$o; } sub display { my ($o, $page) = @_; my $data; if ($page->{no_prev} || $page->{name} eq $welcome->{name}) { $::Wizard_no_previous = 1; } if ($page->{finish}) { $::Wizard_finished = 1; $::Wizard_no_cancel = 1; } if ($page->{nextFinish} eq 'true') { $::Wizard_no_previous = 1; $in->ask_okcancel(translate($page->{name}), translate($page->{info})) or quit_global($in, 0); die; } elsif (!$page->{freetext}) { $in->ask_okcancel(translate($page->{name}), translate($page->{info})) or navigation($o, $page->{old_page}); } else { my $valeur; my @liste; if ($page->{executionLevel} eq 'NORMAL') { $data = map_freetext($page->{freetext}); $in->ask_from($page->{name}, translate($page->{info}), $data) or navigation($o, $page->{old_page}); foreach (@{$page->{freetext}}) { if ($_->{main_order} eq 'bool') { $ENV{$variable{$_->{variableName}}} = $ENV{$variable{$_->{variableName}}} ? 1 : 0; $description{$ENV{$variable{$_->{variableName}}}} = $ENV{$variable{$_->{variableName}}} ? N("enabled") : N("disabled"); } elsif ($_->{main_order} eq 'combo') { $ENV{$variable{$_->{variableName}}} = $chooser_hash{$ENV{$variable{$_->{variableName}}}}; } } } } undef $::Wizard_no_previous; } sub navigation { my ($o, $page, $previous_page) = @_; $page->{old_page} ||= $previous_page; $current_page = $page; display($o, $page); my ($next, $prev) = do { if (defined $perl_module_name && $page->{func}) { my @func_arg = split(/\s/, $page->{func}); my $modStatus = $::{$perl_module_name."::"}{"$func_arg[0]"}->(); if ($page->{Target}->{jumpIndex}) { find_page($o, $page->{Target}->{jumpIndex}->{int($modStatus)}), $page; } else { $page->{next_page}, $page->{old_page}; } } elsif ($page->{jumpScript}) { system("source $lib_script ; $page->{jumpScript}"); if ($page->{Target}->{jumpIndex}) { $? = $? >> 8; find_page($o, $page->{Target}->{jumpIndex}->{$?}), $page; } else { $page->{next_page}, $page; } } elsif ($page->{subWizard}) { my $sub_o = []; my $sub_xmltree = XML::Parser->new(Style => 'Tree')->parsefile($page->{subWizard}); get_parameter($sub_o, $sub_xmltree); eval {navigation($sub_o, $sub_o->[0]); }; $in->exit if $@ =~ /^wizcancel/; $page->{old_page}->{no_prev} = 1; $o->[0], $page, undef; } elsif ($page->{jumpPage}) { find_page($o, $page->{jumpPage}), $page; } else { $page->{next_page}, $page; } }; navigation($o, $next, $prev); } sub is_disabled_summary { my ($widget, $page) = @_; if ($page->{is}) { my ($page_val, $page_arg) = split(/\s*?=\s*/, $page->{is}); if ($page_val eq $widget) { foreach (@{$page->{freetext}}) { my ($val, $arg) = split(/\s*?=\s*/, $_->{is}) if ($_->{is}); $disabled{$_->{variableName}} = defined $page_arg ? ($ENV{$variable{$page_val}} != $page_arg) : !$ENV{$variable{$page_val}}; if ($_->{is} && !$disabled{$_->{variableName}}) { $disabled{$_->{variableName}} = defined $arg ? $ENV{$variable{$val}} != $arg : !$ENV{$variable{$val}}; } } } } is_disabled_summary($widget, $page->{next_page}) if $page->{next_page}; } sub is_disabled { my ($widget, $page) = @_; my $ret; foreach (@{$page->{freetext}}) { if ($_->{is}) { my ($val, $arg) = split(/\s*?=\s*/, $_->{is}); $ret = defined $arg ? $ENV{$variable{$val}} != $arg : !$ENV{$variable{$val}}; } $disabled{$_->{variableName}} = $ret; } } sub callback_common { return 1 if ($disabled{$_[0]} == 1); foreach (keys %variable) { my $toto = $ENV{$variable{$_}}; my $tata = $_; foreach (keys %chooser_hash) { if ($toto eq $_) { $ENV{$variable{$tata}} = $chooser_hash{$_}; } } } 0; } sub callback_summary { return 1 if callback_common($_[0]); is_disabled_summary($_[0], $o2->[0]); } sub callback { return 1 if callback_common($_[0]); is_disabled($_[0], $current_page); } sub get_summary { my ($o, $tree, $tag, $page) = @_; foreach my $leaf (@$tree) { if (ref($leaf) eq 'ARRAY') { $page = get_summary($o, $leaf, $tag, $page); } elsif (ref($leaf) eq 'HASH') { my $common_freetext_chooser; my %actions = ( Wizard => sub { load_wizard(@{$leaf}{ qw(wizardTitle libScript perlModule rpm defaultImage summaryFunc)}) }, Variable => sub { $variable{$leaf->{name}} = $leaf->{shellVariable}; $ENV{$variable{$leaf->{name}}} = $leaf->{defaultValue}; $disabled{$leaf->{name}} = sub { callback_summary($leaf->{name})}; }, Freetext => $common_freetext_chooser = sub { my $main_order = ($tag eq 'Chooser') ? 'combo' : ($tag eq 'Boolean') ? 'bool' : ($leaf->{editable} eq 'true') ? 'entry' : 'hidden'; push @{$summary->{freetext}}, {%$leaf, main_order => $main_order, help => xml_text($leaf->{help})} if $main_order ne 'hidden'; }, Chooser => \&$common_freetext_chooser, Boolean => \&$common_freetext_chooser, Option => sub { push @{${$summary->{freetext}}[-1]->{Option}}, $leaf->{description}; $chooser_hash{$leaf->{description}} = $leaf->{value}; $description{$leaf->{value}} = $leaf->{description}; $disabled{$leaf->{description}} = sub {callback_summary($leaf->{description})}; }); $actions{$tag} and &{$actions{$tag}}; } elsif ($leaf=~ /\w\D/){ $tag = $leaf; } } $page; }