aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ManaTools/Module
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ManaTools/Module')
-rw-r--r--lib/ManaTools/Module/AdminMouse.pm282
-rw-r--r--lib/ManaTools/Module/Clock.pm518
-rw-r--r--lib/ManaTools/Module/DisplayManager.pm298
-rw-r--r--lib/ManaTools/Module/Firewall.pm1208
-rw-r--r--lib/ManaTools/Module/Hosts.pm530
-rw-r--r--lib/ManaTools/Module/LogViewer.pm568
-rw-r--r--lib/ManaTools/Module/Proxy.pm396
-rw-r--r--lib/ManaTools/Module/Services.pm588
-rw-r--r--lib/ManaTools/Module/Users.pm2637
9 files changed, 7025 insertions, 0 deletions
diff --git a/lib/ManaTools/Module/AdminMouse.pm b/lib/ManaTools/Module/AdminMouse.pm
new file mode 100644
index 0000000..279fb76
--- /dev/null
+++ b/lib/ManaTools/Module/AdminMouse.pm
@@ -0,0 +1,282 @@
+# vim: set et ts=4 sw=4:
+#*****************************************************************************
+#
+# Copyright (c) 2013 - 2015 Angelo Naselli <anaselli@linux.it>
+# from drakx services
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2, as
+# published by the Free Software Foundation.
+#
+# 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.
+#
+#*****************************************************************************
+
+# NOTE this module has not been ported and does not work
+# TODO porting it if it is really needed nowadays
+package ManaTools::Module::AdminMouse;
+
+#leaving them atm
+use lib qw(/usr/lib/libDrakX);
+
+# i18n: IMPORTANT: to get correct namespace (drakx-kbd-mouse-x11 instead of libDrakX)
+BEGIN { unshift @::textdomains, 'drakx-kbd-mouse-x11' }
+
+use common;
+use modules;
+use mouse;
+use c;
+
+use ManaTools::Shared;
+
+use yui;
+use Moose;
+
+extends qw( ManaTools::Module );
+
+has '+icon' => (
+ default => "/usr/share/mcc/themes/default/mousedrake-mdk.png",
+);
+
+has '+name' => (
+ default => N("AdminMouse"),
+);
+
+sub start {
+ my $self = shift;
+
+ $self->_adminMouseDialog();
+}
+
+sub _getUntranslatedName {
+ my ($self, $name, $list) = @_;
+
+ foreach my $n (@{$list}) {
+ my @names = split(/\|/, $n);
+ for (my $lev=0; $lev < scalar(@names); $lev++) {
+ if (translate($names[$lev]) eq $name) {
+ return $names[$lev];
+ }
+ }
+ }
+
+ return undef;
+}
+
+
+sub _adminMouseDialog {
+ my $self = shift;
+
+ my $datavalue = "TEST";
+
+ my $appTitle = yui::YUI::app()->applicationTitle();
+
+ ## set new title to get it in dialog
+ yui::YUI::app()->setApplicationTitle($self->name);
+ ## set icon if not already set by external launcher
+ yui::YUI::app()->setApplicationIcon($self->icon);
+
+ my $factory = yui::YUI::widgetFactory;
+
+ my $dialog = $factory->createMainDialog;
+ my $vbox = $factory->createVBox( $dialog );
+ my $frame = $factory->createFrame ($vbox, N("Please choose your type of mouse."));
+ my $treeWidget = $factory->createTree($frame, "");
+
+ my $modules_conf = modules::any_conf->read;
+
+ my $mouse = mouse::read();
+
+ if (!$::noauto) {
+ my $probed_mouse = mouse::detect($modules_conf);
+ $mouse = $probed_mouse if !$mouse->{Protocol} || !$probed_mouse->{unsafe};
+ }
+
+ if (!$mouse || !$::auto) {
+ $mouse ||= mouse::fullname2mouse('Universal|Any PS/2 & USB mice');
+
+ my $prev = my $fullname = $mouse->{type} . '|' . $mouse->{name};
+ my $selected = $mouse->{name};
+
+ my $fullList = { list => [ mouse::_fullnames() ], items => [], separator => '|', val => \$fullname,
+ format => sub { join('|', map { translate($_) } split('\|', $_[0])) } } ;
+ my $i;
+
+ my $itemColl = new yui::YItemCollection;
+ my @items;
+ for ($i=0; $i<scalar(@{$fullList->{list}}); $i++) {
+ my @names = split(/\|/, $fullList->{list}[$i]);
+ for (my $lev=0; $lev < scalar(@names); $lev++) {
+ $names[$lev] = N($names[$lev]);
+ }
+ if ($i == 0 || $names[0] ne $items[0]->{label}) {
+ if ($i != 0) {
+ $itemColl->push($items[0]->{item});
+ push @{$fullList->{items}}, $items[-1]->{item};;
+ }
+ @items = undef;
+ my $item = new yui::YTreeItem ($names[0]);
+
+ if ($selected eq $self->_getUntranslatedName($item->label(), $fullList->{list})) {
+ $item->setSelected(1) ;
+ $item->setOpen(1);
+ my $parent = $item;
+ while($parent = $parent->parent()) {
+ $parent->setOpen(1);
+ }
+ }
+ $item->DISOWN();
+ @items = ({item => $item, label => $names[0], level => 0});
+ for (my $lev=1; $lev < scalar(@names); $lev++) {
+ $item = new yui::YTreeItem ($items[$lev-1]->{item}, $names[$lev]);
+
+ if ($selected eq $self->_getUntranslatedName($item->label(), $fullList->{list})) {
+ $item->setSelected(1) ;
+ $item->setOpen(1);
+ my $parent = $item;
+ while($parent = $parent->parent()) {
+ $parent->setOpen(1);
+ }
+ }
+ $item->DISOWN();
+ if ($lev < scalar(@names)-1) {
+ push @items, {item => $item, label => $names[$lev], level => $lev};
+ }
+ }
+ }
+ else {
+ my $prevItem = 0;
+ for (my $lev=1; $lev < scalar(@names); $lev++) {
+ my $it;
+ for ($it=1; $it < scalar(@items); $it++){
+ if ($items[$it]->{label} eq $names[$lev] && $items[$it]->{level} == $lev) {
+ $prevItem = $it;
+ last;
+ }
+ }
+ if ($it == scalar(@items)) {
+ my $item = new yui::YTreeItem ($items[$prevItem]->{item}, $names[$lev]);
+
+ if ($selected eq $self->_getUntranslatedName($item->label(), $fullList->{list})) {
+ $item->setSelected(1) ;
+ $item->setOpen(1);
+ my $parent = $item;
+ while($parent = $parent->parent()) {
+ $parent->setOpen(1);
+ }
+ }
+ $item->DISOWN();
+ push @items, {item => $item, label => $names[$lev], level => $lev};
+ }
+ }
+ }
+ }
+ $itemColl->push($items[0]->{item});
+ push @{$fullList->{items}}, $items[-1]->{item};
+
+ $treeWidget->addItems($itemColl);
+ my $align = $factory->createLeft($vbox);
+ my $hbox = $factory->createHBox($align);
+ my $aboutButton = $factory->createPushButton($hbox, N("About") );
+ $align = $factory->createRight($hbox);
+ $hbox = $factory->createHBox($align);
+ my $cancelButton = $factory->createPushButton($hbox, N("Cancel") );
+ my $okButton = $factory->createPushButton($hbox, N("Ok") );
+
+ while(1) {
+ my $event = $dialog->waitForEvent();
+ my $eventType = $event->eventType();
+
+ #event type checking
+ if ($eventType == $yui::YEvent::CancelEvent) {
+ last;
+ }
+ elsif ($eventType == $yui::YEvent::WidgetEvent) {
+ # widget selected
+ my $widget = $event->widget();
+
+ if ($widget == $cancelButton) {
+ last;
+ }
+ elsif ($widget == $aboutButton) {
+ my $license = translate($ManaTools::Shared::License);
+ ManaTools::Shared::AboutDialog(
+ { name => N("AdminMouse"),
+ version => $self->VERSION,
+ copyright => N("Copyright (C) %s Mageia community", '2014'),
+ license => $license,
+ comments => N("AdminMouse is the Mageia mouse management tool \n(from the original idea of Mandriva mousedrake)."),
+ website => 'http://www.mageia.org',
+ website_label => N("Mageia"),
+ authors => "Angelo Naselli <anaselli\@linux.it>\nMatteo Pasotti <matteo.pasotti\@gmail.com>",
+ translator_credits =>
+ #-PO: put here name(s) and email(s) of translator(s) (eg: "John Smith <jsmith@nowhere.com>")
+ N("_: Translator(s) name(s) & email(s)\n")}
+ );
+ }
+ elsif ($widget == $okButton) {
+ my $continue = 1;
+ my $selectedItem = $treeWidget->selectedItem();
+
+ my $it=$selectedItem;
+ my $fullname = $self->_getUntranslatedName($it->label(), $fullList->{list});
+ while($it = yui::toYTreeItem($it)->parent()) {
+ $fullname = join("|", $self->_getUntranslatedName($it->label(), $fullList->{list}), $fullname);
+ }
+
+ if ($fullname ne $prev) {
+ my $mouse_ = mouse::fullname2mouse($fullname, device => $mouse->{device});
+ if ($fullname =~ /evdev/) {
+ $mouse_->{evdev_mice} = $mouse_->{evdev_mice_all} = $mouse->{evdev_mice_all};
+ }
+ %$mouse = %$mouse_;
+ }
+
+ if ($mouse->{nbuttons} < 3 ) {
+ $mouse->{Emulate3Buttons} = ManaTools::Shared::ask_YesOrNo('', N("Emulate third button?"));
+ }
+ if ($mouse->{type} eq 'serial') {
+ my @list = ();
+ foreach (detect_devices::serialPorts()) {
+ push @list, detect_devices::serialPort2text($_);
+ }
+ my $choice = ManaTools::Shared::ask_fromList(N("Mouse Port"),
+ N("Please choose which serial port your mouse is connected to."),
+ \@list);
+ if ( !$choice ) {
+ $continue = 0;
+ }
+ else {
+ $mouse->{device} = $choice;
+ }
+ }
+
+ if ($continue) {
+ last;
+ }
+ }
+ }
+ }
+
+ }
+
+ # TODO manage write conf without interactive things
+ # mouse::write_conf($in->do_pkgs, $modules_conf, $mouse, 1);
+ system('systemctl', 'try-restart', 'gpm.service') if -e '/usr/lib/systemd/system/gpm.service';
+
+ ManaTools::Shared::infoMsgBox(N("Not implemented yet: configuration is not changed"));
+
+ $dialog->destroy();
+
+ #restore old application title
+ yui::YUI::app()->setApplicationTitle($appTitle);
+}
+
+1;
diff --git a/lib/ManaTools/Module/Clock.pm b/lib/ManaTools/Module/Clock.pm
new file mode 100644
index 0000000..f2bb5c0
--- /dev/null
+++ b/lib/ManaTools/Module/Clock.pm
@@ -0,0 +1,518 @@
+# vim: set et ts=4 sw=4:
+package ManaTools::Module::Clock;
+#============================================================= -*-perl-*-
+
+=head1 NAME
+
+ManaTools::Module::Clock - This module aims to configure system clock and time
+
+=head1 SYNOPSIS
+
+ my $clockSettings = ManaTools::Module::Clock->new();
+ $clockSettings->start();
+
+=head1 DESCRIPTION
+
+Long_description
+
+=head1 SUPPORT
+
+You can find documentation for this module with the perldoc command:
+
+perldoc ManaTools::Module::Clock
+
+=head1 SEE ALSO
+
+SEE_ALSO
+
+=head1 AUTHOR
+
+Angelo Naselli <anaselli@linux.it>
+
+=head1 COPYRIGHT and LICENSE
+
+Copyright (C) 2014-2015, Angelo Naselli.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License version 2, as
+published by the Free Software Foundation.
+
+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
+
+=head1 FUNCTIONS
+
+=cut
+
+use Moose;
+
+use diagnostics;
+
+use ManaTools::Shared::GUI;
+use ManaTools::Shared::Locales;
+use ManaTools::Shared::TimeZone;
+
+use Time::Piece;
+
+use yui;
+
+extends qw( ManaTools::Module );
+
+### TODO icon
+has '+icon' => (
+ default => "/usr/share/mcc/themes/default/time-mdk.png",
+);
+
+has 'loc' => (
+ is => 'rw',
+ init_arg => undef,
+ builder => '_localeInitialize'
+);
+
+sub _localeInitialize {
+ my $self = shift;
+
+ # TODO fix domain binding for translation
+ $self->loc(ManaTools::Shared::Locales->new(domain_name => 'libDrakX-standalone') );
+ # TODO if we want to give the opportunity to test locally add dir_name => 'path'
+}
+
+has 'sh_gui' => (
+ is => 'rw',
+ lazy => 1,
+ init_arg => undef,
+ builder => '_SharedGUIInitialize'
+);
+
+sub _SharedGUIInitialize {
+ my $self = shift;
+
+ $self->sh_gui(ManaTools::Shared::GUI->new() );
+}
+
+has 'sh_tz' => (
+ is => 'rw',
+ lazy => 1,
+ builder => '_SharedTimeZoneInitialize'
+);
+
+sub _SharedTimeZoneInitialize {
+ my $self = shift;
+
+ $self->sh_tz(ManaTools::Shared::TimeZone->new() );
+}
+
+
+=head1 VERSION
+
+Version 1.0.0
+
+=cut
+
+our $VERSION = '1.0.0';
+
+#=============================================================
+
+=head2 BUILD
+
+=head3 INPUT
+
+ $self: this object
+
+=head3 DESCRIPTION
+
+ The BUILD method is called after a Moose object is created,
+ in this methods Services loads all the service information.
+
+=cut
+
+#=============================================================
+sub BUILD {
+ my $self = shift;
+
+ if (! $self->name) {
+ $self->name ($self->loc->N("Date, Clock & Time Zone Settings"));
+ }
+}
+
+#=============================================================
+
+=head2 start
+
+=head3 INPUT
+
+ $self: this object
+
+=head3 DESCRIPTION
+
+ This method extends Module::start and is invoked to
+ start admin clock
+
+=cut
+
+#=============================================================
+sub start {
+ my $self = shift;
+
+ $self->_adminClockPanel();
+};
+
+### _get_NTPservers
+## returns ntp servers in the format
+## Zone|Nation: server
+#
+sub _get_NTPservers {
+ my $self = shift;
+
+ my $servs = $self->sh_tz->ntpServers();
+ [ map { "$servs->{$_}|$_" } sort { $servs->{$a} cmp $servs->{$b} || $a cmp $b } keys %$servs ];
+}
+
+### _restoreValues
+## restore NTP server and Time Zone from configuration files
+#
+## input '$datetime_only' restore date and time only
+#
+## returns 'info', a HASH references containing:
+## time_zone => time zone hash reference to be restored
+## ntp_server => ntp server address
+## date => date string
+## time => time string
+## ntp_running => is NTP running?
+#
+sub _restoreValues {
+ my ($self, $datetime_only) = @_;
+
+ my $info;
+ if (!$datetime_only) {
+ $info->{time_zone} = $self->sh_tz->readConfiguration();
+ $info->{ntp_server} = $self->sh_tz->ntpCurrentServer();
+ #- strip digits from \d+.foo.pool.ntp.org
+ $info->{ntp_server} =~ s/^\d+\.// if $info->{ntp_server};
+ $info->{ntp_running} = $self->sh_tz->isNTPRunning();
+ }
+ my $t = localtime;
+ my $day = $t->strftime("%F");
+ my $time = $t->strftime("%H:%M:%S");
+ $info->{date} = $day;
+ $info->{time} = $time;
+
+ return $info;
+}
+
+sub _adminClockPanel {
+ my $self = shift;
+
+ my $appTitle = yui::YUI::app()->applicationTitle();
+
+ ## set new title to get it in dialog
+ yui::YUI::app()->setApplicationTitle($self->name);
+ ## set icon if not already set by external launcher
+ yui::YUI::app()->setApplicationIcon($self->icon);
+
+ my $factory = yui::YUI::widgetFactory;
+ my $optFactory = yui::YUI::optionalWidgetFactory;
+ die "calendar widgets missing" if (!$optFactory->hasDateField() || !$optFactory->hasTimeField());
+
+ # Create Dialog
+ my $dialog = $factory->createMainDialog;
+# my $minSize = $factory->createMinSize($dialog, 40, 15);
+
+ # Start Dialog layout:
+ my $layout = $factory->createVBox($dialog);
+ my $align = $factory->createLeft($layout);
+
+ my $frame = $factory->createFrame($align, $self->loc->N("Setting date and time"));
+ my $hbox = $factory->createHBox($frame);
+
+ my $dateField = $optFactory->createDateField($hbox, "");
+ $factory->createHSpacing($hbox, 3.0);
+ my $timeField = $optFactory->createTimeField($hbox, "");
+ $factory->createHSpacing($hbox, 1.0);
+ $factory->createVSpacing($hbox, 1.0);
+ $factory->createVSpacing($layout, 1.0);
+
+ $align = $factory->createLeft($layout);
+ $hbox = $factory->createHBox($align);
+ my $ntpFrame = $factory->createCheckBoxFrame($hbox, $self->loc->N("Enable Network Time Protocol"), 0);
+
+ my $hbox1 = $factory->createHBox($ntpFrame);
+ my $changeNTPButton = $factory->createPushButton($hbox1, $self->loc->N("Change &NTP server"));
+ $factory->createHSpacing($hbox1, 1.0);
+ $factory->createLabel($hbox1,$self->loc->N("Current:"));
+ $factory->createHSpacing($hbox1, 1.0);
+ my $ntpLabel = $factory->createLabel($hbox1, $self->loc->N("not defined"));
+ $factory->createHSpacing($hbox1, 1.0);
+ $ntpLabel->setWeight($yui::YD_HORIZ, 2);
+ $changeNTPButton->setWeight($yui::YD_HORIZ, 1);
+ $factory->createHSpacing($hbox, 1.0);
+
+ $factory->createVSpacing($layout, 1.0);
+ $align = $factory->createLeft($layout);
+ $hbox = $factory->createHBox($align);
+ $frame = $factory->createFrame ($hbox, $self->loc->N("TimeZone"));
+ $hbox1 = $factory->createHBox( $frame );
+ my $changeTZButton = $factory->createPushButton($hbox1, $self->loc->N("Change &Time Zone"));
+ $factory->createHSpacing($hbox1, 1.0);
+ $factory->createLabel($hbox1,$self->loc->N("Current:"));
+ $factory->createHSpacing($hbox1, 1.0);
+ my $timeZoneLbl = $factory->createLabel($hbox1, $self->loc->N("not defined"));
+ $factory->createHSpacing($hbox1, 1.0);
+ $timeZoneLbl->setWeight($yui::YD_HORIZ, 2);
+ $changeTZButton->setWeight($yui::YD_HORIZ, 1);
+
+ $factory->createHSpacing($hbox, 1.0);
+
+ # buttons on the last line
+ $factory->createVSpacing($layout, 1.0);
+ $hbox = $factory->createHBox($layout);
+
+ $align = $factory->createLeft($hbox);
+ $hbox = $factory->createHBox($align);
+ my $aboutButton = $factory->createPushButton($hbox, $self->loc->N("&About") );
+ my $resetButton = $factory->createPushButton($hbox, $self->loc->N("&Reset") );
+
+ $align = $factory->createRight($hbox);
+ $hbox = $factory->createHBox($align);
+ my $cancelButton = $factory->createPushButton($hbox, $self->loc->N("&Cancel"));
+ my $okButton = $factory->createPushButton($hbox, $self->loc->N("&Ok"));
+ $factory->createHSpacing($hbox, 1.0);
+
+ ## no changes by default
+ $dialog->setDefaultButton($cancelButton);
+
+ # End Dialof layout
+
+ ## default value
+ my $info = $self->_restoreValues();
+
+ $dateField->setValue($info->{date});
+ $timeField->setValue($info->{time});
+
+ if (exists $info->{time_zone} && $info->{time_zone}->{ZONE}) {
+ $timeZoneLbl->setValue($info->{time_zone}->{ZONE});
+ }
+
+ if ($info->{ntp_server}) {
+ $ntpLabel->setValue($info->{ntp_server});
+ }
+ $ntpFrame->setValue($info->{ntp_running});
+
+
+ # get only once
+ my $NTPservers = $self->_get_NTPservers();
+
+ while(1) {
+ my $event = $dialog->waitForEvent(1000);
+ my $eventType = $event->eventType();
+
+ #event type checking
+ if ($eventType == $yui::YEvent::CancelEvent) {
+ last;
+ }
+ elsif ($eventType == $yui::YEvent::TimeoutEvent) {
+ my $t = Time::Piece->strptime($timeField->value(), "%H:%M:%S") + 1;
+ $timeField->setValue($t->strftime("%H:%M:%S"));
+ }
+ elsif ($eventType == $yui::YEvent::WidgetEvent) {
+ # widget selected
+ my $widget = $event->widget();
+ if ($widget == $cancelButton) {
+ last;
+ }
+ elsif ($widget == $okButton) {
+ yui::YUI::app()->busyCursor();
+ my $finished = 1;
+ # (1) write new TZ settings
+ # (2) write new NTP settigs if checked
+ # (3) use date time fields if NTP is not checked
+
+ my $old_conf = $self->sh_tz->readConfiguration();
+ if ($info->{time_zone}->{UTC} != $old_conf->{UTC} ||
+ $info->{time_zone}->{ZONE} ne $old_conf->{ZONE}) {
+ # (1)
+ eval { $self->sh_tz->writeConfiguration($info->{time_zone}) };
+ my $errors = $@;
+ if ($errors) {
+ $finished = 0;
+ $self->sh_gui->warningMsgBox({
+ title => $self->loc->N("Write configuration failed"),
+ text => "$errors",
+ richtext => 1,
+ });
+ }
+ }
+ if ($ntpFrame->value()) {
+ # (2)
+ if ($info->{ntp_server}) {
+ eval { $self->sh_tz->setNTPServer($info->{ntp_server}) };
+ my $errors = $@;
+ if ($errors) {
+ $finished = 0;
+ $self->sh_gui->warningMsgBox({
+ title => $self->loc->N("Set NTP failed"),
+ text => "$errors",
+ richtext => 1,
+ });
+ }
+ }
+ else {
+ $self->sh_gui->warningMsgBox({text => $self->loc->N("Please enter a valid NTP server address.")});
+ $finished = 0;
+ }
+ }
+ else {
+ my $t = Time::Piece->strptime($dateField->value()."T".$timeField->value(),
+ "%Y-%m-%dT%H:%M:%S"
+ );
+ eval {
+ $self->sh_tz->disableAndStopNTP();
+ # (3)
+ $self->sh_tz->setTime($t->epoch());
+ };
+ my $errors = $@;
+ if ($errors) {
+ $finished = 0;
+ $self->sh_gui->warningMsgBox({
+ title => $self->loc->N("Set system time failed"),
+ text => "$errors",
+ richtext => 1,
+ });
+ }
+ }
+ yui::YUI::app()->normalCursor();
+
+ last if ($finished);
+ }
+ elsif ($widget == $changeNTPButton) {
+ # get time to calculate elapsed
+ my $t0 = localtime;
+ my $item = $self->sh_gui->ask_fromTreeList({title => $self->loc->N("NTP server - DrakClock"),
+ header => $self->loc->N("Choose your NTP server"),
+ default_button => 1,
+ item_separator => '|',
+ default_item => $info->{ntp_server},
+ skip_path => 1,
+ list => $NTPservers});
+ if ($item) {
+ $ntpLabel->setValue($item);
+ $info->{ntp_server} = $item;
+ }
+ # fixing elapsed time (dialog is modal)
+ my $t1 = localtime;
+ my $elapsed = $t1->epoch - $t0->epoch;
+
+ my $t = Time::Piece->strptime($dateField->value() . "T" . $timeField->value(),
+ '%Y-%m-%dT%H:%M:%S') + $elapsed;
+ $timeField->setValue($t->strftime("%H:%M:%S"));
+ $dateField->setValue($t->strftime("%F"));
+ }
+ elsif ($widget == $changeTZButton) {
+ # get time to calculate elapsed
+ my $t0 = localtime;
+ my $timezones = $self->sh_tz->getTimeZones();
+ if (!$timezones || scalar (@{$timezones}) == 0) {
+ $self->sh_gui->warningMsgBox({title => $self->loc->N("Timezone - DrakClock"),
+ text => $self->loc->N("Failed to retrieve timezone list"),
+ });
+ $changeTZButton->setDisabled();
+ }
+ else {
+ my $item = $self->sh_gui->ask_fromTreeList({title => $self->loc->N("Timezone - DrakClock"),
+ header => $self->loc->N("Which is your timezone?"),
+ default_button => 1,
+ item_separator => '/',
+ default_item => $info->{time_zone}->{ZONE},
+ list => $timezones});
+ if ($item) {
+ my $utc = 0;
+ if ($info->{time_zone}->{UTC} ) {
+ $utc = $info->{time_zone}->{UTC};
+ }
+ $utc = $self->sh_gui->ask_YesOrNo({
+ title => $self->loc->N("GMT - manaclock"),
+ text => $self->loc->N("Is your hardware clock set to GMT?"),
+ default_button => 1,
+ });
+ $info->{time_zone}->{UTC} = $utc;
+ $info->{time_zone}->{ZONE} = $item;
+ $timeZoneLbl->setValue($info->{time_zone}->{ZONE});
+ }
+ }
+ # fixing elapsed time (dialog is modal)
+ my $t1 = localtime;
+ my $elapsed = $t1->epoch - $t0->epoch;
+
+ my $t = Time::Piece->strptime($dateField->value() . "T" . $timeField->value(),
+ '%Y-%m-%dT%H:%M:%S') + $elapsed;
+ $timeField->setValue($t->strftime("%H:%M:%S"));
+ $dateField->setValue($t->strftime("%F"));
+ }
+ elsif ($widget == $resetButton) {
+ my $datetime_only = $self->sh_gui->ask_YesOrNo({
+ title => $self->loc->N("Restore data"),
+ text => $self->loc->N("Restore date and time only?"),
+ default_button => 1, #Yes
+ });
+ my $newInfo = $self->_restoreValues($datetime_only);
+ if ($datetime_only) {
+ $info->{date} = $newInfo->{date};
+ $info->{time} = $newInfo->{time};
+ }
+ else{
+ $info = $newInfo;
+ }
+
+ $dateField->setValue($info->{date});
+ $timeField->setValue($info->{time});
+ if (exists $info->{time_zone} && $info->{time_zone}->{ZONE}) {
+ $timeZoneLbl->setValue($info->{time_zone}->{ZONE});
+ }
+ else {
+ $timeZoneLbl->setValue($self->loc->N("not defined"));
+ }
+ if ($info->{ntp_server}) {
+ $ntpLabel->setValue($info->{ntp_server});
+ }
+ else {
+ $ntpLabel->setValue($self->loc->N("not defined"));
+ }
+ $ntpFrame->setValue($info->{ntp_running});
+ }
+ elsif($widget == $aboutButton) {
+ my $translators = $self->loc->N("_: Translator(s) name(s) & email(s)\n");
+ $translators =~ s/\</\&lt\;/g;
+ $translators =~ s/\>/\&gt\;/g;
+ $self->sh_gui->AboutDialog({ name => $self->name,
+ version => $self->VERSION,
+ credits => $self->loc->N("Copyright (C) %s Mageia community", '2014-2015'),
+ license => $self->loc->N("GPLv2"),
+ description => $self->loc->N("Date, Clock & Time Zone Settings allows to setup time zone and adjust date and time"),
+ authors => $self->loc->N("<h3>Developers</h3>
+ <ul><li>%s</li>
+ <li>%s</li>
+ </ul>
+ <h3>Translators</h3>
+ <ul><li>%s</li></ul>",
+ "Angelo Naselli &lt;anaselli\@linux.it&gt;",
+ $translators
+ ),
+ }
+ );
+ }
+ }
+ }
+ $dialog->destroy();
+
+ #restore old application title
+ yui::YUI::app()->setApplicationTitle($appTitle) if $appTitle;
+}
+
+
+
diff --git a/lib/ManaTools/Module/DisplayManager.pm b/lib/ManaTools/Module/DisplayManager.pm
new file mode 100644
index 0000000..39aa617
--- /dev/null
+++ b/lib/ManaTools/Module/DisplayManager.pm
@@ -0,0 +1,298 @@
+# vim: set et ts=4 sw=4:
+#*****************************************************************************
+#
+# Copyright (c) 2013-2015 Matteo Pasotti <matteo.pasotti@gmail.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2, as
+# published by the Free Software Foundation.
+#
+# 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.
+#
+#*****************************************************************************
+
+package ManaTools::Module::DisplayManager;
+
+use Modern::Perl '2011';
+use autodie;
+use Moose;
+use POSIX qw(ceil);
+use English;
+use utf8;
+
+use yui;
+use ManaTools::Shared qw(trim apcat);
+use ManaTools::Shared::GUI;
+# use ManaTools::Shared::DisplayManager;
+
+# TODROP but provides network::network
+use lib qw(/usr/lib/libDrakX);
+use network::network;
+use MDK::Common::System qw(getVarsFromSh addVarsInSh);
+use MDK::Common::Func qw(find);
+
+extends qw( ManaTools::Module );
+
+
+has '+icon' => (
+ default => "/usr/share/mcc/themes/default/drakedm-mdk.png",
+);
+
+has '+name' => (
+ default => "DisplayManager",
+);
+
+=head1 VERSION
+
+Version 1.0.0
+
+=cut
+
+our $VERSION = '1.0.0';
+
+has 'dialog' => (
+ is => 'rw',
+ init_arg => undef
+);
+
+has 'conffile' => (
+ is => 'rw',
+ isa => 'Str',
+ default => '/etc/sysconfig/desktop',
+);
+
+has 'dmlist' => (
+ is => 'rw',
+ isa => 'ArrayRef',
+ builder => '_build_dmlist',
+);
+
+has 'desc_for_i18n' => (
+ is => 'rw',
+ isa => 'ArrayRef',
+);
+
+has 'sh_gui' => (
+ is => 'rw',
+ init_arg => undef,
+ builder => '_SharedUGUIInitialize'
+);
+
+has 'loc' => (
+ is => 'rw',
+ init_arg => undef,
+ builder => '_localeInitialize'
+);
+
+sub _build_desc_for_i18n {
+ my $self = shift();
+
+ my @_DESCRIPTIONS_for_i18n = (
+ $self->loc->N("LightDM (The Light Display Manager)"),
+ $self->loc->N("GDM (GNOME Display Manager)"),
+ $self->loc->N("KDM (KDE Display Manager)"),
+ $self->loc->N("XDM (X Display Manager)"),
+ );
+
+ $self->desc_for_i18n(\@_DESCRIPTIONS_for_i18n);
+
+ return 1;
+}
+
+sub _build_dmlist {
+ my $self = shift();
+
+ my @list = map {
+ my %l = map { /(\S+)=(.*)/ } apcat($_);
+ \%l;
+ } sort(glob("/usr/share/X11/dm.d/*.conf"));
+ return \@list;
+}
+
+sub _localeInitialize {
+ my $self = shift();
+
+ # TODO fix domain binding for translation
+ $self->loc(ManaTools::Shared::Locales->new(domain_name => 'drakdm') );
+ # TODO if we want to give the opportunity to test locally add dir_name => 'path'
+}
+
+sub _SharedUGUIInitialize {
+ my $self = shift();
+
+ $self->sh_gui( ManaTools::Shared::GUI->new() );
+}
+
+#=============================================================
+
+=head2 start
+
+=head3 INPUT
+
+ $self: this object
+
+=head3 DESCRIPTION
+
+ This method extends Module::start and is invoked to
+ start proxy manager
+
+=cut
+
+#=============================================================
+sub start {
+ my $self = shift;
+
+ if ($EUID != 0) {
+ $self->sh_gui->warningMsgBox({
+ title => $self->name,
+ text => $self->loc->N("root privileges required"),
+ });
+ return;
+ }
+
+ # initialize dm descriptions for i18n
+ $self->_build_desc_for_i18n();
+
+ $self->_manageProxyDialog();
+};
+
+#=============================================================
+
+=head2 ask_for_X_restart
+
+=head3 INPUT
+
+ $self: this object
+
+=head3 DESCRIPTION
+
+ This method shows a message box warning the user
+ that a X server restart is required
+
+=cut
+
+#=============================================================
+
+sub ask_for_X_restart {
+ my $self = shift;
+
+ $self->sh_gui->warningMsgBox({title=>$self->loc->N("X Restart Required"),text=>$self->loc->N("You need to log out and back in again for changes to take effect"),richtext=>1});
+}
+
+sub _manageProxyDialog {
+ my $self = shift;
+
+ ## TODO fix for manatools
+ my $appTitle = yui::YUI::app()->applicationTitle();
+ my $appIcon = yui::YUI::app()->applicationIcon();
+ ## set new title to get it in dialog
+ my $newTitle = $self->loc->N("Display Manager");
+ yui::YUI::app()->setApplicationTitle($newTitle);
+
+ my $factory = yui::YUI::widgetFactory;
+ my $optional = yui::YUI::optionalWidgetFactory;
+
+ my $label_width = 25;
+ my $inputfield_width = 45;
+
+ my ($dm_NAME) = apcat($self->conffile) =~ /^DISPLAYMANAGER=(.*)/m;
+ my $dm = (MDK::Common::Func::find { uc($_->{NAME}) eq uc($dm_NAME) } @{$self->dmlist});
+
+ $self->dialog($factory->createMainDialog());
+ my $layout = $factory->createVBox($self->dialog);
+
+ my $hbox_header = $factory->createHBox($layout);
+ my $headLeft = $factory->createHBox($factory->createLeft($hbox_header));
+ my $headRight = $factory->createHBox($factory->createRight($hbox_header));
+
+ my $logoImage = $factory->createImage($headLeft, $appIcon);
+ my $labelAppDescription = $factory->createLabel($headRight,$newTitle);
+ $logoImage->setWeight($yui::YD_HORIZ,0);
+ $labelAppDescription->setWeight($yui::YD_HORIZ,3);
+
+ # app description
+ my $hbox_content = $factory->createHBox($layout);
+ $factory->createLabel($hbox_content, $self->loc->N("Choosing a display manager"));
+
+ $hbox_content = $factory->createHBox($layout);
+
+ my $vbox_spacer = $factory->createVBox($hbox_content);
+ $factory->createHSpacing($vbox_spacer,2);
+ my $vbox_labels_flags = $factory->createVBox($hbox_content);
+ my $vbox_inputfields = $factory->createVBox($hbox_content);
+
+ # list of desktop managers
+ my $rb_group = $factory->createRadioButtonGroup($vbox_labels_flags);
+ my $rbbox = $factory->createVBox($rb_group);
+ foreach my $d (@{$self->dmlist()})
+ {
+ my $rowentry = $factory->createHBox($factory->createLeft($rbbox));
+ my $rb = $factory->createRadioButton($rowentry, $d->{NAME});
+ $rb->setWeight($yui::YD_HORIZ, 1);
+ my $desc = $factory->createLabel($rowentry, $self->loc->N($d->{DESCRIPTION}));
+ $desc->setWeight($yui::YD_HORIZ, 2);
+ if($d->{PACKAGE} eq lc($dm_NAME))
+ {
+ $rb->setValue(1);
+ }
+ $rb_group->addRadioButton($rb);
+ $rb->DISOWN();
+ }
+ my $hbox_filler = $factory->createHBox($layout);
+ $factory->createSpacing($hbox_filler,$yui::YD_VERT,2);
+
+ my $hbox_foot = $factory->createHBox($layout);
+ my $vbox_foot_left = $factory->createVBox($factory->createLeft($hbox_foot));
+ my $vbox_foot_right = $factory->createVBox($factory->createRight($hbox_foot));
+ my $aboutButton = $factory->createPushButton($vbox_foot_left,$self->loc->N("&About"));
+ my $cancelButton = $factory->createPushButton($vbox_foot_right,$self->loc->N("&Cancel"));
+ my $okButton = $factory->createPushButton($vbox_foot_right,$self->loc->N("&OK"));
+
+ # main loop
+ while(1) {
+ my $event = $self->dialog->waitForEvent();
+ my $eventType = $event->eventType();
+
+ #event type checking
+ if ($eventType == $yui::YEvent::CancelEvent) {
+ last;
+ }
+ elsif ($eventType == $yui::YEvent::WidgetEvent) {
+### Buttons and widgets ###
+ my $widget = $event->widget();
+ if ($widget == $cancelButton) {
+ last;
+ }elsif ($widget == $aboutButton) {
+ $self->sh_gui->AboutDialog({
+ name => $appTitle,
+ version => $VERSION,
+ credits => "Copyright (c) 2013-2015 by Matteo Pasotti",
+ license => "GPLv2",
+ description => $self->loc->N("Graphical configurator for system Display Manager"),
+ authors => "Matteo Pasotti &lt;matteo.pasotti\@gmail.com&gt;"
+ }
+ );
+ }elsif ($widget == $okButton) {
+ my $current_choice = ManaTools::Shared::trim($rb_group->currentButton()->label());
+ $current_choice =~s/\&//g;
+ addVarsInSh($self->conffile, { DISPLAYMANAGER => lc($current_choice) } );
+ $self->ask_for_X_restart();
+ last;
+ }
+ }
+ }
+
+ $self->dialog->destroy() ;
+
+ #restore old application title
+ yui::YUI::app()->setApplicationTitle($appTitle);
+}
+
+1;
diff --git a/lib/ManaTools/Module/Firewall.pm b/lib/ManaTools/Module/Firewall.pm
new file mode 100644
index 0000000..2ac56a5
--- /dev/null
+++ b/lib/ManaTools/Module/Firewall.pm
@@ -0,0 +1,1208 @@
+# vim: set et ts=4 sw=4:
+#*****************************************************************************
+#
+# Copyright (c) 2013-2015 Matteo Pasotti <matteo.pasotti@gmail.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2, as
+# published by the Free Software Foundation.
+#
+# 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.
+#
+#*****************************************************************************
+
+package ManaTools::Module::Firewall;
+
+use Modern::Perl '2011';
+use autodie;
+use Moose;
+use Moose::Autobox;
+use utf8;
+
+use yui;
+use ManaTools::Shared qw(trim);
+use ManaTools::Shared::GUI;
+use ManaTools::Shared::Firewall;
+use ManaTools::Shared::Shorewall;
+use ManaTools::Shared::Services;
+
+use MDK::Common::Func qw(if_ partition);
+use MDK::Common::System qw(getVarsFromSh);
+use MDK::Common::Various qw(text2bool to_bool);
+use MDK::Common::DataStructure qw(intersection);
+use MDK::Common::File qw(substInFile output_with_perm);
+
+use List::Util qw(any);
+use List::MoreUtils qw(uniq);
+
+extends qw( ManaTools::Module );
+
+has '+icon' => (
+ default => "/usr/share/icons/manawall.png",
+);
+
+has '+name' => (
+ default => "Firewall Manager",
+);
+
+=head1 VERSION
+
+Version 1.0.0
+
+=cut
+
+our $VERSION = '1.0.0';
+
+has 'dialog' => (
+ is => 'rw',
+ init_arg => undef
+);
+
+has 'sh_gui' => (
+ is => 'rw',
+ init_arg => undef,
+ builder => '_SharedUGUIInitialize'
+);
+
+has 'loc' => (
+ is => 'rw',
+ init_arg => undef,
+ builder => '_localeInitialize',
+ required => 1,
+);
+
+has 'all_servers' => (
+ is => 'rw',
+ init_arg => undef,
+ isa => 'ArrayRef',
+);
+
+has 'ifw_rules' => (
+ is => 'rw',
+ init_arg => undef,
+ isa => 'ArrayRef',
+);
+
+has 'wdg_ifw' => (
+ is => 'rw',
+ init_arg => undef,
+ isa => 'ArrayRef',
+ default => sub { [] },
+);
+
+has 'wdg_servers' => (
+ is => 'rw',
+ init_arg => undef,
+ isa => 'ArrayRef',
+ default => sub { [] },
+);
+
+has 'net' => (
+ is => 'rw',
+ init_arg => undef,
+ isa => 'HashRef',
+ builder => '_initNet',
+);
+
+has 'unlisted' => (
+ is => 'rw',
+ init_arg => undef,
+ isa => 'ArrayRef',
+ builder => '_initUnlisted',
+);
+
+has 'log_net_drop' => (
+ is => 'rw',
+ isa => 'Bool',
+ default => sub { return 1; }
+);
+
+has 'aboutDialog' => (
+ is => 'ro',
+ init_arg => undef,
+ isa => 'HashRef',
+ builder => '_setupAboutDialog',
+);
+
+sub _setupAboutDialog {
+ my $self = shift();
+ return {
+ name => "",
+ version => $VERSION,
+ credits => "Copyright (c) 2013-2015 by Matteo Pasotti",
+ license => "GPLv2",
+ description => "",
+ authors => "Matteo Pasotti &lt;matteo.pasotti\@gmail.com&gt;"
+ };
+}
+
+sub _localeInitialize {
+ my $self = shift();
+
+ # TODO fix domain binding for translation
+ $self->loc(ManaTools::Shared::Locales->new(domain_name => 'drakx-net') );
+ # TODO if we want to give the opportunity to test locally add dir_name => 'path'
+}
+
+sub _SharedUGUIInitialize {
+ my $self = shift();
+
+ $self->sh_gui(ManaTools::Shared::GUI->new() );
+}
+
+sub _initAllServers {
+ my $self = shift();
+ my @all_servers = (
+ {
+ id => 'www',
+ name => $self->loc->N("Web Server"),
+ pkg => 'apache apache-mod_perl boa lighttpd thttpd',
+ ports => '80/tcp 443/tcp',
+ },
+ {
+ id => 'dns',
+ name => $self->loc->N("Domain Name Server"),
+ pkg => 'bind dnsmasq mydsn',
+ ports => '53/tcp 53/udp',
+ },
+ {
+ id => 'ssh',
+ name => $self->loc->N("SSH server"),
+ pkg => 'openssh-server',
+ ports => '22/tcp',
+ },
+ {
+ id => 'ftp',
+ name => $self->loc->N("FTP server"),
+ pkg => 'ftp-server-krb5 wu-ftpd proftpd pure-ftpd',
+ ports => '20/tcp 21/tcp',
+ },
+ {
+ id => 'dhcp',
+ name => $self->loc->N("DHCP Server"),
+ pkg => 'dhcp-server udhcpd',
+ ports => '67/udp 68/udp',
+ hide => 1,
+ },
+ {
+ id => 'mail',
+ name => $self->loc->N("Mail Server"),
+ pkg => 'sendmail postfix qmail exim',
+ ports => '25/tcp 465/tcp 587/tcp',
+ },
+ {
+ id => 'popimap',
+ name => $self->loc->N("POP and IMAP Server"),
+ pkg => 'imap courier-imap-pop',
+ ports => '109/tcp 110/tcp 143/tcp 993/tcp 995/tcp',
+ },
+ {
+ id => 'telnet',
+ name => $self->loc->N("Telnet server"),
+ pkg => 'telnet-server-krb5',
+ ports => '23/tcp',
+ hide => 1,
+ },
+ {
+ id => 'nfs',
+ name => $self->loc->N("NFS Server"),
+ pkg => 'nfs-utils nfs-utils-clients',
+ ports => '111/tcp 111/udp 2049/tcp 2049/udp ' . network::nfs::list_nfs_ports(),
+ hide => 1,
+ prepare => sub { network::nfs::write_nfs_ports(network::nfs::read_nfs_ports()) },
+ restart => 'nfs-common nfs-server',
+ },
+ {
+ id => 'smb',
+ name => $self->loc->N("Windows Files Sharing (SMB)"),
+ pkg => 'samba-server',
+ ports => '137/tcp 137/udp 138/tcp 138/udp 139/tcp 139/udp 445/tcp 445/udp 1024:1100/tcp 1024:1100/udp',
+ hide => 1,
+ },
+ {
+ id => 'bacula',
+ name => $self->loc->N("Bacula backup"),
+ pkg => 'bacula-fd bacula-sd bacula-dir-common',
+ ports => '9101:9103/tcp',
+ hide => 1,
+ },
+ {
+ id => 'syslog',
+ name => $self->loc->N("Syslog network logging"),
+ pkg => 'rsyslog syslog-ng',
+ ports => '514/udp',
+ hide => 1,
+ },
+ {
+ id => 'cups',
+ name => $self->loc->N("CUPS server"),
+ pkg => 'cups',
+ ports => '631/tcp 631/udp',
+ hide => 1,
+ },
+ {
+ id => 'mysql',
+ name => $self->loc->N("MySQL server"),
+ pkg => 'mysql',
+ ports => '3306/tcp 3306/udp',
+ hide => 1,
+ },
+ {
+ id => 'postgresql',
+ name => $self->loc->N("PostgreSQL server"),
+ pkg => 'postgresql8.2 postgresql8.3',
+ ports => '5432/tcp 5432/udp',
+ hide => 1,
+ },
+ {
+ id => 'echo',
+ name => $self->loc->N("Echo request (ping)"),
+ ports => '8/icmp',
+ force_default_selection => 0,
+ },
+ {
+ id => 'zeroconf',
+ name => $self->loc->N("Network services autodiscovery (zeroconf and slp)"),
+ ports => '5353/udp 427/udp',
+ pkg => 'avahi cups openslp',
+ },
+ {
+ id => 'bittorrent',
+ name => $self->loc->N("BitTorrent"),
+ ports => '6881:6999/tcp 6881:6999/udp',
+ hide => 1,
+ pkg => 'bittorrent deluge ktorrent transmission vuze rtorrent ctorrent',
+ },
+ {
+ id => 'wmds',
+ name => $self->loc->N("Windows Mobile device synchronization"),
+ pkg => 'synce-hal',
+ ports => '990/tcp 999/tcp 5678/tcp 5679/udp 26675/tcp',
+ hide => 1,
+ },
+ );
+ return \@all_servers;
+}
+
+sub _initIFW {
+ my $self = shift();
+ my @ifw_rules = (
+ {
+ id => 'psd',
+ name => $self->loc->N("Port scan detection"),
+ ifw_rule => 'psd',
+ },
+ );
+ return \@ifw_rules;
+}
+
+sub _initNet {
+ my $self = shift();
+ my $net = {};
+ network::network::read_net_conf($net);
+ return $net;
+}
+
+sub _initUnlisted {
+ my $self = shift();
+ my @unlisted = ();
+ return \@unlisted;
+}
+
+#=============================================================
+
+sub check_ports_syntax {
+ my ($ports) = @_;
+ foreach (split ' ', $ports) {
+ my ($nb, $range, $nb2) = m!^(\d+)(:(\d+))?/(tcp|udp|icmp)$! or return $_;
+ foreach my $port ($nb, if_($range, $nb2)) {
+ 1 <= $port && $port <= 65535 or return $_;
+ }
+ $nb < $nb2 or return $_ if $range;
+ }
+ return '';
+}
+
+#=============================================================
+
+=head2 port2server
+
+=head3 INPUT
+
+ $self: this object
+
+ $ports: port object
+
+=head3 DESCRIPTION
+
+ This method retrieves the server from a given port
+
+=cut
+
+#=============================================================
+
+sub port2server {
+ my $self = shift();
+ my ($port) = @_;
+ for my $service(@{$self->all_servers()})
+ {
+ if(any { $port eq $_ } split(' ', $service->{ports}))
+ {
+ return $service;
+ }
+ }
+ return 0;
+}
+
+#=============================================================
+
+=head2 to_ports
+
+=head3 INPUT
+
+ $self: this object
+
+=head3 DESCRIPTION
+
+ This method converts from server definitions to port definitions
+
+=cut
+
+#=============================================================
+
+sub to_ports {
+ my ($self, $servers) = @_;
+ my $ports = join(' ', (map { $_->{ports} } @$servers), @{$self->unlisted()});
+ return $ports;
+}
+
+#=============================================================
+
+=head2 from_ports
+
+=head3 INPUT
+
+ $self: this object
+
+ $ports: ports object
+
+=head3 DESCRIPTION
+
+ This method does...
+
+=cut
+
+#=============================================================
+
+sub from_ports {
+ my $self = shift();
+ my ($ports) = @_;
+
+ my @l;
+ foreach (split ' ', $ports) {
+ if (my $s = $self->port2server($_)) {
+ push @l, $s;
+ } else {
+ push (@{$self->unlisted()}, $_);
+ }
+ }
+ my @result = [ uniq(@l) ], join(' ', @{$self->unlisted()});
+ return \@result;
+}
+
+#=============================================================
+
+=head2 get_conf
+
+=head3 INPUT
+
+ $self: this object
+
+ $disabled: boolean
+
+ $o_ports: object representing ports
+
+=head3 DESCRIPTION
+
+ This method retrieves the configuration
+
+=cut
+
+#=============================================================
+
+sub get_conf {
+ my $self = shift();
+ my ($disabled, $o_ports) = @_;
+ my $possible_servers = undef;
+ my $conf = ManaTools::Shared::Shorewall::read_();
+ my $shorewall = (ManaTools::Shared::Shorewall::get_config_file('zones', '') && $conf);
+
+ if ($o_ports) {
+ return ($disabled, $self->from_ports($o_ports));
+ } elsif ($shorewall) {
+ # WARNING: this condition fails (the method fails)
+ # if manawall runs as unprivileged user
+ # cause it can't read the interfaces file
+ return ($shorewall->{disabled}, $self->from_ports($shorewall->{ports}), $shorewall->{log_net_drop});
+ } else {
+ $self->sh_gui->ask_OkCancel({
+ title => $self->loc->N("Firewall configuration"),
+ text => $self->loc->N("drakfirewall configurator
+ This configures a personal firewall for this Mageia machine."),
+ richtext => 1
+ }) or return;
+
+ $self->sh_gui->ask_OkCancel({
+ title => $self->loc->N("Firewall configuration"),
+ text => $self->loc->N("drakfirewall configurator
+Make sure you have configured your Network/Internet access with
+drakconnect before going any further."),
+ richtext => 1
+ }) or return;
+
+ return($disabled, $possible_servers, '');
+ }
+}
+
+sub set_ifw {
+ # my ($do_pkgs, $enabled, $rules, $ports) = @_;
+ my $self = shift();
+ my ($enabled, $rules, $ports) = @_;
+ if ($enabled)
+ {
+ my $ports_by_proto = ManaTools::Shared::Shorewall::ports_by_proto($ports);
+ output_with_perm("$::prefix/etc/ifw/rules", 0644,
+ (map { ". /etc/ifw/rules.d/$_\n" } @$rules),
+ map {
+ my $proto = $_;
+ map {
+ my $multiport = /:/ && " -m multiport";
+ "iptables -A Ifw -m conntrack --ctstate NEW -p $proto$multiport --dport $_ -j IFWLOG --log-prefix NEW\n";
+ } @{$ports_by_proto->{$proto}};
+ } intersection([ qw(tcp udp) ], [ keys %$ports_by_proto ]),
+ );
+ }
+
+ substInFile {
+ undef $_ if m!^INCLUDE /etc/ifw/rules|^iptables -I INPUT 2 -j Ifw!;
+ } "$::prefix/etc/shorewall/start";
+ ManaTools::Shared::Shorewall::set_in_file('start', $enabled, "INCLUDE /etc/ifw/start", "INCLUDE /etc/ifw/rules", "iptables -I INPUT 1 -j Ifw");
+ ManaTools::Shared::Shorewall::set_in_file('stop', $enabled, "iptables -D INPUT -j Ifw", "INCLUDE /etc/ifw/stop");
+}
+
+#=============================================================
+
+=head2 choose_watched_services
+
+=head3 INPUT
+
+ $self: this object
+
+ $servers: array of hashes representing servers
+
+=head3 DESCRIPTION
+
+ This method shows the main dialog to let users choose the allowed services
+
+=cut
+
+#=============================================================
+
+sub choose_watched_services {
+ my ($self, $servers) = @_;
+
+ my @l = (@{$self->ifw_rules()}, @$servers, map { { ports => $_ } } @{$self->unlisted()});
+
+ my $enabled = 1;
+ $_->{ifw} = 1 foreach @l;
+
+ my $retval = $self->ask_WatchedServices({
+ title => $self->loc->N("Interactive Firewall"),
+ icon => $self->icon(),
+ # if_(!$::isEmbedded, banner_title => N("Interactive Firewall")),
+ messages =>
+ $self->loc->N("You can be warned when someone accesses to a service or tries to intrude into your computer.
+Please select which network activities should be watched."),
+ },
+ [
+ {
+ id=>'useifw',
+ text => $self->loc->N("Use Interactive Firewall"),
+ val => $enabled,
+ type => 'bool'
+ },
+ map {
+ {
+ text => (exists $_->{name} ? $_->{name} : $_->{ports}),
+ val => $_->{ifw},
+ type => 'bool',
+ id => $_->{id},
+ },
+ } @l,
+ ]);
+
+ return if($retval == 0);
+
+ for my $server(@{$self->wdg_ifw()})
+ {
+ for my $k(keys @l)
+ {
+ if(defined($l[$k]->{id}) && defined($server->{id}))
+ {
+ if($server->{id} eq 'useifw')
+ {
+ $enabled = $server->{value};
+ }
+ else
+ {
+ if($l[$k]->{id} eq $server->{id})
+ {
+ $l[$k]->{ifw} = $server->{value};
+ last;
+ }
+ }
+ }
+ }
+ }
+
+ my ($rules, $ports) = partition { exists $_->{ifw_rule} } grep { $_->{ifw} } @l;
+ $self->set_ifw($enabled, [ map { $_->{ifw_rule} } @$rules ], $self->to_ports($ports));
+
+ # return something to say that we are done ok
+ return ($rules, $ports);
+}
+
+#=============================================================
+
+sub ask_WatchedServices {
+ my $self = shift;
+
+ my ($dlg_data,
+ $items) = @_;
+
+ my $old_title = yui::YUI::app()->applicationTitle();
+
+ ## set new title to get it in dialog
+ yui::YUI::app()->setApplicationTitle($dlg_data->{title});
+
+ my $factory = yui::YUI::widgetFactory;
+ my $optional = yui::YUI::optionalWidgetFactory;
+
+ $self->dialog($factory->createMainDialog());
+ my $layout = $factory->createVBox($self->dialog);
+
+ my $hbox_header = $factory->createHBox($layout);
+ my $headLeft = $factory->createHBox($factory->createLeft($hbox_header));
+ my $headRight = $factory->createHBox($factory->createRight($hbox_header));
+
+ my $logoImage = $factory->createImage($headLeft, $dlg_data->{icon});
+ my $labelAppDescription = $factory->createLabel($headRight,$dlg_data->{messages});
+ $logoImage->setWeight($yui::YD_HORIZ,0);
+ $labelAppDescription->setWeight($yui::YD_HORIZ,3);
+
+ my $hbox_content = $factory->createHBox($layout);
+
+ my $widgetContainer = $factory->createVBox($hbox_content);
+
+
+ foreach my $item(@{$items})
+ {
+ if(defined($item->{label}))
+ {
+ $factory->createLabel($factory->createLeft($factory->createHBox($widgetContainer)), $item->{label});
+ }
+ elsif(defined($item->{text}))
+ {
+ my $ckbox = $factory->createCheckBox(
+ $factory->createLeft($factory->createHBox($widgetContainer)),
+ $item->{text},
+ $item->{val}
+ );
+ $ckbox->setNotify(1);
+ push @{$self->wdg_ifw()}, {
+ id => $item->{id},
+ widget => \$ckbox,
+ value => $item->{val},
+ };
+ $ckbox->DISOWN();
+ }
+ }
+
+ my $hbox_foot = $factory->createHBox($layout);
+ my $vbox_foot_left = $factory->createVBox($factory->createLeft($hbox_foot));
+ my $vbox_foot_right = $factory->createVBox($factory->createRight($hbox_foot));
+ my $aboutButton = $factory->createPushButton($vbox_foot_left,$self->loc->N("&About"));
+ my $cancelButton = $factory->createPushButton($vbox_foot_right,$self->loc->N("&Cancel"));
+ my $okButton = $factory->createPushButton($vbox_foot_right,$self->loc->N("&OK"));
+
+ my $retval = 0;
+
+ # main loop
+ while(1) {
+ my $event = $self->dialog->waitForEvent();
+ my $eventType = $event->eventType();
+
+ #event type checking
+ if ($eventType == $yui::YEvent::CancelEvent) {
+ last;
+ }
+ elsif ($eventType == $yui::YEvent::WidgetEvent) {
+ ### Buttons and widgets ###
+ my $widget = $event->widget();
+
+ # loop on every checkbox representing servers
+ foreach my $server(@{$self->wdg_ifw()})
+ {
+ if($widget == ${$server->{widget}})
+ {
+ if($server->{id} eq 'useifw')
+ {
+ if(!${$server->{widget}}->value())
+ {
+ yui::YUI::ui()->blockEvents();
+ foreach my $server(@{$self->wdg_ifw()})
+ {
+ if($server->{id} ne 'useifw')
+ {
+ ${$server->{widget}}->setValue(0);
+ $server->{value} = ${$server->{widget}}->value();
+ }
+ }
+ yui::YUI::ui()->unblockEvents();
+ last;
+ }
+ }
+ else
+ {
+ $server->{value} = ${$server->{widget}}->value();
+ }
+ }
+ }
+ if ($widget == $cancelButton) {
+ last;
+ }elsif ($widget == $aboutButton) {
+ my $abtdlg = $self->aboutDialog();
+ $abtdlg->{name} = $dlg_data->{title};
+ $abtdlg->{description} = $self->loc->N("Graphical manager for interactive firewall rules");
+ $self->sh_gui->AboutDialog($abtdlg
+ );
+ }elsif ($widget == $okButton) {
+ $retval = 1;
+ last;
+ }
+ }
+ }
+
+ $self->dialog->destroy();
+
+ #restore old application title
+ yui::YUI::app()->setApplicationTitle($old_title);
+
+ return $retval;
+}
+
+
+#=============================================================
+
+=head2 choose_allowed_services
+
+=head3 INPUT
+
+ $self: this object
+
+ $disabled: boolean
+
+ $servers: array of hashes representing servers
+
+=head3 DESCRIPTION
+
+ This method shows the main dialog to let users choose the allowed services
+
+=cut
+
+#=============================================================
+
+sub choose_allowed_services {
+ my ($self, $disabled, $servers) = @_;
+
+ $_->{on} = 0 foreach @{$self->all_servers()};
+ $_->{on} = 1 foreach @$servers;
+ my @l = grep { $_->{on} || !$_->{hide} } @{$self->all_servers()};
+
+ my $dialog_data = {
+ title => $self->loc->N("Firewall"),
+ icon => $self->icon(),
+ # if_(!$::isEmbedded, banner_title => $self->loc->N("Firewall")),
+ banner_title => $self->loc->N("Firewall"),
+ };
+
+ my $items = [
+ { label => $self->loc->N("Which services would you like to allow the Internet to connect to?"), title => 1 },
+ if_($self->net()->{PROFILE} && network::network::netprofile_count() > 0, { label => $self->loc->N("Those settings will be saved for the network profile <b>%s</b>", $self->net()->{PROFILE}) }),
+ { text => $self->loc->N("Everything (no firewall)"), val => \$disabled, type => 'bool' },
+ (map { { text => $_->{name}, val => \$_->{on}, type => 'bool', disabled => sub { $disabled }, id => $_->{id} } } @l),
+ ];
+
+ return if(!$self->ask_AllowedServices($dialog_data, $items));
+
+ for my $server(@{$self->wdg_servers()})
+ {
+ for my $k(keys @l)
+ {
+ if(defined($l[$k]->{id}) && defined($server->{id}))
+ {
+ if($l[$k]->{id} eq $server->{id})
+ {
+ $l[$k]->{on} = ${$server->{value}};
+ last;
+ }
+ }
+ else
+ {
+ # fake server, the checkbox allowing the user to disable the firewall
+ # if Everything checkbox is selected, value = 1 then firewall disabled = 1
+ $disabled = ${$server->{value}};
+ last;
+ }
+ }
+ }
+
+ return ($disabled, [ grep { $_->{on} } @l ]);
+}
+
+#=============================================================
+
+sub ask_AllowedServices {
+ my $self = shift;
+
+ my ($dlg_data,
+ $items) = @_;
+
+ my $old_title = yui::YUI::app()->applicationTitle();
+
+ ## set new title to get it in dialog
+ yui::YUI::app()->setApplicationTitle($dlg_data->{title});
+
+ my $factory = yui::YUI::widgetFactory;
+ my $optional = yui::YUI::optionalWidgetFactory;
+
+ $self->dialog($factory->createMainDialog());
+ my $layout = $factory->createVBox($self->dialog);
+
+ my $hbox_header = $factory->createHBox($layout);
+ my $headLeft = $factory->createHBox($factory->createLeft($hbox_header));
+ my $headRight = $factory->createHBox($factory->createRight($hbox_header));
+
+ my $logoImage = $factory->createImage($headLeft, $dlg_data->{icon});
+ my $labelAppDescription = $factory->createLabel($headRight,$dlg_data->{title});
+ $logoImage->setWeight($yui::YD_HORIZ,0);
+ $labelAppDescription->setWeight($yui::YD_HORIZ,3);
+
+ my $hbox_content = $factory->createHBox($layout);
+
+ my $widgetContainer = $factory->createVBox($hbox_content);
+
+ my $evry = undef;
+
+ foreach my $item(@{$items})
+ {
+ if(defined($item->{label}))
+ {
+ $factory->createLabel($factory->createLeft($factory->createHBox($widgetContainer)), $item->{label});
+ }
+ elsif(defined($item->{text}))
+ {
+ my $ckbox = $factory->createCheckBox(
+ $factory->createLeft($factory->createHBox($widgetContainer)),
+ $item->{text},
+ ${$item->{val}}
+ );
+ $ckbox->setNotify(1);
+ if(!defined($item->{id}))
+ {
+ $evry = $ckbox;
+ }
+ if(defined($item->{disabled}))
+ {
+ $ckbox->setEnabled(!$item->{disabled}->());
+ }
+ push @{$self->wdg_servers()}, {
+ id => $item->{id},
+ widget => \$ckbox,
+ value => $item->{val},
+ };
+ $ckbox->DISOWN();
+ }
+ }
+
+ my $hbox_foot = $factory->createHBox($layout);
+ my $vbox_foot_left = $factory->createVBox($factory->createLeft($hbox_foot));
+ my $vbox_foot_right = $factory->createVBox($factory->createRight($hbox_foot));
+ my $advButton = $factory->createPushButton($vbox_foot_left,$self->loc->N("A&dvanced"));
+ my $aboutButton = $factory->createPushButton($vbox_foot_left,$self->loc->N("&About"));
+ my $cancelButton = $factory->createPushButton($vbox_foot_right,$self->loc->N("&Cancel"));
+ my $okButton = $factory->createPushButton($vbox_foot_right,$self->loc->N("&OK"));
+
+ my $retval = 0;
+
+ # main loop
+ while(1) {
+ my $event = $self->dialog->waitForEvent();
+ my $eventType = $event->eventType();
+
+ #event type checking
+ if ($eventType == $yui::YEvent::CancelEvent) {
+ last;
+ }
+ elsif ($eventType == $yui::YEvent::WidgetEvent) {
+ ### Buttons and widgets ###
+ my $widget = $event->widget();
+
+ # loop on every checkbox representing servers
+ foreach my $server(@{$self->wdg_servers()})
+ {
+ if($widget == ${$server->{widget}})
+ {
+ ${$server->{value}} = !${$server->{value}};
+ }
+ }
+
+ if ($widget == $cancelButton) {
+ last;
+ }elsif ($widget == $aboutButton) {
+ my $abtdlg = $self->aboutDialog();
+ $abtdlg->{name} = $dlg_data->{title};
+ $abtdlg->{description} = $self->loc->N("Graphical manager for firewall rules");
+ $self->sh_gui->AboutDialog($abtdlg);
+ }elsif ($widget == $okButton) {
+ $retval = 1;
+ last;
+ }
+ elsif ($widget == $advButton) {
+ $self->ask_CustomPorts();
+ }
+ elsif ($widget == $evry) {
+ foreach my $wdg_ckbox(@{$self->wdg_servers()})
+ {
+ if(defined($wdg_ckbox->{id}))
+ {
+ ${$wdg_ckbox->{widget}}->setEnabled(!${$wdg_ckbox->{widget}}->isEnabled());
+ }
+ }
+ }
+ }
+ }
+
+ $self->dialog->destroy();
+
+ #restore old application title
+ yui::YUI::app()->setApplicationTitle($old_title);
+
+ return $retval;
+}
+
+sub ask_CustomPorts {
+ my $self = shift();
+
+ my $adv_msg = $self->loc->N("You can enter miscellaneous ports.
+Valid examples are: 139/tcp 139/udp 600:610/tcp 600:610/udp.
+Have a look at /etc/services for information.");
+
+ my $old_title = yui::YUI::app()->applicationTitle();
+ my $win_title = $self->loc->N("Define miscellaneus ports");
+
+ ## set new title to get it in dialog
+ yui::YUI::app()->setApplicationTitle($win_title);
+
+ my $factory = yui::YUI::widgetFactory;
+ my $optional = yui::YUI::optionalWidgetFactory;
+
+ my $advdlg = $factory->createPopupDialog();
+ my $layout = $factory->createVBox($advdlg);
+
+ my $hbox_header = $factory->createHBox($layout);
+ my $headLeft = $factory->createHBox($factory->createLeft($hbox_header));
+ my $headRight = $factory->createHBox($factory->createRight($hbox_header));
+
+ my $labelAppDescription = $factory->createLabel($headRight,$self->loc->N("Other ports"));
+ $labelAppDescription->setWeight($yui::YD_HORIZ,3);
+
+ my $hbox_content = $factory->createHBox($layout);
+ my $vbox_inputs = $factory->createVBox($hbox_content);
+ my $labelAdvMessage = $factory->createLabel($factory->createHBox($vbox_inputs), $adv_msg);
+ my $txtPortsList = $factory->createInputField($vbox_inputs,'');
+ $txtPortsList->setValue(join(' ',@{$self->unlisted()}));
+ my $ckbLogFWMessages = $factory->createCheckBox($factory->createHBox($vbox_inputs), $self->loc->N("Log firewall messages in system logs"), $self->log_net_drop());
+ my $hbox_foot = $factory->createHBox($layout);
+ my $vbox_foot_left = $factory->createVBox($factory->createLeft($hbox_foot));
+ my $vbox_foot_right = $factory->createVBox($factory->createRight($hbox_foot));
+ my $cancelButton = $factory->createPushButton($vbox_foot_right,$self->loc->N("&Cancel"));
+ my $okButton = $factory->createPushButton($vbox_foot_right,$self->loc->N("&OK"));
+
+ my $retval = 0;
+
+ # main loop
+ while(1) {
+ my $event = $advdlg->waitForEvent();
+ my $eventType = $event->eventType();
+
+ #event type checking
+ if ($eventType == $yui::YEvent::CancelEvent) {
+ last;
+ }
+ elsif ($eventType == $yui::YEvent::WidgetEvent) {
+ ### Buttons and widgets ###
+ my $widget = $event->widget();
+ if( $widget == $cancelButton )
+ {
+ $retval = 0;
+ last;
+ }
+ elsif( $widget == $okButton )
+ {
+ if(scalar(@{$self->unlisted()}) > 0)
+ {
+ $self->unlisted([]);
+ }
+ my $invalid_ports = check_ports_syntax($txtPortsList->value());
+ if(ManaTools::Shared::trim($invalid_ports) eq '')
+ {
+ if($txtPortsList->value() =~m/\s+/g)
+ {
+ my @unlstd = split(' ', $txtPortsList->value());
+ foreach my $p(@unlstd)
+ {
+ push(@{$self->unlisted()},$p);
+ }
+ }
+ else
+ {
+ if(ManaTools::Shared::trim($txtPortsList->value()) ne '')
+ {
+ push(@{$self->unlisted()}, ManaTools::Shared::trim($txtPortsList->value()));
+ }
+ }
+ $retval = 1;
+ }
+ else
+ {
+ $self->sh_gui->warningMsgBox({
+ title=>$self->loc->N("Invalid port given"),
+ text=> $self->loc->N("Invalid port given: %s.
+The proper format is \"port/tcp\" or \"port/udp\",
+where port is between 1 and 65535.
+
+You can also give a range of ports (eg: 24300:24350/udp)", $invalid_ports)
+ });
+ $retval = 0;
+ }
+ last;
+ }
+ }
+ }
+
+ $advdlg->destroy();
+
+ #restore old application title
+ yui::YUI::app()->setApplicationTitle($old_title);
+
+ return $retval;
+}
+
+sub get_zones {
+ my $self = shift();
+ my $confref = shift();
+ my $disabled = shift();
+ my $conf = ${$confref};
+ my $interfacesfile = ManaTools::Shared::Shorewall::get_config_file('interfaces', $conf->{version} || '');
+ network::network::read_net_conf($self->net());
+ #- find all interfaces but alias interfaces
+ my @all_intf = grep { !/:/ } uniq(keys(%{$self->net()->{ifcfg}}), detect_devices::get_net_interfaces());
+ my %net_zone = map { $_ => undef } @all_intf;
+ $net_zone{$_} = 1 foreach ManaTools::Shared::Shorewall::get_net_zone_interfaces($interfacesfile, $self->net(), \@all_intf);
+
+ # if firewall/shorewall is not disabled (i.e. everything has been allowed)
+ # then ask for network interfaces to protect
+ if(!$disabled)
+ {
+ my $retvals = $self->sh_gui->ask_multiple_fromList({
+ title => $self->loc->N("Firewall configuration"),
+ header => $self->loc->N("Please select the interfaces that will be protected by the firewall.
+
+All interfaces directly connected to Internet should be selected,
+while interfaces connected to a local network may be unselected.
+
+If you intend to use Mageia Internet Connection sharing,
+unselect interfaces which will be connected to local network.
+
+Which interfaces should be protected?
+"),
+ list => [
+ map {
+ {
+ id => $_,
+ text => network::tools::get_interface_description($self->net(), $_),
+ val => \$net_zone{$_},
+ type => 'bool'
+ };
+ } (sort keys %net_zone) ]
+ });
+
+ if(!defined($retvals))
+ {
+ return 0;
+ }
+ else
+ {
+ # it was: ($conf->{net_zone}, $conf->{loc_zone}) = partition { $net_zone{$_} } keys %net_zone;
+ foreach my $net_int (@{$retvals})
+ {
+ push (@{$conf->{net_zone}}, $net_int);
+ }
+ return $retvals;
+ }
+ }
+
+ foreach my $net_int(keys %net_zone)
+ {
+ push (@{$conf->{net_zone}}, $net_int);
+ }
+ return keys %net_zone;
+}
+
+#=============================================================
+
+=head2 set_ports
+
+=head3 INPUT
+
+ $self: this object
+
+=head3 DESCRIPTION
+
+ This method extends Module::start and is invoked to
+ start host manager
+
+=cut
+
+#=============================================================
+
+sub set_ports {
+ my ($self, $disabled, $ports, $log_net_drop) = @_;
+
+ if (!$disabled || -x "$::prefix/sbin/shorewall") {
+ # $do_pkgs->ensure_files_are_installed([ [ qw(shorewall shorewall) ], [ qw(shorewall-ipv6 shorewall6) ] ], $::isInstall) or return;
+ my $conf = ManaTools::Shared::Shorewall::read_();
+ if(!$self->get_zones(\$conf,$disabled))
+ {
+ # Cancel button has been pressed, aborting
+ return 0;
+ }
+ my $shorewall = (ManaTools::Shared::Shorewall::get_config_file('zones', '') && $conf);
+ if (!$shorewall) {
+ print ("unable to read shorewall configuration, skipping installation");
+ return 0;
+ }
+
+ $shorewall->{disabled} = $disabled;
+ $shorewall->{ports} = $ports;
+ $shorewall->{log_net_drop} = $log_net_drop;
+
+ print ($disabled ? "disabling shorewall" : "configuring shorewall to allow ports: $ports");
+
+ # NOTE: the 2nd param is undef in this case!
+ if(!ManaTools::Shared::Shorewall::write_($shorewall))
+ {
+ # user action request
+ my $action = $self->sh_gui->ask_fromList({
+ title => $self->loc->N("Firewall"),
+ header => $self->loc->N("Your firewall configuration has been manually edited and contains
+ rules that may conflict with the configuration that has just been set up.
+ What do you want to do?"),
+ list => [ "keep", "drop"],
+ default => "keep",
+ });
+ ManaTools::Shared::Shorewall::write_($shorewall,$action);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+#=============================================================
+
+=head2 start
+
+=head3 INPUT
+
+ $self: this object
+
+=head3 DESCRIPTION
+
+ This method extends Module::start and is invoked to
+ start host manager
+
+=cut
+
+#=============================================================
+
+sub start {
+ my $self = shift;
+
+ my @server = ();
+ $self->wdg_servers(@server);
+
+ # init servers definitions
+ $self->all_servers($self->_initAllServers());
+
+ # initialize ifw_rules here
+ $self->ifw_rules($self->_initIFW());
+
+ my ($disabled, $servers, $log_net_drop) = $self->get_conf(undef) or return;
+
+ # $log_net_drop: network::shorewall log_net_drop attribute
+ $self->log_net_drop($log_net_drop);
+ undef($log_net_drop);
+ ($disabled, $servers) = $self->choose_allowed_services($disabled, @$servers) or return;
+
+ my $system_file = '/etc/sysconfig/drakx-net';
+ my %global_settings = getVarsFromSh($system_file);
+
+ if (!$disabled && (!defined($global_settings{IFW}) || text2bool($global_settings{IFW}))) {
+ $self->choose_watched_services($servers) or return;
+ }
+
+ # preparing services when required ( look at $self->all_servers() )
+ foreach (@$servers) {
+ exists $_->{prepare} and $_->{prepare}();
+ }
+
+ my $ports = $self->to_ports($servers);
+
+ $self->set_ports($disabled, $ports, $self->log_net_drop()) or return;
+
+ # restart mandi
+ my $services = ManaTools::Shared::Services->new();
+ $services->is_service_running("mandi") and $services->restart("mandi");
+
+ # restarting services if needed
+ foreach my $service (@$servers) {
+ if ($service->{restart}) {
+ $services->is_service_running($_) and $services->restart($_) foreach split(' ', $service->{restart});
+ }
+ }
+
+ # clearing pending ifw notifications in net_applet
+ system('killall -s SIGUSR1 net_applet');
+
+ return ($disabled, $ports);
+};
+
+1;
diff --git a/lib/ManaTools/Module/Hosts.pm b/lib/ManaTools/Module/Hosts.pm
new file mode 100644
index 0000000..faae3f0
--- /dev/null
+++ b/lib/ManaTools/Module/Hosts.pm
@@ -0,0 +1,530 @@
+# vim: set et ts=4 sw=4:
+#*****************************************************************************
+#
+# Copyright (c) 2013-2015 Matteo Pasotti <matteo.pasotti@gmail.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2, as
+# published by the Free Software Foundation.
+#
+# 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.
+#
+#*****************************************************************************
+
+package ManaTools::Module::Hosts;
+
+use Modern::Perl '2011';
+use autodie;
+use Moose;
+use POSIX qw(ceil);
+use utf8;
+
+use Glib;
+use yui;
+use ManaTools::Shared qw(trim);
+use ManaTools::Shared::GUI;
+use ManaTools::Shared::Hosts;
+
+extends qw( ManaTools::Module );
+
+
+has '+icon' => (
+ default => "/usr/lib/libDrakX/icons/IC-Dhost-48.png"
+);
+
+has '+name' => (
+ default => "Hostmanager",
+);
+
+=head1 VERSION
+
+Version 1.0.0
+
+=cut
+
+our $VERSION = '1.0.0';
+
+has 'dialog' => (
+ is => 'rw',
+ init_arg => undef
+);
+
+has 'table' => (
+ is => 'rw',
+ init_arg => undef
+);
+
+has 'cfgHosts' => (
+ is => 'rw',
+ init_arg => undef
+);
+
+has 'sh_gui' => (
+ is => 'rw',
+ init_arg => undef,
+ builder => '_SharedUGUIInitialize'
+);
+
+has 'loc' => (
+ is => 'rw',
+ init_arg => undef,
+ builder => '_localeInitialize'
+);
+
+sub _localeInitialize {
+ my $self = shift();
+
+ # TODO fix domain binding for translation
+ $self->loc(ManaTools::Shared::Locales->new(domain_name => 'drakx-net') );
+ # TODO if we want to give the opportunity to test locally add dir_name => 'path'
+}
+
+sub _SharedUGUIInitialize {
+ my $self = shift();
+
+ $self->sh_gui(ManaTools::Shared::GUI->new() );
+}
+
+#=============================================================
+
+=head2 start
+
+=head3 INPUT
+
+ $self: this object
+
+=head3 DESCRIPTION
+
+ This method extends Module::start and is invoked to
+ start host manager
+
+=cut
+
+#=============================================================
+sub start {
+ my $self = shift;
+
+ $self->_manageHostsDialog();
+};
+
+#=============================================================
+
+=head2 _changeHostNameDialog
+
+=head3 INPUT
+
+ $self: this object
+
+ $headerString: a title for the dialog
+
+=head3 DESCRIPTION
+
+ This method display a dialog allowing the user
+ to change the hostname
+
+=cut
+
+#=============================================================
+sub _changeHostNameDialog {
+ my $self = shift;
+
+ my $headerString = shift();
+
+ my $factory = yui::YUI::widgetFactory;
+ my $dlg = $factory->createPopupDialog();
+ my $layout = $factory->createVBox($dlg);
+
+ my $hbox_header = $factory->createHBox($layout);
+ my $vbox_content = $factory->createVBox($layout);
+ my $hbox_footer = $factory->createHBox($layout);
+
+ # header
+ my $labelDescription = $factory->createLabel($hbox_header,$headerString);
+
+ # content
+ my $firstHbox = $factory->createHBox($vbox_content);
+ my $secondHbox = $factory->createHBox($vbox_content);
+ my $thirdHbox = $factory->createHBox($vbox_content);
+ my $fourthHbox = $factory->createHBox($vbox_content);
+ my $fifthHbox = $factory->createHBox($vbox_content);
+ my $sixthHbox = $factory->createHBox($vbox_content);
+
+ my $labelHostName = $factory->createLabel($secondHbox,$self->loc->N("Hostname"));
+ $labelHostName->setWeight($yui::YD_HORIZ, 10);
+ my $textHostName = $factory->createInputField($secondHbox,"");
+ $textHostName->setWeight($yui::YD_HORIZ, 30);
+
+ my $labelPrettyHostName = $factory->createLabel($thirdHbox,$self->loc->N("Pretty Hostname"));
+ $labelPrettyHostName->setWeight($yui::YD_HORIZ, 10);
+ my $textPrettyHostName = $factory->createInputField($thirdHbox,"");
+ $textPrettyHostName->setWeight($yui::YD_HORIZ, 30);
+
+ my $labelStaticHostName = $factory->createLabel($fourthHbox,$self->loc->N("Static Hostname"));
+ $labelStaticHostName->setWeight($yui::YD_HORIZ, 10);
+ my $textStaticHostName = $factory->createInputField($fourthHbox,"");
+ $textStaticHostName->setWeight($yui::YD_HORIZ, 30);
+
+ my $labelChassis = $factory->createLabel($fifthHbox,$self->loc->N("Chassis"));
+ $labelChassis->setWeight($yui::YD_HORIZ, 10);
+ my $textChassis = $factory->createInputField($fifthHbox,"");
+ $textChassis->setWeight($yui::YD_HORIZ, 30);
+
+ my $labelIconName = $factory->createLabel($sixthHbox,$self->loc->N("Icon Name"));
+ $labelIconName->setWeight($yui::YD_HORIZ, 10);
+ my $textIconName = $factory->createInputField($sixthHbox,"");
+ $textIconName->setWeight($yui::YD_HORIZ, 30);
+
+ $textHostName->setValue($self->cfgHosts->_getLocalHostName());
+ $textPrettyHostName->setValue($self->cfgHosts->_getLocalPrettyHostName());
+ $textStaticHostName->setValue($self->cfgHosts->_getLocalStaticHostName());
+ $textChassis->setValue($self->cfgHosts->_getLocalChassis());
+ $textIconName->setValue($self->cfgHosts->_getLocalIconName());
+
+ # footer
+ my $cancelButton = $factory->createPushButton($factory->createLeft($hbox_footer),$self->loc->N("&Cancel"));
+ my $okButton = $factory->createPushButton($factory->createRight($hbox_footer),$self->loc->N("&OK"));
+
+ while(1){
+ my $event = $dlg->waitForEvent();
+ my $eventType = $event->eventType();
+
+ #event type checking
+ if ($eventType == $yui::YEvent::CancelEvent) {
+ last;
+ }
+ elsif ($eventType == $yui::YEvent::WidgetEvent) {
+ # widget selected
+ my $widget = $event->widget();
+ if ($widget == $cancelButton) {
+ last;
+ }
+ elsif($widget == $okButton) {
+ $self->cfgHosts->_setLocalHostName($textHostName->value());
+ $self->cfgHosts->_setLocalPrettyHostName($textPrettyHostName->value());
+ $self->cfgHosts->_setLocalStaticHostName($textStaticHostName->value());
+ $self->cfgHosts->_setLocalChassis($textChassis->value());
+ $self->cfgHosts->_setLocalIconName($textIconName->value());
+ last;
+ }
+ }
+ }
+
+ destroy $dlg;
+}
+
+sub _manipulateHostDialog {
+ my $self = shift;
+
+ my $headerString = shift();
+ my $boolEdit = shift();
+
+ my $hostIpString = "";
+ my $hostNameString = "";
+ my $hostAliasesString = "";
+
+ if($boolEdit == 1){
+ $hostIpString = shift();
+ $hostNameString = shift();
+ $hostAliasesString = shift();
+ }
+
+ my $factory = yui::YUI::widgetFactory;
+ my $dlg = $factory->createPopupDialog();
+ my $layout = $factory->createVBox($dlg);
+
+ my $hbox_header = $factory->createHBox($layout);
+ my $vbox_content = $factory->createVBox($layout);
+ my $hbox_footer = $factory->createHBox($layout);
+
+ # header
+ my $labelDescription = $factory->createLabel($hbox_header,$headerString);
+
+ # content
+ my $firstHbox = $factory->createHBox($vbox_content);
+ my $secondHbox = $factory->createHBox($vbox_content);
+ my $thirdHbox = $factory->createHBox($vbox_content);
+
+ my $labelIPAddress = $factory->createLabel($firstHbox,$self->loc->N("IP Address"));
+ my $labelHostName = $factory->createLabel($secondHbox,$self->loc->N("Hostname"));
+ my $labelHostAlias = $factory->createLabel($thirdHbox,$self->loc->N("Host aliases"));
+ $labelIPAddress->setWeight($yui::YD_HORIZ, 10);
+ $labelHostName->setWeight($yui::YD_HORIZ, 10);
+ $labelHostAlias->setWeight($yui::YD_HORIZ, 10);
+
+ my $textIPAddress = $factory->createInputField($firstHbox,"");
+ my $textHostName = $factory->createInputField($secondHbox,"");
+ my $textHostAlias = $factory->createInputField($thirdHbox,"");
+ $textIPAddress->setWeight($yui::YD_HORIZ, 30);
+ $textHostName->setWeight($yui::YD_HORIZ, 30);
+ $textHostAlias->setWeight($yui::YD_HORIZ, 30);
+
+ if($boolEdit == 1){
+ $textIPAddress->setValue($hostIpString);
+ $textHostName->setValue($hostNameString);
+ $textHostAlias->setValue($hostAliasesString);
+ }
+
+ # footer
+ my $cancelButton = $factory->createPushButton($factory->createLeft($hbox_footer),$self->loc->N("&Cancel"));
+ my $okButton = $factory->createPushButton($factory->createRight($hbox_footer),$self->loc->N("&OK"));
+
+ while(1){
+ my $event = $dlg->waitForEvent();
+ my $eventType = $event->eventType();
+
+ #event type checking
+ if ($eventType == $yui::YEvent::CancelEvent) {
+ last;
+ }
+ elsif ($eventType == $yui::YEvent::WidgetEvent) {
+ # widget selected
+ my $widget = $event->widget();
+ if ($widget == $cancelButton) {
+ last;
+ }
+ elsif($widget == $okButton) {
+ my $res = undef;
+ my @hosts_toadd;
+ push @hosts_toadd, $textHostName->value();
+ if(ManaTools::Shared::trim($textHostAlias->value()) ne ""){
+ push @hosts_toadd, $textHostAlias->value();
+ }
+ if($boolEdit == 0){
+ $res = $self->cfgHosts->_insertHost($textIPAddress->value(),[@hosts_toadd]);
+ }else{
+ $res = $self->cfgHosts->_modifyHost($textIPAddress->value(),[@hosts_toadd]);
+ }
+ $res = $self->cfgHosts->_writeHosts();
+ last;
+ }
+ }
+ }
+
+ destroy $dlg;
+}
+
+#=============================================================
+
+=head2 _addHostDialog
+
+=head3 INPUT
+
+ $self: this object
+
+=head3 DESCRIPTION
+
+This subroutine creates the Host dialog to add host definitions
+
+=cut
+
+#=============================================================
+
+sub _addHostDialog {
+ my $self = shift();
+ return $self->_manipulateHostDialog($self->loc->N("Add the information"),0);
+}
+
+#=============================================================
+
+=head2 _edtHostDialog
+
+=head3 INPUT
+
+=over 4
+
+=item $self: this object
+
+=item B<$hostIp> : the ip of the host entry that we want to modify
+
+=item B<$hostName> : the name of the host entry we want to modify
+
+=item B<$hostAliases> : aliases of the host entry we want to modify
+
+=back
+
+=head3 DESCRIPTION
+
+This subroutine creates the Host dialog to modify host definitions
+
+=cut
+
+#=============================================================
+
+sub _edtHostDialog {
+ my $self = shift();
+ my $hostIp = shift();
+ my $hostName = shift();
+ my $hostAliases = shift();
+ return $self->_manipulateHostDialog($self->loc->N("Modify the information"),1,$hostIp,$hostName,$hostAliases);
+}
+
+#=============================================================
+
+=head2 setupTable
+
+=head3 INPUT
+
+ $self: this object
+
+ $data: reference to the array containaing the host data to show into the table
+
+=head3 DESCRIPTION
+
+This subroutine populates a previously created YTable with the hosts data
+retrieved by the Config::Hosts module
+
+=cut
+
+#=============================================================
+sub setupTable {
+ my $self = shift();
+
+ my @hosts = $self->cfgHosts->_getHosts();
+ # clear table
+ $self->table->deleteAllItems();
+ foreach my $host (@hosts){
+ my $tblItem;
+ my $aliases = join(',',@{$host->{'hosts'}});
+ if(scalar(@{$host->{'hosts'}}) > 1){
+ $aliases =~s/^$host->{'hosts'}[0]\,*//g;
+ }elsif(scalar(@{$host->{'hosts'}}) == 1){
+ $aliases = "";
+ }
+ $tblItem = new yui::YTableItem($host->{'ip'},$host->{'hosts'}[0],$aliases);
+ $self->table->addItem($tblItem);
+ }
+}
+
+sub _manageHostsDialog {
+ my $self = shift;
+
+ ## TODO fix for manatools
+ my $appTitle = yui::YUI::app()->applicationTitle();
+ my $appIcon = yui::YUI::app()->applicationIcon();
+ ## set new title to get it in dialog
+ my $newTitle = $self->loc->N("Manage hosts definitions");
+ yui::YUI::app()->setApplicationTitle($newTitle);
+
+ my $factory = yui::YUI::widgetFactory;
+ my $optional = yui::YUI::optionalWidgetFactory;
+
+
+ $self->dialog($factory->createMainDialog());
+ my $layout = $factory->createVBox($self->dialog);
+
+ my $hbox_header = $factory->createHBox($layout);
+ my $headLeft = $factory->createHBox($factory->createLeft($hbox_header));
+ my $headRight = $factory->createHBox($factory->createRight($hbox_header));
+
+ my $logoImage = $factory->createImage($headLeft, $appIcon);
+ my $labelAppDescription = $factory->createLabel($headRight,$newTitle);
+ $logoImage->setWeight($yui::YD_HORIZ,0);
+ $labelAppDescription->setWeight($yui::YD_HORIZ,3);
+
+ my $hbox_content = $factory->createHBox($layout);
+
+ my $tableHeader = new yui::YTableHeader();
+ $tableHeader->addColumn($self->loc->N("IP Address"));
+ $tableHeader->addColumn($self->loc->N("Hostname"));
+ $tableHeader->addColumn($self->loc->N("Host Aliases"));
+ my $leftContent = $factory->createLeft($hbox_content);
+ $leftContent->setWeight($yui::YD_HORIZ,45);
+ $self->table($factory->createTable($leftContent,$tableHeader));
+
+ # initialize Config::Hosts
+ $self->cfgHosts(ManaTools::Shared::Hosts->new());
+ $self->setupTable();
+
+ my $rightContent = $factory->createRight($hbox_content);
+ $rightContent->setWeight($yui::YD_HORIZ,10);
+ my $topContent = $factory->createTop($rightContent);
+ my $vbox_commands = $factory->createVBox($topContent);
+ my $addButton = $factory->createPushButton($factory->createHBox($vbox_commands),$self->loc->N("A&dd"));
+ my $edtButton = $factory->createPushButton($factory->createHBox($vbox_commands),$self->loc->N("&Edit"));
+ my $remButton = $factory->createPushButton($factory->createHBox($vbox_commands),$self->loc->N("&Remove"));
+ my $hnButton = $factory->createPushButton($factory->createHBox($vbox_commands),$self->loc->N("&Hostname"));
+ $addButton->setWeight($yui::YD_HORIZ,1);
+ $edtButton->setWeight($yui::YD_HORIZ,1);
+ $remButton->setWeight($yui::YD_HORIZ,1);
+ $hnButton->setWeight($yui::YD_HORIZ,1);
+
+ my $hbox_foot = $factory->createHBox($layout);
+ my $vbox_foot_left = $factory->createVBox($factory->createLeft($hbox_foot));
+ my $vbox_foot_right = $factory->createVBox($factory->createRight($hbox_foot));
+ my $aboutButton = $factory->createPushButton($vbox_foot_left,$self->loc->N("&About"));
+ my $cancelButton = $factory->createPushButton($vbox_foot_right,$self->loc->N("&Cancel"));
+ my $okButton = $factory->createPushButton($vbox_foot_right,$self->loc->N("&OK"));
+
+ # main loop
+ while(1) {
+ my $event = $self->dialog->waitForEvent();
+ my $eventType = $event->eventType();
+
+ #event type checking
+ if ($eventType == $yui::YEvent::CancelEvent) {
+ last;
+ }
+ elsif ($eventType == $yui::YEvent::WidgetEvent) {
+### Buttons and widgets ###
+ my $widget = $event->widget();
+ if ($widget == $cancelButton) {
+ last;
+ }
+ elsif ($widget == $addButton) {
+ $self->_addHostDialog();
+ $self->setupTable();
+ }
+ elsif ($widget == $edtButton) {
+ my $tblItem = yui::toYTableItem($self->table->selectedItem());
+ if($tblItem->cellCount() >= 3){
+ $self->_edtHostDialog($tblItem->cell(0)->label(),$tblItem->cell(1)->label(),$tblItem->cell(2)->label());
+ }else{
+ $self->_edtHostDialog($tblItem->cell(0)->label(),$tblItem->cell(1)->label(),"");
+ }
+ $self->setupTable();
+ }
+ elsif ($widget == $remButton) {
+ # implement deletion dialog
+ if($self->sh_gui->ask_YesOrNo({title => $self->loc->N("Confirmation"), text => $self->loc->N("Are you sure to drop this host?")}) == 1){
+ my $tblItem = yui::toYTableItem($self->table->selectedItem());
+ # drop the host using the ip
+ $self->cfgHosts->_dropHost($tblItem->cell(0)->label());
+ # write changes
+ $self->cfgHosts->_writeHosts();
+ $self->setupTable();
+ }
+ }elsif ($widget == $hnButton) {
+ $self->_changeHostNameDialog("Change the HostName FQDN");
+ $self->setupTable();
+ }elsif ($widget == $aboutButton) {
+ $self->sh_gui->AboutDialog({
+ name => $appTitle,
+ version => $VERSION,
+ credits => "Copyright (c) 2013-2015 by Matteo Pasotti",
+ license => "GPLv2",
+ description => $self->loc->N("Graphical manager for hosts definitions"),
+ authors => "Matteo Pasotti &lt;matteo.pasotti\@gmail.com&gt;"
+ }
+ );
+ }elsif ($widget == $okButton) {
+ # write changes
+ $self->cfgHosts->_writeHosts();
+ last;
+ }
+ }
+ }
+
+ $self->dialog->destroy() ;
+
+ #restore old application title
+ yui::YUI::app()->setApplicationTitle($appTitle);
+}
+
+1;
diff --git a/lib/ManaTools/Module/LogViewer.pm b/lib/ManaTools/Module/LogViewer.pm
new file mode 100644
index 0000000..e009c1c
--- /dev/null
+++ b/lib/ManaTools/Module/LogViewer.pm
@@ -0,0 +1,568 @@
+# vim: set et ts=4 sw=4:
+package ManaTools::Module::LogViewer;
+#============================================================= -*-perl-*-
+
+=head1 NAME
+
+ManaTools::Module::LogViewer - Log viewer
+
+=head1 SYNOPSIS
+
+my $logViewer = ManaTools::Module::LogViewer->new();
+$logViewer->start();
+
+=head1 DESCRIPTION
+
+Log viewer is a backend to journalctl, it can also load a custom
+file.
+
+
+=head1 SUPPORT
+
+You can find documentation for this module with the perldoc command:
+
+perldoc ManaTools::Module::::LogViewer
+
+=head1 AUTHOR
+
+Angelo Naselli <anaselli@linux.it>
+
+=head1 COPYRIGHT and LICENSE
+
+Copyright (C) 2014-2015, Angelo Naselli.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License version 2, as
+published by the Free Software Foundation.
+
+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
+
+=head1 FUNCTIONS
+
+=cut
+
+use Moose;
+
+use diagnostics;
+use open OUT => ':utf8';
+
+use ManaTools::Shared::GUI;
+use ManaTools::Shared::Locales;
+use ManaTools::Shared::Services;
+use ManaTools::Shared::JournalCtl;
+
+
+use POSIX qw/strftime floor/;
+use English;
+use Date::Simple ();
+use File::HomeDir qw(home);
+
+use yui;
+
+extends qw( ManaTools::Module );
+
+### TODO icon
+has '+icon' => (
+ default => "/usr/share/mcc/themes/default/logdrake-mdk.png",
+);
+
+has 'loc' => (
+ is => 'rw',
+ init_arg => undef,
+ builder => '_localeInitialize'
+);
+
+sub _localeInitialize {
+ my $self = shift;
+
+ # TODO fix domain binding for translation
+ $self->loc(ManaTools::Shared::Locales->new(domain_name => 'libDrakX-standalone') );
+ # TODO if we want to give the opportunity to test locally add dir_name => 'path'
+}
+
+has 'sh_gui' => (
+ is => 'rw',
+ init_arg => undef,
+ builder => '_SharedUGUIInitialize'
+);
+
+sub _SharedUGUIInitialize {
+ my $self = shift;
+
+ $self->sh_gui(ManaTools::Shared::GUI->new() );
+}
+
+=head1 VERSION
+
+Version 1.0.0
+
+=cut
+
+our $VERSION = '1.0.0';
+
+
+my %prior = ('emerg' => 0,
+ 'alert' => 1,
+ 'crit' => 2,
+ 'err' => 3,
+ 'warning' => 4,
+ 'notice' => 5,
+ 'info' => 6,
+ 'debug' => 7);
+
+
+#=============================================================
+
+=head2 BUILD
+
+=head3 INPUT
+
+ $self: this object
+
+=head3 DESCRIPTION
+
+ The BUILD method is called after a Moose object is created,
+ in this methods Services loads all the service information.
+
+=cut
+
+#=============================================================
+sub BUILD {
+ my $self = shift;
+
+ if (! $self->name) {
+ $self->name ($self->loc->N("Log viewer"));
+ }
+}
+
+
+#=============================================================
+
+=head2 start
+
+=head3 INPUT
+
+ $self: this object
+
+=head3 DESCRIPTION
+
+ This method extends Module::start and is invoked to
+ start the log viewer
+
+=cut
+
+#=============================================================
+sub start {
+ my $self = shift;
+
+ $self->_logViewerPanel();
+};
+
+
+
+
+
+sub _logViewerPanel {
+ my $self = shift;
+
+ if(!$self->_warn_about_user_mode()) {
+ return 0;
+ }
+
+ my $appTitle = yui::YUI::app()->applicationTitle();
+
+ ## set new title to get it in dialog
+ yui::YUI::app()->setApplicationTitle($self->name);
+ ## set icon if not already set by external launcher
+ yui::YUI::app()->setApplicationIcon($self->icon);
+
+ my $factory = yui::YUI::widgetFactory;
+ my $optFactory = yui::YUI::optionalWidgetFactory;
+
+ # Create Dialog
+ my $dialog = $factory->createMainDialog;
+
+ # Start Dialog layout:
+ my $layout = $factory->createVBox( $dialog );
+ my $align = $factory->createAlignment($layout, $yui::YAlignCenter, $yui::YAlignUnchanged);
+ $factory->createLabel( $align, $self->loc->N("A tool to monitor your logs"), 1, 0 );
+
+ #### matching
+ my $hbox = $factory->createHBox($layout);
+ my $matchingInputField = $factory->createInputField($hbox, $self->loc->N("Matching"));
+ $factory->createHSpacing($hbox, 1);
+
+ #### not matching
+ my $notMatchingInputField = $factory->createInputField($hbox, $self->loc->N("but not matching"));
+ $matchingInputField->setWeight($yui::YD_HORIZ, 2);
+ $notMatchingInputField->setWeight($yui::YD_HORIZ, 2);
+
+ my $frame = $factory->createFrame($layout, $self->loc->N("Options"));
+
+ #### lastBoot
+ my $vbox = $factory->createVBox( $frame );
+ $align = $factory->createLeft($vbox);
+ my $lastBoot = $factory->createCheckBox($align, $self->loc->N("Last boot"), 1);
+ $factory->createVSpacing($vbox, 0.5);
+ $lastBoot->setNotify(1);
+
+ my $row1 = $factory->createHBox($vbox);
+ $factory->createVSpacing($vbox, 0.5);
+ my $row2 = $factory->createHBox($vbox);
+ $factory->createVSpacing($vbox, 0.5);
+ my $row3 = $factory->createHBox($vbox);
+
+ #### since and until
+ my $sinceDate;
+ my $sinceTime;
+ my $sinceFrame = $factory->createCheckBoxFrame($row1, $self->loc->N("Since"), 1);
+ $sinceFrame->setNotify(1);
+
+ my $untilDate;
+ my $untilTime;
+ my $untilFrame = $factory->createCheckBoxFrame($row2, $self->loc->N("Until"), 1);
+ $untilFrame->setNotify(1);
+ if ($optFactory->hasDateField()) {
+ my $hbox1 = $factory->createHBox($sinceFrame);
+
+ $sinceDate = $optFactory->createDateField($hbox1, "");
+ $factory->createHSpacing($hbox1, 1.0);
+ $sinceTime = $optFactory->createTimeField($hbox1, "");
+ my $day = strftime "%F", localtime;
+ $sinceDate->setValue($day);
+ $sinceTime->setValue("00:00:00");
+
+ $hbox1 = $factory->createHBox($untilFrame);
+ $untilDate = $optFactory->createDateField($hbox1, "");
+ $factory->createHSpacing($hbox1, 1.0);
+ $untilTime = $optFactory->createTimeField($hbox1, "");
+ $untilDate->setValue($day);
+ $untilTime->setValue("23:59:59");
+ }
+ else {
+ $sinceFrame->enable(0);
+ $untilFrame->enable(0);
+ }
+
+ #### units
+ my $spacing = $factory->createHSpacing($row1, 2.0);
+
+ my $unitsFrame = $factory->createCheckBoxFrame($row1, $self->loc->N("Select a unit"), 1);
+ $unitsFrame->setNotify(1);
+ $align = $factory->createLeft($unitsFrame);
+ my $units = $factory->createComboBox ( $align, "" );
+ my $itemCollection = new yui::YItemCollection;
+
+ yui::YUI::app()->busyCursor();
+ my $serv = ManaTools::Shared::Services->new();
+ my ($l, $active_services) = $serv->services();
+
+ foreach (@{$active_services}) {
+ my $serviceName = $_;
+ my $item = new yui::YItem($serviceName);
+ $itemCollection->push($item);
+ $item->DISOWN();
+ }
+ $units->addItems($itemCollection);
+ yui::YUI::app()->normalCursor();
+
+ #### priority
+ # From
+ $factory->createHSpacing($row2, 2.0);
+ my $priorityFromFrame = $factory->createCheckBoxFrame($row2, $self->loc->N("From priority"), 1);
+ $priorityFromFrame->setNotify(1);
+ $priorityFromFrame->setWeight($yui::YD_HORIZ, 1);
+ my $priorityFrom = $factory->createComboBox ( $priorityFromFrame, "" );
+ $itemCollection->clear();
+
+ my @pr = ('emerg', 'alert', 'crit', 'err',
+ 'warning', 'notice', 'info', 'debug');
+ foreach (@pr) {
+ my $item = new yui::YItem($_);
+ if ( $_ eq 'emerg' ) {
+ $item->setSelected(1);
+ }
+ $itemCollection->push($item);
+ $item->DISOWN();
+ }
+ $priorityFrom->addItems($itemCollection);
+
+ $factory->createHSpacing( $row2, 2.0 );
+ # To
+ my $priorityToFrame = $factory->createCheckBoxFrame($row2, $self->loc->N("To priority"), 1);
+ $priorityToFrame->setNotify(1);
+ $priorityToFrame->setWeight($yui::YD_HORIZ, 1);
+ my $priorityTo = $factory->createComboBox ( $priorityToFrame, "" );
+ $itemCollection->clear();
+
+ foreach (@pr) {
+ my $item = new yui::YItem($_);
+ if ( $_ eq 'debug' ) {
+ $item->setSelected(1);
+ }
+ $itemCollection->push($item);
+ $item->DISOWN();
+ }
+ $priorityTo->addItems($itemCollection);
+
+ #### search
+ $align = $factory->createRight($row3);
+ my $searchButton = $factory->createPushButton($align, $self->loc->N("&Find"));
+
+ #### create log view object
+ my $logView = $factory->createLogView($layout, $self->loc->N("Log content"), 10, 0);
+
+
+ ### NOTE CheckBoxFrame doesn't honoured his costructor checked value for his children
+ $unitsFrame->setValue(0);
+ $sinceFrame->setValue(0);
+ $untilFrame->setValue(0);
+ $priorityFromFrame->setValue(0);
+ $priorityToFrame->setValue(0);
+
+ # buttons on the last line
+ $align = $factory->createRight($layout);
+ $hbox = $factory->createHBox($align);
+ my $aboutButton = $factory->createPushButton($hbox, $self->loc->N("&About") );
+ $align = $factory->createRight($hbox);
+ $hbox = $factory->createHBox($align);
+ my $saveButton = $factory->createPushButton($hbox, $self->loc->N("&Save"));
+ my $quitButton = $factory->createPushButton($hbox, $self->loc->N("&Quit"));
+
+ # End Dialof layout
+
+ while(1) {
+ my $event = $dialog->waitForEvent();
+ my $eventType = $event->eventType();
+
+ #event type checking
+ if ($eventType == $yui::YEvent::CancelEvent) {
+ last;
+ }
+ elsif ($eventType == $yui::YEvent::WidgetEvent) {
+ # widget selected
+ my $widget = $event->widget();
+ if ($widget == $quitButton) {
+ last;
+ }
+ elsif($widget == $aboutButton) {
+ my $translators = $self->loc->N("_: Translator(s) name(s) & email(s)\n");
+ $translators =~ s/\</\&lt\;/g;
+ $translators =~ s/\>/\&gt\;/g;
+ $self->sh_gui->AboutDialog({ name => $self->name,
+ version => $self->VERSION,
+ credits => $self->loc->N("Copyright (C) %s Mageia community", '2014'),
+ license => $self->loc->N("GPLv2"),
+ description => $self->loc->N("Log viewer is a systemd journal viewer"),
+ authors => $self->loc->N("<h3>Developers</h3>
+ <ul><li>%s</li>
+ <li>%s</li>
+ </ul>
+ <h3>Translators</h3>
+ <ul><li>%s</li></ul>",
+ "Angelo Naselli &lt;anaselli\@linux.it&gt;",
+ "Matteo Pasotti &lt;matteo.pasotti\@gmail.com&gt;",
+ $translators
+ ),
+ }
+ );
+ }
+ elsif($widget == $saveButton) {
+ if ($logView->lines()) {
+ $self->_save($logView);
+ }
+ else {
+ $self->sh_gui->warningMsgBox({text => $self->loc->N("Empty log found")});
+ }
+ }
+ elsif ($widget == $searchButton) {
+ yui::YUI::app()->busyCursor();
+ $dialog->startMultipleChanges();
+ $logView->clearText();
+ my %log_opts;
+ if ($lastBoot->value()) {
+ $log_opts{this_boot} = 1;
+ }
+ if ($unitsFrame->value()) {
+ $log_opts{unit} = $units->value();
+ }
+ if ($sinceFrame->value()) {
+ $log_opts{since} = $sinceDate->value() . " " . $sinceTime->value();
+ }
+ if ($untilFrame->value()) {
+ $log_opts{until} = $untilDate->value() . " " . $untilTime->value();
+# TODO check date until > date since
+ }
+ if ($priorityFromFrame->value() || $priorityToFrame->value()) {
+ my $prio = $priorityFrom->value();
+ $prio .= "..".$priorityTo->value() if ($priorityToFrame->value());
+ $log_opts{priority} = $prio;
+# TODO enabling right using checkBoxes
+ }
+ my $log = $self->_search(\%log_opts);
+print " log lines: ". scalar (@{$log}) ."\n";
+# TODO check on log line number what to do if too big? and adding a progress bar?
+ $self->_parse_content({'matching' => $matchingInputField->value(),
+ 'noMatching' => $notMatchingInputField->value(),
+ 'log' => $log,
+ 'logView' => $logView,
+ }
+ );
+ $dialog->recalcLayout();
+ $dialog->doneMultipleChanges();
+ yui::YUI::app()->normalCursor();
+ }
+ elsif ($widget == $lastBoot) {
+ yui::YUI::ui()->blockEvents();
+ if ($lastBoot->value()) {
+ #last boot overrrides until and since
+ $sinceFrame->setValue(0);
+ $untilFrame->setValue(0);
+ }
+ yui::YUI::ui()->unblockEvents();
+ }
+ elsif ($widget == $sinceFrame) {
+ yui::YUI::ui()->blockEvents();
+ if ($sinceFrame->value()) {
+ #disabling last boot that overrrides until and since
+ $lastBoot->setValue(0);
+ }
+ yui::YUI::ui()->unblockEvents();
+ }
+ elsif ($widget == $untilFrame) {
+ yui::YUI::ui()->blockEvents();
+ if ($untilFrame->value()) {
+ #disabling last boot that overrrides until and since
+ $lastBoot->setValue(0);
+ }
+ yui::YUI::ui()->unblockEvents();
+ }
+ elsif ($widget == $priorityFromFrame) {
+ if ($priorityToFrame->value() && !$priorityFromFrame->value()) {
+ yui::YUI::ui()->blockEvents();
+ $priorityToFrame->setValue(0) ;
+ yui::YUI::ui()->unblockEvents();
+ }
+ }
+ elsif ($widget == $priorityToFrame) {
+ if ($priorityToFrame->value() && !$priorityFromFrame->value()) {
+ yui::YUI::ui()->blockEvents();
+ $priorityFromFrame->setValue(1) ;
+ yui::YUI::ui()->unblockEvents();
+ }
+ }
+
+ }
+ }
+ $dialog->destroy();
+
+ #restore old application title
+ yui::YUI::app()->setApplicationTitle($appTitle) if $appTitle;
+}
+
+
+
+sub _warn_about_user_mode {
+ my $self = shift;
+
+ my $title = $self->loc->N("Running in user mode");
+ my $msg = $self->loc->N("You are launching this program as a normal user.\n".
+ "You will not be able to read system logs which you do not have rights to,\n".
+ "but you may still browse all the others.");
+
+ if(($EUID != 0) and (!$self->sh_gui->ask_OkCancel({title => $title, text => $msg}))) {
+ # TODO add Privileges?
+ return 0;
+ }
+
+ return 1;
+}
+
+
+## Save as
+#
+# $logView: log Widget
+#
+##
+sub _save {
+ my ($self, $logView) = @_;
+
+ yui::YUI::app()->busyCursor();
+
+ my $outFile = yui::YUI::app()->askForSaveFileName(home(), "*", $self->loc->N("Save as.."));
+ if ($outFile) {
+ open(OF, ">".$outFile);
+ print OF $logView->logText();
+ close OF;
+ }
+
+ yui::YUI::app()->normalCursor();
+}
+
+## Search call back
+sub _search {
+ my ($self, $log_opts) = @_;
+
+ my $log = ManaTools::Shared::JournalCtl->new(%{$log_opts});
+ my $all = $log->getLog();
+
+ return $all;
+}
+
+## _parse_content
+#
+# $info : HASH cotaining
+#
+# matching: string to match
+# notMatching: string to skip
+# log: ARRAY REF to log content
+# logViewer: logViewer Widget
+#
+##
+sub _parse_content {
+ my ($self, $info) = @_;
+
+ my $ey = "";
+ my $en = "";
+
+ if( exists($info->{'matching'} ) ){
+ $ey = $info->{'matching'};
+ }
+ if( exists($info->{'noMatching'} ) ){
+ $en = $info->{'noMatching'};
+ }
+
+ $ey =~ s/ OR /|/ if ($ey);
+ $ey =~ s/^\*$// if ($ey);
+ $en =~ s/^\*$/.*/ if ($en);
+
+ my $test;
+
+ if ($en && !$ey) {
+ $test = sub { $_[0] !~ /$en/ };
+ }
+ elsif ($ey && !$en) {
+ $test = sub { $_[0] =~ /$ey/ };
+ }
+ elsif ($ey && $en) {
+ $test = sub { $_[0] =~ /$ey/ && $_[0] !~ /$en/ };
+ }
+ else {
+ $test = sub { $_[0] };
+ }
+
+ foreach (@{$info->{log}}) {
+ $info->{logView}->appendLines($_) if $test->($_);
+ }
+
+}
+
+
+1
diff --git a/lib/ManaTools/Module/Proxy.pm b/lib/ManaTools/Module/Proxy.pm
new file mode 100644
index 0000000..ff2af3e
--- /dev/null
+++ b/lib/ManaTools/Module/Proxy.pm
@@ -0,0 +1,396 @@
+# vim: set et ts=4 sw=4:
+#*****************************************************************************
+#
+# Copyright (c) 2013-2015 Matteo Pasotti <matteo.pasotti@gmail.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2, as
+# published by the Free Software Foundation.
+#
+# 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.
+#
+#*****************************************************************************
+
+package ManaTools::Module::Proxy;
+
+use Modern::Perl '2011';
+use autodie;
+use Moose;
+use POSIX qw(ceil);
+use English;
+use utf8;
+
+use yui;
+use ManaTools::Shared qw(trim);
+use ManaTools::Shared::GUI;
+use ManaTools::Shared::Proxy;
+
+# TODROP but provides network::network
+use lib qw(/usr/lib/libDrakX);
+use network::network;
+use MDK::Common::System qw(getVarsFromSh);
+
+extends qw( ManaTools::Module );
+
+
+has '+icon' => (
+ default => "/usr/share/mcc/themes/default/drakproxy-mdk.png"
+);
+
+has '+name' => (
+ default => "Proxymanager",
+);
+
+=head1 VERSION
+
+Version 1.0.0
+
+=cut
+
+our $VERSION = '1.0.0';
+
+has 'dialog' => (
+ is => 'rw',
+ init_arg => undef
+);
+
+has 'table' => (
+ is => 'rw',
+ init_arg => undef
+);
+
+has 'proxy' => (
+ is => 'rw',
+ isa => 'HashRef',
+ builder => "init_proxy"
+);
+
+has 'sh_gui' => (
+ is => 'rw',
+ init_arg => undef,
+ builder => '_SharedUGUIInitialize'
+);
+
+has 'loc' => (
+ is => 'rw',
+ init_arg => undef,
+ builder => '_localeInitialize'
+);
+
+
+sub _localeInitialize {
+ my $self = shift();
+
+ # TODO fix domain binding for translation
+ $self->loc(ManaTools::Shared::Locales->new(domain_name => 'drakx-net') );
+ # TODO if we want to give the opportunity to test locally add dir_name => 'path'
+}
+
+sub _SharedUGUIInitialize {
+ my $self = shift();
+
+ $self->sh_gui( ManaTools::Shared::GUI->new() );
+}
+
+#=============================================================
+
+=head2 init_proxy
+
+=head3 DESCRIPTION
+
+=over 4
+
+=item This method does initialize the proxy attribute provided by this class.
+
+=item $self->proxy is structured as follows:
+
+=over 6
+
+=item B<no_proxy> the string with the list of the excluded domains/addresses
+
+=item B<http_proxy> the url of the http proxy
+
+=item B<https_proxy> the url of the https proxy
+
+=item B<ftp_proxy> the url for the ftp proxy
+
+=back
+
+=back
+
+=cut
+
+#=============================================================
+
+sub init_proxy {
+ my %p = (
+ 'no_proxy' => '',
+ 'http_proxy' => '',
+ 'https_proxy' => '',
+ 'ftp_proxy' => '',
+ );
+ return \%p;
+}
+
+#=============================================================
+
+=head2 start
+
+=head3 INPUT
+
+ $self: this object
+
+=head3 DESCRIPTION
+
+ This method extends Module::start and is invoked to
+ start proxy manager
+
+=cut
+
+#=============================================================
+sub start {
+ my $self = shift;
+
+ if ($EUID != 0) {
+ $self->sh_gui->warningMsgBox({
+ title => $self->name,
+ text => $self->loc->N("root privileges required"),
+ });
+ return;
+ }
+
+ $self->_manageProxyDialog();
+};
+
+#=============================================================
+
+=head2 ask_for_X_restart
+
+=head3 INPUT
+
+ $self: this object
+
+=head3 DESCRIPTION
+
+ This method shows a message box warning the user
+ that a X server restart is required
+
+=cut
+
+#=============================================================
+
+sub ask_for_X_restart {
+ my $self = shift;
+
+ $self->sh_gui->warningMsgBox({title=>$self->loc->N("X Restart Required"),text=>$self->loc->N("You need to log out and back in again for changes to take effect"),richtext=>1});
+}
+
+#=============================================================
+
+=head2 validate
+
+=head3 INPUT
+
+ $self: this object
+
+ $proxy: the hash containing what returns from getVarFromSh
+ eventually modified by the user
+
+=head3 DESCRIPTION
+
+ This method returns true if the each value match
+ certain conditions like the leading http:// for http proxy
+ or https:// for the https proxy, etc.
+
+ $proxy is passed by reference thus $proxy->{no_proxy} value
+ is sanitized (trimmed).
+
+=cut
+
+#=============================================================
+
+sub validate {
+ my $self = shift;
+ my $proxy = shift;
+ my $retval = 1;
+ $proxy->{no_proxy} =~ s/\s//g;
+ # using commas rather than slashes
+ if($proxy->{http_proxy} !~ m,^($|http://),)
+ {
+ $self->sh_gui->warningMsgBox({title=>'Error',text=>$self->loc->N("Proxy should be http://..."),richtext=>0});
+ $retval = 0;
+ }
+ if($proxy->{https_proxy} !~ m,^($|https?://),)
+ {
+ $self->sh_gui->warningMsgBox({title=>'Error',text=>$self->loc->N("Proxy should be http://... or https://..."),richtext=>0});
+ $retval = 0;
+ }
+ if($proxy->{ftp_proxy} !~ m,^($|ftp://|http://),)
+ {
+ $self->sh_gui->warningMsgBox({title=>'Error',text=>$self->loc->N("URL should begin with 'ftp:' or 'http:'"),richtext=>0});
+ $retval = 0;
+ }
+ return $retval;
+}
+
+sub _manageProxyDialog {
+ my $self = shift;
+
+ ## TODO fix for manatools
+ my $appTitle = yui::YUI::app()->applicationTitle();
+ my $appIcon = yui::YUI::app()->applicationIcon();
+ ## set new title to get it in dialog
+ my $newTitle = $self->loc->N("Proxies configuration");
+ yui::YUI::app()->setApplicationTitle($newTitle);
+
+ my $factory = yui::YUI::widgetFactory;
+ my $optional = yui::YUI::optionalWidgetFactory;
+
+ my $label_width = 25;
+ my $inputfield_width = 45;
+ # getVarsFromSh returns an empty hash if no vars are defined
+ # possible alternatives:
+ # . Config::Auto::parse
+ my $proxy_curr_settings = { getVarsFromSh('/etc/profile.d/proxy.sh') };
+ my $httpsProxyEqualToHttpProxy = 0;
+ if((defined($proxy_curr_settings->{http_proxy}) && defined($proxy_curr_settings->{https_proxy}))&&
+ (($proxy_curr_settings->{http_proxy} eq $proxy_curr_settings->{https_proxy}) &&
+ ($proxy_curr_settings->{http_proxy} ne ""))){
+ $httpsProxyEqualToHttpProxy = 1;
+ }
+
+ #
+ # @layout
+ #
+ # +------------------------------+
+ # | +------------+-------------+ |
+ # | |LABELS | VALUES | |
+ # | | | | |
+ # | | | | |
+ # | | | | |
+ # | +------------+-------------+ |
+ # +------------------------------+
+
+ $self->dialog($factory->createMainDialog());
+ my $layout = $factory->createVBox($self->dialog);
+
+ my $hbox_header = $factory->createHBox($layout);
+ my $headLeft = $factory->createHBox($factory->createLeft($hbox_header));
+ my $headRight = $factory->createHBox($factory->createRight($hbox_header));
+
+ my $logoImage = $factory->createImage($headLeft, $appIcon);
+ my $labelAppDescription = $factory->createLabel($headRight,$newTitle);
+ $logoImage->setWeight($yui::YD_HORIZ,0);
+ $labelAppDescription->setWeight($yui::YD_HORIZ,3);
+
+ # app description
+ my $hbox_content = $factory->createHBox($layout);
+ $factory->createLabel($hbox_content, $self->loc->N("Here you can set up your proxies configuration (eg: http://my_caching_server:8080)"));
+
+ $hbox_content = $factory->createHBox($layout);
+
+ my $vbox_labels_flags = $factory->createVBox($hbox_content);
+ my $vbox_inputfields = $factory->createVBox($hbox_content);
+
+ # http proxy section
+ my $httpproxy_label = $factory->createLabel($vbox_labels_flags, $self->loc->N("HTTP proxy"));
+ my $http_proxy = $factory->createInputField($factory->createHBox($vbox_inputfields),"",0);
+ $http_proxy->setValue($proxy_curr_settings->{http_proxy}) if(defined($proxy_curr_settings->{http_proxy}));
+ $http_proxy->setWeight($yui::YD_HORIZ, 30);
+
+ # flag to setup the https proxy with the same value of the http proxy
+ my $ckbHttpEqHttps = $factory->createCheckBox($vbox_labels_flags, $self->loc->N("Use HTTP proxy for HTTPS connections"),$httpsProxyEqualToHttpProxy);
+ $ckbHttpEqHttps->setNotify(1);
+ # add a spacing as we have
+ $factory->createLabel($factory->createHBox($vbox_inputfields)," ");
+
+ # https proxy
+ $factory->createLabel($vbox_labels_flags, $self->loc->N("HTTPS proxy"));
+ my $https_proxy = $factory->createInputField($factory->createHBox($vbox_inputfields),"",0);
+ $https_proxy->setValue($proxy_curr_settings->{https_proxy}) if(defined($proxy_curr_settings->{https_proxy}));
+ $https_proxy->setWeight($yui::YD_HORIZ, 30);
+
+ # ftp proxy
+ $factory->createLabel($vbox_labels_flags, $self->loc->N("FTP proxy"));
+ my $ftp_proxy = $factory->createInputField($factory->createHBox($vbox_inputfields),"",0);
+ $ftp_proxy->setValue($proxy_curr_settings->{ftp_proxy}) if(defined($proxy_curr_settings->{ftp_proxy}));
+ $ftp_proxy->setWeight($yui::YD_HORIZ, 30);
+
+ # no-proxy list
+ $factory->createLabel($vbox_labels_flags, $self->loc->N("No proxy for (comma separated list):"));
+ my $no_proxy = $factory->createInputField($factory->createHBox($vbox_inputfields),"",0);
+ $no_proxy->setValue($proxy_curr_settings->{no_proxy}) if(defined($proxy_curr_settings->{no_proxy}));
+ $no_proxy->setWeight($yui::YD_HORIZ, 30);
+
+ my $hbox_filler = $factory->createHBox($layout);
+ $factory->createSpacing($hbox_filler,$yui::YD_VERT,2);
+
+ my $hbox_foot = $factory->createHBox($layout);
+ my $vbox_foot_left = $factory->createVBox($factory->createLeft($hbox_foot));
+ my $vbox_foot_right = $factory->createVBox($factory->createRight($hbox_foot));
+ my $aboutButton = $factory->createPushButton($vbox_foot_left,$self->loc->N("&About"));
+ my $cancelButton = $factory->createPushButton($vbox_foot_right,$self->loc->N("&Cancel"));
+ my $okButton = $factory->createPushButton($vbox_foot_right,$self->loc->N("&OK"));
+
+ # main loop
+ while(1) {
+ my $event = $self->dialog->waitForEvent();
+ my $eventType = $event->eventType();
+
+ #event type checking
+ if ($eventType == $yui::YEvent::CancelEvent) {
+ last;
+ }
+ elsif ($eventType == $yui::YEvent::WidgetEvent) {
+### Buttons and widgets ###
+ my $widget = $event->widget();
+ if ($widget == $cancelButton) {
+ last;
+ }elsif ($widget == $aboutButton) {
+ $self->sh_gui->AboutDialog({
+ name => $appTitle,
+ version => $VERSION,
+ credits => "Copyright (c) 2013-2014 by Matteo Pasotti",
+ license => "GPLv2",
+ description => $self->loc->N("Graphical manager for proxies"),
+ authors => "Matteo Pasotti &lt;matteo.pasotti\@gmail.com&gt;"
+ }
+ );
+ }elsif ($widget == $okButton) {
+ # setup proxy attribute
+ my %_proxy = (
+ no_proxy => $no_proxy->value(),
+ http_proxy => $http_proxy->value(),
+ https_proxy => $https_proxy->value(),
+ ftp_proxy => $ftp_proxy->value()
+ );
+ if($self->validate(\%_proxy)) {
+ # validation succeded
+ $self->proxy(\%_proxy);
+ # save changes
+ network::network::proxy_configure($self->proxy);
+ $self->ask_for_X_restart();
+ last;
+ }
+ # validation failed
+ next;
+ }elsif ($widget == $ckbHttpEqHttps){
+ $https_proxy->setEnabled(!$ckbHttpEqHttps->isChecked());
+ }
+ }
+ }
+
+ $self->dialog->destroy() ;
+
+ #restore old application title
+ yui::YUI::app()->setApplicationTitle($appTitle);
+}
+
+1;
diff --git a/lib/ManaTools/Module/Services.pm b/lib/ManaTools/Module/Services.pm
new file mode 100644
index 0000000..dca0c0c
--- /dev/null
+++ b/lib/ManaTools/Module/Services.pm
@@ -0,0 +1,588 @@
+# vim: set et ts=4 sw=4:
+
+package ManaTools::Module::Services;
+
+#============================================================= -*-perl-*-
+
+=head1 NAME
+
+ManaTools::Module::Services - This module aims to manage service
+ with GUI
+
+=head1 SYNOPSIS
+
+ my $serviceMan = ManaTools::Module::Services->new();
+ $serviceMan->start();
+
+=head1 DESCRIPTION
+
+ This module presents all the system service status and gives
+ the availability to administrator to stop, start and active at boot
+ them.
+
+ From the original code drakx services.
+
+=head1 SUPPORT
+
+ You can find documentation for this module with the perldoc command:
+
+ perldoc ManaTools::Module::Services
+
+=head1 SEE ALSO
+
+ ManaTools::Module
+
+=head1 AUTHOR
+
+Angelo Naselli <anaselli@linux.it>
+
+=head1 COPYRIGHT and LICENSE
+
+Copyright (C) 2014-2015, Angelo Naselli.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License version 2, as
+published by the Free Software Foundation.
+
+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
+
+=cut
+
+
+use Moose;
+use English;
+use Time::HiRes qw(usleep);
+
+use MDK::Common::String qw(formatAlaTeX);
+use MDK::Common::DataStructure qw(member);
+
+use yui;
+use ManaTools::Shared::GUI;
+use ManaTools::Shared::Locales;
+use ManaTools::Shared::Services;
+
+
+use File::Basename;
+
+extends qw( ManaTools::Module );
+
+has '+icon' => (
+ default => "/usr/share/mcc/themes/default/service-mdk.png",
+);
+
+has '_services' => (
+ traits => ['Array'],
+ is => 'rw',
+ isa => 'ArrayRef[Str]',
+ default => sub { [] },
+ init_arg => undef,
+ handles => {
+ all_services => 'elements',
+ add_service => 'push',
+ map_service => 'map',
+ service_count => 'count',
+ sorted_services => 'sort',
+ },
+);
+
+has '_xinetd_services' => (
+ traits => ['Array'],
+ is => 'rw',
+ isa => 'ArrayRef[Str]',
+ default => sub { [] },
+ init_arg => undef,
+ handles => {
+ all_xinetd_services => 'elements',
+ add_xinetd_service => 'push',
+ map_xinetd_service => 'map',
+ xinetd_service_count => 'count',
+ sorted_xinetd_services => 'sort',
+ },
+);
+
+has 'on_services' => (
+ traits => ['Array'],
+ is => 'rw',
+ isa => 'ArrayRef[Str]',
+ default => sub { [] },
+ init_arg => undef,
+ handles => {
+ all_on_services => 'elements',
+ add_on_service => 'push',
+ map_on_service => 'map',
+ on_service_count => 'count',
+ sorted_on_services => 'sort',
+ },
+);
+
+
+has 'sh_gui' => (
+ is => 'rw',
+ init_arg => undef,
+ builder => '_SharedUGUIInitialize'
+);
+
+sub _SharedUGUIInitialize {
+ my $self = shift();
+
+ $self->sh_gui(ManaTools::Shared::GUI->new() );
+}
+
+has 'sh_services' => (
+ is => 'rw',
+ init_arg => undef,
+ lazy => 1,
+ builder => '_SharedServicesInitialize'
+);
+
+sub _SharedServicesInitialize {
+ my $self = shift();
+
+ $self->sh_services(ManaTools::Shared::Services->new() );
+}
+
+
+has 'loc' => (
+ is => 'rw',
+ init_arg => undef,
+ builder => '_localeInitialize'
+);
+
+sub _localeInitialize {
+ my $self = shift();
+
+ # TODO fix domain binding for translation
+ $self->loc(ManaTools::Shared::Locales->new(domain_name => 'libDrakX-standalone') );
+ # TODO if we want to give the opportunity to test locally add dir_name => 'path'
+}
+
+=head1 VERSION
+
+Version 1.0.0
+
+=cut
+
+our $VERSION = '1.0.0';
+
+=head1 METHODS
+
+=cut
+
+#=============================================================
+
+=head2 BUILD
+
+=head3 INPUT
+
+ $self: this object
+
+=head3 DESCRIPTION
+
+ The BUILD method is called after a Moose object is created,
+ in this methods Services loads all the service information.
+
+=cut
+
+#=============================================================
+sub BUILD {
+ my $self = shift;
+
+ if (! $self->name) {
+ $self->name ($self->loc->N("adminService"));
+ }
+
+ $self->loadServices();
+}
+
+
+#=============================================================
+
+=head2 start
+
+=head3 INPUT
+
+ $self: this object
+
+=head3 DESCRIPTION
+
+ This method extends Module::start and is invoked to
+ start adminService
+
+=cut
+
+#=============================================================
+sub start {
+ my $self = shift;
+
+# if ($EUID != 0) {
+# $self->sh_gui->warningMsgBox({
+# title => $self->name,
+# text => $self->loc->N("root privileges required"),
+# });
+# return;
+# }
+
+ $self->_servicePanel();
+};
+
+
+#=============================================================
+
+=head2 loadServices
+
+=head3 INPUT
+
+ $self: this object
+
+=head3 DESCRIPTION
+
+ This methonds load service info into local attributes such
+ as xinetd_services, on_services and all the available,
+ services
+
+=cut
+
+#=============================================================
+sub loadServices {
+ my $self = shift;
+
+ my $refresh = 1;
+ my ($l, $on_services) = $self->sh_services->services($refresh);
+ my @xinetd_services = map { $_->[0] } $self->sh_services->xinetd_services();
+
+ $self->_xinetd_services();
+ $self->_xinetd_services(\@xinetd_services);
+ $self->_services(\@$l);
+ $self->on_services(\@$on_services);
+
+}
+
+## _waitUnitStatus wait unit status is reached for
+## a while (10 secs max)
+sub _waitUnitStatus {
+ my ($self, $service, $running) = @_;
+
+ for (my $i=0; $i < 100; $i++) {
+ $self->loadServices();
+ if ($running) {
+ last if $self->sh_services->is_service_running($service);
+ }
+ else {
+ last if !$self->sh_services->is_service_running($service);
+ }
+ usleep(100);
+ }
+}
+
+## _serviceInfo sets service description accordingly to
+## selected service status
+## param
+## 'service' service name
+## 'infoPanel' service information widget
+sub _serviceInfo {
+ my ($self, $service, $infoPanel) = @_;
+
+ yui::YUI::ui()->blockEvents();
+ ## infoPanel
+ $infoPanel->setValue(MDK::Common::String::formatAlaTeX($self->sh_services->description($service)));
+ yui::YUI::ui()->unblockEvents();
+}
+
+
+sub _serviceStatusString {
+ my ($self, $serviceName) = @_;
+
+ my $started;
+
+ if (MDK::Common::DataStructure::member($serviceName, $self->all_xinetd_services)) {
+ $started = $self->loc->N("Start when requested");
+ }
+ else {
+ $started = ($self->sh_services->is_service_running($serviceName)? $self->loc->N("running") : $self->loc->N("stopped"));
+ }
+
+ return $started;
+}
+
+## _serviceStatus sets status label accordingly to selected item
+## param
+## 'service' yui CB table (service table)
+## 'item' selected item (service)
+sub _serviceStatus {
+ my ($self, $tbl, $item) = @_;
+
+ my $started = $self->_serviceStatusString($item->label());
+
+ # TODO add icon green/red led
+ my $cell = $tbl->toCBYTableItem($item)->cell(1);
+ if ($cell) {
+ $cell->setLabel($started);
+ $tbl->cellChanged($cell);
+ }
+}
+
+
+## fill service table with service info
+## param
+## 'tbl' yui table
+sub _fillServiceTable {
+ my ($self, $tbl) = @_;
+
+ $tbl->startMultipleChanges();
+ $tbl->deleteAllItems();
+ my $itemCollection = new yui::YItemCollection;
+ foreach (sort $self->all_services) {
+
+ my $serviceName = $_;
+
+ my $item = new yui::YCBTableItem($serviceName);
+ my $started = $self->_serviceStatusString($serviceName);
+
+ # TODO add icon green/red led
+ my $cell = new yui::YTableCell($started);
+ $item->addCell($cell);
+
+ $item->check(MDK::Common::DataStructure::member($serviceName, $self->all_on_services));
+ $item->setLabel($serviceName);
+ $itemCollection->push($item);
+ $item->DISOWN();
+ }
+ $tbl->addItems($itemCollection);
+ $tbl->doneMultipleChanges();
+}
+
+## draw service panel and manage it (main dialog)
+sub _servicePanel {
+ my $self = shift;
+
+ my $appTitle = yui::YUI::app()->applicationTitle();
+
+ ## set new title to get it in dialog
+ yui::YUI::app()->setApplicationTitle($self->name);
+ ## set icon if not already set by external launcher
+ yui::YUI::app()->setApplicationIcon($self->icon);
+
+ my $mageiaPlugin = "mga";
+ my $factory = yui::YUI::widgetFactory;
+ my $mgaFactory = yui::YExternalWidgets::externalWidgetFactory($mageiaPlugin);
+ $mgaFactory = yui::YMGAWidgetFactory::getYMGAWidgetFactory($mgaFactory);
+
+ my $dialog = $factory->createMainDialog;
+ my $vbox = $factory->createVBox( $dialog );
+
+ #Line for logo and title
+ my $hbox_iconbar = $factory->createHBox($vbox);
+ my $head_align_left = $factory->createLeft($hbox_iconbar);
+ $hbox_iconbar = $factory->createHBox($head_align_left);
+ $factory->createImage($hbox_iconbar, $self->icon);
+
+ $factory->createHeading($hbox_iconbar, $self->loc->N("Manage system services by enabling or disabling them"));
+
+ my $frame = $factory->createFrame ($vbox, "");
+
+ my $frmVbox = $factory->createVBox( $frame );
+ my $hbox = $factory->createHBox( $frmVbox );
+
+ my $yTableHeader = new yui::YTableHeader();
+ $yTableHeader->addColumn($self->loc->N("Service"), $yui::YAlignBegin);
+ $yTableHeader->addColumn($self->loc->N("Status"), $yui::YAlignCenter);
+ $yTableHeader->addColumn($self->loc->N("On boot"), $yui::YAlignBegin);
+
+ ## service list (serviceBox)
+ my $serviceTbl = $mgaFactory->createCBTable($hbox, $yTableHeader, $yui::YCBTableCheckBoxOnLastColumn);
+
+ $self->_fillServiceTable($serviceTbl);
+
+ $serviceTbl->setImmediateMode(1);
+ $serviceTbl->setWeight(0, 50);
+
+ ## info panel (infoPanel)
+ $frame = $factory->createFrame ($hbox, $self->loc->N("Information"));
+ $frame->setWeight(0, 30);
+ $frmVbox = $factory->createVBox( $frame );
+ my $infoPanel = $factory->createRichText($frmVbox, "--------------"); #, 0, 0);
+ $infoPanel->setAutoScrollDown();
+
+ ### Service Start button ($startButton)
+ $hbox = $factory->createHBox( $frmVbox );
+ my $startButton = $factory->createPushButton($hbox, $self->loc->N("&Start"));
+
+ ### Service Stop button ($stopButton)
+ my $stopButton = $factory->createPushButton($hbox, $self->loc->N("S&top"));
+
+ # dialog buttons
+ $factory->createVSpacing($vbox, 1.0);
+ ## Window push buttons
+ $hbox = $factory->createHBox( $vbox );
+ my $align = $factory->createLeft($hbox);
+ $hbox = $factory->createHBox($align);
+ my $aboutButton = $factory->createPushButton($hbox, $self->loc->N("&About") );
+ $align = $factory->createRight($hbox);
+ $hbox = $factory->createHBox($align);
+
+ ### Service Refresh button ($refreshButton)
+ my $refreshButton = $factory->createPushButton($hbox, $self->loc->N("&Refresh"));
+ my $closeButton = $factory->createPushButton($hbox, $self->loc->N("&Quit") );
+
+ #first item status
+ my $item = $serviceTbl->selectedItem();
+ if ($item) {
+ $self->_serviceInfo($item->label(), $infoPanel);
+ if (MDK::Common::DataStructure::member($item->label(), $self->all_xinetd_services)) {
+ $stopButton->setDisabled();
+ $startButton->setDisabled();
+ }
+ else {
+ $stopButton->setEnabled(1);
+ $startButton->setEnabled(1);
+ }
+ }
+
+ while(1) {
+ my $event = $dialog->waitForEvent();
+ my $eventType = $event->eventType();
+
+ #event type checking
+ if ($eventType == $yui::YEvent::CancelEvent) {
+ last;
+ }
+ elsif ($eventType == $yui::YEvent::WidgetEvent) {
+ # widget selected
+ my $widget = $event->widget();
+ my $wEvent = yui::toYWidgetEvent($event);
+
+ if ($widget == $closeButton) {
+ last;
+ }
+ elsif ($widget == $aboutButton) {
+ my $translators = $self->loc->N("_: Translator(s) name(s) & email(s)\n");
+ $translators =~ s/\</\&lt\;/g;
+ $translators =~ s/\>/\&gt\;/g;
+ $self->sh_gui->AboutDialog({ name => $self->name,
+ version => $self->VERSION,
+ credits => $self->loc->N("Copyright (C) %s Mageia community", '2013-2015'),
+ license => $self->loc->N("GPLv2"),
+ description => $self->loc->N("adminService is the Mageia service and daemon management tool\n
+ (from the original idea of Mandriva draxservice)."),
+ authors => $self->loc->N("<h3>Developers</h3>
+ <ul><li>%s</li>
+ <li>%s</li>
+ </ul>
+ <h3>Translators</h3>
+ <ul><li>%s</li></ul>",
+ "Angelo Naselli &lt;anaselli\@linux.it&gt;",
+ "Matteo Pasotti &lt;matteo.pasotti\@gmail.com&gt;",
+ $translators
+ ),
+ }
+ );
+ }
+ elsif ($widget == $serviceTbl) {
+
+ # service selection changed
+ $item = $serviceTbl->selectedItem();
+ if ($item) {
+ $self->_serviceInfo($item->label(), $infoPanel);
+ if (MDK::Common::DataStructure::member($item->label(), $self->all_xinetd_services)) {
+ $stopButton->setDisabled();
+ $startButton->setDisabled();
+ }
+ else {
+ $stopButton->setEnabled(1);
+ $startButton->setEnabled(1);
+ }
+ }
+# TODO fix libyui-mga-XXX item will always be changed after first one
+ if ($wEvent->reason() == $yui::YEvent::ValueChanged) {
+ $item = $serviceTbl->changedItem();
+ if ($item) {
+ yui::YUI::app()->busyCursor();
+ eval {
+ $self->sh_services->set_service($item->label(), $item->checked());
+ };
+ my $errors = $@;
+ $self->loadServices();
+ yui::YUI::app()->normalCursor();
+
+ if ($errors) {
+ $self->sh_gui->warningMsgBox({
+ title => $self->loc->N($item->checked() ? "Enabling %s" : "Disabling %s", $item->label()),
+ text => "$errors",
+ richtext => 1,
+ });
+ $dialog->startMultipleChanges();
+ $self->_fillServiceTable($serviceTbl);
+ $dialog->recalcLayout();
+ $dialog->doneMultipleChanges();
+ }
+ }
+ }
+ }
+ elsif ($widget == $startButton) {
+ $item = $serviceTbl->selectedItem();
+ if ($item) {
+ my $serviceName = $item->label();
+ yui::YUI::app()->busyCursor();
+ eval {
+ $self->sh_services->restart_or_start($serviceName);
+ $self->_waitUnitStatus($serviceName, 1);
+ };
+ my $errors = $@;
+ yui::YUI::app()->normalCursor();
+ $self->_serviceStatus($serviceTbl, $item);
+
+ $self->sh_gui->warningMsgBox({
+ title => $self->loc->N("Starting %s", $serviceName),
+ text => "$errors",
+ richtext => 1,
+ }) if $errors;
+ }
+ }
+ elsif ($widget == $stopButton) {
+ $item = $serviceTbl->selectedItem();
+ if ($item) {
+ my $serviceName = $item->label();
+ yui::YUI::app()->busyCursor();
+ eval {
+ $self->sh_services->stopService($serviceName);
+ $self->_waitUnitStatus($serviceName, 0);
+ };
+ my $errors = $@;
+ yui::YUI::app()->normalCursor();
+ $self->_serviceStatus($serviceTbl, $item);
+
+ $self->sh_gui->warningMsgBox({
+ title => $self->loc->N("Stopping %s", $serviceName),
+ text => "$errors",
+ richtext => 1,
+ }) if $errors;
+ }
+ }
+ elsif ($widget == $refreshButton) {
+ yui::YUI::app()->busyCursor();
+ $self->loadServices();
+ $dialog->startMultipleChanges();
+ $self->_fillServiceTable($serviceTbl);
+ $dialog->recalcLayout();
+ $dialog->doneMultipleChanges();
+ yui::YUI::app()->normalCursor();
+ }
+ }
+ }
+ $dialog->destroy();
+
+ #restore old application title
+ yui::YUI::app()->setApplicationTitle($appTitle) if $appTitle;
+}
+
+no Moose;
+__PACKAGE__->meta->make_immutable;
+
+1;
diff --git a/lib/ManaTools/Module/Users.pm b/lib/ManaTools/Module/Users.pm
new file mode 100644
index 0000000..2ef9066
--- /dev/null
+++ b/lib/ManaTools/Module/Users.pm
@@ -0,0 +1,2637 @@
+# vim: set et ts=4 sw=4:
+
+package ManaTools::Module::Users;
+
+#============================================================= -*-perl-*-
+
+=head1 NAME
+
+ManaTools::Module::Users - This module aims to manage service
+ with GUI
+
+=head1 SYNOPSIS
+
+ my $userManager = ManaTools::Module::Users->new();
+ $userManager->start();
+
+=head1 DESCRIPTION
+
+ This module is a tool to manage users on the system.
+
+ From the original code adduserdrake and userdrake.
+
+=head1 SUPPORT
+
+ You can find documentation for this module with the perldoc command:
+
+ perldoc ManaTools::Module::Users
+
+=head1 SEE ALSO
+
+ ManaTools::Module
+
+=head1 AUTHOR
+
+Angelo Naselli <anaselli@linux.it>
+
+=head1 COPYRIGHT and LICENSE
+
+Copyright (C) 2013-2015, Angelo Naselli.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License version 2, as
+published by the Free Software Foundation.
+
+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
+
+=head1 VERSION
+
+Version 1.0.0
+
+=cut
+
+our $VERSION = '1.0.0';
+
+
+###############################################
+##
+## graphic related routines for managing user
+##
+###############################################
+
+use Moose;
+
+use POSIX qw(ceil);
+use Config::Auto;
+use File::ShareDir ':ALL';
+
+use utf8;
+use Sys::Syslog;
+use Glib;
+use English;
+use yui;
+use ManaTools::Shared;
+use ManaTools::Shared::GUI;
+use ManaTools::Shared::Locales;
+use ManaTools::Shared::Users;
+use MDK::Common::DataStructure qw(member);
+use feature 'state';
+
+extends qw( ManaTools::Module );
+
+has '+icon' => (
+ default => "/usr/share/icons/userdrake.png",
+);
+
+
+# main dialog
+has 'dialog' => (
+ is => 'rw',
+ init_arg => undef,
+);
+
+has 'widgets' => (
+ traits => ['Hash'],
+ default => sub { {} },
+ is => 'rw',
+ isa => 'HashRef',
+ handles => {
+ set_widget => 'set',
+ get_widget => 'get',
+ widget_pairs => 'kv',
+ },
+ init_arg => undef,
+);
+
+has 'action_menu' => (
+ traits => ['Hash'],
+ default => sub { {} },
+ is => 'rw',
+ isa => 'HashRef',
+ handles => {
+ set_action_menu => 'set',
+ get_action_menu => 'get',
+ action_menu_pairs => 'kv',
+ },
+ init_arg => undef,
+);
+
+
+has 'edit_tab_widgets' => (
+ traits => ['Hash'],
+ default => sub { {} },
+ is => 'rw',
+ isa => 'HashRef',
+ handles => {
+ set_edit_tab_widget => 'set',
+ get_edit_tab_widget => 'get',
+ edit_tab_pairs => 'kv',
+ },
+ init_arg => undef,
+);
+
+has 'sh_users' => (
+ is => 'rw',
+ init_arg => undef,
+ builder => '_SharedUsersInitialize'
+);
+
+sub _SharedUsersInitialize {
+ my $self = shift();
+
+ $self->sh_users(ManaTools::Shared::Users->new() );
+}
+
+has 'sh_gui' => (
+ is => 'rw',
+ init_arg => undef,
+ builder => '_SharedUGUIInitialize'
+);
+
+sub _SharedUGUIInitialize {
+ my $self = shift();
+
+ $self->sh_gui(ManaTools::Shared::GUI->new() );
+}
+
+has 'loc' => (
+ is => 'rw',
+ init_arg => undef,
+ builder => '_localeInitialize'
+);
+
+
+sub _localeInitialize {
+ my $self = shift();
+
+ # TODO fix domain binding for translation
+ $self->loc(ManaTools::Shared::Locales->new(domain_name => 'userdrake') );
+ # TODO if we want to give the opportunity to test locally add dir_name => 'path'
+}
+
+
+#=============================================================
+
+=head1 METHODS
+
+=cut
+
+=head2 new - additional parameters
+
+=head3 config_file
+
+ optional parameter to set the configuration file name
+
+=cut
+
+has 'config_file' => (
+ is => 'rw',
+ isa => 'Str',
+ default => '/etc/sysconfig/manauser',
+);
+
+
+
+#=============================================================
+
+=head2 start
+
+=head3 INPUT
+
+ $self: this object
+
+=head3 DESCRIPTION
+
+ This method extends Module::start and is invoked to
+ start adminService
+
+=cut
+
+#=============================================================
+sub start {
+ my $self = shift;
+
+ $self->_manageUsersDialog();
+};
+
+# TODO move to Shared?
+sub _labeledFrameBox {
+ my ($parent, $label) = @_;
+
+ my $factory = yui::YUI::widgetFactory;
+
+ my $frame = $factory->createFrame($parent, $label);
+ $frame->setWeight( $yui::YD_HORIZ, 1);
+ $frame->setWeight( $yui::YD_VERT, 2);
+ $frame = $factory->createHVCenter( $frame );
+ $frame = $factory->createVBox( $frame );
+ return $frame;
+}
+
+# usefull local variable to avoid duplicating
+# translation point for user edit labels
+my %userEditLabel;
+# usefull local variable to avoid duplicating
+# translation point for group edit labels
+my %groupEditLabel;
+
+
+#=============================================================
+
+=head2 BUILD
+
+=head3 INPUT
+
+ $self: this object
+
+=head3 DESCRIPTION
+
+ The BUILD method is called after a Moose object is created,
+ Into this method additional data are initialized.
+
+=cut
+
+#=============================================================
+sub BUILD {
+ my $self = shift;
+
+ if (! $self->name) {
+ $self->name ($self->loc->N("manauser"));
+ }
+
+ %userEditLabel = (
+ user_data => $self->loc->N("User Data"),
+ account_info => $self->loc->N("Account Info"),
+ password_info => $self->loc->N("Password Info"),
+ groups => $self->loc->N("Groups"),
+ );
+ %groupEditLabel = (
+ group_data => $self->loc->N("Group Data"),
+ group_users => $self->loc->N("Group Users"),
+ );
+}
+
+
+#=============================================================
+
+=head2 ChooseGroup
+
+=head3 INPUT
+
+ $self: this object
+
+=head3 OUTPUT
+
+ $choice: 0 or 1 (choice)
+ -1 cancel or exit
+
+=head3 DESCRIPTION
+
+creates a popup dialog to ask if adding user to an existing
+group or to the 'users' group
+
+=cut
+
+#=============================================================
+sub ChooseGroup {
+ my $self = shift;
+
+ my $choice = -1;
+
+ ## push application title
+ my $appTitle = yui::YUI::app()->applicationTitle();
+ ## set new title to get it in dialog
+ yui::YUI::app()->setApplicationTitle($self->loc->N("Choose group"));
+
+ my $factory = yui::YUI::widgetFactory;
+
+ my $dlg = $factory->createPopupDialog();
+ my $layout = $factory->createVBox($dlg);
+
+
+ my $frame = _labeledFrameBox($layout, $self->loc->N("A group with this name already exists. What would you like to do?"));
+
+ my $rbg = $factory->createRadioButtonGroup( $frame );
+ $frame = $factory->createVBox( $rbg );
+ my $align = $factory->createLeft($frame);
+
+ my $rb1 = $factory->createRadioButton( $align, $self->loc->N("Add to the existing group"), 1);
+ $rb1->setNotify(1);
+ $rbg->addRadioButton( $rb1 );
+ $align = $factory->createLeft($frame);
+ my $rb2 = $factory->createRadioButton( $align, $self->loc->N("Add to the 'users' group"), 0);
+ $rb2->setNotify(1);
+ $rbg->addRadioButton( $rb2 );
+
+ my $hbox = $factory->createHBox($layout);
+ $align = $factory->createRight($hbox);
+ my $cancelButton = $factory->createPushButton($align, $self->loc->N("Cancel"));
+ my $okButton = $factory->createPushButton($hbox, $self->loc->N("Ok"));
+ while(1) {
+ my $event = $dlg->waitForEvent();
+ my $eventType = $event->eventType();
+
+ #event type checking
+ if ($eventType == $yui::YEvent::CancelEvent) {
+ last;
+ }
+ elsif ($eventType == $yui::YEvent::WidgetEvent) {
+ # widget selected
+ my $widget = $event->widget();
+ if ($widget == $cancelButton) {
+ last;
+ }
+ if ($widget == $okButton) {
+ $choice = $rb1->value() ? 0 : 1 ;
+ last;
+ }
+ }
+ }
+
+ destroy $dlg;
+
+ #restore old application title
+ yui::YUI::app()->setApplicationTitle($appTitle);
+
+ return $choice;
+}
+
+#=============================================================
+
+=head2 _deleteGroupDialog
+
+=head3 INPUT
+
+ $self: this object
+
+=head3 DESCRIPTION
+
+ This method open a dialog to delete the selected group.
+
+=cut
+
+#=============================================================
+sub _deleteGroupDialog {
+ my $self = shift;
+
+ my $item = $self->get_widget('table')->selectedItem();
+ if (! $item) {
+ return;
+ }
+
+ my $groupname = $item->label();
+ ## push application title
+ my $appTitle = yui::YUI::app()->applicationTitle();
+ ## set new title to get it in dialog
+ yui::YUI::app()->setApplicationTitle($self->loc->N("Warning"));
+
+ my $factory = yui::YUI::widgetFactory;
+ my $dlg = $factory->createPopupDialog();
+ my $layout = $factory->createVBox($dlg);
+
+ my $align = $factory->createLeft($layout);
+
+ $factory->createLabel($align, $self->loc->N("Do you really want to delete the group %s?",
+ $groupname));
+
+ $align = $factory->createRight($layout);
+ my $hbox = $factory->createHBox($align);
+ my $cancelButton = $factory->createPushButton($hbox, $self->loc->N("Cancel"));
+ my $deleteButton = $factory->createPushButton($hbox, $self->loc->N("Delete"));
+
+ while(1) {
+ my $event = $dlg->waitForEvent();
+ my $eventType = $event->eventType();
+
+ #event type checking
+ if ($eventType == $yui::YEvent::CancelEvent) {
+ last;
+ }
+ elsif ($eventType == $yui::YEvent::WidgetEvent) {
+ # widget selected
+ my $widget = $event->widget();
+ if ($widget == $cancelButton) {
+ last;
+ }
+ elsif ($widget == $deleteButton) {
+ my $username = $self->sh_users->isPrimaryGroup($groupname);
+ if (defined($username)) {
+ $self->sh_gui->msgBox({
+ text => $self->loc->N("%s is a primary group for user %s\n Remove the user first",
+ $groupname, $username
+ )
+ });
+ }
+ else {
+ if ($self->sh_users->deleteGroup($groupname)) {
+ Sys::Syslog::syslog('info|local1', $self->loc->N("Removing group: %s", $groupname));
+ }
+ $self->_refresh();
+ }
+ last;
+ }
+ }
+ }
+
+ destroy $dlg;
+
+ #restore old application title
+ yui::YUI::app()->setApplicationTitle($appTitle);
+}
+
+#=============================================================
+
+=head2 _deleteUserDialog
+
+=head3 INPUT
+
+ $self: this object
+
+=head3 DESCRIPTION
+
+ This method open a dialog to delete the selected user.
+ It also asks for additional information to be removed.
+
+=cut
+
+#=============================================================
+sub _deleteUserDialog {
+ my $self = shift;
+
+ my $item = $self->get_widget('table')->selectedItem();
+ if (! $item) {
+ return;
+ }
+ my $username = $item->label();
+
+ my $homedir = $self->sh_users->getUserHome($username);
+ return if !defined($homedir);
+
+
+ ## push application title
+ my $appTitle = yui::YUI::app()->applicationTitle();
+ ## set new title to get it in dialog
+ yui::YUI::app()->setApplicationTitle($self->loc->N("Delete files or not?"));
+
+ my $factory = yui::YUI::widgetFactory;
+ my $dlg = $factory->createPopupDialog();
+ my $layout = $factory->createVBox($dlg);
+
+ my $align = $factory->createLeft($layout);
+ $factory->createLabel($align, $self->loc->N("Deleting user %s\nAlso perform the following actions\n",
+ $username));
+ $align = $factory->createLeft($layout);
+ my $checkhome = $factory->createCheckBox($align, $self->loc->N("Delete Home Directory: %s", $homedir), 0);
+ $align = $factory->createLeft($layout);
+ my $checkspool = $factory->createCheckBox($align, $self->loc->N("Delete Mailbox: /var/spool/mail/%s",
+ $username), 0);
+ $align = $factory->createRight($layout);
+ my $hbox = $factory->createHBox($align);
+ my $cancelButton = $factory->createPushButton($hbox, $self->loc->N("Cancel"));
+ my $deleteButton = $factory->createPushButton($hbox, $self->loc->N("Delete"));
+
+ if ($homedir !~ m!(?:/home|/var/spool)!) {
+ $checkhome->setDisabled();
+ $checkspool->setDisabled();
+ }
+
+
+ while(1) {
+ my $event = $dlg->waitForEvent();
+ my $eventType = $event->eventType();
+
+ #event type checking
+ if ($eventType == $yui::YEvent::CancelEvent) {
+ last;
+ }
+ elsif ($eventType == $yui::YEvent::WidgetEvent) {
+ # widget selected
+ my $widget = $event->widget();
+ if ($widget == $cancelButton) {
+ last;
+ }
+ elsif ($widget == $deleteButton) {
+ Sys::Syslog::syslog('info|local1', $self->loc->N("Removing user: %s", $username));
+ my $option = undef;
+ $option->{clean_home} = $checkhome->isChecked() if $checkhome->isChecked();
+ $option->{clean_spool} = $checkspool->isChecked() if $checkspool->isChecked();
+
+ my $err = $self->sh_users->deleteUser($username, $option);
+ $self->sh_gui->msgBox({text => $err}) if (defined($err));
+
+ #remove added icon
+ $self->sh_users->removeKdmIcon($username);
+ $self->_refresh();
+ last;
+ }
+ }
+ }
+
+ destroy $dlg;
+
+ #restore old application title
+ yui::YUI::app()->setApplicationTitle($appTitle);
+
+}
+
+
+sub _addGroupDialog {
+ my $self = shift;
+
+ my $is_system = 0;
+
+ ## push application title
+ my $appTitle = yui::YUI::app()->applicationTitle();
+ ## set new title to get it in dialog
+ yui::YUI::app()->setApplicationTitle($self->loc->N("Create New Group"));
+ my $factory = yui::YUI::widgetFactory;
+ my $optional = yui::YUI::optionalWidgetFactory;
+
+ my $dlg = $factory->createPopupDialog();
+ my $layout = $factory->createVBox($dlg);
+
+ ## 'group name'
+ my $align = $factory->createRight($layout);
+ my $hbox = $factory->createHBox($align);
+ my $label = $factory->createLabel($hbox, $self->loc->N("Group Name:") );
+ my $groupName = $factory->createInputField($hbox, "", 0);
+ $label->setWeight($yui::YD_HORIZ, 1);
+ $groupName->setWeight($yui::YD_HORIZ, 2);
+
+ $factory->createVSpacing($layout, 1);
+
+ # Specify group id manually
+ $align = $factory->createLeft($layout);
+ $hbox = $factory->createHBox($align);
+ my $gidManually = $factory->createCheckBox($hbox, $self->loc->N("Specify group ID manually"), 0);
+ $factory->createHSpacing($hbox, 2);
+ my $GID = $factory->createIntField($hbox, $self->loc->N("GID"), 1, 65000, $self->sh_users->min_GID);
+ $GID->setEnabled($gidManually->value());
+ $gidManually->setNotify(1);
+
+ $hbox = $factory->createHBox($layout);
+ $align = $factory->createRight($hbox);
+ my $cancelButton = $factory->createPushButton($align, $self->loc->N("Cancel"));
+ my $okButton = $factory->createPushButton($hbox, $self->loc->N("Ok"));
+ while(1) {
+ my $event = $dlg->waitForEvent();
+ my $eventType = $event->eventType();
+
+ #event type checking
+ if ($eventType == $yui::YEvent::CancelEvent) {
+ last;
+ }
+ elsif ($eventType == $yui::YEvent::WidgetEvent) {
+ # widget selected
+ my $widget = $event->widget();
+ if ($widget == $cancelButton) {
+ last;
+ }
+ elsif ($widget == $gidManually) {
+ # GID inserction enabled?
+ $GID->setEnabled($gidManually->value());
+ }
+ elsif ($widget == $okButton) {
+ ## check data
+ my $groupname = $groupName->value();
+ my ($continue, $errorString) = $self->sh_users->valid_groupname($groupname);
+ my $nm = $continue && $self->sh_users->groupNameExists($groupname);
+ if ($nm) {
+ $groupName->setValue("");
+ $errorString = $self->loc->N("Group already exists, please choose another Group Name");
+ $continue = 0;
+ }
+
+ my $gid = -1;
+ if ($continue && $gidManually->value()) {
+ if (($gid = $GID->value()) < $self->sh_users->min_GID) {
+ $errorString = "";
+ my $gidchoice = $self->sh_gui->ask_YesOrNo({ title => $self->loc->N(" Group Gid is < %n", $self->sh_users->min_GID),
+ text => $self->loc->N("Creating a group with a GID less than %d is not recommended.\n Are you sure you want to do this?\n\n",
+ $self->sh_users->min_GID
+ )
+ });
+ $continue = $gidchoice;
+ } else {
+ if ($self->sh_users->groupIDExists($gid)) {
+ $errorString = "";
+ my $gidchoice = $self->sh_gui->ask_YesOrNo({title => $self->loc->N(" Group ID is already used "),
+ text => $self->loc->N("Creating a group with a non unique GID?\n\n")});
+ $continue = $gidchoice;
+ }
+ }
+ }
+
+
+ if (!$continue) {
+ #--- raise error
+ $self->sh_gui->msgBox({text => $errorString}) if ($errorString);
+ }
+ else {
+ Sys::Syslog::syslog('info|local1', $self->loc->N("Adding group: %s ", $groupname));
+ my $groupParams = {
+ groupname => $groupname,
+ is_system => $is_system,
+ };
+ $groupParams->{gid} = $gid if $gid != -1;
+ $self->sh_users->addGroup($groupParams);
+ $self->_refresh();
+ last;
+ }
+ }
+ }
+ }
+ destroy $dlg;
+
+ #restore old application title
+ yui::YUI::app()->setApplicationTitle($appTitle);
+}
+
+
+#=============================================================
+
+=head2 _buildUserData
+
+=head3 INPUT
+
+ $self: this object
+ $layout : layout in wich drawing graphic user data
+
+=head3 OUTPUT
+
+ $userData: hash reference containing reference to graphical object
+ such as:
+ full_name, login_name, password, password1,
+ login_shell
+ full_name, login_name, password, password1,
+ weakness (icon), login_shell
+
+=head3 DESCRIPTION
+
+ This method is used by addUserDialog and _editUserDialog
+ to create User Data dialog
+=cut
+
+#=============================================================
+sub _buildUserData {
+ my ($self, $layout, $selected_shell) = @_;
+
+
+ my @shells = @{$self->sh_users->getUserShells()};
+
+ my $factory = yui::YUI::widgetFactory;
+
+ ## user 'full name'
+ my $align = $factory->createRight($layout);
+ my $hbox = $factory->createHBox($align);
+ my $label = $factory->createLabel($hbox, $self->loc->N("Full Name:") );
+ $factory->createHSpacing($hbox, 2.0);
+ my $fullName = $factory->createInputField($hbox, "", 0);
+ $label->setWeight($yui::YD_HORIZ, 1);
+ $fullName->setWeight($yui::YD_HORIZ, 2);
+
+ ## user 'login name'
+ $align = $factory->createRight($layout);
+ $hbox = $factory->createHBox($align);
+ $label = $factory->createLabel($hbox, $self->loc->N("Login:") );
+ $factory->createHSpacing($hbox, 2.0);
+ my $loginName = $factory->createInputField($hbox, "", 0);
+ $label->setWeight($yui::YD_HORIZ, 1);
+ $loginName->setWeight($yui::YD_HORIZ, 2);
+ $loginName->setNotify(1);
+
+ ## user 'Password'
+ $align = $factory->createRight($layout);
+ $hbox = $factory->createHBox($align);
+ $label = $factory->createLabel($hbox, $self->loc->N("Password:") );
+ my $weakness = undef;
+ if (yui::YUI::app()->hasImageSupport()) {
+ $factory->createHSpacing($hbox, 2.0);
+ my $file = File::ShareDir::dist_file(ManaTools::Shared::distName(), 'images/Blank16x16.png');
+ $weakness = $factory->createImage($hbox, $file);
+ }
+ else {
+ $factory->createHSpacing($hbox, 1.0);
+ $weakness = $factory->createLabel($hbox, " ");
+ $factory->createHSpacing($hbox, 1.0);
+ }
+ my $password = $factory->createInputField($hbox, "", 1);
+ $weakness->setWeight($yui::YD_HORIZ, 1);
+ $label->setWeight($yui::YD_HORIZ, 1);
+ $password->setWeight($yui::YD_HORIZ, 4);
+ # notify input to check weakness
+ $password->setNotify(1);
+
+ ## user 'confirm Password'
+ $align = $factory->createRight($layout);
+ $hbox = $factory->createHBox($align);
+ $label = $factory->createLabel($hbox, $self->loc->N("Confirm Password:") );
+ $factory->createHSpacing($hbox, 2.0);
+ my $password1 = $factory->createInputField($hbox, "", 1);
+ $label->setWeight($yui::YD_HORIZ, 1);
+ $password1->setWeight($yui::YD_HORIZ, 2);
+
+ ## user 'Login Shell'
+ $align = $factory->createRight($layout);
+ $hbox = $factory->createHBox($align);
+ $label = $factory->createLabel($hbox, $self->loc->N("Login Shell:") );
+ $factory->createHSpacing($hbox, 2.0);
+ my $loginShell = $factory->createComboBox($hbox, "", 0);
+ my $itemColl = new yui::YItemCollection;
+ foreach my $shell (@shells) {
+ my $item = new yui::YItem ($shell, 0);
+ $item->setSelected(1) if ($selected_shell && $selected_shell eq $shell);
+ $itemColl->push($item);
+ $item->DISOWN();
+ }
+ $loginShell->addItems($itemColl);
+ $label->setWeight($yui::YD_HORIZ, 1);
+ $loginShell->setWeight($yui::YD_HORIZ, 2);
+
+ my %userData = (
+ full_name => $fullName,
+ login_name => $loginName,
+ password => $password,
+ password1 => $password1,
+ weakness => $weakness,
+ login_shell => $loginShell,
+ );
+
+ return ( \%userData );
+}
+
+# get/set icon button name
+# if $icon_name is present it sets as "&Icon icon_name", so the shortcut is always the same
+# if $icon_name is not present it returns the previous set $label
+sub _iconButtonLabel {
+ my ($self, $icon_button, $icon_name) = @_;
+
+ state $label = "";
+
+ return if !$icon_button;
+ return if ref $icon_button ne "yui::YPushButton";
+
+ if ($icon_name) {
+ #set
+ $icon_button->setLabel($self->loc->N("&Icon (%s)", $icon_name));
+ $label = $icon_name;
+ }
+
+ return $label;
+}
+
+
+#=============================================================
+
+=head2 addUserDialog
+
+=head3 INPUT
+
+ $self: this object
+ $standalone: if set the application title is set
+ from the name set in costructor
+
+=head3 DESCRIPTION
+
+ This method creates and manages the dialog to add a new
+ user.
+
+=cut
+
+#=============================================================
+sub addUserDialog {
+ my $self = shift;
+ my $standalone = shift;
+
+ if ($EUID != 0) {
+ $self->sh_gui->warningMsgBox({
+ title => $self->name,
+ text => $self->loc->N("root privileges required"),
+ });
+ return;
+ }
+
+ my $dontcreatehomedir = 0;
+ my $is_system = 0;
+
+ ## push application title
+ my $appTitle = yui::YUI::app()->applicationTitle();
+ ## set new title to get it in dialog
+ if ($standalone) {
+ yui::YUI::app()->setApplicationTitle($self->name);
+ }
+ else {
+ yui::YUI::app()->setApplicationTitle($self->loc->N("Create New User"));
+ }
+
+ my $factory = yui::YUI::widgetFactory;
+ my $optional = yui::YUI::optionalWidgetFactory;
+
+ my $dlg = $factory->createPopupDialog();
+ my $layout = $factory->createVBox($dlg);
+
+ my $userData = $self->_buildUserData($layout);
+
+ ##### add a separator
+ ## Create Home directory
+ my $align = $factory->createLeft($layout);
+ my $hbox = $factory->createHBox($align);
+ my $createHome = $factory->createCheckBox($hbox, $self->loc->N("Create Home Directory"), 1);
+ ## Home directory
+ $align = $factory->createLeft($layout);
+ $hbox = $factory->createHBox($align);
+ my $label = $factory->createLabel($hbox, $self->loc->N("Home Directory:") );
+ $factory->createHSpacing($hbox, 2.0);
+ my $homeDir = $factory->createInputField($hbox, "", 0);
+ $label->setWeight($yui::YD_HORIZ, 1);
+ $homeDir->setWeight($yui::YD_HORIZ, 2);
+
+ # Create private group
+ $align = $factory->createLeft($layout);
+ $hbox = $factory->createHBox($align);
+ my $createGroup = $factory->createCheckBox($hbox, $self->loc->N("Create a private group for the user"), 1);
+
+ # Specify user id manually
+ $align = $factory->createRight($layout);
+ $hbox = $factory->createHBox($align);
+ my $uidManually = $factory->createCheckBox($hbox, $self->loc->N("Specify user ID manually"), 0);
+ $factory->createHSpacing($hbox, 2.0);
+ my $UID = $factory->createIntField($hbox, $self->loc->N("UID"), 1, 65000, $self->sh_users->min_UID);
+ $UID->setEnabled($uidManually->value());
+ $uidManually->setNotify(1);
+# $uidManually->setWeight($yui::YD_HORIZ, 2);
+ $UID->setWeight($yui::YD_HORIZ, 1);
+
+ ## user 'icon'
+ $hbox = $factory->createHBox($layout);
+ $factory->createLabel($hbox, $self->loc->N("Click on icon to change it") );
+ my $iconFace = $self->sh_users->GetFaceIcon();
+ my $icon = $factory->createPushButton($hbox, "");
+ $icon->setIcon($self->sh_users->face2png($iconFace));
+ $self->_iconButtonLabel($icon, $iconFace);
+
+ $hbox = $factory->createHBox($layout);
+ $align = $factory->createRight($hbox);
+ my $cancelButton = $factory->createPushButton($align, $self->loc->N("&Cancel"));
+ my $okButton = $factory->createPushButton($hbox, $self->loc->N("&Ok"));
+
+ while(1) {
+ my $event = $dlg->waitForEvent();
+ my $eventType = $event->eventType();
+
+ #event type checking
+ if ($eventType == $yui::YEvent::CancelEvent) {
+ last;
+ }
+ elsif ($eventType == $yui::YEvent::WidgetEvent) {
+ # widget selected
+ my $widget = $event->widget();
+ if ($widget == $cancelButton) {
+ last;
+ }
+ elsif ($widget == $icon) {
+ #remove shortcut from label
+ my $iconLabel = $self->_iconButtonLabel($icon);
+ my $nextIcon = $self->sh_users->GetFaceIcon($iconLabel, 1);
+ $self->_iconButtonLabel($icon, $nextIcon);
+ $icon->setIcon($self->sh_users->face2png($nextIcon));
+ }
+ elsif ($widget == $uidManually) {
+ # UID inserction enabled?
+ $UID->setEnabled($uidManually->value());
+ }
+ elsif ($widget == $userData->{ login_name }) {
+ my $username = $userData->{ login_name }->value();
+ $homeDir->setValue("/home/$username");
+ }
+ elsif ($widget == $userData->{password}) {
+ my $pass = $userData->{ password }->value();
+ $self->_checkWeaknessPassword($pass, $userData->{ weakness });
+ }
+ elsif ($widget == $okButton) {
+ ## check data
+ my $username = $userData->{ login_name }->value();
+ my ($continue, $errorString) = $self->sh_users->valid_username($username);
+ my $nm = $continue && $self->sh_users->userNameExists($username);
+ if ($nm) {
+ $userData->{ login_name }->setValue("");
+ $homeDir->setValue("");
+ $errorString = $self->loc->N("User already exists, please choose another User Name");
+ $continue = 0;
+ }
+ my $passwd = $continue && $userData->{ password }->value();
+ if ($continue && $passwd ne $userData->{ password1 }->value()) {
+ $errorString = $self->loc->N("Password Mismatch");
+ $continue = 0;
+ }
+ if ($self->sh_users->weakPasswordForSecurityLevel($passwd)) {
+ $errorString = $self->loc->N("This password is too simple. \n Good passwords should be > 6 characters");
+ $continue = 0;
+ }
+ my $homedir;
+ if ($continue && $createHome->value()) {
+ $homedir = $homeDir->value();
+ if ( -d $homedir) {
+ $errorString = $self->loc->N("Home directory <%s> already exists.\nPlease uncheck the home creation option, or change the directory path name", $homedir);
+ $continue = 0;
+ }
+ else {
+ $dontcreatehomedir = 0;
+ }
+ } else {
+ $dontcreatehomedir = 1;
+ }
+ my $uid = -1;
+ if ($continue && $uidManually->value()) {
+ if (($uid = $UID->value()) < $self->sh_users->min_UID) {
+ $errorString = "";
+ my $uidchoice = $self->sh_gui->ask_YesOrNo({title => $self->loc->N("User Uid is < %d", $self->sh_users->min_UID),
+ text => $self->loc->N("Creating a user with a UID less than %d is not recommended.\nAre you sure you want to do this?\n\n", $self->sh_users->min_UID)});
+ $continue = $uidchoice;
+ }
+ }
+ my $gid = undef;
+ if ($createGroup->value()) {
+ if ($continue) {
+ #Check if group exist
+ if ($self->sh_users->groupNameExists($username)) {
+ my $groupchoice = $self->ChooseGroup();
+ if ($groupchoice == 0 ) {
+ #You choose to put it in the existing group
+ $gid = $self->sh_users->groupID($username);
+ } elsif ($groupchoice == 1) {
+ # Put it in 'users' group
+ Sys::Syslog::syslog('info|local1', $self->loc->N("Putting %s to 'users' group",
+ $username));
+ $gid = $self->sh_users->Add2UsersGroup($username);
+ }
+ else {
+ $errorString = "";
+ $continue = 0;
+ }
+ } else {
+ #it's a new group: Add it
+ $gid = $self->sh_users->addGroup({
+ groupname => $username,
+ is_system => $is_system,
+ });
+ Sys::Syslog::syslog('info|local1', $self->loc->N("Creating new group: %s", $username));
+ }
+ }
+ } else {
+ $continue and $gid = $self->sh_users->Add2UsersGroup($username);
+ }
+
+ if (!$continue) {
+ #---rasie error
+ $self->sh_gui->msgBox({text => $errorString}) if ($errorString);
+ }
+ else {
+ ## OK let's create the user
+ print $self->loc->N("Adding user: ") . $username . " \n";
+ Sys::Syslog::syslog('info|local1', $self->loc->N("Adding user: %s", $username));
+ my $loginshell = $userData->{ login_shell }->value();
+ my $fullname = $userData->{ full_name }->value();
+ utf8::decode($fullname);
+
+ my $userParams = {
+ username => $username,
+ is_system => $is_system,
+ donotcreatehome => $dontcreatehomedir,
+ shell => $loginshell,
+ fullname => $fullname,
+ gid => $gid,
+ password => $passwd,
+ };
+ $userParams->{uid} = $uid if $uid != -1;
+ $userParams->{homedir} = $homedir if !$dontcreatehomedir;
+ $self->sh_users->addUser($userParams);
+
+ defined $icon->label() and
+ $self->sh_users->addKdmIcon($username, $icon->label());
+### TODO Migration wizard
+#
+# Refresh($sysfilter, $stringsearch);
+# transfugdrake::get_windows_disk()
+# and $in->ask_yesorno($self->loc->N("Migration wizard"),
+# $self->loc->N("Do you want to run the migration wizard in order to import Windows documents and settings in your Mageia distribution?"))
+# and run_program::raw({ detach => 1 }, 'transfugdrake');
+
+
+ last;
+ }
+ }
+ }
+ }
+
+ destroy $dlg;
+
+ #restore old application title
+ yui::YUI::app()->setApplicationTitle($appTitle) if $appTitle;
+}
+
+#=============================================================
+
+=head2 _createUserTable
+
+=head3 INPUT
+
+ $self: this object
+
+=head3 DESCRIPTION
+
+This function create the User table to be added to the replace
+point of the tab widget. Note this function is meant for internal
+use only
+
+=cut
+
+#=============================================================
+sub _createUserTable {
+ my $self = shift;
+
+ $self->dialog->startMultipleChanges();
+ $self->get_widget('replace_pnt')->deleteChildren();
+ my $parent = $self->get_widget('replace_pnt');
+ my $factory = yui::YUI::widgetFactory;
+ my $yTableHeader = new yui::YTableHeader();
+ $yTableHeader->addColumn($self->loc->N("User Name"), $yui::YAlignBegin);
+ $yTableHeader->addColumn($self->loc->N("User ID"), $yui::YAlignBegin);
+ $yTableHeader->addColumn($self->loc->N("Primary Group"), $yui::YAlignBegin);
+ $yTableHeader->addColumn($self->loc->N("Full Name"), $yui::YAlignBegin);
+ $yTableHeader->addColumn($self->loc->N("Login Shell"), $yui::YAlignBegin);
+ $yTableHeader->addColumn($self->loc->N("Home Directory"), $yui::YAlignBegin);
+ $yTableHeader->addColumn($self->loc->N("Status"), $yui::YAlignBegin);
+ $yTableHeader->DISOWN();
+
+ $self->set_widget(table => $factory->createTable($parent, $yTableHeader));
+
+ $self->get_widget('table')->setImmediateMode(1);
+ $self->get_widget('table')->DISOWN();
+ $self->get_widget('replace_pnt')->showChild();
+ $self->dialog->recalcLayout();
+ $self->dialog->doneMultipleChanges();
+ $self->_refreshUsers();
+}
+
+#=============================================================
+
+=head2 _createGroupTable
+
+=head3 INPUT
+
+ $self: this object
+
+=head3 DESCRIPTION
+
+This function create the Group table to be added to the replace
+point of the tab widget. Note this function is meant for internal
+use only
+
+
+=cut
+
+#=============================================================
+sub _createGroupTable {
+ my $self = shift;
+
+
+ $self->dialog->startMultipleChanges();
+ $self->get_widget('replace_pnt')->deleteChildren();
+ my $parent = $self->get_widget('replace_pnt');
+ my $factory = yui::YUI::widgetFactory;
+ my $yTableHeader = new yui::YTableHeader();
+ $yTableHeader->addColumn($self->loc->N("Group Name"), $yui::YAlignBegin);
+ $yTableHeader->addColumn($self->loc->N("Group ID"), $yui::YAlignBegin);
+ $yTableHeader->addColumn($self->loc->N("Group Members"), $yui::YAlignBegin);
+ $yTableHeader->DISOWN();
+
+ $self->set_widget(table => $factory->createTable($parent, $yTableHeader));
+
+ $self->get_widget('table')->setImmediateMode(1);
+ $self->get_widget('table')->DISOWN();
+ $self->get_widget('replace_pnt')->showChild();
+ $self->dialog->recalcLayout();
+ $self->dialog->doneMultipleChanges();
+ $self->_refreshGroups();
+}
+
+
+
+
+#=============================================================
+
+=head2 _refreshUsers
+
+=head3 INPUT
+
+ $self: this object
+
+=head3 DESCRIPTION
+
+ This method refresh user info into User tab widget.
+ Note this function is meant for internal use only
+
+=cut
+
+#=============================================================
+sub _refreshUsers {
+ my $self = shift;
+
+ my $strfilt = $self->get_widget('filter')->value();
+ my $filterusers = $self->get_widget('filter_system')->isChecked();
+
+ my $usersInfo = $self->sh_users->getUsersInfo({
+ username_filter => $strfilt,
+ filter_system => $filterusers,
+ });
+
+
+ $self->dialog->startMultipleChanges();
+ #for some reasons QT send an event using table->selectItem()
+ # WA remove notification immediate
+ $self->get_widget('table')->setImmediateMode(0);
+ $self->get_widget('table')->deleteAllItems();
+
+ my $itemColl = new yui::YItemCollection;
+ foreach my $username (keys %{$usersInfo}) {
+ my $info = $usersInfo->{$username};
+ my $item = new yui::YTableItem (
+ "$username",
+ "$info->{uid}",
+ "$info->{group}",
+ "$info->{fullname}",
+ "$info->{shell}",
+ "$info->{home}",
+ "$info->{status}"
+ );
+
+ # TODO workaround to get first cell at least until we don't
+ # a cast from YItem
+ $item->setLabel( $username );
+ $itemColl->push($item);
+ $item->DISOWN();
+ }
+
+ $self->get_widget('table')->addItems($itemColl);
+ my $item = $self->get_widget('table')->selectedItem();
+ $self->get_widget('table')->selectItem($item, 0) if $item;
+ $self->dialog->recalcLayout();
+ $self->dialog->doneMultipleChanges();
+ $self->_refreshActions();
+ $self->get_widget('table')->setImmediateMode(1);
+}
+
+#=============================================================
+
+=head2 _refreshGroups
+
+=head3 INPUT
+
+ $self: this object
+
+=head3 DESCRIPTION
+
+ This method refresh group info into Group tab widget.
+ Note this function is meant for internal use only
+
+=cut
+
+#=============================================================
+sub _refreshGroups {
+ my $self = shift;
+
+ my $strfilt = $self->get_widget('filter')->value();
+ my $filtergroups = $self->get_widget('filter_system')->isChecked();
+
+ $self->dialog->startMultipleChanges();
+ #for some reasons QT send an event using table->selectItem()
+ # WA remove notification immediate
+ $self->get_widget('table')->setImmediateMode(0);
+ $self->get_widget('table')->deleteAllItems();
+
+ my $groupInfo = $self->sh_users->getGroupsInfo({
+ groupname_filter => $strfilt,
+ filter_system => $filtergroups,
+ });
+
+ my $itemColl = new yui::YItemCollection;
+ foreach my $groupname (keys %{$groupInfo}) {
+ my $info = $groupInfo->{$groupname};
+ my $listUbyG = join(',', @{$info->{members}});
+ my $item = new yui::YTableItem ("$groupname",
+ "$info->{gid}",
+ "$listUbyG");
+ $item->setLabel( $groupname );
+ $itemColl->push($item);
+ $item->DISOWN();
+ }
+
+ $self->get_widget('table')->addItems($itemColl);
+ my $item = $self->get_widget('table')->selectedItem();
+ $self->get_widget('table')->selectItem($item, 0) if $item;
+ $self->dialog->recalcLayout();
+ $self->dialog->doneMultipleChanges();
+ $self->_refreshActions();
+ $self->get_widget('table')->setImmediateMode(1);
+}
+
+
+#=============================================================
+
+=head2 _getUserInfo
+
+=head3 INPUT
+
+ $self: this object
+
+=head3 OUTPUT
+
+ $userData: HASH reference containing:
+ username: username
+ full_name: full name of user
+ shell: shell used
+ homedir: home dir path
+ UID: User identifier
+ acc_check_exp: account expiration enabling
+ acc_expy: account expiration year
+ acc_expm: account expiration month
+ acc_expd: account expiration day
+ lockuser: account locked
+ pwd_check_exp: password expiration enabling
+ pwd_exp_min: days before changing password
+ is allowed
+ pwd_exp_max: days before changing password
+ is required
+ pwd_exp_warn: warning days before changing
+ pwd_exp_inact: days before account becomes
+ inact
+ members: Array containing groups the user
+ belongs to.
+ primary_group: primary group ID for the user
+
+=head3 DESCRIPTION
+
+ Retrieves the selected user info from the system
+ Note that acc_expy, acc_expm and acc_expd are valid if
+ acc_check_exp is enabled.
+ Note that pwd_exp_min, pwd_exp_max, pwd_exp_warn,
+ pwd_exp_inact are valid if pwd_check_exp is enabled.
+
+=cut
+
+#=============================================================
+
+sub _getUserInfo {
+ my $self = shift;
+
+ my $label = $self->_skipShortcut($self->get_widget('tabs')->selectedItem()->label());
+ if ($label ne $self->loc->N("Users") ) {
+ return undef;
+ }
+
+ my $item = $self->get_widget('table')->selectedItem();
+ if (! $item) {
+ return undef;
+ }
+
+ my %userData;
+ $userData{old_username} = $item->label();
+ $userData{username} = $item->label();
+
+ my $userInfo = $self->sh_users->getUserInfo($userData{username});
+
+ $userData{full_name} = $userInfo->{fullname};
+ $userData{shell} = $userInfo->{shell};
+ $userData{homedir} = $userInfo->{home};
+ $userData{UID} = $userInfo->{uid};
+
+ # default expiration time
+ my ($day, $mo, $ye) = (localtime())[3, 4, 5];
+ $userData{acc_expy} = $ye+1900;
+ $userData{acc_expm} = $mo+1;
+ $userData{acc_expd} = $day;
+ $userData{acc_check_exp} = 0;
+
+ my $expire = $userInfo->{expire};
+ if ($expire && $expire != -1) {
+ my $times = _TimeOfArray($expire, 1);
+ $userData{acc_expy} = $times->{year};
+ $userData{acc_expm} = $times->{month};
+ $userData{acc_expd} = $times->{dayint};
+ $userData{acc_check_exp} = 1;
+ }
+
+ # user password are not retrieved if admin wants
+ # to change it has to insert a new one
+ $userData{password} = undef;
+ $userData{password1} = undef;
+
+ $userData{lockuser} = $userInfo->{locked};
+ $userData{icon_face} = $self->sh_users->GetFaceIcon($userData{username});
+
+ $userData{pwd_check_exp} = 0;
+ $userData{pwd_exp_min} = $userInfo->{exp_min};
+ $userData{pwd_exp_max} = $userInfo->{exp_max};
+ $userData{pwd_exp_warn} = $userInfo->{exp_warn};
+ $userData{pwd_exp_inact} = $userInfo->{exp_inact};
+ if ($userData{pwd_exp_min} && $userData{pwd_exp_min} != -1 ||
+ $userData{pwd_exp_max} && $userData{pwd_exp_max} != 99999 ||
+ $userData{pwd_exp_warn} && $userData{pwd_exp_warn} != 7 && $userData{pwd_exp_warn} != -1 ||
+ $userData{pwd_exp_inact} && $userData{pwd_exp_inact} != -1) {
+ $userData{pwd_check_exp} = 1;
+ }
+
+ $userData{members} = $userInfo->{members};
+ $userData{primary_group} = $userInfo->{gid};
+
+ return \%userData;
+}
+
+#=============================================================
+
+=head2 _getUserInfo
+
+=head3 INPUT
+
+ $self: this object
+
+=head3 OUTPUT
+
+ %groupData: selected group info as:
+ $groupname: group name
+ $members: users that are members of this group
+
+=head3 DESCRIPTION
+
+ Retrieves the selected group info from the system
+
+=cut
+
+#=============================================================
+
+sub _getGroupInfo {
+ my $self = shift;
+
+ my $label = $self->_skipShortcut($self->get_widget('tabs')->selectedItem()->label());
+ if ($label ne $self->loc->N("Groups") ) {
+ return undef;
+ }
+
+ my $item = $self->get_widget('table')->selectedItem();
+ if (! $item) {
+ return undef;
+ }
+
+ my %groupData;
+ $groupData{start_groupname} = $item->label();
+ $groupData{groupname} = $item->label();
+
+ $groupData{members} = $self->sh_users->groupMembers($groupData{groupname});
+
+ return %groupData;
+
+}
+
+sub _storeDataFromGroupEditPreviousTab {
+ my ($self, %groupData) = @_;
+
+ my $previus_tab = $self->get_edit_tab_widget('edit_tab_label');
+ if (!$previus_tab) {
+ return %groupData;
+ }
+ elsif ($previus_tab eq $groupEditLabel{group_data}) {
+ $groupData{groupname} = $self->get_edit_tab_widget('groupname')->value();
+ }
+ elsif ($previus_tab eq $groupEditLabel{group_users}) {
+ my $tbl = $self->get_edit_tab_widget('members');
+ $groupData{members} = undef;
+ my @members;
+ my $i;
+ for($i=0;$i<$tbl->itemsCount();$i++) {
+ push (@members, $tbl->item($i)->label()) if $tbl->toCBYTableItem($tbl->item($i))->checked();
+ }
+ $groupData{members} = [ @members ];
+ }
+
+ return %groupData;
+}
+
+
+sub _storeDataFromUserEditPreviousTab {
+ my ($self, $userData) = @_;
+
+ my $previus_tab = $self->get_edit_tab_widget('edit_tab_label');
+ if (!$previus_tab) {
+ return $userData;
+ }
+ elsif ($previus_tab eq $userEditLabel{user_data}) {
+ $userData->{full_name} = $self->get_edit_tab_widget('full_name')->value();
+ $userData->{username} = $self->get_edit_tab_widget('login_name')->value() ;
+ $userData->{shell} = $self->get_edit_tab_widget('login_shell')->value();
+ $userData->{homedir} = $self->get_edit_tab_widget('homedir')->value();
+ my $passwd = $self->get_edit_tab_widget('password')->value();
+ $userData->{password} = $passwd;
+ $passwd = $self->get_edit_tab_widget('password1')->value();
+ $userData->{password1} = $passwd;
+ }
+ elsif ($previus_tab eq $userEditLabel{account_info}) {
+ $userData->{acc_check_exp} = $self->get_edit_tab_widget('acc_check_exp')->value();
+ $userData->{acc_expy} = $self->get_edit_tab_widget('acc_expy')->value();
+ $userData->{acc_expm} = $self->get_edit_tab_widget('acc_expm')->value();
+ $userData->{acc_expd} = $self->get_edit_tab_widget('acc_expd')->value();
+ $userData->{lockuser} = $self->get_edit_tab_widget('lockuser')->value();
+ $userData->{icon_face} = $self->_iconButtonLabel($self->get_edit_tab_widget('icon_face'));
+ }
+ elsif ($previus_tab eq $userEditLabel{password_info}) {
+ $userData->{pwd_check_exp} = $self->get_edit_tab_widget('pwd_check_exp')->value();
+ $userData->{pwd_exp_min} = $self->get_edit_tab_widget('pwd_exp_min')->value();
+ $userData->{pwd_exp_max} = $self->get_edit_tab_widget('pwd_exp_max')->value();
+ $userData->{pwd_exp_warn} = $self->get_edit_tab_widget('pwd_exp_warn')->value();
+ $userData->{pwd_exp_inact} = $self->get_edit_tab_widget('pwd_exp_inact')->value();
+ }
+ elsif ($previus_tab eq $userEditLabel{groups}) {
+ my $tbl = $self->get_edit_tab_widget('members');
+ $userData->{members} = undef;
+ my @members;
+ my $i;
+ for($i=0;$i<$tbl->itemsCount();$i++) {
+ push (@members, $tbl->item($i)->label()) if $tbl->toCBYTableItem($tbl->item($i))->checked();
+ }
+ $userData->{members} = \@members;
+
+ if ($self->get_edit_tab_widget('primary_group')->selectedItem()) {
+ my $groupname = $self->get_edit_tab_widget('primary_group')->selectedItem()->label();
+ my $primgroup = $self->sh_users->groupID($groupname);
+ $userData->{primary_group} = $primgroup;
+ }
+ else {
+ $userData->{primary_group} = -1;
+ }
+ }
+
+ return $userData;
+}
+
+#=============================================================
+
+=head2 _userDataTabWidget
+
+=head3 INPUT
+
+ $self: this object
+ $dialog: YUI dialog that owns the YUI replace point
+ $replace_pnt: YUI replace point, needed to add a new tab
+ widget
+ $userData: hash reference containing user data info, tabs are
+ removed and added again on selection, so
+ data must be saved outside of widgets.
+
+=head3 OUTPUT
+
+ $userDataWidget: hash containing new YUI widget objects
+ such as:
+ returned onject from _buildUserData and
+ homedir.
+
+=head3 DESCRIPTION
+
+ This internal method removes old tab widget saving its
+ relevant data into userData and creates new selected table
+ to be shown.
+
+=cut
+
+#=============================================================
+sub _userDataTabWidget {
+ my ($self, $dialog, $replace_pnt, $userData) = @_;
+
+ my $factory = yui::YUI::widgetFactory;
+
+ $dialog->startMultipleChanges();
+
+ $replace_pnt->deleteChildren();
+ my $layout = $factory->createVBox($replace_pnt);
+ my $userDataWidget = $self->_buildUserData($layout, $userData->{shell});
+
+ ## user 'login name'
+ my $align = $factory->createRight($layout);
+ my $hbox = $factory->createHBox($align);
+ my $label = $factory->createLabel($hbox, $self->loc->N("Home:") );
+ $factory->createHSpacing($hbox, 2.0);
+ $userDataWidget->{homedir} = $factory->createInputField($hbox, "", 0);
+ $label->setWeight($yui::YD_HORIZ, 1);
+ $userDataWidget->{homedir}->setWeight($yui::YD_HORIZ, 2);
+
+ # fill data into widgets
+ ##
+ # full_name, login_name, password, password1,
+ # login_shell
+ $userDataWidget->{full_name}->setValue($userData->{full_name});
+ $userDataWidget->{login_name}->setValue($userData->{username});
+ yui::YUI::ui()->blockEvents();
+ $userDataWidget->{password}->setValue($userData->{password}) if $userData->{password};
+ yui::YUI::ui()->unblockEvents();
+ $userDataWidget->{password1}->setValue($userData->{password1}) if $userData->{password1};
+ $userDataWidget->{homedir}->setValue($userData->{homedir});
+
+ $replace_pnt->showChild();
+ $dialog->recalcLayout();
+ $dialog->doneMultipleChanges();
+
+ return $userDataWidget;
+}
+
+
+#=============================================================
+
+=head2 _groupDataTabWidget
+
+=head3 INPUT
+
+ $self: this object
+ $dialog: YUI dialog that owns the YUI replace point
+ $replace_pnt: YUI replace point, needed to add a new tab
+ widget
+ %groupData: hash containing group data info, tabs are
+ removed and added again on selection, so
+ data must be saved outside of widgets.
+ $previus_tab: previous tab widget label, needed to store
+ group data from the old tab before removing
+ it, if user changed something.
+
+=head3 OUTPUT
+
+ %groupDataWidget: hash containing new YUI widget objects
+ such as:
+ groupname.
+
+=head3 DESCRIPTION
+
+ This internal method removes old tab widget saving its
+ relevant data into groupData and creates new selected table
+ to be shown.
+
+=cut
+
+#=============================================================
+sub _groupDataTabWidget {
+ my ($self, $dialog, $replace_pnt, %groupData) = @_;
+
+ my $factory = yui::YUI::widgetFactory;
+
+ $dialog->startMultipleChanges();
+
+ $replace_pnt->deleteChildren();
+ my $layout = $factory->createVBox($replace_pnt);
+
+ my %groupDataWidget;
+
+ ## user 'login name'
+ my $align = $factory->createRight($layout);
+ my $hbox = $factory->createHBox($align);
+ my $label = $factory->createLabel($hbox, $self->loc->N("Group Name:") );
+ $groupDataWidget{groupname} = $factory->createInputField($hbox, "", 0);
+ $label->setWeight($yui::YD_HORIZ, 1);
+ $groupDataWidget{groupname}->setWeight($yui::YD_HORIZ, 2);
+
+ $groupDataWidget{groupname}->setValue($groupData{groupname});
+
+ $replace_pnt->showChild();
+ $dialog->recalcLayout();
+ $dialog->doneMultipleChanges();
+
+ return %groupDataWidget;
+}
+
+
+sub _userAccountInfoTabWidget {
+ my ($self, $dialog, $replace_pnt, $userData) = @_;
+
+ my $factory = yui::YUI::widgetFactory;
+
+ $dialog->startMultipleChanges();
+
+ $replace_pnt->deleteChildren();
+ my $layout = $factory->createVBox($replace_pnt);
+
+ my %userAccountWidget;
+ $userAccountWidget{acc_check_exp} = $factory->createCheckBoxFrame($layout, $self->loc->N("Enable account expiration"), 1);
+ my $align = $factory->createRight($userAccountWidget{acc_check_exp});
+ my $hbox = $factory->createHBox($align);
+ my $label = $factory->createLabel($hbox, $self->loc->N("Account expires (YYYY-MM-DD):"));
+ $userAccountWidget{acc_expy} = $factory->createIntField($hbox, "", 1970, 9999, $userData->{acc_expy});
+ $userAccountWidget{acc_expm} = $factory->createIntField($hbox, "", 1, 12, $userData->{acc_expm});
+ $userAccountWidget{acc_expd} = $factory->createIntField($hbox, "", 1, 31, $userData->{acc_expd});
+ $userAccountWidget{acc_check_exp}->setValue($userData->{acc_check_exp});
+ $label->setWeight($yui::YD_HORIZ, 2);
+ $align = $factory->createLeft($layout);
+ $userAccountWidget{lockuser} = $factory->createCheckBox($align, $self->loc->N("Lock User Account"), $userData->{lockuser});
+
+ $align = $factory->createLeft($layout);
+ $hbox = $factory->createHBox($align);
+ $label = $factory->createLabel($hbox, $self->loc->N("Click on the icon to change it"));
+ $userAccountWidget{icon_face} = $factory->createPushButton($hbox, "");
+ $userAccountWidget{icon_face}->setIcon($self->sh_users->face2png($userData->{icon_face}));
+ $self->_iconButtonLabel($userAccountWidget{icon_face}, $userData->{icon_face});
+
+ $replace_pnt->showChild();
+ $dialog->recalcLayout();
+ $dialog->doneMultipleChanges();
+
+ return \%userAccountWidget;
+}
+
+
+sub _userPasswordInfoTabWidget {
+ my ($self, $dialog, $replace_pnt, $userData) = @_;
+
+ my $factory = yui::YUI::widgetFactory;
+
+ $dialog->startMultipleChanges();
+
+ $replace_pnt->deleteChildren();
+ my $layout = $factory->createVBox($replace_pnt);
+
+ my %userPasswordWidget;
+
+ my $userInfo = $self->sh_users->getUserInfo($userData->{username});
+ my $lastchg = $userInfo->{last_change};
+
+ my $align = $factory->createLeft($layout);
+ my $hbox = $factory->createHBox($align);
+ my $label = $factory->createLabel($hbox, $self->loc->N("User last changed password on: "));
+ my $dayStr = $factory->createLabel($hbox, "");
+ my $month = $factory->createLabel($hbox, "");
+ my $dayInt = $factory->createLabel($hbox, "");
+ my $year = $factory->createLabel($hbox, "");
+ if ($lastchg) {
+ my $times = _TimeOfArray($lastchg, 0);
+ $dayStr->setValue($times->{daystr});
+ $month->setValue($times->{month});
+ $dayInt->setValue($times->{dayint});
+ $year->setValue($times->{year});
+ }
+
+ $userPasswordWidget{pwd_check_exp} = $factory->createCheckBoxFrame($layout, $self->loc->N("Enable Password Expiration"), 1);
+ $layout = $factory->createVBox($userPasswordWidget{pwd_check_exp});
+ $align = $factory->createLeft($layout);
+ $hbox = $factory->createHBox($align);
+ $label = $factory->createLabel($hbox, $self->loc->N("Days before change allowed:"));
+ $userPasswordWidget{pwd_exp_min} = $factory->createInputField($hbox, "", 0);
+ $userPasswordWidget{pwd_exp_min}->setValue("$userData->{pwd_exp_min}");
+ $label->setWeight($yui::YD_HORIZ, 1);
+ $userPasswordWidget{pwd_exp_min}->setWeight($yui::YD_HORIZ, 2);
+
+ $align = $factory->createLeft($layout);
+ $hbox = $factory->createHBox($align);
+ $label = $factory->createLabel($hbox, $self->loc->N("Days before change required:"));
+ $userPasswordWidget{pwd_exp_max} = $factory->createInputField($hbox, "", 0);
+ $userPasswordWidget{pwd_exp_max}->setValue("$userData->{pwd_exp_max}");
+ $label->setWeight($yui::YD_HORIZ, 1);
+ $userPasswordWidget{pwd_exp_max}->setWeight($yui::YD_HORIZ, 2);
+
+ $align = $factory->createLeft($layout);
+ $hbox = $factory->createHBox($align);
+ $label = $factory->createLabel($hbox, $self->loc->N("Days warning before change:"));
+ $userPasswordWidget{pwd_exp_warn} = $factory->createInputField($hbox, "", 0);
+ $userPasswordWidget{pwd_exp_warn}->setValue("$userData->{pwd_exp_warn}");
+ $label->setWeight($yui::YD_HORIZ, 1);
+ $userPasswordWidget{pwd_exp_warn}->setWeight($yui::YD_HORIZ, 2);
+
+ $align = $factory->createLeft($layout);
+ $hbox = $factory->createHBox($align);
+ $label = $factory->createLabel($hbox, $self->loc->N("Days before account inactive:"));
+ $userPasswordWidget{pwd_exp_inact} = $factory->createInputField($hbox, "", 0);
+ $userPasswordWidget{pwd_exp_inact}->setValue("$userData->{pwd_exp_inact}");
+ $label->setWeight($yui::YD_HORIZ, 1);
+ $userPasswordWidget{pwd_exp_inact}->setWeight($yui::YD_HORIZ, 2);
+
+ $userPasswordWidget{pwd_check_exp}->setValue($userData->{pwd_check_exp});
+
+ $replace_pnt->showChild();
+ $dialog->recalcLayout();
+ $dialog->doneMultipleChanges();
+
+ return \%userPasswordWidget;
+}
+
+sub _groupUsersTabWidget {
+ my ($self, $dialog, $replace_pnt, %groupData) = @_;
+
+ my $factory = yui::YUI::widgetFactory;
+ my $mageiaPlugin = "mga";
+ my $mgaFactory = yui::YExternalWidgets::externalWidgetFactory($mageiaPlugin);
+ $mgaFactory = yui::YMGAWidgetFactory::getYMGAWidgetFactory($mgaFactory);
+
+ $dialog->startMultipleChanges();
+
+ $replace_pnt->deleteChildren();
+
+ my %groupUsersWidget;
+
+ my $layout = _labeledFrameBox($replace_pnt, $self->loc->N("Select the users to join this group:"));
+
+ my $yTableHeader = new yui::YTableHeader();
+ $yTableHeader->addColumn("", $yui::YAlignBegin);
+ $yTableHeader->addColumn($self->loc->N("User"), $yui::YAlignBegin);
+
+ $groupUsersWidget{members} = $mgaFactory->createCBTable($layout, $yTableHeader, $yui::YCBTableCheckBoxOnFirstColumn);
+
+ my $users = $self->sh_users->getUsers();
+ my @susers = sort(@$users);
+
+ my $itemCollection = new yui::YItemCollection;
+ my $members = $groupData{members};
+ foreach my $user (@susers) {
+ my $item = new yui::YCBTableItem($user);
+ $item->check(MDK::Common::DataStructure::member($user, @$members));
+ $item->setLabel($user);
+ $itemCollection->push($item);
+ $item->DISOWN();
+ }
+ $groupUsersWidget{members}->addItems($itemCollection);
+
+ $replace_pnt->showChild();
+ $dialog->recalcLayout();
+ $dialog->doneMultipleChanges();
+
+ return %groupUsersWidget;
+}
+
+sub _userGroupsTabWidget {
+ my ($self, $dialog, $replace_pnt, $userData) = @_;
+
+ my $factory = yui::YUI::widgetFactory;
+ my $mageiaPlugin = "mga";
+ my $mgaFactory = yui::YExternalWidgets::externalWidgetFactory($mageiaPlugin);
+ $mgaFactory = yui::YMGAWidgetFactory::getYMGAWidgetFactory($mgaFactory);
+
+ $dialog->startMultipleChanges();
+
+ $replace_pnt->deleteChildren();
+
+ my %userGroupsWidget;
+ my $userInfo = $self->sh_users->getUserInfo($userData->{username});
+ my $lastchg = $userInfo->{last_change};
+
+ my $layout = _labeledFrameBox($replace_pnt, $self->loc->N("Select groups that the user will be member of:"));
+
+ my $yTableHeader = new yui::YTableHeader();
+ $yTableHeader->addColumn("", $yui::YAlignBegin);
+ $yTableHeader->addColumn($self->loc->N("Group"), $yui::YAlignBegin);
+
+ $userGroupsWidget{members} = $mgaFactory->createCBTable($layout, $yTableHeader, $yui::YCBTableCheckBoxOnFirstColumn);
+
+ my $grps = $self->sh_users->getGoups();
+ my @sgroups = sort @$grps;
+
+ my $itemCollection = new yui::YItemCollection;
+ my $members = $userData->{members};
+ foreach my $group (@sgroups) {
+ my $item = new yui::YCBTableItem($group);
+ $item->check(MDK::Common::DataStructure::member($group, @$members));
+ $item->setLabel($group);
+ $itemCollection->push($item);
+ $item->DISOWN();
+ }
+ $userGroupsWidget{members}->addItems($itemCollection);
+ $userGroupsWidget{members}->setNotify(1);
+ my $primgroup = '';
+ if ($userData->{primary_group} != -1) {
+ $primgroup = $self->sh_users->groupName($userData->{primary_group});
+ }
+
+ my $align = $factory->createLeft($layout);
+ my $hbox = $factory->createHBox($align);
+ my $label = $factory->createLabel($hbox, $self->loc->N("Primary Group"));
+ $userGroupsWidget{primary_group} = $factory->createComboBox($hbox, "", 0);
+ my $itemColl = new yui::YItemCollection;
+ foreach my $member (@$members) {
+ my $item = new yui::YItem ($member, 0);
+ $item->setSelected(1) if ($item->label() eq $primgroup);
+ $itemColl->push($item);
+ $item->DISOWN();
+ }
+ $userGroupsWidget{primary_group}->addItems($itemColl);
+ $label->setWeight($yui::YD_HORIZ, 1);
+ $userGroupsWidget{primary_group}->setWeight($yui::YD_HORIZ, 2);
+
+ $replace_pnt->showChild();
+ $dialog->recalcLayout();
+ $dialog->doneMultipleChanges();
+
+ return \%userGroupsWidget;
+}
+
+sub _groupEdit_Ok {
+ my ($self, %groupData) = @_;
+
+ # update last changes if any
+ %groupData = $self->_storeDataFromGroupEditPreviousTab(%groupData);
+
+ my ($continue, $errorString) = $self->sh_users->valid_groupname($groupData{groupname});
+ if (!$continue) {
+ $self->sh_gui->msgBox({text => $errorString}) if ($errorString);
+ return $continue;
+ }
+
+ my $groupInfo = {
+ groupname => $groupData{groupname},
+ members => $groupData{members},
+ };
+
+ if ($groupData{start_groupname} ne $groupData{groupname}) {
+ $groupInfo->{old_groupname} = $groupData{start_groupname};
+ }
+
+ my $retval = $self->sh_users->modifyGroup($groupInfo);
+
+ if (!$retval->{status}) {
+ $self->sh_gui->msgBox({text => $retval->{error}} );
+ }
+
+ $self->_refresh();
+
+ return 1;
+}
+
+sub _userEdit_Ok {
+ my ($self, $userData) = @_;
+
+ # update last changes if any
+ $self->_storeDataFromUserEditPreviousTab($userData);
+
+ my ($continue, $errorString) = $self->sh_users->valid_username($userData->{username});
+ if (!$continue) {
+ $self->sh_gui->msgBox({text => $errorString}) if ($errorString);
+ return $continue;
+ }
+
+ if ( $userData->{password} ne $userData->{password1}) {
+ $self->sh_gui->msgBox({text => $self->loc->N("Password Mismatch")});
+ return 0;
+ }
+
+ if ($userData->{password} ne '') {
+ if ($self->sh_users->weakPasswordForSecurityLevel($userData->{password})) {
+ $self->sh_gui->msgBox({text => $self->loc->N("This password is too simple. \n Good passwords should be > 6 characters")});
+ return 0;
+ }
+ }
+
+ if ($userData->{primary_group} == -1) {
+ $self->sh_gui->msgBox({ text => $self->loc->N("Please select at least one group for the user")});
+ return 0;
+ }
+
+ my $userInfo = {
+ username => $userData->{username},
+ fullname => $userData->{full_name},
+ homedir => $userData->{homedir},
+ shell => $userData->{shell},
+ members => $userData->{members},
+ gid => $userData->{primary_group},
+ lockuser => $userData->{lockuser},
+ };
+
+ $userInfo->{old_username} = $userData->{old_username} if $userData->{username} ne $userData->{old_username};
+ $userInfo->{password} = $userData->{password} if $userData->{password} ne '';
+
+
+ if ($userData->{acc_check_exp}) {
+ my $yr = $userData->{acc_expy};
+ my $mo = $userData->{acc_expm};
+ my $dy = $userData->{acc_expd};
+ if (!_ValidInt($yr, $dy, $mo)) {
+ $self->sh_gui->msgBox({text => $self->loc->N("Please specify Year, Month and Day \n for Account Expiration ")});
+ return 0;
+ }
+ $userInfo->{acc_expires} = {
+ exp_y => $yr,
+ exp_m => $mo,
+ exp_d => $dy,
+ };
+ }
+
+ if ($userData->{pwd_check_exp}) {
+ my $allowed = int($userData->{pwd_exp_min});
+ my $required = int($userData->{pwd_exp_max});
+ my $warning = int($userData->{pwd_exp_warn});
+ my $inactive = int($userData->{pwd_exp_inact});
+ if (!$allowed || !$required || !$warning || !$inactive) {
+ $self->sh_gui->msgBox({text => $self->loc->N("Please fill up all fields in password aging\n")});
+ return 0;
+ }
+ $userInfo->{password_expires} = {
+ exp_min => $allowed,
+ exp_max => $required,
+ exp_warn => $warning,
+ exp_inact => $inactive,
+ };
+ }
+
+ $self->sh_users->modifyUser($userInfo);
+
+
+ defined $userData->{icon_face} and $self->sh_users->addKdmIcon($userData->{username}, $userData->{icon_face});
+ $self->_refresh();
+
+ return 1;
+}
+
+
+# check the password and set the widget accordingly
+sub _checkWeaknessPassword {
+ my ($self, $password, $weakness_widget) = @_;
+
+ my $strongp = $self->sh_users->strongPassword($password);
+ if (yui::YUI::app()->hasImageSupport()) {
+ my $file = File::ShareDir::dist_file(ManaTools::Shared::distName(), 'images/Warning_Shield_Grey16x16.png');
+ if ($strongp) {
+ $file = File::ShareDir::dist_file(ManaTools::Shared::distName(), 'images/Checked_Shield_Green16x16.png');
+ }
+ $weakness_widget->setImage($file);
+ }
+ else {
+ # For ncurses set a label
+ $weakness_widget->setValue(($strongp ? $self->loc->N("Strong") : $self->loc->N("Weak")));
+ }
+}
+
+sub _editUserDialog {
+ my $self = shift;
+
+ my $dontcreatehomedir = 0;
+ my $is_system = 0;
+
+ ## push application title
+ my $appTitle = yui::YUI::app()->applicationTitle();
+ ## set new title to get it in dialog
+ yui::YUI::app()->setApplicationTitle($self->loc->N("Edit User"));
+
+ my $factory = yui::YUI::widgetFactory;
+ my $optional = yui::YUI::optionalWidgetFactory;
+
+ my $dlg = $factory->createPopupDialog();
+ my $layout = $factory->createVBox($dlg);
+
+ my %tabs;
+ if ($optional->hasDumbTab()) {
+ my $hbox = $factory->createHBox($layout);
+ my $align = $factory->createHCenter($hbox);
+ $tabs{widget} = $optional->createDumbTab($align);
+
+ $tabs{user_data} = new yui::YItem($userEditLabel{user_data});
+ $tabs{user_data}->setSelected();
+ $tabs{used} = $tabs{user_data}->label();
+ $tabs{widget}->addItem( $tabs{user_data} );
+ $tabs{user_data}->DISOWN();
+
+ $tabs{account_info} = new yui::YItem($userEditLabel{account_info});
+ $tabs{widget}->addItem( $tabs{account_info} );
+ $tabs{account_info}->DISOWN();
+
+ $tabs{password_info} = new yui::YItem($userEditLabel{password_info});
+ $tabs{widget}->addItem( $tabs{password_info} );
+ $tabs{password_info}->DISOWN();
+
+ $tabs{groups} = new yui::YItem($userEditLabel{groups});
+ $tabs{widget}->addItem( $tabs{groups} );
+ $tabs{groups}->DISOWN();
+
+ my $vbox = $factory->createVBox($tabs{widget});
+ $align = $factory->createLeft($vbox);
+ $tabs{replace_pnt} = $factory->createReplacePoint($align);
+
+ $hbox = $factory->createHBox($vbox);
+ $align = $factory->createRight($hbox);
+ my $cancelButton = $factory->createPushButton($align, $self->loc->N("&Cancel"));
+ my $okButton = $factory->createPushButton($hbox, $self->loc->N("&Ok"));
+
+ my $userData = $self->_getUserInfo();
+ # userData here should be tested because it could be undef
+
+ # Useful entry point for the current edit user/group tab widget
+ $self->set_edit_tab_widget( %{$self->_userDataTabWidget($dlg, $tabs{replace_pnt}, $userData)} );
+ $self->set_edit_tab_widget( edit_tab_label => $userEditLabel{user_data});
+
+ while(1) {
+ my $event = $dlg->waitForEvent();
+ my $eventType = $event->eventType();
+
+ #event type checking
+ if ($eventType == $yui::YEvent::CancelEvent) {
+ last;
+ }
+ elsif ($eventType == $yui::YEvent::MenuEvent) {
+ ### MENU ###
+ my $item = $event->item();
+ if ($item->label() eq $tabs{user_data}->label()) {
+ $self->_storeDataFromUserEditPreviousTab($userData);
+ my $edit_tab = $self->_userDataTabWidget($dlg, $tabs{replace_pnt}, $userData );
+ $self->edit_tab_widgets( {} );
+ $self->set_edit_tab_widget(%{$edit_tab});
+ $self->set_edit_tab_widget( edit_tab_label => $userEditLabel{user_data});
+ }
+ elsif ($item->label() eq $tabs{account_info}->label()) {
+ $self->_storeDataFromUserEditPreviousTab($userData);
+ my $edit_tab = $self->_userAccountInfoTabWidget($dlg, $tabs{replace_pnt}, $userData );
+ $self->edit_tab_widgets( {} );
+ $self->set_edit_tab_widget(%{$edit_tab});
+ $self->set_edit_tab_widget( edit_tab_label => $userEditLabel{account_info});
+ }
+ elsif ($item->label() eq $tabs{password_info}->label()) {
+ $self->_storeDataFromUserEditPreviousTab($userData);
+ my $edit_tab = $self->_userPasswordInfoTabWidget($dlg, $tabs{replace_pnt}, $userData );
+ $self->edit_tab_widgets( {} );
+ $self->set_edit_tab_widget(%{$edit_tab});
+ $self->set_edit_tab_widget( edit_tab_label => $userEditLabel{password_info});
+ }
+ elsif ($item->label() eq $tabs{groups}->label()) {
+ $self->_storeDataFromUserEditPreviousTab($userData);
+ my $edit_tab = $self->_userGroupsTabWidget($dlg, $tabs{replace_pnt}, $userData );
+ $self->edit_tab_widgets( {} );
+ $self->set_edit_tab_widget(%{$edit_tab});
+ $self->set_edit_tab_widget( edit_tab_label => $userEditLabel{groups});
+ }
+ }
+ elsif ($eventType == $yui::YEvent::WidgetEvent) {
+ ### widget
+ my $widget = $event->widget();
+ if ($widget == $cancelButton) {
+ last;
+ }
+ elsif ($widget == $self->get_edit_tab_widget('password')) {
+ my $pass = $self->get_edit_tab_widget('password')->value();
+ $self->_checkWeaknessPassword($pass, $self->get_edit_tab_widget('weakness'));
+ }
+ elsif ($widget == $okButton) {
+ ## save changes
+ if ($self->_userEdit_Ok($userData)) {
+ last;
+ }
+ }
+# last: managing tab widget events
+ else {
+ my $current_tab = $self->get_edit_tab_widget('edit_tab_label');
+ if ($current_tab && $current_tab eq $userEditLabel{account_info}) {
+ if ($widget == $self->get_edit_tab_widget('icon_face')) {
+ my $iconLabel = $self->_iconButtonLabel($self->get_edit_tab_widget('icon_face'));
+ my $nextIcon = $self->sh_users->GetFaceIcon($iconLabel, 1);
+ $self->_iconButtonLabel($self->get_edit_tab_widget('icon_face'), $nextIcon);
+ $self->get_edit_tab_widget('icon_face')->setIcon($self->sh_users->face2png($nextIcon));
+ }
+ }
+ elsif ($current_tab && $current_tab eq $userEditLabel{groups}) {
+ if ($widget == $self->get_edit_tab_widget('members')) {
+ my $item = $self->get_edit_tab_widget('members')->changedItem();
+ if ($item) {
+ if ($item->checked()) {
+ # add it to possible primary groups
+ my $pgItem = new yui::YItem ($item->label(), 0);
+ $self->get_edit_tab_widget('primary_group')->addItem($pgItem);
+ }
+ else {
+ # remove it to possible primary groups
+ $dlg->startMultipleChanges();
+ my $itemColl = new yui::YItemCollection;
+ my $tbl = $self->get_edit_tab_widget('members');
+ for(my $i=0;$i < $tbl->itemsCount();$i++) {
+ if ($tbl->toCBYTableItem($tbl->item($i))->checked()) {
+ my $pgItem = new yui::YItem ($tbl->item($i)->label(), 0);
+ my $primgroup = $self->sh_users->groupName($userData->{primary_group});
+ $pgItem->setSelected(1) if ($pgItem->label() eq $primgroup);
+
+ $itemColl->push($pgItem);
+ $pgItem->DISOWN();
+ }
+ }
+ $self->get_edit_tab_widget('primary_group')->deleteAllItems();
+ $self->get_edit_tab_widget('primary_group')->addItems($itemColl);
+ $dlg->recalcLayout();
+ $dlg->doneMultipleChanges();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ }
+ else {
+ $self->sh_gui->warningMsgBox({text => $self->loc->N("Cannot create tab widgets")});
+ }
+
+ destroy $dlg;
+
+ #restore old application title
+ yui::YUI::app()->setApplicationTitle($appTitle);
+
+}
+
+sub _editGroupDialog {
+ my $self = shift;
+
+ ## push application title
+ my $appTitle = yui::YUI::app()->applicationTitle();
+ ## set new title to get it in dialog
+ yui::YUI::app()->setApplicationTitle($self->loc->N("Edit Group"));
+
+ my $factory = yui::YUI::widgetFactory;
+ my $optional = yui::YUI::optionalWidgetFactory;
+
+ my $dlg = $factory->createPopupDialog();
+ my $layout = $factory->createVBox($dlg);
+
+ my %tabs;
+ if ($optional->hasDumbTab()) {
+ my $hbox = $factory->createHBox($layout);
+ my $align = $factory->createHCenter($hbox);
+ $tabs{widget} = $optional->createDumbTab($align);
+
+ $tabs{group_data} = new yui::YItem($groupEditLabel{group_data});
+ $tabs{group_data}->setSelected();
+ $tabs{widget}->addItem( $tabs{group_data} );
+ $tabs{group_data}->DISOWN();
+
+ $tabs{group_users} = new yui::YItem($groupEditLabel{group_users});
+ $tabs{widget}->addItem( $tabs{group_users} );
+ $tabs{group_users}->DISOWN();
+
+ my $vbox = $factory->createVBox($tabs{widget});
+ $align = $factory->createLeft($vbox);
+ $tabs{replace_pnt} = $factory->createReplacePoint($align);
+
+ $hbox = $factory->createHBox($vbox);
+ $align = $factory->createRight($hbox);
+ my $cancelButton = $factory->createPushButton($align, $self->loc->N("Cancel"));
+ my $okButton = $factory->createPushButton($hbox, $self->loc->N("Ok"));
+
+ my %groupData = $self->_getGroupInfo();
+ # groupData here should be tested because it could be undef
+
+# %groupData: selected group info as:
+# $groupname: group name
+# $members: users that are members of this group
+
+
+ # Useful entry point for the current edit user/group tab widget
+ $self->set_edit_tab_widget( $self->_groupDataTabWidget($dlg, $tabs{replace_pnt}, %groupData) );
+ $self->set_edit_tab_widget( edit_tab_label => $groupEditLabel{group_data});
+
+ while(1) {
+ my $event = $dlg->waitForEvent();
+ my $eventType = $event->eventType();
+
+ #event type checking
+ if ($eventType == $yui::YEvent::CancelEvent) {
+ last;
+ }
+ elsif ($eventType == $yui::YEvent::MenuEvent) {
+ ### MENU ###
+ my $item = $event->item();
+ if ($item->label() eq $tabs{group_data}->label()) {
+ %groupData = $self->_storeDataFromGroupEditPreviousTab(%groupData);
+ my %edit_tab = $self->_groupDataTabWidget($dlg, $tabs{replace_pnt}, %groupData );
+ $self->edit_tab_widgets( {} );
+ $self->set_edit_tab_widget(%edit_tab);
+ $self->set_edit_tab_widget( edit_tab_label => $groupEditLabel{group_data});
+ }
+ elsif ($item->label() eq $tabs{group_users}->label()) {
+ %groupData = $self->_storeDataFromGroupEditPreviousTab(%groupData);
+ my %edit_tab = $self->_groupUsersTabWidget($dlg, $tabs{replace_pnt}, %groupData );
+ $self->edit_tab_widgets( {} );
+ $self->set_edit_tab_widget(%edit_tab);
+ $self->set_edit_tab_widget( edit_tab_label => $groupEditLabel{group_users});
+ }
+ }
+ elsif ($eventType == $yui::YEvent::WidgetEvent) {
+ ### widget
+ my $widget = $event->widget();
+ if ($widget == $cancelButton) {
+ last;
+ }
+ elsif ($widget == $okButton) {
+ ## save changes
+ if ($self->_groupEdit_Ok(%groupData)) {
+ last;
+ }
+ }
+ }
+ }
+
+ }
+ else {
+ $self->sh_gui->warningMsgBox({text => $self->loc->N("Cannot create tab widgets")});
+ }
+
+ destroy $dlg;
+
+ #restore old application title
+ yui::YUI::app()->setApplicationTitle($appTitle);
+
+}
+
+sub _editUserOrGroup {
+ my $self = shift;
+
+ # TODO item management avoid label if possible
+ my $label = $self->_skipShortcut($self->get_widget('tabs')->selectedItem()->label());
+ if ($label eq $self->loc->N("Users") ) {
+ $self->_editUserDialog();
+ }
+ else {
+ $self->_editGroupDialog();
+ }
+ $self->_refresh();
+}
+
+
+sub _deleteUserOrGroup {
+ my $self = shift;
+
+ # TODO item management avoid label if possible
+ my $label = $self->_skipShortcut($self->get_widget('tabs')->selectedItem()->label());
+ if ($label eq $self->loc->N("Users") ) {
+ $self->_deleteUserDialog();
+ $self->_refresh();
+ }
+ else {
+ $self->_deleteGroupDialog();
+ $self->_refresh();
+ }
+}
+
+
+sub _refresh {
+ my $self = shift;
+
+ # TODO item management avoid label if possible
+ my $label = $self->_skipShortcut($self->get_widget('tabs')->selectedItem()->label());
+ if ($label eq $self->loc->N("Users") ) {
+ $self->_refreshUsers();
+ }
+ else {
+ $self->_refreshGroups();
+ }
+# TODO xguest
+# RefreshXguest(1);
+}
+
+# TODO context menu creation is missed in libyui
+sub _contextMenuActions {
+ my $self = shift;
+
+ my $item = $self->get_widget('table')->selectedItem();
+ if ($item) {
+ }
+}
+
+sub _refreshActions {
+ my $self = shift;
+
+ my $item = $self->get_widget('table')->selectedItem();
+ $self->dialog->startMultipleChanges();
+ $self->get_widget('action_menu')->deleteAllItems();
+
+ # do we need to undef them first?
+ $self->set_action_menu(
+ add_user => undef,
+ add_group => undef,
+ edit => undef,
+ del => undef,
+ inst => undef,
+ );
+ $self->set_action_menu(
+ add_user => new yui::YMenuItem($self->loc->N("Add User")),
+ add_group => new yui::YMenuItem($self->loc->N("Add Group")),
+ edit => new yui::YMenuItem($self->loc->N("&Edit")),
+ del => new yui::YMenuItem($self->loc->N("&Delete")),
+ inst => new yui::YMenuItem($self->loc->N("Install guest account")),
+ );
+
+ my $itemColl = new yui::YItemCollection;
+ for my $pair ( $self->action_menu_pairs ) {
+ my $menuItem = $pair->[1];
+ if ($pair->[0] eq 'edit' || $pair->[0] eq 'del') {
+ if ($item) {
+ $itemColl->push($menuItem);
+ }
+ }
+ else {
+ $itemColl->push($menuItem);
+ }
+ $menuItem->DISOWN();
+ }
+ $self->get_widget('action_menu')->addItems($itemColl);
+ $self->get_widget('action_menu')->rebuildMenuTree();
+ if ($item) {
+ $self->get_widget('edit')->setEnabled();
+ $self->get_widget('del')->setEnabled();
+ }
+ else {
+ $self->get_widget('edit')->setDisabled();
+ $self->get_widget('del')->setDisabled();
+ }
+
+ $self->dialog->doneMultipleChanges();
+}
+
+sub _showAboutDialog {
+ my $self = shift;
+
+ my $translators = $self->loc->N("_: Translator(s) name(s) & email(s)\n");
+ $translators =~ s/\</\&lt\;/g;
+ $translators =~ s/\>/\&gt\;/g;
+ $self->sh_gui->AboutDialog({
+ name => $self->loc->N("manauser"),
+ version => $self->VERSION,
+ credits => $self->loc->N("Copyright (C) %s Mageia community", '2013-2015'),
+ license => $self->loc->N("GPLv2"),
+ description => $self->loc->N("manauser is a Mageia user management tool \n(from the original idea of Mandriva userdrake)."),
+ authors => $self->loc->N("<h3>Developers</h3>
+ <ul><li>%s</li>
+ <li>%s</li>
+ </ul>
+ <h3>Translators</h3>
+ <ul><li>%s</li></ul>",
+ "Angelo Naselli &lt;anaselli\@linux.it&gt;",
+ "Matteo Pasotti &lt;matteo.pasotti\@gmail.com&gt;",
+ $translators
+ ),
+ });
+}
+sub _manageUsersDialog {
+ my $self = shift;
+
+ if ($EUID != 0) {
+ $self->sh_gui->warningMsgBox({
+ title => $self->name,
+ text => $self->loc->N("root privileges required"),
+ });
+ return;
+ }
+
+ ## TODO fix for manatools
+ my $pixdir = '/usr/share/userdrake/pixmaps/';
+ ## push application title
+ my $appTitle = yui::YUI::app()->applicationTitle();
+
+ ## set new title to get it in dialog
+ yui::YUI::app()->setApplicationTitle($self->name);
+ ## set icon if not already set by external launcher
+ yui::YUI::app()->setApplicationIcon($self->icon);
+
+
+ my $factory = yui::YUI::widgetFactory;
+ my $optional = yui::YUI::optionalWidgetFactory;
+
+
+ $self->dialog($factory->createMainDialog());
+ my $layout = $factory->createVBox($self->dialog);
+
+ my $hbox_headbar = $factory->createHBox($layout);
+ my $head_align_left = $factory->createLeft($hbox_headbar);
+ my $head_align_right = $factory->createRight($hbox_headbar);
+ my $headbar = $factory->createHBox($head_align_left);
+ my $headRight = $factory->createHBox($head_align_right);
+
+ my %fileMenu = (
+ widget => $factory->createMenuButton($headbar,$self->loc->N("File")),
+ refresh => new yui::YMenuItem($self->loc->N("Refresh")),
+ quit => new yui::YMenuItem($self->loc->N("&Quit")),
+ );
+
+ $fileMenu{ widget }->addItem($fileMenu{ refresh });
+ $fileMenu{ widget }->addItem($fileMenu{ quit });
+ $fileMenu{ widget }->rebuildMenuTree();
+
+ my $actionMenu = $factory->createMenuButton($headbar, $self->loc->N("Actions"));
+ $actionMenu->DISOWN();
+
+ my %helpMenu = (
+ widget => $factory->createMenuButton($headRight, $self->loc->N("&Help")),
+ help => new yui::YMenuItem($self->loc->N("Help")),
+ report_bug => new yui::YMenuItem($self->loc->N("Report Bug")),
+ about => new yui::YMenuItem($self->loc->N("&About")),
+ );
+
+ while ( my ($key, $value) = each(%helpMenu) ) {
+ if ($key ne 'widget' ) {
+ $helpMenu{ widget }->addItem($value);
+ }
+ }
+ $helpMenu{ widget }->rebuildMenuTree();
+
+ my $hbox = $factory->createHBox($layout);
+ $hbox = $factory->createHBox($factory->createLeft($hbox));
+ $self->set_widget(
+ add_user => $factory->createIconButton($hbox, $pixdir . 'user_add.png', $self->loc->N("Add User")),
+ add_group => $factory->createIconButton($hbox, $pixdir . 'group_add.png', $self->loc->N("Add Group")),
+ edit => $factory->createIconButton($hbox, $pixdir . 'user_conf.png', $self->loc->N("Edit")),
+ del => $factory->createIconButton($hbox, $pixdir . 'user_del.png', $self->loc->N("Delete")),
+ refresh => $factory->createIconButton($hbox, $pixdir . 'refresh.png', $self->loc->N("Refresh")),
+ action_menu => $actionMenu,
+ );
+
+
+ $hbox = $factory->createHBox($layout);
+ $head_align_left = $factory->createLeft($hbox);
+
+ my $sysfilter = 1;
+ if (-e $self->config_file) {
+ my $prefs = Config::Auto::parse($self->config_file);
+ $sysfilter = ($prefs->{FILTER} eq 'true' or $prefs->{FILTER} eq 'true' or $prefs->{FILTER} eq '1');
+ }
+ $self->set_widget(filter_system => $factory->createCheckBox($head_align_left, $self->loc->N("Filter system users"),
+ $sysfilter));
+ $factory->createHSpacing($hbox, 3);
+ $head_align_right = $factory->createRight($hbox);
+ $headRight = $factory->createHBox($head_align_right);
+ $factory->createLabel($headRight, $self->loc->N("Search:"));
+ $self->set_widget(filter => $factory->createInputField($headRight, "", 0));
+ $self->set_widget(apply_filter => $factory->createPushButton($headRight, $self->loc->N("Apply filter")));
+ $self->get_widget('filter')->setWeight($yui::YD_HORIZ, 2);
+ $self->get_widget('apply_filter')->setWeight($yui::YD_HORIZ, 1);
+ $self->get_widget('filter_system')->setNotify(1);
+
+ my %tabs;
+ if ($optional->hasDumbTab()) {
+ $hbox = $factory->createHBox($layout);
+ my $align = $factory->createHCenter($hbox);
+ $self->set_widget(tabs => $optional->createDumbTab($align));
+ }
+
+ $hbox = $factory->createHBox($layout);
+ my $align = $factory->createLeft($hbox);
+ my $aboutButton = $factory->createPushButton($align, $self->loc->N("&About") );
+ $align = $factory->createRight($hbox);
+ my $quitButton = $factory->createPushButton($align, $self->loc->N("&Quit") );
+
+ if ($optional->hasDumbTab()) {
+ $tabs{users} = new yui::YItem($self->loc->N("Users"));
+ $tabs{users}->setSelected();
+ $self->get_widget('tabs')->addItem( $tabs{users} );
+ $tabs{users}->DISOWN();
+ $tabs{groups} = new yui::YItem($self->loc->N("Groups"));
+ $self->get_widget('tabs')->addItem( $tabs{groups} );
+ $tabs{groups}->DISOWN();
+ my $vbox = $factory->createVBox($self->get_widget('tabs'));
+ $align = $factory->createLeft($vbox);
+ $self->set_widget(replace_pnt => $factory->createReplacePoint($align));
+ $self->_createUserTable();
+ $self->get_widget('table')->setImmediateMode(1);
+ $self->get_widget('table')->DISOWN();
+ }
+
+ $self->_refreshActions();
+
+ # main loop
+ while(1) {
+ my $event = $self->dialog->waitForEvent();
+ my $eventType = $event->eventType();
+
+ #event type checking
+ if ($eventType == $yui::YEvent::CancelEvent) {
+ last;
+ }
+ elsif ($eventType == $yui::YEvent::MenuEvent) {
+### MENU ###
+ my $item = $event->item();
+ my $menuLabel = $item->label();
+ if ($menuLabel eq $fileMenu{ quit }->label()) {
+ last;
+ }
+ elsif ($menuLabel eq $helpMenu{about}->label()) {
+ $self->_showAboutDialog();
+ }
+ elsif ($menuLabel eq $self->get_action_menu('add_user')->label()) {
+ $self->addUserDialog();
+ $self->_refresh();
+ }
+ elsif ($menuLabel eq $self->get_action_menu('add_group')->label()) {
+ $self->_addGroupDialog();
+ $self->_refresh();
+ }
+ elsif ($menuLabel eq $self->get_action_menu('del')->label()) {
+ $self->_deleteUserOrGroup();
+ }
+ elsif ($menuLabel eq $self->get_action_menu('edit')->label()) {
+ $self->_editUserOrGroup();
+ }
+ elsif ($self->get_widget('tabs') && $menuLabel eq $tabs{groups}->label()) {
+ $self->_createGroupTable();
+ }
+ elsif ($self->get_widget('tabs') && $menuLabel eq $tabs{users}->label()) {
+ $self->_createUserTable();
+ }
+ elsif ($menuLabel eq $fileMenu{refresh}->label()) {
+ $self->_refresh();
+ }
+ }
+ elsif ($eventType == $yui::YEvent::WidgetEvent) {
+### Buttons and widgets ###
+ my $widget = $event->widget();
+ if ($widget == $quitButton) {
+ last;
+ }
+ elsif ($widget == $aboutButton) {
+ $self->_showAboutDialog();
+ }
+ elsif ($widget == $self->get_widget('add_user')) {
+ $self->addUserDialog();
+ $self->_refresh();
+ }
+ elsif ($widget == $self->get_widget('del')) {
+ $self->_deleteUserOrGroup();
+ }
+ elsif ($widget == $self->get_widget('table')) {
+ $self->_refreshActions();
+ my $wEvent = yui::YMGAWidgetFactory::getYWidgetEvent($event);
+ if ($wEvent && $wEvent->reason() == $yui::YEvent::Activated) {
+ $self->_editUserOrGroup();
+ }
+ }
+ elsif ($widget == $self->get_widget('add_group')) {
+ $self->_addGroupDialog();
+ $self->_refresh();
+ }
+ elsif ($widget == $self->get_widget('edit')) {
+ $self->_editUserOrGroup();
+ }
+ elsif ( $widget == $self->get_widget('filter_system') ||
+ $widget == $self->get_widget('refresh') ||
+ $widget == $self->get_widget('apply_filter') ) {
+ $self->_refresh();
+ }
+ }
+ }
+
+ $self->dialog->destroy() ;
+
+ #restore old application title
+ yui::YUI::app()->setApplicationTitle($appTitle) if $appTitle;
+}
+
+#=============================================================
+
+=head2 _skipShortcut
+
+=head3 INPUT
+
+ $self: this object
+ $label: an item label to be cleaned by keyboard shortcut "&"
+
+=head3 OUTPUT
+
+ $label: cleaned label
+
+=head3 DESCRIPTION
+
+ This internal method is a workaround to label that are
+ changed by "&" due to keyborad shortcut.
+
+=cut
+
+#=============================================================
+sub _skipShortcut {
+ my ($self, $label) = @_;
+
+ $label =~ s/&// if ($label);
+
+ return ($label);
+}
+
+
+sub _ValidInt {
+ foreach my $i (@_) { $i =~ /\d+/ or return 0 }
+ return 1;
+}
+
+
+sub _TimeOfArray {
+ my ($reltime, $cm) = @_;
+ my $h; my %mth = (Jan => 1, Feb => 2, Mar => 3, Apr => 4, May => 5, Jun => 6, Jul => 7, Aug => 8, Sep => 9, Oct => 10, Nov => 11, Dec => 12);
+ my $_t = localtime($reltime * 24 * 60 * 60) =~ /(\S+)\s+(\S+)\s+(\d+)\s+(\S+)\s+(\d+)/;
+ $h->{daystr} = $1;
+ $h->{month} = $2;
+ $h->{dayint} = $3;
+ $h->{year} = $5;
+ $cm and $h->{month} = $mth{$2};
+ $h;
+}
+
+
+no Moose;
+__PACKAGE__->meta->make_immutable;
+
+1;