From b4e446c21e299af0441ec44db7a86334980b77c2 Mon Sep 17 00:00:00 2001 From: Angelo Naselli Date: Mon, 16 Mar 2015 19:20:40 +0100 Subject: Moved the tree accordingly --- lib/AdminPanel/Category.pm | 262 -- lib/AdminPanel/ConfigReader.pm | 119 - lib/AdminPanel/MainDisplay.pm | 628 ----- lib/AdminPanel/Module.pm | 162 -- lib/AdminPanel/Module/AdminMouse.pm | 282 -- lib/AdminPanel/Module/Clock.pm | 518 ---- lib/AdminPanel/Module/DisplayManager.pm | 298 -- lib/AdminPanel/Module/Firewall.pm | 1208 --------- lib/AdminPanel/Module/Hosts.pm | 530 ---- lib/AdminPanel/Module/LogViewer.pm | 568 ---- lib/AdminPanel/Module/Proxy.pm | 396 --- lib/AdminPanel/Module/Services.pm | 588 ---- lib/AdminPanel/Module/Users.pm | 2637 ------------------ lib/AdminPanel/Privileges.pm | 61 - lib/AdminPanel/Rpmdragora/.perl_checker | 1 - lib/AdminPanel/Rpmdragora/edit_urpm_sources.pm | 2243 --------------- lib/AdminPanel/Rpmdragora/formatting.pm | 209 -- lib/AdminPanel/Rpmdragora/gui.pm | 1828 ------------- lib/AdminPanel/Rpmdragora/gurpm.pm | 298 -- lib/AdminPanel/Rpmdragora/icon.pm | 234 -- lib/AdminPanel/Rpmdragora/init.pm | 181 -- lib/AdminPanel/Rpmdragora/open_db.pm | 171 -- lib/AdminPanel/Rpmdragora/pkg.pm | 1085 -------- lib/AdminPanel/Rpmdragora/rpmnew.pm | 363 --- lib/AdminPanel/SettingsReader.pm | 101 - lib/AdminPanel/Shared.pm | 376 --- lib/AdminPanel/Shared/Firewall.pm | 35 - lib/AdminPanel/Shared/GUI.pm | 1118 -------- lib/AdminPanel/Shared/Hosts.pm | 216 -- lib/AdminPanel/Shared/JournalCtl.pm | 141 - lib/AdminPanel/Shared/Locales.pm | 280 -- lib/AdminPanel/Shared/Proxy.pm | 36 - lib/AdminPanel/Shared/RunProgram.pm | 352 --- lib/AdminPanel/Shared/Services.pm | 955 ------- lib/AdminPanel/Shared/Shorewall.pm | 271 -- lib/AdminPanel/Shared/TimeZone.pm | 799 ------ lib/AdminPanel/Shared/Users.pm | 1612 ----------- lib/AdminPanel/rpmdragora.pm | 1165 -------- lib/ManaTools/Category.pm | 262 ++ lib/ManaTools/ConfigReader.pm | 119 + lib/ManaTools/MainDisplay.pm | 628 +++++ lib/ManaTools/Module.pm | 162 ++ lib/ManaTools/Module/AdminMouse.pm | 282 ++ lib/ManaTools/Module/Clock.pm | 518 ++++ lib/ManaTools/Module/DisplayManager.pm | 298 ++ lib/ManaTools/Module/Firewall.pm | 1208 +++++++++ lib/ManaTools/Module/Hosts.pm | 530 ++++ lib/ManaTools/Module/LogViewer.pm | 568 ++++ lib/ManaTools/Module/Proxy.pm | 396 +++ lib/ManaTools/Module/Services.pm | 588 ++++ lib/ManaTools/Module/Users.pm | 2637 ++++++++++++++++++ lib/ManaTools/Privileges.pm | 61 + lib/ManaTools/Rpmdragora/.perl_checker | 1 + lib/ManaTools/Rpmdragora/edit_urpm_sources.pm | 2243 +++++++++++++++ lib/ManaTools/Rpmdragora/formatting.pm | 209 ++ lib/ManaTools/Rpmdragora/gui.pm | 1828 +++++++++++++ lib/ManaTools/Rpmdragora/gurpm.pm | 298 ++ lib/ManaTools/Rpmdragora/icon.pm | 234 ++ lib/ManaTools/Rpmdragora/init.pm | 181 ++ lib/ManaTools/Rpmdragora/open_db.pm | 171 ++ lib/ManaTools/Rpmdragora/pkg.pm | 1085 ++++++++ lib/ManaTools/Rpmdragora/rpmnew.pm | 363 +++ lib/ManaTools/SettingsReader.pm | 101 + lib/ManaTools/Shared.pm | 376 +++ lib/ManaTools/Shared/Firewall.pm | 35 + lib/ManaTools/Shared/GUI.pm | 1118 ++++++++ lib/ManaTools/Shared/Hosts.pm | 216 ++ lib/ManaTools/Shared/JournalCtl.pm | 141 + lib/ManaTools/Shared/Locales.pm | 280 ++ lib/ManaTools/Shared/Proxy.pm | 36 + lib/ManaTools/Shared/RunProgram.pm | 352 +++ lib/ManaTools/Shared/Services.pm | 955 +++++++ lib/ManaTools/Shared/Shorewall.pm | 271 ++ lib/ManaTools/Shared/TimeZone.pm | 799 ++++++ lib/ManaTools/Shared/Users.pm | 1612 +++++++++++ lib/ManaTools/rpmdragora.pm | 1165 ++++++++ po/adminpanel.pot | 3445 ------------------------ po/manatools.pot | 3445 ++++++++++++++++++++++++ 78 files changed, 25772 insertions(+), 25772 deletions(-) delete mode 100644 lib/AdminPanel/Category.pm delete mode 100644 lib/AdminPanel/ConfigReader.pm delete mode 100644 lib/AdminPanel/MainDisplay.pm delete mode 100644 lib/AdminPanel/Module.pm delete mode 100644 lib/AdminPanel/Module/AdminMouse.pm delete mode 100644 lib/AdminPanel/Module/Clock.pm delete mode 100644 lib/AdminPanel/Module/DisplayManager.pm delete mode 100644 lib/AdminPanel/Module/Firewall.pm delete mode 100644 lib/AdminPanel/Module/Hosts.pm delete mode 100644 lib/AdminPanel/Module/LogViewer.pm delete mode 100644 lib/AdminPanel/Module/Proxy.pm delete mode 100644 lib/AdminPanel/Module/Services.pm delete mode 100644 lib/AdminPanel/Module/Users.pm delete mode 100644 lib/AdminPanel/Privileges.pm delete mode 100644 lib/AdminPanel/Rpmdragora/.perl_checker delete mode 100644 lib/AdminPanel/Rpmdragora/edit_urpm_sources.pm delete mode 100644 lib/AdminPanel/Rpmdragora/formatting.pm delete mode 100644 lib/AdminPanel/Rpmdragora/gui.pm delete mode 100644 lib/AdminPanel/Rpmdragora/gurpm.pm delete mode 100644 lib/AdminPanel/Rpmdragora/icon.pm delete mode 100644 lib/AdminPanel/Rpmdragora/init.pm delete mode 100644 lib/AdminPanel/Rpmdragora/open_db.pm delete mode 100644 lib/AdminPanel/Rpmdragora/pkg.pm delete mode 100644 lib/AdminPanel/Rpmdragora/rpmnew.pm delete mode 100644 lib/AdminPanel/SettingsReader.pm delete mode 100644 lib/AdminPanel/Shared.pm delete mode 100644 lib/AdminPanel/Shared/Firewall.pm delete mode 100644 lib/AdminPanel/Shared/GUI.pm delete mode 100644 lib/AdminPanel/Shared/Hosts.pm delete mode 100644 lib/AdminPanel/Shared/JournalCtl.pm delete mode 100644 lib/AdminPanel/Shared/Locales.pm delete mode 100644 lib/AdminPanel/Shared/Proxy.pm delete mode 100644 lib/AdminPanel/Shared/RunProgram.pm delete mode 100644 lib/AdminPanel/Shared/Services.pm delete mode 100644 lib/AdminPanel/Shared/Shorewall.pm delete mode 100644 lib/AdminPanel/Shared/TimeZone.pm delete mode 100644 lib/AdminPanel/Shared/Users.pm delete mode 100644 lib/AdminPanel/rpmdragora.pm create mode 100644 lib/ManaTools/Category.pm create mode 100644 lib/ManaTools/ConfigReader.pm create mode 100644 lib/ManaTools/MainDisplay.pm create mode 100644 lib/ManaTools/Module.pm create mode 100644 lib/ManaTools/Module/AdminMouse.pm create mode 100644 lib/ManaTools/Module/Clock.pm create mode 100644 lib/ManaTools/Module/DisplayManager.pm create mode 100644 lib/ManaTools/Module/Firewall.pm create mode 100644 lib/ManaTools/Module/Hosts.pm create mode 100644 lib/ManaTools/Module/LogViewer.pm create mode 100644 lib/ManaTools/Module/Proxy.pm create mode 100644 lib/ManaTools/Module/Services.pm create mode 100644 lib/ManaTools/Module/Users.pm create mode 100644 lib/ManaTools/Privileges.pm create mode 100644 lib/ManaTools/Rpmdragora/.perl_checker create mode 100644 lib/ManaTools/Rpmdragora/edit_urpm_sources.pm create mode 100644 lib/ManaTools/Rpmdragora/formatting.pm create mode 100644 lib/ManaTools/Rpmdragora/gui.pm create mode 100644 lib/ManaTools/Rpmdragora/gurpm.pm create mode 100644 lib/ManaTools/Rpmdragora/icon.pm create mode 100644 lib/ManaTools/Rpmdragora/init.pm create mode 100644 lib/ManaTools/Rpmdragora/open_db.pm create mode 100644 lib/ManaTools/Rpmdragora/pkg.pm create mode 100644 lib/ManaTools/Rpmdragora/rpmnew.pm create mode 100644 lib/ManaTools/SettingsReader.pm create mode 100644 lib/ManaTools/Shared.pm create mode 100644 lib/ManaTools/Shared/Firewall.pm create mode 100644 lib/ManaTools/Shared/GUI.pm create mode 100644 lib/ManaTools/Shared/Hosts.pm create mode 100644 lib/ManaTools/Shared/JournalCtl.pm create mode 100644 lib/ManaTools/Shared/Locales.pm create mode 100644 lib/ManaTools/Shared/Proxy.pm create mode 100644 lib/ManaTools/Shared/RunProgram.pm create mode 100644 lib/ManaTools/Shared/Services.pm create mode 100644 lib/ManaTools/Shared/Shorewall.pm create mode 100644 lib/ManaTools/Shared/TimeZone.pm create mode 100644 lib/ManaTools/Shared/Users.pm create mode 100644 lib/ManaTools/rpmdragora.pm delete mode 100644 po/adminpanel.pot create mode 100644 po/manatools.pot diff --git a/lib/AdminPanel/Category.pm b/lib/AdminPanel/Category.pm deleted file mode 100644 index 4ef7fa7..0000000 --- a/lib/AdminPanel/Category.pm +++ /dev/null @@ -1,262 +0,0 @@ -# vim: set et ts=4 sw=4: -# Copyright 2012 Steven Tucker -# -# This file is part of ManaTools -# -# ManaTools is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. -# -# ManaTools 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 ManaTools. If not, see . - - -#Class Category -package ManaTools::Category; - -use strict; -use warnings; -use diagnostics; -use yui; - -## Can only add the config file data at constructor -## The Gui elements are added in setupGui inside MainDisplay -#============================================================= - -=head2 new - -=head3 INPUT - - $newName: new category name - $newIcon: new category icon - -=head3 OUTPUT - - $self: this object - -=head3 DESCRIPTION - - Constructor: creates a new category named Name - -=cut - -#============================================================= - -sub new { - my ($class, $newName, $newIcon) = @_; - my $self = { - name => 0, - button => 0, - icon => 0, - modules => [], - }; - bless $self, 'ManaTools::Category'; - - $self->{name} = $newName; - $self->{icon} = $newIcon; - - return $self; -} - -## Add a new module to the list -#============================================================= - -=head2 loadModule - -=head3 INPUT - - $self: this object - $module: module to add - -=head3 OUTPUT - - 1: if the module has been added - 0: otherwise - -=head3 DESCRIPTION - - This method adds a module to the loaded - modules if it is not already in. - -=cut - -#============================================================= -sub loadModule { - my ($self, $module) = @_; - - if (!$self->moduleLoaded($module->{name})) { - push ( @{$self->{modules}}, $module ); - - return 1; - } - return 0; -} - -#============================================================= - -=head2 moduleLoaded - -=head3 INPUT - - $self: this object - $module_name or -CLASS => name : module/CLASS name to look for - -=head3 OUTPUT - - $present: module present or not - -=head3 DESCRIPTION - - This method looks for the given module and if already in - returns true. -=cut - -#============================================================= -sub moduleLoaded { - my $self = shift; - my ($module_name) = @_; - my %params = (); - if ($module_name eq '-CLASS') { - (%params) = @_; - } - - my $present = 0; - - if (!$module_name || ! $self->{modules}) { - return $present; - } - - foreach my $mod (@{$self->{modules}}) { - if (exists $params{-CLASS} && ref($mod) eq $params{-CLASS}) { - $present = 1; - last; - } - elsif ($mod->{name} eq $module_name) { - $present = 1; - last; - } - } - - return $present; -} - -#============================================================= - -=head2 addButtons - -=head3 INPUT - - $self: this object - $panel: parent panel layout in which to create buttons - $factory: yui factory - -=head3 DESCRIPTION - - Creates and adds buttons for each module_name - -=cut - -#============================================================= -sub addButtons { - my($self, $panel, $factory) = @_; - my $tmpButton; - my $currLayout = 0; - my %weights = (); - my $curr; - my $count = 0; - foreach my $mod (@{$self->{modules}}) { - if(($count % 2) != 1) { - $factory->createVSpacing($panel, 0.5); - $currLayout = $factory->createHBox($panel); - $factory->createHSpacing($currLayout, 1); - $currLayout->setWeight($yui::YD_VERT, 10); - } - - $tmpButton = $factory->createPushButton( - $currLayout, - $mod->name - ); - $count++; - if (($count < scalar @{$self->{modules}}) || (($count >= scalar @{$self->{modules}}) && ($count % 2) == 0)) { - $tmpButton->setWeight($yui::YD_HORIZ, 20); - } - $factory->createHSpacing($currLayout, 1); - $mod->setButton($tmpButton); - $tmpButton->setLabel($mod->name); - $tmpButton->setIcon($mod->icon); - } -} - -#============================================================= - -=head2 removeButtons - -=head3 INPUT - - $self: this object - -=head3 DESCRIPTION - - Delete the module buttons - -=cut - -#============================================================= -sub removeButtons { - my($self) = @_; - - for(@{$self->{modules}}) { - $_->removeButton(); - } -} - -#============================================================= - -=head2 setIcon - -=head3 INPUT - - $self: this object - -=head3 DESCRIPTION - - set the button icon - -=cut - -#============================================================= -sub setIcon { - my($self) = @_; - - $self->{button}->setIcon($self->{icon}); -} - -1; -__END__ - -=pod - -=head1 NAME - - Category - add new category to window - -=head1 SYNOPSIS - - $category = new Category('Category Name'); - - -=head1 USAGE - - This class is used by MainDisplay internally and should not - be used outside, since MainDisplay::setupGui use it to - build GUI layout. - -=head1 FUNCTIONS - -=cut diff --git a/lib/AdminPanel/ConfigReader.pm b/lib/AdminPanel/ConfigReader.pm deleted file mode 100644 index 792dc0e..0000000 --- a/lib/AdminPanel/ConfigReader.pm +++ /dev/null @@ -1,119 +0,0 @@ -# vim: set et ts=4 sw=4: -# Copyright 2012 Steven Tucker -# -# This file is part of ManaTools -# -# ManaTools is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. -# -# ManaTools 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 ManaTools. If not, see . - - -#Class ConfigReader -package ManaTools::ConfigReader; - -use strict; -use warnings; -use diagnostics; -use XML::Simple; -use Data::Dumper; - -sub new { - my ($class, $fileName) = @_; - - my $self = { - data => 0, - catLen => 0, - currCat => 0, - modLen => 0, - currMod => 0, - placeHolder => 0, - }; - bless $self, 'ManaTools::ConfigReader'; - - my $xml = new XML::Simple (KeyAttr=>[]); - $self->{data} = $xml->XMLin($fileName); - if (ref($self->{data}->{category}) eq "HASH") { - # one element alone - my @categories; - push @categories, $self->{data}->{category}; - $self->{data}->{category} = undef; - push @{$self->{data}->{category}}, @categories; - } - $self->{catLen} = scalar(@{$self->{data}->{category}}); - $self->{currCat} = -1; - - if(ref(@{$self->{data}->{category}}[0]->{module}) eq "ARRAY") { - $self->{modLen} = scalar(@{@{$self->{data}->{category}}[0]->{module}}); - } else { - $self->{modLen} = 1; - } - $self->{currMod} = -1; - - return $self; -} - -sub hasNextCat { - my ($self) = @_; - - if($self->{currCat} + 1 >= $self->{catLen}) { - return 0; - } - return 1; -} - -sub getNextCat { - my ($self) = @_; - - $self->{currCat}++; - if($self->{currCat} >= $self->{catLen}) { - return 0; - } - - # Reset the Module Count and Mod length for new Category - $self->{currMod} = -1; - if(ref(@{$self->{data}->{category}}[$self->{currCat}]->{module}) eq "ARRAY") { - $self->{modLen} = scalar(@{@{$self->{data}->{category}}[$self->{currCat}]->{module}}); - } else { - $self->{modLen} = 1; - } - - my $tmp = @{$self->{data}->{category}}[$self->{currCat}]; - - return $tmp; -} - -sub hasNextMod { - my ($self) = @_; - - if($self->{currMod} + 1 >= $self->{modLen}) { - return 0; - } - return 1; -} - -sub getNextMod { - my ($self) = @_; - - my $ret = 0; - - $self->{currMod}++; - - if($self->{modLen} == 1) { - $ret = @{$self->{data}->{category}}[$self->{currCat}]->{module}; - } else { - $ret = @{@{$self->{data}->{category} }[$self->{currCat}]->{module}}[$self->{currMod}]; - } - - return $ret; -} - -1; diff --git a/lib/AdminPanel/MainDisplay.pm b/lib/AdminPanel/MainDisplay.pm deleted file mode 100644 index 19d0a7f..0000000 --- a/lib/AdminPanel/MainDisplay.pm +++ /dev/null @@ -1,628 +0,0 @@ -# vim: set et ts=4 sw=4: -# Copyright 2012 Steven Tucker -# -# This file is part of ManaTools -# -# ManaTools is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. -# -# ManaTools 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 ManaTools. If not, see . - - -package ManaTools::MainDisplay; -#============================================================= -*-perl-*- - -=head1 NAME - -ManaTools::MainDisplay - class for AdminPaneol main window - -=head1 SYNOPSIS - - $mainDisplay = new ManaTools::MainDisplay(); - $mainDisplay->start(); - $mainDisplay->destroy(); - -=head1 METHODS - -=head1 DESCRIPTION - -Long_description - -=head1 EXPORT - -exported - -=head1 SUPPORT - -You can find documentation for this module with the perldoc command: - -perldoc ManaTools::MainDisplay - -=head1 SEE ALSO - -SEE_ALSO - -=head1 AUTHOR - -Steven Tucker - -=head1 COPYRIGHT and LICENSE - -Copyright (C) 2012, Steven Tucker -Copyright (C) 2014, Angelo Naselli. - -ManaTools is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) any later version. - -ManaTools 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 ManaTools. If not, see . - -=head1 FUNCTIONS - -=cut - - - -=head1 VERSION - -Version 0.01 - -=cut - -our $VERSION = '1.0.0'; - -use strict; -use warnings; -use diagnostics; -use ManaTools::SettingsReader; -use ManaTools::ConfigReader; -use ManaTools::Category; -use ManaTools::Module; -use ManaTools::Shared; -use ManaTools::Shared::GUI; -use ManaTools::Shared::Locales; -use File::ShareDir ':ALL'; - -use yui; - -#============================================================= - -=head2 new - -=head3 DESCRIPTION - -This method instanziates the MainWindo object, and setups -the startup GUI. - -=cut - -#============================================================= -sub new { - - my $self = { - categories => 0, - event => 0, - factory => 0, - mainWin => 0, - mainLayout => 0, - menuLayout => 0, - menus => { - file => 0, - help => 0 - }, - layout => 0, - leftPane => 0, - rightPane => 0, - currCategory => 0, - confDir => 0, - title => 0, - settings => 0, - exitButton => 0, - aboutButton => 0, - loc => 0, - replacePoint => 0, - }; - bless $self, 'ManaTools::MainDisplay'; - -## Default values - $self->{name} = "Mana-tools panel"; - $self->{categories} = []; - $self->{confDir} = "/etc/mpan", - $self->{title} = "mpan", - - my $cmdline = new yui::YCommandLine; - - ## TODO add parameter check - my $pos = $cmdline->find("--name"); - if ($pos > 0) - { - $self->{title} = $cmdline->arg($pos+1); - } - $pos = $cmdline->find("--conf_dir"); - if ($pos > 0) - { - $self->{confDir} = $cmdline->arg($pos+1); - } - else - { - $self->{confDir} = "/etc/$self->{title}"; - } - - # TODO localize - $self->{loc} = ManaTools::Shared::Locales->new(domain_name => 'libDrakX-standalone'); - $self->setupGui(); - - return $self; -} - - -sub _showAboutDialog { - my $self = shift; - - my $translators = $self->{loc}->N("_: Translator(s) name(s) & email(s)\n"); - $translators =~ s/\/\>\;/g; - my $sh_gui = ManaTools::Shared::GUI->new(); - $sh_gui->AboutDialog({ name => $self->{name}, - version => $ManaTools::MainDisplay::VERSION, - credits => $self->{loc}->N("Copyright (C) %s Mageia community", '2013-2015'), - license => $self->{loc}->N("GPLv2"), - description => $self->{loc}->N("mpan is the mana-tools panel that collects all the utilities."), - authors => $self->{loc}->N("

Developers

-
  • %s
  • -
  • %s
  • -
-

Translators

-
  • %s
", - "Angelo Naselli <anaselli\@linux.it>", - "Matteo Pasotti <matteo.pasotti\@gmail.com>", - $translators - ), - - }); -} - - - -## Begin the program event loop -sub start { - my ($self) = shift; - my $reqExit = 0; - - ##Default category selection - if (!$self->{currCategory}) { - $self->{currCategory} = @{$self->{categories}}[0]; - } - $self->{currCategory}->addButtons($self->{rightPane}, $self->{factory}); - $self->{rightPaneFrame}->setLabel($self->{currCategory}->{name}); - $self->{factory}->createSpacing($self->{rightPane}, 1, 1, 1.0 ); - my $launch = 0; - while(!$launch) { - - ## Grab Event - $self->{event} = $self->{mainWin}->waitForEvent(); - my $eventType = $self->{event}->eventType(); - - ## Check for window close - if ($eventType == $yui::YEvent::CancelEvent) { - last; - } - elsif ($eventType == $yui::YEvent::MenuEvent) { - ### MENU ### - my $item = $self->{event}->item(); - my $menuLabel = $item->label(); - if ($menuLabel eq $self->{menus}->{file}->{ quit }->label()) { - ## quit menu item - last; - } - elsif ($menuLabel eq $self->{menus}->{help}->{ about }->label()) { - $self->_showAboutDialog(); - } - elsif ($menuLabel eq $self->{menus}->{help}->{ help }->label()) { - # TODO Help - } - } - elsif ($eventType == $yui::YEvent::WidgetEvent) { - my $widget = $self->{event}->widget(); - - ## Check for Exit button push or menu - if($widget == $self->{exitButton}) { - last; - } - elsif ($widget == $self->{aboutButton}) { - $self->_showAboutDialog(); - } - else { - # category button selected? - my $isCat = $self->_categorySelected($widget); - if (!$isCat) { - # module button selected? - $launch = $self->_moduleSelected($widget); - } - } - } - } - - return $launch; -} - -#============================================================= - -=head2 destroy - -=head3 INPUT - - $self: this object - -=head3 DESCRIPTION - - This method destroyes the main window and all the - relevanto bojects (category and modules buttons). - -=cut - -#============================================================= -sub destroy { - my ($self) = shift; - - $self->{mainWin}->destroy(); - for (my $cat=0; $cat < scalar(@{$self->{categories}}); $cat++ ) { - @{$self->{categories}}[$cat]->{button} = 0; - @{$self->{categories}}[$cat]->removeButtons(); - } -} - -#============================================================= - -=head2 setupGui - -=head3 INPUT - - $self: this object - -=head3 DESCRIPTION - - This method load configuration and build the GUI layout. - -=cut - -#============================================================= -sub setupGui { - my ($self) = shift; - - $self->_loadSettings(); - yui::YUILog::setLogFileName($self->{settings}->{log}) if defined($self->{settings}->{log}); - $self->{name} = $self->{settings}->{title}; - yui::YUI::app()->setApplicationTitle($self->{name}); - my $icon = defined($self->{settings}->{icon}) ? - $self->{settings}->{icon} : - File::ShareDir::dist_file(ManaTools::Shared::distName(), 'images/mageia.png'); - - yui::YUI::app()->setApplicationIcon($icon); - - $self->{factory} = yui::YUI::widgetFactory; - $self->{mainWin} = $self->{factory}->createMainDialog; - - $self->{mainLayout} = $self->{factory}->createVBox($self->{mainWin}); - $self->{menuLayout} = $self->{factory}->createHBox($self->{mainLayout}); - - ## Menu File - my $align = $self->{factory}->createAlignment($self->{menuLayout}, 1, 0); - $self->{menus}->{file} = { - widget => $self->{factory}->createMenuButton($align, $self->{loc}->N("File")), - quit => new yui::YMenuItem($self->{loc}->N("&Quit")), - }; - - my @ordered_menu_lines = qw(quit); - foreach (@ordered_menu_lines) { - $self->{menus}->{file}->{ widget }->addItem($self->{menus}->{file}->{ $_ }); - } - $self->{menus}->{file}->{ widget }->rebuildMenuTree(); - - $align = $self->{factory}->createAlignment($self->{menuLayout}, 2, 0); - $self->{menus}->{help} = { - widget => $self->{factory}->createMenuButton($align, $self->{loc}->N("Help")), - help => new yui::YMenuItem($self->{loc}->N("Help")), - about => new yui::YMenuItem($self->{loc}->N("&About")), - }; - - ## Menu Help - @ordered_menu_lines = qw(help about); - foreach (@ordered_menu_lines) { - $self->{menus}->{help}->{ widget }->addItem($self->{menus}->{help}->{ $_ }); - } - $self->{menus}->{help}->{ widget }->rebuildMenuTree(); - - $self->{layout} = $self->{factory}->createHBox($self->{mainLayout}); - - #create left Panel Frame no need to add a label for title - $self->{leftPaneFrame} = $self->{factory}->createFrame($self->{layout}, $self->{settings}->{category_title}); - #create right Panel Frame no need to add a label for title (use setLabel when module changes) - $self->{rightPaneFrame} = $self->{factory}->createFrame($self->{layout}, ""); - #create replace point for dynamically created widgets - $self->{replacePoint} = $self->{factory}->createReplacePoint($self->{rightPaneFrame}); - - $self->{rightPane} = $self->{factory}->createVBox($self->{replacePoint}); - $self->{leftPane} = $self->{factory}->createVBox($self->{leftPaneFrame}); - - #logo from settings - my $logofile = defined($self->{settings}->{logo}) ? - $self->{settings}->{logo} : - File::ShareDir::dist_file(ManaTools::Shared::distName(), 'images/logo_mageia.png'); - - my $logo = $self->{factory}->createImage($self->{leftPane}, $logofile); - $logo->setAutoScale(1); - -# $self->{leftPaneFrame}->setWeight(0, 1); - $self->{rightPaneFrame}->setWeight(0, 2); - - $self->_loadCategories(); - $self->{factory}->createVStretch($self->{leftPane}); - - $self->{aboutButton} = $self->{factory}->createPushButton($self->{leftPane}, "&About"); - $self->{aboutButton}->setStretchable(0, 1); - - $self->{exitButton} = $self->{factory}->createPushButton($self->{leftPane}, "&Quit"); - my $quitIcon = File::ShareDir::dist_file(ManaTools::Shared::distName(), 'images/quit.png'); - $self->{exitButton}->setIcon($quitIcon); - $self->{exitButton}->setStretchable(0, 1); -} - - -## internal methods - -## Check if event is from current Category View -## If icon click, returns the module to be launched - -sub _moduleSelected { - my ($self, $selectedWidget) = @_; - - for(@{$self->{currCategory}->{modules}}) { - if( $_->{button} == $selectedWidget ){ - return $_; - } - } - return 0; -} - - -## Discover if a category button was selected. -## If category button is selected, sets right panel to display -## the selected Category Modules -## returns 1 if category button is selected -sub _categorySelected { - my ($self, $selectedWidget) = @_; - for (@{$self->{categories}}) { - if( $_->{button} == $selectedWidget ) { - - #if current is already set then skips - if ($self->{currCategory} == $_) { - ## returns 1 to skip any other checks on - ## the selected widget - return 1; - } - ## Menu item selected, set right pane - $self->{mainWin}->startMultipleChanges(); - ## Remove existing modules - $self->{replacePoint}->deleteChildren(); - $self->{rightPane} = $self->{factory}->createVBox($self->{replacePoint}); - - ## Change Current Category to the selected one - $self->{currCategory} = $_; - ## Add new Module Buttons to Right Pane - $self->{currCategory}->addButtons($self->{rightPane}, $self->{factory}); - $self->{rightPaneFrame}->setLabel($self->{currCategory}->{name}); - $self->{factory}->createSpacing($self->{rightPane}, 1, 1, 1.0 ); - $self->{replacePoint}->showChild(); - $self->{mainWin}->recalcLayout(); - $self->{mainWin}->doneMultipleChanges(); - - return 1; - } - } - - return 0; -} - -## adpanel settings -sub _loadSettings { - my ($self, $force_load) = @_; - # configuration file name - my $fileName = "$self->{confDir}/settings.conf"; - die "Configuration file missing" if (! -e $fileName); - if (!$self->{settings} || $force_load) { - $self->{settings} = new ManaTools::SettingsReader($fileName); - } -} - -#============================================================= -# _categoryLoaded -# -# INPUT -# -# $self: this object -# $category: category to look for -# -# OUTPUT -# -# $present: category is present or not -# -# DESCRIPTION -# -# This method looks for the given category and if already in -# returns true. -# -#============================================================= -sub _categoryLoaded { - my ($self, $category) = @_; - my $present = 0; - - if (!$category) { - return $present; - } - - foreach my $cat (@{$self->{categories}}) { - if ($cat->{name} eq $category->{name}) { - $present = 1; - last; - } - } - - return $present; -} - -#============================================================= -# _getCategory -# -# INPUT -# -# $self: this object -# $name: category name -# -# OUTPUT -# -# $category: category object if exists -# -# DESCRIPTION -# -# This method looks for the given category name and returns -# the realte object. -#============================================================= -sub _getCategory { - my ($self, $name) = @_; - my $category = undef; - - foreach $category (@{$self->{categories}}) { - if ($category->{name} eq $name) { - return $category; - } - } - - return $category; -} - -# _loadCategory -# -# creates a new button representing a category -# -sub _loadCategory { - my ($self, $category) = @_; - - if (!$self->_categoryLoaded($category)) { - push ( @{$self->{categories}}, $category ); - - @{$self->{categories}}[-1]->{button} = $self->{factory}->createPushButton( - $self->{leftPane}, - $self->{categories}[-1]->{name} - ); - @{$self->{categories}}[-1]->setIcon(); - - @{$self->{categories}}[-1]->{button}->setStretchable(0, 1); - } - else { - for (my $cat=0; $cat < scalar(@{$self->{categories}}); $cat++ ) { - if( @{$self->{categories}}[$cat]->{name} eq $category->{name} && - !@{$self->{categories}}[$cat]->{button}) { - @{$self->{categories}}[$cat]->{button} = $self->{factory}->createPushButton( - $self->{leftPane}, - $self->{categories}[$cat]->{name} - ); - @{$self->{categories}}[$cat]->setIcon(); - @{$self->{categories}}[$cat]->{button}->setStretchable(0, 1); - last; - - } - } - } -} - -sub _loadCategories { - my ($self) = @_; - - # category files - my @categoryFiles; - my $fileName = "$self->{confDir}/categories.conf"; - - - # configuration file dir - my $directory = "$self->{confDir}/categories.conf.d"; - - push(@categoryFiles, $fileName); - push(@categoryFiles, <$directory/*.conf>); - my $currCategory; - - foreach $fileName (@categoryFiles) { - my $inFile = new ManaTools::ConfigReader($fileName); - my $tmpCat; - my $tmp; - my $hasNextCat = $inFile->hasNextCat(); - while( $hasNextCat ) { - $tmp = $inFile->getNextCat(); - $tmpCat = $self->_getCategory($tmp->{title}); - if (!$tmpCat) { - $tmpCat = new ManaTools::Category($tmp->{title}, $tmp->{icon}); - } - $self->_loadCategory($tmpCat); - $hasNextCat = $inFile->hasNextCat(); - $currCategory = $tmpCat; - - my $hasNextMod = $inFile->hasNextMod(); - while( $hasNextMod ) { - $tmp = $inFile->getNextMod(); - my $tmpMod; - my $loaded = 0; - - if (exists $tmp->{title}) { - if (not $currCategory->moduleLoaded($tmp->{title})) { - $tmpMod = ManaTools::Module->create(name => $tmp->{title}, - icon => $tmp->{icon}, - launch => $tmp->{launcher} - ); - } - } - elsif (exists $tmp->{class}) { - if (not $currCategory->moduleLoaded(-CLASS => $tmp->{class})) { - $tmpMod = ManaTools::Module->create(-CLASS => $tmp->{class}); - } - } - if ($tmpMod) { - $loaded = $currCategory->loadModule($tmpMod); - undef $tmpMod if !$loaded; - } - $hasNextMod = $inFile->hasNextMod(); - } - } - } -} - -1; - -=pod - -=head2 start - - contains the main loop of the application - where we can check for events - -=head2 setupGui - - creates a popupDialog using a YUI::WidgetFactory - and then populate this dialog with some components - -=cut - diff --git a/lib/AdminPanel/Module.pm b/lib/AdminPanel/Module.pm deleted file mode 100644 index 1e13d92..0000000 --- a/lib/AdminPanel/Module.pm +++ /dev/null @@ -1,162 +0,0 @@ -# vim: set et ts=4 sw=4: -# Copyright 2012 Steven Tucker -# -# This file is part of ManaTools -# -# ManaTools is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. -# -# ManaTools 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 ManaTools. If not, see . - - -#Class Module -package ManaTools::Module; - -use Moose; - -=head1 VERSION - -Version 0.01 - -=cut - -our $VERSION = '1.0.0'; - -use yui; - -=head1 SUBROUTINES/METHODS - -=head2 create - returns a Module object such as a module - launcher (this object) or an extension of - this class - -=cut - -sub create { - my $class = shift; - $class = ref $class || $class; - my (%params) = @_; - - my $obj; - if ( exists $params{-CLASS} ) { - my $driver = $params{-CLASS}; - - eval { - my $pkg = $driver; - $pkg =~ s/::/\//g; - $pkg .= '.pm'; - require $pkg; - $obj=$driver->new(); - }; - if ( $@ ) { - die "Error getting obj for driver $params{-CLASS}: $@"; - return undef; - } - } - else { - $obj = new ManaTools::Module(@_); - } - return $obj; -} - -has 'icon' => ( - is => 'rw', - isa => 'Str', -); - -has 'name' => ( - is => 'rw', - isa => 'Str', -); - -has 'launch' => ( - is => 'rw', - isa => 'Str', -); - -has 'button' => ( - is => 'rw', - init_arg => undef, -); - - -#============================================================= - -=head2 setButton - -=head3 INPUT - -$self: this object -$button: yui push button to be assigned to this module - -=head3 DESCRIPTION - -This method assignes a button to this module - -=cut - -#============================================================= -sub setButton { - my ($self, $button) = @_; - $self->{button} = $button; -} - -#============================================================= - -=head2 removeButton - -=head3 INPUT - -$self: this object - -=head3 DESCRIPTION - -This method remove the assigned button from this module - -=cut - -#============================================================= -sub removeButton { - my($self) = @_; - - undef($self->{button}); -} - -# base class launcher -#============================================================= - -=head2 start - -=head3 INPUT - -$self: this object - -=head3 DESCRIPTION - -This method is the base class launcher, run external modules. - -=cut - -#============================================================= -sub start { - my $self = shift; - - if ($self->{launch}) { - my $err = yui::YUI::app()->runInTerminal( $self->{launch} . " --ncurses"); - if ($err == -1) { - system($self->{launch}); - } - } -} - - -no Moose; -1; diff --git a/lib/AdminPanel/Module/AdminMouse.pm b/lib/AdminPanel/Module/AdminMouse.pm deleted file mode 100644 index 279fb76..0000000 --- a/lib/AdminPanel/Module/AdminMouse.pm +++ /dev/null @@ -1,282 +0,0 @@ -# vim: set et ts=4 sw=4: -#***************************************************************************** -# -# Copyright (c) 2013 - 2015 Angelo Naselli -# 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{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 \nMatteo Pasotti ", - translator_credits => - #-PO: put here name(s) and email(s) of translator(s) (eg: "John Smith ") - 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/AdminPanel/Module/Clock.pm b/lib/AdminPanel/Module/Clock.pm deleted file mode 100644 index f2bb5c0..0000000 --- a/lib/AdminPanel/Module/Clock.pm +++ /dev/null @@ -1,518 +0,0 @@ -# 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 - -=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/\/\>\;/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("

Developers

-
  • %s
  • -
  • %s
  • -
-

Translators

-
  • %s
", - "Angelo Naselli <anaselli\@linux.it>", - $translators - ), - } - ); - } - } - } - $dialog->destroy(); - - #restore old application title - yui::YUI::app()->setApplicationTitle($appTitle) if $appTitle; -} - - - diff --git a/lib/AdminPanel/Module/DisplayManager.pm b/lib/AdminPanel/Module/DisplayManager.pm deleted file mode 100644 index 39aa617..0000000 --- a/lib/AdminPanel/Module/DisplayManager.pm +++ /dev/null @@ -1,298 +0,0 @@ -# vim: set et ts=4 sw=4: -#***************************************************************************** -# -# Copyright (c) 2013-2015 Matteo Pasotti -# -# 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 <matteo.pasotti\@gmail.com>" - } - ); - }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/AdminPanel/Module/Firewall.pm b/lib/AdminPanel/Module/Firewall.pm deleted file mode 100644 index 2ac56a5..0000000 --- a/lib/AdminPanel/Module/Firewall.pm +++ /dev/null @@ -1,1208 +0,0 @@ -# vim: set et ts=4 sw=4: -#***************************************************************************** -# -# Copyright (c) 2013-2015 Matteo Pasotti -# -# 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 <matteo.pasotti\@gmail.com>" - }; -} - -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 %s", $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/AdminPanel/Module/Hosts.pm b/lib/AdminPanel/Module/Hosts.pm deleted file mode 100644 index faae3f0..0000000 --- a/lib/AdminPanel/Module/Hosts.pm +++ /dev/null @@ -1,530 +0,0 @@ -# vim: set et ts=4 sw=4: -#***************************************************************************** -# -# Copyright (c) 2013-2015 Matteo Pasotti -# -# 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 <matteo.pasotti\@gmail.com>" - } - ); - }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/AdminPanel/Module/LogViewer.pm b/lib/AdminPanel/Module/LogViewer.pm deleted file mode 100644 index e009c1c..0000000 --- a/lib/AdminPanel/Module/LogViewer.pm +++ /dev/null @@ -1,568 +0,0 @@ -# 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 - -=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/\/\>\;/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("

Developers

-
  • %s
  • -
  • %s
  • -
-

Translators

-
  • %s
", - "Angelo Naselli <anaselli\@linux.it>", - "Matteo Pasotti <matteo.pasotti\@gmail.com>", - $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/AdminPanel/Module/Proxy.pm b/lib/AdminPanel/Module/Proxy.pm deleted file mode 100644 index ff2af3e..0000000 --- a/lib/AdminPanel/Module/Proxy.pm +++ /dev/null @@ -1,396 +0,0 @@ -# vim: set et ts=4 sw=4: -#***************************************************************************** -# -# Copyright (c) 2013-2015 Matteo Pasotti -# -# 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 the string with the list of the excluded domains/addresses - -=item B the url of the http proxy - -=item B the url of the https proxy - -=item B 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 <matteo.pasotti\@gmail.com>" - } - ); - }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/AdminPanel/Module/Services.pm b/lib/AdminPanel/Module/Services.pm deleted file mode 100644 index dca0c0c..0000000 --- a/lib/AdminPanel/Module/Services.pm +++ /dev/null @@ -1,588 +0,0 @@ -# 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 - -=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/\/\>\;/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("

Developers

-
  • %s
  • -
  • %s
  • -
-

Translators

-
  • %s
", - "Angelo Naselli <anaselli\@linux.it>", - "Matteo Pasotti <matteo.pasotti\@gmail.com>", - $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/AdminPanel/Module/Users.pm b/lib/AdminPanel/Module/Users.pm deleted file mode 100644 index 2ef9066..0000000 --- a/lib/AdminPanel/Module/Users.pm +++ /dev/null @@ -1,2637 +0,0 @@ -# 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 - -=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/\/\>\;/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("

Developers

-
  • %s
  • -
  • %s
  • -
-

Translators

-
  • %s
", - "Angelo Naselli <anaselli\@linux.it>", - "Matteo Pasotti <matteo.pasotti\@gmail.com>", - $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; diff --git a/lib/AdminPanel/Privileges.pm b/lib/AdminPanel/Privileges.pm deleted file mode 100644 index 5833900..0000000 --- a/lib/AdminPanel/Privileges.pm +++ /dev/null @@ -1,61 +0,0 @@ -# vim: set et ts=4 sw=4: -# Copyright 2012-2015 Matteo Pasotti -# -# This file is part of ManaTools -# -# ManaTools is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. -# -# ManaTools 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 ManaTools. If not, see . - -package ManaTools::Privileges; - -use strict; -use warnings; -use diagnostics; -require Exporter; -use base qw(Exporter); -use English qw(-no_match_vars); - -our @EXPORT = qw(is_root_capability_required - ask_for_authentication); - -my $wrappers = { "sudo" => "/usr/bin/sudo", - "pkit" => "/usr/bin/pkexec", - "chlp" => "/usr/bin/consolehelper" - }; - -my $wrapper = 0; - -sub is_root_capability_required { - return $EUID != 0; -} - -sub ask_for_authentication { - my $wrapper_id = shift; - $wrapper = $wrappers->{$wrapper_id} if(defined($wrappers->{$wrapper_id})); - my ($command, @args) = wrap_command($0, @ARGV); - unshift(@args,$command->[1]); - unshift(@args, '-n') if($wrapper_id eq "sudo"); # let sudo die if password is needed - exec { $command->[0] } $command->[1], @args or die ("command %s missing", $command->[0]); -} - -sub wrap_command { - my ($app, @args) = @_; - return ([$wrapper, $app], @args); -} - -sub get_wrapper { - my $id = shift; - return $wrappers->{$id} if(defined($wrappers->{$id})); -} - -1; diff --git a/lib/AdminPanel/Rpmdragora/.perl_checker b/lib/AdminPanel/Rpmdragora/.perl_checker deleted file mode 100644 index 202e053..0000000 --- a/lib/AdminPanel/Rpmdragora/.perl_checker +++ /dev/null @@ -1 +0,0 @@ -Basedir .. diff --git a/lib/AdminPanel/Rpmdragora/edit_urpm_sources.pm b/lib/AdminPanel/Rpmdragora/edit_urpm_sources.pm deleted file mode 100644 index c756964..0000000 --- a/lib/AdminPanel/Rpmdragora/edit_urpm_sources.pm +++ /dev/null @@ -1,2243 +0,0 @@ -# vim: set et ts=4 sw=4: -package ManaTools::Rpmdragora::edit_urpm_sources; -#***************************************************************************** -# -# Copyright (c) 2002 Guillaume Cottenceau -# Copyright (c) 2002-2007 Thierry Vignaud -# Copyright (c) 2002-2007 Mandriva Linux -# 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. -# -#***************************************************************************** -# -# $Id: edit_urpm_sources.pm 266598 2010-03-03 12:00:58Z tv $ - - -use strict; -use File::ShareDir ':ALL'; -use File::HomeDir qw(home); - -use MDK::Common::Func qw(if_ each_index); -use MDK::Common::Math qw(max); -use MDK::Common::File qw(cat_ output); -use MDK::Common::DataStructure qw(member put_in_hash uniq); -use MDK::Common::Various qw(to_bool); - -use ManaTools::Shared; -use ManaTools::Shared::Locales; -use ManaTools::rpmdragora; -use ManaTools::Rpmdragora::init; -use ManaTools::Rpmdragora::open_db; -use ManaTools::Rpmdragora::formatting; -use ManaTools::Shared::GUI; -use URPM::Signature; -use urpm::media; -use urpm::download; -use urpm::lock; - -use Exporter; -our @ISA = qw(Exporter); -our @EXPORT_OK = qw(run); - - -my $urpm; -my ($mainw, $list_tv, $something_changed); - -my %col = ( - mainw => { - is_enabled => 0, - is_update => 1, - type => 2, - name => 3, - activatable => 4 - }, -); - -my $loc = ManaTools::rpmdragora::locale(); - -sub get_medium_type { - my ($medium) = @_; - my %medium_type = ( - cdrom => $loc->N("CD-ROM"), - ftp => $loc->N("FTP"), - file => $loc->N("Local"), - http => $loc->N("HTTP"), - https => $loc->N("HTTPS"), - nfs => $loc->N("NFS"), - removable => $loc->N("Removable"), - rsync => $loc->N("rsync"), - ssh => $loc->N("NFS"), - ); - return $loc->N("Mirror list") if $medium->{mirrorlist}; - return $medium_type{$1} if $medium->{url} =~ m!^([^:]*)://!; - return $loc->N("Local"); -} - -sub selrow { - my ($o_list_tv) = @_; - defined $o_list_tv or $o_list_tv = $list_tv; - my ($model, $iter) = $o_list_tv->get_selection->get_selected; - $model && $iter or return -1; - my $path = $model->get_path($iter); - my $row = $path->to_string; - return $row; -} - -sub selected_rows { - my ($o_list_tv) = @_; - defined $o_list_tv or $o_list_tv = $list_tv; - my (@rows) = $o_list_tv->get_selection->get_selected_rows; - return -1 if @rows == 0; - map { $_->to_string } @rows; -} - -sub remove_row { - my ($model, $path_str) = @_; - my $iter = $model->get_iter_from_string($path_str); - $iter or return; - $model->remove($iter); -} - -sub remove_from_list { - my ($list, $list_ref, $model) = @_; - my $row = selrow($list); - if ($row != -1) { - splice @$list_ref, $row, 1; - remove_row($model, $row); - } - -} - -sub _want_base_distro() { - $::expert && distro_type(0) eq 'updates' ? interactive_msg( - $loc->N("Choose media type"), - $loc->N("In order to keep your system secure and stable, you must at a minimum set up -sources for official security and stability updates. You can also choose to set -up a fuller set of sources which includes the complete official Mageia -repositories, giving you access to more software than can fit on the Mageia -discs. Please choose whether to configure update sources only, or the full set -of sources." - ), - transient => $::main_window, - yesno => 1, text => { yes => $loc->N("Full set of sources"), no => $loc->N("Update sources only") }, - ) : 1; -} - -sub easy_add_callback_with_mirror() { - # when called on early init by rpmdragora - $urpm ||= fast_open_urpmi_db(); - - #- cooker and community don't have update sources - my $want_base_distro = _want_base_distro(); - defined $want_base_distro or return 0; - my $distro = $ManaTools::rpmdragora::mageia_release; - my ($mirror) = choose_mirror($urpm, message => - $loc->N("This will attempt to install all official sources corresponding to your -distribution (%s).\n -I need to contact the Mageia website to get the mirror list. -Please check that your network is currently running.\n -Is it ok to continue?", $distro), - transient => $::main_window, - ) or return 0; - ref $mirror or return 0; - my $wait = wait_msg($loc->N("Please wait, adding media...")); - add_distrib_update_media($urpm, $mirror, if_(!$want_base_distro, only_updates => 1)); - $offered_to_add_sources->[0] = 1; - remove_wait_msg($wait); - return 1; -} - -sub easy_add_callback() { - # when called on early init by rpmdragora - $urpm ||= fast_open_urpmi_db(); - - #- cooker and community don't have update sources - my $want_base_distro = _want_base_distro(); - defined $want_base_distro or return 0; - warn_for_network_need(undef, transient => $::main_window) or return 0; - my $wait = wait_msg($loc->N("Please wait, adding media...")); - add_distrib_update_media($urpm, undef, if_(!$want_base_distro, only_updates => 1)); - $offered_to_add_sources->[0] = 1; - remove_wait_msg($wait); - return 1; -} - -## Internal routine that builds input fields needed to manage -## the selected media type to be added -## return HASH reference with the added widgets -sub _build_add_dialog { - my $options = shift; - - die "replace point is needed" if !defined ($options->{replace_pnt}); - die "dialog is needed" if !defined ($options->{dialog}); - die "selected item is needed" if !defined ($options->{selected}); - die "media info is needed" if !defined ($options->{info}); - - my %widgets; - my $factory = yui::YUI::widgetFactory; - - $options->{dialog}->startMultipleChanges(); - $options->{replace_pnt}->deleteChildren(); - - # replace widgets - my $vbox = $factory->createVBox( $options->{replace_pnt} ); - my $hbox = $factory->createHBox($vbox); - $factory->createHSpacing($hbox, 1.0); - my $label = $factory->createLabel($hbox, - $options->{info}->{$options->{selected}}->{url} - ); - - $factory->createHSpacing($hbox, 3.0); - $widgets{url} = $factory->createInputField($hbox, "", 0); - $widgets{url}->setWeight($yui::YD_HORIZ, 2); - if (defined($options->{info}->{$options->{selected}}->{dirsel})) { - $widgets{dirsel} = $factory->createPushButton($hbox, $loc->N("Browse...")); - } - elsif (defined($options->{info}->{$options->{selected}}->{loginpass})) { - $hbox = $factory->createHBox($vbox); - $factory->createHSpacing($hbox, 1.0); - $label = $factory->createLabel($hbox, $loc->N("Login:") ); - $factory->createHSpacing($hbox, 1.0); - $widgets{login} = $factory->createInputField($hbox, "", 0); - $label->setWeight($yui::YD_HORIZ, 1); - $widgets{login}->setWeight($yui::YD_HORIZ, 3); - $hbox = $factory->createHBox($vbox); - $factory->createHSpacing($hbox, 1.0); - $label = $factory->createLabel($hbox, $loc->N("Password:") ); - $factory->createHSpacing($hbox, 1.0); - $widgets{pass} = $factory->createInputField($hbox, "", 1); - $label->setWeight($yui::YD_HORIZ, 1); - $widgets{pass}->setWeight($yui::YD_HORIZ, 3); - - } - # recalc layout - $options->{replace_pnt}->showChild(); - $options->{dialog}->recalcLayout(); - $options->{dialog}->doneMultipleChanges(); - - return \%widgets; -} - -sub add_callback() { - - my $retVal = 0; - - my $appTitle = yui::YUI::app()->applicationTitle(); - ## set new title to get it in dialog - yui::YUI::app()->setApplicationTitle($loc->N("Add a medium")); - - my $factory = yui::YUI::widgetFactory; - - my $dialog = $factory->createPopupDialog(); - my $minSize = $factory->createMinSize( $dialog, 60, 5 ); - my $vbox = $factory->createVBox( $minSize ); - - $factory->createVSpacing($vbox, 0.5); - - my $hbox = $factory->createHBox( $factory->createLeft($vbox) ); - $factory->createHeading($hbox, $loc->N("Adding a medium:")); - $factory->createVSpacing($vbox, 0.5); - - $hbox = $factory->createHBox($vbox); - $factory->createHSpacing($hbox, 1.0); - my $label = $factory->createLabel($hbox, $loc->N("Type of medium:") ); - my $media_type = $factory->createComboBox($hbox, "", 0); - $media_type->setWeight($yui::YD_HORIZ, 2); - - my %radios_infos = ( - local => { name => $loc->N("Local files"), url => $loc->N("Medium path:"), dirsel => 1 }, - ftp => { name => $loc->N("FTP server"), url => $loc->N("URL:"), loginpass => 1 }, - rsync => { name => $loc->N("RSYNC server"), url => $loc->N("URL:") }, - http => { name => $loc->N("HTTP server"), url => $loc->N("URL:") }, - removable => { name => $loc->N("Removable device (CD-ROM, DVD, ...)"), - url => $loc->N("Path or mount point:"), dirsel => 1 }, - ); - my @radios_names_ordered = qw(local ftp rsync http removable); - - my $itemColl = new yui::YItemCollection; - foreach my $elem (@radios_names_ordered) { - my $it = new yui::YItem($radios_infos{$elem}->{'name'}, 0); - if ($elem eq $radios_names_ordered[0]) { - $it->setSelected(1); - } - $itemColl->push($it); - $it->DISOWN(); - } - $media_type->addItems($itemColl); - $media_type->setNotify(1); - - $hbox = $factory->createHBox($vbox); - $factory->createHSpacing($hbox, 1.0); - $label = $factory->createLabel($hbox, $loc->N("Medium name:") ); - $factory->createHSpacing($hbox, 1.0); - my $media_name = $factory->createInputField($hbox, "", 0); - $media_name->setWeight($yui::YD_HORIZ, 2); - - # per function layout (replace point) - my $align = $factory->createLeft($vbox); - my $replace_pnt = $factory->createReplacePoint($align); - - my $add_widgets = _build_add_dialog({replace_pnt => $replace_pnt, dialog => $dialog, - info => \%radios_infos, selected => $radios_names_ordered[0]} - ); - # check-boxes - $hbox = $factory->createHBox($factory->createLeft($vbox)); - $factory->createHSpacing($hbox, 1.3); - my $dist_media = $factory->createCheckBox($hbox, $loc->N("Create media for a whole distribution"), 0); - $hbox = $factory->createHBox($factory->createLeft($vbox)); - $factory->createHSpacing($hbox, 1.3); - my $update_media = $factory->createCheckBox($hbox, $loc->N("Tag this medium as an update medium"), 0); - $dist_media->setNotify(1); - - # Last line buttons - $factory->createVSpacing($vbox, 0.5); - $hbox = $factory->createHBox($vbox); - my $cancelButton = $factory->createPushButton($hbox, $loc->N("&Cancel")); - $factory->createHSpacing($hbox, 3.0); - my $okButton = $factory->createPushButton($hbox, $loc->N("&Ok")); - - $cancelButton->setDefaultButton(1); - - # dialog event loop - 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 - my $widget = $event->widget(); - if ($widget == $cancelButton) { - last; - } - elsif ($widget == $media_type) { - my $item = $media_type->selectedItem(); - my $sel = $item ? $item->index() : 0 ; - $add_widgets = _build_add_dialog({replace_pnt => $replace_pnt, dialog => $dialog, - info => \%radios_infos, selected => $radios_names_ordered[$sel]} - ); - } - elsif ($widget == $dist_media) { - $update_media->setEnabled(!$dist_media->value()); - } - elsif ($widget == $okButton) { - my $item = $media_type->selectedItem(); - my $sel = $item ? $item->index() : 0 ; - my $info = $radios_infos{$radios_names_ordered[$sel]}; - my $name = $media_name->value(); - my $url = $add_widgets->{url}->value(); - $name eq '' || $url eq '' and interactive_msg('rpmdragora', $loc->N("You need to fill up at least the two first entries.")), next; - if (member($name, map { $_->{name} } @{$urpm->{media}})) { - interactive_msg('rpmdragora', - $loc->N("There is already a medium called <%s>,\ndo you really want to replace it?", $name), - yesno => 1) or next; - } - - my %i = ( - name => $name, - url => $url, - distrib => $dist_media->value() ? 1 : 0, - update => $update_media->value() ? 1 : undef, - ); - my %make_url = ( - local => "file:/$i{url}", - http => $i{url}, - rsync => $i{url}, - removable => "removable:/$i{url}", - ); - $i{url} =~ s|^ftp://||; - $make_url{ftp} = sprintf "ftp://%s%s", - defined($add_widgets->{login}) - ? - $add_widgets->{login}->value() . ':' . ( $add_widgets->{pass}->value() ? - $add_widgets->{pass}->value() : - '') - : - '', - $i{url}; - - if ($i{distrib}) { - add_medium_and_check( - $urpm, - { nolock => 1, distrib => 1 }, - $i{name}, $make_url{$radios_names_ordered[$sel]}, probe_with => 'synthesis', update => $i{update}, - ); - } else { - if (member($i{name}, map { $_->{name} } @{$urpm->{media}})) { - urpm::media::select_media($urpm, $i{name}); - urpm::media::remove_selected_media($urpm); - } - add_medium_and_check( - $urpm, - { nolock => 1 }, - $i{name}, $make_url{$radios_names_ordered[$sel]}, $i{hdlist}, update => $i{update}, - ); - } - - $retVal = 1; - last; - } - else { - my $item = $media_type->selectedItem(); - my $sel = $item ? $item->index() : 0 ; - if (defined($radios_infos{$radios_names_ordered[$sel]}->{dirsel}) && - defined($add_widgets->{dirsel}) ) { - if ($widget == $add_widgets->{dirsel}) { - my $dir = yui::YUI::app()->askForExistingDirectory(home(), - $radios_infos{$radios_names_ordered[$sel]}->{url} - ); - $add_widgets->{url}->setValue($dir) if ($dir); - } - } - } - } - } -### End ### - - $dialog->destroy(); - - #restore old application title - yui::YUI::app()->setApplicationTitle($appTitle) if $appTitle; - - return $retVal; - -} - -sub options_callback() { - - my $appTitle = yui::YUI::app()->applicationTitle(); - ## set new title to get it in dialog - yui::YUI::app()->setApplicationTitle($loc->N("Global options for package installation")); - - my $factory = yui::YUI::widgetFactory; - - my $dialog = $factory->createPopupDialog(); - my $minSize = $factory->createMinSize( $dialog, 50, 5 ); - my $vbox = $factory->createVBox( $minSize ); - - my $hbox = $factory->createHBox($vbox); - $factory->createHSpacing($hbox, 1.0); - my $label = $factory->createLabel($hbox, $loc->N("Verify RPMs to be installed:") ); - $factory->createHSpacing($hbox, 3.5); - my $verify_rpm = $factory->createComboBox($hbox, "", 0); - $verify_rpm->setWeight($yui::YD_HORIZ, 2); - my @verif = ($loc->N("never"), $loc->N("always")); - my $verify_rpm_value = $urpm->{global_config}{'verify-rpm'} || 0; - - my $itemColl = new yui::YItemCollection; - my $cnt = 0; - foreach my $elem (@verif) { - my $it = new yui::YItem($elem, 0); - if ($cnt == $verify_rpm_value) { - $it->setSelected(1); - } - $itemColl->push($it); - $it->DISOWN(); - $cnt++; - } - $verify_rpm->addItems($itemColl); - - $hbox = $factory->createHBox($vbox); - $factory->createHSpacing($hbox, 1.0); - $label = $factory->createLabel($hbox, $loc->N("Download program to use:") ); - $factory->createHSpacing($hbox, 4.0); - my $downloader_entry = $factory->createComboBox($hbox, "", 0); - $downloader_entry->setWeight($yui::YD_HORIZ, 2); - - my @comboList = urpm::download::available_ftp_http_downloaders() ; - my $downloader = $urpm->{global_config}{downloader} || $comboList[0]; - - if (scalar(@comboList) > 0) { - $itemColl = new yui::YItemCollection; - foreach my $elem (@comboList) { - my $it = new yui::YItem($elem, 0); - if ($elem eq $downloader) { - $it->setSelected(1); - } - $itemColl->push($it); - $it->DISOWN(); - } - $downloader_entry->addItems($itemColl); - } - - $hbox = $factory->createHBox($vbox); - $factory->createHSpacing($hbox, 1.0); - $label = $factory->createLabel($hbox, $loc->N("XML meta-data download policy:") ); - my $xml_info_policy = $factory->createComboBox($hbox, "", 0); - $xml_info_policy->setWeight($yui::YD_HORIZ, 2); - - my @xml_info_policies = ('', 'never', 'on-demand', 'update-only', 'always'); - my @xml_info_policiesL = ('', $loc->N("Never"), $loc->N("On-demand"), $loc->N("Update-only"), $loc->N("Always")); - my $xml_info_policy_value = $urpm->{global_config}{'xml-info'}; - - $itemColl = new yui::YItemCollection; - $cnt = 0; - foreach my $elem (@xml_info_policiesL) { - my $it = new yui::YItem($elem, 0); - if ($xml_info_policy_value && $xml_info_policy_value eq $xml_info_policies[$cnt]) { - $it->setSelected(1); - } - $itemColl->push($it); - $it->DISOWN(); - $cnt++; - } - $xml_info_policy->addItems($itemColl); - - ### TODO tips ### - #tip => - #join("\n", - #$loc->N("For remote media, specify when XML meta-data (file lists, changelogs & information) are downloaded."), - #'', - #$loc->N("Never"), - #$loc->N("For remote media, XML meta-data are never downloaded."), - #'', - #$loc->N("On-demand"), - #$loc->N("(This is the default)"), - #$loc->N("The specific XML info file is downloaded when clicking on package."), - #'', - #$loc->N("Update-only"), - #$loc->N("Updating media implies updating XML info files already required at least once."), - #'', - #$loc->N("Always"), - #$loc->N("All XML info files are downloaded when adding or updating media."), - - $factory->createVSpacing($vbox, 0.5); - - - ### last line buttons - $factory->createVSpacing($vbox, 0.5); - $hbox = $factory->createHBox($vbox); - my $cancelButton = $factory->createPushButton($hbox, $loc->N("&Cancel")); - $factory->createHSpacing($hbox, 3.0); - my $okButton = $factory->createPushButton($hbox, $loc->N("&Ok")); - - $cancelButton->setDefaultButton(1); - - # dialog event loop - 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 - my $widget = $event->widget(); - if ($widget == $cancelButton) { - last; - } - elsif ($widget == $okButton) { - my $changed = 0; - my $item = $verify_rpm->selectedItem(); - if ($item->index() != $verify_rpm_value) { - $changed = 1; - $urpm->{global_config}{'verify-rpm'} = $item->index(); - } - $item = $downloader_entry->selectedItem(); - if ($item->label() ne $downloader) { - $changed = 1; - $urpm->{global_config}{downloader} = $item->label(); - } - $item = $xml_info_policy->selectedItem(); - if ($xml_info_policies[$item->index()] ne $xml_info_policy_value) { - $changed = 1; - $urpm->{global_config}{'xml-info'} = $xml_info_policies[$item->index()]; - } - if ($changed) { - urpm::media::write_config($urpm); - $urpm = fast_open_urpmi_db(); - } - - last; - } - } - } - - ### End ### - - $dialog->destroy(); - - #restore old application title - yui::YUI::app()->setApplicationTitle($appTitle) if $appTitle; - -} - -#============================================================= - -=head2 remove_callback - -=head3 INPUT - -$selection: YItemCollection (selected items) - - -=head3 DESCRIPTION - -Remove the selected medias - -=cut - -#============================================================= - -sub remove_callback { - my $selection = shift; - - my @rows; - for (my $it = 0; $it < $selection->size(); $it++) { - my $item = $selection->get($it); - push @rows, $item->index(); - } - @rows == 0 and return 0; - interactive_msg( - $loc->N("Source Removal"), - @rows == 1 ? - $loc->N("Are you sure you want to remove source \"%s\"?", $urpm->{media}[$rows[0]]{name}) : - $loc->N("Are you sure you want to remove the following sources?") . "\n\n" . - format_list(map { $urpm->{media}[$_]{name} } @rows), - yesno => 1, scroll => 1, - ) or return 0; - - my $wait = wait_msg($loc->N("Please wait, removing medium...")); - foreach my $row (reverse(@rows)) { - $something_changed = 1; - urpm::media::remove_media($urpm, [ $urpm->{media}[$row] ]); - } - urpm::media::write_urpmi_cfg($urpm); - remove_wait_msg($wait); - - return 1; -} - - -#============================================================= - -=head2 upwards_callback - -=head3 INPUT - -$table: Mirror table (YTable) - -=head3 DESCRIPTION - -Move selected item to high priority level - -=cut - -#============================================================= -sub upwards_callback { - my $table = shift; - - ## get the first - my $item = $table->selectedItem(); - !$item and return 0; - return 0 if ($item->index() == 0); - my $row = $item->index(); - my @media = ( $urpm->{media}[$row-1], $urpm->{media}[$row]); - $urpm->{media}[$row] = $media[0]; - $urpm->{media}[$row-1] = $media[1]; - - urpm::media::write_config($urpm); - $urpm = fast_open_urpmi_db(); - return $row - 1; -} - -#============================================================= - -=head2 downwards_callback - -=head3 INPUT - -$table: Mirror table (YTable) - -=head3 DESCRIPTION - -Move selected item to low priority level - -=cut - -#============================================================= -sub downwards_callback { - my $table = shift; - - ## get the first - my $item = $table->selectedItem(); - !$item and return 0; - my $row = $item->index(); - return $row if ($row >= $table->itemsCount()-1); - - my @media = ( $urpm->{media}[$row], $urpm->{media}[$row+1]); - $urpm->{media}[$row+1] = $media[0]; - $urpm->{media}[$row] = $media[1]; - - urpm::media::write_config($urpm); - $urpm = fast_open_urpmi_db(); - return $row + 1; -} - -#- returns 1 if something changed to force readMedia() -sub edit_callback { - my $table = shift; - - my $changed = 0; - ## get the first - my $item = $table->selectedItem(); - !$item and return 0; - my $row = $item->index(); - - my $medium = $urpm->{media}[$row]; - my $config = urpm::cfg::load_config_raw($urpm->{config}, 1); - my ($verbatim_medium) = grep { $medium->{name} eq $_->{name} } @$config; - - my $appTitle = yui::YUI::app()->applicationTitle(); - ## set new title to get it in dialog - yui::YUI::app()->setApplicationTitle($loc->N("Edit a medium")); - - my $factory = yui::YUI::widgetFactory; - - my $dialog = $factory->createPopupDialog(); - my $minSize = $factory->createMinSize( $dialog, 80, 5 ); - my $vbox = $factory->createVBox( $minSize ); - - my $hbox = $factory->createHBox( $factory->createLeft($vbox) ); - $factory->createHeading($hbox, $loc->N("Editing medium \"%s\":", $medium->{name})); - $factory->createVSpacing($vbox, 1.0); - - $hbox = $factory->createHBox($vbox); - $factory->createHSpacing($hbox, 1.0); - my $label = $factory->createLabel($hbox, $loc->N("URL:")); - my $url_entry = $factory->createInputField($hbox, "", 0); - $url_entry->setWeight($yui::YD_HORIZ, 2); - $url_entry->setValue($verbatim_medium->{url} || $verbatim_medium->{mirrorlist}); - - $hbox = $factory->createHBox($vbox); - $factory->createHSpacing($hbox, 1.0); - $label = $factory->createLabel($hbox, $loc->N("Downloader:") ); - my $downloader_entry = $factory->createComboBox($hbox, "", 0); - $downloader_entry->setWeight($yui::YD_HORIZ, 2); - - my @comboList = urpm::download::available_ftp_http_downloaders() ; - my $downloader = $verbatim_medium->{downloader} || $urpm->{global_config}{downloader} || $comboList[0]; - - if (scalar(@comboList) > 0) { - my $itemColl = new yui::YItemCollection; - foreach my $elem (@comboList) { - my $it = new yui::YItem($elem, 0); - if ($elem eq $downloader) { - $it->setSelected(1); - } - $itemColl->push($it); - $it->DISOWN(); - } - $downloader_entry->addItems($itemColl); - } - $factory->createVSpacing($vbox, 0.5); - - my $url = $url_entry->value(); - - $hbox = $factory->createHBox($factory->createLeft($vbox)); - $factory->createHSpacing($hbox, 1.0); - - my $tableItem = yui::toYTableItem($item); - # enabled cell 0, updates cell 1 - my $cellEnabled = $tableItem->cell(0)->label() ? 1 : 0; - my $enabled = $factory->createCheckBox($hbox, $loc->N("Enabled"), $cellEnabled); - my $cellUpdates = $tableItem->cell(1)->label() ? 1 : 0; - my $update = $factory->createCheckBox($hbox, $loc->N("Updates"), $cellUpdates); - $update->setDisabled() if (!$::expert); - - $factory->createVSpacing($vbox, 0.5); - $hbox = $factory->createHBox($vbox); - my $cancelButton = $factory->createPushButton($hbox, $loc->N("&Cancel")); - $factory->createHSpacing($hbox, 3.0); - my $saveButton = $factory->createPushButton($hbox, $loc->N("&OK")); - $factory->createHSpacing($hbox, 3.0); - my $proxyButton = $factory->createPushButton($hbox, $loc->N("&Proxy...")); - - $cancelButton->setDefaultButton(1); - - # dialog event loop - 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 - my $widget = $event->widget(); - if ($widget == $cancelButton) { - last; - } - elsif ($widget == $saveButton) { - if ($cellEnabled != $enabled->value()) { - $urpm->{media}[$row]{ignore} = !$urpm->{media}[$row]{ignore} || undef; - $changed = 1; - } - if ($cellUpdates != $update->value()) { - $urpm->{media}[$row]{update} = !$urpm->{media}[$row]{update} || undef; - $changed = 1; - } - if ( $changed ) { - urpm::media::write_config($urpm); - } - - my ($m_name, $m_update) = map { $medium->{$_} } qw(name update); - # TODO check if really changed first - $url = $url_entry->value(); - $downloader = $downloader_entry->value(); - $url =~ m|^removable://| and ( - interactive_msg( - $loc->N("You need to insert the medium to continue"), - $loc->N("In order to save the changes, you need to insert the medium in the drive."), - yesno => 1, text => { yes => $loc->N("Ok"), no => $loc->N("Cancel") } - ) or return 0 - ); - my $saved_proxy = urpm::download::get_proxy($m_name); - undef $saved_proxy if !defined $saved_proxy->{http_proxy} && !defined $saved_proxy->{ftp_proxy}; - urpm::media::select_media($urpm, $m_name); - if (my ($media) = grep { $_->{name} eq $m_name } @{$urpm->{media}}) { - MDK::Common::DataStructure::put_in_hash($media, { - ($verbatim_medium->{mirrorlist} ? 'mirrorlist' : 'url') => $url, - name => $m_name, - if_($m_update && $m_update ne $media->{update} || $m_update, update => $m_update), - if_($saved_proxy && $saved_proxy ne $media->{proxy} || $saved_proxy, proxy => $saved_proxy), - if_($downloader ne $media->{downloader} || $downloader, downloader => $downloader), - modified => 1, - }); - urpm::media::write_config($urpm); - update_sources_noninteractive($urpm, [ $m_name ]); - } else { - urpm::media::remove_selected_media($urpm); - add_medium_and_check($urpm, { nolock => 1, proxy => $saved_proxy }, $m_name, $url, undef, update => $m_update, if_($downloader, downloader => $downloader)); - } - last; - } - elsif ($widget == $proxyButton) { - proxy_callback($medium); - } - } - } -### End ### - - $dialog->destroy(); - - #restore old application title - yui::YUI::app()->setApplicationTitle($appTitle) if $appTitle; - - return $changed; -} - -sub update_callback() { - update_sources_interactive($urpm, transient => $::main_window, nolock => 1); -} - -#============================================================= - -=head2 proxy_callback - -=head3 INPUT - -$medium: the medium which proxy is going to be modified - -=head3 DESCRIPTION - -Set or change the proxy settings for the given media. -Note that Ok button saves the changes. - -=cut - -#============================================================= -sub proxy_callback { - my ($medium) = @_; - my $medium_name = $medium ? $medium->{name} : ''; - - my ($proxy, $proxy_user) = readproxy($medium_name); - my ($user, $pass) = $proxy_user =~ /^([^:]*):(.*)$/; - - my $appTitle = yui::YUI::app()->applicationTitle(); - ## set new title to get it in dialog - yui::YUI::app()->setApplicationTitle($loc->N("Configure proxies")); - - my $factory = yui::YUI::widgetFactory; - - my $dialog = $factory->createPopupDialog(); - my $minSize = $factory->createMinSize( $dialog, 80, 5 ); - my $vbox = $factory->createVBox( $minSize ); - - my $hbox = $factory->createHBox( $factory->createLeft($vbox) ); - $factory->createHeading($hbox, - $medium_name - ? $loc->N("Proxy settings for media \"%s\"", $medium_name) - : $loc->N("Global proxy settings")); - $factory->createVSpacing($vbox, 0.5); - - $hbox = $factory->createHBox($vbox); - $factory->createHSpacing($hbox, 1.0); - my $label = $factory->createLabel($hbox, $loc->N("If you need a proxy, enter the hostname and an optional port (syntax: ):")); - $factory->createVSpacing($vbox, 0.5); - - my ($proxybutton, $proxyentry, $proxyuserbutton, $proxyuserentry, $proxypasswordentry); - - $hbox = $factory->createHBox($factory->createLeft($vbox)); - $proxybutton = $factory->createCheckBoxFrame($hbox, $loc->N("Enable proxy"), 1); - my $frm_vbox = $factory->createVBox( $proxybutton ); - my $align = $factory->createRight($frm_vbox); - $hbox = $factory->createHBox($align); - $label = $factory->createLabel($hbox, $loc->N("Proxy hostname:") ); - $proxyentry = $factory->createInputField($hbox, "", 0); - $label->setWeight($yui::YD_HORIZ, 1); - $proxyentry->setWeight($yui::YD_HORIZ, 2); - $proxyuserbutton = $factory->createCheckBoxFrame($factory->createLeft($frm_vbox), - $loc->N("You may specify a username/password for the proxy authentication:"), 1); - $proxyentry->setValue($proxy) if $proxy; - - $frm_vbox = $factory->createVBox( $proxyuserbutton ); - - ## proxy user name - $align = $factory->createRight($frm_vbox); - $hbox = $factory->createHBox($align); - $label = $factory->createLabel($hbox, $loc->N("User:") ); - $proxyuserentry = $factory->createInputField($hbox, "", 0); - $label->setWeight($yui::YD_HORIZ, 1); - $proxyuserentry->setWeight($yui::YD_HORIZ, 2); - $proxyuserentry->setValue($user) if $user; - - ## proxy user password - $align = $factory->createRight($frm_vbox); - $hbox = $factory->createHBox($align); - $label = $factory->createLabel($hbox, $loc->N("Password:") ); - $proxypasswordentry = $factory->createInputField($hbox, "", 1); - $label->setWeight($yui::YD_HORIZ, 1); - $proxypasswordentry->setWeight($yui::YD_HORIZ, 2); - $proxypasswordentry->setValue($pass) if $pass; - - $proxyuserbutton->setValue ($proxy_user ? 1 : 0); - $proxybutton->setValue ($proxy ? 1 : 0); - - # dialog low level buttons - $factory->createVSpacing($vbox, 0.5); - $hbox = $factory->createHBox($vbox); - my $okButton = $factory->createPushButton($hbox, $loc->N("&Ok")); - $factory->createHSpacing($hbox, 3.0); - my $cancelButton = $factory->createPushButton($hbox, $loc->N("&Cancel")); - - $cancelButton->setDefaultButton(1); - - # dialog event loop - 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 - my $widget = $event->widget(); - if ($widget == $cancelButton) { - last; - } - elsif ($widget == $okButton) { - $proxy = $proxybutton->value() ? $proxyentry->value() : ''; - $proxy_user = $proxyuserbutton->value() - ? ($proxyuserentry->value() . ':' . $proxypasswordentry->value()) : ''; - - writeproxy($proxy, $proxy_user, $medium_name); - last; - } - } - } - -### End ### - $dialog->destroy(); - - #restore old application title - yui::YUI::app()->setApplicationTitle($appTitle) if $appTitle; - -} - -sub parallel_read_sysconf() { - my @conf; - foreach (MDK::Common::File::cat_('/etc/urpmi/parallel.cfg')) { - my ($name, $protocol, $command) = /([^:]+):([^:]+):(.*)/ or print STDERR "Warning, unrecognized line in /etc/urpmi/parallel.cfg:\n$_"; - my $medias = $protocol =~ s/\(([^\)]+)\)$// ? [ split /,/, $1 ] : []; - push @conf, { name => $name, protocol => $protocol, medias => $medias, command => $command }; - } - \@conf; -} - -sub parallel_write_sysconf { - my ($conf) = @_; - output '/etc/urpmi/parallel.cfg', - map { my $m = @{$_->{medias}} ? '(' . join(',', @{$_->{medias}}) . ')' : ''; - "$_->{name}:$_->{protocol}$m:$_->{command}\n" } @$conf; -} - -sub remove_parallel { - my ($num, $conf) = @_; - if ($num != -1) { - splice @$conf, $num, 1; - parallel_write_sysconf($conf); - } -} - -sub add_callback_ { - my ($title, $label, $mainw, $widget, $get_value, $check) = @_; - my $w = ugtk2->new($title, grab => 1, transient => $mainw->{real_window}); - local $::main_window = $w->{real_window}; - gtkadd( - $w->{window}, - gtkpack__( - gtknew('VBox', spacing => 5), - gtknew('Label', text => $label), - $widget, - gtknew('HSeparator'), - gtkpack( - gtknew('HButtonBox'), - gtknew('Button', text => $loc->N("Ok"), clicked => sub { $w->{retval} = 1; $get_value->(); Gtk2->main_quit }), - gtknew('Button', text => $loc->N("Cancel"), clicked => sub { $w->{retval} = 0; Gtk2->main_quit }) - ) - ) - ); - $check->() if $w->main; -} - -sub edit_parallel { - my ($num, $conf) = @_; - my $edited = $num == -1 ? {} : $conf->[$num]; - my $w = ugtk2->new($num == -1 ? $loc->N("Add a parallel group") : $loc->N("Edit a parallel group"), grab => 1, center => 1, transient => $::main_window); - local $::main_window = $w->{real_window}; - my $name_entry; - - my ($medias_ls, $hosts_ls) = (Gtk2::ListStore->new("Glib::String"), Gtk2::ListStore->new("Glib::String")); - - my ($medias, $hosts) = map { - my $list = Gtk2::TreeView->new_with_model($_); - $list->append_column(Gtk2::TreeViewColumn->new_with_attributes(undef, Gtk2::CellRendererText->new, 'text' => 0)); - $list->set_headers_visible(0); - $list->get_selection->set_mode('browse'); - $list; - } $medias_ls, $hosts_ls; - - $medias_ls->append_set([ 0 => $_ ]) foreach @{$edited->{medias}}; - - my $add_media = sub { - my $medias_list_ls = Gtk2::ListStore->new("Glib::String"); - my $medias_list = Gtk2::TreeView->new_with_model($medias_list_ls); - $medias_list->append_column(Gtk2::TreeViewColumn->new_with_attributes(undef, Gtk2::CellRendererText->new, 'text' => 0)); - $medias_list->set_headers_visible(0); - $medias_list->get_selection->set_mode('browse'); - $medias_list_ls->append_set([ 0 => $_->{name} ]) foreach @{$urpm->{media}}; - my $sel; - add_callback_($loc->N("Add a medium limit"), $loc->N("Choose a medium to add to the media limit:"), - $w, $medias_list, sub { $sel = selrow($medias_list) }, - sub { - return if $sel == -1; - my $media = ${$urpm->{media}}[$sel]{name}; - $medias_ls->append_set([ 0 => $media ]); - push @{$edited->{medias}}, $media; - } - ); - }; - - my $hosts_list; - if ($edited->{protocol} eq 'ssh') { $hosts_list = [ split /:/, $edited->{command} ] } - elsif ($edited->{protocol} eq 'ka-run') { push @$hosts_list, $1 while $edited->{command} =~ /-m (\S+)/g } - $hosts_ls->append_set([ 0 => $_ ]) foreach @$hosts_list; - my $add_host = sub { - my ($entry, $value); - add_callback_($loc->N("Add a host"), $loc->N("Type in the hostname or IP address of the host to add:"), - $mainw, $entry = gtkentry(), sub { $value = $entry->get_text }, - sub { $hosts_ls->append_set([ 0 => $value ]); push @$hosts_list, $value } - ); - }; - - my @protocols_names = qw(ka-run ssh); - my @protocols; - gtkadd( - $w->{window}, - gtkpack_( - gtknew('VBox', spacing => 5), - if_( - $num != -1, - 0, gtknew('Label', text => $loc->N("Editing parallel group \"%s\":", $edited->{name})) - ), - 1, create_packtable( - {}, - [ $loc->N("Group name:"), $name_entry = gtkentry($edited->{name}) ], - [ $loc->N("Protocol:"), gtknew('HBox', children_tight => [ - @protocols = gtkradio($edited->{protocol}, @protocols_names) ]) ], - [ $loc->N("Media limit:"), - gtknew('HBox', spacing => 5, children => [ - 1, gtknew('Frame', shadow_type => 'in', child => - gtknew('ScrolledWindow', h_policy => 'never', child => $medias)), - 0, gtknew('VBox', children_tight => [ - gtksignal_connect(Gtk2::Button->new(but($loc->N("Add"))), clicked => sub { $add_media->() }), - gtksignal_connect(Gtk2::Button->new(but($loc->N("Remove"))), clicked => sub { - remove_from_list($medias, $edited->{medias}, $medias_ls); - }) ]) ]) ], - [ $loc->N("Hosts:"), - gtknew('HBox', spacing => 5, children => [ - 1, gtknew('Frame', shadow_type => 'in', child => - gtknew('ScrolledWindow', h_policy => 'never', child => $hosts)), - 0, gtknew('VBox', children_tight => [ - gtksignal_connect(Gtk2::Button->new(but($loc->N("Add"))), clicked => sub { $add_host->() }), - gtksignal_connect(Gtk2::Button->new(but($loc->N("Remove"))), clicked => sub { - remove_from_list($hosts, $hosts_list, $hosts_ls); - }) ]) ]) ] - ), - 0, gtknew('HSeparator'), - 0, gtkpack( - gtknew('HButtonBox'), - gtksignal_connect( - gtknew('Button', text => $loc->N("Ok")), clicked => sub { - $w->{retval} = 1; - $edited->{name} = $name_entry->get_text; - mapn { $_[0]->get_active and $edited->{protocol} = $_[1] } \@protocols, \@protocols_names; - Gtk2->main_quit; - } - ), - gtknew('Button', text => $loc->N("Cancel"), clicked => sub { $w->{retval} = 0; Gtk2->main_quit })) - ) - ); - $w->{rwindow}->set_size_request(600, -1); - if ($w->main) { - $num == -1 and push @$conf, $edited; - if ($edited->{protocol} eq 'ssh') { $edited->{command} = join(':', @$hosts_list) } - if ($edited->{protocol} eq 'ka-run') { $edited->{command} = "-c ssh " . join(' ', map { "-m $_" } @$hosts_list) } - parallel_write_sysconf($conf); - return 1; - } - return 0; -} - -sub parallel_callback() { - my $w = ugtk2->new($loc->N("Configure parallel urpmi (distributed execution of urpmi)"), grab => 1, center => 1, transient => $mainw->{real_window}); - local $::main_window = $w->{real_window}; - my $list_ls = Gtk2::ListStore->new("Glib::String", "Glib::String", "Glib::String", "Glib::String"); - my $list = Gtk2::TreeView->new_with_model($list_ls); - each_index { $list->append_column(Gtk2::TreeViewColumn->new_with_attributes($_, Gtk2::CellRendererText->new, 'text' => $::i)) } $loc->N("Group"), $loc->N("Protocol"), $loc->N("Media limit"); - $list->append_column(my $commandcol = Gtk2::TreeViewColumn->new_with_attributes($loc->N("Command"), Gtk2::CellRendererText->new, 'text' => 3)); - $commandcol->set_max_width(200); - - my $conf; - my $reread = sub { - $list_ls->clear; - $conf = parallel_read_sysconf(); - foreach (@$conf) { - $list_ls->append_set([ 0 => $_->{name}, - 1 => $_->{protocol}, - 2 => @{$_->{medias}} ? join(', ', @{$_->{medias}}) : $loc->N("(none)"), - 3 => $_->{command} ]); - } - }; - $reread->(); - - gtkadd( - $w->{window}, - gtkpack_( - gtknew('VBox', spacing => 5), - 1, gtkpack_( - gtknew('HBox', spacing => 10), - 1, $list, - 0, gtkpack__( - gtknew('VBox', spacing => 5), - gtksignal_connect( - Gtk2::Button->new(but($loc->N("Remove"))), - clicked => sub { remove_parallel(selrow($list), $conf); $reread->() }, - ), - gtksignal_connect( - Gtk2::Button->new(but($loc->N("Edit..."))), - clicked => sub { - my $row = selrow($list); - $row != -1 and edit_parallel($row, $conf); - $reread->(); - }, - ), - gtksignal_connect( - Gtk2::Button->new(but($loc->N("Add..."))), - clicked => sub { edit_parallel(-1, $conf) and $reread->() }, - ) - ) - ), - 0, gtknew('HSeparator'), - 0, gtkpack( - gtknew('HButtonBox'), - gtknew('Button', text => $loc->N("Ok"), clicked => sub { Gtk2->main_quit }) - ) - ) - ); - $w->main; -} - -sub keys_callback() { - my $changed = 0; - my $appTitle = yui::YUI::app()->applicationTitle(); - - ## set new title to get it in dialog - yui::YUI::app()->setApplicationTitle($loc->N("Manage keys for digital signatures of packages")); - - my $factory = yui::YUI::widgetFactory; - - my $dialog = $factory->createPopupDialog(); - my $minSize = $factory->createMinSize( $dialog, 80, 20 ); - my $vbox = $factory->createVBox( $minSize ); - - my $hbox_headbar = $factory->createHBox($vbox); - 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 $hbox_content = $factory->createHBox($vbox); - my $leftContent = $factory->createLeft($hbox_content); - $leftContent->setWeight($yui::YD_HORIZ,3); - - my $frame = $factory->createFrame ($leftContent, ""); - - my $frmVbox = $factory->createVBox( $frame ); - my $hbox = $factory->createHBox( $frmVbox ); - - ## media list - my $yTableHeader = new yui::YTableHeader(); - $yTableHeader->addColumn($loc->N("Medium"), $yui::YAlignBegin); - my $multiselection = 0; - my $mediaTbl = $factory->createTable($hbox, $yTableHeader, $multiselection); - $mediaTbl->setKeepSorting(1); - $mediaTbl->setImmediateMode(1); - - my $itemColl = new yui::YItemCollection; - foreach (@{$urpm->{media}}) { - my $name = $_->{name}; - - my $item = new yui::YTableItem ($name); - # NOTE row is $item->index() - $item->setLabel( $name ); - $itemColl->push($item); - $item->DISOWN(); - } - $mediaTbl->addItems($itemColl); - - ## key list - $leftContent = $factory->createLeft($hbox_content); - $leftContent->setWeight($yui::YD_HORIZ,3); - $frame = $factory->createFrame ($leftContent, ""); - $frmVbox = $factory->createVBox( $frame ); - $hbox = $factory->createHBox( $frmVbox ); - $yTableHeader = new yui::YTableHeader(); - $yTableHeader->addColumn($loc->N("Keys"), $yui::YAlignBegin); - $multiselection = 0; - my $keyTbl = $factory->createTable($hbox, $yTableHeader, $multiselection); - $keyTbl->setKeepSorting(1); - - my ($current_medium, $current_medium_nb, @keys); - - ### internal subroutines - my $read_conf = sub { - $urpm->parse_pubkeys(root => $urpm->{root}); - @keys = map { [ split /[,\s]+/, ($_->{'key-ids'} || '') ] } @{$urpm->{media}}; - }; - - my $write = sub { - $something_changed = 1; - urpm::media::write_config($urpm); - $urpm = fast_open_urpmi_db(); - $read_conf->(); - }; - - $read_conf->(); - - my $key_name = sub { - exists $urpm->{keys}{$_[0]} ? $urpm->{keys}{$_[0]}{name} - : $loc->N("no name found, key doesn't exist in rpm keyring!"); - }; - - my $sel_changed = sub { - my $item = $mediaTbl->selectedItem(); - if ($item) { - $current_medium = $item->label(); - $current_medium_nb = $item->index(); - - yui::YUI::app()->busyCursor(); - yui::YUI::ui()->blockEvents(); - $dialog->startMultipleChanges(); - - $keyTbl->deleteAllItems(); - my $itemColl = new yui::YItemCollection; - foreach ( @{$keys[$current_medium_nb]} ) { - my $it = new yui::YTableItem (sprintf("%s (%s)", $_, $key_name->($_))); - # NOTE row is $item->index() - $it->setLabel( $_ ); - $itemColl->push($it); - $it->DISOWN(); - } - $keyTbl->addItems($itemColl); - - $dialog->recalcLayout(); - $dialog->doneMultipleChanges(); - yui::YUI::ui()->unblockEvents(); - yui::YUI::app()->normalCursor(); - } - }; - - my $add_key = sub { - my $sh_gui = ManaTools::Shared::GUI->new(); - my $item = $mediaTbl->selectedItem(); - if ($item) { - $current_medium = $item->label(); - $current_medium_nb = $item->index(); - my @list; - my %key; - foreach (keys %{$urpm->{keys}}) { - my $k = sprintf("%s (%s)", $_, $key_name->($_)); - $key{$k} = $_; - push @list, $k; - } - - my $choice = $sh_gui->ask_fromList({ - title => $loc->N("Add a key"), - header => $loc->N("Choose a key to add to the medium %s", $current_medium), - list => \@list, - }); - if ($choice) { - my $k = $key{$choice}; - $urpm->{media}[$current_medium_nb]{'key-ids'} = join(',', sort(uniq(@{$keys[$current_medium_nb]}, $k))); - $write->(); - return 1; - } - } - return 0; - }; - - my $remove_key = sub { - my $sh_gui = ManaTools::Shared::GUI->new(); - my $keyItem = $keyTbl->selectedItem(); - my $mediaItem = $mediaTbl->selectedItem(); - if ($keyItem && $mediaItem) { - $current_medium = $mediaItem->label(); - $current_medium_nb = $mediaItem->index(); - my $current_key = $keyItem->label(); - my $current_keyVal = yui::toYTableItem($keyItem)->cell(0)->label(); - my $choice = $sh_gui->ask_YesOrNo({ - title => $loc->N("Remove a key"), - text => $loc->N("Are you sure you want to remove the key
%s
from medium %s?
(name of the key: %s)", - $current_keyVal, $current_medium, $current_key - ), - richtext => 1, - }); - if ($choice) { - $urpm->{media}[$current_medium_nb]{'key-ids'} = join(',', - difference2(\@{$keys[$current_medium_nb]}, [ $current_key ]) - ); - $write->(); - return 1; - } - } - - return 0; - - }; - - - #### end subroutines - $sel_changed->(); - - my $rightContent = $factory->createRight($hbox_content); - $rightContent->setWeight($yui::YD_HORIZ,1); - my $topContent = $factory->createTop($rightContent); - my $vbox_commands = $factory->createVBox($topContent); - $factory->createVSpacing($vbox_commands, 1.0); - my $addButton = $factory->createPushButton($factory->createHBox($vbox_commands), $loc->N("Add")); - my $remButton = $factory->createPushButton($factory->createHBox($vbox_commands), $loc->N("Remove")); - - # dialog buttons - $factory->createVSpacing($vbox, 1.0); - $hbox = $factory->createHBox( $vbox ); - - ### Close button - my $closeButton = $factory->createPushButton($hbox, $loc->N("&Quit") ); - - ### dialog event loop - while(1) { - my $event = $dialog->waitForEvent(); - my $eventType = $event->eventType(); - my $changed = 0; - my $selection_changed = 0; - - #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 == $addButton) { - $changed = $add_key->(); - $sel_changed->() if $changed; - } - elsif ($widget == $remButton) { - $changed = $remove_key->(); - $sel_changed->() if $changed; - } - elsif ($widget == $mediaTbl) { - $sel_changed->(); - } - } - } - - $dialog->destroy(); - - #restore old application title - yui::YUI::app()->setApplicationTitle($appTitle) if $appTitle; - - return $changed; -} - -#============================================================= - -=head2 readMedia - -=head3 INPUT - -$name: optional parameter, the media called name has to be - updated - -=head3 OUTPUT - -$itemColl: yui::YItemCollection containing media data to - be added to the YTable - -=head3 DESCRIPTION - -This method reads the configured media and add their info -to the collection - -=cut - -#============================================================= -sub readMedia { - my ($name) = @_; - if (defined $name) { - urpm::media::select_media($urpm, $name); - update_sources_check( - $urpm, - { nolock => 1 }, - $loc->N_("Unable to update medium, errors reported:\n\n%s"), - $name, - ); - } - # reread configuration after updating media else ignore bit will be restored - # by urpm::media::check_existing_medium(): - $urpm = fast_open_urpmi_db(); - - my $itemColl = new yui::YItemCollection; - foreach (grep { ! $_->{external} } @{$urpm->{media}}) { - my $name = $_->{name}; - - my $item = new yui::YTableItem (($_->{ignore} ? "" : "X"), - ($_->{update} ? "X" : ""), - get_medium_type($_), - $name); - ## NOTE anaselli: next lines add check icon to cells, but they are 8x8, a dimension should - ## be evaluated by font size, so disabled atm -# my $cell = $item->cell(0); # Checked -# my $checkedIcon = File::ShareDir::dist_file(ManaTools::Shared::distName(), 'images/Check_8x8.png'); -# -# $cell->setIconName($checkedIcon) if (!$_->{ignore}); -# $cell = $item->cell(1); # Updates -# $cell->setIconName($checkedIcon) if ($_->{update}); - ## end icons on cells - - # TODO manage to_bool($::expert) - # row # is $item->index() - $item->setLabel( $name ); - $itemColl->push($item); - $item->DISOWN(); - } - - return $itemColl; -} - -#============================================================= - -=head2 selectRow - -=head3 INPUT - -$itemCollection: YItem collection in which to find the item that - has to be selected -$row: line to be selected - -=head3 DESCRIPTION - -Select item at row position -=cut - -#============================================================= - -sub selectRow { - my ($itemCollection, $row) = @_; - - return if !$itemCollection; - - for (my $it = 0; $it < $itemCollection->size(); $it++) { - my $item = $itemCollection->get($it); - if ($it == $row) { - $item->setSelected(1); - return; - } - } -} - -#============================================================= - -=head2 _showMediaStatus - -=head3 INPUT - -$info: HASH reference containing - item => selected item - updates => updates checkbox widget - enabled => enabled checkbox widget - -=head3 DESCRIPTION - -This internal function enables/disables checkboxes according to the -passed item value. - -=cut - -#============================================================= -sub _showMediaStatus { - my $info = shift; - - die "Updates checkbox is mandatory" if !defined($info->{updates}) || !$info->{updates}; - die "Enabled checkbox is mandatory" if !defined($info->{enabled}) || !$info->{enabled}; - - if (defined($info->{item})) { - my $tableItem = yui::toYTableItem($info->{item}); - # enabled cell 0, updates cell 1 - my $cellEnabled = $tableItem && $tableItem->cell(0)->label() ? 1 : 0; - my $cellUpdates = $tableItem && $tableItem->cell(1)->label() ? 1 : 0; - $info->{enabled}->setValue($cellEnabled); - $info->{updates}->setValue($cellUpdates); - } - else { - $info->{enabled}->setDisabled(); - $info->{updates}->setDisabled(); - } -} - -sub mainwindow() { - - my $something_changed = 0; - my $appTitle = yui::YUI::app()->applicationTitle(); - - ## set new title to get it in dialog - yui::YUI::app()->setApplicationTitle($loc->N("Configure media")); - ## set icon if not already set by external launcher TODO - yui::YUI::app()->setApplicationIcon("/usr/share/mcc/themes/default/rpmdrake-mdk.png"); - - my $mageiaPlugin = "mga"; - my $factory = yui::YUI::widgetFactory; - - my $dialog = $factory->createMainDialog; - my $vbox = $factory->createVBox( $dialog ); - - my $hbox_headbar = $factory->createHBox($vbox); - 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,$loc->N("File")), - update => new yui::YMenuItem($loc->N("Update")), - add_media => new yui::YMenuItem($loc->N("Add a specific media mirror")), - custom => new yui::YMenuItem($loc->N("Add a custom medium")), - quit => new yui::YMenuItem($loc->N("&Quit")), - ); - - my @ordered_menu_lines = qw(update add_media custom quit); - foreach (@ordered_menu_lines) { - $fileMenu{ widget }->addItem($fileMenu{ $_ }); - } - $fileMenu{ widget }->rebuildMenuTree(); - - my %optionsMenu = ( - widget => $factory->createMenuButton($headbar, $loc->N("&Options")), - global => new yui::YMenuItem($loc->N("Global options")), - man_keys => new yui::YMenuItem($loc->N("Manage keys")), - parallel => new yui::YMenuItem($loc->N("Parallel")), - proxy => new yui::YMenuItem($loc->N("Proxy")), - ); - @ordered_menu_lines = qw(global man_keys parallel proxy); - foreach (@ordered_menu_lines) { - $optionsMenu{ widget }->addItem($optionsMenu{ $_ }); - } - $optionsMenu{ widget }->rebuildMenuTree(); - - my %helpMenu = ( - widget => $factory->createMenuButton($headRight, $loc->N("&Help")), - help => new yui::YMenuItem($loc->N("Manual")), - report_bug => new yui::YMenuItem($loc->N("Report Bug")), - about => new yui::YMenuItem($loc->N("&About")), - ); - @ordered_menu_lines = qw(help report_bug about); - foreach (@ordered_menu_lines) { - $helpMenu{ widget }->addItem($helpMenu{ $_ }); - } - $helpMenu{ widget }->rebuildMenuTree(); - -# my %contextMenu = ( -# enable => $loc->N("Enable/Disable"), -# update => $loc->N("Check as updates"), -# ); -# @ordered_menu_lines = qw(enable update); -# my $itemColl = new yui::YItemCollection; -# foreach (@ordered_menu_lines) { -# # last if (!$::expert && $_ eq "update"); -# my $item = new yui::YMenuItem($contextMenu{$_}); -# $item->DISOWN(); -# $itemColl->push($item); -# } -# yui::YUI::app()->openContextMenu($itemColl) or die "Cannot create contextMenu"; - - my $hbox_content = $factory->createHBox($vbox); - my $leftContent = $factory->createLeft($hbox_content); - $leftContent->setWeight($yui::YD_HORIZ,3); - - my $frame = $factory->createFrame ($leftContent, ""); - - my $frmVbox = $factory->createVBox( $frame ); - my $hbox = $factory->createHBox( $frmVbox ); - - my $yTableHeader = new yui::YTableHeader(); - $yTableHeader->addColumn($loc->N("Enabled"), $yui::YAlignCenter); - $yTableHeader->addColumn($loc->N("Updates"), $yui::YAlignCenter); - $yTableHeader->addColumn($loc->N("Type"), $yui::YAlignBegin); - $yTableHeader->addColumn($loc->N("Medium"), $yui::YAlignBegin); - - ## mirror list - my $multiselection = 1; - my $mirrorTbl = $factory->createTable($hbox, $yTableHeader, $multiselection); - $mirrorTbl->setKeepSorting(1); - $mirrorTbl->setImmediateMode(1); - - my $itemCollection = readMedia(); - selectRow($itemCollection, 0); #default selection - $mirrorTbl->addItems($itemCollection); - - my $rightContent = $factory->createRight($hbox_content); - $rightContent->setWeight($yui::YD_HORIZ,1); - my $topContent = $factory->createTop($rightContent); - my $vbox_commands = $factory->createVBox($topContent); - $factory->createVSpacing($vbox_commands, 1.0); - my $remButton = $factory->createPushButton($factory->createHBox($vbox_commands), $loc->N("Remove")); - my $edtButton = $factory->createPushButton($factory->createHBox($vbox_commands), $loc->N("Edit")); - my $addButton = $factory->createPushButton($factory->createHBox($vbox_commands), $loc->N("Add")); - - $hbox = $factory->createHBox( $vbox_commands ); - my $item = $mirrorTbl->selectedItem(); - $factory->createHSpacing($hbox, 1.0); - my $enabled = $factory->createCheckBox($factory->createLeft($hbox), $loc->N("Enabled")); - my $update = $factory->createCheckBox($factory->createLeft($hbox), $loc->N("Updates")); - _showMediaStatus({item => $item, enabled => $enabled, updates => $update}); - $update->setNotify(1); - $enabled->setNotify(1); - $update->setDisabled() if (!$::expert); - - $hbox = $factory->createHBox( $vbox_commands ); - ## TODO icon and label for ncurses - my $upIcon = File::ShareDir::dist_file(ManaTools::Shared::distName(), 'images/Up_16x16.png'); - my $downIcon = File::ShareDir::dist_file(ManaTools::Shared::distName(), 'images/Down_16x16.png'); - my $upButton = $factory->createPushButton($factory->createHBox($hbox), $loc->N("Up")); - my $downButton = $factory->createPushButton($factory->createHBox($hbox), $loc->N("Down")); - $upButton->setIcon($upIcon); - $downButton->setIcon($downIcon); - - $addButton->setWeight($yui::YD_HORIZ,1); - $edtButton->setWeight($yui::YD_HORIZ,1); - $remButton->setWeight($yui::YD_HORIZ,1); - $upButton->setWeight($yui::YD_HORIZ,1); - $downButton->setWeight($yui::YD_HORIZ,1); - - - # dialog buttons - $factory->createVSpacing($vbox, 1.0); - ## Window push buttons - $hbox = $factory->createHBox( $vbox ); - my $align = $factory->createLeft($hbox); - $hbox = $factory->createHBox($align); - - my $helpButton = $factory->createPushButton($hbox, $loc->N("Help") ); - $align = $factory->createRight($hbox); - $hbox = $factory->createHBox($align); - - ### Close button - my $closeButton = $factory->createPushButton($hbox, $loc->N("&Quit") ); - - ### dialog event loop - while(1) { - my $event = $dialog->waitForEvent(); - my $eventType = $event->eventType(); - my $changed = 0; - my $selection_changed = 0; - - #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()) { - my $translators = $loc->N("_: Translator(s) name(s) & email(s)\n"); - $translators =~ s/\/\>\;/g; - my $sh_gui = ManaTools::Shared::GUI->new(); - $sh_gui->AboutDialog({ name => "Rpmdragora", - version => $VERSION, - credits => $loc->N("Copyright (C) %s Mageia community", '2013-2014'), - license => $loc->N("GPLv2"), - description => $loc->N("Rpmdragora is the Mageia package management tool."), - authors => $loc->N("

Developers

-
  • %s
  • -
  • %s
  • -
-

Translators

-
  • %s
", - "Angelo Naselli <anaselli\@linux.it>", - "Matteo Pasotti <matteo.pasotti\@gmail.com>", - $translators - ), - } - ); - } - elsif ($menuLabel eq $fileMenu{ update }->label()) { - update_callback(); - } - elsif ($menuLabel eq $fileMenu{ add_media }->label()) { - $changed = easy_add_callback_with_mirror(); - } - elsif ($menuLabel eq $fileMenu{ custom }->label()) { - $changed = add_callback(); - } - elsif ($menuLabel eq $optionsMenu{ proxy }->label()) { - proxy_callback(); - } - elsif ($menuLabel eq $optionsMenu{ global }->label()) { - options_callback(); - } - elsif ($menuLabel eq $optionsMenu{ man_keys }->label()) { - $changed = keys_callback(); - } - elsif ($menuLabel eq $optionsMenu{ parallel }->label()) { -# parallel_callback(); - } - } - elsif ($eventType == $yui::YEvent::WidgetEvent) { - # widget selected - my $widget = $event->widget(); - my $wEvent = yui::toYWidgetEvent($event); - - if ($widget == $closeButton) { - last; - } - elsif ($widget == $helpButton) { - } - elsif ($widget == $upButton) { - yui::YUI::app()->busyCursor(); - yui::YUI::ui()->blockEvents(); - $dialog->startMultipleChanges(); - - my $row = upwards_callback($mirrorTbl); - - $mirrorTbl->deleteAllItems(); - my $itemCollection = readMedia(); - selectRow($itemCollection, $row); - $mirrorTbl->addItems($itemCollection); - - $dialog->recalcLayout(); - $dialog->doneMultipleChanges(); - yui::YUI::ui()->unblockEvents(); - yui::YUI::app()->normalCursor(); - } - elsif ($widget == $downButton) { - yui::YUI::app()->busyCursor(); - yui::YUI::ui()->blockEvents(); - $dialog->startMultipleChanges(); - - my $row = downwards_callback($mirrorTbl); - - $mirrorTbl->deleteAllItems(); - my $itemCollection = readMedia(); - selectRow($itemCollection, $row); - $mirrorTbl->addItems($itemCollection); - - $dialog->recalcLayout(); - $dialog->doneMultipleChanges(); - yui::YUI::ui()->unblockEvents(); - yui::YUI::app()->normalCursor(); - } - elsif ($widget == $edtButton) { - my $item = $mirrorTbl->selectedItem(); - if ($item && edit_callback($mirrorTbl) ) { - my $row = $item->index(); - yui::YUI::app()->busyCursor(); - yui::YUI::ui()->blockEvents(); - - $dialog->startMultipleChanges(); - - my $ignored = $urpm->{media}[$row]{ignore}; - my $itemCollection = readMedia(); - if (!$ignored && $urpm->{media}[$row]{ignore}) { - # reread media failed to un-ignore an ignored medium - # probably because urpm::media::check_existing_medium() complains - # about missing synthesis when the medium never was enabled before; - # thus it restored the ignore bit - $urpm->{media}[$row]{ignore} = !$urpm->{media}[$row]{ignore} || undef; - urpm::media::write_config($urpm); - #- Enabling this media failed, force update - interactive_msg('rpmdragora', - $loc->N("This medium needs to be updated to be usable. Update it now?"), - yesno => 1, - ) and $itemCollection = readMedia($urpm->{media}[$row]{name}); - } - $mirrorTbl->deleteAllItems(); - selectRow($itemCollection, $row); - $mirrorTbl->addItems($itemCollection); - - $dialog->recalcLayout(); - $dialog->doneMultipleChanges(); - yui::YUI::ui()->unblockEvents(); - yui::YUI::app()->normalCursor(); - $selection_changed = 1; # to align $enabled and $update status - } - } - elsif ($widget == $remButton) { - my $sel = $mirrorTbl->selectedItems(); - $changed = remove_callback($sel); - } - elsif ($widget == $addButton) { - $changed = easy_add_callback(); - } - elsif ($widget == $update) { - my $item = $mirrorTbl->selectedItem(); - if ($item) { - yui::YUI::app()->busyCursor(); - my $row = $item->index(); - $urpm->{media}[$row]{update} = !$urpm->{media}[$row]{update} || undef; - urpm::media::write_config($urpm); - yui::YUI::ui()->blockEvents(); - $dialog->startMultipleChanges(); - $mirrorTbl->deleteAllItems(); - my $itemCollection = readMedia(); - selectRow($itemCollection, $row); - $mirrorTbl->addItems($itemCollection); - $dialog->recalcLayout(); - $dialog->doneMultipleChanges(); - yui::YUI::ui()->unblockEvents(); - yui::YUI::app()->normalCursor(); - } - } - elsif ($widget == $enabled) { - ## TODO same as $edtButton after edit_callback - my $item = $mirrorTbl->selectedItem(); - if ($item) { - my $row = $item->index(); - yui::YUI::app()->busyCursor(); - yui::YUI::ui()->blockEvents(); - - $dialog->startMultipleChanges(); - - $urpm->{media}[$row]{ignore} = !$urpm->{media}[$row]{ignore} || undef; - urpm::media::write_config($urpm); - my $ignored = $urpm->{media}[$row]{ignore}; - my $itemCollection = readMedia(); - if (!$ignored && $urpm->{media}[$row]{ignore}) { - # reread media failed to un-ignore an ignored medium - # probably because urpm::media::check_existing_medium() complains - # about missing synthesis when the medium never was enabled before; - # thus it restored the ignore bit - $urpm->{media}[$row]{ignore} = !$urpm->{media}[$row]{ignore} || undef; - urpm::media::write_config($urpm); - #- Enabling this media failed, force update - interactive_msg('rpmdragora', - $loc->N("This medium needs to be updated to be usable. Update it now?"), - yesno => 1, - ) and $itemCollection = readMedia($urpm->{media}[$row]{name}); - } - $mirrorTbl->deleteAllItems(); - selectRow($itemCollection, $row); - $mirrorTbl->addItems($itemCollection); - - $dialog->recalcLayout(); - $dialog->doneMultipleChanges(); - yui::YUI::ui()->unblockEvents(); - yui::YUI::app()->normalCursor(); - } - } - elsif ($widget == $mirrorTbl) { - $selection_changed = 1; - } - } - if ($changed) { - yui::YUI::app()->busyCursor(); - yui::YUI::ui()->blockEvents(); - - $dialog->startMultipleChanges(); - - $mirrorTbl->deleteAllItems(); - my $itemCollection = readMedia(); - selectRow($itemCollection, 0); #default selection - $mirrorTbl->addItems($itemCollection); - - $dialog->recalcLayout(); - $dialog->doneMultipleChanges(); - yui::YUI::app()->normalCursor(); - $selection_changed = 1; - } - if ($selection_changed) { - yui::YUI::ui()->blockEvents(); - my $item = $mirrorTbl->selectedItem(); - _showMediaStatus({item => $item, enabled => $enabled, updates => $update}); - - my $sel = $mirrorTbl->selectedItems(); - if ($sel->size() == 0 || $sel->size() > 1 ) { - $remButton->setEnabled(($sel->size() == 0) ? 0 : 1); - $edtButton->setEnabled(0); - $upButton->setEnabled(0); - $downButton->setEnabled(0); - $enabled->setEnabled(0); - $update->setEnabled(0); - } - else { - $remButton->setEnabled(1); - $edtButton->setEnabled(1); - $upButton->setEnabled(1); - $downButton->setEnabled(1); - $enabled->setEnabled(1); - $update->setEnabled(1) if $::expert; - } - - yui::YUI::ui()->unblockEvents(); - } - } - $dialog->destroy(); - - #restore old application title - yui::YUI::app()->setApplicationTitle($appTitle) if $appTitle; - - return $something_changed; -} - - -sub OLD_mainwindow() { - undef $something_changed; - $mainw = ugtk2->new($loc->N("Configure media"), center => 1, transient => $::main_window, modal => 1); - local $::main_window = $mainw->{real_window}; - - my $reread_media; - - my ($menu, $_factory) = create_factory_menu( - $mainw->{real_window}, - [ $loc->N("/_File"), undef, undef, undef, '' ], - [ $loc->N("/_File") . $loc->N("/_Update"), $loc->N("U"), sub { update_callback() and $reread_media->() }, undef, '', ], - [ $loc->N("/_File") . $loc->N("/Add a specific _media mirror"), $loc->N("M"), sub { easy_add_callback_with_mirror() and $reread_media->() }, undef, '' ], - [ $loc->N("/_File") . $loc->N("/_Add a custom medium"), $loc->N("A"), sub { add_callback() and $reread_media->() }, undef, '' ], - [ $loc->N("/_File") . $loc->N("/Close"), $loc->N("W"), sub { Gtk2->main_quit }, undef, '', ], - [ $loc->N("/_Options"), undef, undef, undef, '' ], - [ $loc->N("/_Options") . $loc->N("/_Global options"), $loc->N("G"), \&options_callback, undef, '' ], - [ $loc->N("/_Options") . $loc->N("/Manage _keys"), $loc->N("K"), \&keys_callback, undef, '' ], - [ $loc->N("/_Options") . $loc->N("/_Parallel"), $loc->N("P"), \¶llel_callback, undef, '' ], - [ $loc->N("/_Options") . $loc->N("/P_roxy"), $loc->N("R"), \&proxy_callback, undef, '' ], - if_($0 =~ /edit-urpm-sources/, - [ $loc->N("/_Help"), undef, undef, undef, '' ], - [ $loc->N("/_Help") . $loc->N("/_Report Bug"), undef, sub { run_drakbug('edit-urpm-sources.pl') }, undef, '' ], - [ $loc->N("/_Help") . $loc->N("/_Help"), undef, sub { rpmdragora::open_help('sources') }, undef, '' ], - [ $loc->N("/_Help") . $loc->N("/_About..."), undef, sub { - my $license = MDK::Common::String::formatAlaTeX(translate($::license)); - $license =~ s/\n/\n\n/sg; # nicer formatting - my $w = gtknew('AboutDialog', name => $loc->N("Rpmdragora"), - version => $rpmdragora::distro_version, - copyright => $loc->N("Copyright (C) %s by Mandriva", '2002-2008'), - license => $license, wrap_license => 1, - comments => $loc->N("Rpmdragora is the Mageia package management tool."), - website => 'http://www.mageia.org/', - website_label => $loc->N("Mageia"), - authors => 'Thierry Vignaud ', - artists => 'Hélène Durosini ', - translator_credits => - #-PO: put here name(s) and email(s) of translator(s) (eg: "John Smith ") - $loc->N("_: Translator(s) name(s) & email(s)\n"), - transient_for => $::main_window, modal => 1, position_policy => 'center-on-parent', - ); - $w->show_all; - $w->run; - }, undef, '' - ] - ), - ); - - my $list = Gtk2::ListStore->new("Glib::Boolean", "Glib::Boolean", "Glib::String", "Glib::String", "Glib::Boolean"); - $list_tv = Gtk2::TreeView->new_with_model($list); - $list_tv->get_selection->set_mode('multiple'); - my ($dw_button, $edit_button, $remove_button, $up_button); - $list_tv->get_selection->signal_connect(changed => sub { - my ($selection) = @_; - my @rows = $selection->get_selected_rows; - my $model = $list; - # we can delete several medium at a time: - $remove_button and $remove_button->set_sensitive($#rows != -1); - # we can only edit/move one item at a time: - $_ and $_->set_sensitive(@rows == 1) foreach $up_button, $dw_button, $edit_button; - - # we can only up/down one item if not at begin/end: - return if @rows != 1; - - my $curr_path = $rows[0]; - my $first_path = $model->get_path($model->get_iter_first); - $up_button->set_sensitive($first_path && $first_path->compare($curr_path)); - - $curr_path->next; - my $next_item = $model->get_iter($curr_path); - $dw_button->set_sensitive($next_item); # && !$model->get($next_item, 0) - }); - - $list_tv->set_rules_hint(1); - $list_tv->set_reorderable(1); - - my $reorder_ok = 1; - $list->signal_connect( - row_deleted => sub { - $reorder_ok or return; - my ($model) = @_; - my @media; - $model->foreach( - sub { - my (undef, undef, $iter) = @_; - my $name = $model->get($iter, $col{mainw}{name}); - push @media, urpm::media::name2medium($urpm, $name); - 0; - }, undef); - @{$urpm->{media}} = @media; - }, - ); - - $list_tv->append_column(Gtk2::TreeViewColumn->new_with_attributes($loc->N("Enabled"), - my $tr = Gtk2::CellRendererToggle->new, - 'active' => $col{mainw}{is_enabled})); - $list_tv->append_column(Gtk2::TreeViewColumn->new_with_attributes($loc->N("Updates"), - my $cu = Gtk2::CellRendererToggle->new, - 'active' => $col{mainw}{is_update}, - activatable => $col{mainw}{activatable})); - $list_tv->append_column(Gtk2::TreeViewColumn->new_with_attributes($loc->N("Type"), - Gtk2::CellRendererText->new, - 'text' => $col{mainw}{type})); - $list_tv->append_column(Gtk2::TreeViewColumn->new_with_attributes($loc->N("Medium"), - Gtk2::CellRendererText->new, - 'text' => $col{mainw}{name})); - my $id; - $id = $tr->signal_connect( - toggled => sub { - my (undef, $path) = @_; - $tr->signal_handler_block($id); - my $_guard = before_leaving { $tr->signal_handler_unblock($id) }; - my $iter = $list->get_iter_from_string($path); - $urpm->{media}[$path]{ignore} = !$urpm->{media}[$path]{ignore} || undef; - $list->set($iter, $col{mainw}{is_enabled}, !$urpm->{media}[$path]{ignore}); - urpm::media::write_config($urpm); - my $ignored = $urpm->{media}[$path]{ignore}; - $reread_media->(); - if (!$ignored && $urpm->{media}[$path]{ignore}) { - # reread media failed to un-ignore an ignored medium - # probably because urpm::media::check_existing_medium() complains - # about missing synthesis when the medium never was enabled before; - # thus it restored the ignore bit - $urpm->{media}[$path]{ignore} = !$urpm->{media}[$path]{ignore} || undef; - urpm::media::write_config($urpm); - #- Enabling this media failed, force update - interactive_msg('rpmdragora', - $loc->N("This medium needs to be updated to be usable. Update it now?"), - yesno => 1, - ) and $reread_media->($urpm->{media}[$path]{name}); - } - }, - ); - - $cu->signal_connect( - toggled => sub { - my (undef, $path) = @_; - my $iter = $list->get_iter_from_string($path); - $urpm->{media}[$path]{update} = !$urpm->{media}[$path]{update} || undef; - $list->set($iter, $col{mainw}{is_update}, ! !$urpm->{media}[$path]{update}); - $something_changed = 1; - }, - ); - - $reread_media = sub { - my ($name) = @_; - $reorder_ok = 0; - $something_changed = 1; - if (defined $name) { - urpm::media::select_media($urpm, $name); - update_sources_check( - $urpm, - { nolock => 1 }, - $loc->N_("Unable to update medium, errors reported:\n\n%s"), - $name, - ); - } - # reread configuration after updating media else ignore bit will be restored - # by urpm::media::check_existing_medium(): - $urpm = fast_open_urpmi_db(); - $list->clear; - foreach (grep { ! $_->{external} } @{$urpm->{media}}) { - my $name = $_->{name}; - $list->append_set($col{mainw}{is_enabled} => !$_->{ignore}, - $col{mainw}{is_update} => ! !$_->{update}, - $col{mainw}{type} => get_medium_type($_), - $col{mainw}{name} => $name, - $col{mainw}{activatable} => to_bool($::expert), - ); - } - $reorder_ok = 1; - }; - $reread_media->(); - $something_changed = 0; - - gtkadd( - $mainw->{window}, - gtkpack_( - gtknew('VBox', spacing => 5), - 0, $menu, - ($0 =~ /rpm-edit-media|edit-urpm-sources/ ? (0, Gtk2::Banner->new($ugtk2::wm_icon, $loc->N("Configure media"))) : ()), - 1, gtkpack_( - gtknew('HBox', spacing => 10), - 1, gtknew('ScrolledWindow', child => $list_tv), - 0, gtkpack__( - gtknew('VBox', spacing => 5), - gtksignal_connect( - $remove_button = Gtk2::Button->new(but($loc->N("Remove"))), - clicked => sub { remove_callback() and $reread_media->() }, - ), - gtksignal_connect( - $edit_button = Gtk2::Button->new(but($loc->N("Edit"))), - clicked => sub { - my $name = edit_callback(); defined $name and $reread_media->($name); - } - ), - gtksignal_connect( - Gtk2::Button->new(but($loc->N("Add"))), - clicked => sub { easy_add_callback() and $reread_media->() }, - ), - gtkpack( - gtknew('HBox'), - gtksignal_connect( - $up_button = gtknew('Button', - image => gtknew('Image', stock => 'gtk-go-up')), - clicked => \&upwards_callback), - - gtksignal_connect( - $dw_button = gtknew('Button', - image => gtknew('Image', stock => 'gtk-go-down')), - clicked => \&downwards_callback), - ), - ) - ), - 0, gtknew('HSeparator'), - 0, gtknew('HButtonBox', layout => 'edge', children_loose => [ - gtksignal_connect(Gtk2::Button->new(but($loc->N("Help"))), clicked => sub { rpmdragora::open_help('sources') }), - gtksignal_connect(Gtk2::Button->new(but($loc->N("Ok"))), clicked => sub { Gtk2->main_quit }) - ]) - ) - ); - $_->set_sensitive(0) foreach $dw_button, $edit_button, $remove_button, $up_button; - - $mainw->{rwindow}->set_size_request(600, 400); - $mainw->main; - return $something_changed; -} - - -sub run() { - # ignore rpmdragora's option regarding ignoring debug media: - local $ignore_debug_media = [ 0 ]; -# local $ugtk2::wm_icon = get_icon('rpmdragora-mdk', 'title-media'); - my $lock; - { - $urpm = fast_open_urpmi_db(); - my $err_msg = "urpmdb locked\n"; - local $urpm->{fatal} = sub { - interactive_msg('rpmdragora', - $loc->N("The Package Database is locked. Please close other applications -working with the Package Database. Do you have another media -manager on another desktop, or are you currently installing -packages as well?")); - die $err_msg; - }; - # lock urpmi DB - eval { $lock = urpm::lock::urpmi_db($urpm, 'exclusive', wait => $urpm->{options}{wait_lock}) }; - if (my $err = $@) { - return if $err eq $err_msg; - die $err; - } - } - - my $res = mainwindow(); - urpm::media::write_config($urpm); - - writeconf(); - - undef $lock; - $res; -} - -sub readproxy (;$) { - my $proxy = get_proxy($_[0]); - ($proxy->{http_proxy} || $proxy->{ftp_proxy} || '', - defined $proxy->{user} ? "$proxy->{user}:$proxy->{pwd}" : ''); -} - -sub writeproxy { - my ($proxy, $proxy_user, $o_media_name) = @_; - my ($user, $pwd) = split /:/, $proxy_user; - set_proxy_config(user => $user, $o_media_name); - set_proxy_config(pwd => $pwd, $o_media_name); - set_proxy_config(http_proxy => $proxy, $o_media_name); - set_proxy_config(ftp_proxy => $proxy, $o_media_name); - dump_proxy_config(); -} - -1; diff --git a/lib/AdminPanel/Rpmdragora/formatting.pm b/lib/AdminPanel/Rpmdragora/formatting.pm deleted file mode 100644 index 83a960a..0000000 --- a/lib/AdminPanel/Rpmdragora/formatting.pm +++ /dev/null @@ -1,209 +0,0 @@ -# vim: set et ts=4 sw=4: -package ManaTools::Rpmdragora::formatting; -#***************************************************************************** -# -# Copyright (c) 2002 Guillaume Cottenceau -# Copyright (c) 2002-2006 Thierry Vignaud -# Copyright (c) 2003, 2004, 2005 MandrakeSoft SA -# Copyright (c) 2005, 2006 Mandriva SA -# Copyright (c) 2013 - 2015 Matteo Pasotti -# 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. -# -#***************************************************************************** -# -# $Id: formatting.pm 261189 2009-10-01 14:44:39Z tv $ - -use strict; -use utf8; -use POSIX qw(strftime); -use MDK::Common::Various qw(internal_error); -use ManaTools::Shared::Locales; -use ManaTools::rpmdragora; -use urpm::msg; - - -use Exporter; -our @ISA = qw(Exporter); -our @EXPORT = qw( - $spacing - ensure_utf8 - format_changelog_changelogs - format_changelog_string - format_field - format_header - format_list - format_name_n_summary - format_size - format_filesize - format_update_field - my_fullname - pkg2medium - rpm_description - split_fullname - urpm_name - ); - -my $loc = ManaTools::rpmdragora::locale(); - -sub escape_text_for_TextView_markup_format { - my ($str) = @_; - return '' if !$str; - - my %rules = ('&' => '&', - '<' => '<', - '>' => '>', - ); - eval { $str =~ s!([&<>])!$rules{$1}!g }; #^(&(amp|lt|gt);)!!) { - if (my $err = $@) { - MDK::Common::Various::internal_error("$err\n$str"); - } - $str; -} - -# from rpmtools, #37482: -sub ensure_utf8 { - return '' if !$_[0]; - - if (utf8::is_utf8($_[0])) { - utf8::valid($_[0]) and return; - utf8::encode($_[0]); #- disable utf8 flag - utf8::upgrade($_[0]); - } else { - utf8::decode($_[0]); #- try to set utf8 flag - utf8::valid($_[0]) and return; - warn "do not know what to with $_[0]\n"; - } -} - -sub rpm_description { - my ($description) = @_; - return '' if !$description; - - ensure_utf8($description); - my $t = ""; - my $tmp = ""; - foreach (split "\n", $description) { - s/^\s*//; - if (/^$/ || /^\s*(-|\*|\+|o)\s/) { - $t || $tmp and $t .= "$tmp\n"; - $tmp = $_; - } else { - $tmp = ($tmp ? "$tmp " : ($t && "\n") . $tmp) . $_; - } - } - "$t$tmp\n"; -} - -sub split_fullname { $_[0] =~ /^(.*)-([^-]+)-([^-]+)\.([^.-]+)$/ } - -sub my_fullname { - return '?-?-?' unless ref $_[0]; - my ($name, $version, $release) = $_[0]->fullname; - "$name-$version-$release"; -} - -sub urpm_name { - return '?-?-?.?' unless ref $_[0]; - scalar $_[0]->fullname; -} - -sub pkg2medium { - my ($p, $urpm) = @_; - return if !ref $p; - return { name => $loc->N("None (installed)") } if !defined($p->id); # if installed - URPM::pkg2media($urpm->{media}, $p) || { name => $loc->N("Unknown"), fake => 1 }; -} - -# [ duplicate urpmi's urpm::msg::localtime2changelog() ] -#- strftime returns a string in the locale charset encoding; -#- but gtk2 requires UTF-8, so we use to_utf8() to ensure the -#- output of localtime2changelog() is always in UTF-8 -#- as to_utf8() uses LC_CTYPE for locale encoding and strftime() uses LC_TIME, -#- it doesn't work if those two variables have values with different -#- encodings; but if a user has a so broken setup we can't do much anyway -sub localtime2changelog { $loc->to_utf8(POSIX::strftime("%c", localtime($_[0]))) } - -our $spacing = " "; -sub format_changelog_string { - my ($installed_version, $string) = @_; - - #- preprocess changelog for faster TextView insert reaction - my $version; - my $highlight; - my $chl = [ map { - my %attrs; - if (/^\*/) { - ($version) = /(\S*-\S*)\s*$/; - $highlight = $installed_version ne $loc->N("(none)") && 0 < URPM::rpmvercmp($version, $installed_version); - if ($highlight) { - "" . $_ . ""; - } - else { - "" . $_ . ""; - } - } - else { - "$spacing" . $_ . "\n"; - } - } split("\n", $string) ]; - - return $chl; -} - -sub format_changelog_changelogs { - my ($installed_version, @changelogs) = @_; - format_changelog_string($installed_version, join("\n", map { - "* " . localtime2changelog($_->{time}) . " $_->{name}\n\n$_->{text}\n"; - } @changelogs)); -} - -sub format_update_field { - my ($name) = @_; - '' . escape_text_for_TextView_markup_format($name) . ''; -} - -sub format_name_n_summary { - my ($name, $summary) = @_; - join("\n", '' . $name . '', escape_text_for_TextView_markup_format($summary)); -} - -sub format_header { - my ($str) = @_; - '' . escape_text_for_TextView_markup_format($str) . ''; -} - -sub format_field { - my ($str) = @_; - '' . escape_text_for_TextView_markup_format($str) . ''; -} - -sub format_size { - my ($size) = @_; - $size >= 0 ? - $loc->N("%s of additional disk space will be used.", formatXiB($size)) : - $loc->N("%s of disk space will be freed.", formatXiB(-$size)); -} - -sub format_filesize { - my ($filesize) = @_; - $filesize ? $loc->N("%s of packages will be retrieved.", formatXiB($filesize)) : (); -} - -sub format_list { - return join("\n", map { s/^(\s)/ $1/mg; "- $_" } sort { uc($a) cmp uc($b) } @_); -} - -1; diff --git a/lib/AdminPanel/Rpmdragora/gui.pm b/lib/AdminPanel/Rpmdragora/gui.pm deleted file mode 100644 index 0cf0882..0000000 --- a/lib/AdminPanel/Rpmdragora/gui.pm +++ /dev/null @@ -1,1828 +0,0 @@ -# vim: set et ts=4 sw=4: -package ManaTools::Rpmdragora::gui; -#***************************************************************************** -# -# Copyright (c) 2002 Guillaume Cottenceau -# Copyright (c) 2002-2007 Thierry Vignaud -# Copyright (c) 2003, 2004, 2005 MandrakeSoft SA -# Copyright (c) 2005-2007 Mandriva SA -# Copyright (c) 2013 - 2015 Matteo Pasotti -# 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. -# -#***************************************************************************** -# -# $Id$ - -############################################################ -# WARNING: do not modify before asking matteo or anaselli -############################################################ - -use strict; -use Sys::Syslog; - -use utf8; - -use MDK::Common::Func qw(before_leaving find any if_); -use MDK::Common::DataStructure qw(difference2 member intersection); -use MDK::Common::Various qw(chomp_ to_bool); -use MDK::Common::String qw(formatAlaTeX); -use MDK::Common::Math qw(sum); -use MDK::Common::System qw(list_passwd); - -use ManaTools::rpmdragora; -use ManaTools::Rpmdragora::open_db; -use ManaTools::Rpmdragora::formatting; -use ManaTools::Rpmdragora::init; -use ManaTools::Rpmdragora::icon qw(get_icon_path); -use ManaTools::Rpmdragora::pkg; -use ManaTools::Shared; -use ManaTools::Shared::GUI; -use ManaTools::Shared::Locales; -use ManaTools::Shared::RunProgram qw(get_stdout raw); -use yui; -use feature 'state'; -use Carp; - -use Exporter; -our @ISA = qw(Exporter); -our @EXPORT = qw( - $descriptions - $find_entry - $force_displaying_group - $force_rebuild - $pkgs - $results_ok - $results_none - $size_free - $size_selected - $urpm - %grp_columns - %pkg_columns - @filtered_pkgs - @initial_selection - ask_browse_tree_given_widgets_for_rpmdragora - build_tree - callback_choices - compute_main_window_size - do_action - get_info - get_summary - group_has_parent - group_parent - groups_tree - is_locale_available - node_state - pkgs_provider - real_quit - reset_search - set_node_state - sort_callback - switch_pkg_list_mode - toggle_all - toggle_nodes - fast_toggle - setInfoOnWidget - ); - -my $loc = ManaTools::rpmdragora::locale(); -my $shared_gui = ManaTools::Shared::GUI->new() ; - -our ($descriptions, %filters, @filtered_pkgs, %filter_methods, $force_displaying_group, $force_rebuild, @initial_selection, $pkgs, $size_free, $size_selected, $urpm); -our ($results_ok, $results_none) = ($loc->N("Search results"), $loc->N("Search results (none)")); - -our %hidden_info = ( - details => "details", - changelog => "changelog", - files => "file", - new_deps => "new_deps", - -); -our %grp_columns = ( - label => 0, - icon => 2, -); - -our %pkg_columns = ( - text => 0, - state_icon => 1, - state => 2, - selected => 3, - short_name => 4, - version => 5, - release => 6, - 'arch' => 7, - selectable => 8, -); - - -sub compute_main_window_size { - my ($w) = @_; - ($typical_width) = string_size($w->{real_window}, $loc->N("Graphical Environment") . "xmms-more-vis-plugins"); - $typical_width > 600 and $typical_width = 600; #- try to not being crazy with a too large value - $typical_width < 150 and $typical_width = 150; -} - -sub get_summary { - my ($key) = @_; - my $summary = $loc->N($pkgs->{$key}{pkg}->summary); - require utf8; - utf8::valid($summary) ? $summary : @{[]}; -} - -sub get_advisory_link { - my ($update_descr) = @_; - - my $webref = "
{URL} ."\">". $loc->N("Security advisory") ."
"; - - [ $webref ]; -} - -sub get_description { - my ($pkg, $update_descr) = @_; - - my $descr = ($pkg->{description} || - $update_descr->{description} || - ''. $loc->N("No description").''); - $descr =~ s|\n|
|g; - - return $descr . "
"; -} - -sub get_string_from_keywords { - my ($medium, $name) = @_; - my @media_types; - if ($medium->{mediacfg}) { - my ($distribconf, $medium_path) = @{$medium->{mediacfg}}; - @media_types = split(':', $distribconf->getvalue($medium_path, 'media_type')) if $distribconf; - } - - my $unsupported = $loc->N("It is not supported by Mageia."); - my $dangerous = $loc->N("It may break your system."); - my $s = ""; - $s .= $loc->N("This package is not free software") . "\n" if member('non-free', @media_types); - if ($pkgs->{$name}{is_backport} || member('backport', @media_types)) { - return join("\n", - $loc->N("This package contains a new version that was backported."), - $unsupported, $dangerous, $s); - } elsif (member('testing', @media_types)) { - return join("\n", - $loc->N("This package is a potential candidate for an update."), - $unsupported, $dangerous, $s); - } elsif (member('updates', @media_types)) { - return join("\n", - (member('official', @media_types) ? - $loc->N("This is an official update which is supported by Mageia.") - : ($loc->N("This is an unofficial update."), $unsupported)) - , - $s); - } else { - $s .= $loc->N("This is an official package supported by Mageia") . "\n" if member('official', @media_types); - return $s if $s; - } - - return; -} - -sub get_main_text { - my ($medium, $fullname, $name, $summary, $is_update, $update_descr) = @_; - - my $txt = get_string_from_keywords($medium, $fullname); - my $notice = format_field($loc->N("Notice: ")) . $txt if $txt; - ensure_utf8($notice); - - my $hdr = "

" . format_header(join(' - ', $name, $summary)) . "

\n"; - ensure_utf8($hdr); - - my $update = MDK::Common::Func::if_($is_update, # is it an update? - format_field($loc->N("Importance: ")) . format_update_field($update_descr->{importance}), - format_field($loc->N("Reason for update: ")) . format_update_field(rpm_description($update_descr->{pre})), - ); - ensure_utf8($update); - - my $main_text = $hdr; - $main_text .= "   " . $notice . "
" if $notice; - $main_text .= "   " . $update . "
" if $update; - - return $main_text; -} - -sub get_details { - my ($pkg, $upkg, $installed_version, $raw_medium) = @_; - my @details = (); - push @details, format_field($loc->N("Version: ")) . $upkg->EVR; - push @details, format_field($loc->N("Currently installed version: ")) . $installed_version if($upkg->flag_installed); - push @details, format_field($loc->N("Group: ")) . translate_group($upkg->group); - push @details, format_field($loc->N("Architecture: ")) . $upkg->arch; - push @details, format_field($loc->N("Size: ")) . $loc->N("%s KB", int($upkg->size/1024)); - push @details, eval { format_field($loc->N("Medium: ")) . $raw_medium->{name} }; - - my @link = get_url_link($upkg, $pkg); - push @details, join("
   ",@link) if(@link); - unshift @details, "
   "; - join("
   ", @details); -} - -sub get_new_deps { - my ($urpm, $upkg) = @_; - - my $deps = slow_func(sub { - my $state = {}; - my $db = open_rpm_db(); - my @requested = $urpm->resolve_requested__no_suggests_( - $db, $state, - { $upkg->id => 1 }, - ); - @requested = $urpm->resolve_requested_suggests($db, $state, \@requested); - undef $db; - my @nodes_with_deps = map { urpm_name($_) } @requested; - my @deps = sort { $a cmp $b } difference2(\@nodes_with_deps, [ urpm_name($upkg) ]); - @deps = $loc->N("All dependencies installed.") if !@deps; - return \@deps; - }); - return $deps; -} - -sub get_url_link { - my ($upkg, $pkg) = @_; - - my $url = $upkg->url || $pkg->{url}; - - if (!$url) { - open_rpm_db()->traverse_tag_find('name', $upkg->name, sub { $url = $_[0]->url; return ($url ? 1 : 0) }); - } - - return if !$url; - - my @a; - push @a, format_field($loc->N("URL: ")) . ${spacing} . "". $url .""; - @a; -} - -sub files_format { - my ($files) = @_; - - return '' . $spacing . "
   " . join("
   ", @$files) . '
'; -} - -#============================================================= - -=head2 format_link - -=head3 INPUT - - $description: Description to be shown as link - $url: to be reach when click on $description link - -=head3 OUTPUT - - $webref: href HTML tag - -=head3 DESCRIPTION - - This function returns an href string to be published - -=cut - -#============================================================= -sub format_link { - my ($description, $url) = @_; - - my $webref = "". $description .""; - - return $webref; -} - -sub _format_pkg_simplifiedinfo { - my ($pkgs, $key, $urpm, $descriptions, $options) = @_; - my ($name) = split_fullname($key); - my $pkg = $pkgs->{$key}; - my $upkg = $pkg->{pkg}; - return if !$upkg; - my $raw_medium = pkg2medium($upkg, $urpm); - my $medium = !$raw_medium->{fake} ? $raw_medium->{name} : undef; - my $update_descr = $descriptions->{$medium}{$name}; - # discard update fields if not matching: - - my $is_update = ($upkg->flag_upgrade && $update_descr && $update_descr->{pre}); - my $summary = get_summary($key); - my $dummy_string = get_main_text($raw_medium, $key, $name, $summary, $is_update, $update_descr); - my $s; - push @$s, $dummy_string; - push @$s, get_advisory_link($update_descr) if $is_update; - - push @$s, get_description($pkg, $update_descr); - - my $installed_version = eval { find_installed_version($upkg) }; - - #push @$s, [ gtkadd(gtkshow(my $details_exp = Gtk2::Expander->new(format_field($loc->N("Details:")))), - # gtknew('TextView', text => get_details($pkg, $upkg, $installed_version, $raw_medium))) ]; - my $detail_link = format_link(format_field($loc->N("Details:")), $hidden_info{details} ); - if ($options->{details}) { - my $details = get_details($pkg, $upkg, $installed_version, $raw_medium); - utf8::encode($details); - $detail_link .= "\n" . $details; - } - push @$s, join("\n", $detail_link, "\n"); - - #push @$s, [ build_expander($pkg, $loc->N("Files:"), 'files', sub { files_format($pkg->{files}) }) ]; - my $files_link = format_link(format_field($loc->N("Files:")), $hidden_info{files} ); - if ($options->{files}) { - my $wait = ManaTools::rpmdragora::wait_msg(); - if (!$pkg->{files}) { - extract_header($pkg, $urpm, 'files', $installed_version); - } - my $files = $pkg->{files} ? files_format($pkg->{files}) : $loc->N("(Not available)"); - utf8::encode($files); - $files_link .= "\n\n" . $files; - ManaTools::rpmdragora::remove_wait_msg($wait); - } - push @$s, join("\n", $files_link, "\n"); - - #push @$s, [ build_expander($pkg, $loc->N("Changelog:"), 'changelog', sub { $pkg->{changelog} }, $installed_version) ]; - my $changelog_link = format_link(format_field($loc->N("Changelog:")), $hidden_info{changelog} ); - if ($options->{changelog}) { - my $wait = ManaTools::rpmdragora::wait_msg(); - my @changelog = $pkg->{changelog} ? @{$pkg->{changelog}} : ( $loc->N("(Not available)") ); - if (!$pkg->{changelog} || !scalar @{$pkg->{changelog}} ) { - # my ($pkg, $label, $type, $get_data, $o_installed_version) = @_; - extract_header($pkg, $urpm, 'changelog', $installed_version); - @changelog = $pkg->{changelog} ? @{$pkg->{changelog}} : ( $loc->N("(Not available)") ); - } - utf8::encode(\@changelog); - - $changelog_link .= "
   " . join("
   ", @changelog); - $changelog_link =~ s|\n||g; - ManaTools::rpmdragora::remove_wait_msg($wait); - } - push @$s, join("\n\n", $changelog_link, "\n"); - - my $deps_link = format_link(format_field($loc->N("New dependencies:")), $hidden_info{new_deps} ); - if ($options->{new_deps}) { - if ($upkg->id) { # If not installed - $deps_link .= "
   " . join("
   ", @{get_new_deps($urpm, $upkg)}); - # push @$s, get_new_deps($urpm, $upkg); - } - } - push @$s, join("\n", $deps_link, "\n"); - - return $s; -} - -sub warn_if_no_pkg { - my ($name) = @_; - my ($short_name) = split_fullname($name); - state $warned; - if (!$warned) { - $warned = 1; - interactive_msg($loc->N("Warning"), - join("\n", - $loc->N("The package \"%s\" was found.", $name), - $loc->N("However this package is not in the package list."), - $loc->N("You may want to update your urpmi database."), - '', - $loc->N("Matching packages:"), - '', - join("\n", sort map { - #-PO: this is list fomatting: "- (medium: )" - #-PO: eg: "- rpmdragora (medium: "Main Release" - $loc->N("- %s (medium: %s)", $_, pkg2medium($pkgs->{$_}{pkg}, $urpm)->{name}); - } grep { /^$short_name/ } keys %$pkgs), - ), - scroll => 1, - ); - } - return 'XXX'; -} - -# -# @method node_state -# -=pod - -=head1 node_state(pkgname) - -=over 4 - -=item returns the state of the node (pkg) querying an urpm object from $pkgs->{$pkgname} - -=over 6 - -=item I - -=item I - -=item I - -=item I - -=item I - -=back - -=back - -=cut - -sub node_state { - my ($name) = @_; - #- checks $_[0] -> hack for partial tree displaying - return 'XXX' if !$name; - my $pkg = $pkgs->{$name}; - my $urpm_obj = $pkg->{pkg}; - return warn_if_no_pkg($name) if !$urpm_obj; - $pkg->{selected} ? - ($urpm_obj->flag_installed ? - ($urpm_obj->flag_upgrade ? 'to_install' : 'to_remove') - : 'to_install') - : ($urpm_obj->flag_installed ? - ($pkgs->{$name}{is_backport} ? 'backport' : - ($urpm_obj->flag_upgrade ? 'to_update' - : ($urpm_obj->flag_base ? 'base' : 'installed'))) - : 'uninstalled'); -} - -my ($common, $w, %wtree, %ptree, %pix, @table_item_list); - -# -# @method set_node_state -# - -=pod - -=head1 set_node_state($tblItem, $state, $detail_list) - -=over 4 - -=item setup the table row by adding a cell representing the state of the package - -=item see node_state - -=over 6 - -=item B<$tblItem> , YTableItem instance - -=item B<$state> , string containing the state of the package from node_state - -=item B<$detail_list> , reference to the YCBTable - -=back - -=back - -=cut - -sub set_node_state { - my ($tblItem, $state, $detail_list) = @_; - return if $state eq 'XXX' || !$state; - - if ($detail_list) { - $detail_list->parent()->parent()->startMultipleChanges(); - $tblItem->addCell($state,"/usr/share/rpmdrake/icons/state_$state.png") if(ref $tblItem eq "yui::YCBTableItem"); - if(to_bool(member($state, qw(base installed to_install)))){ - # it should be parent()->setChecked(1) - $detail_list->checkItem($tblItem, 1); - # $tblItem->setSelected(1); - }else{ - $detail_list->checkItem($tblItem, 0); - # $tblItem->setSelected(0); - } -# if(!to_bool($state ne 'base')){ -# #$iter->cell(0)->setLabel('-'); -# $tblItem->cell(0)->setLabel('-'); -# } - $detail_list->parent()->parent()->doneMultipleChanges(); - } - else { - # no item list means we use just the item to add state information - $tblItem->addCell($state,"/usr/share/rpmdrake/icons/state_$state.png") if(ref $tblItem eq "yui::YCBTableItem"); - $tblItem->check(to_bool(member($state, qw(base installed to_install)))); -# $tblItem->cell(0)->setLabel('-') if !to_bool($state ne 'base'); - } -} - -sub set_leaf_state { - my ($leaf, $state, $detail_list) = @_; - # %ptree is a hash using the pkg name as key and a monodimensional array (?) as value - # were it is stored the index of the item into the table - my $nodeIndex = $ptree{$leaf}[0]; - my $node = itemAt($detail_list,$nodeIndex); - set_node_state($node, $state, $detail_list); -} - -#============================================================= - -=head2 grep_unselected - -=head3 INPUT - - $l: ARRAY reference containing the list of package fullnames - -=head3 OUTPUT - - \@result: ARRAY reference containing the list of packages - that are not selected - -=head3 DESCRIPTION - - Function returning the list of not selected packages - -=cut - -#============================================================= -sub grep_unselected { - my $l = shift; - - my @result = grep { exists $pkgs->{$_} && !$pkgs->{$_}{selected} } @{$l} ; - return \@result; -} - -my %groups_tree = (); - -# -# @method add_parent -# - -=pod - -=head1 add_parent($tree, $root, $state) - -=over 4 - -=item populates the treeview with the rpm package groups - -=over 6 - -=item B<$tree> , YTree for the group of the rpm packages - -=item B<$root> , string containing a path-like sequence (e.g. "foo|bar") - -=item B<$state> , not used currently (from the old impl.) - -=back - -=back - -=cut - -sub add_parent { - my ($tree, $root, $state) = @_; - $tree or return undef; - #$root or return undef; - my $parent = 0; - - carp "WARNING TODO: add_parent to be removed (called with " . $root . ")\n"; - - my @items = split('\|', $root); - my $i = 0; - my $parentItem = undef; - my $rootItem = undef; - for my $item (@items) { - chomp $item; - $item = trim($item); - my $treeItem; - if($i == 0){ - $parent = $item; - $treeItem = new yui::YTreeItem($item,get_icon_path($item,0),0); - $rootItem = $treeItem; - $parentItem = $treeItem; - if(!defined($groups_tree{$parent})) { - $groups_tree{$parent}{parent} = $treeItem; - $groups_tree{$parent}{children} = (); -# $tree->addItem($groups_tree{$parent}{'parent'}); - } - }else{ - #if(any { $_ ne $item } @{$groups_tree{$parent}{'children'}}){ - # push @{$groups_tree{$parent}{'children'}}, $item; - #} - $parentItem = new yui::YTreeItem($parentItem, $item,get_icon_path($item,$parent),0); - if(!defined($groups_tree{$parent}{'children'}{$item})){ -# $treeItem = new yui::YTreeItem($treeItem, $item,get_icon_path($item,$parent),0); - $treeItem = $parentItem; - $groups_tree{$parent}{'children'}{$item} = $treeItem; - $groups_tree{$parent}{'parent'}->addChild($treeItem); - } - } - $i++; - } - $tree->addItem($rootItem) if $rootItem; - $tree->rebuildTree(); -} - - -#============================================================= - -=head2 add_tree_item - -=head3 INPUT - -=item B<$tree> YTree for the group of the rpm packages - -=item B<$item> string containing a group (to be added as leaf node) - -=item B<$selected> if the new item is selected - - -=head3 DESCRIPTION - - This function add a group to the tree view - -=cut - -#============================================================= -sub add_tree_item { - my ($tree, $item, $selected) = @_; - - $tree or return undef; - - $tree->startMultipleChanges(); - my $treeItem = new yui::YTreeItem($item, get_icon_path($item, 0), 0); - $treeItem->setSelected($selected); - - $tree->addItem($treeItem); - $tree->rebuildTree(); - $tree->doneMultipleChanges(); -} - -#============================================================= - -=head2 add_package_item - -=head3 INPUT - -=item B<$item_list>: reference to a YItemCollection - -=item B<$pkg_name>: package name - -=item B<$select>: select given package - -=head3 DESCRIPTION - - populates the item list for the table view with the given rpm package - -=cut - -#============================================================= -sub add_package_item { - my ($item_list, $pkg_name, $select) = @_; - - return if !$pkg_name; - - return if ref($item_list) ne "yui::YItemCollection"; - - my $state = node_state($pkg_name) or return; - - my $iter; - if (is_a_package($pkg_name)) { - my ($name, $version, $release, $arch) = split_fullname($pkg_name); - - $name = "" if !defined($name); - $version = "" if !defined($version); - $release = "" if !defined($release); - $arch = "" if !defined($arch); - - my $newTableItem = new yui::YCBTableItem( - $name, - get_summary($pkg_name), - $version, - $release, - $arch - ); - - $newTableItem->setSelected($select); - - set_node_state($newTableItem, $state); - - $item_list->push($newTableItem); - - $newTableItem->DISOWN(); - } - else { - carp $pkg_name . " is not a leaf package and that is not managed!"; - } - -} - -# -# @method add_node -# - -=pod - -=head1 add_node($leaf, $root, $options) - -=over 4 - -=item populates the tableview with the rpm packages or the treeview with the package groups - -=over 6 - -=item B<$leaf> , could be the name of a package or the name of a group o packages - -=item B<$root> , string containing a path-like sequence (e.g. "foo|bar") - -=item B<$state> , the string with the state of the package if leaf is the name of a package - -=back - -=back - -=cut - -sub add_node { - my ($leaf, $root, $o_options) = @_; - my $state = node_state($leaf) or return; - if ($leaf) { - my $iter; - if (is_a_package($leaf)) { -carp "TODO: add_node is_a_package(\$leaf)" . $leaf . "\n"; - - my ($name, $version, $release, $arch) = split_fullname($leaf); - #OLD $iter = $w->{detail_list_model}->append_set([ $pkg_columns{text} => $leaf, - # $pkg_columns{short_name} => format_name_n_summary($name, get_summary($leaf)), - # $pkg_columns{version} => $version, - # $pkg_columns{release} => $release, - # $pkg_columns{arch} => $arch, - # ]); - $name = "" if(!defined($name)); - $version = "" if(!defined($version)); - $release = "" if(!defined($release)); - $arch = "" if(!defined($arch)); - #my $newTableItem = new yui::YTableItem(format_name_n_summary($name, get_summary($leaf)), - my $newTableItem = new yui::YCBTableItem($name, - get_summary($leaf), - $version, - $release, - $arch); - $w->{detail_list}->addItem($newTableItem); - set_node_state($newTableItem, $state, $w->{detail_list}); - # $ptree{$leaf} = [ $newTableItem->label() ]; - $ptree{$leaf} = [ $newTableItem->index() ]; - $table_item_list[$newTableItem->index()] = $leaf; - $newTableItem->DISOWN(); - } else { - carp "TODO: add_node !is_a_package(\$leaf) not MANAGED\n"; -# $iter = $w->{tree_model}->append_set(add_parent($w->{tree},$root, $state), [ $grp_columns{label} => $leaf ]); - #push @{$wtree{$leaf}}, $iter; - } - } else { - carp "TODO: add_node !\$leaf not MANAGED\n"; - -# my $parent = add_parent($w->{tree}, $root, $state); - #- hackery for partial displaying of trees, used in rpmdragora: - #- if leaf is void, we may create the parent and one child (to have the [+] in front of the parent in the ctree) - #- though we use '' as the label of the child; then rpmdragora will connect on tree_expand, and whenever - #- the first child has '' as the label, it will remove the child and add all the "right" children -# $o_options->{nochild} or $w->{tree_model}->append_set($parent, [ $grp_columns{label} => '' ]); # test $leaf? - } -} - -my ($prev_label); -sub update_size { - my ($common) = shift @_; - if ($w->{status}) { - my $new_label = $common->{get_status}(); - $prev_label="" if(!defined($prev_label)); - $prev_label ne $new_label and $w->{status}->setText($prev_label = $new_label); - } -} - -#============================================================= - -=head2 treeview_children - -=head3 INPUT - - $tbl: YCBTable widget containing the package list shown - -=head3 OUTPUT - - \@l: ARRAY reference containing the list - of YItem contained into YCBTable - -=head3 DESCRIPTION - - This functions just returns the YCBTable content such as all the - YItem objects - -=cut - -#============================================================= -sub treeview_children { - my ($tbl) = @_; - my $it; - my @l; - my $i=0; - # using iterators - for ($it = $tbl->itemsBegin(); $it != $tbl->itemsEnd(); ) { - my $item = $tbl->YItemIteratorToYItem($it); - push @l, $item; - $it = $tbl->nextItem($it); - $i++; - if ($i == $tbl->itemsCount()) { - last; - } - } - - return \@l; -} - -#============================================================= - -=head2 children - -=head3 INPUT - - $tbl: YCBTable object - @table_item_list: array containing package fullnames - -=head3 OUTPUT - - \@result: ARRAY reference containing package fullnames - -=head3 DESCRIPTION - - This Function return the list of package fullnames - -=cut - -#============================================================= - -sub children { - my ($tbl, $table_item_list) = @_; - # map { $w->{detail_list}->get($_, $pkg_columns{text}) } treeview_children($w->{detail_list}); - # map { $table_item_list[$_->index()] } treeview_children($w->{detail_list}); - my $children_list = treeview_children($tbl); - my @result; - for my $child(@{$children_list}){ - push @result, $table_item_list->[$child->index()]; - } - return \@result; -} - -sub itemAt { - my ($table, $index) = @_; - return $table->item($index); - #return bless ($table->item($index),'yui::YTableItem'); - #foreach my $item(treeview_children($table)){ - # if($item->index() == $index){ - # print "\n== item label ".$item->label()."\n"; - # return bless ($item, 'yui::YTableItem'); - # } - #} -} - - -#============================================================= - -=head2 toggle_all - -=head3 INPUT - - $common: HASH reference containing (### TODO ###) - widgets => { - detail_list: YTable reference (?) - } - table_item_list => array containing package fullnames - partialsel_unsel => (?) - - set_state_callback => set state callback invoked by - toggle_nodes if needed. if undef - set_leaf_state is used. - $_val: value to be set (so it seems not a toggle! unused?) - -=head3 DESCRIPTION - -This method (should) check -or un-check if already checked- all -the packages - -=cut - -#============================================================= -sub toggle_all { - my ($common, $_val) = @_; - my $w = $common->{widgets}; - - my $l = children($w->{detail_list}, $common->{table_item_list}) or return; - - my $set_state = $common->{set_state_callback} ? $common->{set_state_callback} : \&set_leaf_state; - my $unsel = grep_unselected($l); - my $p = $unsel ? - #- not all is selected, select all if no option to potentially override - (exists $common->{partialsel_unsel} && $common->{partialsel_unsel}->($unsel, $l) ? difference2($l, $unsel) : $unsel) - : $l; - # toggle_nodes($w->{detail_list}, $w->{detail_list_model}, \&set_leaf_state, node_state($p[0]), @p); - - toggle_nodes($w->{detail_list}, $w->{detail_list}, $set_state, node_state($p->[0]), @{$p}); - update_size($common); -} - -sub fast_toggle { - my ($item) = @_; - #gtkset_mousecursor_wait($w->{w}{rwindow}->window); - #my $_cleaner = before_leaving { gtkset_mousecursor_normal($w->{w}{rwindow}->window) }; - my $name = $common->{table_item_list}[$item->index()]; - my $urpm_obj = $pkgs->{$name}{pkg}; - if ($urpm_obj->flag_base) { - interactive_msg($loc->N("Warning"), $loc->N("Removing package %s would break your system", $name)); - return ''; - } - if ($urpm_obj->flag_skip) { - interactive_msg($loc->N("Warning"), $loc->N("The \"%s\" package is in urpmi skip list.\nDo you want to select it anyway?", $name), yesno => 1) or return ''; - $urpm_obj->set_flag_skip(0); - } - if ($ManaTools::Rpmdragora::pkg::need_restart && !$priority_up_alread_warned) { - $priority_up_alread_warned = 1; - interactive_msg($loc->N("Warning"), '' . $loc->N("Rpmdragora or one of its priority dependencies needs to be updated first. Rpmdragora will then restart.") . '' . "\n\n"); - } - # toggle_nodes($w->{tree}->window, $w->{detail_list_model}, \&set_leaf_state, $w->{detail_list_model}->get($iter, $pkg_columns{state}), - - my $old_status = node_state($name); - - #$DB::single = 1; - -# my $old_state; -# if($item->checked()){ -# $old_state = "to_install"; -# }else{ -# $old_state = "to_remove"; -# } - toggle_nodes($w->{tree}, $w->{detail_list}, \&set_leaf_state, $old_status, $name); - update_size($common); -}; - -# ask_browse_tree_given_widgets_for_rpmdragora will run gtk+ loop. its main parameter "common" is a hash containing: -# - a "widgets" subhash which holds: -# o a "w" reference on a ugtk2 object -# o "tree" & "info" references a TreeView -# o "info" is a TextView -# o "tree_model" is the associated model of "tree" -# o "status" references a Label -# - some methods: get_info, node_state, build_tree, partialsel_unsel, grep_unselected, rebuild_tree, toggle_nodes, get_status -# - "tree_submode": the default mode (by group, ...), ... -# - "state": a hash of misc flags: => { flat => '0' }, -# o "flat": is the tree flat or not -# - "tree_mode": mode of the tree ("gui_pkgs", "by_group", ...) (mainly used by rpmdragora) - -sub ask_browse_tree_given_widgets_for_rpmdragora { - ($common) = @_; - $w = $common->{widgets}; - - $common->{table_item_list} = \@table_item_list; - - $w->{detail_list} ||= $w->{tree}; - #$w->{detail_list_model} ||= $w->{tree_model}; - - $common->{add_parent} = \&add_parent; - my $clear_all_caches = sub { - %ptree = %wtree = (); - @table_item_list = (); - }; - $common->{clear_all_caches} = $clear_all_caches; - $common->{delete_all} = sub { - $clear_all_caches->(); - %groups_tree = (); - }; - $common->{rebuild_tree} = sub { - $common->{delete_all}->(); - $common->{build_tree}($common->{state}{flat}, $common->{tree_mode}); - update_size($common); - }; - $common->{delete_category} = sub { - my ($cat) = @_; - carp "WARNING TODO delete_category to be removed!"; - exists $wtree{$cat} or return; - %ptree = (); - update_size($common); - return; - }; - $common->{add_nodes} = sub { - my (@nodes) = @_; - carp "TODO ==================> ADD NODES - add packages (" . scalar(@nodes) . ") \n"; - yui::YUI::app()->busyCursor(); - - my $lastItem = $w->{detail_list}->selectedItem() ? $w->{detail_list}->selectedItem()->label() : ""; - $w->{detail_list}->startMultipleChanges(); - $w->{detail_list}->deleteAllItems(); - my $itemColl = new yui::YItemCollection; - - @table_item_list = (); - my $index = 0; - foreach(@nodes){ - add_package_item($itemColl, $_->[0], ($lastItem eq $_->[0])); - warn "Unmanaged param " . $_->[2] if defined $_->[2]; - $ptree{$_->[0]} = [ $index ]; - $index++; - push @table_item_list, $_->[0]; - } - - update_size($common); - $w->{detail_list}->addItems($itemColl); - $w->{detail_list}->doneMultipleChanges(); - yui::YUI::app()->normalCursor(); - }; - - $common->{rebuild_tree}->(); - update_size($common); - $common->{initial_selection} and toggle_nodes($w->{tree}->window, $w->{detail_list}, \&set_leaf_state, undef, @{$common->{initial_selection}}); - my $_b = before_leaving { $clear_all_caches->() }; - $common->{init_callback}->() if $common->{init_callback}; - - $w->{w}; -} - -our $find_entry; - -sub reset_search() { - return if !$common; - -# TODO $common->{delete_category}->($_) foreach $results_ok, $results_none; - # clear package list: - yui::YUI::app()->busyCursor(); - my $wdgt = $common->{widgets}; - $wdgt->{detail_list}->startMultipleChanges(); - $wdgt->{detail_list}->deleteAllItems(); - $wdgt->{detail_list}->doneMultipleChanges(); - yui::YUI::app()->normalCursor(); -} - -sub is_a_package { - my ($pkg) = @_; - return exists $pkgs->{$pkg}; -} - -sub switch_pkg_list_mode { - my ($mode) = @_; - return if !$mode; - return if !$filter_methods{$mode}; - $force_displaying_group = 1; - $filter_methods{$mode}->(); -} - -sub is_updatable { - my $p = $pkgs->{$_[0]}; - $p->{pkg} && !$p->{selected} && $p->{pkg}->flag_installed && $p->{pkg}->flag_upgrade; -} - -sub pkgs_provider { - my ($mode, %options) = @_; - return if !$mode; - my $h = &get_pkgs(%options); - ($urpm, $descriptions) = @$h{qw(urpm update_descr)}; - $pkgs = $h->{all_pkgs}; - %filters = ( - non_installed => $h->{installable}, - installed => $h->{installed}, - all => [ keys %$pkgs ], - ); - my %tmp_filter_methods = ( - all => sub { - [ difference2([ keys %$pkgs ], $h->{inactive_backports}) ]; - }, - all_updates => sub { - # potential "updates" from media not tagged as updates: - if (!$options{pure_updates} && !$ManaTools::Rpmdragora::pkg::need_restart) { - [ @{$h->{updates}}, - difference2([ grep { is_updatable($_) } @{$h->{installable}} ], $h->{backports}) ]; - } else { - [ difference2($h->{updates}, $h->{inactive_backports}) ]; - } - }, - backports => sub { $h->{backports} }, - meta_pkgs => sub { - [ difference2($h->{meta_pkgs}, $h->{inactive_backports}) ]; - }, - gui_pkgs => sub { - [ difference2($h->{gui_pkgs}, $h->{inactive_backports}) ]; - }, - ); - foreach my $importance (qw(bugfix security normal)) { - $tmp_filter_methods{$importance} = sub { - my @media = keys %$descriptions; - [ grep { - my ($name) = split_fullname($_); - my $medium = MDK::Common::Func::find { $descriptions->{$_}{$name} } @media; - $medium && $descriptions->{$medium}{$name}{importance} eq $importance } @{$h->{updates}} ]; - }; - } - - undef %filter_methods; - foreach my $type (keys %tmp_filter_methods) { - $filter_methods{$type} = sub { - $force_rebuild = 1; # force rebuilding tree since we changed filter (FIXME: switch to SortModel) - @filtered_pkgs = intersection($filters{$filter->[0]}, $tmp_filter_methods{$type}->()); - }; - } - - switch_pkg_list_mode($mode); -} - -sub closure_removal { - local $urpm->{state} = {}; - urpm::select::find_packages_to_remove($urpm, $urpm->{state}, \@_); -} - -sub is_locale_available { - my ($name) = @_; - any { $urpm->{depslist}[$_]->flag_selected } keys %{$urpm->{provides}{$name} || {}} and return 1; - my $found; - open_rpm_db()->traverse_tag_find('name', $name, sub { $found = 1 }); - return $found; -} - -sub callback_choices { - my (undef, undef, undef, $choices) = @_; - return $choices->[0] if $::rpmdragora_options{auto}; - foreach my $pkg (@$choices) { - foreach ($pkg->requires_nosense) { - /locales-/ or next; - is_locale_available($_) and return $pkg; - } - } - my $callback = sub { interactive_msg($loc->N("More information on package..."), get_info($_[0]), scroll => 1) }; - $choices = [ sort { $a->name cmp $b->name } @$choices ]; - my @choices = interactive_list_($loc->N("Please choose"), (scalar(@$choices) == 1 ? - $loc->N("The following package is needed:") : $loc->N("One of the following packages is needed:")), - [ map { urpm_name($_) } @$choices ], $callback, nocancel => 1); - defined $choices[0] ? $choices->[$choices[0]] : undef; -} - -#============================================================= - -=head2 info_details - -=head3 INPUT - - $info_detail_selected: string to get more info details - (see %hidden_info) - $info_options: reference to info options that are going to changed - based on passed $info_detail_selected - -=head3 OUTPUT - - [0, 1]: 0 if $info_detail_selected not valid, 1 otherwise - -=head3 DESCRIPTION - - This function change the info_options accordingly to the string passed - returning 0 if the string is not managed (see %hidden_info) - -=cut - -#============================================================= -sub info_details { - my ($info_detail_selected, $info_options) = @_; - - foreach my $k (keys %hidden_info) { - if ($info_detail_selected eq $hidden_info{$k}) { - $info_options->{$k} = $info_options->{$k} ? 0 : 1; - return 1; - } - } - return 0; -} - -#============================================================= - -=head2 setInfoOnWidget - -=head3 INPUT - - $pckgname: full name of the package - $infoWidget: YRichText object to fill - -=head3 DESCRIPTION - - This function writes on a YRichText object package info - -=cut - -#============================================================= -sub setInfoOnWidget { - my ($pkgname, $infoWidget, $options) = @_; - - return if( ref $infoWidget ne "yui::YRichText"); - - $infoWidget->setValue(""); - - my $info_text = ""; - - my @data = get_info($pkgname, $options); - for(@{$data[0]}){ - if(ref $_ ne "ARRAY"){ - $info_text .= $_ . "
   "; - }else{ - for my $subitem(@{$_}) { - $info_text .= "
" . "
   " . $subitem; - } - } - } - # change \n to
- $info_text =~ s|\n|
|g; - - $infoWidget->setValue($info_text); -} - - -sub deps_msg { - return 1 if $dont_show_selections->[0]; - my ($title, $msg, $nodes, $nodes_with_deps) = @_; - - my @deps = sort { $a cmp $b } difference2($nodes_with_deps, $nodes); - @deps > 0 or return 1; - - my $appTitle = yui::YUI::app()->applicationTitle(); - - ## set new title to get it in dialog - yui::YUI::app()->setApplicationTitle($title); -# TODO icon if needed -# yui::YUI::app()->setApplicationIcon($which_icon); - - my $factory = yui::YUI::widgetFactory; - - ## | [msg-label] | - ## | | - ## | pkg-list | info on selected pkg |(1) - ## | | - ## | [cancel] [ok] | - #### - # (1) info on pkg list: - # [ label info ] - # sub info on click (Details, Files, Changelog, New dependencies) - - my $dialog = $factory->createPopupDialog; - my $vbox = $factory->createVBox( $dialog ); - my $msgBox = $factory->createLabel($vbox, $msg, 1); -# my $hbox = $factory->createHBox( $vbox ); - my $pkgList = $factory->createSelectionBox( $vbox, $loc->N("Select package") ); - $factory->createVSpacing($vbox, 1); - -# my $frame = $factory->createFrame ($hbox, $loc->N("Information on packages")); -# my $frmVbox = $factory->createVBox( $frame ); - my $infoBox = $factory->createRichText($vbox, "", 0); - $pkgList->setWeight($yui::YD_HORIZ, 2); - $infoBox->setWeight($yui::YD_HORIZ, 3); - $factory->createVSpacing($vbox, 1); - my $hbox = $factory->createHBox( $vbox ); - my $align = $factory->createRight($hbox); - my $cancelButton = $factory->createPushButton($align, $loc->N("&Cancel")); - my $okButton = $factory->createPushButton($hbox, $loc->N("&Ok")); - - # adding packages to the list - my $itemColl = new yui::YItemCollection; - foreach my $p (map { scalar(urpm::select::translate_why_removed_one($urpm, $urpm->{state}, $_)) } @deps) { - my $item = new yui::YTableItem ("$p"); - $item->setLabel( $p ); - $itemColl->push($item); - $item->DISOWN(); - } - $pkgList->addItems($itemColl); - $pkgList->setImmediateMode(1); - my $item = $pkgList->selectedItem(); - if ($item) { - my $pkg = $item->label(); - setInfoOnWidget($pkg, $infoBox); - } - - my $retval = 0; - my $info_options = {}; - while(1) { - my $event = $dialog->waitForEvent(); - my $eventType = $event->eventType(); - - #event type checking - if ($eventType == $yui::YEvent::CancelEvent) { - last; - } - elsif ($eventType == $yui::YEvent::MenuEvent) { - my $item = $event->item(); - if (!$item) { - #URL emitted or at least a ref into RichText widget - my $url = yui::toYMenuEvent($event)->id (); - if (ManaTools::Rpmdragora::gui::info_details($url, $info_options) ) { - $item = $pkgList->selectedItem(); - my $pkg = $item->label(); - ManaTools::Rpmdragora::gui::setInfoOnWidget($pkg, $infoBox, $info_options); - } - else { - # default it's really a URL - ManaTools::Rpmdragora::gui::run_browser($url); - } - } - } - elsif ($eventType == $yui::YEvent::WidgetEvent) { - ### widget - my $widget = $event->widget(); - if ($widget == $pkgList) { - #change info - $item = $pkgList->selectedItem(); - $info_options = {}; - if ( $item ) { - my $pkg = $item->label(); - setInfoOnWidget($pkg, $infoBox); - } - } - elsif ($widget == $okButton) { - $retval = 1; - last; - } - elsif ($widget == $cancelButton) { - last; - } - } - } - - destroy $dialog; - - # restore original title - yui::YUI::app()->setApplicationTitle($appTitle) if $appTitle; - - return $retval; -} - -# set_state <- package-fullname, node_state = {to_install, to_remove,...}, list=YTable -sub toggle_nodes { - my ($widget, $detail_list, $set_state, $old_state, @nodes) = @_; - - @nodes = grep { exists $pkgs->{$_} } @nodes - or return; - #- avoid selecting too many packages at once - return if !$dont_show_selections->[0] && @nodes > 2000; - my $new_state = !$pkgs->{$nodes[0]}{selected}; - - my @nodes_with_deps; - - my $bar_id = statusbar_msg($loc->N("Checking dependencies of package..."), 0); - - my $warn_about_additional_packages_to_remove = sub { - my ($msg) = @_; - statusbar_msg_remove($bar_id); - deps_msg($loc->N("Some additional packages need to be removed"), - MDK::Common::String::formatAlaTeX($msg) . "\n\n", - \@nodes, \@nodes_with_deps) or @nodes_with_deps = (); - }; - - if (member($old_state, qw(to_remove installed))) { # remove pacckages - if ($new_state) { - my @remove; - slow_func(sub { @remove = closure_removal(@nodes) }); - @nodes_with_deps = grep { !$pkgs->{$_}{selected} && !/^basesystem/ } @remove; - $warn_about_additional_packages_to_remove->( - $loc->N("Because of their dependencies, the following package(s) also need to be removed:")); - my @impossible_to_remove; - foreach (grep { exists $pkgs->{$_}{base} } @remove) { - ${$pkgs->{$_}{base}} == 1 ? push @impossible_to_remove, $_ : ${$pkgs->{$_}{base}}--; - } - @impossible_to_remove and interactive_msg($loc->N("Some packages cannot be removed"), - $loc->N("Removing these packages would break your system, sorry:\n\n") . - format_list(@impossible_to_remove)); - @nodes_with_deps = difference2(\@nodes_with_deps, \@impossible_to_remove); - } else { - @nodes_with_deps = grep { intersection(\@nodes, [ closure_removal($_) ]) } - grep { $pkgs->{$_}{selected} && !member($_, @nodes) } keys %$pkgs; - push @nodes_with_deps, @nodes; - $warn_about_additional_packages_to_remove->( - $loc->N("Because of their dependencies, the following package(s) must be unselected now:\n\n")); - $pkgs->{$_}{base} && ${$pkgs->{$_}{base}}++ foreach @nodes_with_deps; - } - } else { - if ($new_state) { - if (@nodes > 1) { - #- unselect i18n packages of which locales is not already present (happens when user clicks on KDE group) - my @bad_i18n_pkgs; - foreach my $sel (@nodes) { - foreach ($pkgs->{$sel}{pkg}->requires_nosense) { - /locales-([^-]+)/ or next; - $sel =~ /-$1[-_]/ && !is_locale_available($_) and push @bad_i18n_pkgs, $sel; - } - } - @nodes = difference2(\@nodes, \@bad_i18n_pkgs); - } - my @requested; - @requested = $urpm->resolve_requested( - open_rpm_db(), $urpm->{state}, - { map { $pkgs->{$_}{pkg}->id => 1 } @nodes }, - callback_choices => \&callback_choices, - ); - @nodes_with_deps = map { urpm_name($_) } @requested; - statusbar_msg_remove($bar_id); - if (!deps_msg($loc->N("Additional packages needed"), - MDK::Common::String::formatAlaTeX($loc->N("To satisfy dependencies, the following package(s) also need to be installed:\n\n")) . "\n\n", - \@nodes, \@nodes_with_deps)) { - @nodes_with_deps = (); - $urpm->disable_selected(open_rpm_db(), $urpm->{state}, @requested); - goto packages_selection_ok; - } - - if (my $conflicting_msg = urpm::select::conflicting_packages_msg($urpm, $urpm->{state})) { - if (!interactive_msg($loc->N("Conflicting Packages"), $conflicting_msg, yesno => 1, scroll => 1)) { - @nodes_with_deps = (); - $urpm->disable_selected(open_rpm_db(), $urpm->{state}, @requested); - goto packages_selection_ok; - } - } - - if (my @cant = sort(difference2(\@nodes, \@nodes_with_deps))) { - my @ask_unselect = urpm::select::unselected_packages($urpm->{state}); - my @reasons = map { - my $cant = $_; - my $unsel = MDK::Common::Func::find { $_ eq $cant } @ask_unselect; - $unsel - ? join("\n", urpm::select::translate_why_unselected($urpm, $urpm->{state}, $unsel)) - : ($pkgs->{$_}{pkg}->flag_skip ? $loc->N("%s (belongs to the skip list)", $cant) : $cant); - } @cant; - my $count = @reasons; - interactive_msg( - ($count == 1 ? $loc->N("One package cannot be installed") : $loc->N("Some packages cannot be installed")), - ($count == 1 ? - $loc->N("Sorry, the following package cannot be selected:\n\n%s", format_list(@reasons)) - : $loc->N("Sorry, the following packages cannot be selected:\n\n%s", format_list(@reasons))), - scroll => 1, - ); - foreach (@cant) { - next unless $pkgs->{$_}{pkg}; - $pkgs->{$_}{pkg}->set_flag_requested(0); - $pkgs->{$_}{pkg}->set_flag_required(0); - } - } - packages_selection_ok: - } else { - my @unrequested; - @unrequested = $urpm->disable_selected(open_rpm_db(), $urpm->{state}, - map { $pkgs->{$_}{pkg} } @nodes); - @nodes_with_deps = map { urpm_name($_) } @unrequested; - statusbar_msg_remove($bar_id); - if (!deps_msg($loc->N("Some packages need to be removed"), - $loc->N("Because of their dependencies, the following package(s) must be unselected now:\n\n"), - \@nodes, \@nodes_with_deps)) { - @nodes_with_deps = (); - $urpm->resolve_requested(open_rpm_db(), $urpm->{state}, { map { $_->id => 1 } @unrequested }); - goto packages_unselection_ok; - } - packages_unselection_ok: - } - } - - foreach (@nodes_with_deps) { - #- some deps may exist on some packages which aren't listed because - #- not upgradable (older than what currently installed) - exists $pkgs->{$_} or next; - if (!$pkgs->{$_}{pkg}) { #- can't be removed # FIXME; what about next packages in the loop? - undef $pkgs->{$_}{selected}; - Sys::Syslog::syslog('info|local1', "can't be removed: $_"); - } else { - $pkgs->{$_}{selected} = $new_state; - } - # invoke set_leaf_state($pkgname, node_state, ) - # node_state = {to_install, to_remove,...} - - $set_state->($_, node_state($_), $detail_list); - if (my $pkg = $pkgs->{$_}{pkg}) { - # FIXME: shouldn't we threat all of them as POSITIVE (as selected size) - $size_selected += $pkg->size * ($pkg->flag_installed && !$pkg->flag_upgrade ? ($new_state ? -1 : 1) : ($new_state ? 1 : -1)); - } - } -} - -sub is_there_selected_packages() { - int(grep { $pkgs->{$_}{selected} } keys %$pkgs); -} - -sub real_quit() { - if (is_there_selected_packages()) { - return interactive_msg($loc->N("Some packages are selected."), $loc->N("Some packages are selected.") . "\n" . $loc->N("Do you really want to quit?"), yesno => 1); - } - - return 1; -} - -sub do_action__real { - my ($options, $callback_action, $o_info) = @_; - require urpm::sys; - if (!urpm::sys::check_fs_writable()) { - $urpm->{fatal}(1, $loc->N("Error: %s appears to be mounted read-only.", $urpm::sys::mountpoint)); - return 1; - } - if (!$ManaTools::Rpmdragora::pkg::need_restart && !is_there_selected_packages()) { - interactive_msg($loc->N("You need to select some packages first."), $loc->N("You need to select some packages first.")); - return 1; - } - my $size_added = MDK::Common::Math::sum(map { MDK::Common::Func::if_($_->flag_selected && !$_->flag_installed, $_->size) } @{$urpm->{depslist}}); - if ($MODE eq 'install' && $size_free - $size_added/1024 < 50*1024) { - interactive_msg($loc->N("Too many packages are selected"), - $loc->N("Warning: it seems that you are attempting to add so many -packages that your filesystem may run out of free diskspace, -during or after package installation ; this is particularly -dangerous and should be considered with care. - -Do you really want to install all the selected packages?"), yesno => 1) - or return 1; - } - my $res = $callback_action->($urpm, $pkgs); - if (!$res) { - $force_rebuild = 1; - pkgs_provider($options->{tree_mode}, MDK::Common::Func::if_($ManaTools::Rpmdragora::pkg::probe_only_for_updates, pure_updates => 1), skip_updating_mu => 1); - reset_search(); - $size_selected = 0; - (undef, $size_free) = MDK::Common::System::df('/usr'); - $options->{rebuild_tree}->() if $options->{rebuild_tree}; - $o_info->setValue("") if $o_info; - } - $res; -} - -sub do_action { - my ($options, $callback_action, $o_info) = @_; - my $res = eval { do_action__real($options, $callback_action, $o_info) }; - my $err = $@; - # FIXME: offer to report the problem into bugzilla: - if ($err && $err !~ /cancel_perform/) { - interactive_msg($loc->N("Fatal error"), - $loc->N("A fatal error occurred: %s.", $err)); - } - $res; -} - -sub translate_group { - join('/', map { $loc->N($_) } split m|/|, $_[0]); -} - -sub ctreefy { - join('|', map { $loc->N($_) } split m|/|, $_[0]); -} - -sub _build_tree { - my ($tree, $pkg_by_group_hash, @pkg_name_and_group_list) = @_; - - print "TODO ====> BUILD TREE\n"; - - yui::YUI::app()->busyCursor(); - - #- we populate all the groups tree at first - %{$pkg_by_group_hash} = (); - # better loop on packages, create groups tree and push packages in the proper place: - my @groups = (); - foreach my $pkg (@pkg_name_and_group_list) { - my $grp = $pkg->[1]; - # no state for groups (they're not packages and thus have no state) - push @groups, $grp; - - $pkg_by_group_hash->{$grp} ||= []; - push @{$pkg_by_group_hash->{$grp}}, $pkg; - } - - my $tree_hash = ManaTools::Shared::pathList2hash({ - paths => \@groups, - separator => '|', - }); - - $tree->startMultipleChanges(); - my $selected = $tree->selectedItem(); - my $groupname = group_path_name($selected) if $selected; - - $tree->deleteAllItems() if $tree->hasItems(); - - # TODO fixing geti icon api to get a better hash from the module - my %icons = (); - foreach my $group (@groups) { - next if defined($icons{$group}); - my @items = split('\|', $group); - if (scalar(@items) > 1) { - $icons{$items[0]} = get_icon_path($items[0], 0); - $icons{$group} = get_icon_path($items[1], $items[0]) - } - else { - $icons{$group} = get_icon_path($group, 0); - } - } - - my $itemColl = new yui::YItemCollection; - $shared_gui->hashTreeToYItemCollection({ - collection => $itemColl, - hash_tree => $tree_hash, - icons => \%icons, - default_item_separator => '|', - default_item => $groupname, - }); - - $tree->addItems($itemColl); - $tree->doneMultipleChanges(); - $tree->rebuildTree(); - yui::YUI::app()->normalCursor(); -} - - -sub build_tree { - my ($tree, $pkg_by_group_hash, $options, $force_rebuild, $flat, $mode) = @_; - state $old_mode; - $mode = $options->{rmodes}{$mode} || $mode; - $old_mode = '' if(!defined($old_mode)); - return if $old_mode eq $mode && !$force_rebuild; - $old_mode = $mode; - undef $force_rebuild; - my @elems; - my $wait; $wait = statusbar_msg($loc->N("Please wait, listing packages...")) if $MODE ne 'update'; - - my @keys = @filtered_pkgs; - if (member($mode, qw(all_updates security bugfix normal))) { - @keys = grep { - my ($name) = split_fullname($_); - member($descriptions->{$name}{importance}, @$mandrakeupdate_wanted_categories) - || ! $descriptions->{$name}{importance}; - } @keys; - if (@keys == 0) { - _build_tree($tree, $pkg_by_group_hash, ['', $loc->N("(none)")]); -# add_node('', $loc->N("(none)"), { nochild => 1 }); - state $explanation_only_once; - $explanation_only_once or interactive_msg($loc->N("No update"), - $loc->N("The list of updates is empty. This means that either there is -no available update for the packages installed on your computer, -or you already installed all of them.")); - $explanation_only_once = 1; - } - } - if (scalar @keys) { - # FIXME: better do this on first group access for faster startup... - @elems = map { [ $_, !$flat && ctreefy($pkgs->{$_}{pkg}->group) ] } sort_packages(@keys); - - my %sortmethods = ( - by_size => sub { sort { $pkgs->{$b->[0]}{pkg}->size <=> $pkgs->{$a->[0]}{pkg}->size } @_ }, - by_selection => sub { sort { $pkgs->{$b->[0]}{selected} <=> $pkgs->{$a->[0]}{selected} - || uc($a->[0]) cmp uc($b->[0]) } @_ }, - by_leaves => sub { - # inlining part of MDK::Common::Data::difference2(): - my %l; @l{map { $_->[0] } @_} = (); - my @pkgs_times = ('rpm', '-q', '--qf', '%{name}-%{version}-%{release}.%{arch} %{installtime}\n', - map { chomp_($_) } ManaTools::Shared::RunProgram::get_stdout('urpmi_rpm-find-leaves')); - sort { $b->[1] <=> $a->[1] } grep { exists $l{$_->[0]} } map { chomp; [ split ] } run_rpm(@pkgs_times); - }, - flat => sub { no locale; sort { uc($a->[0]) cmp uc($b->[0]) } @_ }, - by_medium => sub { sort { $a->[2] <=> $b->[2] || uc($a->[0]) cmp uc($b->[0]) } @_ }, - ); - if ($flat) { - carp "WARNING: TODO \$flat not tested\n"; - _build_tree($tree, $pkg_by_group_hash, map {[$_->[0], '']} $sortmethods{$::mode->[0] || 'flat'}->(@elems)); -# add_node($_->[0], '') foreach $sortmethods{$::mode->[0] || 'flat'}->(@elems); - } - else { - if ($::mode->[0] eq 'by_source') { - _build_tree($tree, $pkg_by_group_hash, $sortmethods{by_medium}->(map { - my $m = pkg2medium($pkgs->{$_->[0]}{pkg}, $urpm); [ $_->[0], $m->{name}, $m->{priority} ]; - } @elems)); - } - elsif ($::mode->[0] eq 'by_presence') { - _build_tree($tree, $pkg_by_group_hash, map { - my $pkg = $pkgs->{$_->[0]}{pkg}; - [ $_->[0], $pkg->flag_installed ? - (!$pkg->flag_skip && $pkg->flag_upgrade ? $loc->N("Upgradable") : $loc->N("Installed")) - : $loc->N("Addable") ]; - } $sortmethods{flat}->(@elems)); - } - else { - _build_tree($tree, $pkg_by_group_hash, @elems); - } - } - } - statusbar_msg_remove($wait) if defined $wait; -} - -#============================================================= - -=head2 get_info - -=head3 INPUT - - $key: package full name - $options: HASH reference containing: - details => show details - changelog => show changelog - files => show files - new_deps => show new dependencies - -=head3 DESCRIPTION - - return a string with all the package info - -=cut - -#============================================================= -sub get_info { - my ($key, $options) = @_; - #- the package information hasn't been loaded. Instead of rescanning the media, just give up. - exists $pkgs->{$key} or return [ [ $loc->N("Description not available for this package\n") ] ]; - #- get the description if needed: - exists $pkgs->{$key}{description} or slow_func(sub { extract_header($pkgs->{$key}, $urpm, 'info', find_installed_version($pkgs->{$key}{pkg})) }); - _format_pkg_simplifiedinfo($pkgs, $key, $urpm, $descriptions, $options); -} - -sub sort_callback { - my ($store, $treeiter1, $treeiter2) = @_; - URPM::rpmvercmp(map { $store->get_value($_, $pkg_columns{version}) } $treeiter1, $treeiter2); -} - -sub run_help_callback { - my (undef, $url) = @_; - my ($user) = grep { $_->[2] eq $ENV{USERHELPER_UID} } list_passwd(); - local $ENV{HOME} = $user->[7] if $user && $ENV{USERHELPER_UID}; - ManaTools::Shared::RunProgram::raw({ detach => 1, as_user => 1 }, 'www-browser', $url); -} - -#============================================================= - -=head2 run_browser - -=head3 INPUT - - $url: url to be passed to the configured browser - -=head3 DESCRIPTION - - This function calls the browser with the given URL - -=cut - -#============================================================= -sub run_browser { - my $url = shift; - - my ($user) = grep { $_->[2] eq $ENV{USERHELPER_UID} } MDK::Common::System::list_passwd(); - local $ENV{HOME} = $user->[7] if $user && $ENV{USERHELPER_UID}; - ManaTools::Shared::RunProgram::raw({ detach => 1, as_user => 1 }, 'www-browser', $url); -} - -#============================================================= - -=head2 group_path_name - -=head3 INPUT - - $treeItem: YTreeItem object - -=head3 OUTPUT - - $fullname: completed path group name - -=head3 DESCRIPTION - - This function returns the path name treeItem group name (e.g. foo|bar) - -=cut - -#============================================================= -sub group_path_name { - my $treeItem = shift; - - my $fullname = $treeItem->label(); - my $it = $treeItem; - while ($it = $it->parent()) { - $fullname = join("|", $it->label(), $fullname); - } - - return $fullname; -} - -sub groups_tree { - carp "DEPRECATED groups_tree: do not use it any more!"; - - return %groups_tree; -} - -sub group_has_parent { - my ($group) = shift; - carp "DEPRECATED group_has_parent: do not use it any more!"; - return 0 if(!defined($group)); - return defined($groups_tree{$group}{parent}); -} - -sub group_parent { - my ($group) = shift; - - carp "DEPRECATED group_parent: do not use it any more!"; - # if group is a parent itself return it - # who use group_parent have to take care of the comparison - # between a group and its parent - # e.g. group System has groups_tree{'System'}{parent}->label() = 'System' - return $groups_tree{$group}{parent} if(group_has_parent($group)); - for my $sup (keys %groups_tree){ - for my $item(keys %{$groups_tree{$sup}{children}}){ - if(defined($group) && ($item eq $group)){ - return $groups_tree{$sup}{parent}; - } - } - } - return undef; -} - -1; diff --git a/lib/AdminPanel/Rpmdragora/gurpm.pm b/lib/AdminPanel/Rpmdragora/gurpm.pm deleted file mode 100644 index 20cac6e..0000000 --- a/lib/AdminPanel/Rpmdragora/gurpm.pm +++ /dev/null @@ -1,298 +0,0 @@ -# vim: set et ts=4 sw=4: -package ManaTools::Rpmdragora::gurpm; - -#============================================================= -*-perl-*- - -=head1 NAME - - ManaTools::Rpmdragora::gurpm - Module that shows the urpmi - progress status - -=head1 SYNOPSIS - - my %option = (title => "Urpmi action ivoked", text => "Please wait", ); - my $gurpmi = ManaTools::Rpmdragora::gurpm->new(%option); - $gurpmi->progress(45); - - #add to an existing dialog - %option = (title => "Urpmi action ivoked", text => "Please wait", main_dialog => $dialog, parent => $parent_container); - $gurpmi = ManaTools::Rpmdragora::gurpm->new(%option); - $gurpmi->progress(20); - -=head1 DESCRIPTION - - This class is used to show the progress of an urpmi operation on - its progress bar. It can be istantiated as a popup dialog or used - to add label and progress bar into a YLayoutBox container. - -=head1 SUPPORT - - You can find documentation for this module with the perldoc command: - - perldoc ManaTools::Rpmdragora::gurpm - -=head1 AUTHOR - - Angelo Naselli - - Matteo Pasotti - -=head1 COPYRIGHT and LICENSE - - Copyright (c) 2002 Guillaume Cottenceau - Copyright (c) 2002-2007 Thierry Vignaud - Copyright (c) 2003, 2004, 2005 MandrakeSoft SA - Copyright (c) 2005-2007 Mandriva SA - Copyright (c) 2013 - 2015 Matteo Pasotti - Copyright (C) 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 Carp; -use Time::HiRes; - -use yui; -use feature 'state'; - - -has 'title' => ( - is => 'rw', - isa => 'Str', -); - -has 'text' => ( - is => 'rw', - isa => 'Str', -); - -has 'main_dialog' => ( - is => 'rw', - isa => 'yui::YDialog', -); - -has 'parent' => ( - is => 'rw', - isa => 'yui::YReplacePoint', -); - -has 'label_widget' => ( - is => 'rw', - isa => 'yui::YLabel', - init_arg => undef, -); - -has 'progressbar' => ( - is => 'rw', - isa => 'yui::YProgressBar', - init_arg => undef, -); - -#============================================================= - -=head2 BUILD - -=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; - - my $factory = yui::YUI::widgetFactory; - my $vbox; - - if (! $self->main_dialog) { - if ($self->parent) { - carp "WARNING: parent parameter is skipped without main_dialog set\n" ; - $self->parent(undef); - } - $self->main_dialog($factory->createPopupDialog()); - $vbox = $factory->createVBox($self->main_dialog); - } - else { - die "parent parameter is mandatory with main_dialog" if !$self->parent; - $self->main_dialog->startMultipleChanges(); - $self->parent->deleteChildren(); - $vbox = $factory->createVBox($self->parent); - $factory->createVSpacing($vbox, 0.5); - } - - $self->label_widget( $factory->createLabel($vbox, $self->text) ); - $self->label_widget->setStretchable( $yui::YD_HORIZ, 1 ); - $self->progressbar( $factory->createProgressBar($vbox, "") ); - - if ($self->parent) { - $factory->createVSpacing($vbox, 0.5); - $self->parent->showChild(); - $self->main_dialog->recalcLayout(); - $self->main_dialog->doneMultipleChanges(); - } - - $self->main_dialog->pollEvent(); - $self->flush(); -} - - -#============================================================= - -=head2 flush - -=head3 DESCRIPTION - - Polls a dialog event to refresh the dialog - -=cut - -#============================================================= -sub flush { - my ($self) = @_; - - $self->main_dialog->startMultipleChanges(); - $self->main_dialog->recalcLayout(); - $self->main_dialog->doneMultipleChanges(); - - if ($self->main_dialog->isTopmostDialog()) { - $self->main_dialog->waitForEvent(10); - $self->main_dialog->pollEvent(); - } - else { - carp "This dialog is not a top most dialog\n"; - } - yui::YUI::app()->redrawScreen(); -} - -#============================================================= - -=head2 label - -=head3 INPUT - - $text: text to be shown on label - -=head3 DESCRIPTION - - Sets the label text - -=cut - -#============================================================= -sub label { - my ($self, $text) = @_; - - $self->main_dialog->startMultipleChanges(); - $self->label_widget->setValue($text) if $text; - $self->main_dialog->doneMultipleChanges(); - - $self->flush(); -} - -#============================================================= - -=head2 progress - -=head3 INPUT - - $value: integer value in the range 0..100 - -=head3 DESCRIPTION - - Sets the progress bar percentage value - -=cut - -#============================================================= -sub progress { - my ($self, $value) = @_; - state $time = 0; - - $value = 0 if !defined($value) || $value < 0; - $value = 100 if 100 < $value; - - $self->progressbar->setValue($value); - return if Time::HiRes::clock_gettime() - $time < 0.333; - $time = Time::HiRes::clock_gettime(); - - $self->flush(); -} - -#============================================================= - -=head2 DEMOLISH - -=head3 INPUT - - $val: boolean value indicating whether or not this method - was called as part of the global destruction process - (when the Perl interpreter exits) - -=head3 DESCRIPTION - - Moose provides a hook for object destruction with the - DEMOLISH method as it does for construtor with BUILD - -=cut - -#============================================================= -sub DEMOLISH { - my ($self, $val) = @_; - - $self->main_dialog->destroy if !$self->parent; -} - -# TODO cancel button cannot be easily managed in libyui polling events -# removed atm -# -# sub validate_cancel { -# my ($self, $cancel_msg, $cancel_cb) = @_; -# $self->{main_dialog}->startMultipleChanges(); -# if (!$self->{cancel}) { -# $self->{cancel} = $self->{factory}->createIconButton($self->{vbox},"",$cancel_msg); -# #gtkpack__( -# #$self->{vbox}, -# #$self->{hbox_cancel} = gtkpack__( -# #gtknew('HButtonBox'), -# #$self->{cancel} = gtknew('Button', text => $cancel_msg, clicked => \&$cancel_cb), -# #), -# #); -# } -# #$self->{cancel}->set_sensitive(1); -# #$self->{cancel}->show; -# $self->flush(); -# } -# -# sub invalidate_cancel { -# my ($self) = @_; -# $self->{cancel} and $self->{cancel}->setEnabled(0); -# } -# -# sub invalidate_cancel_forever { -# my ($self) = @_; -# #$self->{hbox_cancel} or return; -# #$self->{hbox_cancel}->destroy; -# # FIXME: temporary workaround that prevents -# # Gtk2::Label::set_text() set_text_internal() -> queue_resize() -> -# # size_allocate() call chain to mess up when ->shrink_topwindow() -# # has been called (#32613): -# #$self->shrink_topwindow; -# } - -1; diff --git a/lib/AdminPanel/Rpmdragora/icon.pm b/lib/AdminPanel/Rpmdragora/icon.pm deleted file mode 100644 index 6c3887d..0000000 --- a/lib/AdminPanel/Rpmdragora/icon.pm +++ /dev/null @@ -1,234 +0,0 @@ -# vim: set et ts=4 sw=4: -package ManaTools::Rpmdragora::icon; -#***************************************************************************** -# -# Copyright (c) 2002 Guillaume Cottenceau -# Copyright (c) 2002-2007 Thierry Vignaud -# Copyright (c) 2003, 2004, 2005 MandrakeSoft SA -# Copyright (c) 2005-2007 Mandriva SA -# Copyright (c) 2013 - 2015 Matteo Pasotti -# 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. -# -#***************************************************************************** -# -# $Id: icon.pm 237459 2008-02-26 14:20:47Z tv $ - -use strict; - -use ManaTools::rpmdragora; -use ManaTools::Shared::Locales; - -my $loc = ManaTools::rpmdragora::locale(); - -use Exporter; -our @ISA = qw(Exporter); -our @EXPORT_OK = qw(get_icon_path); -#- /usr/share/rpmlint/config (duplicates are normal, so that we are not too far away from .py) -my %group_icons = ( - $loc->N("All") => 'system_section', - $loc->N("Accessibility") => 'accessibility_section', - $loc->N("Archiving") => 'archiving_section', - join('|', $loc->N("Archiving"), $loc->N("Backup")) => 'backup_section', - join('|', $loc->N("Archiving"), $loc->N("Cd burning")) => 'cd_burning_section', - join('|', $loc->N("Archiving"), $loc->N("Compression")) => 'compression_section', - join('|', $loc->N("Archiving"), $loc->N("Other")) => 'other_archiving', - $loc->N("Communications") => 'communications_section', - join('|', $loc->N("Communications"), $loc->N("Bluetooth")) => 'communications_bluetooth_section', - join('|', $loc->N("Communications"), $loc->N("Dial-Up")) => 'communications_dialup_section', - join('|', $loc->N("Communications"), $loc->N("Fax")) => 'communications_fax_section', - join('|', $loc->N("Communications"), $loc->N("Mobile")) => 'communications_mobile_section', - join('|', $loc->N("Communications"), $loc->N("Radio")) => 'communications_radio_section', - join('|', $loc->N("Communications"), $loc->N("Serial")) => 'communications_serial_section', - join('|', $loc->N("Communications"), $loc->N("Telephony")) => 'communications_phone_section', - $loc->N("Databases") => 'databases_section', - $loc->N("Development") => 'development_section', - join('|', $loc->N("Development"), $loc->N("Basic")) => '', - join('|', $loc->N("Development"), $loc->N("C")) => '', - join('|', $loc->N("Development"), $loc->N("C++")) => '', - join('|', $loc->N("Development"), $loc->N("C#")) => '', - join('|', $loc->N("Development"), $loc->N("Databases")) => 'databases_section', - join('|', $loc->N("Development"), $loc->N("Debug")) => '', - join('|', $loc->N("Development"), $loc->N("Erlang")) => '', - join('|', $loc->N("Development"), $loc->N("GNOME and GTK+")) => 'gnome_section', - join('|', $loc->N("Development"), $loc->N("Java")) => '', - join('|', $loc->N("Development"), $loc->N("KDE and Qt")) => 'kde_section', - join('|', $loc->N("Development"), $loc->N("Kernel")) => '', - join('|', $loc->N("Development"), $loc->N("OCaml")) => '', - join('|', $loc->N("Development"), $loc->N("Other")) => '', - join('|', $loc->N("Development"), $loc->N("Perl")) => '', - join('|', $loc->N("Development"), $loc->N("PHP")) => '', - join('|', $loc->N("Development"), $loc->N("Python")) => '', - join('|', $loc->N("Development"), $loc->N("Tools")) => 'development_tools_section', - join('|', $loc->N("Development"), $loc->N("X11")) => '', - $loc->N("Documentation") => 'documentation_section', - $loc->N("Editors") => 'editors_section', - $loc->N("Education") => 'education_section', - $loc->N("Emulators") => 'emulators_section', - $loc->N("File tools") => 'file_tools_section', - $loc->N("Games") => 'amusement_section', - join('|', $loc->N("Games"), $loc->N("Adventure")) => 'adventure_section', - join('|', $loc->N("Games"), $loc->N("Arcade")) => 'arcade_section', - join('|', $loc->N("Games"), $loc->N("Boards")) => 'boards_section', - join('|', $loc->N("Games"), $loc->N("Cards")) => 'cards_section', - join('|', $loc->N("Games"), $loc->N("Other")) => 'other_amusement', - join('|', $loc->N("Games"), $loc->N("Puzzles")) => 'puzzle_section', - join('|', $loc->N("Games"), $loc->N("Shooter")) => 'shooter_section', - join('|', $loc->N("Games"), $loc->N("Simulation")) => 'simulation_section', - join('|', $loc->N("Games"), $loc->N("Sports")) => 'sport_section', - join('|', $loc->N("Games"), $loc->N("Strategy")) => 'strategy_section', - $loc->N("Geography") => 'geography_section', - $loc->N("Graphical desktop") => 'graphical_desktop_section', - join('|', $loc->N("Graphical desktop"), - #-PO: This is a package/product name. Only translate it if needed: - $loc->N("Enlightenment")) => 'enlightment_section', - join('|', $loc->N("Graphical desktop"), - #-PO: This is a package/product name. Only translate it if needed: - $loc->N("GNOME")) => 'gnome_section', - join('|', $loc->N("Graphical desktop"), - #-PO: This is a package/product name. Only translate it if needed: - $loc->N("Icewm")) => 'icewm_section', - join('|', $loc->N("Graphical desktop"), - #-PO: This is a package/product name. Only translate it if needed: - $loc->N("KDE")) => 'kde_section', - join('|', $loc->N("Graphical desktop"), $loc->N("Other")) => 'more_applications_other_section', - join('|', $loc->N("Graphical desktop"), - #-PO: This is a package/product name. Only translate it if needed: - $loc->N("WindowMaker")) => 'windowmaker_section', - join('|', $loc->N("Graphical desktop"), - #-PO: This is a package/product name. Only translate it if needed: - $loc->N("Xfce")) => 'xfce_section', - $loc->N("Graphics") => 'graphics_section', - join('|', $loc->N("Graphics"), $loc->N("3D")) => 'graphics_3d_section', - join('|', $loc->N("Graphics"), $loc->N("Editors and Converters")) => 'graphics_editors_section', - join('|', $loc->N("Graphics"), $loc->N("Utilities")) => 'graphics_utilities_section', - join('|', $loc->N("Graphics"), $loc->N("Photography")) => 'graphics_photography_section', - join('|', $loc->N("Graphics"), $loc->N("Scanning")) => 'graphics_scanning_section', - join('|', $loc->N("Graphics"), $loc->N("Viewers")) => 'graphics_viewers_section', - $loc->N("Monitoring") => 'monitoring_section', - $loc->N("Networking") => 'networking_section', - join('|', $loc->N("Networking"), $loc->N("File transfer")) => 'file_transfer_section', - join('|', $loc->N("Networking"), $loc->N("IRC")) => 'irc_section', - join('|', $loc->N("Networking"), $loc->N("Instant messaging")) => 'instant_messaging_section', - join('|', $loc->N("Networking"), $loc->N("Mail")) => 'mail_section', - join('|', $loc->N("Networking"), $loc->N("News")) => 'news_section', - join('|', $loc->N("Networking"), $loc->N("Other")) => 'other_networking', - join('|', $loc->N("Networking"), $loc->N("Remote access")) => 'remote_access_section', - join('|', $loc->N("Networking"), $loc->N("WWW")) => 'networking_www_section', - $loc->N("Office") => 'office_section', - join('|', $loc->N("Office"), $loc->N("Dictionary")) => 'office_dictionary_section', - join('|', $loc->N("Office"), $loc->N("Finance")) => 'finances_section', - join('|', $loc->N("Office"), $loc->N("Management")) => 'timemanagement_section', - join('|', $loc->N("Office"), $loc->N("Organizer")) => 'timemanagement_section', - join('|', $loc->N("Office"), $loc->N("Utilities")) => 'office_accessories_section', - join('|', $loc->N("Office"), $loc->N("Spreadsheet")) => 'spreadsheet_section', - join('|', $loc->N("Office"), $loc->N("Suite")) => 'office_suite', - join('|', $loc->N("Office"), $loc->N("Word processor")) => 'wordprocessor_section', - $loc->N("Publishing") => 'publishing_section', - $loc->N("Sciences") => 'sciences_section', - join('|', $loc->N("Sciences"), $loc->N("Astronomy")) => 'astronomy_section', - join('|', $loc->N("Sciences"), $loc->N("Biology")) => 'biology_section', - join('|', $loc->N("Sciences"), $loc->N("Chemistry")) => 'chemistry_section', - join('|', $loc->N("Sciences"), $loc->N("Computer science")) => 'computer_science_section', - join('|', $loc->N("Sciences"), $loc->N("Geosciences")) => 'geosciences_section', - join('|', $loc->N("Sciences"), $loc->N("Mathematics")) => 'mathematics_section', - join('|', $loc->N("Sciences"), $loc->N("Other")) => 'other_sciences', - join('|', $loc->N("Sciences"), $loc->N("Physics")) => 'physics_section', - $loc->N("Security") => 'security_section', - $loc->N("Shells") => 'shells_section', - $loc->N("Sound") => 'sound_section', - join('|', $loc->N("Sound"), $loc->N("Editors and Converters")) => 'sound_editors_section', - join('|', $loc->N("Sound"), $loc->N("Midi")) => 'sound_midi_section', - join('|', $loc->N("Sound"), $loc->N("Mixers")) => 'sound_mixers_section', - join('|', $loc->N("Sound"), $loc->N("Players")) => 'sound_players_section', - join('|', $loc->N("Sound"), $loc->N("Utilities")) => 'sound_utilities_section', - $loc->N("System") => 'system_section', - join('|', $loc->N("System"), $loc->N("Base")) => 'system_section', - join('|', $loc->N("System"), $loc->N("Boot and Init")) => 'boot_init_section', - join('|', $loc->N("System"), $loc->N("Cluster")) => 'parallel_computing_section', - join('|', $loc->N("System"), $loc->N("Configuration")) => 'configuration_section', - join('|', $loc->N("System"), $loc->N("Fonts")) => 'chinese_section', - join('|', $loc->N("System"), $loc->N("Fonts"), $loc->N("True type")) => '', - join('|', $loc->N("System"), $loc->N("Fonts"), $loc->N("Type1")) => '', - join('|', $loc->N("System"), $loc->N("Fonts"), $loc->N("X11 bitmap")) => '', - join('|', $loc->N("System"), $loc->N("Internationalization")) => 'chinese_section', - join('|', $loc->N("System"), $loc->N("Kernel and hardware")) => 'hardware_configuration_section', - join('|', $loc->N("System"), $loc->N("Libraries")) => 'system_section', - join('|', $loc->N("System"), $loc->N("Networking")) => 'networking_configuration_section', - join('|', $loc->N("System"), $loc->N("Packaging")) => 'packaging_section', - join('|', $loc->N("System"), $loc->N("Printing")) => 'printing_section', - join('|', $loc->N("System"), $loc->N("Servers")) => 'servers_section', - join('|', $loc->N("System"), - #-PO: This is a package/product name. Only translate it if needed: - $loc->N("X11")) => 'x11_section', - $loc->N("Terminals") => 'terminals_section', - $loc->N("Text tools") => 'text_tools_section', - $loc->N("Toys") => 'toys_section', - $loc->N("Video") => 'video_section', - join('|', $loc->N("Video"), $loc->N("Editors and Converters")) => 'video_editors_section', - join('|', $loc->N("Video"), $loc->N("Players")) => 'video_players_section', - join('|', $loc->N("Video"), $loc->N("Television")) => 'video_television_section', - join('|', $loc->N("Video"), $loc->N("Utilities")) => 'video_utilities_section', - - # for Mageia Choice: - $loc->N("Workstation") => 'system_section', - join('|', $loc->N("Workstation"), $loc->N("Configuration")) => 'configuration_section', - join('|', $loc->N("Workstation"), $loc->N("Console Tools")) => 'interpreters_section', - join('|', $loc->N("Workstation"), $loc->N("Documentation")) => 'documentation_section', - join('|', $loc->N("Workstation"), $loc->N("Game station")) => 'amusement_section', - join('|', $loc->N("Workstation"), $loc->N("Internet station")) => 'networking_section', - join('|', $loc->N("Workstation"), $loc->N("Multimedia station")) => 'multimedia_section', - join('|', $loc->N("Workstation"), $loc->N("Network Computer (client)")) => 'other_networking', - join('|', $loc->N("Workstation"), $loc->N("Office Workstation")) => 'office_section', - join('|', $loc->N("Workstation"), $loc->N("Scientific Workstation")) => 'sciences_section', - $loc->N("Graphical Environment") => 'graphical_desktop_section', - - join('|', $loc->N("Graphical Environment"), $loc->N("GNOME Workstation")) => 'gnome_section', - join('|', $loc->N("Graphical Environment"), $loc->N("IceWm Desktop")) => 'icewm_section', - join('|', $loc->N("Graphical Environment"), $loc->N("KDE Workstation")) => 'kde_section', - join('|', $loc->N("Graphical Environment"), $loc->N("Other Graphical Desktops")) => 'more_applications_other_section', - $loc->N("Development") => 'development_section', - join('|', $loc->N("Development"), $loc->N("Development")) => 'development_section', - join('|', $loc->N("Development"), $loc->N("Documentation")) => 'documentation_section', - $loc->N("Server") => 'servers_section', - join('|', $loc->N("Server"), $loc->N("DNS/NIS")) => 'networking_section', - join('|', $loc->N("Server"), $loc->N("Database")) => 'databases_section', - join('|', $loc->N("Server"), $loc->N("Firewall/Router")) => 'networking_section', - join('|', $loc->N("Server"), $loc->N("Mail")) => 'mail_section', - join('|', $loc->N("Server"), $loc->N("Mail/Groupware/News")) => 'mail_section', - join('|', $loc->N("Server"), $loc->N("Network Computer server")) => 'networking_section', - join('|', $loc->N("Server"), $loc->N("Web/FTP")) => 'networking_www_section', - - ); - -sub get_icon_path { - my ($group, $parent) = @_; - - my $path = $parent ? '/usr/share/icons/mini/' : '/usr/share/icons/'; - my $icon_path = ""; - if(defined($group_icons{$group})){ - $icon_path = join('', $path, $group_icons{$group}, '.png'); - }elsif(defined($group_icons{$parent."\|".$group})){ - $icon_path = join('', $path, $group_icons{$parent."\|".$group}, '.png'); - }else{ - $icon_path = join('', $path, 'applications_section', '.png'); - } - unless(-e $icon_path){ - $icon_path = join('', $path, 'applications_section', '.png'); - } - return $icon_path; -} - -1; diff --git a/lib/AdminPanel/Rpmdragora/init.pm b/lib/AdminPanel/Rpmdragora/init.pm deleted file mode 100644 index f6d570d..0000000 --- a/lib/AdminPanel/Rpmdragora/init.pm +++ /dev/null @@ -1,181 +0,0 @@ -# vim: set et ts=4 sw=4: -package ManaTools::Rpmdragora::init; -#***************************************************************************** -# -# Copyright (c) 2002 Guillaume Cottenceau -# Copyright (c) 2002-2007 Thierry Vignaud -# Copyright (c) 2003, 2004, 2005 MandrakeSoft SA -# Copyright (c) 2005-2007 Mandriva SA -# Copyright (c) 2013 - 2015 Matteo Pasotti -# 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. -# -#***************************************************************************** -# -# $Id: init.pm 263915 2009-12-03 17:41:04Z tv $ - -use strict; -use MDK::Common::Func 'any'; -use English; -BEGIN { $::no_global_argv_parsing = 1 } -require urpm::args; -use MDK::Common::Various qw(chomp_); - -use ManaTools::Privileges; -use ManaTools::Shared::Locales; - -use Exporter; -our @ISA = qw(Exporter); -our @EXPORT = qw(init - warn_about_user_mode - $MODE - $VERSION - $changelog_first - $default_list_mode - %rpmdragora_options - @ARGV_copy - ); - -our @ARGV_copy = @ARGV; - -BEGIN { #- we want to run this code before the Gtk->init of the use-my_gtk - my $loc = ManaTools::Shared::Locales->new(domain_name => 'rpmdrake'); - - my $basename = sub { local $_ = shift; s|/*\s*$||; s|.*/||; $_ }; - any { /^--?h/ } @ARGV and do { - printf join("\n", $loc->N("Usage: %s [OPTION]...", $basename->($0)), -$loc->N(" --auto assume default answers to questions"), -$loc->N(" --changelog-first display changelog before filelist in the description window"), -$loc->N(" --media=medium1,.. limit to given media"), -$loc->N(" --merge-all-rpmnew propose to merge all .rpmnew/.rpmsave files found"), -$loc->N(" --mode=MODE set mode (install (default), remove, update)"), -$loc->N(" --justdb update the database, but do not modify the filesystem"), -$loc->N(" --no-confirmation don't ask first confirmation question in update mode"), -$loc->N(" --no-media-update don't update media at startup"), -$loc->N(" --no-verify-rpm don't verify package signatures"), -if_($0 !~ /MageiaUpdate/, $loc->N(" --parallel=alias,host be in parallel mode, use \"alias\" group, use \"host\" machine to show needed deps")), -$loc->N(" --rpm-root=path use another root for rpm installation"), -$loc->N(" --urpmi-root use another root for urpmi db & rpm installation"), -$loc->N(" --run-as-root force to run as root"), -$loc->N(" --search=pkg run search for \"pkg\""), -$loc->N(" --test only verify if the installation can be achieved correctly"), -chomp_($loc->N(" --version print this tool's version number -")), -"" -); - exit 0; - }; -} - -BEGIN { #- for mcc - if ("@ARGV" =~ /--embedded (\w+)/) { - $::XID = $1; - $::isEmbedded = 1; - } -} - - -#- This is needed because text printed by Gtk2 will always be encoded -#- in UTF-8; we first check if LC_ALL is defined, because if it is, -#- changing only LC_COLLATE will have no effect. -use POSIX qw(setlocale LC_ALL LC_COLLATE strftime); -use locale; -my $collation_locale = $ENV{LC_ALL}; -if ($collation_locale) { - $collation_locale =~ /UTF-8/ or setlocale(LC_ALL, "$collation_locale.UTF-8"); -} else { - $collation_locale = setlocale(LC_COLLATE); - $collation_locale =~ /UTF-8/ or setlocale(LC_COLLATE, "$collation_locale.UTF-8"); -} - -our $VERSION = "1.0.0"; -our %rpmdragora_options; - -my $i; -foreach (@ARGV) { - $i++; - /^-?-(\S+)$/ or next; - my $val = $1; - if ($val =~ /=/) { - my ($name, $values) = split /=/, $val; - my @values = split /,/, $values; - $rpmdragora_options{$name} = \@values if @values; - } else { - if ($val eq 'version') { - print "$0 $VERSION\n"; - exit(0); - } elsif ($val =~ /^(test|expert)$/) { - eval "\$::$1 = 1"; - } elsif ($val =~ /^(q|quiet)$/) { - urpm::args::set_verbose(-1); - } elsif ($val =~ /^(v|verbose)$/) { - urpm::args::set_verbose(1); - } else { - $rpmdragora_options{$val} = 1; - } - } -} - -foreach my $option (qw(media mode parallel rpm-root search)) { - if (defined $rpmdragora_options{$option} && !ref($rpmdragora_options{$option})) { - warn qq(wrong usage of "$option" option!\n); - exit(-1); # too early for my_exit() - } -} - -$urpm::args::options{basename} = 1; - -our $MODE = ref $rpmdragora_options{mode} ? $rpmdragora_options{mode}[0] : undef; -our $overriding_config = defined $MODE; -unless ($MODE) { - $MODE = 'install'; - $0 =~ m|remove$| and $MODE = 'remove'; - $0 =~ m|update$|i and $MODE = 'update'; -} - -our $default_list_mode; -$default_list_mode = 'gui_pkgs' if $MODE eq 'install'; -if ($MODE eq 'remove') { - $default_list_mode = 'installed'; -} elsif ($MODE eq 'update') { - $default_list_mode = 'all_updates'; -} - -$MODE eq 'update' || $rpmdragora_options{'run-as-root'} and ManaTools::Privileges::is_root_capability_required(); -$::noborderWhenEmbedded = 1; - -require ManaTools::rpmdragora; - -our $changelog_first = $ManaTools::rpmdragora::changelog_first_config->[0]; -$changelog_first = 1 if $rpmdragora_options{'changelog-first'}; - -sub warn_about_user_mode() { - my $loc = ManaTools::Shared::Locales->new(domain_name => 'rpmdrake'); - my $title = $loc->N("Running in user mode"); - my $msg = $loc->N("You are launching this program as a normal user.\n". - "You will not be able to perform modifications on the system,\n". - "but you may still browse the existing database."); - - if(($EUID != 0) and (!ManaTools::rpmdragora::interactive_msg($title, $msg))) { - return 0; - } - return 1; -} - -sub init() { - URPM::bind_rpm_textdomain_codeset(); -} - -1; diff --git a/lib/AdminPanel/Rpmdragora/open_db.pm b/lib/AdminPanel/Rpmdragora/open_db.pm deleted file mode 100644 index 7bfa7bf..0000000 --- a/lib/AdminPanel/Rpmdragora/open_db.pm +++ /dev/null @@ -1,171 +0,0 @@ -# vim: set et ts=4 sw=4: -package ManaTools::Rpmdragora::open_db; -#***************************************************************************** -# -# Copyright (c) 2002 Guillaume Cottenceau -# Copyright (c) 2002-2014 Thierry Vignaud -# Copyright (c) 2003, 2004, 2005 MandrakeSoft SA -# Copyright (c) 2005-2007 Mandriva SA -# Copyright (c) 2012-2015 Matteo Pasotti -# 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. -# -#***************************************************************************** -# -# $Id: open_db.pm 268344 2010-05-06 13:06:08Z jvictor $ - -use strict; -use Sys::Syslog; - -use MDK::Common::File qw(cat_ mkdir_p); -use MDK::Common::Func; -use ManaTools::rpmdragora; -use URPM; -use urpm; -use urpm::args; -use urpm::select; -use urpm::media; -use urpm::mirrors; -use feature 'state'; - -use Exporter; -our @ISA = qw(Exporter); -our @EXPORT = qw(fast_open_urpmi_db - get_backport_media - get_inactive_backport_media - get_update_medias - is_it_a_devel_distro - open_rpm_db - open_urpmi_db - ); - -my $loc = ManaTools::rpmdragora::locale(); - - -# because rpm blocks some signals when rpm DB is opened, we don't keep open around: -sub open_rpm_db { - my ($o_force) = @_; - my $host; - Sys::Syslog::syslog('info|local1', "opening the RPM database"); - if ($::rpmdragora_options{parallel} && ((undef, $host) = @{$::rpmdragora_options{parallel}})) { - state $done; - my $dblocation = "/var/cache/urpmi/distantdb/$host"; - if (!$done || $o_force) { - print "syncing db from $host to $dblocation..."; - mkdir_p "$dblocation/var/lib/rpm"; - system "rsync -Sauz -e ssh $host:/var/lib/rpm/ $dblocation/var/lib/rpm"; - $? == 0 or die "Couldn't sync db from $host to $dblocation"; - $done = 1; - print "done.\n"; - } - URPM::DB::open($dblocation) or die "Couldn't open RPM DB"; - } else { - my $db; - if ($::env) { - #- URPM has same methods as URPM::DB and empty URPM will be seen as empty URPM::DB. - $db = new URPM; - $db->parse_synthesis("$::env/rpmdb.cz"); - } else { - $db = URPM::DB::open($::rpmdragora_options{'rpm-root'}[0]||''); - } - $db or die "Couldn't open RPM DB (" . ($::env ? "$::env/rpmdb.cz" : $::rpmdragora_options{'rpm-root'}[0]) . ")"; - } -} - -# do not pay the urpm::media::configure() heavy cost: -sub fast_open_urpmi_db() { - my $urpm = urpm->new; - my $error_happened; - $urpm->{fatal} = sub { - $error_happened = 1; - interactive_msg($loc->N("Fatal error"), - $loc->N("A fatal error occurred: %s.", $_[1])); - }; - - urpm::set_files($urpm, $::rpmdragora_options{'urpmi-root'}[0]) if $::rpmdragora_options{'urpmi-root'}[0]; - $::rpmdragora_options{'rpm-root'}[0] ||= $::rpmdragora_options{'urpmi-root'}[0]; - urpm::args::set_root($urpm, $::rpmdragora_options{'rpm-root'}[0]) if $::rpmdragora_options{'rpm-root'}[0]; - urpm::args::set_debug($urpm) if $::rpmdragora_options{debug}; - $urpm->get_global_options; - $urpm->{options}{wait_lock} = $::rpmdragora_options{'wait-lock'}; - $urpm->{options}{'verify-rpm'} = !$::rpmdragora_options{'no-verify-rpm'} if defined $::rpmdragora_options{'no-verify-rpm'}; - $urpm->{options}{auto} = $::rpmdragora_options{auto} if defined $::rpmdragora_options{auto}; - urpm::args::set_verbosity(); - if ($::rpmdragora_options{env} && $::rpmdragora_options{env}[0]) { - $::env = $::rpmdragora_options{env}[0]; - # prevent crashing in URPM.pm prevent when using --env: - $::env = "$ENV{PWD}/$::env" if $::env !~ m!^/!; - urpm::set_env($urpm, $::env); - } - - $urpm::args::options{justdb} = $::rpmdragora_options{justdb}; - - urpm::media::read_config($urpm, 0); - foreach (@{$urpm->{media}}) { - next if $_->{ignore}; - urpm::media::_tempignore($_, 1) if $ignore_debug_media->[0] && $_->{name} =~ /debug/i; - } - # FIXME: seems uneeded with newer urpmi: - if ($error_happened) { - touch('/etc/urpmi/urpmi.cfg'); - exec('edit-urpm-sources.pl'); - } - $urpm; -} - -sub is_it_a_devel_distro() { - state $res; - return $res if defined $res; - - my $path = '/etc/product.id'; - $path = $::rpmdragora_options{'urpmi-root'}[0] . $path if defined($::rpmdragora_options{'urpmi-root'}[0]); - $res = urpm::mirrors::parse_LDAP_namespace_structure(cat_($path))->{branch} eq 'Devel'; - return $res; -} - -sub get_backport_media { - my ($urpm) = @_; - grep { $_->{name} =~ /backport/i && - $_->{name} !~ /debug|sources|testing/i } @{$urpm->{media}}; -} - -sub get_inactive_backport_media { - my ($urpm) = @_; - map { $_->{name} } grep { $_->{ignore} } get_backport_media($urpm); -} - -sub get_update_medias { - my ($urpm) = @_; - if (is_it_a_devel_distro()) { - grep { !$_->{ignore} } @{$urpm->{media}}; - } else { - grep { !$_->{ignore} && $_->{update} } @{$urpm->{media}}; - } -} - -sub open_urpmi_db { - my (%urpmi_options) = @_; - my $urpm = fast_open_urpmi_db(); - my $media = ref $::rpmdragora_options{media} ? join(',', @{$::rpmdragora_options{media}}) : ''; - - my $searchmedia = $urpmi_options{update} ? undef : join(',', get_inactive_backport_media($urpm)); - $urpm->{lock} = urpm::lock::urpmi_db($urpm, undef, wait => $urpm->{options}{wait_lock}) if !$::env; - my $previous = $::rpmdragora_options{'previous-priority-upgrade'}; - urpm::select::set_priority_upgrade_option($urpm, (ref $previous ? join(',', @$previous) : ())); - urpm::media::configure($urpm, media => $media, MDK::Common::Func::if_($searchmedia, searchmedia => $searchmedia), %urpmi_options); - $urpm; -} - -1; diff --git a/lib/AdminPanel/Rpmdragora/pkg.pm b/lib/AdminPanel/Rpmdragora/pkg.pm deleted file mode 100644 index ba0b18b..0000000 --- a/lib/AdminPanel/Rpmdragora/pkg.pm +++ /dev/null @@ -1,1085 +0,0 @@ -# vim: set et ts=4 sw=4: -package ManaTools::Rpmdragora::pkg; -#***************************************************************************** -# -# Copyright (c) 2002 Guillaume Cottenceau -# Copyright (c) 2002-2007 Thierry Vignaud -# Copyright (c) 2003, 2004, 2005 MandrakeSoft SA -# Copyright (c) 2005-2007 Mandriva SA -# Copyright (c) 2012-2015 Matteo Pasotti -# 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. -# -#***************************************************************************** -# -# $Id: pkg.pm 270160 2010-06-22 19:55:40Z jvictor $ - -use strict; -use Sys::Syslog; - -use MDK::Common::Func; #qw(before_leaving any); -use MDK::Common::DataStructure; # qw (uniq difference2 member add2hash put_in_hash); -use MDK::Common::System qw(arch); -use MDK::Common::File; # qw(cat_); -use MDK::Common::Various qw(chomp_); - -use POSIX qw(_exit ceil); -use URPM; -use utf8; -use ManaTools::rpmdragora; -use ManaTools::Rpmdragora::open_db; -use ManaTools::Rpmdragora::gurpm; -use ManaTools::Rpmdragora::formatting; -use ManaTools::Rpmdragora::rpmnew; -use ManaTools::Shared::RunProgram qw(run get_stdout); -use ManaTools::rpmdragora; -use urpm; -use urpm::lock; -use urpm::install; -use urpm::signature; -use urpm::get_pkgs; -use urpm::select; -use urpm::main_loop; -use urpm::args qw(); -use urpm::util; -use Carp; - -my $loc = ManaTools::rpmdragora::locale(); - -use Exporter; -our @ISA = qw(Exporter); -our @EXPORT = qw( - $priority_up_alread_warned - download_callback - extract_header - find_installed_version - get_pkgs - perform_installation - perform_removal - run_rpm - sort_packages - ); - -our $priority_up_alread_warned; - -sub sort_packages_biarch { - sort { - my ($na, $aa) = $a =~ /^(.*-[^-]+-[^-]+)\.([^.-]+)$/; - my ($nb, $ab) = $b =~ /^(.*-[^-]+-[^-]+)\.([^.-]+)$/; - !defined($na) ? - (!defined($nb) ? 0 : 1) : - (!defined($nb) ? -1 : $na cmp $nb || ($ab =~ /64$/) <=> ($aa =~ /64$/)); - } @_; -} - -sub sort_packages_monoarch { - sort { uc($a) cmp uc($b) } @_; -} - -*sort_packages = MDK::Common::System::arch() =~ /x86_64/ ? \&sort_packages_biarch : \&sort_packages_monoarch; - -sub run_rpm { - foreach (qw(LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT LC_IDENTIFICATION LC_ALL)) { - local $ENV{$_} = $ENV{$_} . '.UTF-8' if $ENV{$_} && $ENV{$_} !~ /UTF-8/; - } - my @l = map { ensure_utf8($_); $_ } ManaTools::Shared::RunProgram::get_stdout(@_); - wantarray() ? @l : join('', @l); -} - - -sub extract_header { - my ($pkg, $urpm, $xml_info, $o_installed_version) = @_; - my %fields = ( - info => 'description', - files => 'files', - changelog => 'changelog', - ); - # already extracted: - return if $pkg->{$fields{$xml_info}}; - - my $p = $pkg->{pkg}; - - if (!$p) { - warn ">> ghost package '$pkg' has no URPM object!!!\n"; - return; - } - - my $name = $p->fullname; - # fix extracting info for SRPMS and RPM GPG keys: - $name =~ s!\.src!!; - - if ($p->flag_installed && !$p->flag_upgrade) { - my @files = map { MDK::Common::Various::chomp_($_) } run_rpm("rpm -ql $name"); - MDK::Common::DataStructure::add2hash($pkg, { files => [ @files ? @files : $loc->N("(none)") ], - description => rpm_description(scalar(run_rpm("rpm -q --qf '%{description}' $name"))), - changelog => format_changelog_string($o_installed_version, scalar(run_rpm("rpm -q --changelog $name"))) }); - } else { - my $medium = pkg2medium($p, $urpm); - my ($local_source, %xml_info_pkgs, $bar_id); - my $_statusbar_clean_guard = MDK::Common::Func::before_leaving { $bar_id and statusbar_msg_remove($bar_id) }; - my $dir = urpm::file_from_local_url($medium->{url}); - - print "p->filename: ". $p->filename."\n"; - $local_source = "$dir/" . $p->filename if $dir; - print "local_source: " . ($local_source ? $local_source : "") . "\n"; - - if ($local_source && -e $local_source) { - $bar_id = statusbar_msg($loc->N("Getting information from %s...", $dir), 0); - $urpm->{log}("getting information from rpms from $dir"); - } else { - my $gurpm; - $bar_id = statusbar_msg($loc->N("Getting '%s' from XML meta-data...", $xml_info), 0); - my $_gurpm_clean_guard = MDK::Common::Func::before_leaving { undef $gurpm }; - if (my $xml_info_file = eval { urpm::media::any_xml_info($urpm, $medium, $xml_info, undef, sub { - $gurpm ||= ManaTools::Rpmdragora::gurpm->new( - text => $loc->N("Please wait"), - ); - download_callback($gurpm, @_) - or goto header_non_available; - }) }) { - require urpm::xml_info; - require urpm::xml_info_pkg; - $urpm->{log}("getting information from $xml_info_file"); - my %nodes = eval { urpm::xml_info::get_nodes($xml_info, $xml_info_file, [ $name ]) }; - goto header_non_available if $@; - MDK::Common::DataStructure::put_in_hash($xml_info_pkgs{$name} ||= {}, $nodes{$name}); - } else { - if ($xml_info eq 'info') { - $urpm->{info}($loc->N("No xml info for medium \"%s\", only partial result for package %s", $medium->{name}, $name)); - } else { - $urpm->{error}($loc->N("No xml info for medium \"%s\", unable to return any result for package %s", $medium->{name}, $name)); - } - } - } - - #- even if non-root, search for a header in the global cachedir - if ($local_source && -s $local_source) { - $p->update_header($local_source) or do { - warn "Warning, could not extract header for $name from $medium!"; - goto header_non_available; - }; - my @files = $p->files; - @files = $loc->N("(none)") if !@files; - MDK::Common::DataStructure::add2hash($pkg, { description => rpm_description($p->description), - files => \@files, - url => $p->url, - changelog => format_changelog_changelogs($o_installed_version, $p->changelogs) }); - $p->pack_header; # needed in order to call methods on objects outside ->traverse - } elsif ($xml_info_pkgs{$name}) { - if ($xml_info eq 'info') { - MDK::Common::DataStructure::add2hash($pkg, { description => rpm_description($xml_info_pkgs{$name}{description}), - url => $xml_info_pkgs{$name}{url} - }); - } elsif ($xml_info eq 'files') { - my @files = map { MDK::Common::Various::chomp_($loc->to_utf8($_)) } split("\n", $xml_info_pkgs{$name}{files}); - MDK::Common::DataStructure::add2hash($pkg, { files => scalar(@files) ? \@files : [ $loc->N("(none)") ] }); - } elsif ($xml_info eq 'changelog') { - MDK::Common::DataStructure::add2hash($pkg, { - changelog => format_changelog_changelogs($o_installed_version, - @{$xml_info_pkgs{$name}{changelogs}}) - }); - } - } else { - goto header_non_available; - } - return; - header_non_available: - MDK::Common::DataStructure::add2hash($pkg, { summary => $p->summary || $loc->N("(Not available)"), description => undef }); - } -} - -sub find_installed_version { - my ($p) = @_; - - my $version = $loc->N("(none)"); - open_rpm_db()->traverse_tag_find('name', $p->name, sub { $version = $_[0]->EVR; return ($version ? 1 : 0) }) if $p; - return $version; -} - -my $canceled; -sub download_callback { - my ($gurpm, $mode, $file, $percent, $total, $eta, $speed) = @_; - $canceled = 0; - - if ($mode eq 'start') { - $gurpm->label($loc->N("Downloading package `%s'...", urpm::util::basename($file))); -# $gurpm->validate_cancel(but($loc->N("Cancel")), sub { $canceled = 1 }); - } elsif ($mode eq 'progress') { - $gurpm->label( - join("\n", - $loc->N("Downloading package `%s'...", urpm::util::basename($file)), - (defined $total && defined $eta ? - $loc->N(" %s%% of %s completed, ETA = %s, speed = %s", $percent, $total, $eta, $speed) - : $loc->N(" %s%% completed, speed = %s", $percent, $speed) - ) =~ /^\s*(.*)/ - ), - ); - #$gurpm->progress($percenti/100); - $gurpm->progress(ceil($percent)); - } elsif ($mode eq 'end') { - $gurpm->progress(100); -# $gurpm->invalidate_cancel; - } - !$canceled; -} - - -# -=-=-=---=-=-=---=-=-=-- install packages -=-=-=---=-=-=---=-=-=- - -my (@update_medias, $is_update_media_already_asked); - -sub warn_about_media { - my ($w, %options) = @_; - - return 0 if $::MODE ne 'update'; - return 0 if $::rpmdragora_options{'no-media-update'}; - - # we use our own instance of the urpmi db in order not to mess up with skip-list managment (#31092): - # and no need to fully configure urpmi since we may have to do it again anyway because of new media: - my $urpm = fast_open_urpmi_db(); - - my $_lock = urpm::lock::urpmi_db($urpm, undef, wait => $urpm->{options}{wait_lock}); - - # build media list: - @update_medias = get_update_medias($urpm); - - # do not update again media after installing/removing some packages: - $::rpmdragora_options{'no-media-update'} ||= 1; - - if (@update_medias > 0) { - if (!$options{skip_updating_mu} && !$is_update_media_already_asked) { - $is_update_media_already_asked = 1; - if (!$::rpmdragora_options{'no-confirmation'}) { - my $choice = interactive_msg($loc->N("Confirmation"), - $loc->N("I need to contact the mirror to get latest update packages. -Please check that your network is currently running. - -Is it ok to continue?" - ), yesno => 1, dont_ask_again => 1, -# TODO widget => gtknew('CheckButton', text => $loc->N("Do not ask me next time"), -# active_ref => \$::rpmdragora_options{'no-confirmation'} -# ) - ); - $::rpmdragora_options{'no-confirmation'} = $choice->{dont_ask_again}; - return(-1) if !$choice->{value}; - } - writeconf(); - urpm::media::select_media($urpm, map { $_->{name} } @update_medias); - update_sources($urpm, noclean => 1, medialist => [ map { $_->{name} } @update_medias ]); - } - } else { - if (MDK::Common::Func::any { $_->{update} } @{$urpm->{media}}) { - interactive_msg($loc->N("Already existing update media"), -$loc->N("You already have at least one update medium configured, but -all of them are currently disabled. You should run the Software -Media Manager to enable at least one (check it in the \"%s\" -column). - -Then, restart \"%s\".", $loc->N("Enabled"), $ManaTools::rpmdragora::myname_update)); - return (-1); - } - my ($mirror) = choose_mirror($urpm, transient => $w->{real_window} || $::main_window, - message => join("\n\n", - $loc->N("You have no configured update media. MageiaUpdate cannot operate without any update media."), - $loc->N("I need to contact the Mageia website to get the mirror list. -Please check that your network is currently running. - -Is it ok to continue?"), - ), - ); - my $m = ref($mirror) ? $mirror->{url} : ''; - $m or interactive_msg($loc->N("How to choose manually your mirror"), -$loc->N("You may also choose your desired mirror manually: to do so, -launch the Software Media Manager, and then add a `Security -updates' medium. - -Then, restart %s.", $ManaTools::rpmdragora::myname_update)), return (-1); - add_distrib_update_media($urpm, $mirror, only_updates => 0); - } - return 0; -} - - -sub get_parallel_group() { - $::rpmdragora_options{parallel} ? $::rpmdragora_options{parallel}[0] : undef; -} - -my ($count, $level, $limit, $new_stage, $prev_stage, $total); - -sub init_progress_bar { - my ($urpm) = @_; - undef $_ foreach $count, $prev_stage, $new_stage, $limit; - $level = 5; - $total = @{$urpm->{depslist}}; -} - -sub reset_pbar_count { - undef $prev_stage; - $count = 0; - $limit = $_[0]; -} - -sub update_pbar { - my ($gurpm) = @_; - return if !$total; # don't die if there's no source - $count++; - $new_stage = $level+($limit-$level)*$count/$total; - $prev_stage = 0 if(!defined($prev_stage)); - if ($prev_stage + 1 < $new_stage) { - $prev_stage = $new_stage; - $gurpm->progress(ceil($new_stage)); - } -} - - -sub get_installed_packages { - my ($urpm, $db, $all_pkgs, $gurpm) = @_; - - $urpm->{global_config}{'prohibit-remove'} = '' if(!defined($urpm->{global_config}{'prohibit-remove'})); - my @base = ("basesystem", split /,\s*/, $urpm->{global_config}{'prohibit-remove'}); - my (%base, %basepackages, @installed_pkgs, @processed_base); - reset_pbar_count(33); - while (defined(local $_ = shift @base)) { - exists $basepackages{$_} and next; - $db->traverse_tag(m|^/| ? 'path' : 'whatprovides', [ $_ ], sub { - update_pbar($gurpm); - my $name = $_[0]->fullname; - # workaround looping in URPM: - return if MDK::Common::DataStructure::member($name, @processed_base); - push @processed_base, $name; - push @{$basepackages{$_}}, $name; - push @base, $_[0]->requires_nosense; - }); - } - foreach (values %basepackages) { - my $n = @$_; #- count number of times it's provided - foreach (@$_) { - $base{$_} = \$n; - } - } - # costly: - $db->traverse(sub { - my ($pkg) = @_; - update_pbar($gurpm); - my $fullname = urpm_name($pkg); - return if $fullname =~ /@/; - $all_pkgs->{$fullname} = { - pkg => $pkg, urpm_name => $fullname, - } if !($all_pkgs->{$fullname} && $all_pkgs->{$fullname}{description}); - if (my $name = $base{$fullname}) { - $all_pkgs->{$fullname}{base} = \$name; - $pkg->set_flag_base(1) if $$name == 1; - } - push @installed_pkgs, $fullname; - $pkg->set_flag_installed; - $pkg->pack_header; # needed in order to call methods on objects outside ->traverse - }); - @installed_pkgs; -} - -urpm::select::add_packages_to_priority_upgrade_list('rpmdragora', 'perl-Glib', 'perl-Gtk2'); - -my ($priority_state, $priority_requested); -our $need_restart; - -our $probe_only_for_updates; - -sub get_updates_list { - my ($urpm, $db, $state, $requested, $requested_list, $requested_strict, $all_pkgs, %limit_preselect) = @_; - - $urpm->request_packages_to_upgrade( - $db, - $state, - $requested, - %limit_preselect - ); - - my %common_opts = ( - callback_choices => \&ManaTools::Rpmdragora::gui::callback_choices, - priority_upgrade => $urpm->{options}{'priority-upgrade'}, - ); - - if ($urpm->{options}{'priority-upgrade'}) { - $need_restart = - urpm::select::resolve_priority_upgrades_after_auto_select($urpm, $db, $state, - $requested, %common_opts); - } - - # list of updates (including those matching /etc/urpmi/skip.list): - @$requested_list = sort map { - my $name = urpm_name($_); - $all_pkgs->{$name} = { pkg => $_ }; - $name; - } @{$urpm->{depslist}}[keys %$requested]; - - # list of pure updates (w/o those matching /etc/urpmi/skip.list but with their deps): - if ($probe_only_for_updates && !$need_restart) { - @$requested_strict = sort map { - urpm_name($_); - } $urpm->resolve_requested($db, $state, $requested, callback_choices => \&ManaTools::Rpmdragora::gui::callback_choices); - - if (my @l = grep { $state->{selected}{$_->id} } - urpm::select::_priority_upgrade_pkgs($urpm, $urpm->{options}{'priority-upgrade'})) { - if (!$need_restart) { - $need_restart = - urpm::select::_resolve_priority_upgrades($urpm, $db, $state, $state->{selected}, - \@l, %common_opts); - } - } - } - - if ($need_restart) { - $requested_strict = [ map { scalar $_->fullname } @{$urpm->{depslist}}[keys %{$state->{selected}}] ]; - # drop non priority updates: - @$requested_list = (); - } - - # list updates including skiped ones + their deps in MageiaUpdate: - @$requested_list = MDK::Common::DataStructure::uniq(@$requested_list, @$requested_strict); - - # do not pre select updates in rpmdragora: - @$requested_strict = () if !$probe_only_for_updates; -} - -sub get_pkgs { - my (%options) = @_; - my $w = $::main_window; - - myexit (-1) if (warn_about_media($w, %options) == -1); - - my $gurpm = ManaTools::Rpmdragora::gurpm->new( - text => $loc->N("Please wait"), - ); - my $_gurpm_clean_guard = MDK::Common::Func::before_leaving { undef $gurpm }; - - my $urpm = open_urpmi_db(update => $probe_only_for_updates && !is_it_a_devel_distro()); - - my $_drop_lock = MDK::Common::Func::before_leaving { undef $urpm->{lock} }; - - $priority_up_alread_warned = 0; - - # update media list in case warn_about_media() added some: - @update_medias = get_update_medias($urpm); - - $gurpm->label($loc->N("Reading updates description")); - #- parse the description file - my $update_descr = urpm::get_updates_description($urpm, @update_medias); - $gurpm->progress(100); - - my $_unused = $loc->N("Please wait, finding available packages..."); - -# # find out installed packages: - - init_progress_bar($urpm); - - $gurpm->label($loc->N("Please wait, listing base packages...")); - $gurpm->progress(ceil($level)); - - my $db = eval { open_rpm_db() }; - if (my $err = $@) { - interactive_msg($loc->N("Error"), $loc->N("A fatal error occurred: %s.", $err)); - return; - } - - my $sig_handler = sub { undef $db; exit 3 }; - local $SIG{INT} = $sig_handler; - local $SIG{QUIT} = $sig_handler; - - $gurpm->label($loc->N("Please wait, finding installed packages...")); - $level = 33; - $gurpm->progress(ceil($level)); - reset_pbar_count(66); - my (@installed_pkgs, %all_pkgs); - if (!$probe_only_for_updates) { - @installed_pkgs = get_installed_packages($urpm, $db, \%all_pkgs, $gurpm); - } - - if (my $group = get_parallel_group()) { - urpm::media::configure($urpm, parallel => $group); - } - - # find out availlable packages: - - $urpm->{state} = {}; - - $gurpm->label($loc->N("Please wait, finding available packages...")); - $level = 66; - $gurpm->progress(ceil($level)); - - check_update_media_version($urpm, @update_medias); - - my $requested = {}; - my $state = {}; - my (@requested, @requested_strict); - - if ($compute_updates->[0] || $::MODE eq 'update') { - my %filter; - if ($options{pure_updates}) { - # limit to packages from update-media (dependencies can still come from other media) - %filter = (idlist => [ map { $_->{start} .. $_->{end} } @update_medias ]); - } - get_updates_list($urpm, $db, $state, $requested, \@requested, \@requested_strict, \%all_pkgs, %filter); - } - - if ($need_restart) { - $priority_state = $state; - $priority_requested = $requested; - } else { - ($priority_state, $priority_requested) = (); - } - - if (!$probe_only_for_updates) { - $urpm->compute_installed_flags($db); # TODO/FIXME: not for updates - $urpm->{depslist}[$_]->set_flag_installed foreach keys %$requested; #- pretend it's installed - } - $urpm->{rpmdragora_state} = $state; #- Don't forget it - $level = 70; - $gurpm->progress(ceil($level)); - - my %l; - reset_pbar_count(100); - foreach my $pkg (@{$urpm->{depslist}}) { - update_pbar($gurpm); - $pkg->flag_upgrade or next; - my $key = $pkg->name . $pkg->arch; - $l{$key} = $pkg if !$l{$key} || $l{$key}->compare_pkg($pkg); - } - my @installable_pkgs = map { my $n = $_->fullname; $all_pkgs{$n} = { pkg => $_ }; $n } values %l; - undef %l; - - my @inactive_backports; - my @active_backports; - my @backport_medias = get_backport_media($urpm); - - foreach my $medium (@backport_medias) { - update_pbar($gurpm); - - # The 'searchmedia' flag differentiates inactive backport medias - # (because that option was passed to urpm::media::configure to - # temporarily enable them) - - my $backports = - $medium->{searchmedia} ? \@inactive_backports : \@active_backports; - if (defined($medium->{start}) || defined($medium->{end})) { - foreach my $pkg_id ($medium->{start} .. $medium->{end}) { - next if !$pkg_id; - my $pkg = $urpm->{depslist}[$pkg_id]; - $pkg->flag_upgrade or next; - my $name = $pkg->fullname; - push @$backports, $name; - $all_pkgs{$name} = { pkg => $pkg, is_backport => 1 }; - } - } - } - my @updates = @requested; - # selecting updates by default but skipped ones (MageiaUpdate only): - foreach (@requested_strict) { - $all_pkgs{$_}{selected} = 1; - } - - # urpmi only care about the first medium where it found the package, - # so there's no need to list the same package several time: - @installable_pkgs = MDK::Common::DataStructure::uniq(MDK::Common::DataStructure::difference2(\@installable_pkgs, \@updates)); - - my @meta_pkgs = grep { /^task-|^basesystem/ } keys %all_pkgs; - - my @gui_pkgs = map { chomp; $_ } MDK::Common::File::cat_('/usr/share/rpmdrake/gui.lst'); - # add meta packages to GUI packages list (which expect basic names not fullnames): - push @gui_pkgs, map { (split_fullname($_))[0] } @meta_pkgs; - - +{ urpm => $urpm, - all_pkgs => \%all_pkgs, - installed => \@installed_pkgs, - installable => \@installable_pkgs, - updates => \@updates, - meta_pkgs => \@meta_pkgs, - gui_pkgs => [ grep { my $p = $all_pkgs{$_}{pkg}; $p && MDK::Common::DataStructure::member(($p->fullname)[0], @gui_pkgs) } keys %all_pkgs ], - update_descr => $update_descr, - backports => [ @inactive_backports, @active_backports ], - inactive_backports => \@inactive_backports - }; -} - -sub _display_READMEs_if_needed { - my $urpm = shift; - return if !$urpm->{readmes}; - - my %Readmes = %{$urpm->{readmes}}; - return if ! scalar keys %Readmes; - - my $appTitle = yui::YUI::app()->applicationTitle(); - - ## set new title to get it in dialog - yui::YUI::app()->setApplicationTitle($loc->N("Upgrade information")); - my $factory = yui::YUI::widgetFactory; - - ## | [msg-label] | - ## | | - ## | pkg-list | - ## | | - ## | info on selected pkg |(1) - ## | | - ## | [ok] | - #### - # (1) info on pkg list: - # selected package readmi.urpmi - - my $dialog = $factory->createPopupDialog; - my $vbox = $factory->createVBox( $dialog ); - my $msgBox = $factory->createLabel($vbox, $loc->N("These packages come with upgrade information"), 1); - my $tree = $factory->createTree($vbox, $loc->N("Select a package")); - $factory->createVSpacing($vbox, 1); - my $infoBox = $factory->createRichText($vbox, "", 0); - $tree->setWeight($yui::YD_HORIZ, 2); - $infoBox->setWeight($yui::YD_HORIZ, 4); - $tree->setWeight($yui::YD_VERT, 10); - $infoBox->setWeight($yui::YD_VERT, 10); - $factory->createVSpacing($vbox, 1); - my $hbox = $factory->createHBox( $vbox ); - my $align = $factory->createHCenter($hbox); - my $okButton = $factory->createPushButton($align, $loc->N("&Ok")); - $okButton->setDefaultButton(1); - - # adding packages to the list - my $itemColl = new yui::YItemCollection; - foreach my $f (sort keys %Readmes) { - my $item = new yui::YTreeItem ("$Readmes{$f}"); - my $child = new yui::YTreeItem ($item, "$f"); - $child->DISOWN(); - $itemColl->push($item); - $item->DISOWN(); - } - $tree->addItems($itemColl); - $tree->setImmediateMode(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 - my $widget = $event->widget(); - if ($widget == $tree) { - my $content = ""; - my $item = $tree->selectedItem(); - if ($item && !$item->hasChildren()) { - my $filename = $tree->currentItem()->label(); - $content = scalar MDK::Common::File::cat_($filename); - $content = $loc->N("(none)") if !$content; # should not happen - ensure_utf8($content); - $content =~ s/\n/
/g; - } - $infoBox->setValue($content); - } - elsif ($widget == $okButton) { - last; - } - } - } - - destroy $dialog; - - # restore original title - yui::YUI::app()->setApplicationTitle($appTitle) if $appTitle; - - return; -} - -sub perform_parallel_install { - my ($urpm, $group, $w, $statusbar_msg_id) = @_; - my @pkgs = map { MDK::Common::Func::if_($_->flag_requested, urpm_name($_)) } @{$urpm->{depslist}}; - - my @error_msgs; - my $res = !ManaTools::Shared::RunProgram::run('urpmi', '2>', \@error_msgs, '-v', '--X', '--parallel', $group, @pkgs); - - if ($res) { - $$statusbar_msg_id = statusbar_msg( - #$loc->N("Everything installed successfully"), - $loc->N("All requested packages were installed successfully."), - ); - } else { - interactive_msg( - $loc->N("Problem during installation"), - $loc->N("There was a problem during the installation:\n\n%s", join("\n", @error_msgs)), - scroll => 1, - ); - } - open_rpm_db('force_sync'); - $w->set_sensitive(1); - return 0; -} - -sub perform_installation { #- (partially) duplicated from /usr/sbin/urpmi :-( - my ($urpm, $pkgs) = @_; - - my @error_msgs; - my $statusbar_msg_id; - my $gurpm; - local $urpm->{fatal} = sub { - my $fatal_msg = $_[1]; - printf STDERR "Fatal: %s\n", $fatal_msg; - undef $gurpm; - interactive_msg($loc->N("Installation failed"), - $loc->N("There was a problem during the installation:\n\n%s", $fatal_msg)); - goto return_with_exit_code; - }; - local $urpm->{error} = sub { printf STDERR "Error: %s\n", $_[0]; push @error_msgs, $_[0] }; - - my $w = $::main_window; - #$w->set_sensitive(0); - #my $_restore_sensitive = MDK::Common::Func::before_leaving { $w->set_sensitive(1) }; - - # my $_flush_guard = Gtk2::GUI_Update_Guard->new; - - if (my $group = get_parallel_group()) { - return perform_parallel_install($urpm, $group, $w, \$statusbar_msg_id); - } - - my ($lock, $rpm_lock); - if (!$::env) { - $lock = urpm::lock::urpmi_db($urpm, undef, wait => $urpm->{options}{wait_lock}); - $rpm_lock = urpm::lock::rpm_db($urpm, 'exclusive'); - } - my $state = $priority_state || $probe_only_for_updates ? { } : $urpm->{rpmdragora_state}; - - my $bar_id = statusbar_msg($loc->N("Checking validity of requested packages..."), 0); - - # FIXME: THIS SET flag_requested on all packages!!!! - # select packages to install / enssure selected pkg set is consistant: - my %saved_flags; - my $requested = { map { - $saved_flags{$_->id} = $_->flag_requested; - $_->id => undef; - } grep { $_->flag_selected } @{$urpm->{depslist}} }; - urpm::select::resolve_dependencies( - $urpm, $state, $requested, - rpmdb => $::env && "$::env/rpmdb.cz", - callback_choices => \&ManaTools::Rpmdragora::gui::callback_choices, - ); - statusbar_msg_remove($bar_id); - - my ($local_sources, $blist) = urpm::get_pkgs::selected2local_and_blists($urpm, $state->{selected}); - if (!$local_sources && (!$blist || !@$blist)) { - interactive_msg( - $loc->N("Unable to get source packages."), - $loc->N("Unable to get source packages, sorry. %s", - @error_msgs ? $loc->N("\n\nError(s) reported:\n%s", join("\n", @error_msgs)) : ''), - scroll => 1, - ); - goto return_with_exit_code; - } - - my @to_install = @{$urpm->{depslist}}[keys %{$state->{selected}}]; - my @pkgs = map { scalar($_->fullname) } sort(grep { $_->flag_selected } @to_install); - - @{$urpm->{ask_remove}} = sort(urpm::select::removed_packages($urpm->{state})); - my @to_remove = map { MDK::Common::Func::if_($pkgs->{$_}{selected} && !$pkgs->{$_}{pkg}->flag_upgrade, $pkgs->{$_}{urpm_name}) } keys %$pkgs; - - my $r = format_list(map { scalar(urpm::select::translate_why_removed_one($urpm, $urpm->{state}, $_)) } @to_remove); - - my ($size, $filesize) = $urpm->selected_size_filesize($state); - my $install_count = int(@pkgs); - my $to_install = $install_count == 0 ? '' : - ($priority_state ? '' . $loc->N("Rpmdragora or one of its priority dependencies needs to be updated first. Rpmdragora will then restart.") . '' . "\n\n" : '') . - ($loc->P("The following package is going to be installed:", "The following %d packages are going to be installed:", $install_count, $install_count) - . "\n\n" . format_list(map { s!.*/!!; $_ } @pkgs)); - my $remove_count = scalar(@to_remove); - interactive_msg(($to_install ? $loc->N("Confirmation") : $loc->N("Some packages need to be removed")), - join("\n\n", - ($r ? - (!$to_install ? ($loc->P("Remove one package?", "Remove %d packages?", $remove_count, $remove_count), $r) : - (($remove_count == 1 ? - $loc->N("The following package has to be removed for others to be upgraded:") - : $loc->N("The following packages have to be removed for others to be upgraded:")), $r), MDK::Common::Func::if_($to_install, $to_install)) - : $to_install), - format_size($size), - format_filesize($filesize), - $loc->N("Is it ok to continue?")), - scroll => 1, - yesno => 1, min_size => {lines => 18},) or return 1; - - my $_umount_guard = MDK::Common::Func::before_leaving { urpm::removable::try_umounting_removables($urpm) }; - - # select packages to uninstall for !update mode: - perform_removal($urpm, { map { $_ => $pkgs->{$_} } @to_remove }) if !$probe_only_for_updates; - - $gurpm = ManaTools::Rpmdragora::gurpm->new( - text => $loc->N("Please wait"), - title => $loc->N("Initializing..."), - ); - # my $_gurpm_clean_guard = MDK::Common::Func::before_leaving { undef $gurpm }; - my $something_installed; - - if (@to_install && $::rpmdragora_options{auto_orphans}) { - urpm::orphans::compute_future_unrequested_orphans($urpm, $state); - if (my @orphans = map { scalar $_->fullname } @{$state->{orphans_to_remove}}) { - interactive_msg($loc->N("Orphan packages"), $loc->P("The following orphan package will be removed.", - "The following orphan packages will be removed.", scalar(@orphans)) - . "\n" . urpm::orphans::add_leading_spaces(join("\n", @orphans) . "\n"), scroll => 1); - } - } - - urpm::orphans::mark_as_requested($urpm, $state, 0); - - my ($progress, $total, @rpms_upgrade); - my $transaction; - my ($progress_nb, $transaction_progress_nb, $remaining, $done); - my $callback_inst = sub { - my ($urpm, $type, $id, $subtype, $amount, $total) = @_; - my $pkg = defined $id ? $urpm->{depslist}[$id] : undef; - if ($subtype eq 'start') { - if ($type eq 'trans') { - print(1 ? $loc->N("Preparing package installation...") : $loc->N("Preparing package installation transaction...")); - $gurpm->label($loc->N("Preparing package installation...")); - } elsif (defined $pkg) { - $something_installed = 1; - print($loc->N("Installing package `%s' (%s/%s)...", $pkg->name, $transaction_progress_nb, scalar(@{$transaction->{upgrade}}))."\n" . $loc->N("Total: %s/%s", $progress_nb, $install_count)); - $gurpm->label($loc->N("Installing package `%s' (%s/%s)...", $pkg->name, ++$transaction_progress_nb, scalar(@{$transaction->{upgrade}})) - . "\n" . $loc->N("Total: %s/%s", ++$progress_nb, $install_count)); - } - } elsif ($subtype eq 'progress') { - $gurpm->progress($total ? ceil(($amount/$total)*100) : 100); - # print("Progress: ".($total ? ($amount/$total)*100 : 100)."\n"); - } - }; - - # FIXME: sometimes state is lost: - my @ask_unselect = urpm::select::unselected_packages($state); - - # fix flags for orphan computing: - foreach (keys %{$state->{selected}}) { - my $pkg = $urpm->{depslist}[$_]; - $pkg->set_flag_requested($saved_flags{$pkg->id}); - } - my $exit_code = - urpm::main_loop::run($urpm, $state, 1, \@ask_unselect, - { - completed => sub { - # explicitly destroy the progress window when it's over; we may - # have sg to display before returning (errors, rpmnew/rpmsave, ...): - undef $gurpm; - - undef $lock; - undef $rpm_lock; - }, - inst => $callback_inst, - trans => $callback_inst, - ask_yes_or_no => sub { - # handle 'allow-force' and 'allow-nodeps' options: - my ($title, $msg) = @_; - local $::main_window = $gurpm->{real_window}; - interactive_msg($title, $msg, yesno => 1, scroll => 1, - ); - }, - message => sub { - my ($title, $message) = @_; - interactive_msg($title, $message, scroll => 1); - }, - # cancel installation when 'cancel' button is pressed: - trans_log => sub { download_callback($gurpm, @_) or goto return_with_exit_code }, - post_extract => sub { - my ($set, $transaction_sources, $transaction_sources_install) = @_; - $transaction = $set; - $transaction_progress_nb = 0; - $done += grep { !/\.src\.rpm$/ } values %$transaction_sources; #updates - $total = keys(%$transaction_sources_install) + keys %$transaction_sources; - push @rpms_upgrade, keys %$transaction_sources; - $done += grep { !/\.src\.rpm$/ } values %$transaction_sources_install; # installs - }, - pre_removable => sub { - # Gtk2::GUI_Update_Guard->new use of alarm() kill us when - # running system(), thus making DVD being ejected and printing - # wrong error messages (#30463) - - local $SIG{ALRM} = sub { die "ALARM" }; - $remaining = alarm(0); - }, - - post_removable => sub { alarm $remaining }, - copy_removable => sub { - my ($medium) = @_; - interactive_msg( - $loc->N("Change medium"), - $loc->N("Please insert the medium named \"%s\"", $medium), - yesno => 1, text => { no => $loc->N("Cancel"), yes => $loc->N("Ok") }, - ); - }, - pre_check_sig => sub { $gurpm->label($loc->N("Verifying package signatures...")) }, - check_sig => sub { $gurpm->progress(ceil(++$progress/$total)*100) }, - bad_signature => sub { - my ($msg, $msg2) = @_; - local $::main_window = $gurpm->{real_window}; - $msg =~ s/:$/\n\n/m; # FIXME: to be fixed in urpmi after 2008.0 - interactive_msg( - $loc->N("Warning"), "$msg\n\n$msg2", yesno => 1, MDK::Common::Func::if_(10 < ($msg =~ tr/\n/\n/), scroll => 1), - ); - }, - post_download => sub { - $canceled and goto return_with_exit_code; -# $gurpm->invalidate_cancel_forever; - }, - need_restart => sub { - my ($need_restart_formatted) = @_; - # FIXME: offer to restart the system - interactive_msg($loc->N("Warning"), join("\n", values %$need_restart_formatted), scroll => 1); - }, - trans_error_summary => sub { - my ($nok, $errors) = @_; - interactive_msg( - $loc->N("Problem during installation"), - MDK::Common::Func::if_($nok, $loc->N("%d installation transactions failed", $nok) . "\n\n") . - $loc->N("There was a problem during the installation:\n\n%s", - join("\n\n", @$errors, @error_msgs)), - scroll => 1, - ); - }, - need_restart => sub { - my ($need_restart_formatted) = @_; - interactive_msg($loc->N("Warning"), - join("\n\n", values %$need_restart_formatted)); - }, - success_summary => sub { - if (!($done || @to_remove)) { - interactive_msg($loc->N("Error"), - $loc->N("Unrecoverable error: no package found for installation, sorry.")); - return; - } - my $id = statusbar_msg($loc->N("Inspecting configuration files..."), 0); - my %pkg2rpmnew; - foreach my $id (@rpms_upgrade) { - my $pkg = $urpm->{depslist}[$id]; - next if $pkg->arch eq 'src'; - $pkg2rpmnew{$pkg->fullname} = [ grep { -r "$_.rpmnew" || -r "$_.rpmsave" } $pkg->conf_files ]; - } - statusbar_msg_remove($id); - rpmnew_dialog($loc->N("The installation is finished; everything was installed correctly. - -Some configuration files were created as `.rpmnew' or `.rpmsave', -you may now inspect some in order to take actions:"), - %pkg2rpmnew) - and statusbar_msg($loc->N("All requested packages were installed successfully."), 1); - statusbar_msg($loc->N("Looking for \"README\" files..."), 1); - _display_READMEs_if_needed($urpm); - }, - already_installed_or_not_installable => sub { - my ($msg1, $msg2) = @_; - my $msg = join("\n", @$msg1, @$msg2); - return if !$msg; # workaround missing state - interactive_msg($loc->N("Error"), $msg); - }, - }, - ); - - #- restart rpmdragora if needed, keep command line for that. - if ($need_restart && !$exit_code && $something_installed) { - Sys::Syslog::syslog('info|local1', "restarting rpmdragora"); - #- it seems to work correctly with exec instead of system, provided we stop timers - #- added --previous-priority-upgrade to allow checking if yet if - #- priority-upgrade list has changed. and make sure we don't uselessly restart - my @argv = ('--previous-priority-upgrade=' . $urpm->{options}{'priority-upgrade'}, - grep { !/^--no-priority-upgrade$|--previous-priority-upgrade=/ } @ManaTools::Rpmdragora::init::ARGV_copy); - # remove "--emmbedded " from argv: - my $i = 0; - foreach (@argv) { - splice @argv, $i, 2 if /^--embedded$/; - $i++; - } - alarm(0); - # reMDK::Common::DataStructure::member not to ask again questions and the like: - writeconf(); - exec($0, @argv); - exit(0); - } - - my $_s1 = $loc->N("RPM transaction %d/%d", 0, 0); - my $_s2 = $loc->N("Unselect all"); - my $_s3 = $loc->N("Details"); - - statusbar_msg_remove($statusbar_msg_id); #- XXX maybe remove this - - if ($exit_code == 0 && !$::rpmdragora_options{auto_orphans}) { - if (urpm::orphans::check_unrequested_orphans_after_auto_select($urpm)) { - if (my $msg = urpm::orphans::get_now_orphans_gui_msg($urpm)) { - interactive_msg($loc->N("Orphan packages"), $msg, scroll => 1); - } - } - } - - return_with_exit_code: - return !($something_installed || scalar(@to_remove)); -} - - -# -=-=-=---=-=-=---=-=-=-- remove packages -=-=-=---=-=-=---=-=-=- - -sub perform_removal { - my ($urpm, $pkgs) = @_; - my @toremove = map { MDK::Common::Func::if_($pkgs->{$_}{selected}, $pkgs->{$_}{urpm_name}) } keys %$pkgs; - return if !@toremove; - my $gurpm = ManaTools::Rpmdragora::gurpm->new( - text => $loc->N("Please wait") - ); - my $_gurpm_clean_guard = MDK::Common::Func::before_leaving { undef $gurpm }; - - my $may_be_orphans = 1; - urpm::orphans::unrequested_orphans_after_remove($urpm, \@toremove) - or $may_be_orphans = 0; - - my $progress = -1; - local $urpm->{log} = sub { - my $str = $_[0]; - print $str; - $progress++; - return if $progress <= 0; # skip first "creating transaction..." message - $gurpm->label($str); # display "removing package %s" - $gurpm->progress(ceil(min(99, scalar($progress/@toremove)*100))); - #gtkflush(); - }; - - my @results; - slow_func_statusbar( - $loc->N("Please wait, removing packages..."), - $::main_window, - sub { - @results = $::rpmdragora_options{parallel} - ? urpm::parallel::remove($urpm, \@toremove) - : urpm::install::install($urpm, \@toremove, {}, {}, - callback_report_uninst => sub { $gurpm->label($_[0]) }, - ); - open_rpm_db('force_sync'); - }, - ); - if (@results) { - interactive_msg( - $loc->N("Problem during removal"), - $loc->N("There was a problem during the removal of packages:\n\n%s", join("\n", @results)), - MDK::Common::Func::if_(@results > 1, scroll => 1), - ); - return 1; - } else { - if ($may_be_orphans && !$::rpmdragora_options{auto_orphans}) { - if (my $msg = urpm::orphans::get_now_orphans_gui_msg($urpm)) { - interactive_msg($loc->N("Information"), $msg, scroll => 1); - } - } - return 0; - } -} - -1; diff --git a/lib/AdminPanel/Rpmdragora/rpmnew.pm b/lib/AdminPanel/Rpmdragora/rpmnew.pm deleted file mode 100644 index 659c0b2..0000000 --- a/lib/AdminPanel/Rpmdragora/rpmnew.pm +++ /dev/null @@ -1,363 +0,0 @@ -# vim: set et ts=4 sw=4: -package ManaTools::Rpmdragora::rpmnew; -#***************************************************************************** -# -# Copyright (c) 2002 Guillaume Cottenceau -# Copyright (c) 2002-2007 Thierry Vignaud -# Copyright (c) 2003, 2004, 2005 MandrakeSoft SA -# Copyright (c) 2005-2007 Mandriva SA -# Copyright (c) 2013 - 2015 Matteo Pasotti -# 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. -# -#***************************************************************************** -# -# $Id: rpmnew.pm 263914 2009-12-03 17:41:02Z tv $ - -use strict; -use Text::Diff; -use MDK::Common::Math qw(sum); -use MDK::Common::File qw(renamef); -use MDK::Common::Various qw(chomp_); - -use ManaTools::rpmdragora; -use ManaTools::Rpmdragora::init; -use ManaTools::Rpmdragora::pkg; -use ManaTools::Rpmdragora::open_db; -use ManaTools::Rpmdragora::formatting; - -use yui; - -use Exporter; -our @ISA = qw(Exporter); -our @EXPORT = qw(rpmnew_dialog do_merge_if_needed); - -my $loc = ManaTools::rpmdragora::locale(); - -# /var/lib/nfs/etab /var/lib/nfs/rmtab /var/lib/nfs/xtab /var/cache/man/whatis -my %ignores_rpmnew = map { $_ => 1 } qw( - /etc/adjtime - /etc/fstab - /etc/group - /etc/ld.so.conf - /etc/localtime - /etc/modules - /etc/passwd - /etc/security/fileshare.conf - /etc/shells - /etc/sudoers - /etc/sysconfig/alsa - /etc/sysconfig/autofsck - /etc/sysconfig/harddisks - /etc/sysconfig/harddrake2/previous_hw - /etc/sysconfig/init - /etc/sysconfig/installkernel - /etc/sysconfig/msec - /etc/sysconfig/nfs - /etc/sysconfig/pcmcia - /etc/sysconfig/rawdevices - /etc/sysconfig/saslauthd - /etc/sysconfig/syslog - /etc/sysconfig/usb - /etc/sysconfig/xinetd -); - - -#============================================================= - -=head2 _rpmnewFile - -=head3 INPUT - - $filename: configuration file name - -=head3 OUTPUT - - $rpmnew_filename: new configuration file name - -=head3 DESCRIPTION - - This function evaluate the new configration file generated by - the update - -=cut - -#============================================================= -sub _rpmnewFile ($) { - my $filename = shift; - - my ($rpmnew, $rpmsave) = ("$filename.rpmnew", "$filename.rpmsave"); - my $rpmfile = 'rpmnew'; - -r $rpmnew or $rpmfile = 'rpmsave'; - -r $rpmnew && -r $rpmsave && (stat $rpmsave)[9] > (stat $rpmnew)[9] and $rpmfile = 'rpmsave'; - $rpmfile eq 'rpmsave' and $rpmnew = $rpmsave; - - return $rpmnew; -} - -#============================================================= - -=head2 _performDiff - -=head3 INPUT - - $file: configuration file name - $diffBox: YWidget that will show the difference - -=head3 DESCRIPTION - - This function gets the configuration file perfomrs - the difference with the new one and shows it into the - $diffBox - -=cut - -#============================================================= -sub _performDiff ($$) { - my ($file, $diffBox) = @_; - - my $rpmnew = _rpmnewFile($file); - - foreach (qw(LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT LC_IDENTIFICATION LC_ALL)) { - local $ENV{$_} = $ENV{$_} . '.UTF-8' if $ENV{$_} && $ENV{$_} !~ /UTF-8/; - } - - my $diff = diff $file, $rpmnew, { STYLE => "Unified" }; - $diff = $loc->N("(none)") if !$diff; - - my @lines = split ("\n", $diff); - ## adding color lines to diff - foreach my $line (@lines) { - if (substr ($line, 0, 1) eq "+") { - $line =~ s|^\+(.*)|+$1|; - } - elsif (substr ($line, 0, 1) eq "-") { - $line =~ s|^\-(.*)|-$1|; - } - elsif (substr ($line, 0, 1) eq "@") { - $line =~ s|(.*)|$1|; - } - else { - $line =~ s|(.*)|$1|; - } - } - $diff = join("
", @lines); - - ensure_utf8($diff); - $diffBox->setValue($diff); - - return; -} - -#============================================================= - -=head2 rpmnew_dialog - -=head3 INPUT - - $msg: message to be shown during the choice - %o2r: HASH containing { - the package name => ARRAY of configration files - } - -=head3 OUTPUT - - 1 if nothing to do or 0 after user interaction - -=head3 DESCRIPTION - - This function shows the configuration files difference and - asks for action to be performed - -=cut - -#============================================================= -sub rpmnew_dialog { - my ($msg, %p2r) = @_; - - @{$p2r{$_}} = grep { !$ignores_rpmnew{$_} } @{$p2r{$_}} foreach keys %p2r; - my $sum_rpmnew = MDK::Common::Math::sum(map { int @{$p2r{$_}} } keys %p2r); - $sum_rpmnew == 0 and return 1; - - my $appTitle = yui::YUI::app()->applicationTitle(); - - ## set new title to get it in dialog - yui::YUI::app()->setApplicationTitle($loc->N("Installation finished")); - - my $factory = yui::YUI::widgetFactory; - - ## | [msg-label] | - ## | | - ## | pkg-tree | - ## | | - ## | info on selected pkg |(1) - ## | Remove( ) Use ( ) Do nothing (*) | - ## | | - ## | [ok] | - #### - # (1) info on pkg list: - # selected configuration file diff between rpmnew/rpmsave and used one - - my $dialog = $factory->createPopupDialog; - my $vbox = $factory->createVBox( $dialog ); - my $msgBox = $factory->createLabel($vbox, $msg, 1); - $factory->createVSpacing($vbox, 1); - # Tree for groups - my $tree = $factory->createTree($vbox, $loc->N("Select a package")); - $tree->setWeight($yui::YD_VERT,10); - $factory->createVSpacing($vbox, 1); - my $infoBox = $factory->createRichText($vbox, "", 0); - $infoBox->setWeight($yui::YD_HORIZ, 20); - $infoBox->setWeight($yui::YD_VERT, 20); - $factory->createVSpacing($vbox, 1); - my $radiobuttongroup = $factory->createRadioButtonGroup($vbox); - my $rbbox = $factory->createHBox($radiobuttongroup); - my $rdnBtn = { - remove_rpmnew => $loc->N("Remove new file"), - use_rpmnew => $loc->N("Use new file"), - do_onthing => $loc->N("Do nothing"), - }; - - my %radiobutton = (); - my @rdnbtn_order = ('remove_rpmnew', 'use_rpmnew', 'do_onthing'); - foreach my $btn_name (@rdnbtn_order) { - $radiobutton{$btn_name} = $factory->createRadioButton($rbbox, $rdnBtn->{$btn_name}); - $radiobutton{$btn_name}->setValue(1) if $btn_name eq 'do_onthing'; - $radiobutton{$btn_name}->setNotify(1); - $radiobuttongroup->addRadioButton($radiobutton{$btn_name}); - } - $radiobuttongroup->setEnabled(0); - my $hbox = $factory->createHBox( $vbox ); - my $align = $factory->createHCenter($hbox); - my $okButton = $factory->createPushButton($align, $loc->N("&Ok")); - $okButton->setDefaultButton(1); - - # adding packages to the list - my $itemColl = new yui::YItemCollection; - my $num = 0; - my %file_action = (); - foreach my $p (sort keys %p2r) { - if (scalar @{$p2r{$p}}) { - my $item = new yui::YTreeItem ("$p"); - foreach my $f (@{$p2r{$p}}) { - my $child = new yui::YTreeItem ($item, "$f"); - $child->DISOWN(); - $file_action{$f} = 'do_onthing'; - } - $itemColl->push($item); - $item->DISOWN(); - } - } - - $tree->addItems($itemColl); - $tree->setImmediateMode(1); - $tree->rebuildTree(); - - 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 - my $widget = $event->widget(); - if ($widget == $tree) { - #change info - my $item = $tree->selectedItem(); - if ($item && !$item->hasChildren()) { - my $filename = $tree->currentItem()->label(); - _performDiff($filename, $infoBox); - $radiobuttongroup->setEnabled(1); - #$radiobuttongroup->uncheckOtherButtons ($radiobutton{$file_action{$filename}}); - yui::YUI::ui()->blockEvents(); - $radiobutton{$file_action{$filename}}->setValue(1); - yui::YUI::ui()->unblockEvents(); - } - else { - $infoBox->setValue(""); - $radiobuttongroup->setEnabled(0); - } - } - elsif ($widget == $okButton) { - # TODO - foreach my $file (keys %file_action) { - my $rpmnew = _rpmnewFile($file); - if ($file_action{$file} eq 'remove_rpmnew') { - eval { unlink "$rpmnew"}; - } - elsif ($file_action{$file} eq 'use_rpmnew') { - MDK::Common::File::renamef($rpmnew, $file); - } - # else do_onthing - } - last; - } - else { - # radio buttons - RDNBTN: foreach my $btn_name (@rdnbtn_order) { - if ($widget == $radiobutton{$btn_name}) { - my $filename = $tree->currentItem()->label(); - $file_action{$filename} = $btn_name; - last RDNBTN; - } - } - } - } - } - - destroy $dialog; - - # restore original title - yui::YUI::app()->setApplicationTitle($appTitle) if $appTitle; - - return 0; -} - - -#============================================================= - -=head2 do_merge_if_needed - -=head3 DESCRIPTION - - This function look for new configuration file versions - and ask for actions using the rpmnew_dialog - -=cut - -#============================================================= -sub do_merge_if_needed() { - if ($rpmdragora_options{'merge-all-rpmnew'}) { - my %pkg2rpmnew; - my $wait = wait_msg($loc->N("Please wait, searching...")); - print "Searching .rpmnew and .rpmsave files...\n"; - # costly: - open_rpm_db()->traverse(sub { - my $n = my_fullname($_[0]); - $pkg2rpmnew{$n} = [ grep { m|^/etc| && (-r "$_.rpmnew" || -r "$_.rpmsave") } map { chomp_($_) } $_[0]->conf_files ]; - }); - print "done.\n"; - remove_wait_msg($wait); - - rpmnew_dialog('', %pkg2rpmnew) and print "Nothing to do.\n"; - } - - return; -} - -1; diff --git a/lib/AdminPanel/SettingsReader.pm b/lib/AdminPanel/SettingsReader.pm deleted file mode 100644 index 318aefd..0000000 --- a/lib/AdminPanel/SettingsReader.pm +++ /dev/null @@ -1,101 +0,0 @@ -# vim: set et ts=4 sw=4: -package ManaTools::SettingsReader; -#============================================================= -*-perl-*- - -=head1 NAME - -ManaTools::SettingsReader - This module allows to load an XML configuration file - -=head1 SYNOPSIS - - use ManaTools::SettingsReader; - - my $settings = new ManaTools::SettingsReader($fileName); - -=head1 DESCRIPTION - - This module allows to load a configuration file returning a Hash references with its content. - -=head1 SUPPORT - -You can find documentation for this module with the perldoc command: - -perldoc ManaTools::SettingsReader - -=head1 SEE ALSO - - XML::Simple - -=head1 AUTHOR - - Angelo Naselli - -=head1 COPYRIGHT and LICENSE - - Copyright (C) 2012-2015, Angelo Naselli. - - This file is part of ManaTools - - ManaTools is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - ManaTools 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 ManaTools. If not, see . - -=head1 FUNCTIONS - -=cut - - -use strict; -use warnings; -use diagnostics; -use XML::Simple; -use Data::Dumper; - -#============================================================= - -=head2 new - -=head3 INPUT - - $fileName: File to be loaded - -=head3 OUTPUT - - $settings: Hash reference containing read settings - -=head3 DESCRIPTION - - The constructor just loads the given files and return its representation - into a hash reference. - -=cut - -#============================================================= - -sub new { - my ($class, $fileName) = @_; - - my $self = { - settings => 0, - }; - bless $self, 'ManaTools::SettingsReader'; - - die "File " . $fileName . " not found" if (! -e $fileName); - - my $xml = new XML::Simple (KeyAttr=>[]); - $self->{settings} = $xml->XMLin($fileName); - - return $self->{settings}; -} - - -1; diff --git a/lib/AdminPanel/Shared.pm b/lib/AdminPanel/Shared.pm deleted file mode 100644 index 6a40539..0000000 --- a/lib/AdminPanel/Shared.pm +++ /dev/null @@ -1,376 +0,0 @@ -# vim: set et ts=4 sw=4: -# Copyright 2012-2015 Angelo Naselli -# Copyright 2013-2015 Matteo Pasotti -# -# This file is part of ManaTools -# -# ManaTools is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. -# -# ManaTools 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 ManaTools. If not, see . - -package ManaTools::Shared; - -=head1 NAME - -ManaTools::Shared - ManaTools::Shared contains all the shared routines - needed by ManaTools and modules - -=head1 SYNOPSIS - - - -=head1 DESCRIPTION - -This module collects all the routines shared between ManaTools and its modules. - -=head1 EXPORT - - trim - md5sum - pathList2hash - distName - apcat - inArray - disable_x_screensaver - enable_x_screensaver - isProcessRunning - -=head1 SUPPORT - -You can find documentation for this module with the perldoc command: - - perldoc ManaTools::Shared - -=head1 AUTHOR - -Angelo Naselli - -=head1 COPYRIGHT and LICENSE - -Copyright (C) 2013, Angelo Naselli. -Copyright (C) 2014, Matteo Pasotti. - -This file is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) any later version. - -This file 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 file. If not, see . - -=head1 FUNCTIONS - -=cut - -use strict; -use warnings; -use diagnostics; - -use Digest::MD5; - -use yui; -use base qw(Exporter); - -# TODO move GUI dialogs to Shared::GUI -our @EXPORT_OK = qw( - trim - md5sum - pathList2hash - distName - apcat - inArray - disable_x_screensaver - enable_x_screensaver - isProcessRunning -); - - -=head1 VERSION - -Version 0.01 - -=cut - -our $VERSION = '0.01'; - - - -#============================================================= - -=head2 apcat - -=head3 PARAMETERS - -$filename the name of the file to read - -=head3 OUTPUT - -depending from the context it returns the content -of the file as an array or a string - -=head3 DESCRIPTION - -This function return the content of $filename or false/0 -if it fails - -=cut - -#============================================================= - -sub apcat { - my $fn = shift(); - my $fh = undef; - my @content = (); - open($fh, "<", $fn) || return 0; - while(<$fh>) - { - push(@content, $_); - } - return (wantarray() ? @content : join('',@content)); -} - - -#============================================================= - -=head2 distName - -=head3 OUTPUT - -$distname: name of the distributed package - -=head3 DESCRIPTION - -This function return the distname, useful to retrieve data -with File::ShareDir::dist_file and must be the same as into -Makefile.PL (e.g. manatools) - -=cut - -#============================================================= - -sub distName { - return "manatools"; -} - - -#============================================================= - -=head2 trim - -=head3 INPUT - - $st: String to be trimmed - -=head3 OUTPUT - - $st: trimmed string - -=head3 DESCRIPTION - -This function trim the given string. - -=cut - -#============================================================= - -sub trim { - my ($st) = shift; - $st =~s /^\s+//g; - $st =~s /\s+$//g; - return $st; -} - -#============================================================= - -=head2 inArray - -=head3 INPUT - - $item: item to search - $arr: array container - -=head3 OUTPUT - - true: if the array contains the item - -=head3 DESCRIPTION - -This method returns if an item is into the array container - -=cut - -#============================================================= -sub inArray { - my ($item, $arr) = @_; - - return grep( /^$item$/, @{$arr} ); -} - - -#============================================================= - -=head2 md5sum - -=head3 INPUT - - $filename: file for md5 calculation - -=head3 OUTPUT - - md5 sum - -=head3 DESCRIPTION - - compute MD5 for the given file - -=cut - -#============================================================= - -sub md5sum { - my @files = @_; - - my @md5 = map { - my $sum; - if (open(my $FILE, $_)) { - binmode($FILE); - $sum = Digest::MD5->new->addfile($FILE)->hexdigest; - close($FILE); - } - $sum; - } @files; - return wantarray() ? @md5 : $md5[0]; -} - -#============================================================= - -=head2 pathList2hash - -=head3 INPUT - - $param : HASH ref containing - paths => ARRAY of string containing path like strings - separator => item separator inside a single path - (default separator is /) - -=head3 OUTPUT - - \%tree: HASH reference containing the same structur passed as ARRAY - in a tree view form, leaves are undef. - -=head3 DESCRIPTION - - This function return a tree representation of the given array. - -=cut - -#============================================================= - -sub pathList2hash { - my ($param) = @_; - - die "array of path is missing" if ! exists $param->{paths}; - my $separator = '/'; - $separator = $param->{separator} if $param->{separator}; - if ($separator eq "/" || $separator eq "|") { - $separator = '\\' . $separator; - } - - my %tree; - for (@{$param->{paths}}) - { - my $last = \\%tree; - $last = \$$last->{$_} for split /$separator/; - } - - return \%tree; -} - -#============================================================= - -=head2 disable_x_screensaver - -=head3 DESCRIPTION - - if exists /usr/bin/xset disable screensaver - -=cut - -#============================================================= -sub disable_x_screensaver() { - if (-e '/usr/bin/xset') { - $ENV{PATH} = "/usr/bin:/usr/sbin"; - system ("/usr/bin/xset s off"); - system ("/usr/bin/xset -dpms"); - } -} - -#============================================================= - -=head2 enable_x_screensaver - -=head3 DESCRIPTION - - if exists /usr/bin/xset enables screensaver - -=cut - -#============================================================= -sub enable_x_screensaver() { - if (-e '/usr/bin/xset') { - $ENV{PATH} = "/usr/bin:/usr/sbin"; - system ("/usr/bin/xset +dpms"); - system ("/usr/bin/xset s on"); - system ("/usr/bin/xset s reset"); - } -} - -#============================================================= - -=head2 isProcessRunning - -=head3 INPUT - - $name: Process name - $o_user: user who the process belongs to - -=head3 OUTPUT - - $pid: process identifier - -=head3 DESCRIPTION - - Function returns the process identifier if the given - process is running - -=cut - -#============================================================= -sub isProcessRunning { - my ($name, $o_user) = @_; - my $user = $o_user || $ENV{USER}; - my @proc = `ps -o '%P %p %c' -u $user`; - shift (@proc); - foreach (@proc) { - my ($ppid, $pid, $n) = /^\s*(\d+)\s+(\d+)\s+(.*)/; - return $pid if $n eq $name && $ppid != 1 && $pid != $$; - } - return; -} - -1; # End of ManaTools::Shared - diff --git a/lib/AdminPanel/Shared/Firewall.pm b/lib/AdminPanel/Shared/Firewall.pm deleted file mode 100644 index f5a6c45..0000000 --- a/lib/AdminPanel/Shared/Firewall.pm +++ /dev/null @@ -1,35 +0,0 @@ -# vim: set et ts=4 sw=4: -#***************************************************************************** -# -# Copyright (c) 2013-2015 Matteo Pasotti -# -# 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::Shared::Firewall; - -use Moose; -use diagnostics; -use utf8; - -use lib qw(/usr/lib/libDrakX); -use network::nfs; -use network::network; -use network::tools; - -sub _initialize { - my $self = shift(); -} - -1; diff --git a/lib/AdminPanel/Shared/GUI.pm b/lib/AdminPanel/Shared/GUI.pm deleted file mode 100644 index 6c6144d..0000000 --- a/lib/AdminPanel/Shared/GUI.pm +++ /dev/null @@ -1,1118 +0,0 @@ -# vim: set et ts=4 sw=4: -package ManaTools::Shared::GUI; -#============================================================= -*-perl-*- - -=head1 NAME - -Shared::GUI - Shared graphic routines - -=head1 SYNOPSIS - - my $gui = ManaTools::Shared::GUI->new(); - my $yesPressed = $gui->ask_YesOrNo($title, $text); - -=head1 DESCRIPTION - - This module contains a collection of dialogs or widgets that can be used in more - graphics modules. - -=head1 EXPORT - -exported - -=head1 SUPPORT - -You can find documentation for this module with the perldoc command: - -perldoc Shared::GUI - - -=head1 AUTHOR - -Angelo Naselli - -=head1 COPYRIGHT and LICENSE - -Copyright (C) 2014-2015, Angelo Naselli. -Copyright (C) 2015, Matteo Pasotti . - -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 METHODS - -=cut - - -use Moose; - -use diagnostics; -use yui; - -use ManaTools::Shared qw(pathList2hash); - -use ManaTools::Shared::Locales; - -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' -} - - -#============================================================= - -=head2 warningMsgBox - -=head3 INPUT - - $info: HASH, information to be passed to the dialog. - title => dialog title - text => string to be swhon into the dialog - richtext => 1 if using rich text - -=head3 DESCRIPTION - - This function creates an Warning dialog and show the message - passed as input. - -=cut - -#============================================================= -sub warningMsgBox { - my ($self, $info) = @_; - - return 0 if ( ! $info ); - - my $retVal = 0; - yui::YUI::widgetFactory; - my $factory = yui::YExternalWidgets::externalWidgetFactory("mga"); - $factory = yui::YMGAWidgetFactory::getYMGAWidgetFactory($factory); - my $dlg = $factory->createDialogBox($yui::YMGAMessageBox::B_ONE, - $yui::YMGAMessageBox::D_WARNING); - - $dlg->setTitle($info->{title}) if (exists $info->{title}); - my $rt = (exists $info->{richtext}) ? $info->{richtext} : 0; - $dlg->setText($info->{text}, $rt) if (exists $info->{text}); - - $dlg->setButtonLabel($self->loc->N("Ok"), $yui::YMGAMessageBox::B_ONE ); -# $dlg->setMinSize(50, 5); - - $retVal = $dlg->show(); - - $dlg = undef; - - return 1; -} - -#============================================================= - -=head2 infoMsgBox - -=head3 INPUT - - $info: HASH, information to be passed to the dialog. - title => dialog title - text => string to be swhon into the dialog - richtext => 1 if using rich text - -=head3 DESCRIPTION - - This function creates an Info dialog and show the message - passed as input. - -=cut - -#============================================================= - -sub infoMsgBox { - my ($self, $info) = @_; - - return 0 if ( ! $info ); - - my $retVal = 0; - yui::YUI::widgetFactory; - my $factory = yui::YExternalWidgets::externalWidgetFactory("mga"); - $factory = yui::YMGAWidgetFactory::getYMGAWidgetFactory($factory); - my $dlg = $factory->createDialogBox($yui::YMGAMessageBox::B_ONE, - $yui::YMGAMessageBox::D_INFO); - - $dlg->setTitle($info->{title}) if (exists $info->{title}); - my $rt = (exists $info->{richtext}) ? $info->{richtext} : 0; - $dlg->setText($info->{text}, $rt) if (exists $info->{text}); - - $dlg->setButtonLabel($self->loc->N("Ok"), $yui::YMGAMessageBox::B_ONE ); -# $dlg->setMinSize(50, 5); - - $retVal = $dlg->show(); - - $dlg = undef; - - return 1; -} - -#============================================================= - -=head2 msgBox - -=head3 INPUT - - $info: HASH, information to be passed to the dialog. - title => dialog title - text => string to be swhon into the dialog - richtext => 1 if using rich text - -=head3 DESCRIPTION - - This function creates a dialog and show the message passed as input. - -=cut - -#============================================================= - -sub msgBox { - my ($self, $info) = @_; - - return 0 if ( ! $info ); - - my $retVal = 0; - yui::YUI::widgetFactory; - my $factory = yui::YExternalWidgets::externalWidgetFactory("mga"); - $factory = yui::YMGAWidgetFactory::getYMGAWidgetFactory($factory); - my $dlg = $factory->createDialogBox($yui::YMGAMessageBox::B_ONE); - - $dlg->setTitle($info->{title}) if (exists $info->{title}); - my $rt = (exists $info->{richtext}) ? $info->{richtext} : 0; - $dlg->setText($info->{text}, $rt) if (exists $info->{text}); - - $dlg->setButtonLabel($self->loc->N("Ok"), $yui::YMGAMessageBox::B_ONE ); -# $dlg->setMinSize(50, 5); - - $retVal = $dlg->show(); - - $dlg = undef; - - return 1; -} - -#============================================================= - -=head2 ask_OkCancel - -=head3 INPUT - - $info: HASH, information to be passed to the dialog. - title => dialog title - text => string to be swhon into the dialog - richtext => 1 if using rich text - -=head3 OUTPUT - - 0: Cancel button has been pressed - 1: Ok button has been pressed - -=head3 DESCRIPTION - - This function create an OK-Cancel dialog with a 'title' and a - 'text' passed as parameters. - -=cut - -#============================================================= - -sub ask_OkCancel { - my ($self, $info) = @_; - - return 0 if ( ! $info ); - - my $retVal = 0; - yui::YUI::widgetFactory; - my $factory = yui::YExternalWidgets::externalWidgetFactory("mga"); - $factory = yui::YMGAWidgetFactory::getYMGAWidgetFactory($factory); - my $dlg = $factory->createDialogBox($yui::YMGAMessageBox::B_TWO); - - $dlg->setTitle($info->{title}) if (exists $info->{title}); - my $rt = (exists $info->{richtext}) ? $info->{richtext} : 0; - $dlg->setText($info->{text}, $rt) if (exists $info->{text}); - - $dlg->setButtonLabel($self->loc->N("Ok"), $yui::YMGAMessageBox::B_ONE ); - $dlg->setButtonLabel($self->loc->N("Cancel"), $yui::YMGAMessageBox::B_TWO); - $dlg->setDefaultButton($yui::YMGAMessageBox::B_ONE); - $dlg->setMinSize(50, 5); - - $retVal = $dlg->show() == $yui::YMGAMessageBox::B_ONE ? 1 : 0; - - $dlg = undef; - - return $retVal; -} - -#============================================================= - -=head2 ask_YesOrNo - -=head3 INPUT - - $info: HASH, information to be passed to the dialog. - title => dialog title - text => string to be swhon into the dialog - richtext => 1 if using rich text - default_button => (optional) 1: "Yes" (any other values "No") - -=head3 OUTPUT - - 0: "No" button has been pressed - 1: "Yes" button has been pressed - -=head3 DESCRIPTION - - This function create a Yes-No dialog with a 'title' and a - question 'text' passed as parameters. - -=cut - -#============================================================= - -sub ask_YesOrNo { - my ($self, $info) = @_; - - return 0 if ( ! $info ); - - my $retVal = 0; - yui::YUI::widgetFactory; - my $factory = yui::YExternalWidgets::externalWidgetFactory("mga"); - $factory = yui::YMGAWidgetFactory::getYMGAWidgetFactory($factory); - my $dlg = $factory->createDialogBox($yui::YMGAMessageBox::B_TWO); - - $dlg->setTitle($info->{title}) if (exists $info->{title}); - my $rt = (exists $info->{richtext}) ? $info->{richtext} : 0; - $dlg->setText($info->{text}, $rt) if (exists $info->{text}); - - $dlg->setButtonLabel($self->loc->N("Yes"), $yui::YMGAMessageBox::B_ONE ); - $dlg->setButtonLabel($self->loc->N("No"), $yui::YMGAMessageBox::B_TWO); - if (exists $info->{default_button} && $info->{default_button} == 1) { - $dlg->setDefaultButton($yui::YMGAMessageBox::B_ONE); - } - else { - $dlg->setDefaultButton($yui::YMGAMessageBox::B_TWO); - } - $dlg->setMinSize(50, 5); - - $retVal = $dlg->show() == $yui::YMGAMessageBox::B_ONE ? 1 : 0; - - $dlg = undef; - - return $retVal; -} - - -#============================================================= - -=head2 ask_TwoConfigurableButtons - -=head3 INPUT - -$info: HASH, information to be passed to the dialog. - title => dialog title - text => string to be swhon into the dialog - richtext => 1 if using rich text - button_one => caption for the first button - button_two => caption for the second button - default_button => (optional) 1: "First button" - -=head3 OUTPUT - - 0: "Button One Caption" button has been pressed - 1: "Button Two Caption" button has been pressed - -=head3 DESCRIPTION - -This function create a two-buttons dialog with a 'title', a -question 'text' and a label for each button passed as parameters. - -=cut - -#============================================================= - -sub ask_TwoConfigurableButtons { - my ($self, $info) = @_; - - return 0 if ( ! $info ); - - my $retVal = 0; - yui::YUI::widgetFactory; - my $factory = yui::YExternalWidgets::externalWidgetFactory("mga"); - $factory = yui::YMGAWidgetFactory::getYMGAWidgetFactory($factory); - my $dlg = $factory->createDialogBox($yui::YMGAMessageBox::B_TWO); - - $dlg->setTitle($info->{title}) if (exists $info->{title}); - my $rt = (exists $info->{richtext}) ? $info->{richtext} : 0; - $dlg->setText($info->{text}, $rt) if (exists $info->{text}); - - $dlg->setButtonLabel($info->{button_one}, $yui::YMGAMessageBox::B_ONE ); - $dlg->setButtonLabel($info->{button_two}, $yui::YMGAMessageBox::B_TWO); - if (exists $info->{default_button} && $info->{default_button} == 1) { - $dlg->setDefaultButton($yui::YMGAMessageBox::B_ONE); - } - else { - $dlg->setDefaultButton($yui::YMGAMessageBox::B_TWO); - } - $dlg->setMinSize(50, 5); - - $retVal = $dlg->show() == $yui::YMGAMessageBox::B_ONE ? 1 : 0; - - $dlg = undef; - - return $retVal; -} - -#============================================================= - -=head2 arrayListToYItemCollection - -=head3 INPUT - - $listInfo: HASH reference containing - default_item => Selected item (if any) - item_list => ARRAY reference containing the item list - -=head3 OUTPUT - - $itemList: YItemCollection containing the item list passed - -=head3 DESCRIPTION - - This method returns a YItemCollection containing the item list passed with default item - the "default_item" - -=cut - -#============================================================= - -sub arrayListToYItemCollection { - my ($self, $listInfo) = @_; - - die "Item list is mandatory" if !($listInfo->{item_list}); - # TODO check type - die "Not empty item list is mandatory" if (scalar @{$listInfo->{item_list}} < 1); - - - my $itemColl = new yui::YItemCollection; - foreach (@{$listInfo->{item_list}}) { - my $item = new yui::YItem ($_, 0); - $itemColl->push($item); - $item->DISOWN(); - if ($listInfo->{default_item} && $listInfo->{default_item} eq $item->label()) { - $item->setSelected(1); - } - } - - return $itemColl; -} - - -#============================================================= - -=head2 ask_fromList - -=head3 INPUT - - $info: HASH, information to be passed to the dialog. - title => dialog title - header => combobox header - default_item => selected item if any - list => item list - default_button => (optional) 1: Select (any other values Cancel) - -=head3 OUTPUT - - undef: if Cancel button has been pressed - selected item: if Select button has been pressed - -=head3 DESCRIPTION - - This function create a dialog with a combobox in which to - choose an item from a given list. - -=cut - -#============================================================= - -sub ask_fromList { - my ($self, $info) = @_; - - die "Missing dialog information" if (!$info); - die "Title is mandatory" if (! exists $info->{title}); - die "Header is mandatory" if (! exists $info->{header}); - die "List is mandatory" if (! exists $info->{list} ); - my $list = $info->{list}; - die "At least one element is mandatory into list" if (scalar(@$list) < 1); - - my $choice = undef; - my $factory = yui::YUI::widgetFactory; - - ## push application title - my $appTitle = yui::YUI::app()->applicationTitle(); - ## set new title to get it in dialog - yui::YUI::app()->setApplicationTitle($info->{title}); - - my $dlg = $factory->createPopupDialog($yui::YDialogNormalColor); - my $layout = $factory->createVBox($dlg); - - my $combo = $factory->createComboBox($layout, $info->{header}, 0); - - my $listInfo; - $listInfo->{default_item} = $info->{default_item} if $info->{default_item}; - $listInfo->{item_list} = $info->{list}; - my $itemColl = $self->arrayListToYItemCollection($listInfo); - $combo->addItems($itemColl); - - my $align = $factory->createRight($layout); - my $hbox = $factory->createHBox($align); - my $selectButton = $factory->createPushButton($hbox, $self->loc->N("Select")); - my $cancelButton = $factory->createPushButton($hbox, $self->loc->N("Cancel")); - - if (exists $info->{default_button} ) { - my $dflBtn = ($info->{default_button} == 1) ? $selectButton : $cancelButton; - $dlg->setDefaultButton($selectButton); - } - - 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 == $selectButton) { - my $item = $combo->selectedItem(); - $choice = $item->label() if ($item); - last; - } - } - } - - destroy $dlg; - - #restore old application title - yui::YUI::app()->setApplicationTitle($appTitle); - - return $choice; -} - -#============================================================= - -=head2 ask_multiple_fromList - -=head3 INPUT - -$info: HASH, information to be passed to the dialog. - title => dialog title - header => combobox header - default_item => selected item if any - list => item list - default_button => (optional) 1: Select (any other values Cancel) - -=head3 LIST - -list is an array of hashes like this - - { - id => unique identifier for this particular item, - text => "descriptive text" - val => reference to the boolean value - } - - -=head3 OUTPUT - - undef: if Cancel button has been pressed - selected items: ArrayRef of the selected ids, if Select button has been pressed - -=head3 DESCRIPTION - -This function create a dialog with variable checkboxes in which to -choose the items from a given list. - -Warning: to use only for a reduced set of items because of no scroll available - -=cut - -#============================================================= - -sub ask_multiple_fromList { - my ($self, $info) = @_; - - die "Missing dialog information" if (!$info); - die "Title is mandatory" if (! exists $info->{title}); - die "Header is mandatory" if (! exists $info->{header}); - die "List is mandatory" if (! exists $info->{list} ); - die "At least one element is mandatory into list" if (scalar(@{$info->{list}}) < 1); - - my $selections = []; - my $factory = yui::YUI::widgetFactory; - - ## push application title - my $appTitle = yui::YUI::app()->applicationTitle(); - ## set new title to get it in dialog - yui::YUI::app()->setApplicationTitle($info->{title}); - - my $dlg = $factory->createPopupDialog($yui::YDialogNormalColor); - my $layout = $factory->createVBox($dlg); - - my @ckbox_array = (); - - for my $item(@{$info->{list}}) - { - my $ckbox = $factory->createCheckBox( - $factory->createLeft($factory->createHBox($layout)), - $item->{text}, - ${$item->{val}} - ); - $ckbox->setNotify(1); - push @ckbox_array, { - id => $item->{id}, - widget => \$ckbox, - }; - $ckbox->DISOWN(); - } - - my $align = $factory->createRight($layout); - my $hbox = $factory->createHBox($align); - my $selectButton = $factory->createPushButton($hbox, $self->loc->N("Select")); - my $cancelButton = $factory->createPushButton($hbox, $self->loc->N("Cancel")); - - if (exists $info->{default_button} ) { - my $dflBtn = ($info->{default_button} == 1) ? $selectButton : $cancelButton; - $dlg->setDefaultButton($selectButton); - } - - 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) { - $selections = undef; - last; - } - elsif ($widget == $selectButton) { - foreach my $ckbox (@ckbox_array) - { - if(${$ckbox->{widget}}->value()) - { - # yui::YUI::ui()->blockEvents(); - push @{$selections}, $ckbox->{id}; - # yui::YUI::ui()->unblockEvents(); - } - } - last; - } - } - } - - destroy $dlg; - - #restore old application title - yui::YUI::app()->setApplicationTitle($appTitle); - - return $selections; -} - -#============================================================= - -=head2 AboutDialog - -=head3 INPUT - - $info: HASH containing optional information needed to get info for dialog. - name => the application name - version => the application version - license => the application license, the short length one (e.g. GPLv2, GPLv3, LGPLv2+, etc) - authors => the string providing the list of authors; it could be html-formatted - description => the string providing a brief description of the application - logo => the string providing the file path for the application logo (high-res image) - icon => the string providing the file path for the application icon (low-res image) - credits => the application credits, they can be html-formatted - information => other extra informations, they can be html-formatted - dialog_mode => 1: classic style dialog, any other as tabbed style dialog - -=head3 DESCRIPTION - - About dialog implementation, this dialog can be used by - modules, to show authors, license, credits, etc. - -=cut - -#============================================================= - -sub AboutDialog { - my ($self, $info) = @_; - - die "Missing dialog information" if (!$info); - - - yui::YUI::widgetFactory; - my $factory = yui::YExternalWidgets::externalWidgetFactory("mga"); - $factory = yui::YMGAWidgetFactory::getYMGAWidgetFactory($factory); - - my $name = (exists $info->{name}) ? $info->{name} : ""; - my $version = (exists $info->{version}) ? $info->{version} : ""; - my $license = (exists $info->{license}) ? $info->{license} : ""; - my $authors = (exists $info->{authors}) ? $info->{authors} : ""; - my $description = (exists $info->{description}) ? $info->{description} : ""; - my $logo = (exists $info->{logo}) ? $info->{logo} : ""; - my $icon = (exists $info->{icon}) ? $info->{icon} : ""; - my $credits = (exists $info->{credits}) ? $info->{credits} : ""; - my $information = (exists $info->{information}) ? $info->{information} : ""; - my $dialog_mode = $yui::YMGAAboutDialog::TABBED; - if (exists $info->{dialog_mode}) { - $dialog_mode = $yui::YMGAAboutDialog::CLASSIC if ($info->{dialog_mode} == 1); - } - - my $dlg = $factory->createAboutDialog($name, $version, $license, - $authors, $description, $logo, - $icon, $credits, $information - ); - - $dlg->show($dialog_mode); - - $dlg = undef; - - return 1; -} - -#============================================================= - -=head2 hashTreeToYItemCollection - -=head3 INPUT - - $treeInfo: HASH reference containing - parent ==> YItem parent (if not root object) - collection ==> YItemCollection (mandatory) - default_item ==> Selected item (if any) - default_item_separator ==> If default item is passed and is a path like string - the separator is needed to match the selected item, using - the full pathname instead leaf (e.g. root/subroot/leaf). - Default separator is also needed if '$treeInfo->{icons} entry is passed - to match the right icon to set (e.g. using the full pathname). - hash_tree ==> HASH reference containing the path tree representation - icons ==> HASH reference containing item icons e.g. - { - root => 'root_icon_pathname', - root/subroot => 'root_subroot_icon_pathname', - .... - } - Do not add it if no icons are wanted. - default_icon ==> icon pathname to a default icon for all the items that are - not into $treeInfo->{icons} or if $treeInfo->{icons} is not - defined. Leave undef if no default icon is wanted - -=head3 DESCRIPTION - - This function add to the given $treeInfo->{collection} new tree items from - the the given $treeInfo->{hash_tree} - -=cut - -#============================================================= - -sub hashTreeToYItemCollection { - my ($self, $treeInfo) = @_; - - die "Collection is mandatory" if !($treeInfo->{collection}); - die "Hash tree is mandatory" if !($treeInfo->{hash_tree}); - - my $treeLine = $treeInfo->{parent}; - my $item; - foreach my $key (sort keys %{$treeInfo->{hash_tree}}) { - if ($treeInfo->{parent}) { - $item = new yui::YTreeItem ($treeLine, $key); - $item->DISOWN(); - } - else { - if ($treeLine) { - if ( $treeLine->label() eq $key) { - $item = $treeLine; - } - else { - $treeInfo->{collection}->push($treeLine); - $item = $treeLine = new yui::YTreeItem ($key); - $item->DISOWN(); - } - } - else { - $item = $treeLine = new yui::YTreeItem ($key); - $item->DISOWN(); - } - } - - # building full path name - my $label = $key; - if (exists $treeInfo->{default_item_separator}) { - my $parent = $item; - while($parent = $parent->parent()) { - $label = $parent->label() . $treeInfo->{default_item_separator} . $label ; - } - } - my $icon = undef; - $icon = $treeInfo->{default_icon} if defined($treeInfo->{default_icon}); - $icon = $treeInfo->{icons}->{$label} if defined($treeInfo->{icons}) && defined($treeInfo->{icons}->{$label}); - - $item->setIconName($icon) if $icon; - - ### select item - if ($treeInfo->{default_item}) { - if ($treeInfo->{default_item} eq $label) { - $item->setSelected(1) ; - $item->setOpen(1); - my $parent = $item; - while($parent = $parent->parent()) { - $parent->setOpen(1); - } - } - } - - if ($treeInfo->{hash_tree}->{$key} && keys %{$treeInfo->{hash_tree}->{$key}}) { - my %tf; - $tf{collection} = $treeInfo->{collection}; - $tf{parent} = $item; - $tf{default_item} = $treeInfo->{default_item} if $treeInfo->{default_item}; - $tf{default_item_separator} = $treeInfo->{default_item_separator} if $treeInfo->{default_item_separator}; - $tf{hash_tree} = $treeInfo->{hash_tree}->{$key}; - $tf{icons} = $treeInfo->{icons}; - $self->hashTreeToYItemCollection(\%tf); - } - else { - if (! $treeInfo->{parent}) { - $treeInfo->{collection}->push($treeLine); - $treeLine = undef; - } - } - } - if (! $treeInfo->{parent}) { - $treeInfo->{collection}->push($treeLine) if $treeLine; - } -} - - -#============================================================= - -=head2 ask_fromTreeList - -=head3 INPUT - - $info: HASH, information to be passed to the dialog. - title => dialog title - header => TreeView header - list => path item list - min_size => minimum dialog size in the libYUI meaning - HASH {width => w, height => h} - default_item => selected item if any - item_separator => item separator default "/" - skip_path => if set item is returned without its original path, - just as a leaf (default use full path) - any_item_selection => allow to select any item, not just leaves (default just leaves) - default_button => (optional) 1: Select (any other values Cancel) - -=head3 OUTPUT - - undef: if Cancel button has been pressed - selected item: if Select button has been pressed - -=head3 DESCRIPTION - - This function create a dialog with a combobox in which to - choose an item from a given list. - -=cut - -#============================================================= - -sub ask_fromTreeList { - my ($self, $info) = @_; - - die "Missing dialog information" if (!$info); - die "Title is mandatory" if (! exists $info->{title}); - die "Header is mandatory" if (! exists $info->{header}); - die "List is mandatory" if (! exists $info->{list} ); - my $list = $info->{list}; - die "At least one element is mandatory into list" if (scalar(@$list) < 1); - - my $choice = undef; - my $factory = yui::YUI::widgetFactory; - - ## push application title - my $appTitle = yui::YUI::app()->applicationTitle(); - ## set new title to get it in dialog - yui::YUI::app()->setApplicationTitle($info->{title}); - my $minWidth = 80; - my $minHeight = 25; - - if (exists $info->{min_size}) { - $minWidth = $info->{min_size}->{width} if $info->{min_size}->{width}; - $minHeight = $info->{min_size}->{height} if $info->{min_size}->{height}; - } - - my $dlg = $factory->createPopupDialog($yui::YDialogNormalColor); - my $minSize = $factory->createMinSize( $dlg, $minWidth, $minHeight ); - my $layout = $factory->createVBox($minSize); - - my $treeWidget = $factory->createTree($layout, $info->{header}); - - my $treeInfo; - $treeInfo->{collection} = new yui::YItemCollection; - $treeInfo->{default_item} = $info->{default_item} if $info->{default_item}; - if ($treeInfo->{default_item} && $info->{item_separator}) { - if (index($treeInfo->{default_item}, $info->{item_separator}) != -1) { - $treeInfo->{default_item_separator} = $info->{item_separator}; - } - } - my $list2Convert; - $list2Convert->{paths} = $info->{list}; - $list2Convert->{separator} = $info->{item_separator} if $info->{item_separator}; - $treeInfo->{hash_tree} = ManaTools::Shared::pathList2hash($list2Convert); - - $self->hashTreeToYItemCollection($treeInfo); - $treeWidget->addItems($treeInfo->{collection}); - - my $align = $factory->createRight($layout); - my $hbox = $factory->createHBox($align); - my $selectButton = $factory->createPushButton($hbox, $self->loc->N("Select")); - my $cancelButton = $factory->createPushButton($hbox, $self->loc->N("Cancel")); - - if (exists $info->{default_button} ) { - my $dflBtn = ($info->{default_button} == 1) ? $selectButton : $cancelButton; - $dlg->setDefaultButton($selectButton); - } - - 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 == $selectButton) { - my $item = $treeWidget->selectedItem(); - my $getChoice = 1; - if (!exists $info->{any_item_selection} || $info->{any_item_selection} != 0) { - if ($item) { - $getChoice = (!$item->hasChildren()); - } - } - if ($info->{skip_path} && $info->{skip_path} != 0) { - $choice = $item->label() if ($item && $getChoice); - } - else { - if ($getChoice) { - my $separator = exists $info->{item_separator} ? $info->{item_separator} : '/'; - if ($item) { - $choice = $item->label(); - my $parent = $item; - while($parent = $parent->parent()) { - $choice = $parent->label() . $separator . $choice ; - } - } - } - } - - last; - } - } - } - - destroy $dlg; - - #restore old application title - yui::YUI::app()->setApplicationTitle($appTitle); - - return $choice; -} - - -#============================================================= - -=head2 select_fromList - -=head3 INPUT - - $info: HASH, information to be passed to the dialog. - title => dialog title - info_label => optional info text - header => column header hash reference{ - text_column => text column header - check_column => - } - list => item list hash reference - containing { - text => item text - selected => 0 ur undefined means unchecked - } - -=head3 OUTPUT - - selection: list of selected items - -=head3 DESCRIPTION - - This function create a dialog cotaining a table with a list of - items to be checked. The list of the checked items is returned. - -=cut - -#============================================================= - -sub select_fromList { - my ($self, $info) = @_; - - die "Missing dialog information" if (!$info); - die "Title is mandatory" if (! exists $info->{title}); - die "Header is mandatory" if (! exists $info->{header}); - die "Header text column is mandatory" if (! $info->{header}->{text_column}); - die "List is mandatory" if (! exists $info->{list} ); - my $list = $info->{list}; - die "At least one element is mandatory into list" if (scalar(@$list) < 1); - - my $selection = []; - - my $mageiaPlugin = "mga"; - my $factory = yui::YUI::widgetFactory; - my $mgaFactory = yui::YExternalWidgets::externalWidgetFactory($mageiaPlugin); - $mgaFactory = yui::YMGAWidgetFactory::getYMGAWidgetFactory($mgaFactory); - - ## push application title - my $appTitle = yui::YUI::app()->applicationTitle(); - ## set new title to get it in dialog - yui::YUI::app()->setApplicationTitle($info->{title}); - - my $dlg = $factory->createPopupDialog($yui::YDialogNormalColor); - my $layout = $factory->createVBox($dlg); - - if ($info->{info_label}) { - $factory->createLabel($layout, $info->{info_label}); - } - - my $yTableHeader = new yui::YTableHeader(); - $yTableHeader->addColumn($info->{header}->{text_column}, $yui::YAlignBegin); - $yTableHeader->addColumn($info->{header}->{check_column} || '', $yui::YAlignBegin); - - ## service list (serviceBox) - my $selectionTable = $mgaFactory->createCBTable( - $layout, - $yTableHeader, - $yui::YCBTableCheckBoxOnLastColumn - ); - $selectionTable->setImmediateMode(1); - $selectionTable->setWeight($yui::YD_HORIZ, 75); - - $selectionTable->startMultipleChanges(); - $selectionTable->deleteAllItems(); - my $itemCollection = new yui::YItemCollection; - ## NOTE do not sort to preserve item indexes - foreach (@{$list}) { - my $text = $_->{text} || die "item text is mandatory"; - - my $item = new yui::YCBTableItem($text); - $item->check( $_->{checked} ); - $itemCollection->push($item); - $item->DISOWN(); - } - $selectionTable->addItems($itemCollection); - $selectionTable->doneMultipleChanges(); - - my $align = $factory->createRight($layout); - my $hbox = $factory->createHBox($align); - $factory->createVSpacing($hbox, 1.0); - my $okButton = $factory->createPushButton($hbox, $self->loc->N("Ok")); - $dlg->setDefaultButton($okButton); - $dlg->recalcLayout(); - - 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 == $okButton) { - last; - } - elsif ($widget == $selectionTable) { - my $wEvent = yui::toYWidgetEvent($event); - if ($wEvent->reason() == $yui::YEvent::ValueChanged) { - my $item = $selectionTable->changedItem(); - if ($item) { - my $index = $item->index(); - $list->[$index]->{checked} = $item->checked(); - } - } - } - } - } - - destroy $dlg; - - #restore old application title - yui::YUI::app()->setApplicationTitle($appTitle); - - foreach (@{$list}) { - push @{$selection}, $_->{text} if $_->{checked}; - } - - return $selection; -} - -no Moose; -__PACKAGE__->meta->make_immutable; - - -1; - diff --git a/lib/AdminPanel/Shared/Hosts.pm b/lib/AdminPanel/Shared/Hosts.pm deleted file mode 100644 index d3b7fc9..0000000 --- a/lib/AdminPanel/Shared/Hosts.pm +++ /dev/null @@ -1,216 +0,0 @@ -# vim: set et ts=4 sw=4: -#***************************************************************************** -# -# Copyright (c) 2013-2015 Matteo Pasotti -# -# 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::Shared::Hosts; - -use Moose; -use diagnostics; -use Config::Hosts; -use Net::DBus; -use utf8; - -# costants by Config::Hosts -my $is_ip = 1; -my $is_host = -1; -my $is_none = 0; - -has 'configHosts' => ( - is => 'rw', - init_arg => undef, - builder => '_initialize' -); - -has 'dbusConnectionParams' => ( - is => 'ro', - isa => 'HashRef', - builder => '_initDBusConnectionParams', -); - -sub _initialize { - my $self = shift(); - $self->configHosts(Config::Hosts->new()); -} - -sub _initDBusConnectionParams { - my $self = shift(); - my %dbusConnParams = ( 'servicePath' => 'org.freedesktop.hostname1', 'objectPath' => '/org/freedesktop/hostname1' ); - return \%dbusConnParams; -} - -=pod - -=head2 _getHosts - -=head3 OUTPUT - - @result: array of hashes; each one of them represent a host definition from the hosts configuration file - - NOTE: the 'hosts' item into each hash is an array: it contains the hostname and -eventually- the aliases - -=head3 DESCRIPTION - -retrieve data from the hosts file (/etc/hosts) using the Config::Hosts module - -=cut - -sub _getHosts { - my $self = shift(); - # $self->configHosts(Config::Hosts->new()); - my $hosts = $self->configHosts->read_hosts(); - my @result = (); - while( my ($key, $value) = each(%{$hosts})){ - if($self->configHosts->determine_ip_or_host($key) == $is_ip){ - my $tmp = {}; - $tmp = $self->configHosts->query_host($key); - $tmp->{'ip'} = $key; - push @result,$tmp; - } - } - return @result; -} - -sub _insertHost { - my $self = shift(); - # remember that the order matters! - my $ip = shift(); - my @host_definitions = @_; - # $self->configHosts = Config::Hosts->new(); - return $self->configHosts->insert_host(ip => $ip, hosts => @host_definitions); -} - -sub _dropHost { - my $self = shift(); - my $host_ip = shift(); - return $self->configHosts->delete_host($host_ip); -} - -sub _modifyHost { - my $self = shift(); - my $host_ip = shift(); - my @host_definitions = @_; - return $self->configHosts->update_host($host_ip, hosts => @host_definitions); -} - -sub _writeHosts { - my $self = shift(); - return $self->configHosts->write_hosts(); -} - -sub _dbus_connection { - my $self = shift(); - my %params = %{$self->dbusConnectionParams()}; - my $bus = Net::DBus->system; - my $service = $bus->get_service($params{'servicePath'}); - my $object = $service->get_object($params{'objectPath'}); - return $object; -} - -sub _dbus_inquiry { - my $self = shift(); - my $required_field = shift(); - my $object = $self->_dbus_connection(); - my %params = %{$self->dbusConnectionParams()}; - my $properties = $object->GetAll($params{'servicePath'}); - return $properties->{$required_field} if(defined($properties->{$required_field})); - return 0; -} - -sub _dbus_setup { - my $self = shift(); - my $attribute = shift(); - my $value = shift(); - my $object = $self->_dbus_connection(); - if($attribute eq "Hostname") - { - $object->SetHostname($value,1); - } - elsif($attribute eq "PrettyHostname") - { - $object->SetPrettyHostname($value,1); - } - elsif($attribute eq "StaticHostname") - { - $object->SetStaticHostname($value,1); - } - elsif($attribute eq "Chassis") - { - $object->SetChassis($value,1); - } - elsif($attribute eq "IconName") - { - $object->SetIconName($value,1); - } -} - -sub _getLocalHostName { - my $self = shift(); - return $self->_dbus_inquiry('Hostname'); -} - -sub _getLocalPrettyHostName { - my $self = shift(); - return $self->_dbus_inquiry('PrettyHostname'); -} - -sub _getLocalStaticHostName { - my $self = shift(); - return $self->_dbus_inquiry('StaticHostname'); -} - -sub _getLocalChassis { - my $self = shift(); - return $self->_dbus_inquiry('Chassis'); -} - -sub _getLocalIconName { - my $self = shift(); - return $self->_dbus_inquiry('IconName'); -} - -sub _setLocalHostName { - my $self = shift(); - my $hostname = shift(); - $self->_dbus_setup('Hostname',$hostname); -} - -sub _setLocalPrettyHostName { - my $self = shift(); - my $value = shift(); - $self->_dbus_setup('PrettyHostname',$value); -} - -sub _setLocalStaticHostName { - my $self = shift(); - my $value = shift(); - $self->_dbus_setup('StaticHostname',$value); -} - -sub _setLocalIconName { - my $self = shift(); - my $value = shift(); - $self->_dbus_setup('IconName',$value); -} - -sub _setLocalChassis { - my $self = shift(); - my $value = shift(); - $self->_dbus_setup('Chassis',$value); -} - -1; diff --git a/lib/AdminPanel/Shared/JournalCtl.pm b/lib/AdminPanel/Shared/JournalCtl.pm deleted file mode 100644 index 1194538..0000000 --- a/lib/AdminPanel/Shared/JournalCtl.pm +++ /dev/null @@ -1,141 +0,0 @@ -# vim: set et ts=4 sw=4: -package ManaTools::Shared::JournalCtl; - -#============================================================= -*-perl-*- - -=head1 NAME - -ManaTools::Shared::JournalCtl - journalctl perl wrapper - -=head1 SYNOPSIS - - my $log = ManaTools::Shared::JournalCtl->new(); - my @log_content = $log->getLog(); - -=head1 DESCRIPTION - -This module wraps journalctl allowing some running options and provides the -output log content. - -=head1 SUPPORT - -You can find documentation for this module with the perldoc command: - -perldoc ManaTools::Shared::JournalCtl - - -=head1 AUTHOR - -Angelo Naselli - -=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 METHODS - -=cut - -use Moose; - -use diagnostics; - - -has 'this_boot' => ( - is => 'rw', - isa => 'Int', - default => 0, -); - -has 'since' => ( - is => 'rw', - isa => 'Str', - default => "", -); - -has 'until' => ( - is => 'rw', - isa => 'Str', - default => "", -); - -has 'priority' => ( - is => 'rw', - isa => 'Str', - default => "", -); - -has 'unit' => ( - is => 'rw', - isa => 'Str', - default => "", -); - -#============================================================= - -=head2 getLog - -=head3 INPUT - -Input_Parameter: in_par_description - -=head3 OUTPUT - -\@content: ARRAYREF containing the log content. - -=head3 DESCRIPTION - -This methods gets the log using the provided options - -=cut - -#============================================================= - -sub getLog { - my $self = shift; - - my $params = "--no-pager -q"; - if ($self->this_boot == 1) { - $params .= " -b"; - } - if ($self->since ne "") { - $params .= " --since=" . '"' . $self->since . '"'; - } - if ($self->until ne "") { - $params .= " --until=" . '"' . $self->until .'"'; - } - if ($self->unit ne "") { - $params .= " --unit=" . $self->unit; - } - if ($self->priority ne "") { - $params .= " --priority=" . $self->priority; - } - - $ENV{'PATH'} = '/usr/sbin:/usr/bin'; - my $jctl = "/usr/bin/journalctl " . $params; - - # TODO remove or add to log - print " Running " . $jctl . "\n"; - my @content = `$jctl`; - - return \@content; -} - -no Moose; -__PACKAGE__->meta->make_immutable; - - -1; diff --git a/lib/AdminPanel/Shared/Locales.pm b/lib/AdminPanel/Shared/Locales.pm deleted file mode 100644 index ec54614..0000000 --- a/lib/AdminPanel/Shared/Locales.pm +++ /dev/null @@ -1,280 +0,0 @@ -# vim: set et ts=4 sw=4: -package ManaTools::Shared::Locales; -#============================================================= -*-perl-*- - -=head1 NAME - -ManaTools::Shared::Locales - Class to manage locales - -=head1 SYNOPSIS - -use ManaTools::Shared::Locales; - -my $obj = ManaTools::Shared::Locales->new(domain_name => 'this_domain'); - -print $obj->N("test string %d", 1) . "\n"; - -=head1 DESCRIPTION - -This class wraps Locale::gettext to manage localization - - -=head1 SUPPORT - -You can find documentation for this module with the perldoc command: - -perldoc ManaTools::Shared::Locales - -=head1 SEE ALSO - -Locale::gettext Text::Iconv and gettext - -=head1 AUTHOR - -Angelo Naselli - -=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 utf8; -use Locale::gettext; -use Text::Iconv; - - -#============================================================= - -=head2 new - -=head3 INPUT - - hash ref containing - domain_name: gettext domain name (default mpan) - dir_name: gettext optional catalog directory (default undef) - codeset: gettext codeset (default UTF8) - -=head3 DESCRIPTION - - new is inherited from Moose, to create a Locales object - -=cut - -#============================================================= - -has 'domain_name' => ( - is => 'rw', - default => 'mpan', -); - -has 'dir_name' => ( - is => 'rw', - default => undef, -); - -has 'codeset' => ( - is => 'rw', - default => 'UTF8', -); - -has 'domain' => ( - is => 'rw', - init_arg => undef, -); - -#============================================================= - -=head2 BUILD - -=head3 INPUT - - $self: this object - -=head3 DESCRIPTION - - The BUILD method is called after a Moose object is created. - This method initilaizes gettext domain. - -=cut - -#============================================================= -sub BUILD { - my $self = shift; - - if ($^V ge v5.20.0) { - require POSIX; - POSIX::setlocale (POSIX::LC_ALL (), ''); - } - - $self->domain(Locale::gettext->domain_raw($self->domain_name)); - $self->domain->dir($self->dir_name) if $self->dir_name; - $self->domain->codeset($self->codeset); -} - - -#============================================================= - -=head2 P - -=head3 INPUT - - $self : this object - $s_singular: msg id singular - $s_plural: msg id plural - $nb: value for plural - -=head3 OUTPUT - - locale string - -=head3 DESCRIPTION - - returns the given string localized (see dngettext) - -=cut - -#============================================================= -sub P { - my ($self, $s_singular, $s_plural, $nb, @para) = @_; - - sprintf($self->domain->nget($s_singular, $s_plural, $nb), @para); -} - -#============================================================= - -=head2 N - -=head3 INPUT - - $self : this object - $s: msg id - -=head3 OUTPUT - - locale string - -=head3 DESCRIPTION - - returns the given string localized (see dgettext) - -=cut - -#============================================================= -sub N { - my ($self, $s, @para) = @_; - - sprintf($self->domain->get($s), @para); -} - -#============================================================= - -=head2 N_ - -=head3 INPUT - - $self : this object - $s: msg id - -=head3 OUTPUT - - msg id - -=head3 DESCRIPTION - - returns the given string - -=cut - -#============================================================= -sub N_ { - my $self = shift; - - $_[0]; -} - - -#============================================================= - -=head2 from_utf8 - -=head3 INPUT - - $self: this object - $s: string to be converted - -=head3 OUTPUT\ - - $converted: converted string - -=head3 DESCRIPTION - - convert from utf-8 to current locale - -=cut - -#============================================================= -sub from_utf8 { - my ($self, $s) = @_; - - my $converter = Text::Iconv->new("utf-8", undef); - my $converted = $converter->convert($s); - - return $converted; -} - - -#============================================================= - -=head2 to_utf8 - -=head3 INPUT - - $self: this object - $s: string to be converted - -=head3 OUTPUT\ - - $converted: converted string - -=head3 DESCRIPTION - - convert to utf-8 from current locale - -=cut - -#============================================================= -sub to_utf8 { - my ($self, $s) = @_; - - my $converter = Text::Iconv->new(undef, "utf-8"); - my $converted = $converter->convert($s); - - return $converted; -} - - - -no Moose; -__PACKAGE__->meta->make_immutable; - - -1; diff --git a/lib/AdminPanel/Shared/Proxy.pm b/lib/AdminPanel/Shared/Proxy.pm deleted file mode 100644 index 6accbb7..0000000 --- a/lib/AdminPanel/Shared/Proxy.pm +++ /dev/null @@ -1,36 +0,0 @@ -# vim: set et ts=4 sw=4: -#***************************************************************************** -# -# Copyright (c) 2013-2015 Matteo Pasotti -# -# 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::Shared::Proxy; - -use Moose; -use diagnostics; -use utf8; - -has 'network' => ( - is => 'rw', - init_arg => undef, - builder => '_initialize' -); - -sub _initialize { - my $self = shift(); -} - -1; diff --git a/lib/AdminPanel/Shared/RunProgram.pm b/lib/AdminPanel/Shared/RunProgram.pm deleted file mode 100644 index 042f559..0000000 --- a/lib/AdminPanel/Shared/RunProgram.pm +++ /dev/null @@ -1,352 +0,0 @@ -package ManaTools::Shared::RunProgram; - -use strict; -use MDK::Common; -use Sys::Syslog; -use MDK::Common::File qw(cat_); - -use Exporter; -our @ISA = qw(Exporter); -our @EXPORT_OK = qw( - set_default_timeout - run_or_die - rooted_or_die - get_stdout - get_stdout_raw - rooted_get_stdout - run - raw - rooted -); - -=head1 SYNOPSYS - -B enables to: - -=over 4 - -=item * run programs in foreground or in background, - -=item * to retrieve their stdout or stderr - -=item * ... - -=back - -Most functions exits in a normal form & a rooted one. e.g.: - -=over 4 - -=item * C & C - -=item * C & C - -=back - -Most functions exits in a normal form & one that die. e.g.: - -=over 4 - -=item * C & C - -=item * C & C - -=back - -=head1 Functions - -=over - -=cut - -1; - -my $default_timeout = 10 * 60; - -=item set_default_timeout($seconds) - -Alters defaults timeout (eg for harddrake service) - -=cut - -sub set_default_timeout { - my ($seconds) = @_; - $default_timeout = $seconds; -} - -=item run_or_die($name, @args) - -Runs $name with @args parameterXs. Dies if it exit code is not 0. - -=cut - -sub run_or_die { - my ($name, @args) = @_; - run($name, @args) or die "$name failed\n"; -} - -=item rooted_or_die($root, $name, @args) - -Similar to run_or_die() but runs in chroot in $root - -=cut - -sub rooted_or_die { - my ($root, $name, @args) = @_; - rooted($root, $name, @args) or die "$name failed\n"; -} - -=item get_stdout($name, @args) - -Similar to run_or_die() but return stdout of program: - -=over 4 - -=item * a list of lines in list context - -=item * a string of concatenated lines in scalar context - -=back - -=cut - -sub get_stdout { - my ($name, @args) = @_; - my @r; - run($name, '>', \@r, @args) or return; - wantarray() ? @r : join('', @r); -} - -=item get_stdout_raw($options, $name, @args) - -Similar to get_stdout() but allow to pass options to raw() - -=cut - -sub get_stdout_raw { - my ($options, $name, @args) = @_; - my @r; - raw($options, $name, '>', \@r, @args) or return; - wantarray() ? @r : join('', @r); -} - -=item rooted_get_stdout($root, $name, @args) - -Similar to get_stdout() but runs in chroot in $root - -=cut - -sub rooted_get_stdout { - my ($root, $name, @args) = @_; - my @r; - rooted($root, $name, '>', \@r, @args) or return; - wantarray() ? @r : join('', @r); -} - -=item run($name, @args) - -Runs $name with @args parameters. - -=cut - -sub run { - raw({}, @_); -} - -=item rooted($root, $name, @args) - -Similar to run() but runs in chroot in $root - -=cut - -sub rooted { - my ($root, $name, @args) = @_; - raw({ root => $root }, $name, @args); -} - -=item raw($options, $name, @args) - -The function used by all the other, making every combination possible. -Runs $name with @args parameters. $options is a hash ref that can contains: - -=over 4 - -=item * B: $name will be chrooted in $root prior to run - -=item * B: $name will be run as $ENV{USERHELPER_UID} or with the UID of parent process. Implies I - -=item * B: parameters will be hidden in logs (b/c eg there's a password) - -=item * B: $name will be run in the background. Default is foreground - -=item * B: $name will be run in a different default directory - -=item * B: contains a getpwnam(3) struct ; $name will be with droped privileges ; -make sure environment is set right and keep a copy of the X11 cookie - -=item * B: execution of $name will be aborted after C seconds - -=back - -eg: - -=over 4 - -=item * C<< ManaTools::Shared::RunProgram::raw({ root => $::prefix, sensitive_arguments => 1 }, "echo -e $user->{password} | cryptsetup luksFormat $device"); >> - -=item * C<< ManaTools::Shared::RunProgram::raw({ detach => 1 }, '/etc/rc.d/init.d/dm', '>', '/dev/null', '2>', '/dev/null', 'restart'); >> - -=back - -=cut - -sub raw { - my ($options, $name, @args) = @_; - my $root = $options->{root} || ''; - my $real_name = ref($name) ? $name->[0] : $name; - - my ($stdout_raw, $stdout_mode, $stderr_raw, $stderr_mode); - ($stdout_mode, $stdout_raw, @args) = @args if $args[0] =~ /^>>?$/; - ($stderr_mode, $stderr_raw, @args) = @args if $args[0] =~ /^2>>?$/; - - my $home; - if ($options->{as_user}) { - my $uid; - $uid = $ENV{USERHELPER_UID} && getpwuid($ENV{USERHELPER_UID}); - $uid ||= _get_parent_uid(); - $options->{setuid} = getpwnam($uid) if $uid; - my ($full_user) = grep { $_->[2] eq $uid } list_passwd(); - $home = $full_user->[7] if $full_user; - } - local $ENV{HOME} = $home if $home; - - my $args = $options->{sensitive_arguments} ? '' : join(' ', @args); - Sys::Syslog::syslog('info|local1', "running: $real_name $args" . ($root ? " with root $root" : "")); - - return if $root && $<; - - $root ? ($root .= '/') : ($root = ''); - - my $tmpdir = sub { - my $dir = $< != 0 ? "$ENV{HOME}/tmp" : -d '/root' ? '/root/tmp' : '/tmp'; - -d $dir or mkdir($dir, 0700); - $dir; - }; - my $stdout = $stdout_raw && (ref($stdout_raw) ? $tmpdir->() . "/.drakx-stdout.$$" : "$root$stdout_raw"); - my $stderr = $stderr_raw && (ref($stderr_raw) ? $tmpdir->() . "/.drakx-stderr.$$" : "$root$stderr_raw"); - - #- checking if binary exist to avoid clobbering stdout file - my $rname = $real_name =~ /(.*?)[\s\|]/ ? $1 : $real_name; - if (! ($rname =~ m!^/! - ? -x "$root$rname" || $root && -l "$root$rname" #- handle non-relative symlink which can be broken when non-rooted - : whereis_binary($rname, $root))) { - Sys::Syslog::syslog('warning', "program not found: $real_name"); - - return; - } - - if (my $pid = fork()) { - if ($options->{detach}) { - $pid; - } else { - my $ok; - add2hash_($options, { timeout => $default_timeout }); - eval { - local $SIG{ALRM} = sub { die "ALARM" }; - my $remaining = $options->{timeout} && $options->{timeout} ne 'never' && alarm($options->{timeout}); - waitpid $pid, 0; - $ok = $? == -1 || ($? >> 8) == 0; - alarm $remaining; - }; - if ($@) { - Sys::Syslog::syslog('warning', "ERROR: killing runaway process (process=$real_name, pid=$pid, args=@args, error=$@)"); - kill 9, $pid; - return; - } - - if ($stdout_raw && ref($stdout_raw)) { - if (ref($stdout_raw) eq 'ARRAY') { - @$stdout_raw = cat_($stdout); - } else { - $$stdout_raw = cat_($stdout); - } - unlink $stdout; - } - if ($stderr_raw && ref($stderr_raw)) { - if (ref($stderr_raw) eq 'ARRAY') { - @$stderr_raw = cat_($stderr); - } else { - $$stderr_raw = cat_($stderr); - } - unlink $stderr; - } - $ok; - } - } else { - if ($options->{setuid}) { - require POSIX; - my ($logname, $home) = (getpwuid($options->{setuid}))[0,7]; - $ENV{LOGNAME} = $logname if $logname; - - # if we were root and are going to drop privilege, keep a copy of the X11 cookie: - if (!$> && $home) { - # FIXME: it would be better to remove this but most callers are using 'detach => 1'... - my $xauth = chomp_(`mktemp $home/.Xauthority.XXXXX`); - system('cp', '-a', $ENV{XAUTHORITY}, $xauth); - system('chown', $logname, $xauth); - $ENV{XAUTHORITY} = $xauth; - } - - # drop privileges: - POSIX::setuid($options->{setuid}); - } - - sub _die_exit { - Sys::Syslog::syslog('warning', $_[0]); - POSIX::_exit(128); - } - if ($stderr && $stderr eq 'STDERR') { - } elsif ($stderr) { - $stderr_mode =~ s/2//; - open STDERR, "$stderr_mode $stderr" or _die_exit("ManaTools::Shared::RunProgram cannot output in $stderr (mode `$stderr_mode')"); - } elsif ($::isInstall) { - open STDERR, ">> /tmp/ddebug.log" or open STDOUT, ">> /dev/tty7" or _die_exit("ManaTools::Shared::RunProgram cannot log, give me access to /tmp/ddebug.log"); - } - if ($stdout && $stdout eq 'STDOUT') { - } elsif ($stdout) { - open STDOUT, "$stdout_mode $stdout" or _die_exit("ManaTools::Shared::RunProgram cannot output in $stdout (mode `$stdout_mode')"); - } elsif ($::isInstall) { - open STDOUT, ">> /tmp/ddebug.log" or open STDOUT, ">> /dev/tty7" or _die_exit("ManaTools::Shared::RunProgram cannot log, give me access to /tmp/ddebug.log"); - } - - $root and chroot $root; - chdir($options->{chdir} || "/"); - - my $ok = ref $name ? do { - exec { $name->[0] } $name->[1], @args; - } : do { - exec $name, @args; - }; - if (!$ok) { - _die_exit("exec of $real_name failed: $!"); - } - } - -} - -=item get_parent_uid() - -Returns UID of the parent process. - -=cut - -sub _get_parent_uid() { - cat_('/proc/' . getppid() . '/status') =~ /Uid:\s*(\d+)/ ? $1 : undef; -} - - - -#- Local Variables: -#- mode:cperl -#- tab-width:8 -#- End: diff --git a/lib/AdminPanel/Shared/Services.pm b/lib/AdminPanel/Shared/Services.pm deleted file mode 100644 index abef8c3..0000000 --- a/lib/AdminPanel/Shared/Services.pm +++ /dev/null @@ -1,955 +0,0 @@ -# vim: set et ts=4 sw=4: -package ManaTools::Shared::Services; -#============================================================= -*-perl-*- - -=head1 NAME - -ManaTools::Shared::Services - shares the API to manage services - -=head1 SYNOPSIS - -use ManaTools::Shared::Services; - -my $serv = ManaTools::Shared::Services->new(); - -my ($l, $on_services) = $serv->services(); - -=head1 DESCRIPTION - - This module aims to share all the API to manage system services, - to be used from GUI applications or console. - - From the original code drakx services. - -=head1 SUPPORT - -You can find documentation for this module with the perldoc command: - -perldoc ManaTools::Shared::Services - -=head1 SEE ALSO - -ManaTools::Shared - -=head1 AUTHOR - -Angelo Naselli - -=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 FUNCTIONS - -=cut - - -use Moose; - -use Sys::Syslog; -use Net::DBus; -use Net::DBus::Annotation qw(:auth); -use File::Basename; - -use ManaTools::Shared::Locales; -use MDK::Common::Func qw(find); -use MDK::Common::File; -use MDK::Common::DataStructure qw(member); -use ManaTools::Shared::RunProgram qw(rooted); - -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') ); - # TODO if we want to give the opportunity to test locally add dir_name => 'path' -} - - -has 'dbus_systemd1_service' => ( - is => 'rw', - init_arg => undef, - lazy => 1, - builder => '_dbusServiceInitialize' -); - -sub _dbusServiceInitialize { - my $self = shift(); - - my $bus = Net::DBus->system; - $self->dbus_systemd1_service($bus->get_service("org.freedesktop.systemd1")); -} - - -has 'dbus_systemd1_object' => ( - is => 'rw', - init_arg => undef, - lazy => 1, - builder => '_dbusObjectInitialize' -); - -sub _dbusObjectInitialize { - my $self = shift(); - - $self->dbus_systemd1_object($self->dbus_systemd1_service->get_object("/org/freedesktop/systemd1")); -} - - -has 'service_info' => ( - is => 'rw', - traits => ['Hash'], - isa => 'HashRef', - handles => { - set_service_info => 'set', - get_service_info => 'get', - service_info_pairs => 'kv', - }, - init_arg => undef, - lazy => 1, - builder => '_serviceInfoInitialization' -); - -sub _serviceInfoInitialization { - my $self = shift(); - - my %services = (); - if ($self->_running_systemd()) { - my $object = $self->dbus_systemd1_object; - my $properties = $object->ListUnits(); - - foreach my $s (@{$properties}) { - my $name = $s->[0]; - if (index($name, ".service") != -1) { - my $st = eval{$object->GetUnitFileState($name)} if $name !~ /.*\@.*$/g; - $name =~ s|.service||; - if (!$st) { - if ($name !~ /.*\@$/g && - (-e "/usr/lib/systemd/system/$name.service" or -e "/etc/rc.d/init.d/$name") && - ! -l "/usr/lib/systemd/system/$name.service") { - $st = 'enabled'; - } - } - if ($st && $st ne 'static') { - $services{$name} = { - 'name' => $s->[0], - 'description' => $s->[1], - 'load_state' => $s->[2], - 'active_state' => $s->[3], - 'sub_state' => $s->[4], - 'unit_path' => $s->[6], - 'enabled' => $st eq 'enabled', - }; - } - } - } - - my $unit_files = $object->ListUnitFiles(); - foreach my $s (@{$unit_files}) { - my $name = $s->[0]; - my $st = $s->[1]; - if (index($name, ".service") != -1) { - $name = File::Basename::basename($name, ".service"); - if (!$services{$name} && - $name !~ /.*\@$/g && - (-e $s->[0] or -e "/etc/rc.d/init.d/$name") && - ! -l $s->[0] && ($st eq "disabled" || $st eq "enabled")) { - my $wantedby = $self->_WantedBy($s->[0]); - if ($wantedby) { - my $descr = $self->getUnitProperty($name, 'Description'); - - $services{$name} = { - 'name' => $name, - 'description' => $descr, - 'enabled' => $st eq "enabled", - }; - } - } - } - } - } - - return \%services; -} - -#============================================================= - -=head2 description - -=head3 INPUT - -name: Service Name - -=head3 OUTPUT - -Description: Service description - -=head3 DESCRIPTION - -THis function return the description for the given service - -=cut - -#============================================================= -sub description { - my ($self, $name) = @_; - - my %services = ( -acpid => $self->loc->N_("Listen and dispatch ACPI events from the kernel"), -alsa => $self->loc->N_("Launch the ALSA (Advanced Linux Sound Architecture) sound system"), -anacron => $self->loc->N_("Anacron is a periodic command scheduler."), -apmd => $self->loc->N_("apmd is used for monitoring battery status and logging it via syslog. -It can also be used for shutting down the machine when the battery is low."), -atd => $self->loc->N_("Runs commands scheduled by the at command at the time specified when -at was run, and runs batch commands when the load average is low enough."), -'avahi-deamon' => $self->loc->N_("Avahi is a ZeroConf daemon which implements an mDNS stack"), -chronyd => $self->loc->N_("An NTP client/server"), -cpufreq => $self->loc->N_("Set CPU frequency settings"), -crond => $self->loc->N_("cron is a standard UNIX program that runs user-specified programs -at periodic scheduled times. vixie cron adds a number of features to the basic -UNIX cron, including better security and more powerful configuration options."), -cups => $self->loc->N_("Common UNIX Printing System (CUPS) is an advanced printer spooling system"), -dm => $self->loc->N_("Launches the graphical display manager"), -fam => $self->loc->N_("FAM is a file monitoring daemon. It is used to get reports when files change. -It is used by GNOME and KDE"), -g15daemon => $self->loc->N_("G15Daemon allows users access to all extra keys by decoding them and -pushing them back into the kernel via the linux UINPUT driver. This driver must be loaded -before g15daemon can be used for keyboard access. The G15 LCD is also supported. By default, -with no other clients active, g15daemon will display a clock. Client applications and -scripts can access the LCD via a simple API."), -gpm => $self->loc->N_("GPM adds mouse support to text-based Linux applications such the -Midnight Commander. It also allows mouse-based console cut-and-paste operations, -and includes support for pop-up menus on the console."), -haldaemon => $self->loc->N_("HAL is a daemon that collects and maintains information about hardware"), -harddrake => $self->loc->N_("HardDrake runs a hardware probe, and optionally configures -new/changed hardware."), -httpd => $self->loc->N_("Apache is a World Wide Web server. It is used to serve HTML files and CGI."), -inet => $self->loc->N_("The internet superserver daemon (commonly called inetd) starts a -variety of other internet services as needed. It is responsible for starting -many services, including telnet, ftp, rsh, and rlogin. Disabling inetd disables -all of the services it is responsible for."), -ip6tables => $self->loc->N_("Automates a packet filtering firewall with ip6tables"), -iptables => $self->loc->N_("Automates a packet filtering firewall with iptables"), -irqbalance => $self->loc->N_("Evenly distributes IRQ load across multiple CPUs for enhanced performance"), -keytable => $self->loc->N_("This package loads the selected keyboard map as set in -/etc/sysconfig/keyboard. This can be selected using the kbdconfig utility. -You should leave this enabled for most machines."), -kheader => $self->loc->N_("Automatic regeneration of kernel header in /boot for -/usr/include/linux/{autoconf,version}.h"), -kudzu => $self->loc->N_("Automatic detection and configuration of hardware at boot."), -'laptop-mode' => $self->loc->N_("Tweaks system behavior to extend battery life"), -linuxconf => $self->loc->N_("Linuxconf will sometimes arrange to perform various tasks -at boot-time to maintain the system configuration."), -lpd => $self->loc->N_("lpd is the print daemon required for lpr to work properly. It is -basically a server that arbitrates print jobs to printer(s)."), -lvs => $self->loc->N_("Linux Virtual Server, used to build a high-performance and highly -available server."), -mandi => $self->loc->N_("Monitors the network (Interactive Firewall and wireless"), -mdadm => $self->loc->N_("Software RAID monitoring and management"), -messagebus => $self->loc->N_("DBUS is a daemon which broadcasts notifications of system events and other messages"), -msec => $self->loc->N_("Enables MSEC security policy on system startup"), -named => $self->loc->N_("named (BIND) is a Domain Name Server (DNS) that is used to resolve host names to IP addresses."), -netconsole => $self->loc->N_("Initializes network console logging"), -netfs => $self->loc->N_("Mounts and unmounts all Network File System (NFS), SMB (Lan -Manager/Windows), and NCP (NetWare) mount points."), -network => $self->loc->N_("Activates/Deactivates all network interfaces configured to start -at boot time."), -'network-auth' => $self->loc->N_("Requires network to be up if enabled"), -'network-up' => $self->loc->N_("Wait for the hotplugged network to be up"), -nfs => $self->loc->N_("NFS is a popular protocol for file sharing across TCP/IP networks. -This service provides NFS server functionality, which is configured via the -/etc/exports file."), -nfslock => $self->loc->N_("NFS is a popular protocol for file sharing across TCP/IP -networks. This service provides NFS file locking functionality."), -ntpd => $self->loc->N_("Synchronizes system time using the Network Time Protocol (NTP)"), -numlock => $self->loc->N_("Automatically switch on numlock key locker under console -and Xorg at boot."), -oki4daemon => $self->loc->N_("Support the OKI 4w and compatible winprinters."), -partmon => $self->loc->N_("Checks if a partition is close to full up"), -pcmcia => $self->loc->N_("PCMCIA support is usually to support things like ethernet and -modems in laptops. It will not get started unless configured so it is safe to have -it installed on machines that do not need it."), -portmap => $self->loc->N_("The portmapper manages RPC connections, which are used by -protocols such as NFS and NIS. The portmap server must be running on machines -which act as servers for protocols which make use of the RPC mechanism."), -portreserve => $self->loc->N_("Reserves some TCP ports"), -postfix => $self->loc->N_("Postfix is a Mail Transport Agent, which is the program that moves mail from one machine to another."), -random => $self->loc->N_("Saves and restores system entropy pool for higher quality random -number generation."), -rawdevices => $self->loc->N_("Assign raw devices to block devices (such as hard disk drive -partitions), for the use of applications such as Oracle or DVD players"), -resolvconf => $self->loc->N_("Nameserver information manager"), -routed => $self->loc->N_("The routed daemon allows for automatic IP router table updated via -the RIP protocol. While RIP is widely used on small networks, more complex -routing protocols are needed for complex networks."), -rstatd => $self->loc->N_("The rstat protocol allows users on a network to retrieve -performance metrics for any machine on that network."), -rsyslog => $self->loc->N_("Syslog is the facility by which many daemons use to log messages to various system log files. It is a good idea to always run rsyslog."), -rusersd => $self->loc->N_("The rusers protocol allows users on a network to identify who is -logged in on other responding machines."), -rwhod => $self->loc->N_("The rwho protocol lets remote users get a list of all of the users -logged into a machine running the rwho daemon (similar to finger)."), -saned => $self->loc->N_("SANE (Scanner Access Now Easy) enables to access scanners, video cameras, ..."), -shorewall => $self->loc->N_("Packet filtering firewall"), -smb => $self->loc->N_("The SMB/CIFS protocol enables to share access to files & printers and also integrates with a Windows Server domain"), -sound => $self->loc->N_("Launch the sound system on your machine"), -'speech-dispatcherd' => $self->loc->N_("layer for speech analysis"), -sshd => $self->loc->N_("Secure Shell is a network protocol that allows data to be exchanged over a secure channel between two computers"), -syslog => $self->loc->N_("Syslog is the facility by which many daemons use to log messages -to various system log files. It is a good idea to always run syslog."), -'udev-post' => $self->loc->N_("Moves the generated persistent udev rules to /etc/udev/rules.d"), -usb => $self->loc->N_("Load the drivers for your usb devices."), -vnStat => $self->loc->N_("A lightweight network traffic monitor"), -xfs => $self->loc->N_("Starts the X Font Server."), -xinetd => $self->loc->N_("Starts other deamons on demand."), - ); - - my $s = $services{$name}; - if ($s) { - $s = $self->loc->N($s); - } - elsif ($self->get_service_info($name)) { - $s = $self->get_service_info($name)->{description}; - } - else { - my $file = "/usr/lib/systemd/system/$name.service"; - if (-e $file) { - $s = MDK::Common::File::cat_($file); - $s = $s =~ /^Description=(.*)/mg ? $1 : ''; - } else { - $file = MDK::Common::Func::find { -e $_ } map { "$_/$name" } '/etc/rc.d/init.d', '/etc/init.d', '/etc/xinetd.d'; - $s = MDK::Common::File::cat_($file); - $s =~ s/\\\s*\n#\s*//mg; - $s = - $s =~ /^#\s+(?:Short-)?[dD]escription:\s+(.*?)^(?:[^#]|# {0,2}\S)/sm ? $1 : - $s =~ /^#\s*(.*?)^[^#]/sm ? $1 : ''; - - $s =~ s/#\s*//mg; - } - } - $s =~ s/\n/ /gm; $s =~ s/\s+$//; - $s; -} - - -#============================================================= - -=head2 set_service - -=head3 INPUT - - $service: Service name - $enable: enable/disable service - -=head3 DESCRIPTION - - This function enable/disable at boot the given service - -=cut - -#============================================================= -sub set_service { - my ($self, $service, $enable) = @_; - - my @xinetd_services = map { $_->[0] } $self->xinetd_services(); - - if (MDK::Common::DataStructure::member($service, @xinetd_services)) { - $ENV{PATH} = "/usr/bin:/usr/sbin"; - ManaTools::Shared::RunProgram::rooted("", "/usr/sbin/chkconfig", $enable ? "--add" : "--del", $service); - } elsif ($self->_running_systemd() || $self->_has_systemd()) { - $service = $service . ".service"; - my $dbus_object = $self->dbus_systemd1_object; - if ($enable) { - $dbus_object->EnableUnitFiles(dbus_auth_interactive, [$service], 0, 1); - } - else { - $dbus_object->DisableUnitFiles(dbus_auth_interactive, [$service], 0); - } - # reload local cache - $self->_systemd_services(1); - } else { - my $script = "/etc/rc.d/init.d/$service"; - $ENV{PATH} = "/usr/bin:/usr/sbin"; - ManaTools::Shared::RunProgram::rooted("", "/usr/sbin/chkconfig", $enable ? "--add" : "--del", $service); - #- FIXME: handle services with no chkconfig line and with no Default-Start levels in LSB header - if ($enable && MDK::Common::File::cat_("$script") =~ /^#\s+chkconfig:\s+-/m) { - $ENV{PATH} = "/usr/bin:/usr/sbin"; - ManaTools::Shared::RunProgram::rooted("", "/usr/sbin/chkconfig", "--level", "35", $service, "on"); - } - } -} - -sub _run_action { - my ($self, $service, $action) = @_; - if ($self->_running_systemd()) { - my $object = $self->dbus_systemd1_object; - if ($action eq 'start') { - $object->StartUnit(dbus_auth_interactive, "$service.service", 'fail'); - } - elsif ($action eq 'stop') { - $object->StopUnit(dbus_auth_interactive, "$service.service", 'fail'); - } - else { - $object->RestartUnit(dbus_auth_interactive, "$service.service", 'fail'); - } - # reload local cache - $self->_systemd_services(1); - } else { - $ENV{PATH} = "/usr/bin:/usr/sbin:/etc/rc.d/init.d/"; - ManaTools::Shared::RunProgram::rooted("", "/etc/rc.d/init.d/$service", $action); - } -} - -sub _running_systemd { - my $self = shift; - - $ENV{PATH} = "/usr/bin:/usr/sbin"; - ManaTools::Shared::RunProgram::rooted("", '/usr/bin/mountpoint', '-q', '/sys/fs/cgroup/systemd'); -} - -sub _has_systemd { - my $self = shift; - - $ENV{PATH} = "/usr/bin:/usr/sbin"; - ManaTools::Shared::RunProgram::rooted("", '/usr/bin/rpm', '-q', 'systemd'); -} - -#============================================================= - -=head2 xinetd_services - -=head3 OUTPUT - - xinetd_services: All the xinetd services - -=head3 DESCRIPTION - - This functions returns all the xinetd services in the system. - NOTE that xinetd *must* be enable at boot to get this info - -=cut - -#============================================================= -sub xinetd_services { - my $self = shift; - - my @xinetd_services = (); - - #avoid warning if xinetd is not installed and either enabled - my $ser_info = $self->get_service_info('xinetd'); - if ($ser_info && $ser_info->{enabled} eq "1") { - local $ENV{LANGUAGE} = 'C'; - $ENV{PATH} = "/usr/bin:/usr/sbin"; - foreach (ManaTools::Shared::RunProgram::rooted_get_stdout("", '/usr/sbin/chkconfig', '--list', '--type', 'xinetd')) { - if (my ($xinetd_name, $on_off) = m!^\t(\S+):\s*(on|off)!) { - push @xinetd_services, [ $xinetd_name, $on_off eq 'on' ]; - } - } - } - return @xinetd_services; -} - -sub _systemd_services { - my ($self, $reload) = @_; - - if ($reload) { - $self->service_info($self->_serviceInfoInitialization()); - } - - my @services; - for my $pair ( $self->service_info_pairs) { - my $name = $pair->[0]; - my $info = $pair->[1]; - push @services, [$name, $info->{'enabled'}]; - } - - return @services; - -} - -sub _legacy_services { - my $self = shift; - - local $ENV{LANGUAGE} = 'C'; - my @services; - my $has_systemd = $self->_has_systemd(); - if ($has_systemd) { - # The system not using systemd but will be at next boot. This is - # is typically the case in the installer. In this mode we must read - # as much as is practicable from the native systemd unit files and - # combine that with information from chkconfig regarding legacy sysvinit - # scripts (which systemd will parse and include when running) - Sys::Syslog::syslog('info|local1', "Detected systemd installed. Using fake service+chkconfig introspection."); - foreach (glob_("/usr/lib/systemd/system/*.service")) { - my ($name) = m!([^/]*).service$!; - - # We only look at non-template, non-symlinked service files - if (!(/.*\@\.service$/g) && ! -l $_) { - # Limit ourselves to "standard" targets - my $wantedby = MDK::Common::File::cat_($_) =~ /^WantedBy=(graphical|multi-user).target$/sm ? $1 : ''; - if ($wantedby) { - # Exclude if enabled statically - # Note DO NOT use -e when testing for files that could - # be symbolic links as this will fail under a chroot - # setup where -e will fail if the symlink target does - # exist which is typically the case when viewed outside - # of the chroot. - if (!-l "/usr/lib/systemd/system/$wantedby.target.wants/$name.service") { - push @services, [ $name, !!-l "/etc/systemd/system/$wantedby.target.wants/$name.service" ]; - } - } - } - } - } else { - Sys::Syslog::syslog('info|local1', "Could not detect systemd. Using chkconfig service introspection."); - } - - # Regardless of whether we expect to use systemd on next boot, we still - # need to instrospect information about non-systemd native services. - my $runlevel; - my $on_off; - if (!$::isInstall) { - $runlevel = (split " ", `/sbin/runlevel`)[1]; - } - foreach (ManaTools::Shared::RunProgram::rooted_get_stdout("", '/sbin/chkconfig', '--list', '--type', 'sysv')) { - if (my ($name, $l) = m!^(\S+)\s+(0:(on|off).*)!) { - # If we expect to use systemd (i.e. installer) only show those - # sysvinit scripts which are not masked by a native systemd unit. - my $has_systemd_unit = $self->_systemd_unit_exists($name); - if (!$has_systemd || !$has_systemd_unit) { - if ($::isInstall) { - $on_off = $l =~ /\d+:on/g; - } else { - $on_off = $l =~ /$runlevel:on/g; - } - push @services, [ $name, $on_off ]; - } - } - } - @services; -} - -#- returns: -#--- the listref of installed services -#--- the listref of "on" services -#============================================================= - -=head2 services - -=head3 INPUT - - $reload: load service again - -=head3 OUTPUT - - @l: all the system services - @on_services: all the services that start at boot - -=head3 DESCRIPTION - - This function returns two lists, all the system service and - all the active ones. - -=cut - -#============================================================= - - -sub services { - my ($self, $reload) = @_; - - my @Services; - if ($self->_running_systemd()) { - @Services = $self->_systemd_services($reload); - } else { - @Services = $self->_legacy_services(); - } - - my @l = $self->xinetd_services(); - push @l, @Services; - @l = sort { $a->[0] cmp $b->[0] } @l; - [ map { $_->[0] } @l ], [ map { $_->[0] } grep { $_->[1] } @l ]; -} - - -# if we loaded service info, then exists -sub _systemd_unit_exists { - my ($self, $name) = @_; - - return defined ($self->get_service_info($name)); -} - -#============================================================= - -=head2 service_exists - -=head3 INPUT - - $service: Service name - -=head3 OUTPUT - - 0/1: if the service exists - -=head3 DESCRIPTION - - This function checks if a service is installed by looking for - its unit or init.d service - -=cut - -#============================================================= - -sub service_exists { - my ($self, $service) = @_; - $self->_systemd_unit_exists($service) or -x "/etc/rc.d/init.d/$service"; -} - -#============================================================= - -=head2 restart - -=head3 INPUT - - $service: Service to restart - -=head3 DESCRIPTION - - This function restarts a given service - -=cut - -#============================================================= - - -sub restart { - my ($self, $service) = @_; - # Exit silently if the service is not installed - $self->service_exists($service) or return 1; - $self->_run_action($service, "restart"); -} - -#============================================================= - -=head2 restart_or_start - -=head3 INPUT - - $service: Service to restart or start - -=head3 DESCRIPTION - - This function starts a given service if it is not running, - it restarts that otherwise - -=cut - -#============================================================= - -sub restart_or_start { - my ($self, $service) = @_; - # Exit silently if the service is not installed - $self->service_exists($service) or return 1; - $self->_run_action($service, $self->is_service_running($service) ? "restart" : "start"); -} - - -#============================================================= - -=head2 startService - -=head3 INPUT - - $service: Service to start - -=head3 DESCRIPTION - - This function starts a given service - -=cut - -#============================================================= - -sub startService { - my ($self, $service) = @_; - # Exit silently if the service is not installed - $self->service_exists($service) or return 1; - $self->_run_action($service, "start"); -} - -#============================================================= - -=head2 start_not_running_service - -=head3 INPUT - - $service: Service to start - -=head3 DESCRIPTION - - This function starts a given service if not running - -=cut - -#============================================================= - -sub start_not_running_service { - my ($self, $service) = @_; - # Exit silently if the service is not installed - $self->service_exists($service) or return 1; - $self->is_service_running($service) || $self->_run_action($service, "start"); -} - -#============================================================= - -=head2 stopService - -=head3 INPUT - - $service: Service to stop - -=head3 DESCRIPTION - - This function stops a given service - -=cut - -#============================================================= -sub stopService { - my ($self, $service) = @_; - # Exit silently if the service is not installed - $self->service_exists($service) or return 1; - $self->_run_action($service, "stop"); -} - -#============================================================= - -=head2 is_service_running - -=head3 INPUT - - $service: Service to check - -=head3 DESCRIPTION - - This function returns if the given service is running - -=cut - -#============================================================= - -sub is_service_running { - my ($self, $service) = @_; - # Exit silently if the service is not installed - $self->service_exists($service) or return 0; - my $out; - if ($self->_running_systemd()) { - my $ser_info = $self->get_service_info($service); - $out = $ser_info->{active_state} eq 'active' if $ser_info->{active_state}; - } else { - $ENV{PATH} = "/usr/bin:/usr/sbin"; - $out = ManaTools::Shared::RunProgram::rooted("", '/usr/sbin/service', $service, 'status'); - } - return $out; -} - -#============================================================= - -=head2 starts_on_boot - -=head3 INPUT - - $service: Service name - - -=head3 DESCRIPTION - - This function returns if the given service starts at boot - -=cut - -#============================================================= -sub starts_on_boot { - my ($self, $service) = @_; - my (undef, $on_services) = $self->services(); - MDK::Common::DataStructure::member($service, @$on_services); -} - -#============================================================= - -=head2 start_service_on_boot - -=head3 INPUT - - $service: Service name - - -=head3 DESCRIPTION - - This function set the given service active at boot - -=cut - -#============================================================= -sub start_service_on_boot { - my ($self, $service) = @_; - $self->set_service($service, 1); -} - -#============================================================= - -=head2 do_not_start_service_on_boot - -=head3 INPUT - - $service: Service name - - -=head3 DESCRIPTION - - This function set the given service disabled at boot - -=cut - -#============================================================= -sub do_not_start_service_on_boot { - my ($self, $service) = @_; - $self->set_service($service, 0); -} - -#============================================================= - -=head2 enable - -=head3 INPUT - - $service: Service name - $o_dont_apply: do not start it now - -=head3 DESCRIPTION - - This function set the given service active at boot - and restarts it if o_dont_apply is not given - -=cut - -#============================================================= -sub enable { - my ($self, $service, $o_dont_apply) = @_; - $self->start_service_on_boot($service); - $self->restart_or_start($service) unless $o_dont_apply; -} - -#============================================================= - -=head2 disable - -=head3 INPUT - - $service: Service name - $o_dont_apply: do not stop it now - -=head3 DESCRIPTION - - This function set the given service disabled at boot - and stops it if o_dont_apply is not given - -=cut - -#============================================================= -sub disable { - my ($self, $service, $o_dont_apply) = @_; - $self->do_not_start_service_on_boot($service); - $self->stopService($service) unless $o_dont_apply; -} - -#============================================================= - -=head2 set_status - -=head3 INPUT - - $service: Service name - $enable: Enable/disable - $o_dont_apply: do not start it now - -=head3 DESCRIPTION - - This function set the given service to enable/disable at boot - and restarts/stops it if o_dont_apply is not given - -=cut - -#============================================================= -sub set_status { - my ($self, $service, $enable, $o_dont_apply) = @_; - if ($enable) { - $self->enable($service, $o_dont_apply); - } else { - $self->disable($service, $o_dont_apply); - } -} - -# NOTE $service->get_object("/org/freedesktop/systemd1/unit/$name_2eservice"); -# has empty WantedBy property if disabled -sub _WantedBy { - my ($self, $path_service) = @_; - - my $wantedby = MDK::Common::File::cat_($path_service) =~ /^WantedBy=(graphical|multi-user).target$/sm ? $1 : ''; - - return $wantedby; -} - -#============================================================= - -=head2 getUnitProperty - -=head3 INPUT - - $unit: unit name - $property: property name - -=head3 OUTPUT - - $property_value: property value - -=head3 DESCRIPTION - - This method returns the requested property value - -=cut - -#============================================================= -sub getUnitProperty { - my ($self, $unit, $property) = @_; - - my $name = $unit . ".service"; - $name =~ s|-|_2d|g; - $name =~ s|\.|_2e|g; - my $service = $self->dbus_systemd1_service; - my $unit_object = $service->get_object("/org/freedesktop/systemd1/unit/" . $name); - my $property_value = eval {$unit_object->Get("org.freedesktop.systemd1.Unit", $property)} || ""; - - return $property_value; -} - -1; diff --git a/lib/AdminPanel/Shared/Shorewall.pm b/lib/AdminPanel/Shared/Shorewall.pm deleted file mode 100644 index f82c542..0000000 --- a/lib/AdminPanel/Shared/Shorewall.pm +++ /dev/null @@ -1,271 +0,0 @@ -package ManaTools::Shared::Shorewall; # $Id: shorewall.pm 254244 2009-03-18 22:54:32Z eugeni $ - -use detect_devices; -use network::network; -use ManaTools::Shared::RunProgram; -use ManaTools::Shared::Services; -use MDK::Common::Func qw(if_ partition map_each); -use MDK::Common::File qw(cat_ substInFile output_with_perm); -use MDK::Common::Various qw(to_bool); -use MDK::Common::DataStructure qw(is_empty_array_ref); -use List::Util qw(any); -use List::MoreUtils qw(uniq); -use log; - -my $shorewall_root = "/etc/shorewall"; - -sub check_iptables() { - -f "$::prefix/etc/sysconfig/iptables" || - $::isStandalone && do { - system('modprobe iptable_nat'); - -x '/sbin/iptables' && listlength(`/sbin/iptables -t nat -nL`) > 8; - }; -} - -sub set_config_file { - my ($file, $ver, @l) = @_; - - my $done; - substInFile { - my $last_line = /^#LAST LINE/ && $_; - if (!$done && ($last_line || eof)) { - $_ = join('', map { join("\t", @$_) . "\n" } @l); - $_ .= $last_line if $last_line; - $done = 1; - } else { - $_ = '' unless - /^#/ || $file eq 'rules' && /^SECTION/; - } - } "$::prefix${shorewall_root}${ver}/$file"; -} - -sub get_config_file { - my ($file, $o_ver) = @_; - map { [ split ' ' ] } grep { !/^#/ } cat_("$::prefix${shorewall_root}${o_ver}/$file"); -} - -# Note: Called from drakguard and drakfirewall.pm... -# Deliberately not adding shorewall6 support here for now -sub set_in_file { - my ($file, $enabled, @list) = @_; - my $done; - substInFile { - my $last_line = /^#LAST LINE/ && $_; - foreach my $l (@list) { s|^$l\n|| } - if (!$done && $enabled && ($last_line || eof)) { - $_ = join('', map { "$_\n" } @list); - $_ .= $last_line if $last_line; - $done = 1; - } - } "$::prefix${shorewall_root}/$file"; -} - -sub dev_to_shorewall { - my ($dev) = @_; - $dev =~ /^ippp/ && "ippp+" || - $dev =~ /^ppp/ && "ppp+" || - $dev; -} - -sub get_net_zone_interfaces { - my ($interfacesfile, $_net, $all_intf) = @_; - if(ref($interfacesfile) eq "ARRAY") - { - #- read shorewall configuration first - my @interfaces = map { $_->[1] } grep { $_->[0] eq 'net' } $interfacesfile; - } - else - { - my @interfaces = undef; - } - #- else try to find the best interface available - @interfaces ? @interfaces : @{$all_intf || []}; -} - -sub add_interface_to_net_zone { - my ($conf, $interface) = @_; - if (!member($interface, @{$conf->{net_zone}})) { - push @{$conf->{net_zone}}, $interface; - @{$conf->{loc_zone}} = grep { $_ ne $interface } @{$conf->{loc_zone}}; - } -} - -sub read_ { - my ($o_ver) = @_; - my $ver = ''; - $ver = $o_ver if $o_ver; - #- read old rules file if config is not moved to rules.drakx yet - my @rules = get_config_file(-f "$::prefix${shorewall_root}${ver}/rules.drakx" ? 'rules.drakx' : 'rules', $ver); - my $services = ManaTools::Shared::Services->new(); - my %conf = (disabled => !$services->starts_on_boot("shorewall${ver}"), - version => $ver, - ports => join(' ', map { - my $e = $_; - map { "$_/$e->[3]" } split(',', $e->[4]); - } grep { $_->[0] eq 'ACCEPT' && $_->[1] eq 'net' } @rules), - ); - push @{$conf{accept_local_users}{$_->[4]}}, $_->[8] foreach grep { $_->[0] eq 'ACCEPT+' } @rules; - $conf{redirects}{$_->[3]}{$_->[4]} = $_->[2] foreach grep { $_->[0] eq 'REDIRECT' } @rules; - - if (my ($e) = get_config_file('masq', $ver)) { - ($conf{masq}{net_interface}, $conf{masq}{subnet}) = @$e; - } - - my @policy = get_config_file('policy', $ver); - $conf{log_net_drop} = @policy ? (any { $_->[0] eq 'net' && $_->[1] eq 'all' && $_->[2] eq 'DROP' && $_->[3] } @policy) : 1; - - return \%conf; - - # get_zones has been moved to ManaTools::Module::Firewall cause it requires - # user interaction thus it should be logically separated by shorewall - # get_zones(\%conf); - # get_config_file('zones', $ver) && \%conf; - # consequently, to read shorewall conf - # you have to do something like this now (within Module::Firewall) - # my $conf = ManaTools::Shared::Shorewall::read_(); - # OPTIONAL: my $self->get_zones(\$conf) - # my $shorewall = ManaTools::Shared::Shorewall::get_config_file('zones', '') && $conf; -} - -sub ports_by_proto { - my ($ports) = @_; - my %ports_by_proto; - foreach (split ' ', $ports) { - m!^(\d+(?::\d+)?)/(udp|tcp|icmp)$! or die "bad port $_\n"; - push @{$ports_by_proto{$2}}, $1; - } - \%ports_by_proto; -} - -#============================================================= - -=head2 write_ - -=head3 INPUT - - $conf: HASH, contains the configuration to write - - $action: Str, possible values are "keep" or "drop" - -=head3 OUTPUT - - 0: requires user interaction - 1: everything has been done - -=head3 DESCRIPTION - -This function stores the configuration for shorewall inside -the proper files. - -=head3 NOTES - -if write_ is called without the $action parameter it can return 0 -(i.e. user interaction requested) when the firewall configuration -has been manually changed. - -In that case the developer will have to handle this request by providing -two choices within the domain (keep | drop) and then recall write_ with -the choosen behaviour. - -=cut - -#============================================================= - -sub write_ { - my ($conf, $action) = @_; - my $ver = $conf->{version} || ''; - my $use_pptp = any { /^ppp/ && cat_("$::prefix/etc/ppp/peers/$_") =~ /pptp/ } @{$conf->{net_zone}}; - my $ports_by_proto = ports_by_proto($conf->{ports}); - my $has_loc_zone = to_bool(@{$conf->{loc_zone} || []}); - - my ($include_drakx, $other_rules) = partition { $_ eq "INCLUDE\trules.drakx\n" } grep { !/^(#|SECTION)/ } cat_("$::prefix${shorewall_root}${ver}/rules"); - #- warn if the config is already in rules.drakx and additionnal rules are configured - if (!is_empty_array_ref($include_drakx) && !is_empty_array_ref($other_rules)) { - if(!defined($action) || ManaTools::Shared::trim($action) eq "") - { - return 0; # user interaction requested - } - my %actions = ( - keep => N("Keep custom rules"), - drop => N("Drop custom rules"), - ); - #- reset the rules files if the user has chosen to drop modifications - undef $include_drakx if $action eq 'drop'; - } - - my $interface_settings = sub { - my ($zone, $interface) = @_; - [ $zone, $interface, 'detect', if_(detect_devices::is_bridge_interface($interface), 'bridge') ]; - }; - - set_config_file('zones', $ver, - if_($has_loc_zone, [ 'loc', 'ipv' . ($ver || '4') ]), - [ 'net', 'ipv' . ($ver || '4') ], - [ 'fw', 'firewall' ], - ); - set_config_file('interfaces', $ver, - (map { $interface_settings->('net', $_) } @{$conf->{net_zone}}), - (map { $interface_settings->('loc', $_) } @{$conf->{loc_zone} || []}), - ); - set_config_file('policy', $ver, - if_($has_loc_zone, [ 'loc', 'net', 'ACCEPT' ], [ 'loc', 'fw', 'ACCEPT' ], [ 'fw', 'loc', 'ACCEPT' ]), - [ 'fw', 'net', 'ACCEPT' ], - [ 'net', 'all', 'DROP', if_($conf->{log_net_drop}, 'info') ], - [ 'all', 'all', 'REJECT', 'info' ], - ); - if (is_empty_array_ref($include_drakx)) { - #- make sure the rules.drakx config is read, erasing user modifications - set_config_file('rules', $ver, [ 'INCLUDE', 'rules.drakx' ]); - } - output_with_perm("$::prefix${shorewall_root}${ver}/" . 'rules.drakx', 0600, map { join("\t", @$_) . "\n" } ( - if_($use_pptp, [ 'ACCEPT', 'fw', 'loc:10.0.0.138', 'tcp', '1723' ]), - if_($use_pptp, [ 'ACCEPT', 'fw', 'loc:10.0.0.138', 'gre' ]), - (map_each { [ 'ACCEPT', 'net', 'fw', $::a, join(',', @$::b), '-' ] } %$ports_by_proto), - (map_each { - if_($::b, map { [ 'ACCEPT+', 'fw', 'net', 'tcp', $::a, '-', '-', '-', $_ ] } @$::b); - } %{$conf->{accept_local_users}}), - (map { - my $proto = $_; - #- WARNING: won't redirect ports from the firewall system if a local zone exists - #- set redirect_fw_only to workaround - map_each { - map { [ 'REDIRECT', $_, $::b, $proto, $::a, '-' ] } 'fw', if_($has_loc_zone, 'loc'); - } %{$conf->{redirects}{$proto}}; - } keys %{$conf->{redirects}}), - )); - set_config_file('masq', $ver, if_(exists $conf->{masq}, [ $conf->{masq}{net_interface}, $conf->{masq}{subnet} ])); - - my $services = ManaTools::Shared::Services->new(); - if ($conf->{disabled}) { - $services->disable('shorewall', $::isInstall); - run_program::rooted($::prefix, '/sbin/shorewall', 'clear') unless $::isInstall; - } else { - $services->enable('shorewall', $::isInstall); - } - return 1; -} - -sub set_redirected_ports { - my ($conf, $proto, $dest, @ports) = @_; - if (@ports) { - $conf->{redirects}{$proto}{$_} = $dest foreach @ports; - } else { - my $r = $conf->{redirects}{$proto}; - @ports = grep { $r->{$_} eq $dest } keys %$r; - delete $r->{$_} foreach @ports; - } -} - -sub update_interfaces_list { - my ($o_intf) = @_; - if (!$o_intf || !member($o_intf, map { $_->[1] } get_config_file('interfaces'))) { - my $shorewall = ManaTools::Shared::Shorewall::read_(); - $shorewall && !$shorewall->{disabled} and ManaTools::Shared::Shorewall::write_($shorewall); - } - if (!$o_intf || !member($o_intf, map { $_->[1] } get_config_file('interfaces', 6))) { - my $shorewall6 = ManaTools::Shared::Shorewall::read_(undef, 6); - $shorewall6 && !$shorewall6->{disabled} and ManaTools::Shared::Shorewall::write_($shorewall6); - } -} - -1; diff --git a/lib/AdminPanel/Shared/TimeZone.pm b/lib/AdminPanel/Shared/TimeZone.pm deleted file mode 100644 index efb49a2..0000000 --- a/lib/AdminPanel/Shared/TimeZone.pm +++ /dev/null @@ -1,799 +0,0 @@ -# vim: set et ts=4 sw=4: -package ManaTools::Shared::TimeZone; - -#============================================================= -*-perl-*- - -=head1 NAME - -ManaTools::Shared::TimeZone - module to manage TimeZone settings - -=head1 SYNOPSIS - - my $tz = ManaTools::Shared::TimeZone->new(); - - -=head1 DESCRIPTION - -This module allows to manage time zone settings. - -=head1 SUPPORT - -You can find documentation for this module with the perldoc command: - -perldoc ManaTools::Shared::TimeZone - - -=head1 AUTHOR - -Angelo Naselli - -=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 METHODS - -=cut - - -use diagnostics; -use strict; - -use Moose; - -use DateTime::TimeZone; -use Net::DBus; - -use ManaTools::Shared::Locales; -use ManaTools::Shared::Services; - -use MDK::Common::File qw(cat_ output_p substInFile); -use MDK::Common::Func qw(find if_); - - -#============================================================= - -=head2 new - optional parameters - -=head3 timezone_prefix - - optional parameter to set the system timezone directory, - default value is /usr/share/zoneinfo - -=cut - -#============================================================= - -has 'timezone_prefix' => ( - is => 'rw', - isa => 'Str', - default => "/usr/share/zoneinfo", -); - - -#============================================================= - -=head2 new - optional parameters - -=head3 ntp_configuration_file - - optional parameter to set the ntp server configuration file, - default value is /etc/[chrony|ntp].conf - -=cut - -#============================================================= - -has 'ntp_configuration_file' => ( - is => 'rw', - isa => 'Str', - builder => '_ntp_configuration_file_init', -); - -sub _ntp_configuration_file_init { - my $self = shift; - - if (-f "/etc/chrony.conf") { - return "/etc/chrony.conf"; - } - return "/etc/ntp.conf"; -} - -#============================================================= - -=head2 new - optional parameters - -=head3 ntp_conf_dir - - optional parameter to set ntp configuration directory, - default value is /etc/ntp - -=cut - -#============================================================= - -has 'ntp_conf_dir' => ( - is => 'rw', - isa => 'Str', - lazy => 1, - default => "/etc/ntp", -); - -#============================================================= - -=head2 new - optional parameters - -=head3 ntp_program - - optional parameter to set the ntp program that runs into the - system, default value is [chrony|ntp] - -=cut - -#============================================================= -has 'ntp_program' => ( - is => 'rw', - isa => 'Str', - builder => '_ntp_program_init', -); - -sub _ntp_program_init { - my $self = shift; - - if (-f "/etc/chrony.conf") { - return "chrony"; - } - return "ntp"; -} - -#============================================================= - -=head2 new - optional parameters - -=head3 installer_or_livecd - - To inform the back-end that is working during installer or - livecd. Useful if Time zone setting and using fix_system - to use the real time clock (see setLocalRTC and - writeConfiguration). - -=cut - -#============================================================= -has 'installer_or_livecd' => ( - is => 'rw', - isa => 'Bool', - default => 0, -); - -#=== globals === - -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 'dbus_timedate1_service' => ( - is => 'rw', - init_arg => undef, - lazy => 1, - builder => '_dbusTimeDateInitialize' -); - -sub _dbusTimeDateInitialize { - my $self = shift(); - - my $bus = Net::DBus->system; - $self->dbus_timedate1_service($bus->get_service("org.freedesktop.timedate1")); -} - - -has 'dbus_timedate1_object' => ( - is => 'rw', - init_arg => undef, - lazy => 1, - builder => '_dbusObjectInitialize' -); - -sub _dbusObjectInitialize { - my $self = shift(); - - $self->dbus_timedate1_object($self->dbus_timedate1_service->get_object("/org/freedesktop/timedate1")); -} - - -has 'servername_config_suffix' => ( - is => 'ro', - isa => 'Str', - lazy => 1, - builder => '_servername_config_suffix_init', -); - -sub _servername_config_suffix_init { - my $self = shift; - - return " iburst" if ($self->ntp_program eq "chrony"); - - return ""; -} - -has 'loc' => ( - is => 'rw', - lazy => 1, - 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') ); - # TODO if we want to give the opportunity to test locally add dir_name => 'path' -} - - -has 'ntp_servers' => ( - traits => ['Hash'], - is => 'rw', - isa => 'HashRef', - lazy => 1, - handles => { - get_ntp_server => 'get', - ntp_server_pairs => 'kv', - }, - init_arg => undef, - builder => '_buildNTPServers' -); - -sub _buildNTPServers { - my $self = shift; - - my %ntpServersHash; - $ntpServersHash{"-"} = { - $self->loc->N_("Global") => "pool.ntp.org", - }; - $ntpServersHash{Global} = { - $self->loc->N_("Africa") => "africa.pool.ntp.org", - $self->loc->N_("Asia") => "asia.pool.ntp.org", - $self->loc->N_("Europe") => "europe.pool.ntp.org", - $self->loc->N_("North America") => "north-america.pool.ntp.org", - $self->loc->N_("Oceania") => "oceania.pool.ntp.org", - $self->loc->N_("South America") => "south-america.pool.ntp.org", - }; - $ntpServersHash{Africa} = { - $self->loc->N_("South Africa") => "za.pool.ntp.org", - $self->loc->N_("Tanzania") => "tz.pool.ntp.org", - }; - $ntpServersHash{Asia} = { - $self->loc->N_("Bangladesh") => "bd.pool.ntp.org", - $self->loc->N_("China") => "cn.pool.ntp.org", - $self->loc->N_("Hong Kong") => "hk.pool.ntp.org", - $self->loc->N_("India") => "in.pool.ntp.org", - $self->loc->N_("Indonesia") => "id.pool.ntp.org", - $self->loc->N_("Iran") => "ir.pool.ntp.org", - $self->loc->N_("Israel") => "il.pool.ntp.org", - $self->loc->N_("Japan") => "jp.pool.ntp.org", - $self->loc->N_("Korea") => "kr.pool.ntp.org", - $self->loc->N_("Malaysia") => "my.pool.ntp.org", - $self->loc->N_("Philippines") => "ph.pool.ntp.org", - $self->loc->N_("Singapore") => "sg.pool.ntp.org", - $self->loc->N_("Taiwan") => "tw.pool.ntp.org", - $self->loc->N_("Thailand") => "th.pool.ntp.org", - $self->loc->N_("Turkey") => "tr.pool.ntp.org", - $self->loc->N_("United Arab Emirates") => "ae.pool.ntp.org", - }; - $ntpServersHash{Europe} = { - $self->loc->N_("Austria") => "at.pool.ntp.org", - $self->loc->N_("Belarus") => "by.pool.ntp.org", - $self->loc->N_("Belgium") => "be.pool.ntp.org", - $self->loc->N_("Bulgaria") => "bg.pool.ntp.org", - $self->loc->N_("Czech Republic") => "cz.pool.ntp.org", - $self->loc->N_("Denmark") => "dk.pool.ntp.org", - $self->loc->N_("Estonia") => "ee.pool.ntp.org", - $self->loc->N_("Finland") => "fi.pool.ntp.org", - $self->loc->N_("France") => "fr.pool.ntp.org", - $self->loc->N_("Germany") => "de.pool.ntp.org", - $self->loc->N_("Greece") => "gr.pool.ntp.org", - $self->loc->N_("Hungary") => "hu.pool.ntp.org", - $self->loc->N_("Ireland") => "ie.pool.ntp.org", - $self->loc->N_("Italy") => "it.pool.ntp.org", - $self->loc->N_("Lithuania") => "lt.pool.ntp.org", - $self->loc->N_("Luxembourg") => "lu.pool.ntp.org", - $self->loc->N_("Netherlands") => "nl.pool.ntp.org", - $self->loc->N_("Norway") => "no.pool.ntp.org", - $self->loc->N_("Poland") => "pl.pool.ntp.org", - $self->loc->N_("Portugal") => "pt.pool.ntp.org", - $self->loc->N_("Romania") => "ro.pool.ntp.org", - $self->loc->N_("Russian Federation") => "ru.pool.ntp.org", - $self->loc->N_("Slovakia") => "sk.pool.ntp.org", - $self->loc->N_("Slovenia") => "si.pool.ntp.org", - $self->loc->N_("Spain") => "es.pool.ntp.org", - $self->loc->N_("Sweden") => "se.pool.ntp.org", - $self->loc->N_("Switzerland") => "ch.pool.ntp.org", - $self->loc->N_("Ukraine") => "ua.pool.ntp.org", - $self->loc->N_("United Kingdom") => "uk.pool.ntp.org", - $self->loc->N_("Yugoslavia") => "yu.pool.ntp.org", - }; - $ntpServersHash{"North America"} = { - $self->loc->N_("Canada") => "ca.pool.ntp.org", - $self->loc->N_("Guatemala") => "gt.pool.ntp.org", - $self->loc->N_("Mexico") => "mx.pool.ntp.org", - $self->loc->N_("United States") => "us.pool.ntp.org", - }; - $ntpServersHash{Oceania} = { - $self->loc->N_("Australia") => "au.pool.ntp.org", - $self->loc->N_("New Zealand") => "nz.pool.ntp.org", - }; - $ntpServersHash{"South America"} = { - $self->loc->N_("Argentina") => "ar.pool.ntp.org", - $self->loc->N_("Brazil") => "br.pool.ntp.org", - $self->loc->N_("Chile") => "cl.pool.ntp.org", - }; - - return \%ntpServersHash; -} - - -#============================================================= - -=head2 get_timezone_prefix - -=head3 OUTPUT - -timezone_prefix: directory in which time zone files are - -=head3 DESCRIPTION - -Return the timezone directory (defualt: /usr/share/zoneinfo) - -=cut - -#============================================================= -sub get_timezone_prefix { - my $self = shift; - - return $self->timezone_prefix; -} - -#============================================================= - -=head2 getTimeZones - -=head3 INPUT - - $from_system: if present and its value is not 0 checks into timezone_prefix - directory and gets the list from there - -=head3 OUTPUT - - @l: ARRAY containing sorted time zones - -=head3 DESCRIPTION - - This method returns the available timezones - -=cut - -#============================================================= -sub getTimeZones { - my ($self, $from_system) = @_; - - if ($from_system and $from_system != 0) { - require MDK::Common::DataStructure; - require MDK::Common::Various; - my $tz_prefix = $self->get_timezone_prefix(); - open(my $F, "cd $tz_prefix && find [A-Z]* -noleaf -type f |"); - my @l = MDK::Common::DataStructure::difference2([ MDK::Common::Various::chomp_(<$F>) ], [ 'ROC', 'PRC' ]); - close $F or die "cannot list the available zoneinfos"; - return sort @l; - } - - return DateTime::TimeZone->all_names; -} - -#============================================================= - -=head2 setTimeZone - -=head3 INPUT - - $new_time_zone: New time zone to be set - -=head3 DESCRIPTION - - This method get the new time zone to set and performs - the setting - -=cut - -#============================================================= -sub setTimeZone { - my ($self, $new_time_zone) = @_; - - die "Time zone value required" if !defined($new_time_zone); - - my $object = $self->dbus_timedate1_object; - $object->SetTimezone($new_time_zone, 1); -} - -#============================================================= - -=head2 getTimeZone - -=head3 OUTPUT - - $timezone: current time zone - -=head3 DESCRIPTION - - This method returns the current timezone setting - -=cut - -#============================================================= -sub getTimeZone { - my ($self) = @_; - - my $object = $self->dbus_timedate1_object; - - return $object->Get("org.freedesktop.timedate1", 'Timezone') || ""; -} - - -#============================================================= - -=head2 setLocalRTC - -=head3 INPUT - - $enable: bool value enable/disable real time clock as - localtime - $fix_system: bool read or not the real time clock - -=head3 DESCRIPTION - - This method enables/disables the real time clock as - localtime (e.g. disable means set the rtc to UTC). - NOTE from dbus: - Use SetLocalRTC() to control whether the RTC is in - local time or UTC. It is strongly recommended to maintain - the RTC in UTC. Some OSes (Windows) however maintain the - RTC in local time which might make it necessary to enable - this feature. However, this creates various problems as - daylight changes might be missed. If fix_system is passed - "true" the time from the RTC is read again and the system - clock adjusted according to the new setting. - If fix_system is passed "false" the system time is written - to the RTC taking the new setting into account. - Use fix_system=true in installers and livecds where the - RTC is probably more reliable than the system time. - Use fix_system=false in configuration UIs that are run during - normal operation and where the system clock is probably more - reliable than the RTC. - -=cut - -#============================================================= -sub setLocalRTC { - my ($self, $enable, $fix_system) = @_; - - die "Localtime enable/disable value required" if !defined($enable); - - $fix_system = 0 if !defined($fix_system); - my $object = $self->dbus_timedate1_object; - $object->SetLocalRTC($enable, $fix_system, 1) ; -} - -#============================================================= - -=head2 getLocalRTC - -=head3 OUTPUT - - $localRTC: 1 if RTC is localtime 0 for UTC - -=head3 DESCRIPTION - - This method returns the RTC localtime setting - -=cut - -#============================================================= -sub getLocalRTC { - my $self = shift; - - my $object = $self->dbus_timedate1_object; - - return $object->Get("org.freedesktop.timedate1", 'LocalRTC') ? 1 : 0; -} - - -#============================================================= - -=head2 setTime - -=head3 INPUT - - $sec_since_epoch: Time in seconds since 1/1/1970 - -=head3 DESCRIPTION - - This method set the system time and sets the RTC also - -=cut - -#============================================================= -sub setTime { - my ($self, $sec_since_epoch) = @_; - - die "second since epoch required" if !defined($sec_since_epoch); - - my $object = $self->dbus_timedate1_object; - my $usec = $sec_since_epoch* 1000000; - - $object->SetTime($usec, 0, 1); -} - -#============================================================= - -=head2 readConfiguration - -=head3 OUTPUT - - hash reference containing: - UTC => HW clock is set as UTC - ZONE => Time Zone set - -=head3 DESCRIPTION - - This method returns the time zone system settings as hash - reference - -=cut - -#============================================================= -sub readConfiguration { - my $self = shift; - - my $prefs = {}; - $prefs->{'ZONE'} = $self->getTimeZone(); - $prefs->{'UTC'} = $self->getLocalRTC() ? 0 : 1; - - return $prefs; -} - - -#============================================================= - -=head2 writeConfiguration - -=head3 INPUT - - $info: hash containing: - UTC => HW clock is set as UTC - ZONE => Time Zone - -=head3 DESCRIPTION - - This method sets the passed Time Zone configuration. - If installer_or_livecd attribute is set fix_system is - passed to setLocalRTC - -=cut - -#============================================================= -sub writeConfiguration { - my ($self, $info) = @_; - - die "UTC field required" if !defined($info->{UTC}); - die "ZONE field required" if !defined($info->{ZONE}); - - my $localRTC = $info->{UTC} ? 0 : 1; - $self->setLocalRTC( - $localRTC, - $self->installer_or_livecd - ); - - $self->setTimeZone( - $info->{ZONE} - ); -} - - -#left for back compatibility -sub _get_ntp_server_tree { - my ($self, $zone) = @_; - $zone = "-" if ! $zone; - my $ns = $self->get_ntp_server($zone); - return if !$ns; - - map { - $ns->{$_} => ( - $self->get_ntp_server($_) ? - $zone ? - $self->loc->N($_) . "|" . $self->loc->N("All servers") : - $self->loc->N("All servers") : - $self->loc->N($zone) . "|" . $self->loc->N($_) - ), - $self->_get_ntp_server_tree($_) - } keys %{$ns}; -} - -#============================================================= - -=head2 ntpServers - -=head3 OUTPUT - - HASHREF containing ntp_server => zone info - -=head3 DESCRIPTION - - This method returns an hash ref containing pairs ntp-server, zone - -=cut - -#============================================================= -sub ntpServers { - my ($self) = @_; - # FIXME: missing parameter: - +{$self->_get_ntp_server_tree()}; -} - - -#============================================================= - -=head2 ntpCurrentServer - -=head3 INPUT - -Input_Parameter: in_par_description - -=head3 DESCRIPTION - -Returns the current ntp server address read from configuration file - -=cut - -#============================================================= - -sub ntpCurrentServer { - my $self = shift; - - MDK::Common::Func::find { $_ ne '127.127.1.0' } map { MDK::Common::Func::if_(/^\s*server\s+(\S*)/, $1) } MDK::Common::File::cat_($self->ntp_configuration_file); -} - -#============================================================= - -=head2 isNTPRunning - -=head3 DESCRIPTION - - This method just returns if the given ntp server is running - -=cut - -#============================================================= -sub isNTPRunning { - my $self = shift; - - # TODO is that valid for any ntp program? adding ntp_service_name parameter - my $ntpd = $self->ntp_program . 'd'; - - return $self->sh_services->is_service_running($ntpd); -} - -#============================================================= - -=head2 setNTPServer - -=head3 INPUT - -$server: server address to be configured - -=head3 DESCRIPTION - -This method writes into NTP configuration file new server address -settings - -=cut - -#============================================================= -sub setNTPServer { - my ($self, $server) = @_; - - my $f = $self->ntp_configuration_file; - -f $f or return; - return if (!$server); - - # TODO is that valid for any ntp program? adding ntp_service_name parameter - my $ntpd = $self->ntp_program . 'd'; - - ManaTools::Shared::disable_x_screensaver(); - if ($self->isNTPRunning()) { - $self->sh_services->stopService($ntpd); - } - - my $pool_match = qr/\.pool\.ntp\.org$/; - my @servers = $server =~ $pool_match ? (map { "$_.$server" } 0 .. 2) : $server; - - my $added = 0; - my $servername_config_suffix = $self->servername_config_suffix ? $self->servername_config_suffix : " "; - MDK::Common::File::substInFile { - if (/^#?\s*server\s+(\S*)/ && $1 ne '127.127.1.0') { - $_ = $added ? $_ =~ $pool_match ? undef : "#server $1\n" : join('', map { "server $_$servername_config_suffix\n" } @servers); - $added = 1; - } - } $f; - if ($self->ntp_program eq "ntp") { - my $ntp_prefix = $self->ntp_conf_dir; - MDK::Common::File::output_p("$ntp_prefix/step-tickers", join('', map { "$_\n" } @servers)); - } - - # enable but do not start the service - $self->sh_services->set_status($ntpd, 1, 1); - if ($ntpd eq "chronyd") { - $self->sh_services->startService($ntpd); - $ENV{PATH} = "/usr/bin:/usr/sbin"; - # Wait up to 30s for sync - system('/usr/bin/chronyc', 'waitsync', '30', '0.1'); - } else { - $ENV{PATH} = "/usr/bin:/usr/sbin"; - system('/usr/sbin/ntpdate', $server); - $self->sh_services->startService($ntpd); - } - - ManaTools::Shared::enable_x_screensaver(); -} - -#============================================================= - -=head2 disableAndStopNTP - -=head3 DESCRIPTION - - Disable and stop the ntp server - -=cut - -#============================================================= -sub disableAndStopNTP { - my $self = shift; - - # TODO is that valid for any ntp program? adding ntp_service_name parameter - my $ntpd = $self->ntp_program . 'd'; - - # also stop the service without dont_apply parameter - $self->sh_services->set_status($ntpd, 0); -} - -no Moose; -__PACKAGE__->meta->make_immutable; - - -1; - - diff --git a/lib/AdminPanel/Shared/Users.pm b/lib/AdminPanel/Shared/Users.pm deleted file mode 100644 index 83c6061..0000000 --- a/lib/AdminPanel/Shared/Users.pm +++ /dev/null @@ -1,1612 +0,0 @@ -# vim: set et ts=4 sw=4: -package ManaTools::Shared::Users; -#============================================================= -*-perl-*- - -=head1 NAME - -ManaTools::Shared::Users - backend to manage users - -=head1 SYNOPSIS - - my $userBackEnd = ManaTools::Shared::Users->new(); - my $userInfo = $userManager->getUserInfo('username'); - -=head1 DESCRIPTION - -This module gives a low level access to the system user management it uses libUSER module. - - -=head1 SUPPORT - -You can find documentation for this module with the perldoc command: - -perldoc ManaTools::Shared::Users - -=head1 SEE ALSO - -libUSER - -=head1 AUTHOR - -Angelo Naselli - -=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 METHODS - -=cut - -use Moose; -use diagnostics; - -use Config::Auto; -use Data::Password::Meter; -use IO::All; -use File::Basename; -use File::Copy; -use File::Remove 'remove'; - -## USER is from userdrake -use USER; -use English; -use POSIX qw/ceil/; - -use ManaTools::Shared::Locales; -use ManaTools::Shared; - - -#============================================================= - -=head2 new - optional parameters - -=head3 face_dir - - optional parameter to set the system face icon directory, - default value is /usr/share/mga/faces/ - -=cut - -#============================================================= - -has 'face_dir' => ( - is => 'rw', - isa => 'Str', - default => "/usr/share/mga/faces/", -); - -#============================================================= - -=head2 new - optional parameters - -=head3 user_face_dir - - optional parameter to set the user face icon directory, - default value is /usr/share/mga/faces/ - -=cut - -#============================================================= -has 'user_face_dir' => ( - is => 'rw', - isa => 'Str', - default => "/usr/share/faces/", -); - - -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' -} - -## Used by USER (for getting values? TODO need explanations, where?) -has 'USER_GetValue' => ( - default => -65533, - is => 'ro', - isa => 'Int', - init_arg => undef, -); - -## Used by USER (for getting values? TODO need explanations, where?) -has 'ctx' => ( - is => 'ro', - init_arg => undef, - builder => '_USERInitialize', -); - -sub _USERInitialize { - my $self = shift; - - # $EUID: effective user identifier - if ($EUID == 0) { - return USER::ADMIN->new; - } - - return undef; -} - -## min (custom) UID was 500 now is 1000, let's change in a single point -has 'min_UID' => ( - default => 1000, - is => 'ro', - isa => 'Int', - init_arg => undef, -); - -## min (custom) GID was 500 now should be 1000 as for users -has 'min_GID' => ( - default => 1000, - is => 'ro', - isa => 'Int', - init_arg => undef, -); - -#============================================================= - -=head2 BUILD - -=head3 INPUT - - $self: this object - -=head3 DESCRIPTION - - The BUILD method is called after a Moose object is created, - Into this method new optional parameters are tested once, - instead of into any other methods. - -=cut - -#============================================================= -sub BUILD { - my $self = shift; - - die "Missing face directory" if (! -d $self->face_dir); - die "Missing user face directory" if (! -d $self->user_face_dir); - - $self->face_dir($self->face_dir . "/") if (substr($self->face_dir, -1) ne "/"); - $self->user_face_dir($self->user_face_dir . "/") if (substr($self->user_face_dir, -1) ne "/"); - -} - - -=head2 facedir - -=head3 OUTPUT - - path to directory containing face icon - -=head3 DESCRIPTION - - Return the directory containing face icons. - -=cut - -#============================================================= - -sub facedir { - my $self = shift; - - return $self->face_dir; -} - - -#============================================================= - -=head2 userfacedir - -=head3 OUTPUT - - path to directory containing user face icons - -=head3 DESCRIPTION - - Return the directory containing user face icons. - -=cut - -#============================================================= - -sub userfacedir { - my $self = shift; - - return $self->user_face_dir; -} - - -#============================================================= - -=head2 face2png - -=head3 INPUT - - $face: face icon name (usually username) - -=head3 OUTPUT - - pathname to $face named icon with png extension - -=head3 DESCRIPTION - - This method returns the face icon pathname related to username - -=cut - -#============================================================= - -sub face2png { - my ($self, $face) = @_; - - return $self->face_dir . $face . ".png" if $face; -} - -#============================================================= - -=head2 facenames - - -=head3 OUTPUT - - $namelist: ARRAY reference containing the face name list - -=head3 DESCRIPTION - - Retrieves the list of icon name from facesdir() - -=cut - -#============================================================= - -sub facenames { - my $self = shift; - - my $dir = $self->face_dir; - my @files = io->dir($dir)->all_files; - my @l = grep { /^[A-Z]/ } @files; - my @namelist = map { my $f = fileparse($_->filename, qr/\Q.png\E/) } (@l ? @l : @files); - - return \@namelist; -} - -#============================================================= - -=head2 addKdmIcon - -=head3 INPUT - - $user: username to add - $icon: chosen icon for username $user - - -=head3 DESCRIPTION - - Add a $user named icon to $self->user_face_dir. It just copies - $icon to $self->user_face_dir, naming it as $user - -=cut - -#============================================================= - -sub addKdmIcon { - my ($self, $user, $icon) = @_; - - if ($icon && $user) { - my $icon_name = $self->face_dir . $icon . ".png"; - my $dest = $self->user_face_dir . $user . ".png"; - - eval { copy($icon_name, $dest) } ; - } -} - -#============================================================= - -=head2 removeKdmIcon - -=head3 INPUT - - $user: username icon to remove - -=head3 DESCRIPTION - - Remove a $user named icon from $self->user_face_dir - -=cut - -#============================================================= -sub removeKdmIcon { - my ($self, $user) = @_; - - if ($user) { - my $icon_name = $self->user_face_dir . $user . ".png"; - eval { remove($icon_name) } ; - } -} - - -#============================================================= - -=head2 _valid - -=head3 INPUT - - $name: User or Group name - $name_length: Max length of $name (default 32) - -=head3 OUTPUT - - 1, locale "Ok" if valid - 0, and explanation string if not valid: - - Name field is empty please provide a name - - The name must contain only lower cased latin letters, numbers, '.', '-' and '_' - - Name is too long - -=head3 DESCRIPTION - - this internal method return if a name is compliant to - a group or user name. - -=cut - -#============================================================= - -sub _valid { - my ($self, $name, $name_length) = @_; - - return (0, $self->loc->N("Name field is empty please provide a name")) if (!$name ); - - $name_length = 32 if !$name_length; - - $name =~ /^[a-z]+?[a-z0-9_\-\.]*?$/ or do { - return (0, $self->loc->N("The name must start with a letter and contain only lower cased latin letters, numbers, '.', '-' and '_'")); - }; - - return (0, $self->loc->N("Name is too long. Maximum length is %d", $name_length)) if (! (length($name) <= $name_length)); - - return (1, $self->loc->N("Ok")); -} - -#============================================================= - -=head2 valid_username - -=head3 INPUT - - $username: user name to check - -=head3 OUTPUT - - 1 if valid, 0 if not (see _valid) - -=head3 DESCRIPTION - - Checks the valididty of the string $username - -=cut - -#============================================================= - -sub valid_username { - my ($self, $username) = @_; - - return $self->_valid($username, 32); -} - -#============================================================= - -=head2 valid_groupname - -=head3 INPUT - - $groupname: user name to check - -=head3 OUTPUT - - 1 if valid, 0 if not (see _valid) - -=head3 DESCRIPTION - - Checks the valididty of the string $groupname - -=cut - -#============================================================= -sub valid_groupname { - my ($self, $groupname) = @_; - - return $self->_valid($groupname, 16); -} - - -#============================================================= - -=head2 updateOrDelUsersInGroup - -=head3 INPUT - - $name: username - -=head3 DESCRIPTION - - Fixes user deletion into groups. - -=cut - -#============================================================= -sub updateOrDelUserInGroup { - my ($self, $name) = @_; - my $groups = $self->ctx->GroupsEnumerateFull; - foreach my $g (@$groups) { - my $members = $g->MemberName(1, 0); - if (ManaTools::Shared::inArray($name, $members)) { - eval { $g->MemberName($name, 2) }; - eval { $self->ctx->GroupModify($g) }; - } - } -} - - -#============================================================= - -=head2 getGoups - -=head3 OUTPUT - - $groups: ARRAY reference containing all the groups - -=head3 DESCRIPTION - - This method return the configured groups - -=cut - -#============================================================= -sub getGoups { - my $self = shift; - - return $self->ctx->GroupsEnumerate; -} - - -#============================================================= - -=head2 groupNameExists - -=head3 INPUT - - $groupname: the name of the group to check - -=head3 OUTPUT - - if group exists - -=head3 DESCRIPTION - - This method return if a given group exists - -=cut - -#============================================================= -sub groupNameExists { - my ($self, $groupname) = @_; - - return 0 if (!defined($groupname)); - - return (defined($self->ctx->LookupGroupByName($groupname))); -} - -#============================================================= - -=head2 groupIDExists - -=head3 INPUT - - $group: the id of the group to check - -=head3 OUTPUT - - if group exists - -=head3 DESCRIPTION - - This method return if a given group exists - -=cut - -#============================================================= -sub groupIDExists { - my ($self, $group) = @_; - - return 0 if (!defined($group)); - - return (defined($self->ctx->LookupGroupById($group))); -} - - -#============================================================= - -=head2 groupID - -=head3 INPUT - - $groupname: group name - -=head3 OUTPUT - - groupid or undef - -=head3 DESCRIPTION - - This method returns the group id for the group name - -=cut - -#============================================================= -sub groupID { - my ($self, $groupname) = @_; - - my $gr = $self->ctx->LookupGroupByName($groupname); - return $gr->Gid($self->USER_GetValue) if ($gr); - - return undef; -} - -#============================================================= - -=head2 groupName - -=head3 INPUT - - $gid group identifier - -=head3 OUTPUT - - group name or undef - -=head3 DESCRIPTION - - This method returns the group name for the given group - identifier - -=cut - -#============================================================= -sub groupName { - my ($self, $gid) = @_; - - my $gr = $self->ctx->LookupGroupById($gid); - return $gr->GroupName($self->USER_GetValue) if ($gr); - - return undef; -} - - -#============================================================= - -=head2 addGroup - -=head3 INPUT - - $params: HASH reference containing: - groupname => name of teh group to be added - gid => group id of the group to be added - is_system => is a system group? - -=head3 OUTPUT - - $gid the actual group id - -=head3 DESCRIPTION - - This method add a group to system - -=cut - -#============================================================= -sub addGroup { - my ($self, $params) = @_; - - my $is_system = defined($params->{is_system}) ? - $params->{is_system} : - 0; - - return -1 if !defined($params->{groupname}); - - my $groupEnt = $self->ctx->InitGroup($params->{groupname}, $is_system); - - return -1 if !defined($groupEnt); - - $groupEnt->Gid($params->{gid}) if defined($params->{gid}); - - $self->ctx->GroupAdd($groupEnt); - - return $groupEnt->Gid($self->USER_GetValue); -} - -#============================================================= - -=head2 groupMembers - -=head3 INPUT - - $groupname: The group name - -=head3 OUTPUT - - $members: ARRAY reference containing all the user belonging - to the given $groupname - -=head3 DESCRIPTION - - This method gets the group name and returns the users - belonging to it - -=cut - -#============================================================= -sub groupMembers { - my ($self, $groupname) = @_; - - return $groupname if !defined($groupname); - - my $members = $self->ctx->EnumerateUsersByGroup($groupname); - - return $members; -} - - -#============================================================= - -=head2 isPrimaryGroup - -=head3 INPUT - - $groupname: the name of the group - -=head3 OUTPUT - - $username: undef if it is primary group or the username for - which the group is the primary one. - -=head3 DESCRIPTION - - This methods check if the given group name is primary group - for any users belonging to the group - -=cut - -#============================================================= -sub isPrimaryGroup { - my ($self, $groupname) = @_; - - return $groupname if !defined($groupname); - - my $groupEnt = $self->ctx->LookupGroupByName($groupname); - my $members = $self->ctx->EnumerateUsersByGroup($groupname); - foreach my $username (@$members) { - my $userEnt = $self->ctx->LookupUserByName($username); - if ($userEnt && $userEnt->Gid($self->USER_GetValue) == $groupEnt->Gid($self->USER_GetValue)) { - return $username; - } - } - return undef; -} - - -#============================================================= - -=head2 deleteGroup - -=head3 INPUT - - $groupname: in_par_description - -=head3 OUTPUT - - 0: if error occurred - 1: if removed - -=head3 DESCRIPTION - - This method remove the group from the system - -=cut - -#============================================================= -sub deleteGroup { - my ($self, $groupname) = @_; - - return 0 if !defined($groupname); - - my $groupEnt = $self->ctx->LookupGroupByName($groupname); - eval { $self->ctx->GroupDel($groupEnt) }; - return 0 if $@; - - return 1; -} - - - -#============================================================= - -=head2 modifyGroup - -=head3 INPUT - - $groupInfo: HASH reference containing: - old_groupname => old name of the group (if renaming) - groupname => group name - members => users belonging to the group - -=head3 OUTPUT - - $retval => HASH reference - status => 1 (ok) 0 (error) - error => error message if status is 0 - -=head3 DESCRIPTION - - This method modifies the group groupname - -=cut - -#============================================================= -sub modifyGroup { - my ($self, $groupInfo) = @_; - - die "group name is mandatory" if !defined($groupInfo->{groupname}); - - my $groupEnt = defined($groupInfo->{old_groupname}) ? - $self->ctx->LookupGroupByName($groupInfo->{old_groupname}) : - $self->ctx->LookupGroupByName($groupInfo->{groupname}); - - my $orig_groupname = $groupInfo->{groupname}; - if (defined($groupInfo->{old_groupname}) && - $groupInfo->{old_groupname} ne $groupInfo->{groupname}) { - $groupEnt->GroupName($groupInfo->{groupname}); - $orig_groupname = $groupInfo->{old_groupname}; - } - - my $members = $groupInfo->{members}; - my $gid = $groupEnt->Gid($self->USER_GetValue); - my $users = $self->getUsers(); - my @susers = sort(@{$users}); - - foreach my $user (@susers) { - my $uEnt = $self->ctx->LookupGroupByName($user); - if ($uEnt) { - my $ugid = $uEnt->Gid($self->USER_GetValue); - my $m = $self->ctx->EnumerateUsersByGroup($orig_groupname); - if (MDK::Common::DataStructure::member($user, @{$members})) { - if (!ManaTools::Shared::inArray($user, $m)) { - if ($ugid != $gid) { - eval { $groupEnt->MemberName($user, 1) }; - } - } - } - else { - if (ManaTools::Shared::inArray($user, $m)) { - if ($ugid == $gid) { - return { - status => 0, - error =>$self->loc->N("You cannot remove user <%s> from their primary group", $user) - }; - } - else { - eval { $groupEnt->MemberName($user, 2) }; - } - } - } - } - } - - $self->ctx->GroupModify($groupEnt); - - return {status => 1,}; -} - -#============================================================= - -=head2 getGroupsInfo - - $options: HASH reference containing - groupname_filter => groupname search string - filter_system => hides system groups - -=head3 OUTPUT - - $groupsInfo: HASH reference containing - groupname-1 => { - gid => group identifier - members => ARRAY of username - } - groupname-2 => { - ... - } - -=head3 DESCRIPTION - - This method get group information (all groups or the - filtered ones) - -=cut - -#============================================================= -sub getGroupsInfo { - my ($self, $options) = @_; - - my $groupsInfo = {}; - return $groupsInfo if !defined $self->ctx; - - my $strfilt = $options->{groupname_filter} if exists($options->{groupname_filter}); - my $filtergroups = $options->{filter_system} if exists($options->{filter_system}); - - my $groups = $self->ctx->GroupsEnumerateFull; - - my @GroupReal; - LOOP: foreach my $g (@{$groups}) { - my $gid = $g->Gid($self->USER_GetValue); - next LOOP if $filtergroups && $gid <= 499 || $gid == 65534; - if ($filtergroups && $gid > 499 && $gid < $self->min_GID) { - my $groupname = $g->GroupName($self->USER_GetValue); - my $l = $self->ctx->LookupUserByName($groupname); - if (!defined($l)) { - my $members = $self->ctx->EnumerateUsersByGroup($groupname); - next LOOP if !scalar(@{$members}); - foreach my $username (@$members) { - my $userEnt = $self->ctx->LookupUserByName($username); - next LOOP if $userEnt->HomeDir($self->USER_GetValue) =~ /^\/($|var\/|run\/)/ || $userEnt->LoginShell($self->USER_GetValue) =~ /(nologin|false)$/; - } - } - else { - next LOOP if $l->HomeDir($self->USER_GetValue) =~ /^\/($|var\/|run\/)/ || $l->LoginShell($self->USER_GetValue) =~ /(nologin|false)$/; - } - } - push @GroupReal, $g if $g->GroupName($self->USER_GetValue) =~ /^\Q$strfilt/; - } - - foreach my $g (@GroupReal) { - my $groupname = $g->GroupName($self->USER_GetValue); - my $u_b_g = $self->ctx->EnumerateUsersByGroup($groupname); - my $group_id = $g->Gid($self->USER_GetValue); - - $groupsInfo->{"$groupname"} = { - gid => $group_id, - members => $u_b_g, - }; - } - - return $groupsInfo; -} - -#============================================================= - -=head2 getUsers - -=head3 OUTPUT - - $users: ARRAY reference containing all the users - -=head3 DESCRIPTION - - This method return the configured users - -=cut - -#============================================================= -sub getUsers { - my $self = shift; - - return $self->ctx->UsersEnumerate; -} - -#============================================================= - -=head2 getUserInfo - -=head3 INPUT - - $username: user name - -=head3 OUTPUT - - $userInfo: HASH reference containing - { - uid => user identifier - gid => group identifier - fullname => user full name - home => home directory - shell => user shell - expire => shadow expire time - locked => is locked? - exp_min => shadow Min - exp_max => shadow Max - exp_warn => shadow Warn - exp_inact => shadow Inact - last_change => Shadow last change - members => groups the user belongs to - } - -=head3 DESCRIPTION - - This method get all the information for the given user - -=cut - -#============================================================= -sub getUserInfo { - my ($self, $username) = @_; - - my $userInfo = {}; - return $userInfo if !defined $self->ctx; - - my $userEnt = $self->ctx->LookupUserByName($username); - return $userInfo if !defined($userEnt); - - my $fullname = $userEnt->Gecos($self->USER_GetValue); - utf8::decode($fullname); - $userInfo->{fullname} = $fullname; - $userInfo->{shell} = $userEnt->LoginShell($self->USER_GetValue); - $userInfo->{home} = $userEnt->HomeDir($self->USER_GetValue); - $userInfo->{uid} = $userEnt->Uid($self->USER_GetValue); - $userInfo->{gid} = $userEnt->Gid($self->USER_GetValue); - $userInfo->{expire} = $userEnt->ShadowExpire($self->USER_GetValue); - $userInfo->{locked} = $self->ctx->IsLocked($userEnt); - - $userInfo->{exp_min} = $userEnt->ShadowMin($self->USER_GetValue); - $userInfo->{exp_max} = $userEnt->ShadowMax($self->USER_GetValue); - $userInfo->{exp_warn} = $userEnt->ShadowWarn($self->USER_GetValue); - $userInfo->{exp_inact} = $userEnt->ShadowInact($self->USER_GetValue); - $userInfo->{last_change} = $userEnt->ShadowLastChange($self->USER_GetValue); - $userInfo->{members} = $self->ctx->EnumerateGroupsByUser($username); - - return $userInfo; -} - -#============================================================= - -=head2 getUsersInfo - -=head3 INPUT - - $options: HASH reference containing - username_filter => username search string - filter_system => hides system users - -=head3 OUTPUT - - $usersInfo: HASH reference containing - username-1 => { - uid => user identifier - group => primary group name - gid => group identifier - fullname => user full name - home => home directory - shell => user shell - status => login status (locked, expired, etc) - } - username-2 => { - ... - } - -=head3 DESCRIPTION - - This method get user information (all users or filtered ones) - -=cut - -#============================================================= -sub getUsersInfo { - my ($self, $options) = @_; - - my $usersInfo = {}; - return $usersInfo if !defined $self->ctx; - - my $strfilt = $options->{username_filter} if exists($options->{username_filter}); - my $filterusers = $options->{filter_system} if exists($options->{filter_system}); - - my ($users, $group, $groupnm, $expr); - $users = $self->ctx->UsersEnumerateFull; - - my @UserReal; - LOOP: foreach my $l (@{$users}) { - my $uid = $l->Uid($self->USER_GetValue); - next LOOP if $filterusers && $uid <= 499 || $uid == 65534; - next LOOP if $filterusers && $uid > 499 && $uid < $self->min_UID && - ($l->HomeDir($self->USER_GetValue) =~ /^\/($|var\/|run\/)/ || $l->LoginShell($self->USER_GetValue) =~ /(nologin|false)$/); - push @UserReal, $l if $l->UserName($self->USER_GetValue) =~ /^\Q$strfilt/; - } - my $i; - my $itemColl = new yui::YItemCollection; - foreach my $l (@UserReal) { - $i++; - my $uid = $l->Uid($self->USER_GetValue); - if (!defined $uid) { - warn "bogus user at line $i\n"; - next; - } - my $gid = $l->Gid($self->USER_GetValue); - $group = $self->ctx->LookupGroupById($gid); - $groupnm = ''; - $expr = $self->computeLockExpire($l); - $group and $groupnm = $group->GroupName($self->USER_GetValue); - my $fulln = $l->Gecos($self->USER_GetValue); - utf8::decode($fulln); - my $username = $l->UserName($self->USER_GetValue); - my $shell = $l->LoginShell($self->USER_GetValue); - my $homedir = $l->HomeDir($self->USER_GetValue); - $usersInfo->{"$username"} = { - uid => $uid, - group => $groupnm, - gid => $gid, - fullname => $fulln, - home => $homedir, - status => $expr, - shell => $shell, - }; - } - - return $usersInfo; -} - -#============================================================= - -=head2 getUserHome - -=head3 INPUT - - $username: given user name - -=head3 OUTPUT - - $homedir: user home directory - -=head3 DESCRIPTION - - This method return the home directory belonging to the given - username - -=cut - -#============================================================= -sub getUserHome { - my ($self, $username) = @_; - - return $username if !defined($username); - - my $userEnt = $self->ctx->LookupUserByName($username); - my $homedir = $userEnt->HomeDir($self->USER_GetValue); - - return $homedir; -} - -#============================================================= - -=head2 userNameExists - -=head3 INPUT - - $username: the name of the user to check - -=head3 OUTPUT - - if user exists - -=head3 DESCRIPTION - - This method return if a given user exists - -=cut - -#============================================================= -sub userNameExists { - my ($self, $username) = @_; - - return 0 if (!defined($username)); - - return (defined($self->ctx->LookupUserByName($username))); -} - -#============================================================= - -=head2 computeLockExpire - -=head3 INPUT - - $l: login user info - -=head3 OUTPUT - - $status: Locked, Expired, or empty string - -=head3 DESCRIPTION - - This method returns if the login is Locked, Expired or ok. - Note this function is meant for internal use only - -=cut - -#============================================================= -sub computeLockExpire { - my ( $self, $l ) = @_; - my $ep = $l->ShadowExpire($self->USER_GetValue); - my $tm = ceil(time()/(24*60*60)); - $ep = -1 if int($tm) <= $ep; - my $status = $self->ctx->IsLocked($l) ? $self->loc->N("Locked") : ($ep != -1 ? $self->loc->N("Expired") : ''); - return $status; -} - -#============================================================= - -=head2 addUser - -=head3 INPUT - - $params: HASH reference containing: - username => name of teh user to be added - uid => user id of the username to be added - is_system => is a system user? - homedir => user home directory - donotcreatehome => do not create the home directory - shell => user shall - fullname => user full name - gid => group id for the user - shadowMin => min time password validity - shadowMax => max time password validity - shadowInact => - shadowWarn => - password => user password - -=head3 OUTPUT - - 0 if errors 1 if ok - -=head3 DESCRIPTION - - This method add a user to system - -=cut - -#============================================================= -sub addUser { - my ($self, $params) = @_; - - return 0 if !defined($params->{username}); - - my $is_system = defined($params->{is_system}) ? - $params->{is_system} : - 0; - - my $userEnt = $self->ctx->InitUser($params->{username}, $is_system); - return 0 if !defined($userEnt); - - - $userEnt->HomeDir($params->{homedir}) if defined($params->{homedir}); - $userEnt->Uid($params->{uid}) if defined($params->{uid}); - $userEnt->Gecos($params->{fullname}) if defined($params->{fullname}); - $userEnt->LoginShell($params->{shell}) if defined($params->{shell}); - $userEnt->Gid($params->{gid}) if defined ($params->{gid}); - my $shd = defined ($params->{shadowMin}) ? $params->{shadowMin} : -1; - $userEnt->ShadowMin($shd); - $shd = defined ($params->{shadowMax}) ? $params->{shadowMax} : 99999; - $userEnt->ShadowMax($shd); - $shd = defined ($params->{shadowWarn}) ? $params->{shadowWarn} : -1; - $userEnt->ShadowWarn($shd); - $shd = defined ($params->{shadowInact}) ? $params->{shadowInact} : -1; - $userEnt->ShadowInact($shd); - $self->ctx->UserAdd($userEnt, $is_system, $params->{donotcreatehome}); - $self->ctx->UserSetPass($userEnt, $params->{password}); - - return 1; -} - - -#============================================================= - -=head2 modifyUser - -=head3 INPUT - - $userInfo: HASH reference containing: - old_username => old name of the user (if renaming) - username => user name - fullname => full name of teh user - password => password - homedir => home directory - shell => user shell - members => groups the user belongs to - gid => primary group identifier - lockuser => lock user - acc_expires => account expire time - containing: - exp_y => year - exp_m => month - exp_d => day - password_expires => password expire time - containing: - exp_min => min - exp_max => max - exp_warn => when warn - exp_inact => when inactive - -=head3 DESCRIPTION - - This method modifies the group groupname - -=cut - -#============================================================= -sub modifyUser { - my ($self, $userInfo) = @_; - - die "user name is mandatory" if !defined($userInfo->{username}); - die "primary group identifier is mandatory" if !defined($userInfo->{gid}); - die "a valid group identifier is mandatory" if $userInfo->{gid} < 0; - - if (defined($userInfo->{acc_expires})) { - die "expiring year is mandatory" if !defined($userInfo->{acc_expires}->{exp_y}); - die "expiring month is mandatory" if !defined($userInfo->{acc_expires}->{exp_m}); - die "expiring day is mandatory" if !defined($userInfo->{acc_expires}->{exp_d}); - } - if (defined($userInfo->{password_expires})) { - die "password expiring min is mandatory" if !($userInfo->{password_expires}->{exp_min}); - die "password expiring max is mandatory" if !($userInfo->{password_expires}->{exp_max}); - die "password expiring warn is mandatory" if !($userInfo->{password_expires}->{exp_warn}); - die "password expiring inactive is mandatory" if !($userInfo->{password_expires}->{exp_inact}); - } - my $userEnt = defined($userInfo->{old_username}) ? - $self->ctx->LookupUserByName($userInfo->{old_username}) : - $self->ctx->LookupUserByName($userInfo->{username}); - - my $orig_username = $userInfo->{username}; - if (defined($userInfo->{old_username}) && - $userInfo->{old_username} ne $userInfo->{username}) { - $userEnt->UserName($userInfo->{username}); - $orig_username = $userInfo->{old_username}; - } - - # $userEnt->UserName($userInfo->{username}); - $userEnt->Gecos($userInfo->{fullname}) if defined($userInfo->{fullname}); - $userEnt->HomeDir($userInfo->{homedir}) if defined($userInfo->{homedir}); - $userEnt->LoginShell($userInfo->{shell}) if defined($userInfo->{shell}); - - - my $username = $userEnt->UserName($self->USER_GetValue); - my $grps = $self->getGoups(); - my @sgroups = sort @{$grps}; - - my $members = $userInfo->{members}; - foreach my $group (@sgroups) { - my $gEnt = $self->ctx->LookupGroupByName($group); - my $ugid = $gEnt->Gid($self->USER_GetValue); - my $m = $gEnt->MemberName(1,0); - if (MDK::Common::DataStructure::member($group, @$members)) { - if (!ManaTools::Shared::inArray($username, $m) && $userInfo->{gid} != $ugid) { - eval { $gEnt->MemberName($username, 1) }; - $self->ctx->GroupModify($gEnt); - } - } - else { - if (ManaTools::Shared::inArray($username, $m)) { - eval { $gEnt->MemberName($username, 2) }; - $self->ctx->GroupModify($gEnt); - } - } - } - - $userEnt->Gid($userInfo->{gid}) if defined($userInfo->{gid}); - - if (defined($userInfo->{acc_expires})) { - my $yr = $userInfo->{acc_expires}->{exp_y}; - my $mo = $userInfo->{acc_expires}->{exp_m}; - my $dy = $userInfo->{acc_expires}->{exp_d}; - my $Exp = _ConvTime($dy, $mo, $yr); - $userEnt->ShadowExpire($Exp); - } - else { - $userEnt->ShadowExpire(ceil(-1)) - } - if (defined($userInfo->{password_expires})) { - my $allowed = $userInfo->{password_expires}->{exp_min}; - my $required = $userInfo->{password_expires}->{exp_max}; - my $warning = $userInfo->{password_expires}->{exp_warn}; - my $inactive = $userInfo->{password_expires}->{exp_inact}; - $userEnt->ShadowMin($allowed); - $userEnt->ShadowMax($required); - $userEnt->ShadowWarn($warning); - $userEnt->ShadowInact($inactive); - } - else { - $userEnt->ShadowMin(-1); - $userEnt->ShadowMax(99999); - $userEnt->ShadowWarn(-1); - $userEnt->ShadowInact(-1); - } - - $self->ctx->UserSetPass($userEnt, $userInfo->{password}) if defined($userInfo->{password}); - $self->ctx->UserModify($userEnt); - - if ($userInfo->{lockuser}) { - !$self->ctx->IsLocked($userEnt) and $self->ctx->Lock($userEnt); - } - else { - $self->ctx->IsLocked($userEnt) and $self->ctx->UnLock($userEnt); - } - - return 1; -} - - -#============================================================= - -=head2 deleteUser - -=head3 INPUT - - $username: username to be deleted - $options: HASH reference containing - clean_home => if home has to be removed - clean_spool => if sppol has to be removed - -=head3 OUTPUT - - error string or undef if no errors occurred - -=head3 DESCRIPTION - - This method delete a user from the system. - -=cut - -#============================================================= -sub deleteUser { - my ($self, $username, $options) = @_; - - return $username if !defined($username); - - my $userEnt = $self->ctx->LookupUserByName($username); - - $self->ctx->UserDel($userEnt); - $self->updateOrDelUserInGroup($username); - #Let's check out the user's primary group - my $usergid = $userEnt->Gid($self->USER_GetValue); - my $groupEnt = $self->ctx->LookupGroupById($usergid); - if ($groupEnt) { - my $member = $groupEnt->MemberName(1, 0); - # TODO check if 499 is ok nowadays - if (scalar(@$member) == 0 && $groupEnt->Gid($self->USER_GetValue) > 499) { - $self->ctx->GroupDel($groupEnt); - } - } - if (defined($options)) { - ## testing jusr if exists also undef is allowed - ## as valid option - if (exists($options->{clean_home})) { - eval { $self->ctx->CleanHome($userEnt) }; - return $@ if $@; - } - if (exists($options->{clean_spool})) { - eval { $self->ctx->CleanSpool($userEnt) }; - return $@ if $@; - } - } - return undef; -} - -#============================================================= - -=head2 getUserShells - - -=head3 OUTPUT - - GetUserShells: from libUSER - -=head3 DESCRIPTION - - This method returns the available shell - -=cut - -#============================================================= - -sub getUserShells { - my $self = shift; - - return $self->ctx->GetUserShells; -} -#============================================================= - -=head2 GetFaceIcon - -=head3 INPUT - - $name: icon name for the given username - $next: if passed means getting next icon from the given $name - -=head3 OUTPUT - - $user_icon: icon name - -=head3 DESCRIPTION - - This method returns the icon for the given user ($name) or the - following one if $next is passed - -=cut - -#============================================================= -sub GetFaceIcon { - my ($self, $name, $next) = @_; - my $icons = $self->facenames(); - my $i; - my $current_icon; - # remove shortcut "&" from label - $name =~ s/&// if ($name); - my $user_icon = $self->user_face_dir . $name . ".png" if ($name); - if ($name) { - $user_icon = $self->face2png($name) unless(-e $user_icon); - } - if ($name && -e $user_icon) { - my $current_md5 = ManaTools::Shared::md5sum($user_icon); - my $found = 0; - for ($i = 0; $i < scalar(@$icons); $i++) { - if (ManaTools::Shared::md5sum($self->face2png($icons->[$i])) eq $current_md5) { - $found = 1; - last; - } - } - if ($found) { #- current icon found in @icons, select it - $current_icon = $icons->[$i]; - } else { #- add and select current icon in @icons - push @$icons, $user_icon; - $current_icon = $user_icon; - $i = scalar(@$icons) - 1; - } - } else { - #- no icon yet, select a random one - $current_icon = $icons->[$i = rand(scalar(@$icons))]; - } - - if ($next) { - $current_icon = $icons->[$i = defined $icons->[$i+1] ? $i+1 : 0]; - } - return $current_icon; -} - - -#============================================================= - -=head2 strongPassword - -=head3 INPUT - - $passwd: password to be checked - -=head3 OUTPUT - - 1: if password is strong - 0: if password is weak - -=head3 DESCRIPTION - - Check for a strong password - -=cut - -#============================================================= -sub strongPassword { - my ($self, $passwd, $threshold) = @_; - - return 0 if !$passwd; - - my $pwdm = $threshold ? Data::Password::Meter->new($threshold) : Data::Password::Meter->new(); - - # Check a password - return $pwdm->strong($passwd); -} - - -# TODO methods not tested in Users.t - -#============================================================= - -=head2 weakPasswordForSecurityLevel - -=head3 INPUT - - $passwd: password to check - -=head3 OUTPUT - - 1: if the password is too weak for security level - -=head3 DESCRIPTION - - Check the security level set if /etc/security/msec/security.conf - exists and the level is not 'standard' and if the password - is not at least 6 characters return true - -=cut - -#============================================================= -sub weakPasswordForSecurityLevel { - my ($self, $passwd) = @_; - - my $sec_conf_file = "/etc/security/msec/security.conf"; - if (-e $sec_conf_file) { - my $prefs = Config::Auto::parse($sec_conf_file); - my $level = $prefs->{BASE_LEVEL}; - if ($level eq 'none' or $level eq 'standard') { - return 0; - } - elsif (length($passwd) < 6) { - return 1; - } - } - - return 0; -} - - -#============================================================= - -=head2 Add2UsersGroup - -=head3 INPUT - - $name: username - -=head3 OUTPUT - - $gid: group id - -=head3 DESCRIPTION - - Adds the given username $name to 'users' group - -=cut - -#============================================================= -sub Add2UsersGroup { - my ($self, $name) = @_; - - my $usersgroup = $self->ctx->LookupGroupByName('users'); - $usersgroup->MemberName($name, 1); - return $usersgroup->Gid($self->USER_GetValue); -} - -sub _ConvTime { - my ($day, $month, $year) = @_; - my ($tm, $days, $mon, $yr); - $mon = $month - 1; $yr = $year - 1900; - $tm = POSIX::mktime(0, 0, 0, $day, $mon, $yr); - $days = ceil($tm / (24 * 60 * 60)); - return $days; -} - -no Moose; -__PACKAGE__->meta->make_immutable; - -1; diff --git a/lib/AdminPanel/rpmdragora.pm b/lib/AdminPanel/rpmdragora.pm deleted file mode 100644 index ecdf06f..0000000 --- a/lib/AdminPanel/rpmdragora.pm +++ /dev/null @@ -1,1165 +0,0 @@ -# vim: set et ts=4 sw=4: -#***************************************************************************** -# -# Copyright (c) 2002 Guillaume Cottenceau -# Copyright (c) 2002-2007 Thierry Vignaud -# Copyright (c) 2003, 2004, 2005 MandrakeSoft SA -# Copyright (c) 2005, 2007 Mandriva SA -# Copyright (c) 2013 - 2015 Matteo Pasotti -# -# 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. -# -#***************************************************************************** -# -# $Id: rpmdragora.pm 267936 2010-04-26 16:40:21Z jvictor $ - -package ManaTools::rpmdragora; -use warnings::register; - -use urpm; -use urpm::cfg; -use urpm::mirrors; -use urpm::download (); -use urpm::prompt; -use urpm::media; - -# quick fix for mirror.pm -use lib qw(/usr/lib/libDrakX); - -use MDK::Common; -use MDK::Common::System; -use MDK::Common::String; -use MDK::Common::Func; -use MDK::Common::File qw(basename cat_ output); -use URPM; -use URPM::Resolve; -use strict; -use POSIX qw(_exit); - -use feature 'state'; - -use ManaTools::Shared; -use ManaTools::Shared::Locales; -use ManaTools::Shared::GUI; - -use Carp; - -our @ISA = qw(Exporter); -our @EXPORT = qw( - $changelog_first_config - $compute_updates - $filter - $dont_show_selections - $ignore_debug_media - $mandrakeupdate_wanted_categories - $mandrivaupdate_height - $mandrivaupdate_width - $max_info_in_descr - $mode - $NVR_searches - $offered_to_add_sources - $rpmdragora_height - $rpmdragora_width - $tree_flat - $tree_mode - $use_regexp - $typical_width - $clean_cache - $auto_select - locale - add_distrib_update_media - add_medium_and_check - but - but_ - check_update_media_version - choose_mirror - distro_type - fatal_msg - getbanner - get_icon - interactive_list - interactive_list_ - interactive_msg - myexit - readconf - remove_wait_msg - run_drakbug - show_urpm_progress - slow_func - slow_func_statusbar - statusbar_msg - statusbar_msg_remove - strip_first_underscore - update_sources - update_sources_check - update_sources_interactive - update_sources_noninteractive - wait_msg - warn_for_network_need - writeconf -); -our $typical_width = 280; - -our $dont_show_selections; - -# i18n: IMPORTANT: to get correct namespace (rpmdragora instead of libDrakX) -BEGIN { unshift @::textdomains, qw(rpmdragora urpmi rpm-summary-main rpm-summary-contrib rpm-summary-devel rpm-summary-non-free) } - -use yui; -use Glib; -#ugtk2::add_icon_path('/usr/share/rpmdragora/icons'); - -# Locale::gettext::bind_textdomain_codeset('rpmdragora', 'UTF8'); -my $loc = ManaTools::Shared::Locales->new(domain_name => 'rpmdrake');; - -our $mageia_release = MDK::Common::File::cat_( - -e '/etc/mageia-release' ? '/etc/mageia-release' : '/etc/release' -) || ''; -chomp $mageia_release; -our ($distro_version) = $mageia_release =~ /(\d+\.\d+)/; -our ($branded, %distrib); -$branded = -f '/etc/sysconfig/oem' - and %distrib = MDK::Common::System::distrib(); -our $myname_update = $branded ? $loc->N_("Software Update") : $loc->N_("Mageia Update"); - -@rpmdragora::prompt::ISA = 'urpm::prompt'; - - -sub locale() { - - if (!defined($loc)) { - $loc = ManaTools::Shared::Locales->new(domain_name => 'rpmdrake'); - } - - return $loc; -} - -sub rpmdragora::prompt::prompt { - my ($self) = @_; - my @answers; - my $d = ugtk2->new("", grab => 1, if_($::main_window, transient => $::main_window)); - $d->{rwindow}->set_position('center_on_parent'); - gtkadd( - $d->{window}, - gtkpack( - Gtk2::VBox->new(0, 5), - Gtk2::WrappedLabel->new($self->{title}), - (map { gtkpack( - Gtk2::HBox->new(0, 5), - Gtk2::Label->new($self->{prompts}[$_]), - $answers[$_] = gtkset_visibility(gtkentry(), !$self->{hidden}[$_]), - ) } 0 .. $#{$self->{prompts}}), - gtksignal_connect(Gtk2::Button->new($loc->N("Ok")), clicked => sub { Gtk2->main_quit }), - ), - ); - $d->main; - map { $_->get_text } @answers; -} - -$urpm::download::PROMPT_PROXY = new rpmdragora::prompt( - $loc->N_("Please enter your credentials for accessing proxy\n"), - [ $loc->N_("User name:"), $loc->N_("Password:") ], - undef, - [ 0, 1 ], -); - -sub myexit { - writeconf(); - destroy $::main_window if $::main_window; - exit @_; -} - -my ($root) = grep { $_->[2] == 0 } list_passwd(); -$ENV{HOME} = $> == 0 ? $root->[7] : $ENV{HOME} || '/root'; -$ENV{HOME} = $::env if $::env = $ManaTools::Rpmdragora::init::rpmdragora_options{env}[0]; - -our $configfile = "$ENV{HOME}/.rpmdragora"; - -# -# Configuration File Options -# - -# clear download cache after successfull installation of packages -our $clean_cache; - -# automatic select dependencies without user intervention -our $auto_select; - -our ($changelog_first_config, $compute_updates, $filter, $max_info_in_descr, $mode, $NVR_searches, $tree_flat, $tree_mode, $use_regexp); -our ($mandrakeupdate_wanted_categories, $ignore_debug_media, $offered_to_add_sources, $no_confirmation); -our ($rpmdragora_height, $rpmdragora_width, $mandrivaupdate_height, $mandrivaupdate_width); - -our %config = ( - clean_cache => { - var => \$clean_cache, - default => [ 0 ] - }, - auto_select => { - var => \$auto_select, - default => [ 0 ] - }, - changelog_first_config => { var => \$changelog_first_config, default => [ 0 ] }, - compute_updates => { var => \$compute_updates, default => [ 1 ] }, - dont_show_selections => { var => \$dont_show_selections, default => [ $> ? 1 : 0 ] }, - filter => { var => \$filter, default => [ 'all' ] }, - ignore_debug_media => { var => \$ignore_debug_media, default => [ 0 ] }, - mandrakeupdate_wanted_categories => { var => \$mandrakeupdate_wanted_categories, default => [ qw(security) ] }, - mandrivaupdate_height => { var => \$mandrivaupdate_height, default => [ 0 ] }, - mandrivaupdate_width => { var => \$mandrivaupdate_width, default => [ 0 ] }, - max_info_in_descr => { var => \$max_info_in_descr, default => [] }, - mode => { var => \$mode, default => [ 'by_group' ] }, - NVR_searches => { var => \$NVR_searches, default => [ 0 ] }, - 'no-confirmation' => { var => \$no_confirmation, default => [ 0 ] }, - offered_to_add_sources => { var => \$offered_to_add_sources, default => [ 0 ] }, - rpmdragora_height => { var => \$rpmdragora_height, default => [ 0 ] }, - rpmdragora_width => { var => \$rpmdragora_width, default => [ 0 ] }, - tree_flat => { var => \$tree_flat, default => [ 0 ] }, - tree_mode => { var => \$tree_mode, default => [ qw(gui_pkgs) ] }, - use_regexp => { var => \$use_regexp, default => [ 0 ] }, -); - -sub readconf() { - ${$config{$_}{var}} = $config{$_}{default} foreach keys %config; - foreach my $l (MDK::Common::File::cat_($configfile)) { - my ($key, @values) = split ' ', $l; - ${$config{$key}{var}} = \@values if scalar @values; - } - # special cases: - $::rpmdragora_options{'no-confirmation'} = $no_confirmation->[0] if !defined $::rpmdragora_options{'no-confirmation'}; - $ManaTools::Rpmdragora::init::default_list_mode = $tree_mode->[0] if ref $tree_mode && !$ManaTools::Rpmdragora::init::overriding_config; -} - -sub writeconf() { - return if $::env; - unlink $configfile; - - # special case: - $no_confirmation->[0] = $::rpmdragora_options{'no-confirmation'}; - my @config_content = map { "$_ " . (ref ${$config{$_}{var}} ? join(' ', @${$config{$_}{var}}) : '') . "\n" } sort keys %config; - MDK::Common::File::output($configfile, @config_content); - print "writeconf done!\n"; -} - -sub getbanner() { - $::MODE or return undef; - if (0) { - +{ - remove => $loc->N("Software Packages Removal"), - update => $loc->N("Software Packages Update"), - install => $loc->N("Software Packages Installation"), - }; - } -# Gtk2::Banner->new($ugtk2::wm_icon, $::MODE eq 'update' ? $loc->N("Software Packages Update") : $loc->N("Software Management")); -} - - -#============================================================= - -=head2 interactive_msg - -=head3 INPUT - - $title: dialog title - $contents: dialog text - %options: optional HASH containing { - scroll => Rich Text with scroll bar used - yesno => dialog with "yes" and "no" buttons (deafult yes) - dont_ask_again => add a checkbox with "dont ask again text" - main_dialog => create a main dialog instead of a popup one - min_size => {columns => X, lines => Y} for minimum dialog size, - } - -=head3 OUTPUT - - retval: if dont_ask_again HASH reference containig { - value => 1 yes (or ok) pressed, 0 no pressed - dont_ask_again => 1 if checked - } - or if dont_ask_again is not passed: - 1 yes (or ok) pressed, 0 no pressed - -=head3 DESCRIPTION - - This function shows a dialog with contents text and return the button - pressed (1 ok or yes), optionally returns the checkbox value if dont_ask_again is - passed. - If min_size is passed a minimum dialog size is set (default is 75x6) see libyui - createMinSize documenatation for explanation. - -=cut - -#============================================================= -sub interactive_msg { - my ($title, $contents, %options) = @_; - - my $retVal = 0; - - my $info; - - if ($options{scroll}) { - ## richtext needs
instead of '\n' - $contents =~ s/\n/
/g; - } - - my $oldTitle = yui::YUI::app()->applicationTitle(); - yui::YUI::app()->setApplicationTitle($title); - - my $factory = yui::YUI::widgetFactory; - my $dlg = $options{main_dialog} ? - $factory->createMainDialog() : - $factory->createPopupDialog(); - my $columns = $options{min_size}->{columns} || 75; - my $lines = $options{min_size}->{lines} || 6; - my $minSize = $factory->createMinSize( $dlg, $columns, $lines); - my $vbox = $factory->createVBox( $minSize ); - my $midhbox = $factory->createHBox($vbox); - ## app description - my $toprightvbox = $factory->createVBox($midhbox); - $toprightvbox->setWeight($yui::YD_HORIZ, 5); - $factory->createSpacing($toprightvbox,$yui::YD_HORIZ, 0, 5.0); - $factory->createRichText($toprightvbox, $contents, !$options{scroll}); - $factory->createSpacing($toprightvbox, $yui::YD_HORIZ, 0, 5.0); - - if ($options{dont_ask_again}){ - my $hbox = $factory->createHBox($vbox); - my $align = $factory->createRight($hbox); - $info->{checkbox} = $factory->createCheckBox($align, $loc->N("Do not ask me next time")); - } - - my $bottomhbox = $factory->createHBox($vbox); - if ($options{yesno}) { - my $alignRight = $factory->createRight($bottomhbox); - my $buttonBox = $factory->createHBox($alignRight); - - $info->{B1} = $factory->createPushButton($buttonBox, $options{text}{yes} || $loc->N("Yes")); - $info->{B2} = $factory->createPushButton($buttonBox, $options{text}{no} || $loc->N("No")); - } - else { - $info->{B1} = $factory->createPushButton($bottomhbox, $loc->N("Ok")); - } - - $dlg->setDefaultButton($info->{B1}); - - while (1) { - my $event = $dlg->waitForEvent(); - my $eventType = $event->eventType(); - #event type checking - if ($eventType == $yui::YEvent::CancelEvent) { - $retVal = 1; ##default value - last; - } - elsif ($eventType == $yui::YEvent::WidgetEvent) { - # widget selected - my $widget = $event->widget(); - - if ($info->{B1} && $widget == $info->{B1}) { - $retVal = 1; - last; - } - elsif ($info->{B2} && $widget == $info->{B2}) { - last; - } - } - } - - if ($info->{checkbox}) { - my $value = $retVal; - $retVal = undef; - $retVal->{value} = $value; - $retVal->{dont_ask_again} = $info->{checkbox}->isChecked(); - } - - $dlg->destroy(); - yui::YUI::app()->setApplicationTitle($oldTitle); - - return $retVal; -} - -sub interactive_list { - my ($title, $contents, $list, $callback, %options) = @_; - - my $factory = yui::YUI::widgetFactory; - my $mainw = $factory->createPopupDialog(); - my $vbox = $factory->createVBox($mainw); - my $lbltitle = $factory->createLabel($vbox, $loc->N("Dependencies")); - my $left = $factory->createLeft($factory->createHBox($vbox)); - my $radiobuttongroup = $factory->createRadioButtonGroup($left); - my $rbbox = $factory->createVBox($radiobuttongroup); - foreach my $item (@$list) { - my $radiobutton = $factory->createRadioButton($rbbox,$item); - if ($item eq $list->[0]) { - # select first by default - $radiobutton->setValue(1); - } - $radiobutton->setNotify(0); - $radiobuttongroup->addRadioButton($radiobutton); - } - my $submitButton = $factory->createIconButton($vbox,"", $loc->N("OK")); - my $choice; - - while(1) { - my $event = $mainw->waitForEvent(); - my $eventType = $event->eventType(); - #event type checking - if ($eventType == $yui::YEvent::CancelEvent) { - $mainw->destroy(); - last; - } - elsif ($eventType == $yui::YEvent::WidgetEvent) { - # widget selected - my $widget = $event->widget(); - - if($widget == $submitButton) { - # NOTE if for any reason radio button is not checked let's take the first package - $choice = $radiobuttongroup->currentButton() ? $radiobuttongroup->currentButton()->label() : $list->[0]; - $choice =~s/\&//g; - last; - } - } - } - $mainw->destroy(); - return $choice; -} - -sub interactive_list_ { interactive_list(@_, if_($::main_window, transient => $::main_window)) } - -sub fatal_msg { - interactive_msg @_; - myexit -1; -} - -sub wait_msg { - my $msg = shift; - - my $label = $msg ? $msg : $loc->N("Please wait"); - - my $factory = yui::YUI::widgetFactory; - my $mainw = $factory->createPopupDialog(); - my $vbox = $factory->createVBox($mainw); - my $title = $factory->createLabel($vbox, $label); - #$mainw->recalcLayout(); - #$mainw->doneMultipleChanges(); - $mainw->waitForEvent(10); - $mainw->pollEvent(); - #$mainw->recalcLayout(); - #$mainw->doneMultipleChanges(); - yui::YUI::app()->busyCursor(); - - $mainw; -} - -sub remove_wait_msg { - my $w = shift; - #gtkset_mousecursor_normal($w->{rwindow}->window); - $w->destroy; - yui::YUI::app()->normalCursor(); -} - -sub but { " $_[0] " } -sub but_ { " $_[0] " } - -#============================================================= - -=head2 slow_func - -=head3 INPUT - - $func: function to be executed with a busy cursor or waiting - dialog - $msg: message to be shown in ncurses waiting dialog (if any) - -=head3 DESCRIPTION - - This function executes a given function with a busy cursor set - in graphical environment, or with a waiting dialog if in ncurses - text mode - -=cut - -#============================================================= -sub slow_func (&) { - my ($func, $msg) = @_; - - my $retval = 1; - # NOTE busy cursor is not implemented in yui-ncurses - # but we can avoid a waiting dialog in Gtk and QT - if (yui::YUI::app()->isTextMode()) { - my $w = wait_msg($msg); - $retval = $func->(); - remove_wait_msg($w) - } - else { - yui::YUI::app()->busyCursor(); - $retval = $func->(); - yui::YUI::app()->normalCursor(); - } - return $retval; -} - -sub statusbar_msg { - my ($msg, $o_timeout) = @_; - - unless ($::statusbar) { #- fallback if no status bar - return wait_msg($msg); - } - - $::statusbar->setLabel($msg); - #- always use the same context description for now - #my $cx = $::statusbar->get_context_id("foo"); - #$::w and $::w->{rwindow} and gtkset_mousecursor_wait($::w->{rwindow}->window); - #- returns a msg_id to be passed optionnally to statusbar_msg_remove - #my $id = $::statusbar->push($cx, $msg); - #gtkflush(); - #Glib::Timeout->add(5000, sub { statusbar_msg_remove($id); 0 }) if $o_timeout; - $::statusbar->setTimeout ( 5000 ); - Glib::Timeout->add(5000, sub { statusbar_msg_remove(); 0 }) if $o_timeout; - #$id; - return 1; -} - -sub statusbar_msg_remove { - if (!$::statusbar) { #- fallback if no status bar - my $id = shift; - return remove_wait_msg($id);; - } - my ($msg_id) = @_; - #my $cx = $::statusbar->get_context_id("foo"); - #if (defined $msg_id) { - #$::statusbar->remove($cx, $msg_id); - #} else { - #$::statusbar->pop($cx); - #} - #$::w and $::w->{rwindow} and gtkset_mousecursor_normal($::w->{rwindow}->window); - $::statusbar->setLabel(""); -} - -sub slow_func_statusbar ($$&) { - my ($msg, $w, $func) = @_; - yui::YUI::app()->busyCursor(); - - my $msg_id = statusbar_msg($msg); - $func->(); - statusbar_msg_remove($msg_id); - - yui::YUI::app()->normalCursor(); -} - -my %u2l = ( - ar => $loc->N_("Argentina"), - at => $loc->N_("Austria"), - au => $loc->N_("Australia"), - by => $loc->N_("Belarus"), - be => $loc->N_("Belgium"), - br => $loc->N_("Brazil"), - gb => $loc->N_("Britain"), - ca => $loc->N_("Canada"), - ch => $loc->N_("Switzerland"), - cr => $loc->N_("Costa Rica"), - cz => $loc->N_("Czech Republic"), - de => $loc->N_("Germany"), - dk => $loc->N_("Danmark"), - ec => $loc->N_("Ecuador"), - el => $loc->N_("Greece"), - es => $loc->N_("Spain"), - fi => $loc->N_("Finland"), - fr => $loc->N_("France"), - gr => $loc->N_("Greece"), - hu => $loc->N_("Hungary"), - id => $loc->N_("Indonesia"), - il => $loc->N_("Israel"), - it => $loc->N_("Italy"), - jp => $loc->N_("Japan"), - ko => $loc->N_("Korea"), - nl => $loc->N_("Netherlands"), - no => $loc->N_("Norway"), - pl => $loc->N_("Poland"), - pt => $loc->N_("Portugal"), - ru => $loc->N_("Russia"), - se => $loc->N_("Sweden"), - sg => $loc->N_("Singapore"), - sk => $loc->N_("Slovakia"), - za => $loc->N_("South Africa"), - tw => $loc->N_("Taiwan"), - th => $loc->N_("Thailand"), - tr => $loc->N_("Turkey"), - uk => $loc->N_("United Kingdom"), - cn => $loc->N_("China"), - us => $loc->N_("United States"), - com => $loc->N_("United States"), - org => $loc->N_("United States"), - net => $loc->N_("United States"), - edu => $loc->N_("United States"), -); -my $us = [ qw(us com org net edu) ]; -my %t2l = ( - 'America/\w+' => $us, - 'Asia/Tel_Aviv' => [ qw(il ru it cz at de fr se) ], - 'Asia/Tokyo' => [ qw(jp ko tw), @$us ], - 'Asia/Seoul' => [ qw(ko jp tw), @$us ], - 'Asia/Taipei' => [ qw(tw jp), @$us ], - 'Asia/(Shanghai|Beijing)' => [ qw(cn tw sg), @$us ], - 'Asia/Singapore' => [ qw(cn sg), @$us ], - 'Atlantic/Reykjavik' => [ qw(gb uk no se fi dk), @$us, qw(nl de fr at cz it) ], - 'Australia/\w+' => [ qw(au jp ko tw), @$us ], - 'Brazil/\w+' => [ 'br', @$us ], - 'Canada/\w+' => [ 'ca', @$us ], - 'Europe/Amsterdam' => [ qw(nl be de at cz fr se dk it) ], - 'Europe/Athens' => [ qw(gr pl cz de it nl at fr) ], - 'Europe/Berlin' => [ qw(de be at nl cz it fr se) ], - 'Europe/Brussels' => [ qw(be de nl fr cz at it se) ], - 'Europe/Budapest' => [ qw(cz it at de fr nl se) ], - 'Europe/Copenhagen' => [ qw(dk nl de be se at cz it) ], - 'Europe/Dublin' => [ qw(gb uk fr be nl dk se cz it) ], - 'Europe/Helsinki' => [ qw(fi se no nl be de fr at it) ], - 'Europe/Istanbul' => [ qw(il ru it cz it at de fr nl se) ], - 'Europe/Lisbon' => [ qw(pt es fr it cz at de se) ], - 'Europe/London' => [ qw(gb uk fr be nl de at cz se it) ], - 'Europe/Madrid' => [ qw(es fr pt it cz at de se) ], - 'Europe/Moscow' => [ qw(ru de pl cz at se be fr it) ], - 'Europe/Oslo' => [ qw(no se fi dk de be at cz it) ], - 'Europe/Paris' => [ qw(fr be de at cz nl it se) ], - 'Europe/Prague' => [ qw(cz it at de fr nl se) ], - 'Europe/Rome' => [ qw(it fr cz de at nl se) ], - 'Europe/Stockholm' => [ qw(se no dk fi nl de at cz fr it) ], - 'Europe/Vienna' => [ qw(at de cz it fr nl se) ], -); - -#- get distrib release number (2006.0, etc) -sub etc_version() { - (my $v) = split / /, MDK::Common::File::cat_('/etc/version'); - return $v; -} - -#- returns the keyword describing the type of the distribution. -#- the parameter indicates whether we want base or update sources -sub distro_type { - my ($want_base_distro) = @_; - return 'cauldron' if $mageia_release =~ /cauldron/i; - #- we can't use updates for community while official is not out (release ends in ".0") - if ($want_base_distro || $mageia_release =~ /community/i && etc_version() =~ /\.0$/) { - return 'official' if $mageia_release =~ /official|limited/i; - return 'community' if $mageia_release =~ /community/i; - #- unknown: fallback to updates - } - return 'updates'; -} - -sub compat_arch_for_updates($) { - # FIXME: We prefer 64-bit packages to update on biarch platforms, - # since the system is populated with 64-bit packages anyway. - my ($arch) = @_; - return $arch =~ /x86_64|amd64/ if arch() eq 'x86_64'; - MDK::Common::System::compat_arch($arch); -} - -sub add_medium_and_check { - my ($urpm, $options) = splice @_, 0, 2; - my @newnames = ($_[0]); #- names of added media - my $fatal_msg; - my @error_msgs; - local $urpm->{fatal} = sub { printf STDERR "Fatal: %s\n", $_[1]; $fatal_msg = $_[1]; goto fatal_error }; - local $urpm->{error} = sub { printf STDERR "Error: %s\n", $_[0]; push @error_msgs, $_[0] }; - if ($options->{distrib}) { - @newnames = urpm::media::add_distrib_media($urpm, @_); - } else { - urpm::media::add_medium($urpm, @_); - } - if (@error_msgs) { - interactive_msg( - $loc->N("Error"), - $loc->N("Unable to add medium, errors reported:\n\n%s", - join("\n", map { MDK::Common::String::formatAlaTeX($_) } @error_msgs)) . "\n\n" . $loc->N("Medium: ") . "$_[0] ($_[1])", - scroll => 1, - ); - return 0; - } - - foreach my $name (@newnames) { - urpm::download::set_proxy_config($_, $options->{proxy}{$_}, $name) foreach keys %{$options->{proxy} || {}}; - } - - if (update_sources_check($urpm, $options, $loc->N_("Unable to add medium, errors reported:\n\n%s"), @newnames)) { - urpm::media::write_config($urpm); - $options->{proxy} and urpm::download::dump_proxy_config(); - } else { - urpm::media::read_config($urpm, 0); - return 0; - } - - my %newnames; @newnames{@newnames} = (); - if (any { exists $newnames{$_->{name}} } @{$urpm->{media}}) { - return 1; - } else { - interactive_msg($loc->N("Error"), $loc->N("Unable to create medium.")); - return 0; - } - - fatal_error: - interactive_msg($loc->N("Failure when adding medium"), - $loc->N("There was a problem adding medium:\n\n%s", $fatal_msg)); - return 0; -} - -sub update_sources_check { - my ($urpm, $options, $error_msg, @media) = @_; - my @error_msgs; - local $urpm->{fatal} = sub { push @error_msgs, $_[1]; goto fatal_error }; - local $urpm->{error} = sub { push @error_msgs, $_[0] }; - update_sources($urpm, %$options, noclean => 1, medialist => \@media); - fatal_error: - if (@error_msgs) { - interactive_msg($loc->N("Error"), $loc->N($error_msg, join("\n", map { formatAlaTeX($_) } @error_msgs)), scroll => 1); - return 0; - } - return 1; -} - -sub update_sources { - my ($urpm, %options) = @_; - my $cancel = 0; - - - my $factory = yui::YUI::widgetFactory; - - ## set new title to get it in dialog - yui::YUI::app()->setApplicationTitle($loc->N("rpmdragora")); - - my $dlg = $factory->createPopupDialog(); - my $minSize = $factory->createMinSize( $dlg, 80, 5 ); - my $vbox = $factory->createVBox($minSize); - my $hbox = $factory->createHBox($factory->createLeft($vbox)); - my $label = $factory->createRichText($hbox, $loc->N("Please wait, updating media..."), 1 ); - $label->setWeight($yui::YD_HORIZ, 1); - $label->setWeight($yui::YD_VERT, 1); - - my $pb = $factory->createProgressBar( $vbox, ""); - $pb->setValue(0); - # NOTE urpm::media::update_those_media seems not to say anything - # when downloads and tests md5sum - # a fake event (timeout 10 msec) allow to draw the waiting - # dialog - $dlg->waitForEvent(10); - $dlg->pollEvent(); - - my @media; @media = @{$options{medialist}} if ref $options{medialist}; - my $outerfatal = $urpm->{fatal}; - local $urpm->{fatal} = sub { $outerfatal->(@_) }; - urpm::media::update_those_media($urpm, [ urpm::media::select_media_by_name($urpm, \@media) ], - %options, allow_failures => 1, - callback => sub { - $cancel and goto cancel_update; - my ($type, $media) = @_; - goto cancel_update if $type !~ /^(?:start|progress|end)$/ && @media && !member($media, @media); - if ($type eq 'failed') { - $urpm->{fatal}->($loc->N("Error retrieving packages"), -$loc->N("It's impossible to retrieve the list of new packages from the media -`%s'. Either this update media is misconfigured, and in this case -you should use the Software Media Manager to remove it and re-add it in order -to reconfigure it, either it is currently unreachable and you should retry -later.", - $media)); - } else { - show_urpm_progress($label, $pb, @_); - $dlg->pollEvent(); - } - }, - ); - - $pb->setValue(100); - $dlg->waitForEvent(10); - $dlg->pollEvent(); - -cancel_update: - $dlg->destroy(); -} - -sub show_urpm_progress { - my ($label, $pb, $mode, $file, $percent, $total, $eta, $speed) = @_; - $file =~ s|([^:]*://[^/:\@]*:)[^/:\@]*(\@.*)|$1xxxx$2|; #- if needed... - state $medium; - - if ($mode eq 'copy') { - $pb->setValue(0); - $label->setValue($loc->N("Copying file for medium `%s'...", $file)); - } elsif ($mode eq 'parse') { - $pb->setValue(0); - $label->setValue($loc->N("Examining file of medium `%s'...", $file)); - } elsif ($mode eq 'retrieve') { - $pb->setValue(0); - $label->setValue($loc->N("Examining remote file of medium `%s'...", $file)); - $medium = $file; - } elsif ($mode eq 'done') { - $pb->setValue(100); - $label->setValue($label->value() . $loc->N(" done.")); - $medium = undef; - } elsif ($mode eq 'failed') { - $pb->setValue(100); - $label->setValue($label->value() . $loc->N(" failed!")); - $medium = undef; - } else { - # FIXME: we're displaying misplaced quotes such as "downloading `foobar from 'medium Main Updates'´" - $file = $medium && length($file) < 40 ? #-PO: We're downloading the said file from the said medium - $loc->N("%s from medium %s", basename($file), $medium) - : basename($file); - if ($mode eq 'start') { - $pb->setValue(0); - $label->setValue($loc->N("Starting download of `%s'...", $file)); - } elsif ($mode eq 'progress') { - if (defined $total && defined $eta) { - $pb->setValue($percent); - $label->setValue($loc->N("Download of `%s'\ntime to go:%s, speed:%s", $file, $eta, $speed)); - } else { - $pb->setValue($percent); - $label->setValue($loc->N("Download of `%s'\nspeed:%s", $file, $speed)); - } - } - } -} - - -sub update_sources_interactive { - my ($urpm, %options) = @_; - - my @media = grep { ! $_->{ignore} } @{$urpm->{media}}; - unless (@media) { - interactive_msg($loc->N("Warning"), $loc->N("No active medium found. You must enable some media to be able to update them.")); - return 0; - } - - my $appTitle = yui::YUI::app()->applicationTitle(); - - ## set new title to get it in dialog - yui::YUI::app()->setApplicationTitle($loc->N("Update media")); - - my $retVal = 0; - my $mageiaPlugin = "mga"; - my $factory = yui::YUI::widgetFactory; - my $mgaFactory = yui::YExternalWidgets::externalWidgetFactory($mageiaPlugin); - $mgaFactory = yui::YMGAWidgetFactory::getYMGAWidgetFactory($mgaFactory); - - my $dialog = $factory->createPopupDialog(); - my $minSize = $factory->createMinSize( $dialog, 60, 15 ); - my $vbox = $factory->createVBox($minSize); - - my $yTableHeader = new yui::YTableHeader(); - $yTableHeader->addColumn("", $yui::YAlignBegin); - $yTableHeader->addColumn($loc->N("Media"), $yui::YAlignBegin); - - my $mediaTable = $mgaFactory->createCBTable($vbox, $yTableHeader, $yui::YCBTableCheckBoxOnFirstColumn); - - my $itemCollection = new yui::YItemCollection; - foreach (@media) { - my $item = new yui::YCBTableItem($_->{name}); - $item->setLabel($_->{name}); - $itemCollection->push($item); - $item->DISOWN(); - } - $mediaTable->addItems($itemCollection); - - # dialog buttons - $factory->createVSpacing($vbox, 1.0); - ## Window push buttons - my $hbox = $factory->createHBox( $vbox ); - - my $cancelButton = $factory->createPushButton($hbox, $loc->N("Cancel") ); - my $selectButton = $factory->createPushButton($hbox, $loc->N("Select all") ); - my $updateButton = $factory->createPushButton($hbox, $loc->N("Update") ); - - 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 == $cancelButton) { - last; - } - elsif ($widget == $selectButton) { - yui::YUI::app()->busyCursor(); - yui::YUI::ui()->blockEvents(); - $dialog->startMultipleChanges(); - for (my $it = $mediaTable->itemsBegin(); $it != $mediaTable->itemsEnd(); ) { - my $item = $mediaTable->YItemIteratorToYItem($it); - if ($item) { - $mediaTable->checkItem($item, 1); - # NOTE for some reasons it is never == $mediaTable->itemsEnd() - if ($item->index() == $mediaTable->itemsCount()-1) { - last; - } - } - $it = $mediaTable->nextItem($it); - } - $dialog->recalcLayout(); - $dialog->doneMultipleChanges(); - yui::YUI::ui()->unblockEvents(); - yui::YUI::app()->normalCursor(); - - } - elsif ($widget == $updateButton) { - yui::YUI::app()->busyCursor(); - my @checked_media; - for (my $it = $mediaTable->itemsBegin(); $it != $mediaTable->itemsEnd(); ) { - my $item = $mediaTable->YItemIteratorToYItem($it); - $item = $mediaTable->toCBYTableItem($item); - if ($item) { - if ($item->checked()) { - push @checked_media, $item->label(); - } - # NOTE for some reasons it is never == $mediaTable->itemsEnd() - if ($item->index() == $mediaTable->itemsCount()-1) { - last; - } - } - $it = $mediaTable->nextItem($it); - } - - $retVal = update_sources_noninteractive($urpm, \@checked_media, %options); - yui::YUI::app()->normalCursor(); - last; - } - } - } - - $dialog->destroy(); - - #restore old application title - yui::YUI::app()->setApplicationTitle($appTitle) if $appTitle; - - return $retVal; -} - -sub update_sources_noninteractive { - my ($urpm, $media, %options) = @_; - - urpm::media::select_media_by_name($urpm, $media); - update_sources_check( - $urpm, - {}, - $loc->N_("Unable to update medium; it will be automatically disabled.\n\nErrors:\n%s"), - @$media, - ); - return 1; -} - -sub add_distrib_update_media { - my ($urpm, $mirror, %options) = @_; - #- ensure a unique medium name - my $medium_name = $ManaTools::rpmdragora::mageia_release =~ /(\d+\.\d+) \((\w+)\)/ ? $2 . $1 . '-' : 'distrib'; - my $initial_number = 1 + max map { $_->{name} =~ /\(\Q$medium_name\E(\d+)\b/ ? $1 : 0 } @{$urpm->{media}}; - add_medium_and_check( - $urpm, - { nolock => 1, distrib => 1 }, - $medium_name, - ($mirror ? $mirror->{url} : (undef, mirrorlist => '$MIRRORLIST')), - probe_with => 'synthesis', initial_number => $initial_number, %options, - usedistrib => 1, - ); -} - -sub warn_for_network_need { - my ($message, %options) = @_; - $message ||= - $branded - ? $loc->N("I need to access internet to get the mirror list. -Please check that your network is currently running. - -Is it ok to continue?") - : $loc->N("I need to contact the Mageia website to get the mirror list. -Please check that your network is currently running. - -Is it ok to continue?"); - interactive_msg($loc->N("Mirror choice"), $message, yesno => 1, %options) or return ''; -} - -sub choose_mirror { - my ($urpm, %options) = @_; - delete $options{message}; - my @transient_options = exists $options{transient} ? (transient => $options{transient}) : (); - warn_for_network_need($options{message}, %options) or return; - my @mirrors = eval { mirrors($urpm, $options{want_base_distro}) }; - my $error = $@; - if ($error) { - $error = "\n$error\n"; - interactive_msg($loc->N("Error during download"), - ($branded - ? $loc->N("There was an error downloading the mirror list:\n%s\n -The network, or the website, may be unavailable. -Please try again later.", $error) - : $loc->N("There was an error downloading the mirror list:\n%s\n -The network, or the Mageia website, may be unavailable. -Please try again later.", $error)), %options - ); - return ''; - } - - !@mirrors and interactive_msg($loc->N("No mirror"), - ($branded - ? $loc->N("I can't find any suitable mirror.") - : $loc->N("I can't find any suitable mirror.\n -There can be many reasons for this problem; the most frequent is -the case when the architecture of your processor is not supported -by Mageia Official Updates.")), %options - ), return ''; - - my @mirrorlist = map {$_->{country} . "|" . $_->{url}} @mirrors; - - my $sh_gui = ManaTools::Shared::GUI->new(); - my $mirror = $sh_gui->ask_fromTreeList({title => $loc->N("Mirror choice"), - header => $loc->N("Please choose the desired mirror."), - default_button => 1, - item_separator => "|", - default_item => $mirrors[0]->{url}, - skip_path => 1, - list => \@mirrorlist } - ); - - return $mirror ? { url => $mirror} : undef; - -} - - - - - - - -#- Check whether the default update media (added by installation) -#- matches the current mdk version -sub check_update_media_version { - my $urpm = shift; - foreach (@_) { - if ($_->{name} =~ /(\d+\.\d+).*\bftp\du\b/ && $1 ne $distro_version) { - interactive_msg( - $loc->N("Warning"), - $branded - ? $loc->N("Your medium `%s', used for updates, does not match the version of %s you're running (%s). -It will be disabled.", - $_->{name}, $distrib{system}, $distrib{product}) - : $loc->N("Your medium `%s', used for updates, does not match the version of Mageia you're running (%s). -It will be disabled.", - $_->{name}, $distro_version) - ); - $_->{ignore} = 1; - urpm::media::write_config($urpm) if -w $urpm->{config}; - return 0; - } - } - 1; -} - - - -sub mirrors { - my ($urpm, $want_base_distro) = @_; - my $cachedir = $urpm->{cachedir} || '/root'; - require mirror; - mirror::register_downloader( - sub { - my ($url) = @_; - my $file = $url; - $file =~ s!.*/!$cachedir/!; - unlink $file; # prevent "partial file" errors - MDK::Common::Func::before_leaving(sub { unlink $file }); - - my ($gurpm, $id, $canceled); - # display a message in statusbar (if availlable): - $::statusbar and $id = statusbar_msg( - $branded - ? $loc->N("Please wait, downloading mirror addresses.") - : $loc->N("Please wait, downloading mirror addresses from the Mageia website."), - 0); - my $_clean_guard = MDK::Common::Func::before_leaving { - undef $gurpm; - $id and statusbar_msg_remove($id); - }; - - require ManaTools::Rpmdragora::gurpm; - require ManaTools::Rpmdragora::pkg; - - my $res = urpm::download::sync_url($urpm, $url, - dir => $cachedir, - callback => sub { - $gurpm ||= - ManaTools::Rpmdragora::gurpm->new( - text => $loc->N("Please wait"), - ); - $canceled ||= - !ManaTools::Rpmdragora::pkg::download_callback($gurpm, @_); - $gurpm->flush(); - }, - ); - $res or die $loc->N("retrieval of [%s] failed", $file) . "\n"; - return $canceled ? () : MDK::Common::File::cat_($file); - }); - my @mirrors = @{ mirror::list(urpm::mirrors::parse_LDAP_namespace_structure(MDK::Common::File::cat_('/etc/product.id')), 'distrib') || [] }; - - require ManaTools::Shared::TimeZone; - my $tzo = ManaTools::Shared::TimeZone->new(); - my $tz = $tzo->readConfiguration()->{ZONE}; - foreach my $mirror (@mirrors) { - my $goodness = 0; - my $pri_mirr = defined ($t2l{$tz}) ? $t2l{$tz} : $us; - my $ind = 0; - foreach (@{$pri_mirr}) { - if (($_ eq lc($mirror->{zone})) || ($_ eq lc($mirror->{country}))) { - $goodness = scalar(@{$pri_mirr}) - $ind; - } - $ind ++; - } - - $mirror->{goodness} = $goodness + rand(); - $mirror->{country} = $u2l{lc($mirror->{country})} ? $loc->N($u2l{lc($mirror->{country})}) : $mirror->{country}; - } - unless (-x '/usr/bin/rsync') { - @mirrors = grep { $_->{url} !~ /^rsync:/ } @mirrors; - } - return sort { $b->{goodness} <=> $a->{goodness} } @mirrors; -} - - - - - -sub open_help { - my ($mode) = @_; - require ManaTools::Shared::RunProgram; - ManaTools::Shared::RunProgram::raw({ detach => 1, as_user => 1 }, 'drakhelp', '--id', $mode ? "software-management-$mode" : 'software-management'); - my $_s = $loc->N("Help launched in background"); - statusbar_msg($loc->N("The help window has been started, it should appear shortly on your desktop."), 1); -} - -sub run_drakbug { - my ($id) = @_; - require ManaTools::Shared::RunProgram; - ManaTools::Shared::RunProgram::raw({ detach => 1, as_user => 1 }, 'drakbug', '--report', $id); -} - -#mygtk2::add_icon_path('/usr/share/mcc/themes/default/'); -sub get_icon { - my ($mcc_icon, $fallback_icon) = @_; - my $icon = eval { mygtk2::_find_imgfile($mcc_icon) }; - $icon ||= eval { mygtk2::_find_imgfile($fallback_icon) }; - $icon; -} - -sub strip_first_underscore { join '', map { s/_//; $_ } @_ } - -1; diff --git a/lib/ManaTools/Category.pm b/lib/ManaTools/Category.pm new file mode 100644 index 0000000..4ef7fa7 --- /dev/null +++ b/lib/ManaTools/Category.pm @@ -0,0 +1,262 @@ +# vim: set et ts=4 sw=4: +# Copyright 2012 Steven Tucker +# +# This file is part of ManaTools +# +# ManaTools is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# ManaTools 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 ManaTools. If not, see . + + +#Class Category +package ManaTools::Category; + +use strict; +use warnings; +use diagnostics; +use yui; + +## Can only add the config file data at constructor +## The Gui elements are added in setupGui inside MainDisplay +#============================================================= + +=head2 new + +=head3 INPUT + + $newName: new category name + $newIcon: new category icon + +=head3 OUTPUT + + $self: this object + +=head3 DESCRIPTION + + Constructor: creates a new category named Name + +=cut + +#============================================================= + +sub new { + my ($class, $newName, $newIcon) = @_; + my $self = { + name => 0, + button => 0, + icon => 0, + modules => [], + }; + bless $self, 'ManaTools::Category'; + + $self->{name} = $newName; + $self->{icon} = $newIcon; + + return $self; +} + +## Add a new module to the list +#============================================================= + +=head2 loadModule + +=head3 INPUT + + $self: this object + $module: module to add + +=head3 OUTPUT + + 1: if the module has been added + 0: otherwise + +=head3 DESCRIPTION + + This method adds a module to the loaded + modules if it is not already in. + +=cut + +#============================================================= +sub loadModule { + my ($self, $module) = @_; + + if (!$self->moduleLoaded($module->{name})) { + push ( @{$self->{modules}}, $module ); + + return 1; + } + return 0; +} + +#============================================================= + +=head2 moduleLoaded + +=head3 INPUT + + $self: this object + $module_name or -CLASS => name : module/CLASS name to look for + +=head3 OUTPUT + + $present: module present or not + +=head3 DESCRIPTION + + This method looks for the given module and if already in + returns true. +=cut + +#============================================================= +sub moduleLoaded { + my $self = shift; + my ($module_name) = @_; + my %params = (); + if ($module_name eq '-CLASS') { + (%params) = @_; + } + + my $present = 0; + + if (!$module_name || ! $self->{modules}) { + return $present; + } + + foreach my $mod (@{$self->{modules}}) { + if (exists $params{-CLASS} && ref($mod) eq $params{-CLASS}) { + $present = 1; + last; + } + elsif ($mod->{name} eq $module_name) { + $present = 1; + last; + } + } + + return $present; +} + +#============================================================= + +=head2 addButtons + +=head3 INPUT + + $self: this object + $panel: parent panel layout in which to create buttons + $factory: yui factory + +=head3 DESCRIPTION + + Creates and adds buttons for each module_name + +=cut + +#============================================================= +sub addButtons { + my($self, $panel, $factory) = @_; + my $tmpButton; + my $currLayout = 0; + my %weights = (); + my $curr; + my $count = 0; + foreach my $mod (@{$self->{modules}}) { + if(($count % 2) != 1) { + $factory->createVSpacing($panel, 0.5); + $currLayout = $factory->createHBox($panel); + $factory->createHSpacing($currLayout, 1); + $currLayout->setWeight($yui::YD_VERT, 10); + } + + $tmpButton = $factory->createPushButton( + $currLayout, + $mod->name + ); + $count++; + if (($count < scalar @{$self->{modules}}) || (($count >= scalar @{$self->{modules}}) && ($count % 2) == 0)) { + $tmpButton->setWeight($yui::YD_HORIZ, 20); + } + $factory->createHSpacing($currLayout, 1); + $mod->setButton($tmpButton); + $tmpButton->setLabel($mod->name); + $tmpButton->setIcon($mod->icon); + } +} + +#============================================================= + +=head2 removeButtons + +=head3 INPUT + + $self: this object + +=head3 DESCRIPTION + + Delete the module buttons + +=cut + +#============================================================= +sub removeButtons { + my($self) = @_; + + for(@{$self->{modules}}) { + $_->removeButton(); + } +} + +#============================================================= + +=head2 setIcon + +=head3 INPUT + + $self: this object + +=head3 DESCRIPTION + + set the button icon + +=cut + +#============================================================= +sub setIcon { + my($self) = @_; + + $self->{button}->setIcon($self->{icon}); +} + +1; +__END__ + +=pod + +=head1 NAME + + Category - add new category to window + +=head1 SYNOPSIS + + $category = new Category('Category Name'); + + +=head1 USAGE + + This class is used by MainDisplay internally and should not + be used outside, since MainDisplay::setupGui use it to + build GUI layout. + +=head1 FUNCTIONS + +=cut diff --git a/lib/ManaTools/ConfigReader.pm b/lib/ManaTools/ConfigReader.pm new file mode 100644 index 0000000..792dc0e --- /dev/null +++ b/lib/ManaTools/ConfigReader.pm @@ -0,0 +1,119 @@ +# vim: set et ts=4 sw=4: +# Copyright 2012 Steven Tucker +# +# This file is part of ManaTools +# +# ManaTools is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# ManaTools 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 ManaTools. If not, see . + + +#Class ConfigReader +package ManaTools::ConfigReader; + +use strict; +use warnings; +use diagnostics; +use XML::Simple; +use Data::Dumper; + +sub new { + my ($class, $fileName) = @_; + + my $self = { + data => 0, + catLen => 0, + currCat => 0, + modLen => 0, + currMod => 0, + placeHolder => 0, + }; + bless $self, 'ManaTools::ConfigReader'; + + my $xml = new XML::Simple (KeyAttr=>[]); + $self->{data} = $xml->XMLin($fileName); + if (ref($self->{data}->{category}) eq "HASH") { + # one element alone + my @categories; + push @categories, $self->{data}->{category}; + $self->{data}->{category} = undef; + push @{$self->{data}->{category}}, @categories; + } + $self->{catLen} = scalar(@{$self->{data}->{category}}); + $self->{currCat} = -1; + + if(ref(@{$self->{data}->{category}}[0]->{module}) eq "ARRAY") { + $self->{modLen} = scalar(@{@{$self->{data}->{category}}[0]->{module}}); + } else { + $self->{modLen} = 1; + } + $self->{currMod} = -1; + + return $self; +} + +sub hasNextCat { + my ($self) = @_; + + if($self->{currCat} + 1 >= $self->{catLen}) { + return 0; + } + return 1; +} + +sub getNextCat { + my ($self) = @_; + + $self->{currCat}++; + if($self->{currCat} >= $self->{catLen}) { + return 0; + } + + # Reset the Module Count and Mod length for new Category + $self->{currMod} = -1; + if(ref(@{$self->{data}->{category}}[$self->{currCat}]->{module}) eq "ARRAY") { + $self->{modLen} = scalar(@{@{$self->{data}->{category}}[$self->{currCat}]->{module}}); + } else { + $self->{modLen} = 1; + } + + my $tmp = @{$self->{data}->{category}}[$self->{currCat}]; + + return $tmp; +} + +sub hasNextMod { + my ($self) = @_; + + if($self->{currMod} + 1 >= $self->{modLen}) { + return 0; + } + return 1; +} + +sub getNextMod { + my ($self) = @_; + + my $ret = 0; + + $self->{currMod}++; + + if($self->{modLen} == 1) { + $ret = @{$self->{data}->{category}}[$self->{currCat}]->{module}; + } else { + $ret = @{@{$self->{data}->{category} }[$self->{currCat}]->{module}}[$self->{currMod}]; + } + + return $ret; +} + +1; diff --git a/lib/ManaTools/MainDisplay.pm b/lib/ManaTools/MainDisplay.pm new file mode 100644 index 0000000..19d0a7f --- /dev/null +++ b/lib/ManaTools/MainDisplay.pm @@ -0,0 +1,628 @@ +# vim: set et ts=4 sw=4: +# Copyright 2012 Steven Tucker +# +# This file is part of ManaTools +# +# ManaTools is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# ManaTools 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 ManaTools. If not, see . + + +package ManaTools::MainDisplay; +#============================================================= -*-perl-*- + +=head1 NAME + +ManaTools::MainDisplay - class for AdminPaneol main window + +=head1 SYNOPSIS + + $mainDisplay = new ManaTools::MainDisplay(); + $mainDisplay->start(); + $mainDisplay->destroy(); + +=head1 METHODS + +=head1 DESCRIPTION + +Long_description + +=head1 EXPORT + +exported + +=head1 SUPPORT + +You can find documentation for this module with the perldoc command: + +perldoc ManaTools::MainDisplay + +=head1 SEE ALSO + +SEE_ALSO + +=head1 AUTHOR + +Steven Tucker + +=head1 COPYRIGHT and LICENSE + +Copyright (C) 2012, Steven Tucker +Copyright (C) 2014, Angelo Naselli. + +ManaTools is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +ManaTools 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 ManaTools. If not, see . + +=head1 FUNCTIONS + +=cut + + + +=head1 VERSION + +Version 0.01 + +=cut + +our $VERSION = '1.0.0'; + +use strict; +use warnings; +use diagnostics; +use ManaTools::SettingsReader; +use ManaTools::ConfigReader; +use ManaTools::Category; +use ManaTools::Module; +use ManaTools::Shared; +use ManaTools::Shared::GUI; +use ManaTools::Shared::Locales; +use File::ShareDir ':ALL'; + +use yui; + +#============================================================= + +=head2 new + +=head3 DESCRIPTION + +This method instanziates the MainWindo object, and setups +the startup GUI. + +=cut + +#============================================================= +sub new { + + my $self = { + categories => 0, + event => 0, + factory => 0, + mainWin => 0, + mainLayout => 0, + menuLayout => 0, + menus => { + file => 0, + help => 0 + }, + layout => 0, + leftPane => 0, + rightPane => 0, + currCategory => 0, + confDir => 0, + title => 0, + settings => 0, + exitButton => 0, + aboutButton => 0, + loc => 0, + replacePoint => 0, + }; + bless $self, 'ManaTools::MainDisplay'; + +## Default values + $self->{name} = "Mana-tools panel"; + $self->{categories} = []; + $self->{confDir} = "/etc/mpan", + $self->{title} = "mpan", + + my $cmdline = new yui::YCommandLine; + + ## TODO add parameter check + my $pos = $cmdline->find("--name"); + if ($pos > 0) + { + $self->{title} = $cmdline->arg($pos+1); + } + $pos = $cmdline->find("--conf_dir"); + if ($pos > 0) + { + $self->{confDir} = $cmdline->arg($pos+1); + } + else + { + $self->{confDir} = "/etc/$self->{title}"; + } + + # TODO localize + $self->{loc} = ManaTools::Shared::Locales->new(domain_name => 'libDrakX-standalone'); + $self->setupGui(); + + return $self; +} + + +sub _showAboutDialog { + my $self = shift; + + my $translators = $self->{loc}->N("_: Translator(s) name(s) & email(s)\n"); + $translators =~ s/\/\>\;/g; + my $sh_gui = ManaTools::Shared::GUI->new(); + $sh_gui->AboutDialog({ name => $self->{name}, + version => $ManaTools::MainDisplay::VERSION, + credits => $self->{loc}->N("Copyright (C) %s Mageia community", '2013-2015'), + license => $self->{loc}->N("GPLv2"), + description => $self->{loc}->N("mpan is the mana-tools panel that collects all the utilities."), + authors => $self->{loc}->N("

Developers

+
  • %s
  • +
  • %s
  • +
+

Translators

+
  • %s
", + "Angelo Naselli <anaselli\@linux.it>", + "Matteo Pasotti <matteo.pasotti\@gmail.com>", + $translators + ), + + }); +} + + + +## Begin the program event loop +sub start { + my ($self) = shift; + my $reqExit = 0; + + ##Default category selection + if (!$self->{currCategory}) { + $self->{currCategory} = @{$self->{categories}}[0]; + } + $self->{currCategory}->addButtons($self->{rightPane}, $self->{factory}); + $self->{rightPaneFrame}->setLabel($self->{currCategory}->{name}); + $self->{factory}->createSpacing($self->{rightPane}, 1, 1, 1.0 ); + my $launch = 0; + while(!$launch) { + + ## Grab Event + $self->{event} = $self->{mainWin}->waitForEvent(); + my $eventType = $self->{event}->eventType(); + + ## Check for window close + if ($eventType == $yui::YEvent::CancelEvent) { + last; + } + elsif ($eventType == $yui::YEvent::MenuEvent) { + ### MENU ### + my $item = $self->{event}->item(); + my $menuLabel = $item->label(); + if ($menuLabel eq $self->{menus}->{file}->{ quit }->label()) { + ## quit menu item + last; + } + elsif ($menuLabel eq $self->{menus}->{help}->{ about }->label()) { + $self->_showAboutDialog(); + } + elsif ($menuLabel eq $self->{menus}->{help}->{ help }->label()) { + # TODO Help + } + } + elsif ($eventType == $yui::YEvent::WidgetEvent) { + my $widget = $self->{event}->widget(); + + ## Check for Exit button push or menu + if($widget == $self->{exitButton}) { + last; + } + elsif ($widget == $self->{aboutButton}) { + $self->_showAboutDialog(); + } + else { + # category button selected? + my $isCat = $self->_categorySelected($widget); + if (!$isCat) { + # module button selected? + $launch = $self->_moduleSelected($widget); + } + } + } + } + + return $launch; +} + +#============================================================= + +=head2 destroy + +=head3 INPUT + + $self: this object + +=head3 DESCRIPTION + + This method destroyes the main window and all the + relevanto bojects (category and modules buttons). + +=cut + +#============================================================= +sub destroy { + my ($self) = shift; + + $self->{mainWin}->destroy(); + for (my $cat=0; $cat < scalar(@{$self->{categories}}); $cat++ ) { + @{$self->{categories}}[$cat]->{button} = 0; + @{$self->{categories}}[$cat]->removeButtons(); + } +} + +#============================================================= + +=head2 setupGui + +=head3 INPUT + + $self: this object + +=head3 DESCRIPTION + + This method load configuration and build the GUI layout. + +=cut + +#============================================================= +sub setupGui { + my ($self) = shift; + + $self->_loadSettings(); + yui::YUILog::setLogFileName($self->{settings}->{log}) if defined($self->{settings}->{log}); + $self->{name} = $self->{settings}->{title}; + yui::YUI::app()->setApplicationTitle($self->{name}); + my $icon = defined($self->{settings}->{icon}) ? + $self->{settings}->{icon} : + File::ShareDir::dist_file(ManaTools::Shared::distName(), 'images/mageia.png'); + + yui::YUI::app()->setApplicationIcon($icon); + + $self->{factory} = yui::YUI::widgetFactory; + $self->{mainWin} = $self->{factory}->createMainDialog; + + $self->{mainLayout} = $self->{factory}->createVBox($self->{mainWin}); + $self->{menuLayout} = $self->{factory}->createHBox($self->{mainLayout}); + + ## Menu File + my $align = $self->{factory}->createAlignment($self->{menuLayout}, 1, 0); + $self->{menus}->{file} = { + widget => $self->{factory}->createMenuButton($align, $self->{loc}->N("File")), + quit => new yui::YMenuItem($self->{loc}->N("&Quit")), + }; + + my @ordered_menu_lines = qw(quit); + foreach (@ordered_menu_lines) { + $self->{menus}->{file}->{ widget }->addItem($self->{menus}->{file}->{ $_ }); + } + $self->{menus}->{file}->{ widget }->rebuildMenuTree(); + + $align = $self->{factory}->createAlignment($self->{menuLayout}, 2, 0); + $self->{menus}->{help} = { + widget => $self->{factory}->createMenuButton($align, $self->{loc}->N("Help")), + help => new yui::YMenuItem($self->{loc}->N("Help")), + about => new yui::YMenuItem($self->{loc}->N("&About")), + }; + + ## Menu Help + @ordered_menu_lines = qw(help about); + foreach (@ordered_menu_lines) { + $self->{menus}->{help}->{ widget }->addItem($self->{menus}->{help}->{ $_ }); + } + $self->{menus}->{help}->{ widget }->rebuildMenuTree(); + + $self->{layout} = $self->{factory}->createHBox($self->{mainLayout}); + + #create left Panel Frame no need to add a label for title + $self->{leftPaneFrame} = $self->{factory}->createFrame($self->{layout}, $self->{settings}->{category_title}); + #create right Panel Frame no need to add a label for title (use setLabel when module changes) + $self->{rightPaneFrame} = $self->{factory}->createFrame($self->{layout}, ""); + #create replace point for dynamically created widgets + $self->{replacePoint} = $self->{factory}->createReplacePoint($self->{rightPaneFrame}); + + $self->{rightPane} = $self->{factory}->createVBox($self->{replacePoint}); + $self->{leftPane} = $self->{factory}->createVBox($self->{leftPaneFrame}); + + #logo from settings + my $logofile = defined($self->{settings}->{logo}) ? + $self->{settings}->{logo} : + File::ShareDir::dist_file(ManaTools::Shared::distName(), 'images/logo_mageia.png'); + + my $logo = $self->{factory}->createImage($self->{leftPane}, $logofile); + $logo->setAutoScale(1); + +# $self->{leftPaneFrame}->setWeight(0, 1); + $self->{rightPaneFrame}->setWeight(0, 2); + + $self->_loadCategories(); + $self->{factory}->createVStretch($self->{leftPane}); + + $self->{aboutButton} = $self->{factory}->createPushButton($self->{leftPane}, "&About"); + $self->{aboutButton}->setStretchable(0, 1); + + $self->{exitButton} = $self->{factory}->createPushButton($self->{leftPane}, "&Quit"); + my $quitIcon = File::ShareDir::dist_file(ManaTools::Shared::distName(), 'images/quit.png'); + $self->{exitButton}->setIcon($quitIcon); + $self->{exitButton}->setStretchable(0, 1); +} + + +## internal methods + +## Check if event is from current Category View +## If icon click, returns the module to be launched + +sub _moduleSelected { + my ($self, $selectedWidget) = @_; + + for(@{$self->{currCategory}->{modules}}) { + if( $_->{button} == $selectedWidget ){ + return $_; + } + } + return 0; +} + + +## Discover if a category button was selected. +## If category button is selected, sets right panel to display +## the selected Category Modules +## returns 1 if category button is selected +sub _categorySelected { + my ($self, $selectedWidget) = @_; + for (@{$self->{categories}}) { + if( $_->{button} == $selectedWidget ) { + + #if current is already set then skips + if ($self->{currCategory} == $_) { + ## returns 1 to skip any other checks on + ## the selected widget + return 1; + } + ## Menu item selected, set right pane + $self->{mainWin}->startMultipleChanges(); + ## Remove existing modules + $self->{replacePoint}->deleteChildren(); + $self->{rightPane} = $self->{factory}->createVBox($self->{replacePoint}); + + ## Change Current Category to the selected one + $self->{currCategory} = $_; + ## Add new Module Buttons to Right Pane + $self->{currCategory}->addButtons($self->{rightPane}, $self->{factory}); + $self->{rightPaneFrame}->setLabel($self->{currCategory}->{name}); + $self->{factory}->createSpacing($self->{rightPane}, 1, 1, 1.0 ); + $self->{replacePoint}->showChild(); + $self->{mainWin}->recalcLayout(); + $self->{mainWin}->doneMultipleChanges(); + + return 1; + } + } + + return 0; +} + +## adpanel settings +sub _loadSettings { + my ($self, $force_load) = @_; + # configuration file name + my $fileName = "$self->{confDir}/settings.conf"; + die "Configuration file missing" if (! -e $fileName); + if (!$self->{settings} || $force_load) { + $self->{settings} = new ManaTools::SettingsReader($fileName); + } +} + +#============================================================= +# _categoryLoaded +# +# INPUT +# +# $self: this object +# $category: category to look for +# +# OUTPUT +# +# $present: category is present or not +# +# DESCRIPTION +# +# This method looks for the given category and if already in +# returns true. +# +#============================================================= +sub _categoryLoaded { + my ($self, $category) = @_; + my $present = 0; + + if (!$category) { + return $present; + } + + foreach my $cat (@{$self->{categories}}) { + if ($cat->{name} eq $category->{name}) { + $present = 1; + last; + } + } + + return $present; +} + +#============================================================= +# _getCategory +# +# INPUT +# +# $self: this object +# $name: category name +# +# OUTPUT +# +# $category: category object if exists +# +# DESCRIPTION +# +# This method looks for the given category name and returns +# the realte object. +#============================================================= +sub _getCategory { + my ($self, $name) = @_; + my $category = undef; + + foreach $category (@{$self->{categories}}) { + if ($category->{name} eq $name) { + return $category; + } + } + + return $category; +} + +# _loadCategory +# +# creates a new button representing a category +# +sub _loadCategory { + my ($self, $category) = @_; + + if (!$self->_categoryLoaded($category)) { + push ( @{$self->{categories}}, $category ); + + @{$self->{categories}}[-1]->{button} = $self->{factory}->createPushButton( + $self->{leftPane}, + $self->{categories}[-1]->{name} + ); + @{$self->{categories}}[-1]->setIcon(); + + @{$self->{categories}}[-1]->{button}->setStretchable(0, 1); + } + else { + for (my $cat=0; $cat < scalar(@{$self->{categories}}); $cat++ ) { + if( @{$self->{categories}}[$cat]->{name} eq $category->{name} && + !@{$self->{categories}}[$cat]->{button}) { + @{$self->{categories}}[$cat]->{button} = $self->{factory}->createPushButton( + $self->{leftPane}, + $self->{categories}[$cat]->{name} + ); + @{$self->{categories}}[$cat]->setIcon(); + @{$self->{categories}}[$cat]->{button}->setStretchable(0, 1); + last; + + } + } + } +} + +sub _loadCategories { + my ($self) = @_; + + # category files + my @categoryFiles; + my $fileName = "$self->{confDir}/categories.conf"; + + + # configuration file dir + my $directory = "$self->{confDir}/categories.conf.d"; + + push(@categoryFiles, $fileName); + push(@categoryFiles, <$directory/*.conf>); + my $currCategory; + + foreach $fileName (@categoryFiles) { + my $inFile = new ManaTools::ConfigReader($fileName); + my $tmpCat; + my $tmp; + my $hasNextCat = $inFile->hasNextCat(); + while( $hasNextCat ) { + $tmp = $inFile->getNextCat(); + $tmpCat = $self->_getCategory($tmp->{title}); + if (!$tmpCat) { + $tmpCat = new ManaTools::Category($tmp->{title}, $tmp->{icon}); + } + $self->_loadCategory($tmpCat); + $hasNextCat = $inFile->hasNextCat(); + $currCategory = $tmpCat; + + my $hasNextMod = $inFile->hasNextMod(); + while( $hasNextMod ) { + $tmp = $inFile->getNextMod(); + my $tmpMod; + my $loaded = 0; + + if (exists $tmp->{title}) { + if (not $currCategory->moduleLoaded($tmp->{title})) { + $tmpMod = ManaTools::Module->create(name => $tmp->{title}, + icon => $tmp->{icon}, + launch => $tmp->{launcher} + ); + } + } + elsif (exists $tmp->{class}) { + if (not $currCategory->moduleLoaded(-CLASS => $tmp->{class})) { + $tmpMod = ManaTools::Module->create(-CLASS => $tmp->{class}); + } + } + if ($tmpMod) { + $loaded = $currCategory->loadModule($tmpMod); + undef $tmpMod if !$loaded; + } + $hasNextMod = $inFile->hasNextMod(); + } + } + } +} + +1; + +=pod + +=head2 start + + contains the main loop of the application + where we can check for events + +=head2 setupGui + + creates a popupDialog using a YUI::WidgetFactory + and then populate this dialog with some components + +=cut + diff --git a/lib/ManaTools/Module.pm b/lib/ManaTools/Module.pm new file mode 100644 index 0000000..1e13d92 --- /dev/null +++ b/lib/ManaTools/Module.pm @@ -0,0 +1,162 @@ +# vim: set et ts=4 sw=4: +# Copyright 2012 Steven Tucker +# +# This file is part of ManaTools +# +# ManaTools is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# ManaTools 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 ManaTools. If not, see . + + +#Class Module +package ManaTools::Module; + +use Moose; + +=head1 VERSION + +Version 0.01 + +=cut + +our $VERSION = '1.0.0'; + +use yui; + +=head1 SUBROUTINES/METHODS + +=head2 create - returns a Module object such as a module + launcher (this object) or an extension of + this class + +=cut + +sub create { + my $class = shift; + $class = ref $class || $class; + my (%params) = @_; + + my $obj; + if ( exists $params{-CLASS} ) { + my $driver = $params{-CLASS}; + + eval { + my $pkg = $driver; + $pkg =~ s/::/\//g; + $pkg .= '.pm'; + require $pkg; + $obj=$driver->new(); + }; + if ( $@ ) { + die "Error getting obj for driver $params{-CLASS}: $@"; + return undef; + } + } + else { + $obj = new ManaTools::Module(@_); + } + return $obj; +} + +has 'icon' => ( + is => 'rw', + isa => 'Str', +); + +has 'name' => ( + is => 'rw', + isa => 'Str', +); + +has 'launch' => ( + is => 'rw', + isa => 'Str', +); + +has 'button' => ( + is => 'rw', + init_arg => undef, +); + + +#============================================================= + +=head2 setButton + +=head3 INPUT + +$self: this object +$button: yui push button to be assigned to this module + +=head3 DESCRIPTION + +This method assignes a button to this module + +=cut + +#============================================================= +sub setButton { + my ($self, $button) = @_; + $self->{button} = $button; +} + +#============================================================= + +=head2 removeButton + +=head3 INPUT + +$self: this object + +=head3 DESCRIPTION + +This method remove the assigned button from this module + +=cut + +#============================================================= +sub removeButton { + my($self) = @_; + + undef($self->{button}); +} + +# base class launcher +#============================================================= + +=head2 start + +=head3 INPUT + +$self: this object + +=head3 DESCRIPTION + +This method is the base class launcher, run external modules. + +=cut + +#============================================================= +sub start { + my $self = shift; + + if ($self->{launch}) { + my $err = yui::YUI::app()->runInTerminal( $self->{launch} . " --ncurses"); + if ($err == -1) { + system($self->{launch}); + } + } +} + + +no Moose; +1; 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 +# 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{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 \nMatteo Pasotti ", + translator_credits => + #-PO: put here name(s) and email(s) of translator(s) (eg: "John Smith ") + 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 + +=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/\/\>\;/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("

Developers

+
  • %s
  • +
  • %s
  • +
+

Translators

+
  • %s
", + "Angelo Naselli <anaselli\@linux.it>", + $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 +# +# 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 <matteo.pasotti\@gmail.com>" + } + ); + }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 +# +# 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 <matteo.pasotti\@gmail.com>" + }; +} + +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 %s", $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 +# +# 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 <matteo.pasotti\@gmail.com>" + } + ); + }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 + +=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/\/\>\;/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("

Developers

+
  • %s
  • +
  • %s
  • +
+

Translators

+
  • %s
", + "Angelo Naselli <anaselli\@linux.it>", + "Matteo Pasotti <matteo.pasotti\@gmail.com>", + $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 +# +# 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 the string with the list of the excluded domains/addresses + +=item B the url of the http proxy + +=item B the url of the https proxy + +=item B 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 <matteo.pasotti\@gmail.com>" + } + ); + }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 + +=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/\/\>\;/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("

Developers

+
  • %s
  • +
  • %s
  • +
+

Translators

+
  • %s
", + "Angelo Naselli <anaselli\@linux.it>", + "Matteo Pasotti <matteo.pasotti\@gmail.com>", + $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 + +=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/\/\>\;/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("

Developers

+
  • %s
  • +
  • %s
  • +
+

Translators

+
  • %s
", + "Angelo Naselli <anaselli\@linux.it>", + "Matteo Pasotti <matteo.pasotti\@gmail.com>", + $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; diff --git a/lib/ManaTools/Privileges.pm b/lib/ManaTools/Privileges.pm new file mode 100644 index 0000000..5833900 --- /dev/null +++ b/lib/ManaTools/Privileges.pm @@ -0,0 +1,61 @@ +# vim: set et ts=4 sw=4: +# Copyright 2012-2015 Matteo Pasotti +# +# This file is part of ManaTools +# +# ManaTools is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# ManaTools 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 ManaTools. If not, see . + +package ManaTools::Privileges; + +use strict; +use warnings; +use diagnostics; +require Exporter; +use base qw(Exporter); +use English qw(-no_match_vars); + +our @EXPORT = qw(is_root_capability_required + ask_for_authentication); + +my $wrappers = { "sudo" => "/usr/bin/sudo", + "pkit" => "/usr/bin/pkexec", + "chlp" => "/usr/bin/consolehelper" + }; + +my $wrapper = 0; + +sub is_root_capability_required { + return $EUID != 0; +} + +sub ask_for_authentication { + my $wrapper_id = shift; + $wrapper = $wrappers->{$wrapper_id} if(defined($wrappers->{$wrapper_id})); + my ($command, @args) = wrap_command($0, @ARGV); + unshift(@args,$command->[1]); + unshift(@args, '-n') if($wrapper_id eq "sudo"); # let sudo die if password is needed + exec { $command->[0] } $command->[1], @args or die ("command %s missing", $command->[0]); +} + +sub wrap_command { + my ($app, @args) = @_; + return ([$wrapper, $app], @args); +} + +sub get_wrapper { + my $id = shift; + return $wrappers->{$id} if(defined($wrappers->{$id})); +} + +1; diff --git a/lib/ManaTools/Rpmdragora/.perl_checker b/lib/ManaTools/Rpmdragora/.perl_checker new file mode 100644 index 0000000..202e053 --- /dev/null +++ b/lib/ManaTools/Rpmdragora/.perl_checker @@ -0,0 +1 @@ +Basedir .. diff --git a/lib/ManaTools/Rpmdragora/edit_urpm_sources.pm b/lib/ManaTools/Rpmdragora/edit_urpm_sources.pm new file mode 100644 index 0000000..c756964 --- /dev/null +++ b/lib/ManaTools/Rpmdragora/edit_urpm_sources.pm @@ -0,0 +1,2243 @@ +# vim: set et ts=4 sw=4: +package ManaTools::Rpmdragora::edit_urpm_sources; +#***************************************************************************** +# +# Copyright (c) 2002 Guillaume Cottenceau +# Copyright (c) 2002-2007 Thierry Vignaud +# Copyright (c) 2002-2007 Mandriva Linux +# 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. +# +#***************************************************************************** +# +# $Id: edit_urpm_sources.pm 266598 2010-03-03 12:00:58Z tv $ + + +use strict; +use File::ShareDir ':ALL'; +use File::HomeDir qw(home); + +use MDK::Common::Func qw(if_ each_index); +use MDK::Common::Math qw(max); +use MDK::Common::File qw(cat_ output); +use MDK::Common::DataStructure qw(member put_in_hash uniq); +use MDK::Common::Various qw(to_bool); + +use ManaTools::Shared; +use ManaTools::Shared::Locales; +use ManaTools::rpmdragora; +use ManaTools::Rpmdragora::init; +use ManaTools::Rpmdragora::open_db; +use ManaTools::Rpmdragora::formatting; +use ManaTools::Shared::GUI; +use URPM::Signature; +use urpm::media; +use urpm::download; +use urpm::lock; + +use Exporter; +our @ISA = qw(Exporter); +our @EXPORT_OK = qw(run); + + +my $urpm; +my ($mainw, $list_tv, $something_changed); + +my %col = ( + mainw => { + is_enabled => 0, + is_update => 1, + type => 2, + name => 3, + activatable => 4 + }, +); + +my $loc = ManaTools::rpmdragora::locale(); + +sub get_medium_type { + my ($medium) = @_; + my %medium_type = ( + cdrom => $loc->N("CD-ROM"), + ftp => $loc->N("FTP"), + file => $loc->N("Local"), + http => $loc->N("HTTP"), + https => $loc->N("HTTPS"), + nfs => $loc->N("NFS"), + removable => $loc->N("Removable"), + rsync => $loc->N("rsync"), + ssh => $loc->N("NFS"), + ); + return $loc->N("Mirror list") if $medium->{mirrorlist}; + return $medium_type{$1} if $medium->{url} =~ m!^([^:]*)://!; + return $loc->N("Local"); +} + +sub selrow { + my ($o_list_tv) = @_; + defined $o_list_tv or $o_list_tv = $list_tv; + my ($model, $iter) = $o_list_tv->get_selection->get_selected; + $model && $iter or return -1; + my $path = $model->get_path($iter); + my $row = $path->to_string; + return $row; +} + +sub selected_rows { + my ($o_list_tv) = @_; + defined $o_list_tv or $o_list_tv = $list_tv; + my (@rows) = $o_list_tv->get_selection->get_selected_rows; + return -1 if @rows == 0; + map { $_->to_string } @rows; +} + +sub remove_row { + my ($model, $path_str) = @_; + my $iter = $model->get_iter_from_string($path_str); + $iter or return; + $model->remove($iter); +} + +sub remove_from_list { + my ($list, $list_ref, $model) = @_; + my $row = selrow($list); + if ($row != -1) { + splice @$list_ref, $row, 1; + remove_row($model, $row); + } + +} + +sub _want_base_distro() { + $::expert && distro_type(0) eq 'updates' ? interactive_msg( + $loc->N("Choose media type"), + $loc->N("In order to keep your system secure and stable, you must at a minimum set up +sources for official security and stability updates. You can also choose to set +up a fuller set of sources which includes the complete official Mageia +repositories, giving you access to more software than can fit on the Mageia +discs. Please choose whether to configure update sources only, or the full set +of sources." + ), + transient => $::main_window, + yesno => 1, text => { yes => $loc->N("Full set of sources"), no => $loc->N("Update sources only") }, + ) : 1; +} + +sub easy_add_callback_with_mirror() { + # when called on early init by rpmdragora + $urpm ||= fast_open_urpmi_db(); + + #- cooker and community don't have update sources + my $want_base_distro = _want_base_distro(); + defined $want_base_distro or return 0; + my $distro = $ManaTools::rpmdragora::mageia_release; + my ($mirror) = choose_mirror($urpm, message => + $loc->N("This will attempt to install all official sources corresponding to your +distribution (%s).\n +I need to contact the Mageia website to get the mirror list. +Please check that your network is currently running.\n +Is it ok to continue?", $distro), + transient => $::main_window, + ) or return 0; + ref $mirror or return 0; + my $wait = wait_msg($loc->N("Please wait, adding media...")); + add_distrib_update_media($urpm, $mirror, if_(!$want_base_distro, only_updates => 1)); + $offered_to_add_sources->[0] = 1; + remove_wait_msg($wait); + return 1; +} + +sub easy_add_callback() { + # when called on early init by rpmdragora + $urpm ||= fast_open_urpmi_db(); + + #- cooker and community don't have update sources + my $want_base_distro = _want_base_distro(); + defined $want_base_distro or return 0; + warn_for_network_need(undef, transient => $::main_window) or return 0; + my $wait = wait_msg($loc->N("Please wait, adding media...")); + add_distrib_update_media($urpm, undef, if_(!$want_base_distro, only_updates => 1)); + $offered_to_add_sources->[0] = 1; + remove_wait_msg($wait); + return 1; +} + +## Internal routine that builds input fields needed to manage +## the selected media type to be added +## return HASH reference with the added widgets +sub _build_add_dialog { + my $options = shift; + + die "replace point is needed" if !defined ($options->{replace_pnt}); + die "dialog is needed" if !defined ($options->{dialog}); + die "selected item is needed" if !defined ($options->{selected}); + die "media info is needed" if !defined ($options->{info}); + + my %widgets; + my $factory = yui::YUI::widgetFactory; + + $options->{dialog}->startMultipleChanges(); + $options->{replace_pnt}->deleteChildren(); + + # replace widgets + my $vbox = $factory->createVBox( $options->{replace_pnt} ); + my $hbox = $factory->createHBox($vbox); + $factory->createHSpacing($hbox, 1.0); + my $label = $factory->createLabel($hbox, + $options->{info}->{$options->{selected}}->{url} + ); + + $factory->createHSpacing($hbox, 3.0); + $widgets{url} = $factory->createInputField($hbox, "", 0); + $widgets{url}->setWeight($yui::YD_HORIZ, 2); + if (defined($options->{info}->{$options->{selected}}->{dirsel})) { + $widgets{dirsel} = $factory->createPushButton($hbox, $loc->N("Browse...")); + } + elsif (defined($options->{info}->{$options->{selected}}->{loginpass})) { + $hbox = $factory->createHBox($vbox); + $factory->createHSpacing($hbox, 1.0); + $label = $factory->createLabel($hbox, $loc->N("Login:") ); + $factory->createHSpacing($hbox, 1.0); + $widgets{login} = $factory->createInputField($hbox, "", 0); + $label->setWeight($yui::YD_HORIZ, 1); + $widgets{login}->setWeight($yui::YD_HORIZ, 3); + $hbox = $factory->createHBox($vbox); + $factory->createHSpacing($hbox, 1.0); + $label = $factory->createLabel($hbox, $loc->N("Password:") ); + $factory->createHSpacing($hbox, 1.0); + $widgets{pass} = $factory->createInputField($hbox, "", 1); + $label->setWeight($yui::YD_HORIZ, 1); + $widgets{pass}->setWeight($yui::YD_HORIZ, 3); + + } + # recalc layout + $options->{replace_pnt}->showChild(); + $options->{dialog}->recalcLayout(); + $options->{dialog}->doneMultipleChanges(); + + return \%widgets; +} + +sub add_callback() { + + my $retVal = 0; + + my $appTitle = yui::YUI::app()->applicationTitle(); + ## set new title to get it in dialog + yui::YUI::app()->setApplicationTitle($loc->N("Add a medium")); + + my $factory = yui::YUI::widgetFactory; + + my $dialog = $factory->createPopupDialog(); + my $minSize = $factory->createMinSize( $dialog, 60, 5 ); + my $vbox = $factory->createVBox( $minSize ); + + $factory->createVSpacing($vbox, 0.5); + + my $hbox = $factory->createHBox( $factory->createLeft($vbox) ); + $factory->createHeading($hbox, $loc->N("Adding a medium:")); + $factory->createVSpacing($vbox, 0.5); + + $hbox = $factory->createHBox($vbox); + $factory->createHSpacing($hbox, 1.0); + my $label = $factory->createLabel($hbox, $loc->N("Type of medium:") ); + my $media_type = $factory->createComboBox($hbox, "", 0); + $media_type->setWeight($yui::YD_HORIZ, 2); + + my %radios_infos = ( + local => { name => $loc->N("Local files"), url => $loc->N("Medium path:"), dirsel => 1 }, + ftp => { name => $loc->N("FTP server"), url => $loc->N("URL:"), loginpass => 1 }, + rsync => { name => $loc->N("RSYNC server"), url => $loc->N("URL:") }, + http => { name => $loc->N("HTTP server"), url => $loc->N("URL:") }, + removable => { name => $loc->N("Removable device (CD-ROM, DVD, ...)"), + url => $loc->N("Path or mount point:"), dirsel => 1 }, + ); + my @radios_names_ordered = qw(local ftp rsync http removable); + + my $itemColl = new yui::YItemCollection; + foreach my $elem (@radios_names_ordered) { + my $it = new yui::YItem($radios_infos{$elem}->{'name'}, 0); + if ($elem eq $radios_names_ordered[0]) { + $it->setSelected(1); + } + $itemColl->push($it); + $it->DISOWN(); + } + $media_type->addItems($itemColl); + $media_type->setNotify(1); + + $hbox = $factory->createHBox($vbox); + $factory->createHSpacing($hbox, 1.0); + $label = $factory->createLabel($hbox, $loc->N("Medium name:") ); + $factory->createHSpacing($hbox, 1.0); + my $media_name = $factory->createInputField($hbox, "", 0); + $media_name->setWeight($yui::YD_HORIZ, 2); + + # per function layout (replace point) + my $align = $factory->createLeft($vbox); + my $replace_pnt = $factory->createReplacePoint($align); + + my $add_widgets = _build_add_dialog({replace_pnt => $replace_pnt, dialog => $dialog, + info => \%radios_infos, selected => $radios_names_ordered[0]} + ); + # check-boxes + $hbox = $factory->createHBox($factory->createLeft($vbox)); + $factory->createHSpacing($hbox, 1.3); + my $dist_media = $factory->createCheckBox($hbox, $loc->N("Create media for a whole distribution"), 0); + $hbox = $factory->createHBox($factory->createLeft($vbox)); + $factory->createHSpacing($hbox, 1.3); + my $update_media = $factory->createCheckBox($hbox, $loc->N("Tag this medium as an update medium"), 0); + $dist_media->setNotify(1); + + # Last line buttons + $factory->createVSpacing($vbox, 0.5); + $hbox = $factory->createHBox($vbox); + my $cancelButton = $factory->createPushButton($hbox, $loc->N("&Cancel")); + $factory->createHSpacing($hbox, 3.0); + my $okButton = $factory->createPushButton($hbox, $loc->N("&Ok")); + + $cancelButton->setDefaultButton(1); + + # dialog event loop + 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 + my $widget = $event->widget(); + if ($widget == $cancelButton) { + last; + } + elsif ($widget == $media_type) { + my $item = $media_type->selectedItem(); + my $sel = $item ? $item->index() : 0 ; + $add_widgets = _build_add_dialog({replace_pnt => $replace_pnt, dialog => $dialog, + info => \%radios_infos, selected => $radios_names_ordered[$sel]} + ); + } + elsif ($widget == $dist_media) { + $update_media->setEnabled(!$dist_media->value()); + } + elsif ($widget == $okButton) { + my $item = $media_type->selectedItem(); + my $sel = $item ? $item->index() : 0 ; + my $info = $radios_infos{$radios_names_ordered[$sel]}; + my $name = $media_name->value(); + my $url = $add_widgets->{url}->value(); + $name eq '' || $url eq '' and interactive_msg('rpmdragora', $loc->N("You need to fill up at least the two first entries.")), next; + if (member($name, map { $_->{name} } @{$urpm->{media}})) { + interactive_msg('rpmdragora', + $loc->N("There is already a medium called <%s>,\ndo you really want to replace it?", $name), + yesno => 1) or next; + } + + my %i = ( + name => $name, + url => $url, + distrib => $dist_media->value() ? 1 : 0, + update => $update_media->value() ? 1 : undef, + ); + my %make_url = ( + local => "file:/$i{url}", + http => $i{url}, + rsync => $i{url}, + removable => "removable:/$i{url}", + ); + $i{url} =~ s|^ftp://||; + $make_url{ftp} = sprintf "ftp://%s%s", + defined($add_widgets->{login}) + ? + $add_widgets->{login}->value() . ':' . ( $add_widgets->{pass}->value() ? + $add_widgets->{pass}->value() : + '') + : + '', + $i{url}; + + if ($i{distrib}) { + add_medium_and_check( + $urpm, + { nolock => 1, distrib => 1 }, + $i{name}, $make_url{$radios_names_ordered[$sel]}, probe_with => 'synthesis', update => $i{update}, + ); + } else { + if (member($i{name}, map { $_->{name} } @{$urpm->{media}})) { + urpm::media::select_media($urpm, $i{name}); + urpm::media::remove_selected_media($urpm); + } + add_medium_and_check( + $urpm, + { nolock => 1 }, + $i{name}, $make_url{$radios_names_ordered[$sel]}, $i{hdlist}, update => $i{update}, + ); + } + + $retVal = 1; + last; + } + else { + my $item = $media_type->selectedItem(); + my $sel = $item ? $item->index() : 0 ; + if (defined($radios_infos{$radios_names_ordered[$sel]}->{dirsel}) && + defined($add_widgets->{dirsel}) ) { + if ($widget == $add_widgets->{dirsel}) { + my $dir = yui::YUI::app()->askForExistingDirectory(home(), + $radios_infos{$radios_names_ordered[$sel]}->{url} + ); + $add_widgets->{url}->setValue($dir) if ($dir); + } + } + } + } + } +### End ### + + $dialog->destroy(); + + #restore old application title + yui::YUI::app()->setApplicationTitle($appTitle) if $appTitle; + + return $retVal; + +} + +sub options_callback() { + + my $appTitle = yui::YUI::app()->applicationTitle(); + ## set new title to get it in dialog + yui::YUI::app()->setApplicationTitle($loc->N("Global options for package installation")); + + my $factory = yui::YUI::widgetFactory; + + my $dialog = $factory->createPopupDialog(); + my $minSize = $factory->createMinSize( $dialog, 50, 5 ); + my $vbox = $factory->createVBox( $minSize ); + + my $hbox = $factory->createHBox($vbox); + $factory->createHSpacing($hbox, 1.0); + my $label = $factory->createLabel($hbox, $loc->N("Verify RPMs to be installed:") ); + $factory->createHSpacing($hbox, 3.5); + my $verify_rpm = $factory->createComboBox($hbox, "", 0); + $verify_rpm->setWeight($yui::YD_HORIZ, 2); + my @verif = ($loc->N("never"), $loc->N("always")); + my $verify_rpm_value = $urpm->{global_config}{'verify-rpm'} || 0; + + my $itemColl = new yui::YItemCollection; + my $cnt = 0; + foreach my $elem (@verif) { + my $it = new yui::YItem($elem, 0); + if ($cnt == $verify_rpm_value) { + $it->setSelected(1); + } + $itemColl->push($it); + $it->DISOWN(); + $cnt++; + } + $verify_rpm->addItems($itemColl); + + $hbox = $factory->createHBox($vbox); + $factory->createHSpacing($hbox, 1.0); + $label = $factory->createLabel($hbox, $loc->N("Download program to use:") ); + $factory->createHSpacing($hbox, 4.0); + my $downloader_entry = $factory->createComboBox($hbox, "", 0); + $downloader_entry->setWeight($yui::YD_HORIZ, 2); + + my @comboList = urpm::download::available_ftp_http_downloaders() ; + my $downloader = $urpm->{global_config}{downloader} || $comboList[0]; + + if (scalar(@comboList) > 0) { + $itemColl = new yui::YItemCollection; + foreach my $elem (@comboList) { + my $it = new yui::YItem($elem, 0); + if ($elem eq $downloader) { + $it->setSelected(1); + } + $itemColl->push($it); + $it->DISOWN(); + } + $downloader_entry->addItems($itemColl); + } + + $hbox = $factory->createHBox($vbox); + $factory->createHSpacing($hbox, 1.0); + $label = $factory->createLabel($hbox, $loc->N("XML meta-data download policy:") ); + my $xml_info_policy = $factory->createComboBox($hbox, "", 0); + $xml_info_policy->setWeight($yui::YD_HORIZ, 2); + + my @xml_info_policies = ('', 'never', 'on-demand', 'update-only', 'always'); + my @xml_info_policiesL = ('', $loc->N("Never"), $loc->N("On-demand"), $loc->N("Update-only"), $loc->N("Always")); + my $xml_info_policy_value = $urpm->{global_config}{'xml-info'}; + + $itemColl = new yui::YItemCollection; + $cnt = 0; + foreach my $elem (@xml_info_policiesL) { + my $it = new yui::YItem($elem, 0); + if ($xml_info_policy_value && $xml_info_policy_value eq $xml_info_policies[$cnt]) { + $it->setSelected(1); + } + $itemColl->push($it); + $it->DISOWN(); + $cnt++; + } + $xml_info_policy->addItems($itemColl); + + ### TODO tips ### + #tip => + #join("\n", + #$loc->N("For remote media, specify when XML meta-data (file lists, changelogs & information) are downloaded."), + #'', + #$loc->N("Never"), + #$loc->N("For remote media, XML meta-data are never downloaded."), + #'', + #$loc->N("On-demand"), + #$loc->N("(This is the default)"), + #$loc->N("The specific XML info file is downloaded when clicking on package."), + #'', + #$loc->N("Update-only"), + #$loc->N("Updating media implies updating XML info files already required at least once."), + #'', + #$loc->N("Always"), + #$loc->N("All XML info files are downloaded when adding or updating media."), + + $factory->createVSpacing($vbox, 0.5); + + + ### last line buttons + $factory->createVSpacing($vbox, 0.5); + $hbox = $factory->createHBox($vbox); + my $cancelButton = $factory->createPushButton($hbox, $loc->N("&Cancel")); + $factory->createHSpacing($hbox, 3.0); + my $okButton = $factory->createPushButton($hbox, $loc->N("&Ok")); + + $cancelButton->setDefaultButton(1); + + # dialog event loop + 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 + my $widget = $event->widget(); + if ($widget == $cancelButton) { + last; + } + elsif ($widget == $okButton) { + my $changed = 0; + my $item = $verify_rpm->selectedItem(); + if ($item->index() != $verify_rpm_value) { + $changed = 1; + $urpm->{global_config}{'verify-rpm'} = $item->index(); + } + $item = $downloader_entry->selectedItem(); + if ($item->label() ne $downloader) { + $changed = 1; + $urpm->{global_config}{downloader} = $item->label(); + } + $item = $xml_info_policy->selectedItem(); + if ($xml_info_policies[$item->index()] ne $xml_info_policy_value) { + $changed = 1; + $urpm->{global_config}{'xml-info'} = $xml_info_policies[$item->index()]; + } + if ($changed) { + urpm::media::write_config($urpm); + $urpm = fast_open_urpmi_db(); + } + + last; + } + } + } + + ### End ### + + $dialog->destroy(); + + #restore old application title + yui::YUI::app()->setApplicationTitle($appTitle) if $appTitle; + +} + +#============================================================= + +=head2 remove_callback + +=head3 INPUT + +$selection: YItemCollection (selected items) + + +=head3 DESCRIPTION + +Remove the selected medias + +=cut + +#============================================================= + +sub remove_callback { + my $selection = shift; + + my @rows; + for (my $it = 0; $it < $selection->size(); $it++) { + my $item = $selection->get($it); + push @rows, $item->index(); + } + @rows == 0 and return 0; + interactive_msg( + $loc->N("Source Removal"), + @rows == 1 ? + $loc->N("Are you sure you want to remove source \"%s\"?", $urpm->{media}[$rows[0]]{name}) : + $loc->N("Are you sure you want to remove the following sources?") . "\n\n" . + format_list(map { $urpm->{media}[$_]{name} } @rows), + yesno => 1, scroll => 1, + ) or return 0; + + my $wait = wait_msg($loc->N("Please wait, removing medium...")); + foreach my $row (reverse(@rows)) { + $something_changed = 1; + urpm::media::remove_media($urpm, [ $urpm->{media}[$row] ]); + } + urpm::media::write_urpmi_cfg($urpm); + remove_wait_msg($wait); + + return 1; +} + + +#============================================================= + +=head2 upwards_callback + +=head3 INPUT + +$table: Mirror table (YTable) + +=head3 DESCRIPTION + +Move selected item to high priority level + +=cut + +#============================================================= +sub upwards_callback { + my $table = shift; + + ## get the first + my $item = $table->selectedItem(); + !$item and return 0; + return 0 if ($item->index() == 0); + my $row = $item->index(); + my @media = ( $urpm->{media}[$row-1], $urpm->{media}[$row]); + $urpm->{media}[$row] = $media[0]; + $urpm->{media}[$row-1] = $media[1]; + + urpm::media::write_config($urpm); + $urpm = fast_open_urpmi_db(); + return $row - 1; +} + +#============================================================= + +=head2 downwards_callback + +=head3 INPUT + +$table: Mirror table (YTable) + +=head3 DESCRIPTION + +Move selected item to low priority level + +=cut + +#============================================================= +sub downwards_callback { + my $table = shift; + + ## get the first + my $item = $table->selectedItem(); + !$item and return 0; + my $row = $item->index(); + return $row if ($row >= $table->itemsCount()-1); + + my @media = ( $urpm->{media}[$row], $urpm->{media}[$row+1]); + $urpm->{media}[$row+1] = $media[0]; + $urpm->{media}[$row] = $media[1]; + + urpm::media::write_config($urpm); + $urpm = fast_open_urpmi_db(); + return $row + 1; +} + +#- returns 1 if something changed to force readMedia() +sub edit_callback { + my $table = shift; + + my $changed = 0; + ## get the first + my $item = $table->selectedItem(); + !$item and return 0; + my $row = $item->index(); + + my $medium = $urpm->{media}[$row]; + my $config = urpm::cfg::load_config_raw($urpm->{config}, 1); + my ($verbatim_medium) = grep { $medium->{name} eq $_->{name} } @$config; + + my $appTitle = yui::YUI::app()->applicationTitle(); + ## set new title to get it in dialog + yui::YUI::app()->setApplicationTitle($loc->N("Edit a medium")); + + my $factory = yui::YUI::widgetFactory; + + my $dialog = $factory->createPopupDialog(); + my $minSize = $factory->createMinSize( $dialog, 80, 5 ); + my $vbox = $factory->createVBox( $minSize ); + + my $hbox = $factory->createHBox( $factory->createLeft($vbox) ); + $factory->createHeading($hbox, $loc->N("Editing medium \"%s\":", $medium->{name})); + $factory->createVSpacing($vbox, 1.0); + + $hbox = $factory->createHBox($vbox); + $factory->createHSpacing($hbox, 1.0); + my $label = $factory->createLabel($hbox, $loc->N("URL:")); + my $url_entry = $factory->createInputField($hbox, "", 0); + $url_entry->setWeight($yui::YD_HORIZ, 2); + $url_entry->setValue($verbatim_medium->{url} || $verbatim_medium->{mirrorlist}); + + $hbox = $factory->createHBox($vbox); + $factory->createHSpacing($hbox, 1.0); + $label = $factory->createLabel($hbox, $loc->N("Downloader:") ); + my $downloader_entry = $factory->createComboBox($hbox, "", 0); + $downloader_entry->setWeight($yui::YD_HORIZ, 2); + + my @comboList = urpm::download::available_ftp_http_downloaders() ; + my $downloader = $verbatim_medium->{downloader} || $urpm->{global_config}{downloader} || $comboList[0]; + + if (scalar(@comboList) > 0) { + my $itemColl = new yui::YItemCollection; + foreach my $elem (@comboList) { + my $it = new yui::YItem($elem, 0); + if ($elem eq $downloader) { + $it->setSelected(1); + } + $itemColl->push($it); + $it->DISOWN(); + } + $downloader_entry->addItems($itemColl); + } + $factory->createVSpacing($vbox, 0.5); + + my $url = $url_entry->value(); + + $hbox = $factory->createHBox($factory->createLeft($vbox)); + $factory->createHSpacing($hbox, 1.0); + + my $tableItem = yui::toYTableItem($item); + # enabled cell 0, updates cell 1 + my $cellEnabled = $tableItem->cell(0)->label() ? 1 : 0; + my $enabled = $factory->createCheckBox($hbox, $loc->N("Enabled"), $cellEnabled); + my $cellUpdates = $tableItem->cell(1)->label() ? 1 : 0; + my $update = $factory->createCheckBox($hbox, $loc->N("Updates"), $cellUpdates); + $update->setDisabled() if (!$::expert); + + $factory->createVSpacing($vbox, 0.5); + $hbox = $factory->createHBox($vbox); + my $cancelButton = $factory->createPushButton($hbox, $loc->N("&Cancel")); + $factory->createHSpacing($hbox, 3.0); + my $saveButton = $factory->createPushButton($hbox, $loc->N("&OK")); + $factory->createHSpacing($hbox, 3.0); + my $proxyButton = $factory->createPushButton($hbox, $loc->N("&Proxy...")); + + $cancelButton->setDefaultButton(1); + + # dialog event loop + 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 + my $widget = $event->widget(); + if ($widget == $cancelButton) { + last; + } + elsif ($widget == $saveButton) { + if ($cellEnabled != $enabled->value()) { + $urpm->{media}[$row]{ignore} = !$urpm->{media}[$row]{ignore} || undef; + $changed = 1; + } + if ($cellUpdates != $update->value()) { + $urpm->{media}[$row]{update} = !$urpm->{media}[$row]{update} || undef; + $changed = 1; + } + if ( $changed ) { + urpm::media::write_config($urpm); + } + + my ($m_name, $m_update) = map { $medium->{$_} } qw(name update); + # TODO check if really changed first + $url = $url_entry->value(); + $downloader = $downloader_entry->value(); + $url =~ m|^removable://| and ( + interactive_msg( + $loc->N("You need to insert the medium to continue"), + $loc->N("In order to save the changes, you need to insert the medium in the drive."), + yesno => 1, text => { yes => $loc->N("Ok"), no => $loc->N("Cancel") } + ) or return 0 + ); + my $saved_proxy = urpm::download::get_proxy($m_name); + undef $saved_proxy if !defined $saved_proxy->{http_proxy} && !defined $saved_proxy->{ftp_proxy}; + urpm::media::select_media($urpm, $m_name); + if (my ($media) = grep { $_->{name} eq $m_name } @{$urpm->{media}}) { + MDK::Common::DataStructure::put_in_hash($media, { + ($verbatim_medium->{mirrorlist} ? 'mirrorlist' : 'url') => $url, + name => $m_name, + if_($m_update && $m_update ne $media->{update} || $m_update, update => $m_update), + if_($saved_proxy && $saved_proxy ne $media->{proxy} || $saved_proxy, proxy => $saved_proxy), + if_($downloader ne $media->{downloader} || $downloader, downloader => $downloader), + modified => 1, + }); + urpm::media::write_config($urpm); + update_sources_noninteractive($urpm, [ $m_name ]); + } else { + urpm::media::remove_selected_media($urpm); + add_medium_and_check($urpm, { nolock => 1, proxy => $saved_proxy }, $m_name, $url, undef, update => $m_update, if_($downloader, downloader => $downloader)); + } + last; + } + elsif ($widget == $proxyButton) { + proxy_callback($medium); + } + } + } +### End ### + + $dialog->destroy(); + + #restore old application title + yui::YUI::app()->setApplicationTitle($appTitle) if $appTitle; + + return $changed; +} + +sub update_callback() { + update_sources_interactive($urpm, transient => $::main_window, nolock => 1); +} + +#============================================================= + +=head2 proxy_callback + +=head3 INPUT + +$medium: the medium which proxy is going to be modified + +=head3 DESCRIPTION + +Set or change the proxy settings for the given media. +Note that Ok button saves the changes. + +=cut + +#============================================================= +sub proxy_callback { + my ($medium) = @_; + my $medium_name = $medium ? $medium->{name} : ''; + + my ($proxy, $proxy_user) = readproxy($medium_name); + my ($user, $pass) = $proxy_user =~ /^([^:]*):(.*)$/; + + my $appTitle = yui::YUI::app()->applicationTitle(); + ## set new title to get it in dialog + yui::YUI::app()->setApplicationTitle($loc->N("Configure proxies")); + + my $factory = yui::YUI::widgetFactory; + + my $dialog = $factory->createPopupDialog(); + my $minSize = $factory->createMinSize( $dialog, 80, 5 ); + my $vbox = $factory->createVBox( $minSize ); + + my $hbox = $factory->createHBox( $factory->createLeft($vbox) ); + $factory->createHeading($hbox, + $medium_name + ? $loc->N("Proxy settings for media \"%s\"", $medium_name) + : $loc->N("Global proxy settings")); + $factory->createVSpacing($vbox, 0.5); + + $hbox = $factory->createHBox($vbox); + $factory->createHSpacing($hbox, 1.0); + my $label = $factory->createLabel($hbox, $loc->N("If you need a proxy, enter the hostname and an optional port (syntax: ):")); + $factory->createVSpacing($vbox, 0.5); + + my ($proxybutton, $proxyentry, $proxyuserbutton, $proxyuserentry, $proxypasswordentry); + + $hbox = $factory->createHBox($factory->createLeft($vbox)); + $proxybutton = $factory->createCheckBoxFrame($hbox, $loc->N("Enable proxy"), 1); + my $frm_vbox = $factory->createVBox( $proxybutton ); + my $align = $factory->createRight($frm_vbox); + $hbox = $factory->createHBox($align); + $label = $factory->createLabel($hbox, $loc->N("Proxy hostname:") ); + $proxyentry = $factory->createInputField($hbox, "", 0); + $label->setWeight($yui::YD_HORIZ, 1); + $proxyentry->setWeight($yui::YD_HORIZ, 2); + $proxyuserbutton = $factory->createCheckBoxFrame($factory->createLeft($frm_vbox), + $loc->N("You may specify a username/password for the proxy authentication:"), 1); + $proxyentry->setValue($proxy) if $proxy; + + $frm_vbox = $factory->createVBox( $proxyuserbutton ); + + ## proxy user name + $align = $factory->createRight($frm_vbox); + $hbox = $factory->createHBox($align); + $label = $factory->createLabel($hbox, $loc->N("User:") ); + $proxyuserentry = $factory->createInputField($hbox, "", 0); + $label->setWeight($yui::YD_HORIZ, 1); + $proxyuserentry->setWeight($yui::YD_HORIZ, 2); + $proxyuserentry->setValue($user) if $user; + + ## proxy user password + $align = $factory->createRight($frm_vbox); + $hbox = $factory->createHBox($align); + $label = $factory->createLabel($hbox, $loc->N("Password:") ); + $proxypasswordentry = $factory->createInputField($hbox, "", 1); + $label->setWeight($yui::YD_HORIZ, 1); + $proxypasswordentry->setWeight($yui::YD_HORIZ, 2); + $proxypasswordentry->setValue($pass) if $pass; + + $proxyuserbutton->setValue ($proxy_user ? 1 : 0); + $proxybutton->setValue ($proxy ? 1 : 0); + + # dialog low level buttons + $factory->createVSpacing($vbox, 0.5); + $hbox = $factory->createHBox($vbox); + my $okButton = $factory->createPushButton($hbox, $loc->N("&Ok")); + $factory->createHSpacing($hbox, 3.0); + my $cancelButton = $factory->createPushButton($hbox, $loc->N("&Cancel")); + + $cancelButton->setDefaultButton(1); + + # dialog event loop + 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 + my $widget = $event->widget(); + if ($widget == $cancelButton) { + last; + } + elsif ($widget == $okButton) { + $proxy = $proxybutton->value() ? $proxyentry->value() : ''; + $proxy_user = $proxyuserbutton->value() + ? ($proxyuserentry->value() . ':' . $proxypasswordentry->value()) : ''; + + writeproxy($proxy, $proxy_user, $medium_name); + last; + } + } + } + +### End ### + $dialog->destroy(); + + #restore old application title + yui::YUI::app()->setApplicationTitle($appTitle) if $appTitle; + +} + +sub parallel_read_sysconf() { + my @conf; + foreach (MDK::Common::File::cat_('/etc/urpmi/parallel.cfg')) { + my ($name, $protocol, $command) = /([^:]+):([^:]+):(.*)/ or print STDERR "Warning, unrecognized line in /etc/urpmi/parallel.cfg:\n$_"; + my $medias = $protocol =~ s/\(([^\)]+)\)$// ? [ split /,/, $1 ] : []; + push @conf, { name => $name, protocol => $protocol, medias => $medias, command => $command }; + } + \@conf; +} + +sub parallel_write_sysconf { + my ($conf) = @_; + output '/etc/urpmi/parallel.cfg', + map { my $m = @{$_->{medias}} ? '(' . join(',', @{$_->{medias}}) . ')' : ''; + "$_->{name}:$_->{protocol}$m:$_->{command}\n" } @$conf; +} + +sub remove_parallel { + my ($num, $conf) = @_; + if ($num != -1) { + splice @$conf, $num, 1; + parallel_write_sysconf($conf); + } +} + +sub add_callback_ { + my ($title, $label, $mainw, $widget, $get_value, $check) = @_; + my $w = ugtk2->new($title, grab => 1, transient => $mainw->{real_window}); + local $::main_window = $w->{real_window}; + gtkadd( + $w->{window}, + gtkpack__( + gtknew('VBox', spacing => 5), + gtknew('Label', text => $label), + $widget, + gtknew('HSeparator'), + gtkpack( + gtknew('HButtonBox'), + gtknew('Button', text => $loc->N("Ok"), clicked => sub { $w->{retval} = 1; $get_value->(); Gtk2->main_quit }), + gtknew('Button', text => $loc->N("Cancel"), clicked => sub { $w->{retval} = 0; Gtk2->main_quit }) + ) + ) + ); + $check->() if $w->main; +} + +sub edit_parallel { + my ($num, $conf) = @_; + my $edited = $num == -1 ? {} : $conf->[$num]; + my $w = ugtk2->new($num == -1 ? $loc->N("Add a parallel group") : $loc->N("Edit a parallel group"), grab => 1, center => 1, transient => $::main_window); + local $::main_window = $w->{real_window}; + my $name_entry; + + my ($medias_ls, $hosts_ls) = (Gtk2::ListStore->new("Glib::String"), Gtk2::ListStore->new("Glib::String")); + + my ($medias, $hosts) = map { + my $list = Gtk2::TreeView->new_with_model($_); + $list->append_column(Gtk2::TreeViewColumn->new_with_attributes(undef, Gtk2::CellRendererText->new, 'text' => 0)); + $list->set_headers_visible(0); + $list->get_selection->set_mode('browse'); + $list; + } $medias_ls, $hosts_ls; + + $medias_ls->append_set([ 0 => $_ ]) foreach @{$edited->{medias}}; + + my $add_media = sub { + my $medias_list_ls = Gtk2::ListStore->new("Glib::String"); + my $medias_list = Gtk2::TreeView->new_with_model($medias_list_ls); + $medias_list->append_column(Gtk2::TreeViewColumn->new_with_attributes(undef, Gtk2::CellRendererText->new, 'text' => 0)); + $medias_list->set_headers_visible(0); + $medias_list->get_selection->set_mode('browse'); + $medias_list_ls->append_set([ 0 => $_->{name} ]) foreach @{$urpm->{media}}; + my $sel; + add_callback_($loc->N("Add a medium limit"), $loc->N("Choose a medium to add to the media limit:"), + $w, $medias_list, sub { $sel = selrow($medias_list) }, + sub { + return if $sel == -1; + my $media = ${$urpm->{media}}[$sel]{name}; + $medias_ls->append_set([ 0 => $media ]); + push @{$edited->{medias}}, $media; + } + ); + }; + + my $hosts_list; + if ($edited->{protocol} eq 'ssh') { $hosts_list = [ split /:/, $edited->{command} ] } + elsif ($edited->{protocol} eq 'ka-run') { push @$hosts_list, $1 while $edited->{command} =~ /-m (\S+)/g } + $hosts_ls->append_set([ 0 => $_ ]) foreach @$hosts_list; + my $add_host = sub { + my ($entry, $value); + add_callback_($loc->N("Add a host"), $loc->N("Type in the hostname or IP address of the host to add:"), + $mainw, $entry = gtkentry(), sub { $value = $entry->get_text }, + sub { $hosts_ls->append_set([ 0 => $value ]); push @$hosts_list, $value } + ); + }; + + my @protocols_names = qw(ka-run ssh); + my @protocols; + gtkadd( + $w->{window}, + gtkpack_( + gtknew('VBox', spacing => 5), + if_( + $num != -1, + 0, gtknew('Label', text => $loc->N("Editing parallel group \"%s\":", $edited->{name})) + ), + 1, create_packtable( + {}, + [ $loc->N("Group name:"), $name_entry = gtkentry($edited->{name}) ], + [ $loc->N("Protocol:"), gtknew('HBox', children_tight => [ + @protocols = gtkradio($edited->{protocol}, @protocols_names) ]) ], + [ $loc->N("Media limit:"), + gtknew('HBox', spacing => 5, children => [ + 1, gtknew('Frame', shadow_type => 'in', child => + gtknew('ScrolledWindow', h_policy => 'never', child => $medias)), + 0, gtknew('VBox', children_tight => [ + gtksignal_connect(Gtk2::Button->new(but($loc->N("Add"))), clicked => sub { $add_media->() }), + gtksignal_connect(Gtk2::Button->new(but($loc->N("Remove"))), clicked => sub { + remove_from_list($medias, $edited->{medias}, $medias_ls); + }) ]) ]) ], + [ $loc->N("Hosts:"), + gtknew('HBox', spacing => 5, children => [ + 1, gtknew('Frame', shadow_type => 'in', child => + gtknew('ScrolledWindow', h_policy => 'never', child => $hosts)), + 0, gtknew('VBox', children_tight => [ + gtksignal_connect(Gtk2::Button->new(but($loc->N("Add"))), clicked => sub { $add_host->() }), + gtksignal_connect(Gtk2::Button->new(but($loc->N("Remove"))), clicked => sub { + remove_from_list($hosts, $hosts_list, $hosts_ls); + }) ]) ]) ] + ), + 0, gtknew('HSeparator'), + 0, gtkpack( + gtknew('HButtonBox'), + gtksignal_connect( + gtknew('Button', text => $loc->N("Ok")), clicked => sub { + $w->{retval} = 1; + $edited->{name} = $name_entry->get_text; + mapn { $_[0]->get_active and $edited->{protocol} = $_[1] } \@protocols, \@protocols_names; + Gtk2->main_quit; + } + ), + gtknew('Button', text => $loc->N("Cancel"), clicked => sub { $w->{retval} = 0; Gtk2->main_quit })) + ) + ); + $w->{rwindow}->set_size_request(600, -1); + if ($w->main) { + $num == -1 and push @$conf, $edited; + if ($edited->{protocol} eq 'ssh') { $edited->{command} = join(':', @$hosts_list) } + if ($edited->{protocol} eq 'ka-run') { $edited->{command} = "-c ssh " . join(' ', map { "-m $_" } @$hosts_list) } + parallel_write_sysconf($conf); + return 1; + } + return 0; +} + +sub parallel_callback() { + my $w = ugtk2->new($loc->N("Configure parallel urpmi (distributed execution of urpmi)"), grab => 1, center => 1, transient => $mainw->{real_window}); + local $::main_window = $w->{real_window}; + my $list_ls = Gtk2::ListStore->new("Glib::String", "Glib::String", "Glib::String", "Glib::String"); + my $list = Gtk2::TreeView->new_with_model($list_ls); + each_index { $list->append_column(Gtk2::TreeViewColumn->new_with_attributes($_, Gtk2::CellRendererText->new, 'text' => $::i)) } $loc->N("Group"), $loc->N("Protocol"), $loc->N("Media limit"); + $list->append_column(my $commandcol = Gtk2::TreeViewColumn->new_with_attributes($loc->N("Command"), Gtk2::CellRendererText->new, 'text' => 3)); + $commandcol->set_max_width(200); + + my $conf; + my $reread = sub { + $list_ls->clear; + $conf = parallel_read_sysconf(); + foreach (@$conf) { + $list_ls->append_set([ 0 => $_->{name}, + 1 => $_->{protocol}, + 2 => @{$_->{medias}} ? join(', ', @{$_->{medias}}) : $loc->N("(none)"), + 3 => $_->{command} ]); + } + }; + $reread->(); + + gtkadd( + $w->{window}, + gtkpack_( + gtknew('VBox', spacing => 5), + 1, gtkpack_( + gtknew('HBox', spacing => 10), + 1, $list, + 0, gtkpack__( + gtknew('VBox', spacing => 5), + gtksignal_connect( + Gtk2::Button->new(but($loc->N("Remove"))), + clicked => sub { remove_parallel(selrow($list), $conf); $reread->() }, + ), + gtksignal_connect( + Gtk2::Button->new(but($loc->N("Edit..."))), + clicked => sub { + my $row = selrow($list); + $row != -1 and edit_parallel($row, $conf); + $reread->(); + }, + ), + gtksignal_connect( + Gtk2::Button->new(but($loc->N("Add..."))), + clicked => sub { edit_parallel(-1, $conf) and $reread->() }, + ) + ) + ), + 0, gtknew('HSeparator'), + 0, gtkpack( + gtknew('HButtonBox'), + gtknew('Button', text => $loc->N("Ok"), clicked => sub { Gtk2->main_quit }) + ) + ) + ); + $w->main; +} + +sub keys_callback() { + my $changed = 0; + my $appTitle = yui::YUI::app()->applicationTitle(); + + ## set new title to get it in dialog + yui::YUI::app()->setApplicationTitle($loc->N("Manage keys for digital signatures of packages")); + + my $factory = yui::YUI::widgetFactory; + + my $dialog = $factory->createPopupDialog(); + my $minSize = $factory->createMinSize( $dialog, 80, 20 ); + my $vbox = $factory->createVBox( $minSize ); + + my $hbox_headbar = $factory->createHBox($vbox); + 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 $hbox_content = $factory->createHBox($vbox); + my $leftContent = $factory->createLeft($hbox_content); + $leftContent->setWeight($yui::YD_HORIZ,3); + + my $frame = $factory->createFrame ($leftContent, ""); + + my $frmVbox = $factory->createVBox( $frame ); + my $hbox = $factory->createHBox( $frmVbox ); + + ## media list + my $yTableHeader = new yui::YTableHeader(); + $yTableHeader->addColumn($loc->N("Medium"), $yui::YAlignBegin); + my $multiselection = 0; + my $mediaTbl = $factory->createTable($hbox, $yTableHeader, $multiselection); + $mediaTbl->setKeepSorting(1); + $mediaTbl->setImmediateMode(1); + + my $itemColl = new yui::YItemCollection; + foreach (@{$urpm->{media}}) { + my $name = $_->{name}; + + my $item = new yui::YTableItem ($name); + # NOTE row is $item->index() + $item->setLabel( $name ); + $itemColl->push($item); + $item->DISOWN(); + } + $mediaTbl->addItems($itemColl); + + ## key list + $leftContent = $factory->createLeft($hbox_content); + $leftContent->setWeight($yui::YD_HORIZ,3); + $frame = $factory->createFrame ($leftContent, ""); + $frmVbox = $factory->createVBox( $frame ); + $hbox = $factory->createHBox( $frmVbox ); + $yTableHeader = new yui::YTableHeader(); + $yTableHeader->addColumn($loc->N("Keys"), $yui::YAlignBegin); + $multiselection = 0; + my $keyTbl = $factory->createTable($hbox, $yTableHeader, $multiselection); + $keyTbl->setKeepSorting(1); + + my ($current_medium, $current_medium_nb, @keys); + + ### internal subroutines + my $read_conf = sub { + $urpm->parse_pubkeys(root => $urpm->{root}); + @keys = map { [ split /[,\s]+/, ($_->{'key-ids'} || '') ] } @{$urpm->{media}}; + }; + + my $write = sub { + $something_changed = 1; + urpm::media::write_config($urpm); + $urpm = fast_open_urpmi_db(); + $read_conf->(); + }; + + $read_conf->(); + + my $key_name = sub { + exists $urpm->{keys}{$_[0]} ? $urpm->{keys}{$_[0]}{name} + : $loc->N("no name found, key doesn't exist in rpm keyring!"); + }; + + my $sel_changed = sub { + my $item = $mediaTbl->selectedItem(); + if ($item) { + $current_medium = $item->label(); + $current_medium_nb = $item->index(); + + yui::YUI::app()->busyCursor(); + yui::YUI::ui()->blockEvents(); + $dialog->startMultipleChanges(); + + $keyTbl->deleteAllItems(); + my $itemColl = new yui::YItemCollection; + foreach ( @{$keys[$current_medium_nb]} ) { + my $it = new yui::YTableItem (sprintf("%s (%s)", $_, $key_name->($_))); + # NOTE row is $item->index() + $it->setLabel( $_ ); + $itemColl->push($it); + $it->DISOWN(); + } + $keyTbl->addItems($itemColl); + + $dialog->recalcLayout(); + $dialog->doneMultipleChanges(); + yui::YUI::ui()->unblockEvents(); + yui::YUI::app()->normalCursor(); + } + }; + + my $add_key = sub { + my $sh_gui = ManaTools::Shared::GUI->new(); + my $item = $mediaTbl->selectedItem(); + if ($item) { + $current_medium = $item->label(); + $current_medium_nb = $item->index(); + my @list; + my %key; + foreach (keys %{$urpm->{keys}}) { + my $k = sprintf("%s (%s)", $_, $key_name->($_)); + $key{$k} = $_; + push @list, $k; + } + + my $choice = $sh_gui->ask_fromList({ + title => $loc->N("Add a key"), + header => $loc->N("Choose a key to add to the medium %s", $current_medium), + list => \@list, + }); + if ($choice) { + my $k = $key{$choice}; + $urpm->{media}[$current_medium_nb]{'key-ids'} = join(',', sort(uniq(@{$keys[$current_medium_nb]}, $k))); + $write->(); + return 1; + } + } + return 0; + }; + + my $remove_key = sub { + my $sh_gui = ManaTools::Shared::GUI->new(); + my $keyItem = $keyTbl->selectedItem(); + my $mediaItem = $mediaTbl->selectedItem(); + if ($keyItem && $mediaItem) { + $current_medium = $mediaItem->label(); + $current_medium_nb = $mediaItem->index(); + my $current_key = $keyItem->label(); + my $current_keyVal = yui::toYTableItem($keyItem)->cell(0)->label(); + my $choice = $sh_gui->ask_YesOrNo({ + title => $loc->N("Remove a key"), + text => $loc->N("Are you sure you want to remove the key
%s
from medium %s?
(name of the key: %s)", + $current_keyVal, $current_medium, $current_key + ), + richtext => 1, + }); + if ($choice) { + $urpm->{media}[$current_medium_nb]{'key-ids'} = join(',', + difference2(\@{$keys[$current_medium_nb]}, [ $current_key ]) + ); + $write->(); + return 1; + } + } + + return 0; + + }; + + + #### end subroutines + $sel_changed->(); + + my $rightContent = $factory->createRight($hbox_content); + $rightContent->setWeight($yui::YD_HORIZ,1); + my $topContent = $factory->createTop($rightContent); + my $vbox_commands = $factory->createVBox($topContent); + $factory->createVSpacing($vbox_commands, 1.0); + my $addButton = $factory->createPushButton($factory->createHBox($vbox_commands), $loc->N("Add")); + my $remButton = $factory->createPushButton($factory->createHBox($vbox_commands), $loc->N("Remove")); + + # dialog buttons + $factory->createVSpacing($vbox, 1.0); + $hbox = $factory->createHBox( $vbox ); + + ### Close button + my $closeButton = $factory->createPushButton($hbox, $loc->N("&Quit") ); + + ### dialog event loop + while(1) { + my $event = $dialog->waitForEvent(); + my $eventType = $event->eventType(); + my $changed = 0; + my $selection_changed = 0; + + #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 == $addButton) { + $changed = $add_key->(); + $sel_changed->() if $changed; + } + elsif ($widget == $remButton) { + $changed = $remove_key->(); + $sel_changed->() if $changed; + } + elsif ($widget == $mediaTbl) { + $sel_changed->(); + } + } + } + + $dialog->destroy(); + + #restore old application title + yui::YUI::app()->setApplicationTitle($appTitle) if $appTitle; + + return $changed; +} + +#============================================================= + +=head2 readMedia + +=head3 INPUT + +$name: optional parameter, the media called name has to be + updated + +=head3 OUTPUT + +$itemColl: yui::YItemCollection containing media data to + be added to the YTable + +=head3 DESCRIPTION + +This method reads the configured media and add their info +to the collection + +=cut + +#============================================================= +sub readMedia { + my ($name) = @_; + if (defined $name) { + urpm::media::select_media($urpm, $name); + update_sources_check( + $urpm, + { nolock => 1 }, + $loc->N_("Unable to update medium, errors reported:\n\n%s"), + $name, + ); + } + # reread configuration after updating media else ignore bit will be restored + # by urpm::media::check_existing_medium(): + $urpm = fast_open_urpmi_db(); + + my $itemColl = new yui::YItemCollection; + foreach (grep { ! $_->{external} } @{$urpm->{media}}) { + my $name = $_->{name}; + + my $item = new yui::YTableItem (($_->{ignore} ? "" : "X"), + ($_->{update} ? "X" : ""), + get_medium_type($_), + $name); + ## NOTE anaselli: next lines add check icon to cells, but they are 8x8, a dimension should + ## be evaluated by font size, so disabled atm +# my $cell = $item->cell(0); # Checked +# my $checkedIcon = File::ShareDir::dist_file(ManaTools::Shared::distName(), 'images/Check_8x8.png'); +# +# $cell->setIconName($checkedIcon) if (!$_->{ignore}); +# $cell = $item->cell(1); # Updates +# $cell->setIconName($checkedIcon) if ($_->{update}); + ## end icons on cells + + # TODO manage to_bool($::expert) + # row # is $item->index() + $item->setLabel( $name ); + $itemColl->push($item); + $item->DISOWN(); + } + + return $itemColl; +} + +#============================================================= + +=head2 selectRow + +=head3 INPUT + +$itemCollection: YItem collection in which to find the item that + has to be selected +$row: line to be selected + +=head3 DESCRIPTION + +Select item at row position +=cut + +#============================================================= + +sub selectRow { + my ($itemCollection, $row) = @_; + + return if !$itemCollection; + + for (my $it = 0; $it < $itemCollection->size(); $it++) { + my $item = $itemCollection->get($it); + if ($it == $row) { + $item->setSelected(1); + return; + } + } +} + +#============================================================= + +=head2 _showMediaStatus + +=head3 INPUT + +$info: HASH reference containing + item => selected item + updates => updates checkbox widget + enabled => enabled checkbox widget + +=head3 DESCRIPTION + +This internal function enables/disables checkboxes according to the +passed item value. + +=cut + +#============================================================= +sub _showMediaStatus { + my $info = shift; + + die "Updates checkbox is mandatory" if !defined($info->{updates}) || !$info->{updates}; + die "Enabled checkbox is mandatory" if !defined($info->{enabled}) || !$info->{enabled}; + + if (defined($info->{item})) { + my $tableItem = yui::toYTableItem($info->{item}); + # enabled cell 0, updates cell 1 + my $cellEnabled = $tableItem && $tableItem->cell(0)->label() ? 1 : 0; + my $cellUpdates = $tableItem && $tableItem->cell(1)->label() ? 1 : 0; + $info->{enabled}->setValue($cellEnabled); + $info->{updates}->setValue($cellUpdates); + } + else { + $info->{enabled}->setDisabled(); + $info->{updates}->setDisabled(); + } +} + +sub mainwindow() { + + my $something_changed = 0; + my $appTitle = yui::YUI::app()->applicationTitle(); + + ## set new title to get it in dialog + yui::YUI::app()->setApplicationTitle($loc->N("Configure media")); + ## set icon if not already set by external launcher TODO + yui::YUI::app()->setApplicationIcon("/usr/share/mcc/themes/default/rpmdrake-mdk.png"); + + my $mageiaPlugin = "mga"; + my $factory = yui::YUI::widgetFactory; + + my $dialog = $factory->createMainDialog; + my $vbox = $factory->createVBox( $dialog ); + + my $hbox_headbar = $factory->createHBox($vbox); + 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,$loc->N("File")), + update => new yui::YMenuItem($loc->N("Update")), + add_media => new yui::YMenuItem($loc->N("Add a specific media mirror")), + custom => new yui::YMenuItem($loc->N("Add a custom medium")), + quit => new yui::YMenuItem($loc->N("&Quit")), + ); + + my @ordered_menu_lines = qw(update add_media custom quit); + foreach (@ordered_menu_lines) { + $fileMenu{ widget }->addItem($fileMenu{ $_ }); + } + $fileMenu{ widget }->rebuildMenuTree(); + + my %optionsMenu = ( + widget => $factory->createMenuButton($headbar, $loc->N("&Options")), + global => new yui::YMenuItem($loc->N("Global options")), + man_keys => new yui::YMenuItem($loc->N("Manage keys")), + parallel => new yui::YMenuItem($loc->N("Parallel")), + proxy => new yui::YMenuItem($loc->N("Proxy")), + ); + @ordered_menu_lines = qw(global man_keys parallel proxy); + foreach (@ordered_menu_lines) { + $optionsMenu{ widget }->addItem($optionsMenu{ $_ }); + } + $optionsMenu{ widget }->rebuildMenuTree(); + + my %helpMenu = ( + widget => $factory->createMenuButton($headRight, $loc->N("&Help")), + help => new yui::YMenuItem($loc->N("Manual")), + report_bug => new yui::YMenuItem($loc->N("Report Bug")), + about => new yui::YMenuItem($loc->N("&About")), + ); + @ordered_menu_lines = qw(help report_bug about); + foreach (@ordered_menu_lines) { + $helpMenu{ widget }->addItem($helpMenu{ $_ }); + } + $helpMenu{ widget }->rebuildMenuTree(); + +# my %contextMenu = ( +# enable => $loc->N("Enable/Disable"), +# update => $loc->N("Check as updates"), +# ); +# @ordered_menu_lines = qw(enable update); +# my $itemColl = new yui::YItemCollection; +# foreach (@ordered_menu_lines) { +# # last if (!$::expert && $_ eq "update"); +# my $item = new yui::YMenuItem($contextMenu{$_}); +# $item->DISOWN(); +# $itemColl->push($item); +# } +# yui::YUI::app()->openContextMenu($itemColl) or die "Cannot create contextMenu"; + + my $hbox_content = $factory->createHBox($vbox); + my $leftContent = $factory->createLeft($hbox_content); + $leftContent->setWeight($yui::YD_HORIZ,3); + + my $frame = $factory->createFrame ($leftContent, ""); + + my $frmVbox = $factory->createVBox( $frame ); + my $hbox = $factory->createHBox( $frmVbox ); + + my $yTableHeader = new yui::YTableHeader(); + $yTableHeader->addColumn($loc->N("Enabled"), $yui::YAlignCenter); + $yTableHeader->addColumn($loc->N("Updates"), $yui::YAlignCenter); + $yTableHeader->addColumn($loc->N("Type"), $yui::YAlignBegin); + $yTableHeader->addColumn($loc->N("Medium"), $yui::YAlignBegin); + + ## mirror list + my $multiselection = 1; + my $mirrorTbl = $factory->createTable($hbox, $yTableHeader, $multiselection); + $mirrorTbl->setKeepSorting(1); + $mirrorTbl->setImmediateMode(1); + + my $itemCollection = readMedia(); + selectRow($itemCollection, 0); #default selection + $mirrorTbl->addItems($itemCollection); + + my $rightContent = $factory->createRight($hbox_content); + $rightContent->setWeight($yui::YD_HORIZ,1); + my $topContent = $factory->createTop($rightContent); + my $vbox_commands = $factory->createVBox($topContent); + $factory->createVSpacing($vbox_commands, 1.0); + my $remButton = $factory->createPushButton($factory->createHBox($vbox_commands), $loc->N("Remove")); + my $edtButton = $factory->createPushButton($factory->createHBox($vbox_commands), $loc->N("Edit")); + my $addButton = $factory->createPushButton($factory->createHBox($vbox_commands), $loc->N("Add")); + + $hbox = $factory->createHBox( $vbox_commands ); + my $item = $mirrorTbl->selectedItem(); + $factory->createHSpacing($hbox, 1.0); + my $enabled = $factory->createCheckBox($factory->createLeft($hbox), $loc->N("Enabled")); + my $update = $factory->createCheckBox($factory->createLeft($hbox), $loc->N("Updates")); + _showMediaStatus({item => $item, enabled => $enabled, updates => $update}); + $update->setNotify(1); + $enabled->setNotify(1); + $update->setDisabled() if (!$::expert); + + $hbox = $factory->createHBox( $vbox_commands ); + ## TODO icon and label for ncurses + my $upIcon = File::ShareDir::dist_file(ManaTools::Shared::distName(), 'images/Up_16x16.png'); + my $downIcon = File::ShareDir::dist_file(ManaTools::Shared::distName(), 'images/Down_16x16.png'); + my $upButton = $factory->createPushButton($factory->createHBox($hbox), $loc->N("Up")); + my $downButton = $factory->createPushButton($factory->createHBox($hbox), $loc->N("Down")); + $upButton->setIcon($upIcon); + $downButton->setIcon($downIcon); + + $addButton->setWeight($yui::YD_HORIZ,1); + $edtButton->setWeight($yui::YD_HORIZ,1); + $remButton->setWeight($yui::YD_HORIZ,1); + $upButton->setWeight($yui::YD_HORIZ,1); + $downButton->setWeight($yui::YD_HORIZ,1); + + + # dialog buttons + $factory->createVSpacing($vbox, 1.0); + ## Window push buttons + $hbox = $factory->createHBox( $vbox ); + my $align = $factory->createLeft($hbox); + $hbox = $factory->createHBox($align); + + my $helpButton = $factory->createPushButton($hbox, $loc->N("Help") ); + $align = $factory->createRight($hbox); + $hbox = $factory->createHBox($align); + + ### Close button + my $closeButton = $factory->createPushButton($hbox, $loc->N("&Quit") ); + + ### dialog event loop + while(1) { + my $event = $dialog->waitForEvent(); + my $eventType = $event->eventType(); + my $changed = 0; + my $selection_changed = 0; + + #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()) { + my $translators = $loc->N("_: Translator(s) name(s) & email(s)\n"); + $translators =~ s/\/\>\;/g; + my $sh_gui = ManaTools::Shared::GUI->new(); + $sh_gui->AboutDialog({ name => "Rpmdragora", + version => $VERSION, + credits => $loc->N("Copyright (C) %s Mageia community", '2013-2014'), + license => $loc->N("GPLv2"), + description => $loc->N("Rpmdragora is the Mageia package management tool."), + authors => $loc->N("

Developers

+
  • %s
  • +
  • %s
  • +
+

Translators

+
  • %s
", + "Angelo Naselli <anaselli\@linux.it>", + "Matteo Pasotti <matteo.pasotti\@gmail.com>", + $translators + ), + } + ); + } + elsif ($menuLabel eq $fileMenu{ update }->label()) { + update_callback(); + } + elsif ($menuLabel eq $fileMenu{ add_media }->label()) { + $changed = easy_add_callback_with_mirror(); + } + elsif ($menuLabel eq $fileMenu{ custom }->label()) { + $changed = add_callback(); + } + elsif ($menuLabel eq $optionsMenu{ proxy }->label()) { + proxy_callback(); + } + elsif ($menuLabel eq $optionsMenu{ global }->label()) { + options_callback(); + } + elsif ($menuLabel eq $optionsMenu{ man_keys }->label()) { + $changed = keys_callback(); + } + elsif ($menuLabel eq $optionsMenu{ parallel }->label()) { +# parallel_callback(); + } + } + elsif ($eventType == $yui::YEvent::WidgetEvent) { + # widget selected + my $widget = $event->widget(); + my $wEvent = yui::toYWidgetEvent($event); + + if ($widget == $closeButton) { + last; + } + elsif ($widget == $helpButton) { + } + elsif ($widget == $upButton) { + yui::YUI::app()->busyCursor(); + yui::YUI::ui()->blockEvents(); + $dialog->startMultipleChanges(); + + my $row = upwards_callback($mirrorTbl); + + $mirrorTbl->deleteAllItems(); + my $itemCollection = readMedia(); + selectRow($itemCollection, $row); + $mirrorTbl->addItems($itemCollection); + + $dialog->recalcLayout(); + $dialog->doneMultipleChanges(); + yui::YUI::ui()->unblockEvents(); + yui::YUI::app()->normalCursor(); + } + elsif ($widget == $downButton) { + yui::YUI::app()->busyCursor(); + yui::YUI::ui()->blockEvents(); + $dialog->startMultipleChanges(); + + my $row = downwards_callback($mirrorTbl); + + $mirrorTbl->deleteAllItems(); + my $itemCollection = readMedia(); + selectRow($itemCollection, $row); + $mirrorTbl->addItems($itemCollection); + + $dialog->recalcLayout(); + $dialog->doneMultipleChanges(); + yui::YUI::ui()->unblockEvents(); + yui::YUI::app()->normalCursor(); + } + elsif ($widget == $edtButton) { + my $item = $mirrorTbl->selectedItem(); + if ($item && edit_callback($mirrorTbl) ) { + my $row = $item->index(); + yui::YUI::app()->busyCursor(); + yui::YUI::ui()->blockEvents(); + + $dialog->startMultipleChanges(); + + my $ignored = $urpm->{media}[$row]{ignore}; + my $itemCollection = readMedia(); + if (!$ignored && $urpm->{media}[$row]{ignore}) { + # reread media failed to un-ignore an ignored medium + # probably because urpm::media::check_existing_medium() complains + # about missing synthesis when the medium never was enabled before; + # thus it restored the ignore bit + $urpm->{media}[$row]{ignore} = !$urpm->{media}[$row]{ignore} || undef; + urpm::media::write_config($urpm); + #- Enabling this media failed, force update + interactive_msg('rpmdragora', + $loc->N("This medium needs to be updated to be usable. Update it now?"), + yesno => 1, + ) and $itemCollection = readMedia($urpm->{media}[$row]{name}); + } + $mirrorTbl->deleteAllItems(); + selectRow($itemCollection, $row); + $mirrorTbl->addItems($itemCollection); + + $dialog->recalcLayout(); + $dialog->doneMultipleChanges(); + yui::YUI::ui()->unblockEvents(); + yui::YUI::app()->normalCursor(); + $selection_changed = 1; # to align $enabled and $update status + } + } + elsif ($widget == $remButton) { + my $sel = $mirrorTbl->selectedItems(); + $changed = remove_callback($sel); + } + elsif ($widget == $addButton) { + $changed = easy_add_callback(); + } + elsif ($widget == $update) { + my $item = $mirrorTbl->selectedItem(); + if ($item) { + yui::YUI::app()->busyCursor(); + my $row = $item->index(); + $urpm->{media}[$row]{update} = !$urpm->{media}[$row]{update} || undef; + urpm::media::write_config($urpm); + yui::YUI::ui()->blockEvents(); + $dialog->startMultipleChanges(); + $mirrorTbl->deleteAllItems(); + my $itemCollection = readMedia(); + selectRow($itemCollection, $row); + $mirrorTbl->addItems($itemCollection); + $dialog->recalcLayout(); + $dialog->doneMultipleChanges(); + yui::YUI::ui()->unblockEvents(); + yui::YUI::app()->normalCursor(); + } + } + elsif ($widget == $enabled) { + ## TODO same as $edtButton after edit_callback + my $item = $mirrorTbl->selectedItem(); + if ($item) { + my $row = $item->index(); + yui::YUI::app()->busyCursor(); + yui::YUI::ui()->blockEvents(); + + $dialog->startMultipleChanges(); + + $urpm->{media}[$row]{ignore} = !$urpm->{media}[$row]{ignore} || undef; + urpm::media::write_config($urpm); + my $ignored = $urpm->{media}[$row]{ignore}; + my $itemCollection = readMedia(); + if (!$ignored && $urpm->{media}[$row]{ignore}) { + # reread media failed to un-ignore an ignored medium + # probably because urpm::media::check_existing_medium() complains + # about missing synthesis when the medium never was enabled before; + # thus it restored the ignore bit + $urpm->{media}[$row]{ignore} = !$urpm->{media}[$row]{ignore} || undef; + urpm::media::write_config($urpm); + #- Enabling this media failed, force update + interactive_msg('rpmdragora', + $loc->N("This medium needs to be updated to be usable. Update it now?"), + yesno => 1, + ) and $itemCollection = readMedia($urpm->{media}[$row]{name}); + } + $mirrorTbl->deleteAllItems(); + selectRow($itemCollection, $row); + $mirrorTbl->addItems($itemCollection); + + $dialog->recalcLayout(); + $dialog->doneMultipleChanges(); + yui::YUI::ui()->unblockEvents(); + yui::YUI::app()->normalCursor(); + } + } + elsif ($widget == $mirrorTbl) { + $selection_changed = 1; + } + } + if ($changed) { + yui::YUI::app()->busyCursor(); + yui::YUI::ui()->blockEvents(); + + $dialog->startMultipleChanges(); + + $mirrorTbl->deleteAllItems(); + my $itemCollection = readMedia(); + selectRow($itemCollection, 0); #default selection + $mirrorTbl->addItems($itemCollection); + + $dialog->recalcLayout(); + $dialog->doneMultipleChanges(); + yui::YUI::app()->normalCursor(); + $selection_changed = 1; + } + if ($selection_changed) { + yui::YUI::ui()->blockEvents(); + my $item = $mirrorTbl->selectedItem(); + _showMediaStatus({item => $item, enabled => $enabled, updates => $update}); + + my $sel = $mirrorTbl->selectedItems(); + if ($sel->size() == 0 || $sel->size() > 1 ) { + $remButton->setEnabled(($sel->size() == 0) ? 0 : 1); + $edtButton->setEnabled(0); + $upButton->setEnabled(0); + $downButton->setEnabled(0); + $enabled->setEnabled(0); + $update->setEnabled(0); + } + else { + $remButton->setEnabled(1); + $edtButton->setEnabled(1); + $upButton->setEnabled(1); + $downButton->setEnabled(1); + $enabled->setEnabled(1); + $update->setEnabled(1) if $::expert; + } + + yui::YUI::ui()->unblockEvents(); + } + } + $dialog->destroy(); + + #restore old application title + yui::YUI::app()->setApplicationTitle($appTitle) if $appTitle; + + return $something_changed; +} + + +sub OLD_mainwindow() { + undef $something_changed; + $mainw = ugtk2->new($loc->N("Configure media"), center => 1, transient => $::main_window, modal => 1); + local $::main_window = $mainw->{real_window}; + + my $reread_media; + + my ($menu, $_factory) = create_factory_menu( + $mainw->{real_window}, + [ $loc->N("/_File"), undef, undef, undef, '' ], + [ $loc->N("/_File") . $loc->N("/_Update"), $loc->N("U"), sub { update_callback() and $reread_media->() }, undef, '', ], + [ $loc->N("/_File") . $loc->N("/Add a specific _media mirror"), $loc->N("M"), sub { easy_add_callback_with_mirror() and $reread_media->() }, undef, '' ], + [ $loc->N("/_File") . $loc->N("/_Add a custom medium"), $loc->N("A"), sub { add_callback() and $reread_media->() }, undef, '' ], + [ $loc->N("/_File") . $loc->N("/Close"), $loc->N("W"), sub { Gtk2->main_quit }, undef, '', ], + [ $loc->N("/_Options"), undef, undef, undef, '' ], + [ $loc->N("/_Options") . $loc->N("/_Global options"), $loc->N("G"), \&options_callback, undef, '' ], + [ $loc->N("/_Options") . $loc->N("/Manage _keys"), $loc->N("K"), \&keys_callback, undef, '' ], + [ $loc->N("/_Options") . $loc->N("/_Parallel"), $loc->N("P"), \¶llel_callback, undef, '' ], + [ $loc->N("/_Options") . $loc->N("/P_roxy"), $loc->N("R"), \&proxy_callback, undef, '' ], + if_($0 =~ /edit-urpm-sources/, + [ $loc->N("/_Help"), undef, undef, undef, '' ], + [ $loc->N("/_Help") . $loc->N("/_Report Bug"), undef, sub { run_drakbug('edit-urpm-sources.pl') }, undef, '' ], + [ $loc->N("/_Help") . $loc->N("/_Help"), undef, sub { rpmdragora::open_help('sources') }, undef, '' ], + [ $loc->N("/_Help") . $loc->N("/_About..."), undef, sub { + my $license = MDK::Common::String::formatAlaTeX(translate($::license)); + $license =~ s/\n/\n\n/sg; # nicer formatting + my $w = gtknew('AboutDialog', name => $loc->N("Rpmdragora"), + version => $rpmdragora::distro_version, + copyright => $loc->N("Copyright (C) %s by Mandriva", '2002-2008'), + license => $license, wrap_license => 1, + comments => $loc->N("Rpmdragora is the Mageia package management tool."), + website => 'http://www.mageia.org/', + website_label => $loc->N("Mageia"), + authors => 'Thierry Vignaud ', + artists => 'Hélène Durosini ', + translator_credits => + #-PO: put here name(s) and email(s) of translator(s) (eg: "John Smith ") + $loc->N("_: Translator(s) name(s) & email(s)\n"), + transient_for => $::main_window, modal => 1, position_policy => 'center-on-parent', + ); + $w->show_all; + $w->run; + }, undef, '' + ] + ), + ); + + my $list = Gtk2::ListStore->new("Glib::Boolean", "Glib::Boolean", "Glib::String", "Glib::String", "Glib::Boolean"); + $list_tv = Gtk2::TreeView->new_with_model($list); + $list_tv->get_selection->set_mode('multiple'); + my ($dw_button, $edit_button, $remove_button, $up_button); + $list_tv->get_selection->signal_connect(changed => sub { + my ($selection) = @_; + my @rows = $selection->get_selected_rows; + my $model = $list; + # we can delete several medium at a time: + $remove_button and $remove_button->set_sensitive($#rows != -1); + # we can only edit/move one item at a time: + $_ and $_->set_sensitive(@rows == 1) foreach $up_button, $dw_button, $edit_button; + + # we can only up/down one item if not at begin/end: + return if @rows != 1; + + my $curr_path = $rows[0]; + my $first_path = $model->get_path($model->get_iter_first); + $up_button->set_sensitive($first_path && $first_path->compare($curr_path)); + + $curr_path->next; + my $next_item = $model->get_iter($curr_path); + $dw_button->set_sensitive($next_item); # && !$model->get($next_item, 0) + }); + + $list_tv->set_rules_hint(1); + $list_tv->set_reorderable(1); + + my $reorder_ok = 1; + $list->signal_connect( + row_deleted => sub { + $reorder_ok or return; + my ($model) = @_; + my @media; + $model->foreach( + sub { + my (undef, undef, $iter) = @_; + my $name = $model->get($iter, $col{mainw}{name}); + push @media, urpm::media::name2medium($urpm, $name); + 0; + }, undef); + @{$urpm->{media}} = @media; + }, + ); + + $list_tv->append_column(Gtk2::TreeViewColumn->new_with_attributes($loc->N("Enabled"), + my $tr = Gtk2::CellRendererToggle->new, + 'active' => $col{mainw}{is_enabled})); + $list_tv->append_column(Gtk2::TreeViewColumn->new_with_attributes($loc->N("Updates"), + my $cu = Gtk2::CellRendererToggle->new, + 'active' => $col{mainw}{is_update}, + activatable => $col{mainw}{activatable})); + $list_tv->append_column(Gtk2::TreeViewColumn->new_with_attributes($loc->N("Type"), + Gtk2::CellRendererText->new, + 'text' => $col{mainw}{type})); + $list_tv->append_column(Gtk2::TreeViewColumn->new_with_attributes($loc->N("Medium"), + Gtk2::CellRendererText->new, + 'text' => $col{mainw}{name})); + my $id; + $id = $tr->signal_connect( + toggled => sub { + my (undef, $path) = @_; + $tr->signal_handler_block($id); + my $_guard = before_leaving { $tr->signal_handler_unblock($id) }; + my $iter = $list->get_iter_from_string($path); + $urpm->{media}[$path]{ignore} = !$urpm->{media}[$path]{ignore} || undef; + $list->set($iter, $col{mainw}{is_enabled}, !$urpm->{media}[$path]{ignore}); + urpm::media::write_config($urpm); + my $ignored = $urpm->{media}[$path]{ignore}; + $reread_media->(); + if (!$ignored && $urpm->{media}[$path]{ignore}) { + # reread media failed to un-ignore an ignored medium + # probably because urpm::media::check_existing_medium() complains + # about missing synthesis when the medium never was enabled before; + # thus it restored the ignore bit + $urpm->{media}[$path]{ignore} = !$urpm->{media}[$path]{ignore} || undef; + urpm::media::write_config($urpm); + #- Enabling this media failed, force update + interactive_msg('rpmdragora', + $loc->N("This medium needs to be updated to be usable. Update it now?"), + yesno => 1, + ) and $reread_media->($urpm->{media}[$path]{name}); + } + }, + ); + + $cu->signal_connect( + toggled => sub { + my (undef, $path) = @_; + my $iter = $list->get_iter_from_string($path); + $urpm->{media}[$path]{update} = !$urpm->{media}[$path]{update} || undef; + $list->set($iter, $col{mainw}{is_update}, ! !$urpm->{media}[$path]{update}); + $something_changed = 1; + }, + ); + + $reread_media = sub { + my ($name) = @_; + $reorder_ok = 0; + $something_changed = 1; + if (defined $name) { + urpm::media::select_media($urpm, $name); + update_sources_check( + $urpm, + { nolock => 1 }, + $loc->N_("Unable to update medium, errors reported:\n\n%s"), + $name, + ); + } + # reread configuration after updating media else ignore bit will be restored + # by urpm::media::check_existing_medium(): + $urpm = fast_open_urpmi_db(); + $list->clear; + foreach (grep { ! $_->{external} } @{$urpm->{media}}) { + my $name = $_->{name}; + $list->append_set($col{mainw}{is_enabled} => !$_->{ignore}, + $col{mainw}{is_update} => ! !$_->{update}, + $col{mainw}{type} => get_medium_type($_), + $col{mainw}{name} => $name, + $col{mainw}{activatable} => to_bool($::expert), + ); + } + $reorder_ok = 1; + }; + $reread_media->(); + $something_changed = 0; + + gtkadd( + $mainw->{window}, + gtkpack_( + gtknew('VBox', spacing => 5), + 0, $menu, + ($0 =~ /rpm-edit-media|edit-urpm-sources/ ? (0, Gtk2::Banner->new($ugtk2::wm_icon, $loc->N("Configure media"))) : ()), + 1, gtkpack_( + gtknew('HBox', spacing => 10), + 1, gtknew('ScrolledWindow', child => $list_tv), + 0, gtkpack__( + gtknew('VBox', spacing => 5), + gtksignal_connect( + $remove_button = Gtk2::Button->new(but($loc->N("Remove"))), + clicked => sub { remove_callback() and $reread_media->() }, + ), + gtksignal_connect( + $edit_button = Gtk2::Button->new(but($loc->N("Edit"))), + clicked => sub { + my $name = edit_callback(); defined $name and $reread_media->($name); + } + ), + gtksignal_connect( + Gtk2::Button->new(but($loc->N("Add"))), + clicked => sub { easy_add_callback() and $reread_media->() }, + ), + gtkpack( + gtknew('HBox'), + gtksignal_connect( + $up_button = gtknew('Button', + image => gtknew('Image', stock => 'gtk-go-up')), + clicked => \&upwards_callback), + + gtksignal_connect( + $dw_button = gtknew('Button', + image => gtknew('Image', stock => 'gtk-go-down')), + clicked => \&downwards_callback), + ), + ) + ), + 0, gtknew('HSeparator'), + 0, gtknew('HButtonBox', layout => 'edge', children_loose => [ + gtksignal_connect(Gtk2::Button->new(but($loc->N("Help"))), clicked => sub { rpmdragora::open_help('sources') }), + gtksignal_connect(Gtk2::Button->new(but($loc->N("Ok"))), clicked => sub { Gtk2->main_quit }) + ]) + ) + ); + $_->set_sensitive(0) foreach $dw_button, $edit_button, $remove_button, $up_button; + + $mainw->{rwindow}->set_size_request(600, 400); + $mainw->main; + return $something_changed; +} + + +sub run() { + # ignore rpmdragora's option regarding ignoring debug media: + local $ignore_debug_media = [ 0 ]; +# local $ugtk2::wm_icon = get_icon('rpmdragora-mdk', 'title-media'); + my $lock; + { + $urpm = fast_open_urpmi_db(); + my $err_msg = "urpmdb locked\n"; + local $urpm->{fatal} = sub { + interactive_msg('rpmdragora', + $loc->N("The Package Database is locked. Please close other applications +working with the Package Database. Do you have another media +manager on another desktop, or are you currently installing +packages as well?")); + die $err_msg; + }; + # lock urpmi DB + eval { $lock = urpm::lock::urpmi_db($urpm, 'exclusive', wait => $urpm->{options}{wait_lock}) }; + if (my $err = $@) { + return if $err eq $err_msg; + die $err; + } + } + + my $res = mainwindow(); + urpm::media::write_config($urpm); + + writeconf(); + + undef $lock; + $res; +} + +sub readproxy (;$) { + my $proxy = get_proxy($_[0]); + ($proxy->{http_proxy} || $proxy->{ftp_proxy} || '', + defined $proxy->{user} ? "$proxy->{user}:$proxy->{pwd}" : ''); +} + +sub writeproxy { + my ($proxy, $proxy_user, $o_media_name) = @_; + my ($user, $pwd) = split /:/, $proxy_user; + set_proxy_config(user => $user, $o_media_name); + set_proxy_config(pwd => $pwd, $o_media_name); + set_proxy_config(http_proxy => $proxy, $o_media_name); + set_proxy_config(ftp_proxy => $proxy, $o_media_name); + dump_proxy_config(); +} + +1; diff --git a/lib/ManaTools/Rpmdragora/formatting.pm b/lib/ManaTools/Rpmdragora/formatting.pm new file mode 100644 index 0000000..83a960a --- /dev/null +++ b/lib/ManaTools/Rpmdragora/formatting.pm @@ -0,0 +1,209 @@ +# vim: set et ts=4 sw=4: +package ManaTools::Rpmdragora::formatting; +#***************************************************************************** +# +# Copyright (c) 2002 Guillaume Cottenceau +# Copyright (c) 2002-2006 Thierry Vignaud +# Copyright (c) 2003, 2004, 2005 MandrakeSoft SA +# Copyright (c) 2005, 2006 Mandriva SA +# Copyright (c) 2013 - 2015 Matteo Pasotti +# 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. +# +#***************************************************************************** +# +# $Id: formatting.pm 261189 2009-10-01 14:44:39Z tv $ + +use strict; +use utf8; +use POSIX qw(strftime); +use MDK::Common::Various qw(internal_error); +use ManaTools::Shared::Locales; +use ManaTools::rpmdragora; +use urpm::msg; + + +use Exporter; +our @ISA = qw(Exporter); +our @EXPORT = qw( + $spacing + ensure_utf8 + format_changelog_changelogs + format_changelog_string + format_field + format_header + format_list + format_name_n_summary + format_size + format_filesize + format_update_field + my_fullname + pkg2medium + rpm_description + split_fullname + urpm_name + ); + +my $loc = ManaTools::rpmdragora::locale(); + +sub escape_text_for_TextView_markup_format { + my ($str) = @_; + return '' if !$str; + + my %rules = ('&' => '&', + '<' => '<', + '>' => '>', + ); + eval { $str =~ s!([&<>])!$rules{$1}!g }; #^(&(amp|lt|gt);)!!) { + if (my $err = $@) { + MDK::Common::Various::internal_error("$err\n$str"); + } + $str; +} + +# from rpmtools, #37482: +sub ensure_utf8 { + return '' if !$_[0]; + + if (utf8::is_utf8($_[0])) { + utf8::valid($_[0]) and return; + utf8::encode($_[0]); #- disable utf8 flag + utf8::upgrade($_[0]); + } else { + utf8::decode($_[0]); #- try to set utf8 flag + utf8::valid($_[0]) and return; + warn "do not know what to with $_[0]\n"; + } +} + +sub rpm_description { + my ($description) = @_; + return '' if !$description; + + ensure_utf8($description); + my $t = ""; + my $tmp = ""; + foreach (split "\n", $description) { + s/^\s*//; + if (/^$/ || /^\s*(-|\*|\+|o)\s/) { + $t || $tmp and $t .= "$tmp\n"; + $tmp = $_; + } else { + $tmp = ($tmp ? "$tmp " : ($t && "\n") . $tmp) . $_; + } + } + "$t$tmp\n"; +} + +sub split_fullname { $_[0] =~ /^(.*)-([^-]+)-([^-]+)\.([^.-]+)$/ } + +sub my_fullname { + return '?-?-?' unless ref $_[0]; + my ($name, $version, $release) = $_[0]->fullname; + "$name-$version-$release"; +} + +sub urpm_name { + return '?-?-?.?' unless ref $_[0]; + scalar $_[0]->fullname; +} + +sub pkg2medium { + my ($p, $urpm) = @_; + return if !ref $p; + return { name => $loc->N("None (installed)") } if !defined($p->id); # if installed + URPM::pkg2media($urpm->{media}, $p) || { name => $loc->N("Unknown"), fake => 1 }; +} + +# [ duplicate urpmi's urpm::msg::localtime2changelog() ] +#- strftime returns a string in the locale charset encoding; +#- but gtk2 requires UTF-8, so we use to_utf8() to ensure the +#- output of localtime2changelog() is always in UTF-8 +#- as to_utf8() uses LC_CTYPE for locale encoding and strftime() uses LC_TIME, +#- it doesn't work if those two variables have values with different +#- encodings; but if a user has a so broken setup we can't do much anyway +sub localtime2changelog { $loc->to_utf8(POSIX::strftime("%c", localtime($_[0]))) } + +our $spacing = " "; +sub format_changelog_string { + my ($installed_version, $string) = @_; + + #- preprocess changelog for faster TextView insert reaction + my $version; + my $highlight; + my $chl = [ map { + my %attrs; + if (/^\*/) { + ($version) = /(\S*-\S*)\s*$/; + $highlight = $installed_version ne $loc->N("(none)") && 0 < URPM::rpmvercmp($version, $installed_version); + if ($highlight) { + "" . $_ . ""; + } + else { + "" . $_ . ""; + } + } + else { + "$spacing" . $_ . "\n"; + } + } split("\n", $string) ]; + + return $chl; +} + +sub format_changelog_changelogs { + my ($installed_version, @changelogs) = @_; + format_changelog_string($installed_version, join("\n", map { + "* " . localtime2changelog($_->{time}) . " $_->{name}\n\n$_->{text}\n"; + } @changelogs)); +} + +sub format_update_field { + my ($name) = @_; + '' . escape_text_for_TextView_markup_format($name) . ''; +} + +sub format_name_n_summary { + my ($name, $summary) = @_; + join("\n", '' . $name . '', escape_text_for_TextView_markup_format($summary)); +} + +sub format_header { + my ($str) = @_; + '' . escape_text_for_TextView_markup_format($str) . ''; +} + +sub format_field { + my ($str) = @_; + '' . escape_text_for_TextView_markup_format($str) . ''; +} + +sub format_size { + my ($size) = @_; + $size >= 0 ? + $loc->N("%s of additional disk space will be used.", formatXiB($size)) : + $loc->N("%s of disk space will be freed.", formatXiB(-$size)); +} + +sub format_filesize { + my ($filesize) = @_; + $filesize ? $loc->N("%s of packages will be retrieved.", formatXiB($filesize)) : (); +} + +sub format_list { + return join("\n", map { s/^(\s)/ $1/mg; "- $_" } sort { uc($a) cmp uc($b) } @_); +} + +1; diff --git a/lib/ManaTools/Rpmdragora/gui.pm b/lib/ManaTools/Rpmdragora/gui.pm new file mode 100644 index 0000000..0cf0882 --- /dev/null +++ b/lib/ManaTools/Rpmdragora/gui.pm @@ -0,0 +1,1828 @@ +# vim: set et ts=4 sw=4: +package ManaTools::Rpmdragora::gui; +#***************************************************************************** +# +# Copyright (c) 2002 Guillaume Cottenceau +# Copyright (c) 2002-2007 Thierry Vignaud +# Copyright (c) 2003, 2004, 2005 MandrakeSoft SA +# Copyright (c) 2005-2007 Mandriva SA +# Copyright (c) 2013 - 2015 Matteo Pasotti +# 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. +# +#***************************************************************************** +# +# $Id$ + +############################################################ +# WARNING: do not modify before asking matteo or anaselli +############################################################ + +use strict; +use Sys::Syslog; + +use utf8; + +use MDK::Common::Func qw(before_leaving find any if_); +use MDK::Common::DataStructure qw(difference2 member intersection); +use MDK::Common::Various qw(chomp_ to_bool); +use MDK::Common::String qw(formatAlaTeX); +use MDK::Common::Math qw(sum); +use MDK::Common::System qw(list_passwd); + +use ManaTools::rpmdragora; +use ManaTools::Rpmdragora::open_db; +use ManaTools::Rpmdragora::formatting; +use ManaTools::Rpmdragora::init; +use ManaTools::Rpmdragora::icon qw(get_icon_path); +use ManaTools::Rpmdragora::pkg; +use ManaTools::Shared; +use ManaTools::Shared::GUI; +use ManaTools::Shared::Locales; +use ManaTools::Shared::RunProgram qw(get_stdout raw); +use yui; +use feature 'state'; +use Carp; + +use Exporter; +our @ISA = qw(Exporter); +our @EXPORT = qw( + $descriptions + $find_entry + $force_displaying_group + $force_rebuild + $pkgs + $results_ok + $results_none + $size_free + $size_selected + $urpm + %grp_columns + %pkg_columns + @filtered_pkgs + @initial_selection + ask_browse_tree_given_widgets_for_rpmdragora + build_tree + callback_choices + compute_main_window_size + do_action + get_info + get_summary + group_has_parent + group_parent + groups_tree + is_locale_available + node_state + pkgs_provider + real_quit + reset_search + set_node_state + sort_callback + switch_pkg_list_mode + toggle_all + toggle_nodes + fast_toggle + setInfoOnWidget + ); + +my $loc = ManaTools::rpmdragora::locale(); +my $shared_gui = ManaTools::Shared::GUI->new() ; + +our ($descriptions, %filters, @filtered_pkgs, %filter_methods, $force_displaying_group, $force_rebuild, @initial_selection, $pkgs, $size_free, $size_selected, $urpm); +our ($results_ok, $results_none) = ($loc->N("Search results"), $loc->N("Search results (none)")); + +our %hidden_info = ( + details => "details", + changelog => "changelog", + files => "file", + new_deps => "new_deps", + +); +our %grp_columns = ( + label => 0, + icon => 2, +); + +our %pkg_columns = ( + text => 0, + state_icon => 1, + state => 2, + selected => 3, + short_name => 4, + version => 5, + release => 6, + 'arch' => 7, + selectable => 8, +); + + +sub compute_main_window_size { + my ($w) = @_; + ($typical_width) = string_size($w->{real_window}, $loc->N("Graphical Environment") . "xmms-more-vis-plugins"); + $typical_width > 600 and $typical_width = 600; #- try to not being crazy with a too large value + $typical_width < 150 and $typical_width = 150; +} + +sub get_summary { + my ($key) = @_; + my $summary = $loc->N($pkgs->{$key}{pkg}->summary); + require utf8; + utf8::valid($summary) ? $summary : @{[]}; +} + +sub get_advisory_link { + my ($update_descr) = @_; + + my $webref = "
{URL} ."\">". $loc->N("Security advisory") ."
"; + + [ $webref ]; +} + +sub get_description { + my ($pkg, $update_descr) = @_; + + my $descr = ($pkg->{description} || + $update_descr->{description} || + ''. $loc->N("No description").''); + $descr =~ s|\n|
|g; + + return $descr . "
"; +} + +sub get_string_from_keywords { + my ($medium, $name) = @_; + my @media_types; + if ($medium->{mediacfg}) { + my ($distribconf, $medium_path) = @{$medium->{mediacfg}}; + @media_types = split(':', $distribconf->getvalue($medium_path, 'media_type')) if $distribconf; + } + + my $unsupported = $loc->N("It is not supported by Mageia."); + my $dangerous = $loc->N("It may break your system."); + my $s = ""; + $s .= $loc->N("This package is not free software") . "\n" if member('non-free', @media_types); + if ($pkgs->{$name}{is_backport} || member('backport', @media_types)) { + return join("\n", + $loc->N("This package contains a new version that was backported."), + $unsupported, $dangerous, $s); + } elsif (member('testing', @media_types)) { + return join("\n", + $loc->N("This package is a potential candidate for an update."), + $unsupported, $dangerous, $s); + } elsif (member('updates', @media_types)) { + return join("\n", + (member('official', @media_types) ? + $loc->N("This is an official update which is supported by Mageia.") + : ($loc->N("This is an unofficial update."), $unsupported)) + , + $s); + } else { + $s .= $loc->N("This is an official package supported by Mageia") . "\n" if member('official', @media_types); + return $s if $s; + } + + return; +} + +sub get_main_text { + my ($medium, $fullname, $name, $summary, $is_update, $update_descr) = @_; + + my $txt = get_string_from_keywords($medium, $fullname); + my $notice = format_field($loc->N("Notice: ")) . $txt if $txt; + ensure_utf8($notice); + + my $hdr = "

" . format_header(join(' - ', $name, $summary)) . "

\n"; + ensure_utf8($hdr); + + my $update = MDK::Common::Func::if_($is_update, # is it an update? + format_field($loc->N("Importance: ")) . format_update_field($update_descr->{importance}), + format_field($loc->N("Reason for update: ")) . format_update_field(rpm_description($update_descr->{pre})), + ); + ensure_utf8($update); + + my $main_text = $hdr; + $main_text .= "   " . $notice . "
" if $notice; + $main_text .= "   " . $update . "
" if $update; + + return $main_text; +} + +sub get_details { + my ($pkg, $upkg, $installed_version, $raw_medium) = @_; + my @details = (); + push @details, format_field($loc->N("Version: ")) . $upkg->EVR; + push @details, format_field($loc->N("Currently installed version: ")) . $installed_version if($upkg->flag_installed); + push @details, format_field($loc->N("Group: ")) . translate_group($upkg->group); + push @details, format_field($loc->N("Architecture: ")) . $upkg->arch; + push @details, format_field($loc->N("Size: ")) . $loc->N("%s KB", int($upkg->size/1024)); + push @details, eval { format_field($loc->N("Medium: ")) . $raw_medium->{name} }; + + my @link = get_url_link($upkg, $pkg); + push @details, join("
   ",@link) if(@link); + unshift @details, "
   "; + join("
   ", @details); +} + +sub get_new_deps { + my ($urpm, $upkg) = @_; + + my $deps = slow_func(sub { + my $state = {}; + my $db = open_rpm_db(); + my @requested = $urpm->resolve_requested__no_suggests_( + $db, $state, + { $upkg->id => 1 }, + ); + @requested = $urpm->resolve_requested_suggests($db, $state, \@requested); + undef $db; + my @nodes_with_deps = map { urpm_name($_) } @requested; + my @deps = sort { $a cmp $b } difference2(\@nodes_with_deps, [ urpm_name($upkg) ]); + @deps = $loc->N("All dependencies installed.") if !@deps; + return \@deps; + }); + return $deps; +} + +sub get_url_link { + my ($upkg, $pkg) = @_; + + my $url = $upkg->url || $pkg->{url}; + + if (!$url) { + open_rpm_db()->traverse_tag_find('name', $upkg->name, sub { $url = $_[0]->url; return ($url ? 1 : 0) }); + } + + return if !$url; + + my @a; + push @a, format_field($loc->N("URL: ")) . ${spacing} . "". $url .""; + @a; +} + +sub files_format { + my ($files) = @_; + + return '' . $spacing . "
   " . join("
   ", @$files) . '
'; +} + +#============================================================= + +=head2 format_link + +=head3 INPUT + + $description: Description to be shown as link + $url: to be reach when click on $description link + +=head3 OUTPUT + + $webref: href HTML tag + +=head3 DESCRIPTION + + This function returns an href string to be published + +=cut + +#============================================================= +sub format_link { + my ($description, $url) = @_; + + my $webref = "". $description .""; + + return $webref; +} + +sub _format_pkg_simplifiedinfo { + my ($pkgs, $key, $urpm, $descriptions, $options) = @_; + my ($name) = split_fullname($key); + my $pkg = $pkgs->{$key}; + my $upkg = $pkg->{pkg}; + return if !$upkg; + my $raw_medium = pkg2medium($upkg, $urpm); + my $medium = !$raw_medium->{fake} ? $raw_medium->{name} : undef; + my $update_descr = $descriptions->{$medium}{$name}; + # discard update fields if not matching: + + my $is_update = ($upkg->flag_upgrade && $update_descr && $update_descr->{pre}); + my $summary = get_summary($key); + my $dummy_string = get_main_text($raw_medium, $key, $name, $summary, $is_update, $update_descr); + my $s; + push @$s, $dummy_string; + push @$s, get_advisory_link($update_descr) if $is_update; + + push @$s, get_description($pkg, $update_descr); + + my $installed_version = eval { find_installed_version($upkg) }; + + #push @$s, [ gtkadd(gtkshow(my $details_exp = Gtk2::Expander->new(format_field($loc->N("Details:")))), + # gtknew('TextView', text => get_details($pkg, $upkg, $installed_version, $raw_medium))) ]; + my $detail_link = format_link(format_field($loc->N("Details:")), $hidden_info{details} ); + if ($options->{details}) { + my $details = get_details($pkg, $upkg, $installed_version, $raw_medium); + utf8::encode($details); + $detail_link .= "\n" . $details; + } + push @$s, join("\n", $detail_link, "\n"); + + #push @$s, [ build_expander($pkg, $loc->N("Files:"), 'files', sub { files_format($pkg->{files}) }) ]; + my $files_link = format_link(format_field($loc->N("Files:")), $hidden_info{files} ); + if ($options->{files}) { + my $wait = ManaTools::rpmdragora::wait_msg(); + if (!$pkg->{files}) { + extract_header($pkg, $urpm, 'files', $installed_version); + } + my $files = $pkg->{files} ? files_format($pkg->{files}) : $loc->N("(Not available)"); + utf8::encode($files); + $files_link .= "\n\n" . $files; + ManaTools::rpmdragora::remove_wait_msg($wait); + } + push @$s, join("\n", $files_link, "\n"); + + #push @$s, [ build_expander($pkg, $loc->N("Changelog:"), 'changelog', sub { $pkg->{changelog} }, $installed_version) ]; + my $changelog_link = format_link(format_field($loc->N("Changelog:")), $hidden_info{changelog} ); + if ($options->{changelog}) { + my $wait = ManaTools::rpmdragora::wait_msg(); + my @changelog = $pkg->{changelog} ? @{$pkg->{changelog}} : ( $loc->N("(Not available)") ); + if (!$pkg->{changelog} || !scalar @{$pkg->{changelog}} ) { + # my ($pkg, $label, $type, $get_data, $o_installed_version) = @_; + extract_header($pkg, $urpm, 'changelog', $installed_version); + @changelog = $pkg->{changelog} ? @{$pkg->{changelog}} : ( $loc->N("(Not available)") ); + } + utf8::encode(\@changelog); + + $changelog_link .= "
   " . join("
   ", @changelog); + $changelog_link =~ s|\n||g; + ManaTools::rpmdragora::remove_wait_msg($wait); + } + push @$s, join("\n\n", $changelog_link, "\n"); + + my $deps_link = format_link(format_field($loc->N("New dependencies:")), $hidden_info{new_deps} ); + if ($options->{new_deps}) { + if ($upkg->id) { # If not installed + $deps_link .= "
   " . join("
   ", @{get_new_deps($urpm, $upkg)}); + # push @$s, get_new_deps($urpm, $upkg); + } + } + push @$s, join("\n", $deps_link, "\n"); + + return $s; +} + +sub warn_if_no_pkg { + my ($name) = @_; + my ($short_name) = split_fullname($name); + state $warned; + if (!$warned) { + $warned = 1; + interactive_msg($loc->N("Warning"), + join("\n", + $loc->N("The package \"%s\" was found.", $name), + $loc->N("However this package is not in the package list."), + $loc->N("You may want to update your urpmi database."), + '', + $loc->N("Matching packages:"), + '', + join("\n", sort map { + #-PO: this is list fomatting: "- (medium: )" + #-PO: eg: "- rpmdragora (medium: "Main Release" + $loc->N("- %s (medium: %s)", $_, pkg2medium($pkgs->{$_}{pkg}, $urpm)->{name}); + } grep { /^$short_name/ } keys %$pkgs), + ), + scroll => 1, + ); + } + return 'XXX'; +} + +# +# @method node_state +# +=pod + +=head1 node_state(pkgname) + +=over 4 + +=item returns the state of the node (pkg) querying an urpm object from $pkgs->{$pkgname} + +=over 6 + +=item I + +=item I + +=item I + +=item I + +=item I + +=back + +=back + +=cut + +sub node_state { + my ($name) = @_; + #- checks $_[0] -> hack for partial tree displaying + return 'XXX' if !$name; + my $pkg = $pkgs->{$name}; + my $urpm_obj = $pkg->{pkg}; + return warn_if_no_pkg($name) if !$urpm_obj; + $pkg->{selected} ? + ($urpm_obj->flag_installed ? + ($urpm_obj->flag_upgrade ? 'to_install' : 'to_remove') + : 'to_install') + : ($urpm_obj->flag_installed ? + ($pkgs->{$name}{is_backport} ? 'backport' : + ($urpm_obj->flag_upgrade ? 'to_update' + : ($urpm_obj->flag_base ? 'base' : 'installed'))) + : 'uninstalled'); +} + +my ($common, $w, %wtree, %ptree, %pix, @table_item_list); + +# +# @method set_node_state +# + +=pod + +=head1 set_node_state($tblItem, $state, $detail_list) + +=over 4 + +=item setup the table row by adding a cell representing the state of the package + +=item see node_state + +=over 6 + +=item B<$tblItem> , YTableItem instance + +=item B<$state> , string containing the state of the package from node_state + +=item B<$detail_list> , reference to the YCBTable + +=back + +=back + +=cut + +sub set_node_state { + my ($tblItem, $state, $detail_list) = @_; + return if $state eq 'XXX' || !$state; + + if ($detail_list) { + $detail_list->parent()->parent()->startMultipleChanges(); + $tblItem->addCell($state,"/usr/share/rpmdrake/icons/state_$state.png") if(ref $tblItem eq "yui::YCBTableItem"); + if(to_bool(member($state, qw(base installed to_install)))){ + # it should be parent()->setChecked(1) + $detail_list->checkItem($tblItem, 1); + # $tblItem->setSelected(1); + }else{ + $detail_list->checkItem($tblItem, 0); + # $tblItem->setSelected(0); + } +# if(!to_bool($state ne 'base')){ +# #$iter->cell(0)->setLabel('-'); +# $tblItem->cell(0)->setLabel('-'); +# } + $detail_list->parent()->parent()->doneMultipleChanges(); + } + else { + # no item list means we use just the item to add state information + $tblItem->addCell($state,"/usr/share/rpmdrake/icons/state_$state.png") if(ref $tblItem eq "yui::YCBTableItem"); + $tblItem->check(to_bool(member($state, qw(base installed to_install)))); +# $tblItem->cell(0)->setLabel('-') if !to_bool($state ne 'base'); + } +} + +sub set_leaf_state { + my ($leaf, $state, $detail_list) = @_; + # %ptree is a hash using the pkg name as key and a monodimensional array (?) as value + # were it is stored the index of the item into the table + my $nodeIndex = $ptree{$leaf}[0]; + my $node = itemAt($detail_list,$nodeIndex); + set_node_state($node, $state, $detail_list); +} + +#============================================================= + +=head2 grep_unselected + +=head3 INPUT + + $l: ARRAY reference containing the list of package fullnames + +=head3 OUTPUT + + \@result: ARRAY reference containing the list of packages + that are not selected + +=head3 DESCRIPTION + + Function returning the list of not selected packages + +=cut + +#============================================================= +sub grep_unselected { + my $l = shift; + + my @result = grep { exists $pkgs->{$_} && !$pkgs->{$_}{selected} } @{$l} ; + return \@result; +} + +my %groups_tree = (); + +# +# @method add_parent +# + +=pod + +=head1 add_parent($tree, $root, $state) + +=over 4 + +=item populates the treeview with the rpm package groups + +=over 6 + +=item B<$tree> , YTree for the group of the rpm packages + +=item B<$root> , string containing a path-like sequence (e.g. "foo|bar") + +=item B<$state> , not used currently (from the old impl.) + +=back + +=back + +=cut + +sub add_parent { + my ($tree, $root, $state) = @_; + $tree or return undef; + #$root or return undef; + my $parent = 0; + + carp "WARNING TODO: add_parent to be removed (called with " . $root . ")\n"; + + my @items = split('\|', $root); + my $i = 0; + my $parentItem = undef; + my $rootItem = undef; + for my $item (@items) { + chomp $item; + $item = trim($item); + my $treeItem; + if($i == 0){ + $parent = $item; + $treeItem = new yui::YTreeItem($item,get_icon_path($item,0),0); + $rootItem = $treeItem; + $parentItem = $treeItem; + if(!defined($groups_tree{$parent})) { + $groups_tree{$parent}{parent} = $treeItem; + $groups_tree{$parent}{children} = (); +# $tree->addItem($groups_tree{$parent}{'parent'}); + } + }else{ + #if(any { $_ ne $item } @{$groups_tree{$parent}{'children'}}){ + # push @{$groups_tree{$parent}{'children'}}, $item; + #} + $parentItem = new yui::YTreeItem($parentItem, $item,get_icon_path($item,$parent),0); + if(!defined($groups_tree{$parent}{'children'}{$item})){ +# $treeItem = new yui::YTreeItem($treeItem, $item,get_icon_path($item,$parent),0); + $treeItem = $parentItem; + $groups_tree{$parent}{'children'}{$item} = $treeItem; + $groups_tree{$parent}{'parent'}->addChild($treeItem); + } + } + $i++; + } + $tree->addItem($rootItem) if $rootItem; + $tree->rebuildTree(); +} + + +#============================================================= + +=head2 add_tree_item + +=head3 INPUT + +=item B<$tree> YTree for the group of the rpm packages + +=item B<$item> string containing a group (to be added as leaf node) + +=item B<$selected> if the new item is selected + + +=head3 DESCRIPTION + + This function add a group to the tree view + +=cut + +#============================================================= +sub add_tree_item { + my ($tree, $item, $selected) = @_; + + $tree or return undef; + + $tree->startMultipleChanges(); + my $treeItem = new yui::YTreeItem($item, get_icon_path($item, 0), 0); + $treeItem->setSelected($selected); + + $tree->addItem($treeItem); + $tree->rebuildTree(); + $tree->doneMultipleChanges(); +} + +#============================================================= + +=head2 add_package_item + +=head3 INPUT + +=item B<$item_list>: reference to a YItemCollection + +=item B<$pkg_name>: package name + +=item B<$select>: select given package + +=head3 DESCRIPTION + + populates the item list for the table view with the given rpm package + +=cut + +#============================================================= +sub add_package_item { + my ($item_list, $pkg_name, $select) = @_; + + return if !$pkg_name; + + return if ref($item_list) ne "yui::YItemCollection"; + + my $state = node_state($pkg_name) or return; + + my $iter; + if (is_a_package($pkg_name)) { + my ($name, $version, $release, $arch) = split_fullname($pkg_name); + + $name = "" if !defined($name); + $version = "" if !defined($version); + $release = "" if !defined($release); + $arch = "" if !defined($arch); + + my $newTableItem = new yui::YCBTableItem( + $name, + get_summary($pkg_name), + $version, + $release, + $arch + ); + + $newTableItem->setSelected($select); + + set_node_state($newTableItem, $state); + + $item_list->push($newTableItem); + + $newTableItem->DISOWN(); + } + else { + carp $pkg_name . " is not a leaf package and that is not managed!"; + } + +} + +# +# @method add_node +# + +=pod + +=head1 add_node($leaf, $root, $options) + +=over 4 + +=item populates the tableview with the rpm packages or the treeview with the package groups + +=over 6 + +=item B<$leaf> , could be the name of a package or the name of a group o packages + +=item B<$root> , string containing a path-like sequence (e.g. "foo|bar") + +=item B<$state> , the string with the state of the package if leaf is the name of a package + +=back + +=back + +=cut + +sub add_node { + my ($leaf, $root, $o_options) = @_; + my $state = node_state($leaf) or return; + if ($leaf) { + my $iter; + if (is_a_package($leaf)) { +carp "TODO: add_node is_a_package(\$leaf)" . $leaf . "\n"; + + my ($name, $version, $release, $arch) = split_fullname($leaf); + #OLD $iter = $w->{detail_list_model}->append_set([ $pkg_columns{text} => $leaf, + # $pkg_columns{short_name} => format_name_n_summary($name, get_summary($leaf)), + # $pkg_columns{version} => $version, + # $pkg_columns{release} => $release, + # $pkg_columns{arch} => $arch, + # ]); + $name = "" if(!defined($name)); + $version = "" if(!defined($version)); + $release = "" if(!defined($release)); + $arch = "" if(!defined($arch)); + #my $newTableItem = new yui::YTableItem(format_name_n_summary($name, get_summary($leaf)), + my $newTableItem = new yui::YCBTableItem($name, + get_summary($leaf), + $version, + $release, + $arch); + $w->{detail_list}->addItem($newTableItem); + set_node_state($newTableItem, $state, $w->{detail_list}); + # $ptree{$leaf} = [ $newTableItem->label() ]; + $ptree{$leaf} = [ $newTableItem->index() ]; + $table_item_list[$newTableItem->index()] = $leaf; + $newTableItem->DISOWN(); + } else { + carp "TODO: add_node !is_a_package(\$leaf) not MANAGED\n"; +# $iter = $w->{tree_model}->append_set(add_parent($w->{tree},$root, $state), [ $grp_columns{label} => $leaf ]); + #push @{$wtree{$leaf}}, $iter; + } + } else { + carp "TODO: add_node !\$leaf not MANAGED\n"; + +# my $parent = add_parent($w->{tree}, $root, $state); + #- hackery for partial displaying of trees, used in rpmdragora: + #- if leaf is void, we may create the parent and one child (to have the [+] in front of the parent in the ctree) + #- though we use '' as the label of the child; then rpmdragora will connect on tree_expand, and whenever + #- the first child has '' as the label, it will remove the child and add all the "right" children +# $o_options->{nochild} or $w->{tree_model}->append_set($parent, [ $grp_columns{label} => '' ]); # test $leaf? + } +} + +my ($prev_label); +sub update_size { + my ($common) = shift @_; + if ($w->{status}) { + my $new_label = $common->{get_status}(); + $prev_label="" if(!defined($prev_label)); + $prev_label ne $new_label and $w->{status}->setText($prev_label = $new_label); + } +} + +#============================================================= + +=head2 treeview_children + +=head3 INPUT + + $tbl: YCBTable widget containing the package list shown + +=head3 OUTPUT + + \@l: ARRAY reference containing the list + of YItem contained into YCBTable + +=head3 DESCRIPTION + + This functions just returns the YCBTable content such as all the + YItem objects + +=cut + +#============================================================= +sub treeview_children { + my ($tbl) = @_; + my $it; + my @l; + my $i=0; + # using iterators + for ($it = $tbl->itemsBegin(); $it != $tbl->itemsEnd(); ) { + my $item = $tbl->YItemIteratorToYItem($it); + push @l, $item; + $it = $tbl->nextItem($it); + $i++; + if ($i == $tbl->itemsCount()) { + last; + } + } + + return \@l; +} + +#============================================================= + +=head2 children + +=head3 INPUT + + $tbl: YCBTable object + @table_item_list: array containing package fullnames + +=head3 OUTPUT + + \@result: ARRAY reference containing package fullnames + +=head3 DESCRIPTION + + This Function return the list of package fullnames + +=cut + +#============================================================= + +sub children { + my ($tbl, $table_item_list) = @_; + # map { $w->{detail_list}->get($_, $pkg_columns{text}) } treeview_children($w->{detail_list}); + # map { $table_item_list[$_->index()] } treeview_children($w->{detail_list}); + my $children_list = treeview_children($tbl); + my @result; + for my $child(@{$children_list}){ + push @result, $table_item_list->[$child->index()]; + } + return \@result; +} + +sub itemAt { + my ($table, $index) = @_; + return $table->item($index); + #return bless ($table->item($index),'yui::YTableItem'); + #foreach my $item(treeview_children($table)){ + # if($item->index() == $index){ + # print "\n== item label ".$item->label()."\n"; + # return bless ($item, 'yui::YTableItem'); + # } + #} +} + + +#============================================================= + +=head2 toggle_all + +=head3 INPUT + + $common: HASH reference containing (### TODO ###) + widgets => { + detail_list: YTable reference (?) + } + table_item_list => array containing package fullnames + partialsel_unsel => (?) + + set_state_callback => set state callback invoked by + toggle_nodes if needed. if undef + set_leaf_state is used. + $_val: value to be set (so it seems not a toggle! unused?) + +=head3 DESCRIPTION + +This method (should) check -or un-check if already checked- all +the packages + +=cut + +#============================================================= +sub toggle_all { + my ($common, $_val) = @_; + my $w = $common->{widgets}; + + my $l = children($w->{detail_list}, $common->{table_item_list}) or return; + + my $set_state = $common->{set_state_callback} ? $common->{set_state_callback} : \&set_leaf_state; + my $unsel = grep_unselected($l); + my $p = $unsel ? + #- not all is selected, select all if no option to potentially override + (exists $common->{partialsel_unsel} && $common->{partialsel_unsel}->($unsel, $l) ? difference2($l, $unsel) : $unsel) + : $l; + # toggle_nodes($w->{detail_list}, $w->{detail_list_model}, \&set_leaf_state, node_state($p[0]), @p); + + toggle_nodes($w->{detail_list}, $w->{detail_list}, $set_state, node_state($p->[0]), @{$p}); + update_size($common); +} + +sub fast_toggle { + my ($item) = @_; + #gtkset_mousecursor_wait($w->{w}{rwindow}->window); + #my $_cleaner = before_leaving { gtkset_mousecursor_normal($w->{w}{rwindow}->window) }; + my $name = $common->{table_item_list}[$item->index()]; + my $urpm_obj = $pkgs->{$name}{pkg}; + if ($urpm_obj->flag_base) { + interactive_msg($loc->N("Warning"), $loc->N("Removing package %s would break your system", $name)); + return ''; + } + if ($urpm_obj->flag_skip) { + interactive_msg($loc->N("Warning"), $loc->N("The \"%s\" package is in urpmi skip list.\nDo you want to select it anyway?", $name), yesno => 1) or return ''; + $urpm_obj->set_flag_skip(0); + } + if ($ManaTools::Rpmdragora::pkg::need_restart && !$priority_up_alread_warned) { + $priority_up_alread_warned = 1; + interactive_msg($loc->N("Warning"), '' . $loc->N("Rpmdragora or one of its priority dependencies needs to be updated first. Rpmdragora will then restart.") . '' . "\n\n"); + } + # toggle_nodes($w->{tree}->window, $w->{detail_list_model}, \&set_leaf_state, $w->{detail_list_model}->get($iter, $pkg_columns{state}), + + my $old_status = node_state($name); + + #$DB::single = 1; + +# my $old_state; +# if($item->checked()){ +# $old_state = "to_install"; +# }else{ +# $old_state = "to_remove"; +# } + toggle_nodes($w->{tree}, $w->{detail_list}, \&set_leaf_state, $old_status, $name); + update_size($common); +}; + +# ask_browse_tree_given_widgets_for_rpmdragora will run gtk+ loop. its main parameter "common" is a hash containing: +# - a "widgets" subhash which holds: +# o a "w" reference on a ugtk2 object +# o "tree" & "info" references a TreeView +# o "info" is a TextView +# o "tree_model" is the associated model of "tree" +# o "status" references a Label +# - some methods: get_info, node_state, build_tree, partialsel_unsel, grep_unselected, rebuild_tree, toggle_nodes, get_status +# - "tree_submode": the default mode (by group, ...), ... +# - "state": a hash of misc flags: => { flat => '0' }, +# o "flat": is the tree flat or not +# - "tree_mode": mode of the tree ("gui_pkgs", "by_group", ...) (mainly used by rpmdragora) + +sub ask_browse_tree_given_widgets_for_rpmdragora { + ($common) = @_; + $w = $common->{widgets}; + + $common->{table_item_list} = \@table_item_list; + + $w->{detail_list} ||= $w->{tree}; + #$w->{detail_list_model} ||= $w->{tree_model}; + + $common->{add_parent} = \&add_parent; + my $clear_all_caches = sub { + %ptree = %wtree = (); + @table_item_list = (); + }; + $common->{clear_all_caches} = $clear_all_caches; + $common->{delete_all} = sub { + $clear_all_caches->(); + %groups_tree = (); + }; + $common->{rebuild_tree} = sub { + $common->{delete_all}->(); + $common->{build_tree}($common->{state}{flat}, $common->{tree_mode}); + update_size($common); + }; + $common->{delete_category} = sub { + my ($cat) = @_; + carp "WARNING TODO delete_category to be removed!"; + exists $wtree{$cat} or return; + %ptree = (); + update_size($common); + return; + }; + $common->{add_nodes} = sub { + my (@nodes) = @_; + carp "TODO ==================> ADD NODES - add packages (" . scalar(@nodes) . ") \n"; + yui::YUI::app()->busyCursor(); + + my $lastItem = $w->{detail_list}->selectedItem() ? $w->{detail_list}->selectedItem()->label() : ""; + $w->{detail_list}->startMultipleChanges(); + $w->{detail_list}->deleteAllItems(); + my $itemColl = new yui::YItemCollection; + + @table_item_list = (); + my $index = 0; + foreach(@nodes){ + add_package_item($itemColl, $_->[0], ($lastItem eq $_->[0])); + warn "Unmanaged param " . $_->[2] if defined $_->[2]; + $ptree{$_->[0]} = [ $index ]; + $index++; + push @table_item_list, $_->[0]; + } + + update_size($common); + $w->{detail_list}->addItems($itemColl); + $w->{detail_list}->doneMultipleChanges(); + yui::YUI::app()->normalCursor(); + }; + + $common->{rebuild_tree}->(); + update_size($common); + $common->{initial_selection} and toggle_nodes($w->{tree}->window, $w->{detail_list}, \&set_leaf_state, undef, @{$common->{initial_selection}}); + my $_b = before_leaving { $clear_all_caches->() }; + $common->{init_callback}->() if $common->{init_callback}; + + $w->{w}; +} + +our $find_entry; + +sub reset_search() { + return if !$common; + +# TODO $common->{delete_category}->($_) foreach $results_ok, $results_none; + # clear package list: + yui::YUI::app()->busyCursor(); + my $wdgt = $common->{widgets}; + $wdgt->{detail_list}->startMultipleChanges(); + $wdgt->{detail_list}->deleteAllItems(); + $wdgt->{detail_list}->doneMultipleChanges(); + yui::YUI::app()->normalCursor(); +} + +sub is_a_package { + my ($pkg) = @_; + return exists $pkgs->{$pkg}; +} + +sub switch_pkg_list_mode { + my ($mode) = @_; + return if !$mode; + return if !$filter_methods{$mode}; + $force_displaying_group = 1; + $filter_methods{$mode}->(); +} + +sub is_updatable { + my $p = $pkgs->{$_[0]}; + $p->{pkg} && !$p->{selected} && $p->{pkg}->flag_installed && $p->{pkg}->flag_upgrade; +} + +sub pkgs_provider { + my ($mode, %options) = @_; + return if !$mode; + my $h = &get_pkgs(%options); + ($urpm, $descriptions) = @$h{qw(urpm update_descr)}; + $pkgs = $h->{all_pkgs}; + %filters = ( + non_installed => $h->{installable}, + installed => $h->{installed}, + all => [ keys %$pkgs ], + ); + my %tmp_filter_methods = ( + all => sub { + [ difference2([ keys %$pkgs ], $h->{inactive_backports}) ]; + }, + all_updates => sub { + # potential "updates" from media not tagged as updates: + if (!$options{pure_updates} && !$ManaTools::Rpmdragora::pkg::need_restart) { + [ @{$h->{updates}}, + difference2([ grep { is_updatable($_) } @{$h->{installable}} ], $h->{backports}) ]; + } else { + [ difference2($h->{updates}, $h->{inactive_backports}) ]; + } + }, + backports => sub { $h->{backports} }, + meta_pkgs => sub { + [ difference2($h->{meta_pkgs}, $h->{inactive_backports}) ]; + }, + gui_pkgs => sub { + [ difference2($h->{gui_pkgs}, $h->{inactive_backports}) ]; + }, + ); + foreach my $importance (qw(bugfix security normal)) { + $tmp_filter_methods{$importance} = sub { + my @media = keys %$descriptions; + [ grep { + my ($name) = split_fullname($_); + my $medium = MDK::Common::Func::find { $descriptions->{$_}{$name} } @media; + $medium && $descriptions->{$medium}{$name}{importance} eq $importance } @{$h->{updates}} ]; + }; + } + + undef %filter_methods; + foreach my $type (keys %tmp_filter_methods) { + $filter_methods{$type} = sub { + $force_rebuild = 1; # force rebuilding tree since we changed filter (FIXME: switch to SortModel) + @filtered_pkgs = intersection($filters{$filter->[0]}, $tmp_filter_methods{$type}->()); + }; + } + + switch_pkg_list_mode($mode); +} + +sub closure_removal { + local $urpm->{state} = {}; + urpm::select::find_packages_to_remove($urpm, $urpm->{state}, \@_); +} + +sub is_locale_available { + my ($name) = @_; + any { $urpm->{depslist}[$_]->flag_selected } keys %{$urpm->{provides}{$name} || {}} and return 1; + my $found; + open_rpm_db()->traverse_tag_find('name', $name, sub { $found = 1 }); + return $found; +} + +sub callback_choices { + my (undef, undef, undef, $choices) = @_; + return $choices->[0] if $::rpmdragora_options{auto}; + foreach my $pkg (@$choices) { + foreach ($pkg->requires_nosense) { + /locales-/ or next; + is_locale_available($_) and return $pkg; + } + } + my $callback = sub { interactive_msg($loc->N("More information on package..."), get_info($_[0]), scroll => 1) }; + $choices = [ sort { $a->name cmp $b->name } @$choices ]; + my @choices = interactive_list_($loc->N("Please choose"), (scalar(@$choices) == 1 ? + $loc->N("The following package is needed:") : $loc->N("One of the following packages is needed:")), + [ map { urpm_name($_) } @$choices ], $callback, nocancel => 1); + defined $choices[0] ? $choices->[$choices[0]] : undef; +} + +#============================================================= + +=head2 info_details + +=head3 INPUT + + $info_detail_selected: string to get more info details + (see %hidden_info) + $info_options: reference to info options that are going to changed + based on passed $info_detail_selected + +=head3 OUTPUT + + [0, 1]: 0 if $info_detail_selected not valid, 1 otherwise + +=head3 DESCRIPTION + + This function change the info_options accordingly to the string passed + returning 0 if the string is not managed (see %hidden_info) + +=cut + +#============================================================= +sub info_details { + my ($info_detail_selected, $info_options) = @_; + + foreach my $k (keys %hidden_info) { + if ($info_detail_selected eq $hidden_info{$k}) { + $info_options->{$k} = $info_options->{$k} ? 0 : 1; + return 1; + } + } + return 0; +} + +#============================================================= + +=head2 setInfoOnWidget + +=head3 INPUT + + $pckgname: full name of the package + $infoWidget: YRichText object to fill + +=head3 DESCRIPTION + + This function writes on a YRichText object package info + +=cut + +#============================================================= +sub setInfoOnWidget { + my ($pkgname, $infoWidget, $options) = @_; + + return if( ref $infoWidget ne "yui::YRichText"); + + $infoWidget->setValue(""); + + my $info_text = ""; + + my @data = get_info($pkgname, $options); + for(@{$data[0]}){ + if(ref $_ ne "ARRAY"){ + $info_text .= $_ . "
   "; + }else{ + for my $subitem(@{$_}) { + $info_text .= "
" . "
   " . $subitem; + } + } + } + # change \n to
+ $info_text =~ s|\n|
|g; + + $infoWidget->setValue($info_text); +} + + +sub deps_msg { + return 1 if $dont_show_selections->[0]; + my ($title, $msg, $nodes, $nodes_with_deps) = @_; + + my @deps = sort { $a cmp $b } difference2($nodes_with_deps, $nodes); + @deps > 0 or return 1; + + my $appTitle = yui::YUI::app()->applicationTitle(); + + ## set new title to get it in dialog + yui::YUI::app()->setApplicationTitle($title); +# TODO icon if needed +# yui::YUI::app()->setApplicationIcon($which_icon); + + my $factory = yui::YUI::widgetFactory; + + ## | [msg-label] | + ## | | + ## | pkg-list | info on selected pkg |(1) + ## | | + ## | [cancel] [ok] | + #### + # (1) info on pkg list: + # [ label info ] + # sub info on click (Details, Files, Changelog, New dependencies) + + my $dialog = $factory->createPopupDialog; + my $vbox = $factory->createVBox( $dialog ); + my $msgBox = $factory->createLabel($vbox, $msg, 1); +# my $hbox = $factory->createHBox( $vbox ); + my $pkgList = $factory->createSelectionBox( $vbox, $loc->N("Select package") ); + $factory->createVSpacing($vbox, 1); + +# my $frame = $factory->createFrame ($hbox, $loc->N("Information on packages")); +# my $frmVbox = $factory->createVBox( $frame ); + my $infoBox = $factory->createRichText($vbox, "", 0); + $pkgList->setWeight($yui::YD_HORIZ, 2); + $infoBox->setWeight($yui::YD_HORIZ, 3); + $factory->createVSpacing($vbox, 1); + my $hbox = $factory->createHBox( $vbox ); + my $align = $factory->createRight($hbox); + my $cancelButton = $factory->createPushButton($align, $loc->N("&Cancel")); + my $okButton = $factory->createPushButton($hbox, $loc->N("&Ok")); + + # adding packages to the list + my $itemColl = new yui::YItemCollection; + foreach my $p (map { scalar(urpm::select::translate_why_removed_one($urpm, $urpm->{state}, $_)) } @deps) { + my $item = new yui::YTableItem ("$p"); + $item->setLabel( $p ); + $itemColl->push($item); + $item->DISOWN(); + } + $pkgList->addItems($itemColl); + $pkgList->setImmediateMode(1); + my $item = $pkgList->selectedItem(); + if ($item) { + my $pkg = $item->label(); + setInfoOnWidget($pkg, $infoBox); + } + + my $retval = 0; + my $info_options = {}; + while(1) { + my $event = $dialog->waitForEvent(); + my $eventType = $event->eventType(); + + #event type checking + if ($eventType == $yui::YEvent::CancelEvent) { + last; + } + elsif ($eventType == $yui::YEvent::MenuEvent) { + my $item = $event->item(); + if (!$item) { + #URL emitted or at least a ref into RichText widget + my $url = yui::toYMenuEvent($event)->id (); + if (ManaTools::Rpmdragora::gui::info_details($url, $info_options) ) { + $item = $pkgList->selectedItem(); + my $pkg = $item->label(); + ManaTools::Rpmdragora::gui::setInfoOnWidget($pkg, $infoBox, $info_options); + } + else { + # default it's really a URL + ManaTools::Rpmdragora::gui::run_browser($url); + } + } + } + elsif ($eventType == $yui::YEvent::WidgetEvent) { + ### widget + my $widget = $event->widget(); + if ($widget == $pkgList) { + #change info + $item = $pkgList->selectedItem(); + $info_options = {}; + if ( $item ) { + my $pkg = $item->label(); + setInfoOnWidget($pkg, $infoBox); + } + } + elsif ($widget == $okButton) { + $retval = 1; + last; + } + elsif ($widget == $cancelButton) { + last; + } + } + } + + destroy $dialog; + + # restore original title + yui::YUI::app()->setApplicationTitle($appTitle) if $appTitle; + + return $retval; +} + +# set_state <- package-fullname, node_state = {to_install, to_remove,...}, list=YTable +sub toggle_nodes { + my ($widget, $detail_list, $set_state, $old_state, @nodes) = @_; + + @nodes = grep { exists $pkgs->{$_} } @nodes + or return; + #- avoid selecting too many packages at once + return if !$dont_show_selections->[0] && @nodes > 2000; + my $new_state = !$pkgs->{$nodes[0]}{selected}; + + my @nodes_with_deps; + + my $bar_id = statusbar_msg($loc->N("Checking dependencies of package..."), 0); + + my $warn_about_additional_packages_to_remove = sub { + my ($msg) = @_; + statusbar_msg_remove($bar_id); + deps_msg($loc->N("Some additional packages need to be removed"), + MDK::Common::String::formatAlaTeX($msg) . "\n\n", + \@nodes, \@nodes_with_deps) or @nodes_with_deps = (); + }; + + if (member($old_state, qw(to_remove installed))) { # remove pacckages + if ($new_state) { + my @remove; + slow_func(sub { @remove = closure_removal(@nodes) }); + @nodes_with_deps = grep { !$pkgs->{$_}{selected} && !/^basesystem/ } @remove; + $warn_about_additional_packages_to_remove->( + $loc->N("Because of their dependencies, the following package(s) also need to be removed:")); + my @impossible_to_remove; + foreach (grep { exists $pkgs->{$_}{base} } @remove) { + ${$pkgs->{$_}{base}} == 1 ? push @impossible_to_remove, $_ : ${$pkgs->{$_}{base}}--; + } + @impossible_to_remove and interactive_msg($loc->N("Some packages cannot be removed"), + $loc->N("Removing these packages would break your system, sorry:\n\n") . + format_list(@impossible_to_remove)); + @nodes_with_deps = difference2(\@nodes_with_deps, \@impossible_to_remove); + } else { + @nodes_with_deps = grep { intersection(\@nodes, [ closure_removal($_) ]) } + grep { $pkgs->{$_}{selected} && !member($_, @nodes) } keys %$pkgs; + push @nodes_with_deps, @nodes; + $warn_about_additional_packages_to_remove->( + $loc->N("Because of their dependencies, the following package(s) must be unselected now:\n\n")); + $pkgs->{$_}{base} && ${$pkgs->{$_}{base}}++ foreach @nodes_with_deps; + } + } else { + if ($new_state) { + if (@nodes > 1) { + #- unselect i18n packages of which locales is not already present (happens when user clicks on KDE group) + my @bad_i18n_pkgs; + foreach my $sel (@nodes) { + foreach ($pkgs->{$sel}{pkg}->requires_nosense) { + /locales-([^-]+)/ or next; + $sel =~ /-$1[-_]/ && !is_locale_available($_) and push @bad_i18n_pkgs, $sel; + } + } + @nodes = difference2(\@nodes, \@bad_i18n_pkgs); + } + my @requested; + @requested = $urpm->resolve_requested( + open_rpm_db(), $urpm->{state}, + { map { $pkgs->{$_}{pkg}->id => 1 } @nodes }, + callback_choices => \&callback_choices, + ); + @nodes_with_deps = map { urpm_name($_) } @requested; + statusbar_msg_remove($bar_id); + if (!deps_msg($loc->N("Additional packages needed"), + MDK::Common::String::formatAlaTeX($loc->N("To satisfy dependencies, the following package(s) also need to be installed:\n\n")) . "\n\n", + \@nodes, \@nodes_with_deps)) { + @nodes_with_deps = (); + $urpm->disable_selected(open_rpm_db(), $urpm->{state}, @requested); + goto packages_selection_ok; + } + + if (my $conflicting_msg = urpm::select::conflicting_packages_msg($urpm, $urpm->{state})) { + if (!interactive_msg($loc->N("Conflicting Packages"), $conflicting_msg, yesno => 1, scroll => 1)) { + @nodes_with_deps = (); + $urpm->disable_selected(open_rpm_db(), $urpm->{state}, @requested); + goto packages_selection_ok; + } + } + + if (my @cant = sort(difference2(\@nodes, \@nodes_with_deps))) { + my @ask_unselect = urpm::select::unselected_packages($urpm->{state}); + my @reasons = map { + my $cant = $_; + my $unsel = MDK::Common::Func::find { $_ eq $cant } @ask_unselect; + $unsel + ? join("\n", urpm::select::translate_why_unselected($urpm, $urpm->{state}, $unsel)) + : ($pkgs->{$_}{pkg}->flag_skip ? $loc->N("%s (belongs to the skip list)", $cant) : $cant); + } @cant; + my $count = @reasons; + interactive_msg( + ($count == 1 ? $loc->N("One package cannot be installed") : $loc->N("Some packages cannot be installed")), + ($count == 1 ? + $loc->N("Sorry, the following package cannot be selected:\n\n%s", format_list(@reasons)) + : $loc->N("Sorry, the following packages cannot be selected:\n\n%s", format_list(@reasons))), + scroll => 1, + ); + foreach (@cant) { + next unless $pkgs->{$_}{pkg}; + $pkgs->{$_}{pkg}->set_flag_requested(0); + $pkgs->{$_}{pkg}->set_flag_required(0); + } + } + packages_selection_ok: + } else { + my @unrequested; + @unrequested = $urpm->disable_selected(open_rpm_db(), $urpm->{state}, + map { $pkgs->{$_}{pkg} } @nodes); + @nodes_with_deps = map { urpm_name($_) } @unrequested; + statusbar_msg_remove($bar_id); + if (!deps_msg($loc->N("Some packages need to be removed"), + $loc->N("Because of their dependencies, the following package(s) must be unselected now:\n\n"), + \@nodes, \@nodes_with_deps)) { + @nodes_with_deps = (); + $urpm->resolve_requested(open_rpm_db(), $urpm->{state}, { map { $_->id => 1 } @unrequested }); + goto packages_unselection_ok; + } + packages_unselection_ok: + } + } + + foreach (@nodes_with_deps) { + #- some deps may exist on some packages which aren't listed because + #- not upgradable (older than what currently installed) + exists $pkgs->{$_} or next; + if (!$pkgs->{$_}{pkg}) { #- can't be removed # FIXME; what about next packages in the loop? + undef $pkgs->{$_}{selected}; + Sys::Syslog::syslog('info|local1', "can't be removed: $_"); + } else { + $pkgs->{$_}{selected} = $new_state; + } + # invoke set_leaf_state($pkgname, node_state, ) + # node_state = {to_install, to_remove,...} + + $set_state->($_, node_state($_), $detail_list); + if (my $pkg = $pkgs->{$_}{pkg}) { + # FIXME: shouldn't we threat all of them as POSITIVE (as selected size) + $size_selected += $pkg->size * ($pkg->flag_installed && !$pkg->flag_upgrade ? ($new_state ? -1 : 1) : ($new_state ? 1 : -1)); + } + } +} + +sub is_there_selected_packages() { + int(grep { $pkgs->{$_}{selected} } keys %$pkgs); +} + +sub real_quit() { + if (is_there_selected_packages()) { + return interactive_msg($loc->N("Some packages are selected."), $loc->N("Some packages are selected.") . "\n" . $loc->N("Do you really want to quit?"), yesno => 1); + } + + return 1; +} + +sub do_action__real { + my ($options, $callback_action, $o_info) = @_; + require urpm::sys; + if (!urpm::sys::check_fs_writable()) { + $urpm->{fatal}(1, $loc->N("Error: %s appears to be mounted read-only.", $urpm::sys::mountpoint)); + return 1; + } + if (!$ManaTools::Rpmdragora::pkg::need_restart && !is_there_selected_packages()) { + interactive_msg($loc->N("You need to select some packages first."), $loc->N("You need to select some packages first.")); + return 1; + } + my $size_added = MDK::Common::Math::sum(map { MDK::Common::Func::if_($_->flag_selected && !$_->flag_installed, $_->size) } @{$urpm->{depslist}}); + if ($MODE eq 'install' && $size_free - $size_added/1024 < 50*1024) { + interactive_msg($loc->N("Too many packages are selected"), + $loc->N("Warning: it seems that you are attempting to add so many +packages that your filesystem may run out of free diskspace, +during or after package installation ; this is particularly +dangerous and should be considered with care. + +Do you really want to install all the selected packages?"), yesno => 1) + or return 1; + } + my $res = $callback_action->($urpm, $pkgs); + if (!$res) { + $force_rebuild = 1; + pkgs_provider($options->{tree_mode}, MDK::Common::Func::if_($ManaTools::Rpmdragora::pkg::probe_only_for_updates, pure_updates => 1), skip_updating_mu => 1); + reset_search(); + $size_selected = 0; + (undef, $size_free) = MDK::Common::System::df('/usr'); + $options->{rebuild_tree}->() if $options->{rebuild_tree}; + $o_info->setValue("") if $o_info; + } + $res; +} + +sub do_action { + my ($options, $callback_action, $o_info) = @_; + my $res = eval { do_action__real($options, $callback_action, $o_info) }; + my $err = $@; + # FIXME: offer to report the problem into bugzilla: + if ($err && $err !~ /cancel_perform/) { + interactive_msg($loc->N("Fatal error"), + $loc->N("A fatal error occurred: %s.", $err)); + } + $res; +} + +sub translate_group { + join('/', map { $loc->N($_) } split m|/|, $_[0]); +} + +sub ctreefy { + join('|', map { $loc->N($_) } split m|/|, $_[0]); +} + +sub _build_tree { + my ($tree, $pkg_by_group_hash, @pkg_name_and_group_list) = @_; + + print "TODO ====> BUILD TREE\n"; + + yui::YUI::app()->busyCursor(); + + #- we populate all the groups tree at first + %{$pkg_by_group_hash} = (); + # better loop on packages, create groups tree and push packages in the proper place: + my @groups = (); + foreach my $pkg (@pkg_name_and_group_list) { + my $grp = $pkg->[1]; + # no state for groups (they're not packages and thus have no state) + push @groups, $grp; + + $pkg_by_group_hash->{$grp} ||= []; + push @{$pkg_by_group_hash->{$grp}}, $pkg; + } + + my $tree_hash = ManaTools::Shared::pathList2hash({ + paths => \@groups, + separator => '|', + }); + + $tree->startMultipleChanges(); + my $selected = $tree->selectedItem(); + my $groupname = group_path_name($selected) if $selected; + + $tree->deleteAllItems() if $tree->hasItems(); + + # TODO fixing geti icon api to get a better hash from the module + my %icons = (); + foreach my $group (@groups) { + next if defined($icons{$group}); + my @items = split('\|', $group); + if (scalar(@items) > 1) { + $icons{$items[0]} = get_icon_path($items[0], 0); + $icons{$group} = get_icon_path($items[1], $items[0]) + } + else { + $icons{$group} = get_icon_path($group, 0); + } + } + + my $itemColl = new yui::YItemCollection; + $shared_gui->hashTreeToYItemCollection({ + collection => $itemColl, + hash_tree => $tree_hash, + icons => \%icons, + default_item_separator => '|', + default_item => $groupname, + }); + + $tree->addItems($itemColl); + $tree->doneMultipleChanges(); + $tree->rebuildTree(); + yui::YUI::app()->normalCursor(); +} + + +sub build_tree { + my ($tree, $pkg_by_group_hash, $options, $force_rebuild, $flat, $mode) = @_; + state $old_mode; + $mode = $options->{rmodes}{$mode} || $mode; + $old_mode = '' if(!defined($old_mode)); + return if $old_mode eq $mode && !$force_rebuild; + $old_mode = $mode; + undef $force_rebuild; + my @elems; + my $wait; $wait = statusbar_msg($loc->N("Please wait, listing packages...")) if $MODE ne 'update'; + + my @keys = @filtered_pkgs; + if (member($mode, qw(all_updates security bugfix normal))) { + @keys = grep { + my ($name) = split_fullname($_); + member($descriptions->{$name}{importance}, @$mandrakeupdate_wanted_categories) + || ! $descriptions->{$name}{importance}; + } @keys; + if (@keys == 0) { + _build_tree($tree, $pkg_by_group_hash, ['', $loc->N("(none)")]); +# add_node('', $loc->N("(none)"), { nochild => 1 }); + state $explanation_only_once; + $explanation_only_once or interactive_msg($loc->N("No update"), + $loc->N("The list of updates is empty. This means that either there is +no available update for the packages installed on your computer, +or you already installed all of them.")); + $explanation_only_once = 1; + } + } + if (scalar @keys) { + # FIXME: better do this on first group access for faster startup... + @elems = map { [ $_, !$flat && ctreefy($pkgs->{$_}{pkg}->group) ] } sort_packages(@keys); + + my %sortmethods = ( + by_size => sub { sort { $pkgs->{$b->[0]}{pkg}->size <=> $pkgs->{$a->[0]}{pkg}->size } @_ }, + by_selection => sub { sort { $pkgs->{$b->[0]}{selected} <=> $pkgs->{$a->[0]}{selected} + || uc($a->[0]) cmp uc($b->[0]) } @_ }, + by_leaves => sub { + # inlining part of MDK::Common::Data::difference2(): + my %l; @l{map { $_->[0] } @_} = (); + my @pkgs_times = ('rpm', '-q', '--qf', '%{name}-%{version}-%{release}.%{arch} %{installtime}\n', + map { chomp_($_) } ManaTools::Shared::RunProgram::get_stdout('urpmi_rpm-find-leaves')); + sort { $b->[1] <=> $a->[1] } grep { exists $l{$_->[0]} } map { chomp; [ split ] } run_rpm(@pkgs_times); + }, + flat => sub { no locale; sort { uc($a->[0]) cmp uc($b->[0]) } @_ }, + by_medium => sub { sort { $a->[2] <=> $b->[2] || uc($a->[0]) cmp uc($b->[0]) } @_ }, + ); + if ($flat) { + carp "WARNING: TODO \$flat not tested\n"; + _build_tree($tree, $pkg_by_group_hash, map {[$_->[0], '']} $sortmethods{$::mode->[0] || 'flat'}->(@elems)); +# add_node($_->[0], '') foreach $sortmethods{$::mode->[0] || 'flat'}->(@elems); + } + else { + if ($::mode->[0] eq 'by_source') { + _build_tree($tree, $pkg_by_group_hash, $sortmethods{by_medium}->(map { + my $m = pkg2medium($pkgs->{$_->[0]}{pkg}, $urpm); [ $_->[0], $m->{name}, $m->{priority} ]; + } @elems)); + } + elsif ($::mode->[0] eq 'by_presence') { + _build_tree($tree, $pkg_by_group_hash, map { + my $pkg = $pkgs->{$_->[0]}{pkg}; + [ $_->[0], $pkg->flag_installed ? + (!$pkg->flag_skip && $pkg->flag_upgrade ? $loc->N("Upgradable") : $loc->N("Installed")) + : $loc->N("Addable") ]; + } $sortmethods{flat}->(@elems)); + } + else { + _build_tree($tree, $pkg_by_group_hash, @elems); + } + } + } + statusbar_msg_remove($wait) if defined $wait; +} + +#============================================================= + +=head2 get_info + +=head3 INPUT + + $key: package full name + $options: HASH reference containing: + details => show details + changelog => show changelog + files => show files + new_deps => show new dependencies + +=head3 DESCRIPTION + + return a string with all the package info + +=cut + +#============================================================= +sub get_info { + my ($key, $options) = @_; + #- the package information hasn't been loaded. Instead of rescanning the media, just give up. + exists $pkgs->{$key} or return [ [ $loc->N("Description not available for this package\n") ] ]; + #- get the description if needed: + exists $pkgs->{$key}{description} or slow_func(sub { extract_header($pkgs->{$key}, $urpm, 'info', find_installed_version($pkgs->{$key}{pkg})) }); + _format_pkg_simplifiedinfo($pkgs, $key, $urpm, $descriptions, $options); +} + +sub sort_callback { + my ($store, $treeiter1, $treeiter2) = @_; + URPM::rpmvercmp(map { $store->get_value($_, $pkg_columns{version}) } $treeiter1, $treeiter2); +} + +sub run_help_callback { + my (undef, $url) = @_; + my ($user) = grep { $_->[2] eq $ENV{USERHELPER_UID} } list_passwd(); + local $ENV{HOME} = $user->[7] if $user && $ENV{USERHELPER_UID}; + ManaTools::Shared::RunProgram::raw({ detach => 1, as_user => 1 }, 'www-browser', $url); +} + +#============================================================= + +=head2 run_browser + +=head3 INPUT + + $url: url to be passed to the configured browser + +=head3 DESCRIPTION + + This function calls the browser with the given URL + +=cut + +#============================================================= +sub run_browser { + my $url = shift; + + my ($user) = grep { $_->[2] eq $ENV{USERHELPER_UID} } MDK::Common::System::list_passwd(); + local $ENV{HOME} = $user->[7] if $user && $ENV{USERHELPER_UID}; + ManaTools::Shared::RunProgram::raw({ detach => 1, as_user => 1 }, 'www-browser', $url); +} + +#============================================================= + +=head2 group_path_name + +=head3 INPUT + + $treeItem: YTreeItem object + +=head3 OUTPUT + + $fullname: completed path group name + +=head3 DESCRIPTION + + This function returns the path name treeItem group name (e.g. foo|bar) + +=cut + +#============================================================= +sub group_path_name { + my $treeItem = shift; + + my $fullname = $treeItem->label(); + my $it = $treeItem; + while ($it = $it->parent()) { + $fullname = join("|", $it->label(), $fullname); + } + + return $fullname; +} + +sub groups_tree { + carp "DEPRECATED groups_tree: do not use it any more!"; + + return %groups_tree; +} + +sub group_has_parent { + my ($group) = shift; + carp "DEPRECATED group_has_parent: do not use it any more!"; + return 0 if(!defined($group)); + return defined($groups_tree{$group}{parent}); +} + +sub group_parent { + my ($group) = shift; + + carp "DEPRECATED group_parent: do not use it any more!"; + # if group is a parent itself return it + # who use group_parent have to take care of the comparison + # between a group and its parent + # e.g. group System has groups_tree{'System'}{parent}->label() = 'System' + return $groups_tree{$group}{parent} if(group_has_parent($group)); + for my $sup (keys %groups_tree){ + for my $item(keys %{$groups_tree{$sup}{children}}){ + if(defined($group) && ($item eq $group)){ + return $groups_tree{$sup}{parent}; + } + } + } + return undef; +} + +1; diff --git a/lib/ManaTools/Rpmdragora/gurpm.pm b/lib/ManaTools/Rpmdragora/gurpm.pm new file mode 100644 index 0000000..20cac6e --- /dev/null +++ b/lib/ManaTools/Rpmdragora/gurpm.pm @@ -0,0 +1,298 @@ +# vim: set et ts=4 sw=4: +package ManaTools::Rpmdragora::gurpm; + +#============================================================= -*-perl-*- + +=head1 NAME + + ManaTools::Rpmdragora::gurpm - Module that shows the urpmi + progress status + +=head1 SYNOPSIS + + my %option = (title => "Urpmi action ivoked", text => "Please wait", ); + my $gurpmi = ManaTools::Rpmdragora::gurpm->new(%option); + $gurpmi->progress(45); + + #add to an existing dialog + %option = (title => "Urpmi action ivoked", text => "Please wait", main_dialog => $dialog, parent => $parent_container); + $gurpmi = ManaTools::Rpmdragora::gurpm->new(%option); + $gurpmi->progress(20); + +=head1 DESCRIPTION + + This class is used to show the progress of an urpmi operation on + its progress bar. It can be istantiated as a popup dialog or used + to add label and progress bar into a YLayoutBox container. + +=head1 SUPPORT + + You can find documentation for this module with the perldoc command: + + perldoc ManaTools::Rpmdragora::gurpm + +=head1 AUTHOR + + Angelo Naselli + + Matteo Pasotti + +=head1 COPYRIGHT and LICENSE + + Copyright (c) 2002 Guillaume Cottenceau + Copyright (c) 2002-2007 Thierry Vignaud + Copyright (c) 2003, 2004, 2005 MandrakeSoft SA + Copyright (c) 2005-2007 Mandriva SA + Copyright (c) 2013 - 2015 Matteo Pasotti + Copyright (C) 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 Carp; +use Time::HiRes; + +use yui; +use feature 'state'; + + +has 'title' => ( + is => 'rw', + isa => 'Str', +); + +has 'text' => ( + is => 'rw', + isa => 'Str', +); + +has 'main_dialog' => ( + is => 'rw', + isa => 'yui::YDialog', +); + +has 'parent' => ( + is => 'rw', + isa => 'yui::YReplacePoint', +); + +has 'label_widget' => ( + is => 'rw', + isa => 'yui::YLabel', + init_arg => undef, +); + +has 'progressbar' => ( + is => 'rw', + isa => 'yui::YProgressBar', + init_arg => undef, +); + +#============================================================= + +=head2 BUILD + +=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; + + my $factory = yui::YUI::widgetFactory; + my $vbox; + + if (! $self->main_dialog) { + if ($self->parent) { + carp "WARNING: parent parameter is skipped without main_dialog set\n" ; + $self->parent(undef); + } + $self->main_dialog($factory->createPopupDialog()); + $vbox = $factory->createVBox($self->main_dialog); + } + else { + die "parent parameter is mandatory with main_dialog" if !$self->parent; + $self->main_dialog->startMultipleChanges(); + $self->parent->deleteChildren(); + $vbox = $factory->createVBox($self->parent); + $factory->createVSpacing($vbox, 0.5); + } + + $self->label_widget( $factory->createLabel($vbox, $self->text) ); + $self->label_widget->setStretchable( $yui::YD_HORIZ, 1 ); + $self->progressbar( $factory->createProgressBar($vbox, "") ); + + if ($self->parent) { + $factory->createVSpacing($vbox, 0.5); + $self->parent->showChild(); + $self->main_dialog->recalcLayout(); + $self->main_dialog->doneMultipleChanges(); + } + + $self->main_dialog->pollEvent(); + $self->flush(); +} + + +#============================================================= + +=head2 flush + +=head3 DESCRIPTION + + Polls a dialog event to refresh the dialog + +=cut + +#============================================================= +sub flush { + my ($self) = @_; + + $self->main_dialog->startMultipleChanges(); + $self->main_dialog->recalcLayout(); + $self->main_dialog->doneMultipleChanges(); + + if ($self->main_dialog->isTopmostDialog()) { + $self->main_dialog->waitForEvent(10); + $self->main_dialog->pollEvent(); + } + else { + carp "This dialog is not a top most dialog\n"; + } + yui::YUI::app()->redrawScreen(); +} + +#============================================================= + +=head2 label + +=head3 INPUT + + $text: text to be shown on label + +=head3 DESCRIPTION + + Sets the label text + +=cut + +#============================================================= +sub label { + my ($self, $text) = @_; + + $self->main_dialog->startMultipleChanges(); + $self->label_widget->setValue($text) if $text; + $self->main_dialog->doneMultipleChanges(); + + $self->flush(); +} + +#============================================================= + +=head2 progress + +=head3 INPUT + + $value: integer value in the range 0..100 + +=head3 DESCRIPTION + + Sets the progress bar percentage value + +=cut + +#============================================================= +sub progress { + my ($self, $value) = @_; + state $time = 0; + + $value = 0 if !defined($value) || $value < 0; + $value = 100 if 100 < $value; + + $self->progressbar->setValue($value); + return if Time::HiRes::clock_gettime() - $time < 0.333; + $time = Time::HiRes::clock_gettime(); + + $self->flush(); +} + +#============================================================= + +=head2 DEMOLISH + +=head3 INPUT + + $val: boolean value indicating whether or not this method + was called as part of the global destruction process + (when the Perl interpreter exits) + +=head3 DESCRIPTION + + Moose provides a hook for object destruction with the + DEMOLISH method as it does for construtor with BUILD + +=cut + +#============================================================= +sub DEMOLISH { + my ($self, $val) = @_; + + $self->main_dialog->destroy if !$self->parent; +} + +# TODO cancel button cannot be easily managed in libyui polling events +# removed atm +# +# sub validate_cancel { +# my ($self, $cancel_msg, $cancel_cb) = @_; +# $self->{main_dialog}->startMultipleChanges(); +# if (!$self->{cancel}) { +# $self->{cancel} = $self->{factory}->createIconButton($self->{vbox},"",$cancel_msg); +# #gtkpack__( +# #$self->{vbox}, +# #$self->{hbox_cancel} = gtkpack__( +# #gtknew('HButtonBox'), +# #$self->{cancel} = gtknew('Button', text => $cancel_msg, clicked => \&$cancel_cb), +# #), +# #); +# } +# #$self->{cancel}->set_sensitive(1); +# #$self->{cancel}->show; +# $self->flush(); +# } +# +# sub invalidate_cancel { +# my ($self) = @_; +# $self->{cancel} and $self->{cancel}->setEnabled(0); +# } +# +# sub invalidate_cancel_forever { +# my ($self) = @_; +# #$self->{hbox_cancel} or return; +# #$self->{hbox_cancel}->destroy; +# # FIXME: temporary workaround that prevents +# # Gtk2::Label::set_text() set_text_internal() -> queue_resize() -> +# # size_allocate() call chain to mess up when ->shrink_topwindow() +# # has been called (#32613): +# #$self->shrink_topwindow; +# } + +1; diff --git a/lib/ManaTools/Rpmdragora/icon.pm b/lib/ManaTools/Rpmdragora/icon.pm new file mode 100644 index 0000000..6c3887d --- /dev/null +++ b/lib/ManaTools/Rpmdragora/icon.pm @@ -0,0 +1,234 @@ +# vim: set et ts=4 sw=4: +package ManaTools::Rpmdragora::icon; +#***************************************************************************** +# +# Copyright (c) 2002 Guillaume Cottenceau +# Copyright (c) 2002-2007 Thierry Vignaud +# Copyright (c) 2003, 2004, 2005 MandrakeSoft SA +# Copyright (c) 2005-2007 Mandriva SA +# Copyright (c) 2013 - 2015 Matteo Pasotti +# 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. +# +#***************************************************************************** +# +# $Id: icon.pm 237459 2008-02-26 14:20:47Z tv $ + +use strict; + +use ManaTools::rpmdragora; +use ManaTools::Shared::Locales; + +my $loc = ManaTools::rpmdragora::locale(); + +use Exporter; +our @ISA = qw(Exporter); +our @EXPORT_OK = qw(get_icon_path); +#- /usr/share/rpmlint/config (duplicates are normal, so that we are not too far away from .py) +my %group_icons = ( + $loc->N("All") => 'system_section', + $loc->N("Accessibility") => 'accessibility_section', + $loc->N("Archiving") => 'archiving_section', + join('|', $loc->N("Archiving"), $loc->N("Backup")) => 'backup_section', + join('|', $loc->N("Archiving"), $loc->N("Cd burning")) => 'cd_burning_section', + join('|', $loc->N("Archiving"), $loc->N("Compression")) => 'compression_section', + join('|', $loc->N("Archiving"), $loc->N("Other")) => 'other_archiving', + $loc->N("Communications") => 'communications_section', + join('|', $loc->N("Communications"), $loc->N("Bluetooth")) => 'communications_bluetooth_section', + join('|', $loc->N("Communications"), $loc->N("Dial-Up")) => 'communications_dialup_section', + join('|', $loc->N("Communications"), $loc->N("Fax")) => 'communications_fax_section', + join('|', $loc->N("Communications"), $loc->N("Mobile")) => 'communications_mobile_section', + join('|', $loc->N("Communications"), $loc->N("Radio")) => 'communications_radio_section', + join('|', $loc->N("Communications"), $loc->N("Serial")) => 'communications_serial_section', + join('|', $loc->N("Communications"), $loc->N("Telephony")) => 'communications_phone_section', + $loc->N("Databases") => 'databases_section', + $loc->N("Development") => 'development_section', + join('|', $loc->N("Development"), $loc->N("Basic")) => '', + join('|', $loc->N("Development"), $loc->N("C")) => '', + join('|', $loc->N("Development"), $loc->N("C++")) => '', + join('|', $loc->N("Development"), $loc->N("C#")) => '', + join('|', $loc->N("Development"), $loc->N("Databases")) => 'databases_section', + join('|', $loc->N("Development"), $loc->N("Debug")) => '', + join('|', $loc->N("Development"), $loc->N("Erlang")) => '', + join('|', $loc->N("Development"), $loc->N("GNOME and GTK+")) => 'gnome_section', + join('|', $loc->N("Development"), $loc->N("Java")) => '', + join('|', $loc->N("Development"), $loc->N("KDE and Qt")) => 'kde_section', + join('|', $loc->N("Development"), $loc->N("Kernel")) => '', + join('|', $loc->N("Development"), $loc->N("OCaml")) => '', + join('|', $loc->N("Development"), $loc->N("Other")) => '', + join('|', $loc->N("Development"), $loc->N("Perl")) => '', + join('|', $loc->N("Development"), $loc->N("PHP")) => '', + join('|', $loc->N("Development"), $loc->N("Python")) => '', + join('|', $loc->N("Development"), $loc->N("Tools")) => 'development_tools_section', + join('|', $loc->N("Development"), $loc->N("X11")) => '', + $loc->N("Documentation") => 'documentation_section', + $loc->N("Editors") => 'editors_section', + $loc->N("Education") => 'education_section', + $loc->N("Emulators") => 'emulators_section', + $loc->N("File tools") => 'file_tools_section', + $loc->N("Games") => 'amusement_section', + join('|', $loc->N("Games"), $loc->N("Adventure")) => 'adventure_section', + join('|', $loc->N("Games"), $loc->N("Arcade")) => 'arcade_section', + join('|', $loc->N("Games"), $loc->N("Boards")) => 'boards_section', + join('|', $loc->N("Games"), $loc->N("Cards")) => 'cards_section', + join('|', $loc->N("Games"), $loc->N("Other")) => 'other_amusement', + join('|', $loc->N("Games"), $loc->N("Puzzles")) => 'puzzle_section', + join('|', $loc->N("Games"), $loc->N("Shooter")) => 'shooter_section', + join('|', $loc->N("Games"), $loc->N("Simulation")) => 'simulation_section', + join('|', $loc->N("Games"), $loc->N("Sports")) => 'sport_section', + join('|', $loc->N("Games"), $loc->N("Strategy")) => 'strategy_section', + $loc->N("Geography") => 'geography_section', + $loc->N("Graphical desktop") => 'graphical_desktop_section', + join('|', $loc->N("Graphical desktop"), + #-PO: This is a package/product name. Only translate it if needed: + $loc->N("Enlightenment")) => 'enlightment_section', + join('|', $loc->N("Graphical desktop"), + #-PO: This is a package/product name. Only translate it if needed: + $loc->N("GNOME")) => 'gnome_section', + join('|', $loc->N("Graphical desktop"), + #-PO: This is a package/product name. Only translate it if needed: + $loc->N("Icewm")) => 'icewm_section', + join('|', $loc->N("Graphical desktop"), + #-PO: This is a package/product name. Only translate it if needed: + $loc->N("KDE")) => 'kde_section', + join('|', $loc->N("Graphical desktop"), $loc->N("Other")) => 'more_applications_other_section', + join('|', $loc->N("Graphical desktop"), + #-PO: This is a package/product name. Only translate it if needed: + $loc->N("WindowMaker")) => 'windowmaker_section', + join('|', $loc->N("Graphical desktop"), + #-PO: This is a package/product name. Only translate it if needed: + $loc->N("Xfce")) => 'xfce_section', + $loc->N("Graphics") => 'graphics_section', + join('|', $loc->N("Graphics"), $loc->N("3D")) => 'graphics_3d_section', + join('|', $loc->N("Graphics"), $loc->N("Editors and Converters")) => 'graphics_editors_section', + join('|', $loc->N("Graphics"), $loc->N("Utilities")) => 'graphics_utilities_section', + join('|', $loc->N("Graphics"), $loc->N("Photography")) => 'graphics_photography_section', + join('|', $loc->N("Graphics"), $loc->N("Scanning")) => 'graphics_scanning_section', + join('|', $loc->N("Graphics"), $loc->N("Viewers")) => 'graphics_viewers_section', + $loc->N("Monitoring") => 'monitoring_section', + $loc->N("Networking") => 'networking_section', + join('|', $loc->N("Networking"), $loc->N("File transfer")) => 'file_transfer_section', + join('|', $loc->N("Networking"), $loc->N("IRC")) => 'irc_section', + join('|', $loc->N("Networking"), $loc->N("Instant messaging")) => 'instant_messaging_section', + join('|', $loc->N("Networking"), $loc->N("Mail")) => 'mail_section', + join('|', $loc->N("Networking"), $loc->N("News")) => 'news_section', + join('|', $loc->N("Networking"), $loc->N("Other")) => 'other_networking', + join('|', $loc->N("Networking"), $loc->N("Remote access")) => 'remote_access_section', + join('|', $loc->N("Networking"), $loc->N("WWW")) => 'networking_www_section', + $loc->N("Office") => 'office_section', + join('|', $loc->N("Office"), $loc->N("Dictionary")) => 'office_dictionary_section', + join('|', $loc->N("Office"), $loc->N("Finance")) => 'finances_section', + join('|', $loc->N("Office"), $loc->N("Management")) => 'timemanagement_section', + join('|', $loc->N("Office"), $loc->N("Organizer")) => 'timemanagement_section', + join('|', $loc->N("Office"), $loc->N("Utilities")) => 'office_accessories_section', + join('|', $loc->N("Office"), $loc->N("Spreadsheet")) => 'spreadsheet_section', + join('|', $loc->N("Office"), $loc->N("Suite")) => 'office_suite', + join('|', $loc->N("Office"), $loc->N("Word processor")) => 'wordprocessor_section', + $loc->N("Publishing") => 'publishing_section', + $loc->N("Sciences") => 'sciences_section', + join('|', $loc->N("Sciences"), $loc->N("Astronomy")) => 'astronomy_section', + join('|', $loc->N("Sciences"), $loc->N("Biology")) => 'biology_section', + join('|', $loc->N("Sciences"), $loc->N("Chemistry")) => 'chemistry_section', + join('|', $loc->N("Sciences"), $loc->N("Computer science")) => 'computer_science_section', + join('|', $loc->N("Sciences"), $loc->N("Geosciences")) => 'geosciences_section', + join('|', $loc->N("Sciences"), $loc->N("Mathematics")) => 'mathematics_section', + join('|', $loc->N("Sciences"), $loc->N("Other")) => 'other_sciences', + join('|', $loc->N("Sciences"), $loc->N("Physics")) => 'physics_section', + $loc->N("Security") => 'security_section', + $loc->N("Shells") => 'shells_section', + $loc->N("Sound") => 'sound_section', + join('|', $loc->N("Sound"), $loc->N("Editors and Converters")) => 'sound_editors_section', + join('|', $loc->N("Sound"), $loc->N("Midi")) => 'sound_midi_section', + join('|', $loc->N("Sound"), $loc->N("Mixers")) => 'sound_mixers_section', + join('|', $loc->N("Sound"), $loc->N("Players")) => 'sound_players_section', + join('|', $loc->N("Sound"), $loc->N("Utilities")) => 'sound_utilities_section', + $loc->N("System") => 'system_section', + join('|', $loc->N("System"), $loc->N("Base")) => 'system_section', + join('|', $loc->N("System"), $loc->N("Boot and Init")) => 'boot_init_section', + join('|', $loc->N("System"), $loc->N("Cluster")) => 'parallel_computing_section', + join('|', $loc->N("System"), $loc->N("Configuration")) => 'configuration_section', + join('|', $loc->N("System"), $loc->N("Fonts")) => 'chinese_section', + join('|', $loc->N("System"), $loc->N("Fonts"), $loc->N("True type")) => '', + join('|', $loc->N("System"), $loc->N("Fonts"), $loc->N("Type1")) => '', + join('|', $loc->N("System"), $loc->N("Fonts"), $loc->N("X11 bitmap")) => '', + join('|', $loc->N("System"), $loc->N("Internationalization")) => 'chinese_section', + join('|', $loc->N("System"), $loc->N("Kernel and hardware")) => 'hardware_configuration_section', + join('|', $loc->N("System"), $loc->N("Libraries")) => 'system_section', + join('|', $loc->N("System"), $loc->N("Networking")) => 'networking_configuration_section', + join('|', $loc->N("System"), $loc->N("Packaging")) => 'packaging_section', + join('|', $loc->N("System"), $loc->N("Printing")) => 'printing_section', + join('|', $loc->N("System"), $loc->N("Servers")) => 'servers_section', + join('|', $loc->N("System"), + #-PO: This is a package/product name. Only translate it if needed: + $loc->N("X11")) => 'x11_section', + $loc->N("Terminals") => 'terminals_section', + $loc->N("Text tools") => 'text_tools_section', + $loc->N("Toys") => 'toys_section', + $loc->N("Video") => 'video_section', + join('|', $loc->N("Video"), $loc->N("Editors and Converters")) => 'video_editors_section', + join('|', $loc->N("Video"), $loc->N("Players")) => 'video_players_section', + join('|', $loc->N("Video"), $loc->N("Television")) => 'video_television_section', + join('|', $loc->N("Video"), $loc->N("Utilities")) => 'video_utilities_section', + + # for Mageia Choice: + $loc->N("Workstation") => 'system_section', + join('|', $loc->N("Workstation"), $loc->N("Configuration")) => 'configuration_section', + join('|', $loc->N("Workstation"), $loc->N("Console Tools")) => 'interpreters_section', + join('|', $loc->N("Workstation"), $loc->N("Documentation")) => 'documentation_section', + join('|', $loc->N("Workstation"), $loc->N("Game station")) => 'amusement_section', + join('|', $loc->N("Workstation"), $loc->N("Internet station")) => 'networking_section', + join('|', $loc->N("Workstation"), $loc->N("Multimedia station")) => 'multimedia_section', + join('|', $loc->N("Workstation"), $loc->N("Network Computer (client)")) => 'other_networking', + join('|', $loc->N("Workstation"), $loc->N("Office Workstation")) => 'office_section', + join('|', $loc->N("Workstation"), $loc->N("Scientific Workstation")) => 'sciences_section', + $loc->N("Graphical Environment") => 'graphical_desktop_section', + + join('|', $loc->N("Graphical Environment"), $loc->N("GNOME Workstation")) => 'gnome_section', + join('|', $loc->N("Graphical Environment"), $loc->N("IceWm Desktop")) => 'icewm_section', + join('|', $loc->N("Graphical Environment"), $loc->N("KDE Workstation")) => 'kde_section', + join('|', $loc->N("Graphical Environment"), $loc->N("Other Graphical Desktops")) => 'more_applications_other_section', + $loc->N("Development") => 'development_section', + join('|', $loc->N("Development"), $loc->N("Development")) => 'development_section', + join('|', $loc->N("Development"), $loc->N("Documentation")) => 'documentation_section', + $loc->N("Server") => 'servers_section', + join('|', $loc->N("Server"), $loc->N("DNS/NIS")) => 'networking_section', + join('|', $loc->N("Server"), $loc->N("Database")) => 'databases_section', + join('|', $loc->N("Server"), $loc->N("Firewall/Router")) => 'networking_section', + join('|', $loc->N("Server"), $loc->N("Mail")) => 'mail_section', + join('|', $loc->N("Server"), $loc->N("Mail/Groupware/News")) => 'mail_section', + join('|', $loc->N("Server"), $loc->N("Network Computer server")) => 'networking_section', + join('|', $loc->N("Server"), $loc->N("Web/FTP")) => 'networking_www_section', + + ); + +sub get_icon_path { + my ($group, $parent) = @_; + + my $path = $parent ? '/usr/share/icons/mini/' : '/usr/share/icons/'; + my $icon_path = ""; + if(defined($group_icons{$group})){ + $icon_path = join('', $path, $group_icons{$group}, '.png'); + }elsif(defined($group_icons{$parent."\|".$group})){ + $icon_path = join('', $path, $group_icons{$parent."\|".$group}, '.png'); + }else{ + $icon_path = join('', $path, 'applications_section', '.png'); + } + unless(-e $icon_path){ + $icon_path = join('', $path, 'applications_section', '.png'); + } + return $icon_path; +} + +1; diff --git a/lib/ManaTools/Rpmdragora/init.pm b/lib/ManaTools/Rpmdragora/init.pm new file mode 100644 index 0000000..f6d570d --- /dev/null +++ b/lib/ManaTools/Rpmdragora/init.pm @@ -0,0 +1,181 @@ +# vim: set et ts=4 sw=4: +package ManaTools::Rpmdragora::init; +#***************************************************************************** +# +# Copyright (c) 2002 Guillaume Cottenceau +# Copyright (c) 2002-2007 Thierry Vignaud +# Copyright (c) 2003, 2004, 2005 MandrakeSoft SA +# Copyright (c) 2005-2007 Mandriva SA +# Copyright (c) 2013 - 2015 Matteo Pasotti +# 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. +# +#***************************************************************************** +# +# $Id: init.pm 263915 2009-12-03 17:41:04Z tv $ + +use strict; +use MDK::Common::Func 'any'; +use English; +BEGIN { $::no_global_argv_parsing = 1 } +require urpm::args; +use MDK::Common::Various qw(chomp_); + +use ManaTools::Privileges; +use ManaTools::Shared::Locales; + +use Exporter; +our @ISA = qw(Exporter); +our @EXPORT = qw(init + warn_about_user_mode + $MODE + $VERSION + $changelog_first + $default_list_mode + %rpmdragora_options + @ARGV_copy + ); + +our @ARGV_copy = @ARGV; + +BEGIN { #- we want to run this code before the Gtk->init of the use-my_gtk + my $loc = ManaTools::Shared::Locales->new(domain_name => 'rpmdrake'); + + my $basename = sub { local $_ = shift; s|/*\s*$||; s|.*/||; $_ }; + any { /^--?h/ } @ARGV and do { + printf join("\n", $loc->N("Usage: %s [OPTION]...", $basename->($0)), +$loc->N(" --auto assume default answers to questions"), +$loc->N(" --changelog-first display changelog before filelist in the description window"), +$loc->N(" --media=medium1,.. limit to given media"), +$loc->N(" --merge-all-rpmnew propose to merge all .rpmnew/.rpmsave files found"), +$loc->N(" --mode=MODE set mode (install (default), remove, update)"), +$loc->N(" --justdb update the database, but do not modify the filesystem"), +$loc->N(" --no-confirmation don't ask first confirmation question in update mode"), +$loc->N(" --no-media-update don't update media at startup"), +$loc->N(" --no-verify-rpm don't verify package signatures"), +if_($0 !~ /MageiaUpdate/, $loc->N(" --parallel=alias,host be in parallel mode, use \"alias\" group, use \"host\" machine to show needed deps")), +$loc->N(" --rpm-root=path use another root for rpm installation"), +$loc->N(" --urpmi-root use another root for urpmi db & rpm installation"), +$loc->N(" --run-as-root force to run as root"), +$loc->N(" --search=pkg run search for \"pkg\""), +$loc->N(" --test only verify if the installation can be achieved correctly"), +chomp_($loc->N(" --version print this tool's version number +")), +"" +); + exit 0; + }; +} + +BEGIN { #- for mcc + if ("@ARGV" =~ /--embedded (\w+)/) { + $::XID = $1; + $::isEmbedded = 1; + } +} + + +#- This is needed because text printed by Gtk2 will always be encoded +#- in UTF-8; we first check if LC_ALL is defined, because if it is, +#- changing only LC_COLLATE will have no effect. +use POSIX qw(setlocale LC_ALL LC_COLLATE strftime); +use locale; +my $collation_locale = $ENV{LC_ALL}; +if ($collation_locale) { + $collation_locale =~ /UTF-8/ or setlocale(LC_ALL, "$collation_locale.UTF-8"); +} else { + $collation_locale = setlocale(LC_COLLATE); + $collation_locale =~ /UTF-8/ or setlocale(LC_COLLATE, "$collation_locale.UTF-8"); +} + +our $VERSION = "1.0.0"; +our %rpmdragora_options; + +my $i; +foreach (@ARGV) { + $i++; + /^-?-(\S+)$/ or next; + my $val = $1; + if ($val =~ /=/) { + my ($name, $values) = split /=/, $val; + my @values = split /,/, $values; + $rpmdragora_options{$name} = \@values if @values; + } else { + if ($val eq 'version') { + print "$0 $VERSION\n"; + exit(0); + } elsif ($val =~ /^(test|expert)$/) { + eval "\$::$1 = 1"; + } elsif ($val =~ /^(q|quiet)$/) { + urpm::args::set_verbose(-1); + } elsif ($val =~ /^(v|verbose)$/) { + urpm::args::set_verbose(1); + } else { + $rpmdragora_options{$val} = 1; + } + } +} + +foreach my $option (qw(media mode parallel rpm-root search)) { + if (defined $rpmdragora_options{$option} && !ref($rpmdragora_options{$option})) { + warn qq(wrong usage of "$option" option!\n); + exit(-1); # too early for my_exit() + } +} + +$urpm::args::options{basename} = 1; + +our $MODE = ref $rpmdragora_options{mode} ? $rpmdragora_options{mode}[0] : undef; +our $overriding_config = defined $MODE; +unless ($MODE) { + $MODE = 'install'; + $0 =~ m|remove$| and $MODE = 'remove'; + $0 =~ m|update$|i and $MODE = 'update'; +} + +our $default_list_mode; +$default_list_mode = 'gui_pkgs' if $MODE eq 'install'; +if ($MODE eq 'remove') { + $default_list_mode = 'installed'; +} elsif ($MODE eq 'update') { + $default_list_mode = 'all_updates'; +} + +$MODE eq 'update' || $rpmdragora_options{'run-as-root'} and ManaTools::Privileges::is_root_capability_required(); +$::noborderWhenEmbedded = 1; + +require ManaTools::rpmdragora; + +our $changelog_first = $ManaTools::rpmdragora::changelog_first_config->[0]; +$changelog_first = 1 if $rpmdragora_options{'changelog-first'}; + +sub warn_about_user_mode() { + my $loc = ManaTools::Shared::Locales->new(domain_name => 'rpmdrake'); + my $title = $loc->N("Running in user mode"); + my $msg = $loc->N("You are launching this program as a normal user.\n". + "You will not be able to perform modifications on the system,\n". + "but you may still browse the existing database."); + + if(($EUID != 0) and (!ManaTools::rpmdragora::interactive_msg($title, $msg))) { + return 0; + } + return 1; +} + +sub init() { + URPM::bind_rpm_textdomain_codeset(); +} + +1; diff --git a/lib/ManaTools/Rpmdragora/open_db.pm b/lib/ManaTools/Rpmdragora/open_db.pm new file mode 100644 index 0000000..7bfa7bf --- /dev/null +++ b/lib/ManaTools/Rpmdragora/open_db.pm @@ -0,0 +1,171 @@ +# vim: set et ts=4 sw=4: +package ManaTools::Rpmdragora::open_db; +#***************************************************************************** +# +# Copyright (c) 2002 Guillaume Cottenceau +# Copyright (c) 2002-2014 Thierry Vignaud +# Copyright (c) 2003, 2004, 2005 MandrakeSoft SA +# Copyright (c) 2005-2007 Mandriva SA +# Copyright (c) 2012-2015 Matteo Pasotti +# 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. +# +#***************************************************************************** +# +# $Id: open_db.pm 268344 2010-05-06 13:06:08Z jvictor $ + +use strict; +use Sys::Syslog; + +use MDK::Common::File qw(cat_ mkdir_p); +use MDK::Common::Func; +use ManaTools::rpmdragora; +use URPM; +use urpm; +use urpm::args; +use urpm::select; +use urpm::media; +use urpm::mirrors; +use feature 'state'; + +use Exporter; +our @ISA = qw(Exporter); +our @EXPORT = qw(fast_open_urpmi_db + get_backport_media + get_inactive_backport_media + get_update_medias + is_it_a_devel_distro + open_rpm_db + open_urpmi_db + ); + +my $loc = ManaTools::rpmdragora::locale(); + + +# because rpm blocks some signals when rpm DB is opened, we don't keep open around: +sub open_rpm_db { + my ($o_force) = @_; + my $host; + Sys::Syslog::syslog('info|local1', "opening the RPM database"); + if ($::rpmdragora_options{parallel} && ((undef, $host) = @{$::rpmdragora_options{parallel}})) { + state $done; + my $dblocation = "/var/cache/urpmi/distantdb/$host"; + if (!$done || $o_force) { + print "syncing db from $host to $dblocation..."; + mkdir_p "$dblocation/var/lib/rpm"; + system "rsync -Sauz -e ssh $host:/var/lib/rpm/ $dblocation/var/lib/rpm"; + $? == 0 or die "Couldn't sync db from $host to $dblocation"; + $done = 1; + print "done.\n"; + } + URPM::DB::open($dblocation) or die "Couldn't open RPM DB"; + } else { + my $db; + if ($::env) { + #- URPM has same methods as URPM::DB and empty URPM will be seen as empty URPM::DB. + $db = new URPM; + $db->parse_synthesis("$::env/rpmdb.cz"); + } else { + $db = URPM::DB::open($::rpmdragora_options{'rpm-root'}[0]||''); + } + $db or die "Couldn't open RPM DB (" . ($::env ? "$::env/rpmdb.cz" : $::rpmdragora_options{'rpm-root'}[0]) . ")"; + } +} + +# do not pay the urpm::media::configure() heavy cost: +sub fast_open_urpmi_db() { + my $urpm = urpm->new; + my $error_happened; + $urpm->{fatal} = sub { + $error_happened = 1; + interactive_msg($loc->N("Fatal error"), + $loc->N("A fatal error occurred: %s.", $_[1])); + }; + + urpm::set_files($urpm, $::rpmdragora_options{'urpmi-root'}[0]) if $::rpmdragora_options{'urpmi-root'}[0]; + $::rpmdragora_options{'rpm-root'}[0] ||= $::rpmdragora_options{'urpmi-root'}[0]; + urpm::args::set_root($urpm, $::rpmdragora_options{'rpm-root'}[0]) if $::rpmdragora_options{'rpm-root'}[0]; + urpm::args::set_debug($urpm) if $::rpmdragora_options{debug}; + $urpm->get_global_options; + $urpm->{options}{wait_lock} = $::rpmdragora_options{'wait-lock'}; + $urpm->{options}{'verify-rpm'} = !$::rpmdragora_options{'no-verify-rpm'} if defined $::rpmdragora_options{'no-verify-rpm'}; + $urpm->{options}{auto} = $::rpmdragora_options{auto} if defined $::rpmdragora_options{auto}; + urpm::args::set_verbosity(); + if ($::rpmdragora_options{env} && $::rpmdragora_options{env}[0]) { + $::env = $::rpmdragora_options{env}[0]; + # prevent crashing in URPM.pm prevent when using --env: + $::env = "$ENV{PWD}/$::env" if $::env !~ m!^/!; + urpm::set_env($urpm, $::env); + } + + $urpm::args::options{justdb} = $::rpmdragora_options{justdb}; + + urpm::media::read_config($urpm, 0); + foreach (@{$urpm->{media}}) { + next if $_->{ignore}; + urpm::media::_tempignore($_, 1) if $ignore_debug_media->[0] && $_->{name} =~ /debug/i; + } + # FIXME: seems uneeded with newer urpmi: + if ($error_happened) { + touch('/etc/urpmi/urpmi.cfg'); + exec('edit-urpm-sources.pl'); + } + $urpm; +} + +sub is_it_a_devel_distro() { + state $res; + return $res if defined $res; + + my $path = '/etc/product.id'; + $path = $::rpmdragora_options{'urpmi-root'}[0] . $path if defined($::rpmdragora_options{'urpmi-root'}[0]); + $res = urpm::mirrors::parse_LDAP_namespace_structure(cat_($path))->{branch} eq 'Devel'; + return $res; +} + +sub get_backport_media { + my ($urpm) = @_; + grep { $_->{name} =~ /backport/i && + $_->{name} !~ /debug|sources|testing/i } @{$urpm->{media}}; +} + +sub get_inactive_backport_media { + my ($urpm) = @_; + map { $_->{name} } grep { $_->{ignore} } get_backport_media($urpm); +} + +sub get_update_medias { + my ($urpm) = @_; + if (is_it_a_devel_distro()) { + grep { !$_->{ignore} } @{$urpm->{media}}; + } else { + grep { !$_->{ignore} && $_->{update} } @{$urpm->{media}}; + } +} + +sub open_urpmi_db { + my (%urpmi_options) = @_; + my $urpm = fast_open_urpmi_db(); + my $media = ref $::rpmdragora_options{media} ? join(',', @{$::rpmdragora_options{media}}) : ''; + + my $searchmedia = $urpmi_options{update} ? undef : join(',', get_inactive_backport_media($urpm)); + $urpm->{lock} = urpm::lock::urpmi_db($urpm, undef, wait => $urpm->{options}{wait_lock}) if !$::env; + my $previous = $::rpmdragora_options{'previous-priority-upgrade'}; + urpm::select::set_priority_upgrade_option($urpm, (ref $previous ? join(',', @$previous) : ())); + urpm::media::configure($urpm, media => $media, MDK::Common::Func::if_($searchmedia, searchmedia => $searchmedia), %urpmi_options); + $urpm; +} + +1; diff --git a/lib/ManaTools/Rpmdragora/pkg.pm b/lib/ManaTools/Rpmdragora/pkg.pm new file mode 100644 index 0000000..ba0b18b --- /dev/null +++ b/lib/ManaTools/Rpmdragora/pkg.pm @@ -0,0 +1,1085 @@ +# vim: set et ts=4 sw=4: +package ManaTools::Rpmdragora::pkg; +#***************************************************************************** +# +# Copyright (c) 2002 Guillaume Cottenceau +# Copyright (c) 2002-2007 Thierry Vignaud +# Copyright (c) 2003, 2004, 2005 MandrakeSoft SA +# Copyright (c) 2005-2007 Mandriva SA +# Copyright (c) 2012-2015 Matteo Pasotti +# 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. +# +#***************************************************************************** +# +# $Id: pkg.pm 270160 2010-06-22 19:55:40Z jvictor $ + +use strict; +use Sys::Syslog; + +use MDK::Common::Func; #qw(before_leaving any); +use MDK::Common::DataStructure; # qw (uniq difference2 member add2hash put_in_hash); +use MDK::Common::System qw(arch); +use MDK::Common::File; # qw(cat_); +use MDK::Common::Various qw(chomp_); + +use POSIX qw(_exit ceil); +use URPM; +use utf8; +use ManaTools::rpmdragora; +use ManaTools::Rpmdragora::open_db; +use ManaTools::Rpmdragora::gurpm; +use ManaTools::Rpmdragora::formatting; +use ManaTools::Rpmdragora::rpmnew; +use ManaTools::Shared::RunProgram qw(run get_stdout); +use ManaTools::rpmdragora; +use urpm; +use urpm::lock; +use urpm::install; +use urpm::signature; +use urpm::get_pkgs; +use urpm::select; +use urpm::main_loop; +use urpm::args qw(); +use urpm::util; +use Carp; + +my $loc = ManaTools::rpmdragora::locale(); + +use Exporter; +our @ISA = qw(Exporter); +our @EXPORT = qw( + $priority_up_alread_warned + download_callback + extract_header + find_installed_version + get_pkgs + perform_installation + perform_removal + run_rpm + sort_packages + ); + +our $priority_up_alread_warned; + +sub sort_packages_biarch { + sort { + my ($na, $aa) = $a =~ /^(.*-[^-]+-[^-]+)\.([^.-]+)$/; + my ($nb, $ab) = $b =~ /^(.*-[^-]+-[^-]+)\.([^.-]+)$/; + !defined($na) ? + (!defined($nb) ? 0 : 1) : + (!defined($nb) ? -1 : $na cmp $nb || ($ab =~ /64$/) <=> ($aa =~ /64$/)); + } @_; +} + +sub sort_packages_monoarch { + sort { uc($a) cmp uc($b) } @_; +} + +*sort_packages = MDK::Common::System::arch() =~ /x86_64/ ? \&sort_packages_biarch : \&sort_packages_monoarch; + +sub run_rpm { + foreach (qw(LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT LC_IDENTIFICATION LC_ALL)) { + local $ENV{$_} = $ENV{$_} . '.UTF-8' if $ENV{$_} && $ENV{$_} !~ /UTF-8/; + } + my @l = map { ensure_utf8($_); $_ } ManaTools::Shared::RunProgram::get_stdout(@_); + wantarray() ? @l : join('', @l); +} + + +sub extract_header { + my ($pkg, $urpm, $xml_info, $o_installed_version) = @_; + my %fields = ( + info => 'description', + files => 'files', + changelog => 'changelog', + ); + # already extracted: + return if $pkg->{$fields{$xml_info}}; + + my $p = $pkg->{pkg}; + + if (!$p) { + warn ">> ghost package '$pkg' has no URPM object!!!\n"; + return; + } + + my $name = $p->fullname; + # fix extracting info for SRPMS and RPM GPG keys: + $name =~ s!\.src!!; + + if ($p->flag_installed && !$p->flag_upgrade) { + my @files = map { MDK::Common::Various::chomp_($_) } run_rpm("rpm -ql $name"); + MDK::Common::DataStructure::add2hash($pkg, { files => [ @files ? @files : $loc->N("(none)") ], + description => rpm_description(scalar(run_rpm("rpm -q --qf '%{description}' $name"))), + changelog => format_changelog_string($o_installed_version, scalar(run_rpm("rpm -q --changelog $name"))) }); + } else { + my $medium = pkg2medium($p, $urpm); + my ($local_source, %xml_info_pkgs, $bar_id); + my $_statusbar_clean_guard = MDK::Common::Func::before_leaving { $bar_id and statusbar_msg_remove($bar_id) }; + my $dir = urpm::file_from_local_url($medium->{url}); + + print "p->filename: ". $p->filename."\n"; + $local_source = "$dir/" . $p->filename if $dir; + print "local_source: " . ($local_source ? $local_source : "") . "\n"; + + if ($local_source && -e $local_source) { + $bar_id = statusbar_msg($loc->N("Getting information from %s...", $dir), 0); + $urpm->{log}("getting information from rpms from $dir"); + } else { + my $gurpm; + $bar_id = statusbar_msg($loc->N("Getting '%s' from XML meta-data...", $xml_info), 0); + my $_gurpm_clean_guard = MDK::Common::Func::before_leaving { undef $gurpm }; + if (my $xml_info_file = eval { urpm::media::any_xml_info($urpm, $medium, $xml_info, undef, sub { + $gurpm ||= ManaTools::Rpmdragora::gurpm->new( + text => $loc->N("Please wait"), + ); + download_callback($gurpm, @_) + or goto header_non_available; + }) }) { + require urpm::xml_info; + require urpm::xml_info_pkg; + $urpm->{log}("getting information from $xml_info_file"); + my %nodes = eval { urpm::xml_info::get_nodes($xml_info, $xml_info_file, [ $name ]) }; + goto header_non_available if $@; + MDK::Common::DataStructure::put_in_hash($xml_info_pkgs{$name} ||= {}, $nodes{$name}); + } else { + if ($xml_info eq 'info') { + $urpm->{info}($loc->N("No xml info for medium \"%s\", only partial result for package %s", $medium->{name}, $name)); + } else { + $urpm->{error}($loc->N("No xml info for medium \"%s\", unable to return any result for package %s", $medium->{name}, $name)); + } + } + } + + #- even if non-root, search for a header in the global cachedir + if ($local_source && -s $local_source) { + $p->update_header($local_source) or do { + warn "Warning, could not extract header for $name from $medium!"; + goto header_non_available; + }; + my @files = $p->files; + @files = $loc->N("(none)") if !@files; + MDK::Common::DataStructure::add2hash($pkg, { description => rpm_description($p->description), + files => \@files, + url => $p->url, + changelog => format_changelog_changelogs($o_installed_version, $p->changelogs) }); + $p->pack_header; # needed in order to call methods on objects outside ->traverse + } elsif ($xml_info_pkgs{$name}) { + if ($xml_info eq 'info') { + MDK::Common::DataStructure::add2hash($pkg, { description => rpm_description($xml_info_pkgs{$name}{description}), + url => $xml_info_pkgs{$name}{url} + }); + } elsif ($xml_info eq 'files') { + my @files = map { MDK::Common::Various::chomp_($loc->to_utf8($_)) } split("\n", $xml_info_pkgs{$name}{files}); + MDK::Common::DataStructure::add2hash($pkg, { files => scalar(@files) ? \@files : [ $loc->N("(none)") ] }); + } elsif ($xml_info eq 'changelog') { + MDK::Common::DataStructure::add2hash($pkg, { + changelog => format_changelog_changelogs($o_installed_version, + @{$xml_info_pkgs{$name}{changelogs}}) + }); + } + } else { + goto header_non_available; + } + return; + header_non_available: + MDK::Common::DataStructure::add2hash($pkg, { summary => $p->summary || $loc->N("(Not available)"), description => undef }); + } +} + +sub find_installed_version { + my ($p) = @_; + + my $version = $loc->N("(none)"); + open_rpm_db()->traverse_tag_find('name', $p->name, sub { $version = $_[0]->EVR; return ($version ? 1 : 0) }) if $p; + return $version; +} + +my $canceled; +sub download_callback { + my ($gurpm, $mode, $file, $percent, $total, $eta, $speed) = @_; + $canceled = 0; + + if ($mode eq 'start') { + $gurpm->label($loc->N("Downloading package `%s'...", urpm::util::basename($file))); +# $gurpm->validate_cancel(but($loc->N("Cancel")), sub { $canceled = 1 }); + } elsif ($mode eq 'progress') { + $gurpm->label( + join("\n", + $loc->N("Downloading package `%s'...", urpm::util::basename($file)), + (defined $total && defined $eta ? + $loc->N(" %s%% of %s completed, ETA = %s, speed = %s", $percent, $total, $eta, $speed) + : $loc->N(" %s%% completed, speed = %s", $percent, $speed) + ) =~ /^\s*(.*)/ + ), + ); + #$gurpm->progress($percenti/100); + $gurpm->progress(ceil($percent)); + } elsif ($mode eq 'end') { + $gurpm->progress(100); +# $gurpm->invalidate_cancel; + } + !$canceled; +} + + +# -=-=-=---=-=-=---=-=-=-- install packages -=-=-=---=-=-=---=-=-=- + +my (@update_medias, $is_update_media_already_asked); + +sub warn_about_media { + my ($w, %options) = @_; + + return 0 if $::MODE ne 'update'; + return 0 if $::rpmdragora_options{'no-media-update'}; + + # we use our own instance of the urpmi db in order not to mess up with skip-list managment (#31092): + # and no need to fully configure urpmi since we may have to do it again anyway because of new media: + my $urpm = fast_open_urpmi_db(); + + my $_lock = urpm::lock::urpmi_db($urpm, undef, wait => $urpm->{options}{wait_lock}); + + # build media list: + @update_medias = get_update_medias($urpm); + + # do not update again media after installing/removing some packages: + $::rpmdragora_options{'no-media-update'} ||= 1; + + if (@update_medias > 0) { + if (!$options{skip_updating_mu} && !$is_update_media_already_asked) { + $is_update_media_already_asked = 1; + if (!$::rpmdragora_options{'no-confirmation'}) { + my $choice = interactive_msg($loc->N("Confirmation"), + $loc->N("I need to contact the mirror to get latest update packages. +Please check that your network is currently running. + +Is it ok to continue?" + ), yesno => 1, dont_ask_again => 1, +# TODO widget => gtknew('CheckButton', text => $loc->N("Do not ask me next time"), +# active_ref => \$::rpmdragora_options{'no-confirmation'} +# ) + ); + $::rpmdragora_options{'no-confirmation'} = $choice->{dont_ask_again}; + return(-1) if !$choice->{value}; + } + writeconf(); + urpm::media::select_media($urpm, map { $_->{name} } @update_medias); + update_sources($urpm, noclean => 1, medialist => [ map { $_->{name} } @update_medias ]); + } + } else { + if (MDK::Common::Func::any { $_->{update} } @{$urpm->{media}}) { + interactive_msg($loc->N("Already existing update media"), +$loc->N("You already have at least one update medium configured, but +all of them are currently disabled. You should run the Software +Media Manager to enable at least one (check it in the \"%s\" +column). + +Then, restart \"%s\".", $loc->N("Enabled"), $ManaTools::rpmdragora::myname_update)); + return (-1); + } + my ($mirror) = choose_mirror($urpm, transient => $w->{real_window} || $::main_window, + message => join("\n\n", + $loc->N("You have no configured update media. MageiaUpdate cannot operate without any update media."), + $loc->N("I need to contact the Mageia website to get the mirror list. +Please check that your network is currently running. + +Is it ok to continue?"), + ), + ); + my $m = ref($mirror) ? $mirror->{url} : ''; + $m or interactive_msg($loc->N("How to choose manually your mirror"), +$loc->N("You may also choose your desired mirror manually: to do so, +launch the Software Media Manager, and then add a `Security +updates' medium. + +Then, restart %s.", $ManaTools::rpmdragora::myname_update)), return (-1); + add_distrib_update_media($urpm, $mirror, only_updates => 0); + } + return 0; +} + + +sub get_parallel_group() { + $::rpmdragora_options{parallel} ? $::rpmdragora_options{parallel}[0] : undef; +} + +my ($count, $level, $limit, $new_stage, $prev_stage, $total); + +sub init_progress_bar { + my ($urpm) = @_; + undef $_ foreach $count, $prev_stage, $new_stage, $limit; + $level = 5; + $total = @{$urpm->{depslist}}; +} + +sub reset_pbar_count { + undef $prev_stage; + $count = 0; + $limit = $_[0]; +} + +sub update_pbar { + my ($gurpm) = @_; + return if !$total; # don't die if there's no source + $count++; + $new_stage = $level+($limit-$level)*$count/$total; + $prev_stage = 0 if(!defined($prev_stage)); + if ($prev_stage + 1 < $new_stage) { + $prev_stage = $new_stage; + $gurpm->progress(ceil($new_stage)); + } +} + + +sub get_installed_packages { + my ($urpm, $db, $all_pkgs, $gurpm) = @_; + + $urpm->{global_config}{'prohibit-remove'} = '' if(!defined($urpm->{global_config}{'prohibit-remove'})); + my @base = ("basesystem", split /,\s*/, $urpm->{global_config}{'prohibit-remove'}); + my (%base, %basepackages, @installed_pkgs, @processed_base); + reset_pbar_count(33); + while (defined(local $_ = shift @base)) { + exists $basepackages{$_} and next; + $db->traverse_tag(m|^/| ? 'path' : 'whatprovides', [ $_ ], sub { + update_pbar($gurpm); + my $name = $_[0]->fullname; + # workaround looping in URPM: + return if MDK::Common::DataStructure::member($name, @processed_base); + push @processed_base, $name; + push @{$basepackages{$_}}, $name; + push @base, $_[0]->requires_nosense; + }); + } + foreach (values %basepackages) { + my $n = @$_; #- count number of times it's provided + foreach (@$_) { + $base{$_} = \$n; + } + } + # costly: + $db->traverse(sub { + my ($pkg) = @_; + update_pbar($gurpm); + my $fullname = urpm_name($pkg); + return if $fullname =~ /@/; + $all_pkgs->{$fullname} = { + pkg => $pkg, urpm_name => $fullname, + } if !($all_pkgs->{$fullname} && $all_pkgs->{$fullname}{description}); + if (my $name = $base{$fullname}) { + $all_pkgs->{$fullname}{base} = \$name; + $pkg->set_flag_base(1) if $$name == 1; + } + push @installed_pkgs, $fullname; + $pkg->set_flag_installed; + $pkg->pack_header; # needed in order to call methods on objects outside ->traverse + }); + @installed_pkgs; +} + +urpm::select::add_packages_to_priority_upgrade_list('rpmdragora', 'perl-Glib', 'perl-Gtk2'); + +my ($priority_state, $priority_requested); +our $need_restart; + +our $probe_only_for_updates; + +sub get_updates_list { + my ($urpm, $db, $state, $requested, $requested_list, $requested_strict, $all_pkgs, %limit_preselect) = @_; + + $urpm->request_packages_to_upgrade( + $db, + $state, + $requested, + %limit_preselect + ); + + my %common_opts = ( + callback_choices => \&ManaTools::Rpmdragora::gui::callback_choices, + priority_upgrade => $urpm->{options}{'priority-upgrade'}, + ); + + if ($urpm->{options}{'priority-upgrade'}) { + $need_restart = + urpm::select::resolve_priority_upgrades_after_auto_select($urpm, $db, $state, + $requested, %common_opts); + } + + # list of updates (including those matching /etc/urpmi/skip.list): + @$requested_list = sort map { + my $name = urpm_name($_); + $all_pkgs->{$name} = { pkg => $_ }; + $name; + } @{$urpm->{depslist}}[keys %$requested]; + + # list of pure updates (w/o those matching /etc/urpmi/skip.list but with their deps): + if ($probe_only_for_updates && !$need_restart) { + @$requested_strict = sort map { + urpm_name($_); + } $urpm->resolve_requested($db, $state, $requested, callback_choices => \&ManaTools::Rpmdragora::gui::callback_choices); + + if (my @l = grep { $state->{selected}{$_->id} } + urpm::select::_priority_upgrade_pkgs($urpm, $urpm->{options}{'priority-upgrade'})) { + if (!$need_restart) { + $need_restart = + urpm::select::_resolve_priority_upgrades($urpm, $db, $state, $state->{selected}, + \@l, %common_opts); + } + } + } + + if ($need_restart) { + $requested_strict = [ map { scalar $_->fullname } @{$urpm->{depslist}}[keys %{$state->{selected}}] ]; + # drop non priority updates: + @$requested_list = (); + } + + # list updates including skiped ones + their deps in MageiaUpdate: + @$requested_list = MDK::Common::DataStructure::uniq(@$requested_list, @$requested_strict); + + # do not pre select updates in rpmdragora: + @$requested_strict = () if !$probe_only_for_updates; +} + +sub get_pkgs { + my (%options) = @_; + my $w = $::main_window; + + myexit (-1) if (warn_about_media($w, %options) == -1); + + my $gurpm = ManaTools::Rpmdragora::gurpm->new( + text => $loc->N("Please wait"), + ); + my $_gurpm_clean_guard = MDK::Common::Func::before_leaving { undef $gurpm }; + + my $urpm = open_urpmi_db(update => $probe_only_for_updates && !is_it_a_devel_distro()); + + my $_drop_lock = MDK::Common::Func::before_leaving { undef $urpm->{lock} }; + + $priority_up_alread_warned = 0; + + # update media list in case warn_about_media() added some: + @update_medias = get_update_medias($urpm); + + $gurpm->label($loc->N("Reading updates description")); + #- parse the description file + my $update_descr = urpm::get_updates_description($urpm, @update_medias); + $gurpm->progress(100); + + my $_unused = $loc->N("Please wait, finding available packages..."); + +# # find out installed packages: + + init_progress_bar($urpm); + + $gurpm->label($loc->N("Please wait, listing base packages...")); + $gurpm->progress(ceil($level)); + + my $db = eval { open_rpm_db() }; + if (my $err = $@) { + interactive_msg($loc->N("Error"), $loc->N("A fatal error occurred: %s.", $err)); + return; + } + + my $sig_handler = sub { undef $db; exit 3 }; + local $SIG{INT} = $sig_handler; + local $SIG{QUIT} = $sig_handler; + + $gurpm->label($loc->N("Please wait, finding installed packages...")); + $level = 33; + $gurpm->progress(ceil($level)); + reset_pbar_count(66); + my (@installed_pkgs, %all_pkgs); + if (!$probe_only_for_updates) { + @installed_pkgs = get_installed_packages($urpm, $db, \%all_pkgs, $gurpm); + } + + if (my $group = get_parallel_group()) { + urpm::media::configure($urpm, parallel => $group); + } + + # find out availlable packages: + + $urpm->{state} = {}; + + $gurpm->label($loc->N("Please wait, finding available packages...")); + $level = 66; + $gurpm->progress(ceil($level)); + + check_update_media_version($urpm, @update_medias); + + my $requested = {}; + my $state = {}; + my (@requested, @requested_strict); + + if ($compute_updates->[0] || $::MODE eq 'update') { + my %filter; + if ($options{pure_updates}) { + # limit to packages from update-media (dependencies can still come from other media) + %filter = (idlist => [ map { $_->{start} .. $_->{end} } @update_medias ]); + } + get_updates_list($urpm, $db, $state, $requested, \@requested, \@requested_strict, \%all_pkgs, %filter); + } + + if ($need_restart) { + $priority_state = $state; + $priority_requested = $requested; + } else { + ($priority_state, $priority_requested) = (); + } + + if (!$probe_only_for_updates) { + $urpm->compute_installed_flags($db); # TODO/FIXME: not for updates + $urpm->{depslist}[$_]->set_flag_installed foreach keys %$requested; #- pretend it's installed + } + $urpm->{rpmdragora_state} = $state; #- Don't forget it + $level = 70; + $gurpm->progress(ceil($level)); + + my %l; + reset_pbar_count(100); + foreach my $pkg (@{$urpm->{depslist}}) { + update_pbar($gurpm); + $pkg->flag_upgrade or next; + my $key = $pkg->name . $pkg->arch; + $l{$key} = $pkg if !$l{$key} || $l{$key}->compare_pkg($pkg); + } + my @installable_pkgs = map { my $n = $_->fullname; $all_pkgs{$n} = { pkg => $_ }; $n } values %l; + undef %l; + + my @inactive_backports; + my @active_backports; + my @backport_medias = get_backport_media($urpm); + + foreach my $medium (@backport_medias) { + update_pbar($gurpm); + + # The 'searchmedia' flag differentiates inactive backport medias + # (because that option was passed to urpm::media::configure to + # temporarily enable them) + + my $backports = + $medium->{searchmedia} ? \@inactive_backports : \@active_backports; + if (defined($medium->{start}) || defined($medium->{end})) { + foreach my $pkg_id ($medium->{start} .. $medium->{end}) { + next if !$pkg_id; + my $pkg = $urpm->{depslist}[$pkg_id]; + $pkg->flag_upgrade or next; + my $name = $pkg->fullname; + push @$backports, $name; + $all_pkgs{$name} = { pkg => $pkg, is_backport => 1 }; + } + } + } + my @updates = @requested; + # selecting updates by default but skipped ones (MageiaUpdate only): + foreach (@requested_strict) { + $all_pkgs{$_}{selected} = 1; + } + + # urpmi only care about the first medium where it found the package, + # so there's no need to list the same package several time: + @installable_pkgs = MDK::Common::DataStructure::uniq(MDK::Common::DataStructure::difference2(\@installable_pkgs, \@updates)); + + my @meta_pkgs = grep { /^task-|^basesystem/ } keys %all_pkgs; + + my @gui_pkgs = map { chomp; $_ } MDK::Common::File::cat_('/usr/share/rpmdrake/gui.lst'); + # add meta packages to GUI packages list (which expect basic names not fullnames): + push @gui_pkgs, map { (split_fullname($_))[0] } @meta_pkgs; + + +{ urpm => $urpm, + all_pkgs => \%all_pkgs, + installed => \@installed_pkgs, + installable => \@installable_pkgs, + updates => \@updates, + meta_pkgs => \@meta_pkgs, + gui_pkgs => [ grep { my $p = $all_pkgs{$_}{pkg}; $p && MDK::Common::DataStructure::member(($p->fullname)[0], @gui_pkgs) } keys %all_pkgs ], + update_descr => $update_descr, + backports => [ @inactive_backports, @active_backports ], + inactive_backports => \@inactive_backports + }; +} + +sub _display_READMEs_if_needed { + my $urpm = shift; + return if !$urpm->{readmes}; + + my %Readmes = %{$urpm->{readmes}}; + return if ! scalar keys %Readmes; + + my $appTitle = yui::YUI::app()->applicationTitle(); + + ## set new title to get it in dialog + yui::YUI::app()->setApplicationTitle($loc->N("Upgrade information")); + my $factory = yui::YUI::widgetFactory; + + ## | [msg-label] | + ## | | + ## | pkg-list | + ## | | + ## | info on selected pkg |(1) + ## | | + ## | [ok] | + #### + # (1) info on pkg list: + # selected package readmi.urpmi + + my $dialog = $factory->createPopupDialog; + my $vbox = $factory->createVBox( $dialog ); + my $msgBox = $factory->createLabel($vbox, $loc->N("These packages come with upgrade information"), 1); + my $tree = $factory->createTree($vbox, $loc->N("Select a package")); + $factory->createVSpacing($vbox, 1); + my $infoBox = $factory->createRichText($vbox, "", 0); + $tree->setWeight($yui::YD_HORIZ, 2); + $infoBox->setWeight($yui::YD_HORIZ, 4); + $tree->setWeight($yui::YD_VERT, 10); + $infoBox->setWeight($yui::YD_VERT, 10); + $factory->createVSpacing($vbox, 1); + my $hbox = $factory->createHBox( $vbox ); + my $align = $factory->createHCenter($hbox); + my $okButton = $factory->createPushButton($align, $loc->N("&Ok")); + $okButton->setDefaultButton(1); + + # adding packages to the list + my $itemColl = new yui::YItemCollection; + foreach my $f (sort keys %Readmes) { + my $item = new yui::YTreeItem ("$Readmes{$f}"); + my $child = new yui::YTreeItem ($item, "$f"); + $child->DISOWN(); + $itemColl->push($item); + $item->DISOWN(); + } + $tree->addItems($itemColl); + $tree->setImmediateMode(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 + my $widget = $event->widget(); + if ($widget == $tree) { + my $content = ""; + my $item = $tree->selectedItem(); + if ($item && !$item->hasChildren()) { + my $filename = $tree->currentItem()->label(); + $content = scalar MDK::Common::File::cat_($filename); + $content = $loc->N("(none)") if !$content; # should not happen + ensure_utf8($content); + $content =~ s/\n/
/g; + } + $infoBox->setValue($content); + } + elsif ($widget == $okButton) { + last; + } + } + } + + destroy $dialog; + + # restore original title + yui::YUI::app()->setApplicationTitle($appTitle) if $appTitle; + + return; +} + +sub perform_parallel_install { + my ($urpm, $group, $w, $statusbar_msg_id) = @_; + my @pkgs = map { MDK::Common::Func::if_($_->flag_requested, urpm_name($_)) } @{$urpm->{depslist}}; + + my @error_msgs; + my $res = !ManaTools::Shared::RunProgram::run('urpmi', '2>', \@error_msgs, '-v', '--X', '--parallel', $group, @pkgs); + + if ($res) { + $$statusbar_msg_id = statusbar_msg( + #$loc->N("Everything installed successfully"), + $loc->N("All requested packages were installed successfully."), + ); + } else { + interactive_msg( + $loc->N("Problem during installation"), + $loc->N("There was a problem during the installation:\n\n%s", join("\n", @error_msgs)), + scroll => 1, + ); + } + open_rpm_db('force_sync'); + $w->set_sensitive(1); + return 0; +} + +sub perform_installation { #- (partially) duplicated from /usr/sbin/urpmi :-( + my ($urpm, $pkgs) = @_; + + my @error_msgs; + my $statusbar_msg_id; + my $gurpm; + local $urpm->{fatal} = sub { + my $fatal_msg = $_[1]; + printf STDERR "Fatal: %s\n", $fatal_msg; + undef $gurpm; + interactive_msg($loc->N("Installation failed"), + $loc->N("There was a problem during the installation:\n\n%s", $fatal_msg)); + goto return_with_exit_code; + }; + local $urpm->{error} = sub { printf STDERR "Error: %s\n", $_[0]; push @error_msgs, $_[0] }; + + my $w = $::main_window; + #$w->set_sensitive(0); + #my $_restore_sensitive = MDK::Common::Func::before_leaving { $w->set_sensitive(1) }; + + # my $_flush_guard = Gtk2::GUI_Update_Guard->new; + + if (my $group = get_parallel_group()) { + return perform_parallel_install($urpm, $group, $w, \$statusbar_msg_id); + } + + my ($lock, $rpm_lock); + if (!$::env) { + $lock = urpm::lock::urpmi_db($urpm, undef, wait => $urpm->{options}{wait_lock}); + $rpm_lock = urpm::lock::rpm_db($urpm, 'exclusive'); + } + my $state = $priority_state || $probe_only_for_updates ? { } : $urpm->{rpmdragora_state}; + + my $bar_id = statusbar_msg($loc->N("Checking validity of requested packages..."), 0); + + # FIXME: THIS SET flag_requested on all packages!!!! + # select packages to install / enssure selected pkg set is consistant: + my %saved_flags; + my $requested = { map { + $saved_flags{$_->id} = $_->flag_requested; + $_->id => undef; + } grep { $_->flag_selected } @{$urpm->{depslist}} }; + urpm::select::resolve_dependencies( + $urpm, $state, $requested, + rpmdb => $::env && "$::env/rpmdb.cz", + callback_choices => \&ManaTools::Rpmdragora::gui::callback_choices, + ); + statusbar_msg_remove($bar_id); + + my ($local_sources, $blist) = urpm::get_pkgs::selected2local_and_blists($urpm, $state->{selected}); + if (!$local_sources && (!$blist || !@$blist)) { + interactive_msg( + $loc->N("Unable to get source packages."), + $loc->N("Unable to get source packages, sorry. %s", + @error_msgs ? $loc->N("\n\nError(s) reported:\n%s", join("\n", @error_msgs)) : ''), + scroll => 1, + ); + goto return_with_exit_code; + } + + my @to_install = @{$urpm->{depslist}}[keys %{$state->{selected}}]; + my @pkgs = map { scalar($_->fullname) } sort(grep { $_->flag_selected } @to_install); + + @{$urpm->{ask_remove}} = sort(urpm::select::removed_packages($urpm->{state})); + my @to_remove = map { MDK::Common::Func::if_($pkgs->{$_}{selected} && !$pkgs->{$_}{pkg}->flag_upgrade, $pkgs->{$_}{urpm_name}) } keys %$pkgs; + + my $r = format_list(map { scalar(urpm::select::translate_why_removed_one($urpm, $urpm->{state}, $_)) } @to_remove); + + my ($size, $filesize) = $urpm->selected_size_filesize($state); + my $install_count = int(@pkgs); + my $to_install = $install_count == 0 ? '' : + ($priority_state ? '' . $loc->N("Rpmdragora or one of its priority dependencies needs to be updated first. Rpmdragora will then restart.") . '' . "\n\n" : '') . + ($loc->P("The following package is going to be installed:", "The following %d packages are going to be installed:", $install_count, $install_count) + . "\n\n" . format_list(map { s!.*/!!; $_ } @pkgs)); + my $remove_count = scalar(@to_remove); + interactive_msg(($to_install ? $loc->N("Confirmation") : $loc->N("Some packages need to be removed")), + join("\n\n", + ($r ? + (!$to_install ? ($loc->P("Remove one package?", "Remove %d packages?", $remove_count, $remove_count), $r) : + (($remove_count == 1 ? + $loc->N("The following package has to be removed for others to be upgraded:") + : $loc->N("The following packages have to be removed for others to be upgraded:")), $r), MDK::Common::Func::if_($to_install, $to_install)) + : $to_install), + format_size($size), + format_filesize($filesize), + $loc->N("Is it ok to continue?")), + scroll => 1, + yesno => 1, min_size => {lines => 18},) or return 1; + + my $_umount_guard = MDK::Common::Func::before_leaving { urpm::removable::try_umounting_removables($urpm) }; + + # select packages to uninstall for !update mode: + perform_removal($urpm, { map { $_ => $pkgs->{$_} } @to_remove }) if !$probe_only_for_updates; + + $gurpm = ManaTools::Rpmdragora::gurpm->new( + text => $loc->N("Please wait"), + title => $loc->N("Initializing..."), + ); + # my $_gurpm_clean_guard = MDK::Common::Func::before_leaving { undef $gurpm }; + my $something_installed; + + if (@to_install && $::rpmdragora_options{auto_orphans}) { + urpm::orphans::compute_future_unrequested_orphans($urpm, $state); + if (my @orphans = map { scalar $_->fullname } @{$state->{orphans_to_remove}}) { + interactive_msg($loc->N("Orphan packages"), $loc->P("The following orphan package will be removed.", + "The following orphan packages will be removed.", scalar(@orphans)) + . "\n" . urpm::orphans::add_leading_spaces(join("\n", @orphans) . "\n"), scroll => 1); + } + } + + urpm::orphans::mark_as_requested($urpm, $state, 0); + + my ($progress, $total, @rpms_upgrade); + my $transaction; + my ($progress_nb, $transaction_progress_nb, $remaining, $done); + my $callback_inst = sub { + my ($urpm, $type, $id, $subtype, $amount, $total) = @_; + my $pkg = defined $id ? $urpm->{depslist}[$id] : undef; + if ($subtype eq 'start') { + if ($type eq 'trans') { + print(1 ? $loc->N("Preparing package installation...") : $loc->N("Preparing package installation transaction...")); + $gurpm->label($loc->N("Preparing package installation...")); + } elsif (defined $pkg) { + $something_installed = 1; + print($loc->N("Installing package `%s' (%s/%s)...", $pkg->name, $transaction_progress_nb, scalar(@{$transaction->{upgrade}}))."\n" . $loc->N("Total: %s/%s", $progress_nb, $install_count)); + $gurpm->label($loc->N("Installing package `%s' (%s/%s)...", $pkg->name, ++$transaction_progress_nb, scalar(@{$transaction->{upgrade}})) + . "\n" . $loc->N("Total: %s/%s", ++$progress_nb, $install_count)); + } + } elsif ($subtype eq 'progress') { + $gurpm->progress($total ? ceil(($amount/$total)*100) : 100); + # print("Progress: ".($total ? ($amount/$total)*100 : 100)."\n"); + } + }; + + # FIXME: sometimes state is lost: + my @ask_unselect = urpm::select::unselected_packages($state); + + # fix flags for orphan computing: + foreach (keys %{$state->{selected}}) { + my $pkg = $urpm->{depslist}[$_]; + $pkg->set_flag_requested($saved_flags{$pkg->id}); + } + my $exit_code = + urpm::main_loop::run($urpm, $state, 1, \@ask_unselect, + { + completed => sub { + # explicitly destroy the progress window when it's over; we may + # have sg to display before returning (errors, rpmnew/rpmsave, ...): + undef $gurpm; + + undef $lock; + undef $rpm_lock; + }, + inst => $callback_inst, + trans => $callback_inst, + ask_yes_or_no => sub { + # handle 'allow-force' and 'allow-nodeps' options: + my ($title, $msg) = @_; + local $::main_window = $gurpm->{real_window}; + interactive_msg($title, $msg, yesno => 1, scroll => 1, + ); + }, + message => sub { + my ($title, $message) = @_; + interactive_msg($title, $message, scroll => 1); + }, + # cancel installation when 'cancel' button is pressed: + trans_log => sub { download_callback($gurpm, @_) or goto return_with_exit_code }, + post_extract => sub { + my ($set, $transaction_sources, $transaction_sources_install) = @_; + $transaction = $set; + $transaction_progress_nb = 0; + $done += grep { !/\.src\.rpm$/ } values %$transaction_sources; #updates + $total = keys(%$transaction_sources_install) + keys %$transaction_sources; + push @rpms_upgrade, keys %$transaction_sources; + $done += grep { !/\.src\.rpm$/ } values %$transaction_sources_install; # installs + }, + pre_removable => sub { + # Gtk2::GUI_Update_Guard->new use of alarm() kill us when + # running system(), thus making DVD being ejected and printing + # wrong error messages (#30463) + + local $SIG{ALRM} = sub { die "ALARM" }; + $remaining = alarm(0); + }, + + post_removable => sub { alarm $remaining }, + copy_removable => sub { + my ($medium) = @_; + interactive_msg( + $loc->N("Change medium"), + $loc->N("Please insert the medium named \"%s\"", $medium), + yesno => 1, text => { no => $loc->N("Cancel"), yes => $loc->N("Ok") }, + ); + }, + pre_check_sig => sub { $gurpm->label($loc->N("Verifying package signatures...")) }, + check_sig => sub { $gurpm->progress(ceil(++$progress/$total)*100) }, + bad_signature => sub { + my ($msg, $msg2) = @_; + local $::main_window = $gurpm->{real_window}; + $msg =~ s/:$/\n\n/m; # FIXME: to be fixed in urpmi after 2008.0 + interactive_msg( + $loc->N("Warning"), "$msg\n\n$msg2", yesno => 1, MDK::Common::Func::if_(10 < ($msg =~ tr/\n/\n/), scroll => 1), + ); + }, + post_download => sub { + $canceled and goto return_with_exit_code; +# $gurpm->invalidate_cancel_forever; + }, + need_restart => sub { + my ($need_restart_formatted) = @_; + # FIXME: offer to restart the system + interactive_msg($loc->N("Warning"), join("\n", values %$need_restart_formatted), scroll => 1); + }, + trans_error_summary => sub { + my ($nok, $errors) = @_; + interactive_msg( + $loc->N("Problem during installation"), + MDK::Common::Func::if_($nok, $loc->N("%d installation transactions failed", $nok) . "\n\n") . + $loc->N("There was a problem during the installation:\n\n%s", + join("\n\n", @$errors, @error_msgs)), + scroll => 1, + ); + }, + need_restart => sub { + my ($need_restart_formatted) = @_; + interactive_msg($loc->N("Warning"), + join("\n\n", values %$need_restart_formatted)); + }, + success_summary => sub { + if (!($done || @to_remove)) { + interactive_msg($loc->N("Error"), + $loc->N("Unrecoverable error: no package found for installation, sorry.")); + return; + } + my $id = statusbar_msg($loc->N("Inspecting configuration files..."), 0); + my %pkg2rpmnew; + foreach my $id (@rpms_upgrade) { + my $pkg = $urpm->{depslist}[$id]; + next if $pkg->arch eq 'src'; + $pkg2rpmnew{$pkg->fullname} = [ grep { -r "$_.rpmnew" || -r "$_.rpmsave" } $pkg->conf_files ]; + } + statusbar_msg_remove($id); + rpmnew_dialog($loc->N("The installation is finished; everything was installed correctly. + +Some configuration files were created as `.rpmnew' or `.rpmsave', +you may now inspect some in order to take actions:"), + %pkg2rpmnew) + and statusbar_msg($loc->N("All requested packages were installed successfully."), 1); + statusbar_msg($loc->N("Looking for \"README\" files..."), 1); + _display_READMEs_if_needed($urpm); + }, + already_installed_or_not_installable => sub { + my ($msg1, $msg2) = @_; + my $msg = join("\n", @$msg1, @$msg2); + return if !$msg; # workaround missing state + interactive_msg($loc->N("Error"), $msg); + }, + }, + ); + + #- restart rpmdragora if needed, keep command line for that. + if ($need_restart && !$exit_code && $something_installed) { + Sys::Syslog::syslog('info|local1', "restarting rpmdragora"); + #- it seems to work correctly with exec instead of system, provided we stop timers + #- added --previous-priority-upgrade to allow checking if yet if + #- priority-upgrade list has changed. and make sure we don't uselessly restart + my @argv = ('--previous-priority-upgrade=' . $urpm->{options}{'priority-upgrade'}, + grep { !/^--no-priority-upgrade$|--previous-priority-upgrade=/ } @ManaTools::Rpmdragora::init::ARGV_copy); + # remove "--emmbedded " from argv: + my $i = 0; + foreach (@argv) { + splice @argv, $i, 2 if /^--embedded$/; + $i++; + } + alarm(0); + # reMDK::Common::DataStructure::member not to ask again questions and the like: + writeconf(); + exec($0, @argv); + exit(0); + } + + my $_s1 = $loc->N("RPM transaction %d/%d", 0, 0); + my $_s2 = $loc->N("Unselect all"); + my $_s3 = $loc->N("Details"); + + statusbar_msg_remove($statusbar_msg_id); #- XXX maybe remove this + + if ($exit_code == 0 && !$::rpmdragora_options{auto_orphans}) { + if (urpm::orphans::check_unrequested_orphans_after_auto_select($urpm)) { + if (my $msg = urpm::orphans::get_now_orphans_gui_msg($urpm)) { + interactive_msg($loc->N("Orphan packages"), $msg, scroll => 1); + } + } + } + + return_with_exit_code: + return !($something_installed || scalar(@to_remove)); +} + + +# -=-=-=---=-=-=---=-=-=-- remove packages -=-=-=---=-=-=---=-=-=- + +sub perform_removal { + my ($urpm, $pkgs) = @_; + my @toremove = map { MDK::Common::Func::if_($pkgs->{$_}{selected}, $pkgs->{$_}{urpm_name}) } keys %$pkgs; + return if !@toremove; + my $gurpm = ManaTools::Rpmdragora::gurpm->new( + text => $loc->N("Please wait") + ); + my $_gurpm_clean_guard = MDK::Common::Func::before_leaving { undef $gurpm }; + + my $may_be_orphans = 1; + urpm::orphans::unrequested_orphans_after_remove($urpm, \@toremove) + or $may_be_orphans = 0; + + my $progress = -1; + local $urpm->{log} = sub { + my $str = $_[0]; + print $str; + $progress++; + return if $progress <= 0; # skip first "creating transaction..." message + $gurpm->label($str); # display "removing package %s" + $gurpm->progress(ceil(min(99, scalar($progress/@toremove)*100))); + #gtkflush(); + }; + + my @results; + slow_func_statusbar( + $loc->N("Please wait, removing packages..."), + $::main_window, + sub { + @results = $::rpmdragora_options{parallel} + ? urpm::parallel::remove($urpm, \@toremove) + : urpm::install::install($urpm, \@toremove, {}, {}, + callback_report_uninst => sub { $gurpm->label($_[0]) }, + ); + open_rpm_db('force_sync'); + }, + ); + if (@results) { + interactive_msg( + $loc->N("Problem during removal"), + $loc->N("There was a problem during the removal of packages:\n\n%s", join("\n", @results)), + MDK::Common::Func::if_(@results > 1, scroll => 1), + ); + return 1; + } else { + if ($may_be_orphans && !$::rpmdragora_options{auto_orphans}) { + if (my $msg = urpm::orphans::get_now_orphans_gui_msg($urpm)) { + interactive_msg($loc->N("Information"), $msg, scroll => 1); + } + } + return 0; + } +} + +1; diff --git a/lib/ManaTools/Rpmdragora/rpmnew.pm b/lib/ManaTools/Rpmdragora/rpmnew.pm new file mode 100644 index 0000000..659c0b2 --- /dev/null +++ b/lib/ManaTools/Rpmdragora/rpmnew.pm @@ -0,0 +1,363 @@ +# vim: set et ts=4 sw=4: +package ManaTools::Rpmdragora::rpmnew; +#***************************************************************************** +# +# Copyright (c) 2002 Guillaume Cottenceau +# Copyright (c) 2002-2007 Thierry Vignaud +# Copyright (c) 2003, 2004, 2005 MandrakeSoft SA +# Copyright (c) 2005-2007 Mandriva SA +# Copyright (c) 2013 - 2015 Matteo Pasotti +# 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. +# +#***************************************************************************** +# +# $Id: rpmnew.pm 263914 2009-12-03 17:41:02Z tv $ + +use strict; +use Text::Diff; +use MDK::Common::Math qw(sum); +use MDK::Common::File qw(renamef); +use MDK::Common::Various qw(chomp_); + +use ManaTools::rpmdragora; +use ManaTools::Rpmdragora::init; +use ManaTools::Rpmdragora::pkg; +use ManaTools::Rpmdragora::open_db; +use ManaTools::Rpmdragora::formatting; + +use yui; + +use Exporter; +our @ISA = qw(Exporter); +our @EXPORT = qw(rpmnew_dialog do_merge_if_needed); + +my $loc = ManaTools::rpmdragora::locale(); + +# /var/lib/nfs/etab /var/lib/nfs/rmtab /var/lib/nfs/xtab /var/cache/man/whatis +my %ignores_rpmnew = map { $_ => 1 } qw( + /etc/adjtime + /etc/fstab + /etc/group + /etc/ld.so.conf + /etc/localtime + /etc/modules + /etc/passwd + /etc/security/fileshare.conf + /etc/shells + /etc/sudoers + /etc/sysconfig/alsa + /etc/sysconfig/autofsck + /etc/sysconfig/harddisks + /etc/sysconfig/harddrake2/previous_hw + /etc/sysconfig/init + /etc/sysconfig/installkernel + /etc/sysconfig/msec + /etc/sysconfig/nfs + /etc/sysconfig/pcmcia + /etc/sysconfig/rawdevices + /etc/sysconfig/saslauthd + /etc/sysconfig/syslog + /etc/sysconfig/usb + /etc/sysconfig/xinetd +); + + +#============================================================= + +=head2 _rpmnewFile + +=head3 INPUT + + $filename: configuration file name + +=head3 OUTPUT + + $rpmnew_filename: new configuration file name + +=head3 DESCRIPTION + + This function evaluate the new configration file generated by + the update + +=cut + +#============================================================= +sub _rpmnewFile ($) { + my $filename = shift; + + my ($rpmnew, $rpmsave) = ("$filename.rpmnew", "$filename.rpmsave"); + my $rpmfile = 'rpmnew'; + -r $rpmnew or $rpmfile = 'rpmsave'; + -r $rpmnew && -r $rpmsave && (stat $rpmsave)[9] > (stat $rpmnew)[9] and $rpmfile = 'rpmsave'; + $rpmfile eq 'rpmsave' and $rpmnew = $rpmsave; + + return $rpmnew; +} + +#============================================================= + +=head2 _performDiff + +=head3 INPUT + + $file: configuration file name + $diffBox: YWidget that will show the difference + +=head3 DESCRIPTION + + This function gets the configuration file perfomrs + the difference with the new one and shows it into the + $diffBox + +=cut + +#============================================================= +sub _performDiff ($$) { + my ($file, $diffBox) = @_; + + my $rpmnew = _rpmnewFile($file); + + foreach (qw(LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT LC_IDENTIFICATION LC_ALL)) { + local $ENV{$_} = $ENV{$_} . '.UTF-8' if $ENV{$_} && $ENV{$_} !~ /UTF-8/; + } + + my $diff = diff $file, $rpmnew, { STYLE => "Unified" }; + $diff = $loc->N("(none)") if !$diff; + + my @lines = split ("\n", $diff); + ## adding color lines to diff + foreach my $line (@lines) { + if (substr ($line, 0, 1) eq "+") { + $line =~ s|^\+(.*)|+$1|; + } + elsif (substr ($line, 0, 1) eq "-") { + $line =~ s|^\-(.*)|-$1|; + } + elsif (substr ($line, 0, 1) eq "@") { + $line =~ s|(.*)|$1|; + } + else { + $line =~ s|(.*)|$1|; + } + } + $diff = join("
", @lines); + + ensure_utf8($diff); + $diffBox->setValue($diff); + + return; +} + +#============================================================= + +=head2 rpmnew_dialog + +=head3 INPUT + + $msg: message to be shown during the choice + %o2r: HASH containing { + the package name => ARRAY of configration files + } + +=head3 OUTPUT + + 1 if nothing to do or 0 after user interaction + +=head3 DESCRIPTION + + This function shows the configuration files difference and + asks for action to be performed + +=cut + +#============================================================= +sub rpmnew_dialog { + my ($msg, %p2r) = @_; + + @{$p2r{$_}} = grep { !$ignores_rpmnew{$_} } @{$p2r{$_}} foreach keys %p2r; + my $sum_rpmnew = MDK::Common::Math::sum(map { int @{$p2r{$_}} } keys %p2r); + $sum_rpmnew == 0 and return 1; + + my $appTitle = yui::YUI::app()->applicationTitle(); + + ## set new title to get it in dialog + yui::YUI::app()->setApplicationTitle($loc->N("Installation finished")); + + my $factory = yui::YUI::widgetFactory; + + ## | [msg-label] | + ## | | + ## | pkg-tree | + ## | | + ## | info on selected pkg |(1) + ## | Remove( ) Use ( ) Do nothing (*) | + ## | | + ## | [ok] | + #### + # (1) info on pkg list: + # selected configuration file diff between rpmnew/rpmsave and used one + + my $dialog = $factory->createPopupDialog; + my $vbox = $factory->createVBox( $dialog ); + my $msgBox = $factory->createLabel($vbox, $msg, 1); + $factory->createVSpacing($vbox, 1); + # Tree for groups + my $tree = $factory->createTree($vbox, $loc->N("Select a package")); + $tree->setWeight($yui::YD_VERT,10); + $factory->createVSpacing($vbox, 1); + my $infoBox = $factory->createRichText($vbox, "", 0); + $infoBox->setWeight($yui::YD_HORIZ, 20); + $infoBox->setWeight($yui::YD_VERT, 20); + $factory->createVSpacing($vbox, 1); + my $radiobuttongroup = $factory->createRadioButtonGroup($vbox); + my $rbbox = $factory->createHBox($radiobuttongroup); + my $rdnBtn = { + remove_rpmnew => $loc->N("Remove new file"), + use_rpmnew => $loc->N("Use new file"), + do_onthing => $loc->N("Do nothing"), + }; + + my %radiobutton = (); + my @rdnbtn_order = ('remove_rpmnew', 'use_rpmnew', 'do_onthing'); + foreach my $btn_name (@rdnbtn_order) { + $radiobutton{$btn_name} = $factory->createRadioButton($rbbox, $rdnBtn->{$btn_name}); + $radiobutton{$btn_name}->setValue(1) if $btn_name eq 'do_onthing'; + $radiobutton{$btn_name}->setNotify(1); + $radiobuttongroup->addRadioButton($radiobutton{$btn_name}); + } + $radiobuttongroup->setEnabled(0); + my $hbox = $factory->createHBox( $vbox ); + my $align = $factory->createHCenter($hbox); + my $okButton = $factory->createPushButton($align, $loc->N("&Ok")); + $okButton->setDefaultButton(1); + + # adding packages to the list + my $itemColl = new yui::YItemCollection; + my $num = 0; + my %file_action = (); + foreach my $p (sort keys %p2r) { + if (scalar @{$p2r{$p}}) { + my $item = new yui::YTreeItem ("$p"); + foreach my $f (@{$p2r{$p}}) { + my $child = new yui::YTreeItem ($item, "$f"); + $child->DISOWN(); + $file_action{$f} = 'do_onthing'; + } + $itemColl->push($item); + $item->DISOWN(); + } + } + + $tree->addItems($itemColl); + $tree->setImmediateMode(1); + $tree->rebuildTree(); + + 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 + my $widget = $event->widget(); + if ($widget == $tree) { + #change info + my $item = $tree->selectedItem(); + if ($item && !$item->hasChildren()) { + my $filename = $tree->currentItem()->label(); + _performDiff($filename, $infoBox); + $radiobuttongroup->setEnabled(1); + #$radiobuttongroup->uncheckOtherButtons ($radiobutton{$file_action{$filename}}); + yui::YUI::ui()->blockEvents(); + $radiobutton{$file_action{$filename}}->setValue(1); + yui::YUI::ui()->unblockEvents(); + } + else { + $infoBox->setValue(""); + $radiobuttongroup->setEnabled(0); + } + } + elsif ($widget == $okButton) { + # TODO + foreach my $file (keys %file_action) { + my $rpmnew = _rpmnewFile($file); + if ($file_action{$file} eq 'remove_rpmnew') { + eval { unlink "$rpmnew"}; + } + elsif ($file_action{$file} eq 'use_rpmnew') { + MDK::Common::File::renamef($rpmnew, $file); + } + # else do_onthing + } + last; + } + else { + # radio buttons + RDNBTN: foreach my $btn_name (@rdnbtn_order) { + if ($widget == $radiobutton{$btn_name}) { + my $filename = $tree->currentItem()->label(); + $file_action{$filename} = $btn_name; + last RDNBTN; + } + } + } + } + } + + destroy $dialog; + + # restore original title + yui::YUI::app()->setApplicationTitle($appTitle) if $appTitle; + + return 0; +} + + +#============================================================= + +=head2 do_merge_if_needed + +=head3 DESCRIPTION + + This function look for new configuration file versions + and ask for actions using the rpmnew_dialog + +=cut + +#============================================================= +sub do_merge_if_needed() { + if ($rpmdragora_options{'merge-all-rpmnew'}) { + my %pkg2rpmnew; + my $wait = wait_msg($loc->N("Please wait, searching...")); + print "Searching .rpmnew and .rpmsave files...\n"; + # costly: + open_rpm_db()->traverse(sub { + my $n = my_fullname($_[0]); + $pkg2rpmnew{$n} = [ grep { m|^/etc| && (-r "$_.rpmnew" || -r "$_.rpmsave") } map { chomp_($_) } $_[0]->conf_files ]; + }); + print "done.\n"; + remove_wait_msg($wait); + + rpmnew_dialog('', %pkg2rpmnew) and print "Nothing to do.\n"; + } + + return; +} + +1; diff --git a/lib/ManaTools/SettingsReader.pm b/lib/ManaTools/SettingsReader.pm new file mode 100644 index 0000000..318aefd --- /dev/null +++ b/lib/ManaTools/SettingsReader.pm @@ -0,0 +1,101 @@ +# vim: set et ts=4 sw=4: +package ManaTools::SettingsReader; +#============================================================= -*-perl-*- + +=head1 NAME + +ManaTools::SettingsReader - This module allows to load an XML configuration file + +=head1 SYNOPSIS + + use ManaTools::SettingsReader; + + my $settings = new ManaTools::SettingsReader($fileName); + +=head1 DESCRIPTION + + This module allows to load a configuration file returning a Hash references with its content. + +=head1 SUPPORT + +You can find documentation for this module with the perldoc command: + +perldoc ManaTools::SettingsReader + +=head1 SEE ALSO + + XML::Simple + +=head1 AUTHOR + + Angelo Naselli + +=head1 COPYRIGHT and LICENSE + + Copyright (C) 2012-2015, Angelo Naselli. + + This file is part of ManaTools + + ManaTools is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + ManaTools 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 ManaTools. If not, see . + +=head1 FUNCTIONS + +=cut + + +use strict; +use warnings; +use diagnostics; +use XML::Simple; +use Data::Dumper; + +#============================================================= + +=head2 new + +=head3 INPUT + + $fileName: File to be loaded + +=head3 OUTPUT + + $settings: Hash reference containing read settings + +=head3 DESCRIPTION + + The constructor just loads the given files and return its representation + into a hash reference. + +=cut + +#============================================================= + +sub new { + my ($class, $fileName) = @_; + + my $self = { + settings => 0, + }; + bless $self, 'ManaTools::SettingsReader'; + + die "File " . $fileName . " not found" if (! -e $fileName); + + my $xml = new XML::Simple (KeyAttr=>[]); + $self->{settings} = $xml->XMLin($fileName); + + return $self->{settings}; +} + + +1; diff --git a/lib/ManaTools/Shared.pm b/lib/ManaTools/Shared.pm new file mode 100644 index 0000000..6a40539 --- /dev/null +++ b/lib/ManaTools/Shared.pm @@ -0,0 +1,376 @@ +# vim: set et ts=4 sw=4: +# Copyright 2012-2015 Angelo Naselli +# Copyright 2013-2015 Matteo Pasotti +# +# This file is part of ManaTools +# +# ManaTools is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# ManaTools 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 ManaTools. If not, see . + +package ManaTools::Shared; + +=head1 NAME + +ManaTools::Shared - ManaTools::Shared contains all the shared routines + needed by ManaTools and modules + +=head1 SYNOPSIS + + + +=head1 DESCRIPTION + +This module collects all the routines shared between ManaTools and its modules. + +=head1 EXPORT + + trim + md5sum + pathList2hash + distName + apcat + inArray + disable_x_screensaver + enable_x_screensaver + isProcessRunning + +=head1 SUPPORT + +You can find documentation for this module with the perldoc command: + + perldoc ManaTools::Shared + +=head1 AUTHOR + +Angelo Naselli + +=head1 COPYRIGHT and LICENSE + +Copyright (C) 2013, Angelo Naselli. +Copyright (C) 2014, Matteo Pasotti. + +This file is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This file 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 file. If not, see . + +=head1 FUNCTIONS + +=cut + +use strict; +use warnings; +use diagnostics; + +use Digest::MD5; + +use yui; +use base qw(Exporter); + +# TODO move GUI dialogs to Shared::GUI +our @EXPORT_OK = qw( + trim + md5sum + pathList2hash + distName + apcat + inArray + disable_x_screensaver + enable_x_screensaver + isProcessRunning +); + + +=head1 VERSION + +Version 0.01 + +=cut + +our $VERSION = '0.01'; + + + +#============================================================= + +=head2 apcat + +=head3 PARAMETERS + +$filename the name of the file to read + +=head3 OUTPUT + +depending from the context it returns the content +of the file as an array or a string + +=head3 DESCRIPTION + +This function return the content of $filename or false/0 +if it fails + +=cut + +#============================================================= + +sub apcat { + my $fn = shift(); + my $fh = undef; + my @content = (); + open($fh, "<", $fn) || return 0; + while(<$fh>) + { + push(@content, $_); + } + return (wantarray() ? @content : join('',@content)); +} + + +#============================================================= + +=head2 distName + +=head3 OUTPUT + +$distname: name of the distributed package + +=head3 DESCRIPTION + +This function return the distname, useful to retrieve data +with File::ShareDir::dist_file and must be the same as into +Makefile.PL (e.g. manatools) + +=cut + +#============================================================= + +sub distName { + return "manatools"; +} + + +#============================================================= + +=head2 trim + +=head3 INPUT + + $st: String to be trimmed + +=head3 OUTPUT + + $st: trimmed string + +=head3 DESCRIPTION + +This function trim the given string. + +=cut + +#============================================================= + +sub trim { + my ($st) = shift; + $st =~s /^\s+//g; + $st =~s /\s+$//g; + return $st; +} + +#============================================================= + +=head2 inArray + +=head3 INPUT + + $item: item to search + $arr: array container + +=head3 OUTPUT + + true: if the array contains the item + +=head3 DESCRIPTION + +This method returns if an item is into the array container + +=cut + +#============================================================= +sub inArray { + my ($item, $arr) = @_; + + return grep( /^$item$/, @{$arr} ); +} + + +#============================================================= + +=head2 md5sum + +=head3 INPUT + + $filename: file for md5 calculation + +=head3 OUTPUT + + md5 sum + +=head3 DESCRIPTION + + compute MD5 for the given file + +=cut + +#============================================================= + +sub md5sum { + my @files = @_; + + my @md5 = map { + my $sum; + if (open(my $FILE, $_)) { + binmode($FILE); + $sum = Digest::MD5->new->addfile($FILE)->hexdigest; + close($FILE); + } + $sum; + } @files; + return wantarray() ? @md5 : $md5[0]; +} + +#============================================================= + +=head2 pathList2hash + +=head3 INPUT + + $param : HASH ref containing + paths => ARRAY of string containing path like strings + separator => item separator inside a single path + (default separator is /) + +=head3 OUTPUT + + \%tree: HASH reference containing the same structur passed as ARRAY + in a tree view form, leaves are undef. + +=head3 DESCRIPTION + + This function return a tree representation of the given array. + +=cut + +#============================================================= + +sub pathList2hash { + my ($param) = @_; + + die "array of path is missing" if ! exists $param->{paths}; + my $separator = '/'; + $separator = $param->{separator} if $param->{separator}; + if ($separator eq "/" || $separator eq "|") { + $separator = '\\' . $separator; + } + + my %tree; + for (@{$param->{paths}}) + { + my $last = \\%tree; + $last = \$$last->{$_} for split /$separator/; + } + + return \%tree; +} + +#============================================================= + +=head2 disable_x_screensaver + +=head3 DESCRIPTION + + if exists /usr/bin/xset disable screensaver + +=cut + +#============================================================= +sub disable_x_screensaver() { + if (-e '/usr/bin/xset') { + $ENV{PATH} = "/usr/bin:/usr/sbin"; + system ("/usr/bin/xset s off"); + system ("/usr/bin/xset -dpms"); + } +} + +#============================================================= + +=head2 enable_x_screensaver + +=head3 DESCRIPTION + + if exists /usr/bin/xset enables screensaver + +=cut + +#============================================================= +sub enable_x_screensaver() { + if (-e '/usr/bin/xset') { + $ENV{PATH} = "/usr/bin:/usr/sbin"; + system ("/usr/bin/xset +dpms"); + system ("/usr/bin/xset s on"); + system ("/usr/bin/xset s reset"); + } +} + +#============================================================= + +=head2 isProcessRunning + +=head3 INPUT + + $name: Process name + $o_user: user who the process belongs to + +=head3 OUTPUT + + $pid: process identifier + +=head3 DESCRIPTION + + Function returns the process identifier if the given + process is running + +=cut + +#============================================================= +sub isProcessRunning { + my ($name, $o_user) = @_; + my $user = $o_user || $ENV{USER}; + my @proc = `ps -o '%P %p %c' -u $user`; + shift (@proc); + foreach (@proc) { + my ($ppid, $pid, $n) = /^\s*(\d+)\s+(\d+)\s+(.*)/; + return $pid if $n eq $name && $ppid != 1 && $pid != $$; + } + return; +} + +1; # End of ManaTools::Shared + diff --git a/lib/ManaTools/Shared/Firewall.pm b/lib/ManaTools/Shared/Firewall.pm new file mode 100644 index 0000000..f5a6c45 --- /dev/null +++ b/lib/ManaTools/Shared/Firewall.pm @@ -0,0 +1,35 @@ +# vim: set et ts=4 sw=4: +#***************************************************************************** +# +# Copyright (c) 2013-2015 Matteo Pasotti +# +# 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::Shared::Firewall; + +use Moose; +use diagnostics; +use utf8; + +use lib qw(/usr/lib/libDrakX); +use network::nfs; +use network::network; +use network::tools; + +sub _initialize { + my $self = shift(); +} + +1; diff --git a/lib/ManaTools/Shared/GUI.pm b/lib/ManaTools/Shared/GUI.pm new file mode 100644 index 0000000..6c6144d --- /dev/null +++ b/lib/ManaTools/Shared/GUI.pm @@ -0,0 +1,1118 @@ +# vim: set et ts=4 sw=4: +package ManaTools::Shared::GUI; +#============================================================= -*-perl-*- + +=head1 NAME + +Shared::GUI - Shared graphic routines + +=head1 SYNOPSIS + + my $gui = ManaTools::Shared::GUI->new(); + my $yesPressed = $gui->ask_YesOrNo($title, $text); + +=head1 DESCRIPTION + + This module contains a collection of dialogs or widgets that can be used in more + graphics modules. + +=head1 EXPORT + +exported + +=head1 SUPPORT + +You can find documentation for this module with the perldoc command: + +perldoc Shared::GUI + + +=head1 AUTHOR + +Angelo Naselli + +=head1 COPYRIGHT and LICENSE + +Copyright (C) 2014-2015, Angelo Naselli. +Copyright (C) 2015, Matteo Pasotti . + +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 METHODS + +=cut + + +use Moose; + +use diagnostics; +use yui; + +use ManaTools::Shared qw(pathList2hash); + +use ManaTools::Shared::Locales; + +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' +} + + +#============================================================= + +=head2 warningMsgBox + +=head3 INPUT + + $info: HASH, information to be passed to the dialog. + title => dialog title + text => string to be swhon into the dialog + richtext => 1 if using rich text + +=head3 DESCRIPTION + + This function creates an Warning dialog and show the message + passed as input. + +=cut + +#============================================================= +sub warningMsgBox { + my ($self, $info) = @_; + + return 0 if ( ! $info ); + + my $retVal = 0; + yui::YUI::widgetFactory; + my $factory = yui::YExternalWidgets::externalWidgetFactory("mga"); + $factory = yui::YMGAWidgetFactory::getYMGAWidgetFactory($factory); + my $dlg = $factory->createDialogBox($yui::YMGAMessageBox::B_ONE, + $yui::YMGAMessageBox::D_WARNING); + + $dlg->setTitle($info->{title}) if (exists $info->{title}); + my $rt = (exists $info->{richtext}) ? $info->{richtext} : 0; + $dlg->setText($info->{text}, $rt) if (exists $info->{text}); + + $dlg->setButtonLabel($self->loc->N("Ok"), $yui::YMGAMessageBox::B_ONE ); +# $dlg->setMinSize(50, 5); + + $retVal = $dlg->show(); + + $dlg = undef; + + return 1; +} + +#============================================================= + +=head2 infoMsgBox + +=head3 INPUT + + $info: HASH, information to be passed to the dialog. + title => dialog title + text => string to be swhon into the dialog + richtext => 1 if using rich text + +=head3 DESCRIPTION + + This function creates an Info dialog and show the message + passed as input. + +=cut + +#============================================================= + +sub infoMsgBox { + my ($self, $info) = @_; + + return 0 if ( ! $info ); + + my $retVal = 0; + yui::YUI::widgetFactory; + my $factory = yui::YExternalWidgets::externalWidgetFactory("mga"); + $factory = yui::YMGAWidgetFactory::getYMGAWidgetFactory($factory); + my $dlg = $factory->createDialogBox($yui::YMGAMessageBox::B_ONE, + $yui::YMGAMessageBox::D_INFO); + + $dlg->setTitle($info->{title}) if (exists $info->{title}); + my $rt = (exists $info->{richtext}) ? $info->{richtext} : 0; + $dlg->setText($info->{text}, $rt) if (exists $info->{text}); + + $dlg->setButtonLabel($self->loc->N("Ok"), $yui::YMGAMessageBox::B_ONE ); +# $dlg->setMinSize(50, 5); + + $retVal = $dlg->show(); + + $dlg = undef; + + return 1; +} + +#============================================================= + +=head2 msgBox + +=head3 INPUT + + $info: HASH, information to be passed to the dialog. + title => dialog title + text => string to be swhon into the dialog + richtext => 1 if using rich text + +=head3 DESCRIPTION + + This function creates a dialog and show the message passed as input. + +=cut + +#============================================================= + +sub msgBox { + my ($self, $info) = @_; + + return 0 if ( ! $info ); + + my $retVal = 0; + yui::YUI::widgetFactory; + my $factory = yui::YExternalWidgets::externalWidgetFactory("mga"); + $factory = yui::YMGAWidgetFactory::getYMGAWidgetFactory($factory); + my $dlg = $factory->createDialogBox($yui::YMGAMessageBox::B_ONE); + + $dlg->setTitle($info->{title}) if (exists $info->{title}); + my $rt = (exists $info->{richtext}) ? $info->{richtext} : 0; + $dlg->setText($info->{text}, $rt) if (exists $info->{text}); + + $dlg->setButtonLabel($self->loc->N("Ok"), $yui::YMGAMessageBox::B_ONE ); +# $dlg->setMinSize(50, 5); + + $retVal = $dlg->show(); + + $dlg = undef; + + return 1; +} + +#============================================================= + +=head2 ask_OkCancel + +=head3 INPUT + + $info: HASH, information to be passed to the dialog. + title => dialog title + text => string to be swhon into the dialog + richtext => 1 if using rich text + +=head3 OUTPUT + + 0: Cancel button has been pressed + 1: Ok button has been pressed + +=head3 DESCRIPTION + + This function create an OK-Cancel dialog with a 'title' and a + 'text' passed as parameters. + +=cut + +#============================================================= + +sub ask_OkCancel { + my ($self, $info) = @_; + + return 0 if ( ! $info ); + + my $retVal = 0; + yui::YUI::widgetFactory; + my $factory = yui::YExternalWidgets::externalWidgetFactory("mga"); + $factory = yui::YMGAWidgetFactory::getYMGAWidgetFactory($factory); + my $dlg = $factory->createDialogBox($yui::YMGAMessageBox::B_TWO); + + $dlg->setTitle($info->{title}) if (exists $info->{title}); + my $rt = (exists $info->{richtext}) ? $info->{richtext} : 0; + $dlg->setText($info->{text}, $rt) if (exists $info->{text}); + + $dlg->setButtonLabel($self->loc->N("Ok"), $yui::YMGAMessageBox::B_ONE ); + $dlg->setButtonLabel($self->loc->N("Cancel"), $yui::YMGAMessageBox::B_TWO); + $dlg->setDefaultButton($yui::YMGAMessageBox::B_ONE); + $dlg->setMinSize(50, 5); + + $retVal = $dlg->show() == $yui::YMGAMessageBox::B_ONE ? 1 : 0; + + $dlg = undef; + + return $retVal; +} + +#============================================================= + +=head2 ask_YesOrNo + +=head3 INPUT + + $info: HASH, information to be passed to the dialog. + title => dialog title + text => string to be swhon into the dialog + richtext => 1 if using rich text + default_button => (optional) 1: "Yes" (any other values "No") + +=head3 OUTPUT + + 0: "No" button has been pressed + 1: "Yes" button has been pressed + +=head3 DESCRIPTION + + This function create a Yes-No dialog with a 'title' and a + question 'text' passed as parameters. + +=cut + +#============================================================= + +sub ask_YesOrNo { + my ($self, $info) = @_; + + return 0 if ( ! $info ); + + my $retVal = 0; + yui::YUI::widgetFactory; + my $factory = yui::YExternalWidgets::externalWidgetFactory("mga"); + $factory = yui::YMGAWidgetFactory::getYMGAWidgetFactory($factory); + my $dlg = $factory->createDialogBox($yui::YMGAMessageBox::B_TWO); + + $dlg->setTitle($info->{title}) if (exists $info->{title}); + my $rt = (exists $info->{richtext}) ? $info->{richtext} : 0; + $dlg->setText($info->{text}, $rt) if (exists $info->{text}); + + $dlg->setButtonLabel($self->loc->N("Yes"), $yui::YMGAMessageBox::B_ONE ); + $dlg->setButtonLabel($self->loc->N("No"), $yui::YMGAMessageBox::B_TWO); + if (exists $info->{default_button} && $info->{default_button} == 1) { + $dlg->setDefaultButton($yui::YMGAMessageBox::B_ONE); + } + else { + $dlg->setDefaultButton($yui::YMGAMessageBox::B_TWO); + } + $dlg->setMinSize(50, 5); + + $retVal = $dlg->show() == $yui::YMGAMessageBox::B_ONE ? 1 : 0; + + $dlg = undef; + + return $retVal; +} + + +#============================================================= + +=head2 ask_TwoConfigurableButtons + +=head3 INPUT + +$info: HASH, information to be passed to the dialog. + title => dialog title + text => string to be swhon into the dialog + richtext => 1 if using rich text + button_one => caption for the first button + button_two => caption for the second button + default_button => (optional) 1: "First button" + +=head3 OUTPUT + + 0: "Button One Caption" button has been pressed + 1: "Button Two Caption" button has been pressed + +=head3 DESCRIPTION + +This function create a two-buttons dialog with a 'title', a +question 'text' and a label for each button passed as parameters. + +=cut + +#============================================================= + +sub ask_TwoConfigurableButtons { + my ($self, $info) = @_; + + return 0 if ( ! $info ); + + my $retVal = 0; + yui::YUI::widgetFactory; + my $factory = yui::YExternalWidgets::externalWidgetFactory("mga"); + $factory = yui::YMGAWidgetFactory::getYMGAWidgetFactory($factory); + my $dlg = $factory->createDialogBox($yui::YMGAMessageBox::B_TWO); + + $dlg->setTitle($info->{title}) if (exists $info->{title}); + my $rt = (exists $info->{richtext}) ? $info->{richtext} : 0; + $dlg->setText($info->{text}, $rt) if (exists $info->{text}); + + $dlg->setButtonLabel($info->{button_one}, $yui::YMGAMessageBox::B_ONE ); + $dlg->setButtonLabel($info->{button_two}, $yui::YMGAMessageBox::B_TWO); + if (exists $info->{default_button} && $info->{default_button} == 1) { + $dlg->setDefaultButton($yui::YMGAMessageBox::B_ONE); + } + else { + $dlg->setDefaultButton($yui::YMGAMessageBox::B_TWO); + } + $dlg->setMinSize(50, 5); + + $retVal = $dlg->show() == $yui::YMGAMessageBox::B_ONE ? 1 : 0; + + $dlg = undef; + + return $retVal; +} + +#============================================================= + +=head2 arrayListToYItemCollection + +=head3 INPUT + + $listInfo: HASH reference containing + default_item => Selected item (if any) + item_list => ARRAY reference containing the item list + +=head3 OUTPUT + + $itemList: YItemCollection containing the item list passed + +=head3 DESCRIPTION + + This method returns a YItemCollection containing the item list passed with default item + the "default_item" + +=cut + +#============================================================= + +sub arrayListToYItemCollection { + my ($self, $listInfo) = @_; + + die "Item list is mandatory" if !($listInfo->{item_list}); + # TODO check type + die "Not empty item list is mandatory" if (scalar @{$listInfo->{item_list}} < 1); + + + my $itemColl = new yui::YItemCollection; + foreach (@{$listInfo->{item_list}}) { + my $item = new yui::YItem ($_, 0); + $itemColl->push($item); + $item->DISOWN(); + if ($listInfo->{default_item} && $listInfo->{default_item} eq $item->label()) { + $item->setSelected(1); + } + } + + return $itemColl; +} + + +#============================================================= + +=head2 ask_fromList + +=head3 INPUT + + $info: HASH, information to be passed to the dialog. + title => dialog title + header => combobox header + default_item => selected item if any + list => item list + default_button => (optional) 1: Select (any other values Cancel) + +=head3 OUTPUT + + undef: if Cancel button has been pressed + selected item: if Select button has been pressed + +=head3 DESCRIPTION + + This function create a dialog with a combobox in which to + choose an item from a given list. + +=cut + +#============================================================= + +sub ask_fromList { + my ($self, $info) = @_; + + die "Missing dialog information" if (!$info); + die "Title is mandatory" if (! exists $info->{title}); + die "Header is mandatory" if (! exists $info->{header}); + die "List is mandatory" if (! exists $info->{list} ); + my $list = $info->{list}; + die "At least one element is mandatory into list" if (scalar(@$list) < 1); + + my $choice = undef; + my $factory = yui::YUI::widgetFactory; + + ## push application title + my $appTitle = yui::YUI::app()->applicationTitle(); + ## set new title to get it in dialog + yui::YUI::app()->setApplicationTitle($info->{title}); + + my $dlg = $factory->createPopupDialog($yui::YDialogNormalColor); + my $layout = $factory->createVBox($dlg); + + my $combo = $factory->createComboBox($layout, $info->{header}, 0); + + my $listInfo; + $listInfo->{default_item} = $info->{default_item} if $info->{default_item}; + $listInfo->{item_list} = $info->{list}; + my $itemColl = $self->arrayListToYItemCollection($listInfo); + $combo->addItems($itemColl); + + my $align = $factory->createRight($layout); + my $hbox = $factory->createHBox($align); + my $selectButton = $factory->createPushButton($hbox, $self->loc->N("Select")); + my $cancelButton = $factory->createPushButton($hbox, $self->loc->N("Cancel")); + + if (exists $info->{default_button} ) { + my $dflBtn = ($info->{default_button} == 1) ? $selectButton : $cancelButton; + $dlg->setDefaultButton($selectButton); + } + + 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 == $selectButton) { + my $item = $combo->selectedItem(); + $choice = $item->label() if ($item); + last; + } + } + } + + destroy $dlg; + + #restore old application title + yui::YUI::app()->setApplicationTitle($appTitle); + + return $choice; +} + +#============================================================= + +=head2 ask_multiple_fromList + +=head3 INPUT + +$info: HASH, information to be passed to the dialog. + title => dialog title + header => combobox header + default_item => selected item if any + list => item list + default_button => (optional) 1: Select (any other values Cancel) + +=head3 LIST + +list is an array of hashes like this + + { + id => unique identifier for this particular item, + text => "descriptive text" + val => reference to the boolean value + } + + +=head3 OUTPUT + + undef: if Cancel button has been pressed + selected items: ArrayRef of the selected ids, if Select button has been pressed + +=head3 DESCRIPTION + +This function create a dialog with variable checkboxes in which to +choose the items from a given list. + +Warning: to use only for a reduced set of items because of no scroll available + +=cut + +#============================================================= + +sub ask_multiple_fromList { + my ($self, $info) = @_; + + die "Missing dialog information" if (!$info); + die "Title is mandatory" if (! exists $info->{title}); + die "Header is mandatory" if (! exists $info->{header}); + die "List is mandatory" if (! exists $info->{list} ); + die "At least one element is mandatory into list" if (scalar(@{$info->{list}}) < 1); + + my $selections = []; + my $factory = yui::YUI::widgetFactory; + + ## push application title + my $appTitle = yui::YUI::app()->applicationTitle(); + ## set new title to get it in dialog + yui::YUI::app()->setApplicationTitle($info->{title}); + + my $dlg = $factory->createPopupDialog($yui::YDialogNormalColor); + my $layout = $factory->createVBox($dlg); + + my @ckbox_array = (); + + for my $item(@{$info->{list}}) + { + my $ckbox = $factory->createCheckBox( + $factory->createLeft($factory->createHBox($layout)), + $item->{text}, + ${$item->{val}} + ); + $ckbox->setNotify(1); + push @ckbox_array, { + id => $item->{id}, + widget => \$ckbox, + }; + $ckbox->DISOWN(); + } + + my $align = $factory->createRight($layout); + my $hbox = $factory->createHBox($align); + my $selectButton = $factory->createPushButton($hbox, $self->loc->N("Select")); + my $cancelButton = $factory->createPushButton($hbox, $self->loc->N("Cancel")); + + if (exists $info->{default_button} ) { + my $dflBtn = ($info->{default_button} == 1) ? $selectButton : $cancelButton; + $dlg->setDefaultButton($selectButton); + } + + 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) { + $selections = undef; + last; + } + elsif ($widget == $selectButton) { + foreach my $ckbox (@ckbox_array) + { + if(${$ckbox->{widget}}->value()) + { + # yui::YUI::ui()->blockEvents(); + push @{$selections}, $ckbox->{id}; + # yui::YUI::ui()->unblockEvents(); + } + } + last; + } + } + } + + destroy $dlg; + + #restore old application title + yui::YUI::app()->setApplicationTitle($appTitle); + + return $selections; +} + +#============================================================= + +=head2 AboutDialog + +=head3 INPUT + + $info: HASH containing optional information needed to get info for dialog. + name => the application name + version => the application version + license => the application license, the short length one (e.g. GPLv2, GPLv3, LGPLv2+, etc) + authors => the string providing the list of authors; it could be html-formatted + description => the string providing a brief description of the application + logo => the string providing the file path for the application logo (high-res image) + icon => the string providing the file path for the application icon (low-res image) + credits => the application credits, they can be html-formatted + information => other extra informations, they can be html-formatted + dialog_mode => 1: classic style dialog, any other as tabbed style dialog + +=head3 DESCRIPTION + + About dialog implementation, this dialog can be used by + modules, to show authors, license, credits, etc. + +=cut + +#============================================================= + +sub AboutDialog { + my ($self, $info) = @_; + + die "Missing dialog information" if (!$info); + + + yui::YUI::widgetFactory; + my $factory = yui::YExternalWidgets::externalWidgetFactory("mga"); + $factory = yui::YMGAWidgetFactory::getYMGAWidgetFactory($factory); + + my $name = (exists $info->{name}) ? $info->{name} : ""; + my $version = (exists $info->{version}) ? $info->{version} : ""; + my $license = (exists $info->{license}) ? $info->{license} : ""; + my $authors = (exists $info->{authors}) ? $info->{authors} : ""; + my $description = (exists $info->{description}) ? $info->{description} : ""; + my $logo = (exists $info->{logo}) ? $info->{logo} : ""; + my $icon = (exists $info->{icon}) ? $info->{icon} : ""; + my $credits = (exists $info->{credits}) ? $info->{credits} : ""; + my $information = (exists $info->{information}) ? $info->{information} : ""; + my $dialog_mode = $yui::YMGAAboutDialog::TABBED; + if (exists $info->{dialog_mode}) { + $dialog_mode = $yui::YMGAAboutDialog::CLASSIC if ($info->{dialog_mode} == 1); + } + + my $dlg = $factory->createAboutDialog($name, $version, $license, + $authors, $description, $logo, + $icon, $credits, $information + ); + + $dlg->show($dialog_mode); + + $dlg = undef; + + return 1; +} + +#============================================================= + +=head2 hashTreeToYItemCollection + +=head3 INPUT + + $treeInfo: HASH reference containing + parent ==> YItem parent (if not root object) + collection ==> YItemCollection (mandatory) + default_item ==> Selected item (if any) + default_item_separator ==> If default item is passed and is a path like string + the separator is needed to match the selected item, using + the full pathname instead leaf (e.g. root/subroot/leaf). + Default separator is also needed if '$treeInfo->{icons} entry is passed + to match the right icon to set (e.g. using the full pathname). + hash_tree ==> HASH reference containing the path tree representation + icons ==> HASH reference containing item icons e.g. + { + root => 'root_icon_pathname', + root/subroot => 'root_subroot_icon_pathname', + .... + } + Do not add it if no icons are wanted. + default_icon ==> icon pathname to a default icon for all the items that are + not into $treeInfo->{icons} or if $treeInfo->{icons} is not + defined. Leave undef if no default icon is wanted + +=head3 DESCRIPTION + + This function add to the given $treeInfo->{collection} new tree items from + the the given $treeInfo->{hash_tree} + +=cut + +#============================================================= + +sub hashTreeToYItemCollection { + my ($self, $treeInfo) = @_; + + die "Collection is mandatory" if !($treeInfo->{collection}); + die "Hash tree is mandatory" if !($treeInfo->{hash_tree}); + + my $treeLine = $treeInfo->{parent}; + my $item; + foreach my $key (sort keys %{$treeInfo->{hash_tree}}) { + if ($treeInfo->{parent}) { + $item = new yui::YTreeItem ($treeLine, $key); + $item->DISOWN(); + } + else { + if ($treeLine) { + if ( $treeLine->label() eq $key) { + $item = $treeLine; + } + else { + $treeInfo->{collection}->push($treeLine); + $item = $treeLine = new yui::YTreeItem ($key); + $item->DISOWN(); + } + } + else { + $item = $treeLine = new yui::YTreeItem ($key); + $item->DISOWN(); + } + } + + # building full path name + my $label = $key; + if (exists $treeInfo->{default_item_separator}) { + my $parent = $item; + while($parent = $parent->parent()) { + $label = $parent->label() . $treeInfo->{default_item_separator} . $label ; + } + } + my $icon = undef; + $icon = $treeInfo->{default_icon} if defined($treeInfo->{default_icon}); + $icon = $treeInfo->{icons}->{$label} if defined($treeInfo->{icons}) && defined($treeInfo->{icons}->{$label}); + + $item->setIconName($icon) if $icon; + + ### select item + if ($treeInfo->{default_item}) { + if ($treeInfo->{default_item} eq $label) { + $item->setSelected(1) ; + $item->setOpen(1); + my $parent = $item; + while($parent = $parent->parent()) { + $parent->setOpen(1); + } + } + } + + if ($treeInfo->{hash_tree}->{$key} && keys %{$treeInfo->{hash_tree}->{$key}}) { + my %tf; + $tf{collection} = $treeInfo->{collection}; + $tf{parent} = $item; + $tf{default_item} = $treeInfo->{default_item} if $treeInfo->{default_item}; + $tf{default_item_separator} = $treeInfo->{default_item_separator} if $treeInfo->{default_item_separator}; + $tf{hash_tree} = $treeInfo->{hash_tree}->{$key}; + $tf{icons} = $treeInfo->{icons}; + $self->hashTreeToYItemCollection(\%tf); + } + else { + if (! $treeInfo->{parent}) { + $treeInfo->{collection}->push($treeLine); + $treeLine = undef; + } + } + } + if (! $treeInfo->{parent}) { + $treeInfo->{collection}->push($treeLine) if $treeLine; + } +} + + +#============================================================= + +=head2 ask_fromTreeList + +=head3 INPUT + + $info: HASH, information to be passed to the dialog. + title => dialog title + header => TreeView header + list => path item list + min_size => minimum dialog size in the libYUI meaning + HASH {width => w, height => h} + default_item => selected item if any + item_separator => item separator default "/" + skip_path => if set item is returned without its original path, + just as a leaf (default use full path) + any_item_selection => allow to select any item, not just leaves (default just leaves) + default_button => (optional) 1: Select (any other values Cancel) + +=head3 OUTPUT + + undef: if Cancel button has been pressed + selected item: if Select button has been pressed + +=head3 DESCRIPTION + + This function create a dialog with a combobox in which to + choose an item from a given list. + +=cut + +#============================================================= + +sub ask_fromTreeList { + my ($self, $info) = @_; + + die "Missing dialog information" if (!$info); + die "Title is mandatory" if (! exists $info->{title}); + die "Header is mandatory" if (! exists $info->{header}); + die "List is mandatory" if (! exists $info->{list} ); + my $list = $info->{list}; + die "At least one element is mandatory into list" if (scalar(@$list) < 1); + + my $choice = undef; + my $factory = yui::YUI::widgetFactory; + + ## push application title + my $appTitle = yui::YUI::app()->applicationTitle(); + ## set new title to get it in dialog + yui::YUI::app()->setApplicationTitle($info->{title}); + my $minWidth = 80; + my $minHeight = 25; + + if (exists $info->{min_size}) { + $minWidth = $info->{min_size}->{width} if $info->{min_size}->{width}; + $minHeight = $info->{min_size}->{height} if $info->{min_size}->{height}; + } + + my $dlg = $factory->createPopupDialog($yui::YDialogNormalColor); + my $minSize = $factory->createMinSize( $dlg, $minWidth, $minHeight ); + my $layout = $factory->createVBox($minSize); + + my $treeWidget = $factory->createTree($layout, $info->{header}); + + my $treeInfo; + $treeInfo->{collection} = new yui::YItemCollection; + $treeInfo->{default_item} = $info->{default_item} if $info->{default_item}; + if ($treeInfo->{default_item} && $info->{item_separator}) { + if (index($treeInfo->{default_item}, $info->{item_separator}) != -1) { + $treeInfo->{default_item_separator} = $info->{item_separator}; + } + } + my $list2Convert; + $list2Convert->{paths} = $info->{list}; + $list2Convert->{separator} = $info->{item_separator} if $info->{item_separator}; + $treeInfo->{hash_tree} = ManaTools::Shared::pathList2hash($list2Convert); + + $self->hashTreeToYItemCollection($treeInfo); + $treeWidget->addItems($treeInfo->{collection}); + + my $align = $factory->createRight($layout); + my $hbox = $factory->createHBox($align); + my $selectButton = $factory->createPushButton($hbox, $self->loc->N("Select")); + my $cancelButton = $factory->createPushButton($hbox, $self->loc->N("Cancel")); + + if (exists $info->{default_button} ) { + my $dflBtn = ($info->{default_button} == 1) ? $selectButton : $cancelButton; + $dlg->setDefaultButton($selectButton); + } + + 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 == $selectButton) { + my $item = $treeWidget->selectedItem(); + my $getChoice = 1; + if (!exists $info->{any_item_selection} || $info->{any_item_selection} != 0) { + if ($item) { + $getChoice = (!$item->hasChildren()); + } + } + if ($info->{skip_path} && $info->{skip_path} != 0) { + $choice = $item->label() if ($item && $getChoice); + } + else { + if ($getChoice) { + my $separator = exists $info->{item_separator} ? $info->{item_separator} : '/'; + if ($item) { + $choice = $item->label(); + my $parent = $item; + while($parent = $parent->parent()) { + $choice = $parent->label() . $separator . $choice ; + } + } + } + } + + last; + } + } + } + + destroy $dlg; + + #restore old application title + yui::YUI::app()->setApplicationTitle($appTitle); + + return $choice; +} + + +#============================================================= + +=head2 select_fromList + +=head3 INPUT + + $info: HASH, information to be passed to the dialog. + title => dialog title + info_label => optional info text + header => column header hash reference{ + text_column => text column header + check_column => + } + list => item list hash reference + containing { + text => item text + selected => 0 ur undefined means unchecked + } + +=head3 OUTPUT + + selection: list of selected items + +=head3 DESCRIPTION + + This function create a dialog cotaining a table with a list of + items to be checked. The list of the checked items is returned. + +=cut + +#============================================================= + +sub select_fromList { + my ($self, $info) = @_; + + die "Missing dialog information" if (!$info); + die "Title is mandatory" if (! exists $info->{title}); + die "Header is mandatory" if (! exists $info->{header}); + die "Header text column is mandatory" if (! $info->{header}->{text_column}); + die "List is mandatory" if (! exists $info->{list} ); + my $list = $info->{list}; + die "At least one element is mandatory into list" if (scalar(@$list) < 1); + + my $selection = []; + + my $mageiaPlugin = "mga"; + my $factory = yui::YUI::widgetFactory; + my $mgaFactory = yui::YExternalWidgets::externalWidgetFactory($mageiaPlugin); + $mgaFactory = yui::YMGAWidgetFactory::getYMGAWidgetFactory($mgaFactory); + + ## push application title + my $appTitle = yui::YUI::app()->applicationTitle(); + ## set new title to get it in dialog + yui::YUI::app()->setApplicationTitle($info->{title}); + + my $dlg = $factory->createPopupDialog($yui::YDialogNormalColor); + my $layout = $factory->createVBox($dlg); + + if ($info->{info_label}) { + $factory->createLabel($layout, $info->{info_label}); + } + + my $yTableHeader = new yui::YTableHeader(); + $yTableHeader->addColumn($info->{header}->{text_column}, $yui::YAlignBegin); + $yTableHeader->addColumn($info->{header}->{check_column} || '', $yui::YAlignBegin); + + ## service list (serviceBox) + my $selectionTable = $mgaFactory->createCBTable( + $layout, + $yTableHeader, + $yui::YCBTableCheckBoxOnLastColumn + ); + $selectionTable->setImmediateMode(1); + $selectionTable->setWeight($yui::YD_HORIZ, 75); + + $selectionTable->startMultipleChanges(); + $selectionTable->deleteAllItems(); + my $itemCollection = new yui::YItemCollection; + ## NOTE do not sort to preserve item indexes + foreach (@{$list}) { + my $text = $_->{text} || die "item text is mandatory"; + + my $item = new yui::YCBTableItem($text); + $item->check( $_->{checked} ); + $itemCollection->push($item); + $item->DISOWN(); + } + $selectionTable->addItems($itemCollection); + $selectionTable->doneMultipleChanges(); + + my $align = $factory->createRight($layout); + my $hbox = $factory->createHBox($align); + $factory->createVSpacing($hbox, 1.0); + my $okButton = $factory->createPushButton($hbox, $self->loc->N("Ok")); + $dlg->setDefaultButton($okButton); + $dlg->recalcLayout(); + + 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 == $okButton) { + last; + } + elsif ($widget == $selectionTable) { + my $wEvent = yui::toYWidgetEvent($event); + if ($wEvent->reason() == $yui::YEvent::ValueChanged) { + my $item = $selectionTable->changedItem(); + if ($item) { + my $index = $item->index(); + $list->[$index]->{checked} = $item->checked(); + } + } + } + } + } + + destroy $dlg; + + #restore old application title + yui::YUI::app()->setApplicationTitle($appTitle); + + foreach (@{$list}) { + push @{$selection}, $_->{text} if $_->{checked}; + } + + return $selection; +} + +no Moose; +__PACKAGE__->meta->make_immutable; + + +1; + diff --git a/lib/ManaTools/Shared/Hosts.pm b/lib/ManaTools/Shared/Hosts.pm new file mode 100644 index 0000000..d3b7fc9 --- /dev/null +++ b/lib/ManaTools/Shared/Hosts.pm @@ -0,0 +1,216 @@ +# vim: set et ts=4 sw=4: +#***************************************************************************** +# +# Copyright (c) 2013-2015 Matteo Pasotti +# +# 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::Shared::Hosts; + +use Moose; +use diagnostics; +use Config::Hosts; +use Net::DBus; +use utf8; + +# costants by Config::Hosts +my $is_ip = 1; +my $is_host = -1; +my $is_none = 0; + +has 'configHosts' => ( + is => 'rw', + init_arg => undef, + builder => '_initialize' +); + +has 'dbusConnectionParams' => ( + is => 'ro', + isa => 'HashRef', + builder => '_initDBusConnectionParams', +); + +sub _initialize { + my $self = shift(); + $self->configHosts(Config::Hosts->new()); +} + +sub _initDBusConnectionParams { + my $self = shift(); + my %dbusConnParams = ( 'servicePath' => 'org.freedesktop.hostname1', 'objectPath' => '/org/freedesktop/hostname1' ); + return \%dbusConnParams; +} + +=pod + +=head2 _getHosts + +=head3 OUTPUT + + @result: array of hashes; each one of them represent a host definition from the hosts configuration file + + NOTE: the 'hosts' item into each hash is an array: it contains the hostname and -eventually- the aliases + +=head3 DESCRIPTION + +retrieve data from the hosts file (/etc/hosts) using the Config::Hosts module + +=cut + +sub _getHosts { + my $self = shift(); + # $self->configHosts(Config::Hosts->new()); + my $hosts = $self->configHosts->read_hosts(); + my @result = (); + while( my ($key, $value) = each(%{$hosts})){ + if($self->configHosts->determine_ip_or_host($key) == $is_ip){ + my $tmp = {}; + $tmp = $self->configHosts->query_host($key); + $tmp->{'ip'} = $key; + push @result,$tmp; + } + } + return @result; +} + +sub _insertHost { + my $self = shift(); + # remember that the order matters! + my $ip = shift(); + my @host_definitions = @_; + # $self->configHosts = Config::Hosts->new(); + return $self->configHosts->insert_host(ip => $ip, hosts => @host_definitions); +} + +sub _dropHost { + my $self = shift(); + my $host_ip = shift(); + return $self->configHosts->delete_host($host_ip); +} + +sub _modifyHost { + my $self = shift(); + my $host_ip = shift(); + my @host_definitions = @_; + return $self->configHosts->update_host($host_ip, hosts => @host_definitions); +} + +sub _writeHosts { + my $self = shift(); + return $self->configHosts->write_hosts(); +} + +sub _dbus_connection { + my $self = shift(); + my %params = %{$self->dbusConnectionParams()}; + my $bus = Net::DBus->system; + my $service = $bus->get_service($params{'servicePath'}); + my $object = $service->get_object($params{'objectPath'}); + return $object; +} + +sub _dbus_inquiry { + my $self = shift(); + my $required_field = shift(); + my $object = $self->_dbus_connection(); + my %params = %{$self->dbusConnectionParams()}; + my $properties = $object->GetAll($params{'servicePath'}); + return $properties->{$required_field} if(defined($properties->{$required_field})); + return 0; +} + +sub _dbus_setup { + my $self = shift(); + my $attribute = shift(); + my $value = shift(); + my $object = $self->_dbus_connection(); + if($attribute eq "Hostname") + { + $object->SetHostname($value,1); + } + elsif($attribute eq "PrettyHostname") + { + $object->SetPrettyHostname($value,1); + } + elsif($attribute eq "StaticHostname") + { + $object->SetStaticHostname($value,1); + } + elsif($attribute eq "Chassis") + { + $object->SetChassis($value,1); + } + elsif($attribute eq "IconName") + { + $object->SetIconName($value,1); + } +} + +sub _getLocalHostName { + my $self = shift(); + return $self->_dbus_inquiry('Hostname'); +} + +sub _getLocalPrettyHostName { + my $self = shift(); + return $self->_dbus_inquiry('PrettyHostname'); +} + +sub _getLocalStaticHostName { + my $self = shift(); + return $self->_dbus_inquiry('StaticHostname'); +} + +sub _getLocalChassis { + my $self = shift(); + return $self->_dbus_inquiry('Chassis'); +} + +sub _getLocalIconName { + my $self = shift(); + return $self->_dbus_inquiry('IconName'); +} + +sub _setLocalHostName { + my $self = shift(); + my $hostname = shift(); + $self->_dbus_setup('Hostname',$hostname); +} + +sub _setLocalPrettyHostName { + my $self = shift(); + my $value = shift(); + $self->_dbus_setup('PrettyHostname',$value); +} + +sub _setLocalStaticHostName { + my $self = shift(); + my $value = shift(); + $self->_dbus_setup('StaticHostname',$value); +} + +sub _setLocalIconName { + my $self = shift(); + my $value = shift(); + $self->_dbus_setup('IconName',$value); +} + +sub _setLocalChassis { + my $self = shift(); + my $value = shift(); + $self->_dbus_setup('Chassis',$value); +} + +1; diff --git a/lib/ManaTools/Shared/JournalCtl.pm b/lib/ManaTools/Shared/JournalCtl.pm new file mode 100644 index 0000000..1194538 --- /dev/null +++ b/lib/ManaTools/Shared/JournalCtl.pm @@ -0,0 +1,141 @@ +# vim: set et ts=4 sw=4: +package ManaTools::Shared::JournalCtl; + +#============================================================= -*-perl-*- + +=head1 NAME + +ManaTools::Shared::JournalCtl - journalctl perl wrapper + +=head1 SYNOPSIS + + my $log = ManaTools::Shared::JournalCtl->new(); + my @log_content = $log->getLog(); + +=head1 DESCRIPTION + +This module wraps journalctl allowing some running options and provides the +output log content. + +=head1 SUPPORT + +You can find documentation for this module with the perldoc command: + +perldoc ManaTools::Shared::JournalCtl + + +=head1 AUTHOR + +Angelo Naselli + +=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 METHODS + +=cut + +use Moose; + +use diagnostics; + + +has 'this_boot' => ( + is => 'rw', + isa => 'Int', + default => 0, +); + +has 'since' => ( + is => 'rw', + isa => 'Str', + default => "", +); + +has 'until' => ( + is => 'rw', + isa => 'Str', + default => "", +); + +has 'priority' => ( + is => 'rw', + isa => 'Str', + default => "", +); + +has 'unit' => ( + is => 'rw', + isa => 'Str', + default => "", +); + +#============================================================= + +=head2 getLog + +=head3 INPUT + +Input_Parameter: in_par_description + +=head3 OUTPUT + +\@content: ARRAYREF containing the log content. + +=head3 DESCRIPTION + +This methods gets the log using the provided options + +=cut + +#============================================================= + +sub getLog { + my $self = shift; + + my $params = "--no-pager -q"; + if ($self->this_boot == 1) { + $params .= " -b"; + } + if ($self->since ne "") { + $params .= " --since=" . '"' . $self->since . '"'; + } + if ($self->until ne "") { + $params .= " --until=" . '"' . $self->until .'"'; + } + if ($self->unit ne "") { + $params .= " --unit=" . $self->unit; + } + if ($self->priority ne "") { + $params .= " --priority=" . $self->priority; + } + + $ENV{'PATH'} = '/usr/sbin:/usr/bin'; + my $jctl = "/usr/bin/journalctl " . $params; + + # TODO remove or add to log + print " Running " . $jctl . "\n"; + my @content = `$jctl`; + + return \@content; +} + +no Moose; +__PACKAGE__->meta->make_immutable; + + +1; diff --git a/lib/ManaTools/Shared/Locales.pm b/lib/ManaTools/Shared/Locales.pm new file mode 100644 index 0000000..ec54614 --- /dev/null +++ b/lib/ManaTools/Shared/Locales.pm @@ -0,0 +1,280 @@ +# vim: set et ts=4 sw=4: +package ManaTools::Shared::Locales; +#============================================================= -*-perl-*- + +=head1 NAME + +ManaTools::Shared::Locales - Class to manage locales + +=head1 SYNOPSIS + +use ManaTools::Shared::Locales; + +my $obj = ManaTools::Shared::Locales->new(domain_name => 'this_domain'); + +print $obj->N("test string %d", 1) . "\n"; + +=head1 DESCRIPTION + +This class wraps Locale::gettext to manage localization + + +=head1 SUPPORT + +You can find documentation for this module with the perldoc command: + +perldoc ManaTools::Shared::Locales + +=head1 SEE ALSO + +Locale::gettext Text::Iconv and gettext + +=head1 AUTHOR + +Angelo Naselli + +=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 utf8; +use Locale::gettext; +use Text::Iconv; + + +#============================================================= + +=head2 new + +=head3 INPUT + + hash ref containing + domain_name: gettext domain name (default mpan) + dir_name: gettext optional catalog directory (default undef) + codeset: gettext codeset (default UTF8) + +=head3 DESCRIPTION + + new is inherited from Moose, to create a Locales object + +=cut + +#============================================================= + +has 'domain_name' => ( + is => 'rw', + default => 'mpan', +); + +has 'dir_name' => ( + is => 'rw', + default => undef, +); + +has 'codeset' => ( + is => 'rw', + default => 'UTF8', +); + +has 'domain' => ( + is => 'rw', + init_arg => undef, +); + +#============================================================= + +=head2 BUILD + +=head3 INPUT + + $self: this object + +=head3 DESCRIPTION + + The BUILD method is called after a Moose object is created. + This method initilaizes gettext domain. + +=cut + +#============================================================= +sub BUILD { + my $self = shift; + + if ($^V ge v5.20.0) { + require POSIX; + POSIX::setlocale (POSIX::LC_ALL (), ''); + } + + $self->domain(Locale::gettext->domain_raw($self->domain_name)); + $self->domain->dir($self->dir_name) if $self->dir_name; + $self->domain->codeset($self->codeset); +} + + +#============================================================= + +=head2 P + +=head3 INPUT + + $self : this object + $s_singular: msg id singular + $s_plural: msg id plural + $nb: value for plural + +=head3 OUTPUT + + locale string + +=head3 DESCRIPTION + + returns the given string localized (see dngettext) + +=cut + +#============================================================= +sub P { + my ($self, $s_singular, $s_plural, $nb, @para) = @_; + + sprintf($self->domain->nget($s_singular, $s_plural, $nb), @para); +} + +#============================================================= + +=head2 N + +=head3 INPUT + + $self : this object + $s: msg id + +=head3 OUTPUT + + locale string + +=head3 DESCRIPTION + + returns the given string localized (see dgettext) + +=cut + +#============================================================= +sub N { + my ($self, $s, @para) = @_; + + sprintf($self->domain->get($s), @para); +} + +#============================================================= + +=head2 N_ + +=head3 INPUT + + $self : this object + $s: msg id + +=head3 OUTPUT + + msg id + +=head3 DESCRIPTION + + returns the given string + +=cut + +#============================================================= +sub N_ { + my $self = shift; + + $_[0]; +} + + +#============================================================= + +=head2 from_utf8 + +=head3 INPUT + + $self: this object + $s: string to be converted + +=head3 OUTPUT\ + + $converted: converted string + +=head3 DESCRIPTION + + convert from utf-8 to current locale + +=cut + +#============================================================= +sub from_utf8 { + my ($self, $s) = @_; + + my $converter = Text::Iconv->new("utf-8", undef); + my $converted = $converter->convert($s); + + return $converted; +} + + +#============================================================= + +=head2 to_utf8 + +=head3 INPUT + + $self: this object + $s: string to be converted + +=head3 OUTPUT\ + + $converted: converted string + +=head3 DESCRIPTION + + convert to utf-8 from current locale + +=cut + +#============================================================= +sub to_utf8 { + my ($self, $s) = @_; + + my $converter = Text::Iconv->new(undef, "utf-8"); + my $converted = $converter->convert($s); + + return $converted; +} + + + +no Moose; +__PACKAGE__->meta->make_immutable; + + +1; diff --git a/lib/ManaTools/Shared/Proxy.pm b/lib/ManaTools/Shared/Proxy.pm new file mode 100644 index 0000000..6accbb7 --- /dev/null +++ b/lib/ManaTools/Shared/Proxy.pm @@ -0,0 +1,36 @@ +# vim: set et ts=4 sw=4: +#***************************************************************************** +# +# Copyright (c) 2013-2015 Matteo Pasotti +# +# 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::Shared::Proxy; + +use Moose; +use diagnostics; +use utf8; + +has 'network' => ( + is => 'rw', + init_arg => undef, + builder => '_initialize' +); + +sub _initialize { + my $self = shift(); +} + +1; diff --git a/lib/ManaTools/Shared/RunProgram.pm b/lib/ManaTools/Shared/RunProgram.pm new file mode 100644 index 0000000..042f559 --- /dev/null +++ b/lib/ManaTools/Shared/RunProgram.pm @@ -0,0 +1,352 @@ +package ManaTools::Shared::RunProgram; + +use strict; +use MDK::Common; +use Sys::Syslog; +use MDK::Common::File qw(cat_); + +use Exporter; +our @ISA = qw(Exporter); +our @EXPORT_OK = qw( + set_default_timeout + run_or_die + rooted_or_die + get_stdout + get_stdout_raw + rooted_get_stdout + run + raw + rooted +); + +=head1 SYNOPSYS + +B enables to: + +=over 4 + +=item * run programs in foreground or in background, + +=item * to retrieve their stdout or stderr + +=item * ... + +=back + +Most functions exits in a normal form & a rooted one. e.g.: + +=over 4 + +=item * C & C + +=item * C & C + +=back + +Most functions exits in a normal form & one that die. e.g.: + +=over 4 + +=item * C & C + +=item * C & C + +=back + +=head1 Functions + +=over + +=cut + +1; + +my $default_timeout = 10 * 60; + +=item set_default_timeout($seconds) + +Alters defaults timeout (eg for harddrake service) + +=cut + +sub set_default_timeout { + my ($seconds) = @_; + $default_timeout = $seconds; +} + +=item run_or_die($name, @args) + +Runs $name with @args parameterXs. Dies if it exit code is not 0. + +=cut + +sub run_or_die { + my ($name, @args) = @_; + run($name, @args) or die "$name failed\n"; +} + +=item rooted_or_die($root, $name, @args) + +Similar to run_or_die() but runs in chroot in $root + +=cut + +sub rooted_or_die { + my ($root, $name, @args) = @_; + rooted($root, $name, @args) or die "$name failed\n"; +} + +=item get_stdout($name, @args) + +Similar to run_or_die() but return stdout of program: + +=over 4 + +=item * a list of lines in list context + +=item * a string of concatenated lines in scalar context + +=back + +=cut + +sub get_stdout { + my ($name, @args) = @_; + my @r; + run($name, '>', \@r, @args) or return; + wantarray() ? @r : join('', @r); +} + +=item get_stdout_raw($options, $name, @args) + +Similar to get_stdout() but allow to pass options to raw() + +=cut + +sub get_stdout_raw { + my ($options, $name, @args) = @_; + my @r; + raw($options, $name, '>', \@r, @args) or return; + wantarray() ? @r : join('', @r); +} + +=item rooted_get_stdout($root, $name, @args) + +Similar to get_stdout() but runs in chroot in $root + +=cut + +sub rooted_get_stdout { + my ($root, $name, @args) = @_; + my @r; + rooted($root, $name, '>', \@r, @args) or return; + wantarray() ? @r : join('', @r); +} + +=item run($name, @args) + +Runs $name with @args parameters. + +=cut + +sub run { + raw({}, @_); +} + +=item rooted($root, $name, @args) + +Similar to run() but runs in chroot in $root + +=cut + +sub rooted { + my ($root, $name, @args) = @_; + raw({ root => $root }, $name, @args); +} + +=item raw($options, $name, @args) + +The function used by all the other, making every combination possible. +Runs $name with @args parameters. $options is a hash ref that can contains: + +=over 4 + +=item * B: $name will be chrooted in $root prior to run + +=item * B: $name will be run as $ENV{USERHELPER_UID} or with the UID of parent process. Implies I + +=item * B: parameters will be hidden in logs (b/c eg there's a password) + +=item * B: $name will be run in the background. Default is foreground + +=item * B: $name will be run in a different default directory + +=item * B: contains a getpwnam(3) struct ; $name will be with droped privileges ; +make sure environment is set right and keep a copy of the X11 cookie + +=item * B: execution of $name will be aborted after C seconds + +=back + +eg: + +=over 4 + +=item * C<< ManaTools::Shared::RunProgram::raw({ root => $::prefix, sensitive_arguments => 1 }, "echo -e $user->{password} | cryptsetup luksFormat $device"); >> + +=item * C<< ManaTools::Shared::RunProgram::raw({ detach => 1 }, '/etc/rc.d/init.d/dm', '>', '/dev/null', '2>', '/dev/null', 'restart'); >> + +=back + +=cut + +sub raw { + my ($options, $name, @args) = @_; + my $root = $options->{root} || ''; + my $real_name = ref($name) ? $name->[0] : $name; + + my ($stdout_raw, $stdout_mode, $stderr_raw, $stderr_mode); + ($stdout_mode, $stdout_raw, @args) = @args if $args[0] =~ /^>>?$/; + ($stderr_mode, $stderr_raw, @args) = @args if $args[0] =~ /^2>>?$/; + + my $home; + if ($options->{as_user}) { + my $uid; + $uid = $ENV{USERHELPER_UID} && getpwuid($ENV{USERHELPER_UID}); + $uid ||= _get_parent_uid(); + $options->{setuid} = getpwnam($uid) if $uid; + my ($full_user) = grep { $_->[2] eq $uid } list_passwd(); + $home = $full_user->[7] if $full_user; + } + local $ENV{HOME} = $home if $home; + + my $args = $options->{sensitive_arguments} ? '' : join(' ', @args); + Sys::Syslog::syslog('info|local1', "running: $real_name $args" . ($root ? " with root $root" : "")); + + return if $root && $<; + + $root ? ($root .= '/') : ($root = ''); + + my $tmpdir = sub { + my $dir = $< != 0 ? "$ENV{HOME}/tmp" : -d '/root' ? '/root/tmp' : '/tmp'; + -d $dir or mkdir($dir, 0700); + $dir; + }; + my $stdout = $stdout_raw && (ref($stdout_raw) ? $tmpdir->() . "/.drakx-stdout.$$" : "$root$stdout_raw"); + my $stderr = $stderr_raw && (ref($stderr_raw) ? $tmpdir->() . "/.drakx-stderr.$$" : "$root$stderr_raw"); + + #- checking if binary exist to avoid clobbering stdout file + my $rname = $real_name =~ /(.*?)[\s\|]/ ? $1 : $real_name; + if (! ($rname =~ m!^/! + ? -x "$root$rname" || $root && -l "$root$rname" #- handle non-relative symlink which can be broken when non-rooted + : whereis_binary($rname, $root))) { + Sys::Syslog::syslog('warning', "program not found: $real_name"); + + return; + } + + if (my $pid = fork()) { + if ($options->{detach}) { + $pid; + } else { + my $ok; + add2hash_($options, { timeout => $default_timeout }); + eval { + local $SIG{ALRM} = sub { die "ALARM" }; + my $remaining = $options->{timeout} && $options->{timeout} ne 'never' && alarm($options->{timeout}); + waitpid $pid, 0; + $ok = $? == -1 || ($? >> 8) == 0; + alarm $remaining; + }; + if ($@) { + Sys::Syslog::syslog('warning', "ERROR: killing runaway process (process=$real_name, pid=$pid, args=@args, error=$@)"); + kill 9, $pid; + return; + } + + if ($stdout_raw && ref($stdout_raw)) { + if (ref($stdout_raw) eq 'ARRAY') { + @$stdout_raw = cat_($stdout); + } else { + $$stdout_raw = cat_($stdout); + } + unlink $stdout; + } + if ($stderr_raw && ref($stderr_raw)) { + if (ref($stderr_raw) eq 'ARRAY') { + @$stderr_raw = cat_($stderr); + } else { + $$stderr_raw = cat_($stderr); + } + unlink $stderr; + } + $ok; + } + } else { + if ($options->{setuid}) { + require POSIX; + my ($logname, $home) = (getpwuid($options->{setuid}))[0,7]; + $ENV{LOGNAME} = $logname if $logname; + + # if we were root and are going to drop privilege, keep a copy of the X11 cookie: + if (!$> && $home) { + # FIXME: it would be better to remove this but most callers are using 'detach => 1'... + my $xauth = chomp_(`mktemp $home/.Xauthority.XXXXX`); + system('cp', '-a', $ENV{XAUTHORITY}, $xauth); + system('chown', $logname, $xauth); + $ENV{XAUTHORITY} = $xauth; + } + + # drop privileges: + POSIX::setuid($options->{setuid}); + } + + sub _die_exit { + Sys::Syslog::syslog('warning', $_[0]); + POSIX::_exit(128); + } + if ($stderr && $stderr eq 'STDERR') { + } elsif ($stderr) { + $stderr_mode =~ s/2//; + open STDERR, "$stderr_mode $stderr" or _die_exit("ManaTools::Shared::RunProgram cannot output in $stderr (mode `$stderr_mode')"); + } elsif ($::isInstall) { + open STDERR, ">> /tmp/ddebug.log" or open STDOUT, ">> /dev/tty7" or _die_exit("ManaTools::Shared::RunProgram cannot log, give me access to /tmp/ddebug.log"); + } + if ($stdout && $stdout eq 'STDOUT') { + } elsif ($stdout) { + open STDOUT, "$stdout_mode $stdout" or _die_exit("ManaTools::Shared::RunProgram cannot output in $stdout (mode `$stdout_mode')"); + } elsif ($::isInstall) { + open STDOUT, ">> /tmp/ddebug.log" or open STDOUT, ">> /dev/tty7" or _die_exit("ManaTools::Shared::RunProgram cannot log, give me access to /tmp/ddebug.log"); + } + + $root and chroot $root; + chdir($options->{chdir} || "/"); + + my $ok = ref $name ? do { + exec { $name->[0] } $name->[1], @args; + } : do { + exec $name, @args; + }; + if (!$ok) { + _die_exit("exec of $real_name failed: $!"); + } + } + +} + +=item get_parent_uid() + +Returns UID of the parent process. + +=cut + +sub _get_parent_uid() { + cat_('/proc/' . getppid() . '/status') =~ /Uid:\s*(\d+)/ ? $1 : undef; +} + + + +#- Local Variables: +#- mode:cperl +#- tab-width:8 +#- End: diff --git a/lib/ManaTools/Shared/Services.pm b/lib/ManaTools/Shared/Services.pm new file mode 100644 index 0000000..abef8c3 --- /dev/null +++ b/lib/ManaTools/Shared/Services.pm @@ -0,0 +1,955 @@ +# vim: set et ts=4 sw=4: +package ManaTools::Shared::Services; +#============================================================= -*-perl-*- + +=head1 NAME + +ManaTools::Shared::Services - shares the API to manage services + +=head1 SYNOPSIS + +use ManaTools::Shared::Services; + +my $serv = ManaTools::Shared::Services->new(); + +my ($l, $on_services) = $serv->services(); + +=head1 DESCRIPTION + + This module aims to share all the API to manage system services, + to be used from GUI applications or console. + + From the original code drakx services. + +=head1 SUPPORT + +You can find documentation for this module with the perldoc command: + +perldoc ManaTools::Shared::Services + +=head1 SEE ALSO + +ManaTools::Shared + +=head1 AUTHOR + +Angelo Naselli + +=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 FUNCTIONS + +=cut + + +use Moose; + +use Sys::Syslog; +use Net::DBus; +use Net::DBus::Annotation qw(:auth); +use File::Basename; + +use ManaTools::Shared::Locales; +use MDK::Common::Func qw(find); +use MDK::Common::File; +use MDK::Common::DataStructure qw(member); +use ManaTools::Shared::RunProgram qw(rooted); + +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') ); + # TODO if we want to give the opportunity to test locally add dir_name => 'path' +} + + +has 'dbus_systemd1_service' => ( + is => 'rw', + init_arg => undef, + lazy => 1, + builder => '_dbusServiceInitialize' +); + +sub _dbusServiceInitialize { + my $self = shift(); + + my $bus = Net::DBus->system; + $self->dbus_systemd1_service($bus->get_service("org.freedesktop.systemd1")); +} + + +has 'dbus_systemd1_object' => ( + is => 'rw', + init_arg => undef, + lazy => 1, + builder => '_dbusObjectInitialize' +); + +sub _dbusObjectInitialize { + my $self = shift(); + + $self->dbus_systemd1_object($self->dbus_systemd1_service->get_object("/org/freedesktop/systemd1")); +} + + +has 'service_info' => ( + is => 'rw', + traits => ['Hash'], + isa => 'HashRef', + handles => { + set_service_info => 'set', + get_service_info => 'get', + service_info_pairs => 'kv', + }, + init_arg => undef, + lazy => 1, + builder => '_serviceInfoInitialization' +); + +sub _serviceInfoInitialization { + my $self = shift(); + + my %services = (); + if ($self->_running_systemd()) { + my $object = $self->dbus_systemd1_object; + my $properties = $object->ListUnits(); + + foreach my $s (@{$properties}) { + my $name = $s->[0]; + if (index($name, ".service") != -1) { + my $st = eval{$object->GetUnitFileState($name)} if $name !~ /.*\@.*$/g; + $name =~ s|.service||; + if (!$st) { + if ($name !~ /.*\@$/g && + (-e "/usr/lib/systemd/system/$name.service" or -e "/etc/rc.d/init.d/$name") && + ! -l "/usr/lib/systemd/system/$name.service") { + $st = 'enabled'; + } + } + if ($st && $st ne 'static') { + $services{$name} = { + 'name' => $s->[0], + 'description' => $s->[1], + 'load_state' => $s->[2], + 'active_state' => $s->[3], + 'sub_state' => $s->[4], + 'unit_path' => $s->[6], + 'enabled' => $st eq 'enabled', + }; + } + } + } + + my $unit_files = $object->ListUnitFiles(); + foreach my $s (@{$unit_files}) { + my $name = $s->[0]; + my $st = $s->[1]; + if (index($name, ".service") != -1) { + $name = File::Basename::basename($name, ".service"); + if (!$services{$name} && + $name !~ /.*\@$/g && + (-e $s->[0] or -e "/etc/rc.d/init.d/$name") && + ! -l $s->[0] && ($st eq "disabled" || $st eq "enabled")) { + my $wantedby = $self->_WantedBy($s->[0]); + if ($wantedby) { + my $descr = $self->getUnitProperty($name, 'Description'); + + $services{$name} = { + 'name' => $name, + 'description' => $descr, + 'enabled' => $st eq "enabled", + }; + } + } + } + } + } + + return \%services; +} + +#============================================================= + +=head2 description + +=head3 INPUT + +name: Service Name + +=head3 OUTPUT + +Description: Service description + +=head3 DESCRIPTION + +THis function return the description for the given service + +=cut + +#============================================================= +sub description { + my ($self, $name) = @_; + + my %services = ( +acpid => $self->loc->N_("Listen and dispatch ACPI events from the kernel"), +alsa => $self->loc->N_("Launch the ALSA (Advanced Linux Sound Architecture) sound system"), +anacron => $self->loc->N_("Anacron is a periodic command scheduler."), +apmd => $self->loc->N_("apmd is used for monitoring battery status and logging it via syslog. +It can also be used for shutting down the machine when the battery is low."), +atd => $self->loc->N_("Runs commands scheduled by the at command at the time specified when +at was run, and runs batch commands when the load average is low enough."), +'avahi-deamon' => $self->loc->N_("Avahi is a ZeroConf daemon which implements an mDNS stack"), +chronyd => $self->loc->N_("An NTP client/server"), +cpufreq => $self->loc->N_("Set CPU frequency settings"), +crond => $self->loc->N_("cron is a standard UNIX program that runs user-specified programs +at periodic scheduled times. vixie cron adds a number of features to the basic +UNIX cron, including better security and more powerful configuration options."), +cups => $self->loc->N_("Common UNIX Printing System (CUPS) is an advanced printer spooling system"), +dm => $self->loc->N_("Launches the graphical display manager"), +fam => $self->loc->N_("FAM is a file monitoring daemon. It is used to get reports when files change. +It is used by GNOME and KDE"), +g15daemon => $self->loc->N_("G15Daemon allows users access to all extra keys by decoding them and +pushing them back into the kernel via the linux UINPUT driver. This driver must be loaded +before g15daemon can be used for keyboard access. The G15 LCD is also supported. By default, +with no other clients active, g15daemon will display a clock. Client applications and +scripts can access the LCD via a simple API."), +gpm => $self->loc->N_("GPM adds mouse support to text-based Linux applications such the +Midnight Commander. It also allows mouse-based console cut-and-paste operations, +and includes support for pop-up menus on the console."), +haldaemon => $self->loc->N_("HAL is a daemon that collects and maintains information about hardware"), +harddrake => $self->loc->N_("HardDrake runs a hardware probe, and optionally configures +new/changed hardware."), +httpd => $self->loc->N_("Apache is a World Wide Web server. It is used to serve HTML files and CGI."), +inet => $self->loc->N_("The internet superserver daemon (commonly called inetd) starts a +variety of other internet services as needed. It is responsible for starting +many services, including telnet, ftp, rsh, and rlogin. Disabling inetd disables +all of the services it is responsible for."), +ip6tables => $self->loc->N_("Automates a packet filtering firewall with ip6tables"), +iptables => $self->loc->N_("Automates a packet filtering firewall with iptables"), +irqbalance => $self->loc->N_("Evenly distributes IRQ load across multiple CPUs for enhanced performance"), +keytable => $self->loc->N_("This package loads the selected keyboard map as set in +/etc/sysconfig/keyboard. This can be selected using the kbdconfig utility. +You should leave this enabled for most machines."), +kheader => $self->loc->N_("Automatic regeneration of kernel header in /boot for +/usr/include/linux/{autoconf,version}.h"), +kudzu => $self->loc->N_("Automatic detection and configuration of hardware at boot."), +'laptop-mode' => $self->loc->N_("Tweaks system behavior to extend battery life"), +linuxconf => $self->loc->N_("Linuxconf will sometimes arrange to perform various tasks +at boot-time to maintain the system configuration."), +lpd => $self->loc->N_("lpd is the print daemon required for lpr to work properly. It is +basically a server that arbitrates print jobs to printer(s)."), +lvs => $self->loc->N_("Linux Virtual Server, used to build a high-performance and highly +available server."), +mandi => $self->loc->N_("Monitors the network (Interactive Firewall and wireless"), +mdadm => $self->loc->N_("Software RAID monitoring and management"), +messagebus => $self->loc->N_("DBUS is a daemon which broadcasts notifications of system events and other messages"), +msec => $self->loc->N_("Enables MSEC security policy on system startup"), +named => $self->loc->N_("named (BIND) is a Domain Name Server (DNS) that is used to resolve host names to IP addresses."), +netconsole => $self->loc->N_("Initializes network console logging"), +netfs => $self->loc->N_("Mounts and unmounts all Network File System (NFS), SMB (Lan +Manager/Windows), and NCP (NetWare) mount points."), +network => $self->loc->N_("Activates/Deactivates all network interfaces configured to start +at boot time."), +'network-auth' => $self->loc->N_("Requires network to be up if enabled"), +'network-up' => $self->loc->N_("Wait for the hotplugged network to be up"), +nfs => $self->loc->N_("NFS is a popular protocol for file sharing across TCP/IP networks. +This service provides NFS server functionality, which is configured via the +/etc/exports file."), +nfslock => $self->loc->N_("NFS is a popular protocol for file sharing across TCP/IP +networks. This service provides NFS file locking functionality."), +ntpd => $self->loc->N_("Synchronizes system time using the Network Time Protocol (NTP)"), +numlock => $self->loc->N_("Automatically switch on numlock key locker under console +and Xorg at boot."), +oki4daemon => $self->loc->N_("Support the OKI 4w and compatible winprinters."), +partmon => $self->loc->N_("Checks if a partition is close to full up"), +pcmcia => $self->loc->N_("PCMCIA support is usually to support things like ethernet and +modems in laptops. It will not get started unless configured so it is safe to have +it installed on machines that do not need it."), +portmap => $self->loc->N_("The portmapper manages RPC connections, which are used by +protocols such as NFS and NIS. The portmap server must be running on machines +which act as servers for protocols which make use of the RPC mechanism."), +portreserve => $self->loc->N_("Reserves some TCP ports"), +postfix => $self->loc->N_("Postfix is a Mail Transport Agent, which is the program that moves mail from one machine to another."), +random => $self->loc->N_("Saves and restores system entropy pool for higher quality random +number generation."), +rawdevices => $self->loc->N_("Assign raw devices to block devices (such as hard disk drive +partitions), for the use of applications such as Oracle or DVD players"), +resolvconf => $self->loc->N_("Nameserver information manager"), +routed => $self->loc->N_("The routed daemon allows for automatic IP router table updated via +the RIP protocol. While RIP is widely used on small networks, more complex +routing protocols are needed for complex networks."), +rstatd => $self->loc->N_("The rstat protocol allows users on a network to retrieve +performance metrics for any machine on that network."), +rsyslog => $self->loc->N_("Syslog is the facility by which many daemons use to log messages to various system log files. It is a good idea to always run rsyslog."), +rusersd => $self->loc->N_("The rusers protocol allows users on a network to identify who is +logged in on other responding machines."), +rwhod => $self->loc->N_("The rwho protocol lets remote users get a list of all of the users +logged into a machine running the rwho daemon (similar to finger)."), +saned => $self->loc->N_("SANE (Scanner Access Now Easy) enables to access scanners, video cameras, ..."), +shorewall => $self->loc->N_("Packet filtering firewall"), +smb => $self->loc->N_("The SMB/CIFS protocol enables to share access to files & printers and also integrates with a Windows Server domain"), +sound => $self->loc->N_("Launch the sound system on your machine"), +'speech-dispatcherd' => $self->loc->N_("layer for speech analysis"), +sshd => $self->loc->N_("Secure Shell is a network protocol that allows data to be exchanged over a secure channel between two computers"), +syslog => $self->loc->N_("Syslog is the facility by which many daemons use to log messages +to various system log files. It is a good idea to always run syslog."), +'udev-post' => $self->loc->N_("Moves the generated persistent udev rules to /etc/udev/rules.d"), +usb => $self->loc->N_("Load the drivers for your usb devices."), +vnStat => $self->loc->N_("A lightweight network traffic monitor"), +xfs => $self->loc->N_("Starts the X Font Server."), +xinetd => $self->loc->N_("Starts other deamons on demand."), + ); + + my $s = $services{$name}; + if ($s) { + $s = $self->loc->N($s); + } + elsif ($self->get_service_info($name)) { + $s = $self->get_service_info($name)->{description}; + } + else { + my $file = "/usr/lib/systemd/system/$name.service"; + if (-e $file) { + $s = MDK::Common::File::cat_($file); + $s = $s =~ /^Description=(.*)/mg ? $1 : ''; + } else { + $file = MDK::Common::Func::find { -e $_ } map { "$_/$name" } '/etc/rc.d/init.d', '/etc/init.d', '/etc/xinetd.d'; + $s = MDK::Common::File::cat_($file); + $s =~ s/\\\s*\n#\s*//mg; + $s = + $s =~ /^#\s+(?:Short-)?[dD]escription:\s+(.*?)^(?:[^#]|# {0,2}\S)/sm ? $1 : + $s =~ /^#\s*(.*?)^[^#]/sm ? $1 : ''; + + $s =~ s/#\s*//mg; + } + } + $s =~ s/\n/ /gm; $s =~ s/\s+$//; + $s; +} + + +#============================================================= + +=head2 set_service + +=head3 INPUT + + $service: Service name + $enable: enable/disable service + +=head3 DESCRIPTION + + This function enable/disable at boot the given service + +=cut + +#============================================================= +sub set_service { + my ($self, $service, $enable) = @_; + + my @xinetd_services = map { $_->[0] } $self->xinetd_services(); + + if (MDK::Common::DataStructure::member($service, @xinetd_services)) { + $ENV{PATH} = "/usr/bin:/usr/sbin"; + ManaTools::Shared::RunProgram::rooted("", "/usr/sbin/chkconfig", $enable ? "--add" : "--del", $service); + } elsif ($self->_running_systemd() || $self->_has_systemd()) { + $service = $service . ".service"; + my $dbus_object = $self->dbus_systemd1_object; + if ($enable) { + $dbus_object->EnableUnitFiles(dbus_auth_interactive, [$service], 0, 1); + } + else { + $dbus_object->DisableUnitFiles(dbus_auth_interactive, [$service], 0); + } + # reload local cache + $self->_systemd_services(1); + } else { + my $script = "/etc/rc.d/init.d/$service"; + $ENV{PATH} = "/usr/bin:/usr/sbin"; + ManaTools::Shared::RunProgram::rooted("", "/usr/sbin/chkconfig", $enable ? "--add" : "--del", $service); + #- FIXME: handle services with no chkconfig line and with no Default-Start levels in LSB header + if ($enable && MDK::Common::File::cat_("$script") =~ /^#\s+chkconfig:\s+-/m) { + $ENV{PATH} = "/usr/bin:/usr/sbin"; + ManaTools::Shared::RunProgram::rooted("", "/usr/sbin/chkconfig", "--level", "35", $service, "on"); + } + } +} + +sub _run_action { + my ($self, $service, $action) = @_; + if ($self->_running_systemd()) { + my $object = $self->dbus_systemd1_object; + if ($action eq 'start') { + $object->StartUnit(dbus_auth_interactive, "$service.service", 'fail'); + } + elsif ($action eq 'stop') { + $object->StopUnit(dbus_auth_interactive, "$service.service", 'fail'); + } + else { + $object->RestartUnit(dbus_auth_interactive, "$service.service", 'fail'); + } + # reload local cache + $self->_systemd_services(1); + } else { + $ENV{PATH} = "/usr/bin:/usr/sbin:/etc/rc.d/init.d/"; + ManaTools::Shared::RunProgram::rooted("", "/etc/rc.d/init.d/$service", $action); + } +} + +sub _running_systemd { + my $self = shift; + + $ENV{PATH} = "/usr/bin:/usr/sbin"; + ManaTools::Shared::RunProgram::rooted("", '/usr/bin/mountpoint', '-q', '/sys/fs/cgroup/systemd'); +} + +sub _has_systemd { + my $self = shift; + + $ENV{PATH} = "/usr/bin:/usr/sbin"; + ManaTools::Shared::RunProgram::rooted("", '/usr/bin/rpm', '-q', 'systemd'); +} + +#============================================================= + +=head2 xinetd_services + +=head3 OUTPUT + + xinetd_services: All the xinetd services + +=head3 DESCRIPTION + + This functions returns all the xinetd services in the system. + NOTE that xinetd *must* be enable at boot to get this info + +=cut + +#============================================================= +sub xinetd_services { + my $self = shift; + + my @xinetd_services = (); + + #avoid warning if xinetd is not installed and either enabled + my $ser_info = $self->get_service_info('xinetd'); + if ($ser_info && $ser_info->{enabled} eq "1") { + local $ENV{LANGUAGE} = 'C'; + $ENV{PATH} = "/usr/bin:/usr/sbin"; + foreach (ManaTools::Shared::RunProgram::rooted_get_stdout("", '/usr/sbin/chkconfig', '--list', '--type', 'xinetd')) { + if (my ($xinetd_name, $on_off) = m!^\t(\S+):\s*(on|off)!) { + push @xinetd_services, [ $xinetd_name, $on_off eq 'on' ]; + } + } + } + return @xinetd_services; +} + +sub _systemd_services { + my ($self, $reload) = @_; + + if ($reload) { + $self->service_info($self->_serviceInfoInitialization()); + } + + my @services; + for my $pair ( $self->service_info_pairs) { + my $name = $pair->[0]; + my $info = $pair->[1]; + push @services, [$name, $info->{'enabled'}]; + } + + return @services; + +} + +sub _legacy_services { + my $self = shift; + + local $ENV{LANGUAGE} = 'C'; + my @services; + my $has_systemd = $self->_has_systemd(); + if ($has_systemd) { + # The system not using systemd but will be at next boot. This is + # is typically the case in the installer. In this mode we must read + # as much as is practicable from the native systemd unit files and + # combine that with information from chkconfig regarding legacy sysvinit + # scripts (which systemd will parse and include when running) + Sys::Syslog::syslog('info|local1', "Detected systemd installed. Using fake service+chkconfig introspection."); + foreach (glob_("/usr/lib/systemd/system/*.service")) { + my ($name) = m!([^/]*).service$!; + + # We only look at non-template, non-symlinked service files + if (!(/.*\@\.service$/g) && ! -l $_) { + # Limit ourselves to "standard" targets + my $wantedby = MDK::Common::File::cat_($_) =~ /^WantedBy=(graphical|multi-user).target$/sm ? $1 : ''; + if ($wantedby) { + # Exclude if enabled statically + # Note DO NOT use -e when testing for files that could + # be symbolic links as this will fail under a chroot + # setup where -e will fail if the symlink target does + # exist which is typically the case when viewed outside + # of the chroot. + if (!-l "/usr/lib/systemd/system/$wantedby.target.wants/$name.service") { + push @services, [ $name, !!-l "/etc/systemd/system/$wantedby.target.wants/$name.service" ]; + } + } + } + } + } else { + Sys::Syslog::syslog('info|local1', "Could not detect systemd. Using chkconfig service introspection."); + } + + # Regardless of whether we expect to use systemd on next boot, we still + # need to instrospect information about non-systemd native services. + my $runlevel; + my $on_off; + if (!$::isInstall) { + $runlevel = (split " ", `/sbin/runlevel`)[1]; + } + foreach (ManaTools::Shared::RunProgram::rooted_get_stdout("", '/sbin/chkconfig', '--list', '--type', 'sysv')) { + if (my ($name, $l) = m!^(\S+)\s+(0:(on|off).*)!) { + # If we expect to use systemd (i.e. installer) only show those + # sysvinit scripts which are not masked by a native systemd unit. + my $has_systemd_unit = $self->_systemd_unit_exists($name); + if (!$has_systemd || !$has_systemd_unit) { + if ($::isInstall) { + $on_off = $l =~ /\d+:on/g; + } else { + $on_off = $l =~ /$runlevel:on/g; + } + push @services, [ $name, $on_off ]; + } + } + } + @services; +} + +#- returns: +#--- the listref of installed services +#--- the listref of "on" services +#============================================================= + +=head2 services + +=head3 INPUT + + $reload: load service again + +=head3 OUTPUT + + @l: all the system services + @on_services: all the services that start at boot + +=head3 DESCRIPTION + + This function returns two lists, all the system service and + all the active ones. + +=cut + +#============================================================= + + +sub services { + my ($self, $reload) = @_; + + my @Services; + if ($self->_running_systemd()) { + @Services = $self->_systemd_services($reload); + } else { + @Services = $self->_legacy_services(); + } + + my @l = $self->xinetd_services(); + push @l, @Services; + @l = sort { $a->[0] cmp $b->[0] } @l; + [ map { $_->[0] } @l ], [ map { $_->[0] } grep { $_->[1] } @l ]; +} + + +# if we loaded service info, then exists +sub _systemd_unit_exists { + my ($self, $name) = @_; + + return defined ($self->get_service_info($name)); +} + +#============================================================= + +=head2 service_exists + +=head3 INPUT + + $service: Service name + +=head3 OUTPUT + + 0/1: if the service exists + +=head3 DESCRIPTION + + This function checks if a service is installed by looking for + its unit or init.d service + +=cut + +#============================================================= + +sub service_exists { + my ($self, $service) = @_; + $self->_systemd_unit_exists($service) or -x "/etc/rc.d/init.d/$service"; +} + +#============================================================= + +=head2 restart + +=head3 INPUT + + $service: Service to restart + +=head3 DESCRIPTION + + This function restarts a given service + +=cut + +#============================================================= + + +sub restart { + my ($self, $service) = @_; + # Exit silently if the service is not installed + $self->service_exists($service) or return 1; + $self->_run_action($service, "restart"); +} + +#============================================================= + +=head2 restart_or_start + +=head3 INPUT + + $service: Service to restart or start + +=head3 DESCRIPTION + + This function starts a given service if it is not running, + it restarts that otherwise + +=cut + +#============================================================= + +sub restart_or_start { + my ($self, $service) = @_; + # Exit silently if the service is not installed + $self->service_exists($service) or return 1; + $self->_run_action($service, $self->is_service_running($service) ? "restart" : "start"); +} + + +#============================================================= + +=head2 startService + +=head3 INPUT + + $service: Service to start + +=head3 DESCRIPTION + + This function starts a given service + +=cut + +#============================================================= + +sub startService { + my ($self, $service) = @_; + # Exit silently if the service is not installed + $self->service_exists($service) or return 1; + $self->_run_action($service, "start"); +} + +#============================================================= + +=head2 start_not_running_service + +=head3 INPUT + + $service: Service to start + +=head3 DESCRIPTION + + This function starts a given service if not running + +=cut + +#============================================================= + +sub start_not_running_service { + my ($self, $service) = @_; + # Exit silently if the service is not installed + $self->service_exists($service) or return 1; + $self->is_service_running($service) || $self->_run_action($service, "start"); +} + +#============================================================= + +=head2 stopService + +=head3 INPUT + + $service: Service to stop + +=head3 DESCRIPTION + + This function stops a given service + +=cut + +#============================================================= +sub stopService { + my ($self, $service) = @_; + # Exit silently if the service is not installed + $self->service_exists($service) or return 1; + $self->_run_action($service, "stop"); +} + +#============================================================= + +=head2 is_service_running + +=head3 INPUT + + $service: Service to check + +=head3 DESCRIPTION + + This function returns if the given service is running + +=cut + +#============================================================= + +sub is_service_running { + my ($self, $service) = @_; + # Exit silently if the service is not installed + $self->service_exists($service) or return 0; + my $out; + if ($self->_running_systemd()) { + my $ser_info = $self->get_service_info($service); + $out = $ser_info->{active_state} eq 'active' if $ser_info->{active_state}; + } else { + $ENV{PATH} = "/usr/bin:/usr/sbin"; + $out = ManaTools::Shared::RunProgram::rooted("", '/usr/sbin/service', $service, 'status'); + } + return $out; +} + +#============================================================= + +=head2 starts_on_boot + +=head3 INPUT + + $service: Service name + + +=head3 DESCRIPTION + + This function returns if the given service starts at boot + +=cut + +#============================================================= +sub starts_on_boot { + my ($self, $service) = @_; + my (undef, $on_services) = $self->services(); + MDK::Common::DataStructure::member($service, @$on_services); +} + +#============================================================= + +=head2 start_service_on_boot + +=head3 INPUT + + $service: Service name + + +=head3 DESCRIPTION + + This function set the given service active at boot + +=cut + +#============================================================= +sub start_service_on_boot { + my ($self, $service) = @_; + $self->set_service($service, 1); +} + +#============================================================= + +=head2 do_not_start_service_on_boot + +=head3 INPUT + + $service: Service name + + +=head3 DESCRIPTION + + This function set the given service disabled at boot + +=cut + +#============================================================= +sub do_not_start_service_on_boot { + my ($self, $service) = @_; + $self->set_service($service, 0); +} + +#============================================================= + +=head2 enable + +=head3 INPUT + + $service: Service name + $o_dont_apply: do not start it now + +=head3 DESCRIPTION + + This function set the given service active at boot + and restarts it if o_dont_apply is not given + +=cut + +#============================================================= +sub enable { + my ($self, $service, $o_dont_apply) = @_; + $self->start_service_on_boot($service); + $self->restart_or_start($service) unless $o_dont_apply; +} + +#============================================================= + +=head2 disable + +=head3 INPUT + + $service: Service name + $o_dont_apply: do not stop it now + +=head3 DESCRIPTION + + This function set the given service disabled at boot + and stops it if o_dont_apply is not given + +=cut + +#============================================================= +sub disable { + my ($self, $service, $o_dont_apply) = @_; + $self->do_not_start_service_on_boot($service); + $self->stopService($service) unless $o_dont_apply; +} + +#============================================================= + +=head2 set_status + +=head3 INPUT + + $service: Service name + $enable: Enable/disable + $o_dont_apply: do not start it now + +=head3 DESCRIPTION + + This function set the given service to enable/disable at boot + and restarts/stops it if o_dont_apply is not given + +=cut + +#============================================================= +sub set_status { + my ($self, $service, $enable, $o_dont_apply) = @_; + if ($enable) { + $self->enable($service, $o_dont_apply); + } else { + $self->disable($service, $o_dont_apply); + } +} + +# NOTE $service->get_object("/org/freedesktop/systemd1/unit/$name_2eservice"); +# has empty WantedBy property if disabled +sub _WantedBy { + my ($self, $path_service) = @_; + + my $wantedby = MDK::Common::File::cat_($path_service) =~ /^WantedBy=(graphical|multi-user).target$/sm ? $1 : ''; + + return $wantedby; +} + +#============================================================= + +=head2 getUnitProperty + +=head3 INPUT + + $unit: unit name + $property: property name + +=head3 OUTPUT + + $property_value: property value + +=head3 DESCRIPTION + + This method returns the requested property value + +=cut + +#============================================================= +sub getUnitProperty { + my ($self, $unit, $property) = @_; + + my $name = $unit . ".service"; + $name =~ s|-|_2d|g; + $name =~ s|\.|_2e|g; + my $service = $self->dbus_systemd1_service; + my $unit_object = $service->get_object("/org/freedesktop/systemd1/unit/" . $name); + my $property_value = eval {$unit_object->Get("org.freedesktop.systemd1.Unit", $property)} || ""; + + return $property_value; +} + +1; diff --git a/lib/ManaTools/Shared/Shorewall.pm b/lib/ManaTools/Shared/Shorewall.pm new file mode 100644 index 0000000..f82c542 --- /dev/null +++ b/lib/ManaTools/Shared/Shorewall.pm @@ -0,0 +1,271 @@ +package ManaTools::Shared::Shorewall; # $Id: shorewall.pm 254244 2009-03-18 22:54:32Z eugeni $ + +use detect_devices; +use network::network; +use ManaTools::Shared::RunProgram; +use ManaTools::Shared::Services; +use MDK::Common::Func qw(if_ partition map_each); +use MDK::Common::File qw(cat_ substInFile output_with_perm); +use MDK::Common::Various qw(to_bool); +use MDK::Common::DataStructure qw(is_empty_array_ref); +use List::Util qw(any); +use List::MoreUtils qw(uniq); +use log; + +my $shorewall_root = "/etc/shorewall"; + +sub check_iptables() { + -f "$::prefix/etc/sysconfig/iptables" || + $::isStandalone && do { + system('modprobe iptable_nat'); + -x '/sbin/iptables' && listlength(`/sbin/iptables -t nat -nL`) > 8; + }; +} + +sub set_config_file { + my ($file, $ver, @l) = @_; + + my $done; + substInFile { + my $last_line = /^#LAST LINE/ && $_; + if (!$done && ($last_line || eof)) { + $_ = join('', map { join("\t", @$_) . "\n" } @l); + $_ .= $last_line if $last_line; + $done = 1; + } else { + $_ = '' unless + /^#/ || $file eq 'rules' && /^SECTION/; + } + } "$::prefix${shorewall_root}${ver}/$file"; +} + +sub get_config_file { + my ($file, $o_ver) = @_; + map { [ split ' ' ] } grep { !/^#/ } cat_("$::prefix${shorewall_root}${o_ver}/$file"); +} + +# Note: Called from drakguard and drakfirewall.pm... +# Deliberately not adding shorewall6 support here for now +sub set_in_file { + my ($file, $enabled, @list) = @_; + my $done; + substInFile { + my $last_line = /^#LAST LINE/ && $_; + foreach my $l (@list) { s|^$l\n|| } + if (!$done && $enabled && ($last_line || eof)) { + $_ = join('', map { "$_\n" } @list); + $_ .= $last_line if $last_line; + $done = 1; + } + } "$::prefix${shorewall_root}/$file"; +} + +sub dev_to_shorewall { + my ($dev) = @_; + $dev =~ /^ippp/ && "ippp+" || + $dev =~ /^ppp/ && "ppp+" || + $dev; +} + +sub get_net_zone_interfaces { + my ($interfacesfile, $_net, $all_intf) = @_; + if(ref($interfacesfile) eq "ARRAY") + { + #- read shorewall configuration first + my @interfaces = map { $_->[1] } grep { $_->[0] eq 'net' } $interfacesfile; + } + else + { + my @interfaces = undef; + } + #- else try to find the best interface available + @interfaces ? @interfaces : @{$all_intf || []}; +} + +sub add_interface_to_net_zone { + my ($conf, $interface) = @_; + if (!member($interface, @{$conf->{net_zone}})) { + push @{$conf->{net_zone}}, $interface; + @{$conf->{loc_zone}} = grep { $_ ne $interface } @{$conf->{loc_zone}}; + } +} + +sub read_ { + my ($o_ver) = @_; + my $ver = ''; + $ver = $o_ver if $o_ver; + #- read old rules file if config is not moved to rules.drakx yet + my @rules = get_config_file(-f "$::prefix${shorewall_root}${ver}/rules.drakx" ? 'rules.drakx' : 'rules', $ver); + my $services = ManaTools::Shared::Services->new(); + my %conf = (disabled => !$services->starts_on_boot("shorewall${ver}"), + version => $ver, + ports => join(' ', map { + my $e = $_; + map { "$_/$e->[3]" } split(',', $e->[4]); + } grep { $_->[0] eq 'ACCEPT' && $_->[1] eq 'net' } @rules), + ); + push @{$conf{accept_local_users}{$_->[4]}}, $_->[8] foreach grep { $_->[0] eq 'ACCEPT+' } @rules; + $conf{redirects}{$_->[3]}{$_->[4]} = $_->[2] foreach grep { $_->[0] eq 'REDIRECT' } @rules; + + if (my ($e) = get_config_file('masq', $ver)) { + ($conf{masq}{net_interface}, $conf{masq}{subnet}) = @$e; + } + + my @policy = get_config_file('policy', $ver); + $conf{log_net_drop} = @policy ? (any { $_->[0] eq 'net' && $_->[1] eq 'all' && $_->[2] eq 'DROP' && $_->[3] } @policy) : 1; + + return \%conf; + + # get_zones has been moved to ManaTools::Module::Firewall cause it requires + # user interaction thus it should be logically separated by shorewall + # get_zones(\%conf); + # get_config_file('zones', $ver) && \%conf; + # consequently, to read shorewall conf + # you have to do something like this now (within Module::Firewall) + # my $conf = ManaTools::Shared::Shorewall::read_(); + # OPTIONAL: my $self->get_zones(\$conf) + # my $shorewall = ManaTools::Shared::Shorewall::get_config_file('zones', '') && $conf; +} + +sub ports_by_proto { + my ($ports) = @_; + my %ports_by_proto; + foreach (split ' ', $ports) { + m!^(\d+(?::\d+)?)/(udp|tcp|icmp)$! or die "bad port $_\n"; + push @{$ports_by_proto{$2}}, $1; + } + \%ports_by_proto; +} + +#============================================================= + +=head2 write_ + +=head3 INPUT + + $conf: HASH, contains the configuration to write + + $action: Str, possible values are "keep" or "drop" + +=head3 OUTPUT + + 0: requires user interaction + 1: everything has been done + +=head3 DESCRIPTION + +This function stores the configuration for shorewall inside +the proper files. + +=head3 NOTES + +if write_ is called without the $action parameter it can return 0 +(i.e. user interaction requested) when the firewall configuration +has been manually changed. + +In that case the developer will have to handle this request by providing +two choices within the domain (keep | drop) and then recall write_ with +the choosen behaviour. + +=cut + +#============================================================= + +sub write_ { + my ($conf, $action) = @_; + my $ver = $conf->{version} || ''; + my $use_pptp = any { /^ppp/ && cat_("$::prefix/etc/ppp/peers/$_") =~ /pptp/ } @{$conf->{net_zone}}; + my $ports_by_proto = ports_by_proto($conf->{ports}); + my $has_loc_zone = to_bool(@{$conf->{loc_zone} || []}); + + my ($include_drakx, $other_rules) = partition { $_ eq "INCLUDE\trules.drakx\n" } grep { !/^(#|SECTION)/ } cat_("$::prefix${shorewall_root}${ver}/rules"); + #- warn if the config is already in rules.drakx and additionnal rules are configured + if (!is_empty_array_ref($include_drakx) && !is_empty_array_ref($other_rules)) { + if(!defined($action) || ManaTools::Shared::trim($action) eq "") + { + return 0; # user interaction requested + } + my %actions = ( + keep => N("Keep custom rules"), + drop => N("Drop custom rules"), + ); + #- reset the rules files if the user has chosen to drop modifications + undef $include_drakx if $action eq 'drop'; + } + + my $interface_settings = sub { + my ($zone, $interface) = @_; + [ $zone, $interface, 'detect', if_(detect_devices::is_bridge_interface($interface), 'bridge') ]; + }; + + set_config_file('zones', $ver, + if_($has_loc_zone, [ 'loc', 'ipv' . ($ver || '4') ]), + [ 'net', 'ipv' . ($ver || '4') ], + [ 'fw', 'firewall' ], + ); + set_config_file('interfaces', $ver, + (map { $interface_settings->('net', $_) } @{$conf->{net_zone}}), + (map { $interface_settings->('loc', $_) } @{$conf->{loc_zone} || []}), + ); + set_config_file('policy', $ver, + if_($has_loc_zone, [ 'loc', 'net', 'ACCEPT' ], [ 'loc', 'fw', 'ACCEPT' ], [ 'fw', 'loc', 'ACCEPT' ]), + [ 'fw', 'net', 'ACCEPT' ], + [ 'net', 'all', 'DROP', if_($conf->{log_net_drop}, 'info') ], + [ 'all', 'all', 'REJECT', 'info' ], + ); + if (is_empty_array_ref($include_drakx)) { + #- make sure the rules.drakx config is read, erasing user modifications + set_config_file('rules', $ver, [ 'INCLUDE', 'rules.drakx' ]); + } + output_with_perm("$::prefix${shorewall_root}${ver}/" . 'rules.drakx', 0600, map { join("\t", @$_) . "\n" } ( + if_($use_pptp, [ 'ACCEPT', 'fw', 'loc:10.0.0.138', 'tcp', '1723' ]), + if_($use_pptp, [ 'ACCEPT', 'fw', 'loc:10.0.0.138', 'gre' ]), + (map_each { [ 'ACCEPT', 'net', 'fw', $::a, join(',', @$::b), '-' ] } %$ports_by_proto), + (map_each { + if_($::b, map { [ 'ACCEPT+', 'fw', 'net', 'tcp', $::a, '-', '-', '-', $_ ] } @$::b); + } %{$conf->{accept_local_users}}), + (map { + my $proto = $_; + #- WARNING: won't redirect ports from the firewall system if a local zone exists + #- set redirect_fw_only to workaround + map_each { + map { [ 'REDIRECT', $_, $::b, $proto, $::a, '-' ] } 'fw', if_($has_loc_zone, 'loc'); + } %{$conf->{redirects}{$proto}}; + } keys %{$conf->{redirects}}), + )); + set_config_file('masq', $ver, if_(exists $conf->{masq}, [ $conf->{masq}{net_interface}, $conf->{masq}{subnet} ])); + + my $services = ManaTools::Shared::Services->new(); + if ($conf->{disabled}) { + $services->disable('shorewall', $::isInstall); + run_program::rooted($::prefix, '/sbin/shorewall', 'clear') unless $::isInstall; + } else { + $services->enable('shorewall', $::isInstall); + } + return 1; +} + +sub set_redirected_ports { + my ($conf, $proto, $dest, @ports) = @_; + if (@ports) { + $conf->{redirects}{$proto}{$_} = $dest foreach @ports; + } else { + my $r = $conf->{redirects}{$proto}; + @ports = grep { $r->{$_} eq $dest } keys %$r; + delete $r->{$_} foreach @ports; + } +} + +sub update_interfaces_list { + my ($o_intf) = @_; + if (!$o_intf || !member($o_intf, map { $_->[1] } get_config_file('interfaces'))) { + my $shorewall = ManaTools::Shared::Shorewall::read_(); + $shorewall && !$shorewall->{disabled} and ManaTools::Shared::Shorewall::write_($shorewall); + } + if (!$o_intf || !member($o_intf, map { $_->[1] } get_config_file('interfaces', 6))) { + my $shorewall6 = ManaTools::Shared::Shorewall::read_(undef, 6); + $shorewall6 && !$shorewall6->{disabled} and ManaTools::Shared::Shorewall::write_($shorewall6); + } +} + +1; diff --git a/lib/ManaTools/Shared/TimeZone.pm b/lib/ManaTools/Shared/TimeZone.pm new file mode 100644 index 0000000..efb49a2 --- /dev/null +++ b/lib/ManaTools/Shared/TimeZone.pm @@ -0,0 +1,799 @@ +# vim: set et ts=4 sw=4: +package ManaTools::Shared::TimeZone; + +#============================================================= -*-perl-*- + +=head1 NAME + +ManaTools::Shared::TimeZone - module to manage TimeZone settings + +=head1 SYNOPSIS + + my $tz = ManaTools::Shared::TimeZone->new(); + + +=head1 DESCRIPTION + +This module allows to manage time zone settings. + +=head1 SUPPORT + +You can find documentation for this module with the perldoc command: + +perldoc ManaTools::Shared::TimeZone + + +=head1 AUTHOR + +Angelo Naselli + +=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 METHODS + +=cut + + +use diagnostics; +use strict; + +use Moose; + +use DateTime::TimeZone; +use Net::DBus; + +use ManaTools::Shared::Locales; +use ManaTools::Shared::Services; + +use MDK::Common::File qw(cat_ output_p substInFile); +use MDK::Common::Func qw(find if_); + + +#============================================================= + +=head2 new - optional parameters + +=head3 timezone_prefix + + optional parameter to set the system timezone directory, + default value is /usr/share/zoneinfo + +=cut + +#============================================================= + +has 'timezone_prefix' => ( + is => 'rw', + isa => 'Str', + default => "/usr/share/zoneinfo", +); + + +#============================================================= + +=head2 new - optional parameters + +=head3 ntp_configuration_file + + optional parameter to set the ntp server configuration file, + default value is /etc/[chrony|ntp].conf + +=cut + +#============================================================= + +has 'ntp_configuration_file' => ( + is => 'rw', + isa => 'Str', + builder => '_ntp_configuration_file_init', +); + +sub _ntp_configuration_file_init { + my $self = shift; + + if (-f "/etc/chrony.conf") { + return "/etc/chrony.conf"; + } + return "/etc/ntp.conf"; +} + +#============================================================= + +=head2 new - optional parameters + +=head3 ntp_conf_dir + + optional parameter to set ntp configuration directory, + default value is /etc/ntp + +=cut + +#============================================================= + +has 'ntp_conf_dir' => ( + is => 'rw', + isa => 'Str', + lazy => 1, + default => "/etc/ntp", +); + +#============================================================= + +=head2 new - optional parameters + +=head3 ntp_program + + optional parameter to set the ntp program that runs into the + system, default value is [chrony|ntp] + +=cut + +#============================================================= +has 'ntp_program' => ( + is => 'rw', + isa => 'Str', + builder => '_ntp_program_init', +); + +sub _ntp_program_init { + my $self = shift; + + if (-f "/etc/chrony.conf") { + return "chrony"; + } + return "ntp"; +} + +#============================================================= + +=head2 new - optional parameters + +=head3 installer_or_livecd + + To inform the back-end that is working during installer or + livecd. Useful if Time zone setting and using fix_system + to use the real time clock (see setLocalRTC and + writeConfiguration). + +=cut + +#============================================================= +has 'installer_or_livecd' => ( + is => 'rw', + isa => 'Bool', + default => 0, +); + +#=== globals === + +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 'dbus_timedate1_service' => ( + is => 'rw', + init_arg => undef, + lazy => 1, + builder => '_dbusTimeDateInitialize' +); + +sub _dbusTimeDateInitialize { + my $self = shift(); + + my $bus = Net::DBus->system; + $self->dbus_timedate1_service($bus->get_service("org.freedesktop.timedate1")); +} + + +has 'dbus_timedate1_object' => ( + is => 'rw', + init_arg => undef, + lazy => 1, + builder => '_dbusObjectInitialize' +); + +sub _dbusObjectInitialize { + my $self = shift(); + + $self->dbus_timedate1_object($self->dbus_timedate1_service->get_object("/org/freedesktop/timedate1")); +} + + +has 'servername_config_suffix' => ( + is => 'ro', + isa => 'Str', + lazy => 1, + builder => '_servername_config_suffix_init', +); + +sub _servername_config_suffix_init { + my $self = shift; + + return " iburst" if ($self->ntp_program eq "chrony"); + + return ""; +} + +has 'loc' => ( + is => 'rw', + lazy => 1, + 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') ); + # TODO if we want to give the opportunity to test locally add dir_name => 'path' +} + + +has 'ntp_servers' => ( + traits => ['Hash'], + is => 'rw', + isa => 'HashRef', + lazy => 1, + handles => { + get_ntp_server => 'get', + ntp_server_pairs => 'kv', + }, + init_arg => undef, + builder => '_buildNTPServers' +); + +sub _buildNTPServers { + my $self = shift; + + my %ntpServersHash; + $ntpServersHash{"-"} = { + $self->loc->N_("Global") => "pool.ntp.org", + }; + $ntpServersHash{Global} = { + $self->loc->N_("Africa") => "africa.pool.ntp.org", + $self->loc->N_("Asia") => "asia.pool.ntp.org", + $self->loc->N_("Europe") => "europe.pool.ntp.org", + $self->loc->N_("North America") => "north-america.pool.ntp.org", + $self->loc->N_("Oceania") => "oceania.pool.ntp.org", + $self->loc->N_("South America") => "south-america.pool.ntp.org", + }; + $ntpServersHash{Africa} = { + $self->loc->N_("South Africa") => "za.pool.ntp.org", + $self->loc->N_("Tanzania") => "tz.pool.ntp.org", + }; + $ntpServersHash{Asia} = { + $self->loc->N_("Bangladesh") => "bd.pool.ntp.org", + $self->loc->N_("China") => "cn.pool.ntp.org", + $self->loc->N_("Hong Kong") => "hk.pool.ntp.org", + $self->loc->N_("India") => "in.pool.ntp.org", + $self->loc->N_("Indonesia") => "id.pool.ntp.org", + $self->loc->N_("Iran") => "ir.pool.ntp.org", + $self->loc->N_("Israel") => "il.pool.ntp.org", + $self->loc->N_("Japan") => "jp.pool.ntp.org", + $self->loc->N_("Korea") => "kr.pool.ntp.org", + $self->loc->N_("Malaysia") => "my.pool.ntp.org", + $self->loc->N_("Philippines") => "ph.pool.ntp.org", + $self->loc->N_("Singapore") => "sg.pool.ntp.org", + $self->loc->N_("Taiwan") => "tw.pool.ntp.org", + $self->loc->N_("Thailand") => "th.pool.ntp.org", + $self->loc->N_("Turkey") => "tr.pool.ntp.org", + $self->loc->N_("United Arab Emirates") => "ae.pool.ntp.org", + }; + $ntpServersHash{Europe} = { + $self->loc->N_("Austria") => "at.pool.ntp.org", + $self->loc->N_("Belarus") => "by.pool.ntp.org", + $self->loc->N_("Belgium") => "be.pool.ntp.org", + $self->loc->N_("Bulgaria") => "bg.pool.ntp.org", + $self->loc->N_("Czech Republic") => "cz.pool.ntp.org", + $self->loc->N_("Denmark") => "dk.pool.ntp.org", + $self->loc->N_("Estonia") => "ee.pool.ntp.org", + $self->loc->N_("Finland") => "fi.pool.ntp.org", + $self->loc->N_("France") => "fr.pool.ntp.org", + $self->loc->N_("Germany") => "de.pool.ntp.org", + $self->loc->N_("Greece") => "gr.pool.ntp.org", + $self->loc->N_("Hungary") => "hu.pool.ntp.org", + $self->loc->N_("Ireland") => "ie.pool.ntp.org", + $self->loc->N_("Italy") => "it.pool.ntp.org", + $self->loc->N_("Lithuania") => "lt.pool.ntp.org", + $self->loc->N_("Luxembourg") => "lu.pool.ntp.org", + $self->loc->N_("Netherlands") => "nl.pool.ntp.org", + $self->loc->N_("Norway") => "no.pool.ntp.org", + $self->loc->N_("Poland") => "pl.pool.ntp.org", + $self->loc->N_("Portugal") => "pt.pool.ntp.org", + $self->loc->N_("Romania") => "ro.pool.ntp.org", + $self->loc->N_("Russian Federation") => "ru.pool.ntp.org", + $self->loc->N_("Slovakia") => "sk.pool.ntp.org", + $self->loc->N_("Slovenia") => "si.pool.ntp.org", + $self->loc->N_("Spain") => "es.pool.ntp.org", + $self->loc->N_("Sweden") => "se.pool.ntp.org", + $self->loc->N_("Switzerland") => "ch.pool.ntp.org", + $self->loc->N_("Ukraine") => "ua.pool.ntp.org", + $self->loc->N_("United Kingdom") => "uk.pool.ntp.org", + $self->loc->N_("Yugoslavia") => "yu.pool.ntp.org", + }; + $ntpServersHash{"North America"} = { + $self->loc->N_("Canada") => "ca.pool.ntp.org", + $self->loc->N_("Guatemala") => "gt.pool.ntp.org", + $self->loc->N_("Mexico") => "mx.pool.ntp.org", + $self->loc->N_("United States") => "us.pool.ntp.org", + }; + $ntpServersHash{Oceania} = { + $self->loc->N_("Australia") => "au.pool.ntp.org", + $self->loc->N_("New Zealand") => "nz.pool.ntp.org", + }; + $ntpServersHash{"South America"} = { + $self->loc->N_("Argentina") => "ar.pool.ntp.org", + $self->loc->N_("Brazil") => "br.pool.ntp.org", + $self->loc->N_("Chile") => "cl.pool.ntp.org", + }; + + return \%ntpServersHash; +} + + +#============================================================= + +=head2 get_timezone_prefix + +=head3 OUTPUT + +timezone_prefix: directory in which time zone files are + +=head3 DESCRIPTION + +Return the timezone directory (defualt: /usr/share/zoneinfo) + +=cut + +#============================================================= +sub get_timezone_prefix { + my $self = shift; + + return $self->timezone_prefix; +} + +#============================================================= + +=head2 getTimeZones + +=head3 INPUT + + $from_system: if present and its value is not 0 checks into timezone_prefix + directory and gets the list from there + +=head3 OUTPUT + + @l: ARRAY containing sorted time zones + +=head3 DESCRIPTION + + This method returns the available timezones + +=cut + +#============================================================= +sub getTimeZones { + my ($self, $from_system) = @_; + + if ($from_system and $from_system != 0) { + require MDK::Common::DataStructure; + require MDK::Common::Various; + my $tz_prefix = $self->get_timezone_prefix(); + open(my $F, "cd $tz_prefix && find [A-Z]* -noleaf -type f |"); + my @l = MDK::Common::DataStructure::difference2([ MDK::Common::Various::chomp_(<$F>) ], [ 'ROC', 'PRC' ]); + close $F or die "cannot list the available zoneinfos"; + return sort @l; + } + + return DateTime::TimeZone->all_names; +} + +#============================================================= + +=head2 setTimeZone + +=head3 INPUT + + $new_time_zone: New time zone to be set + +=head3 DESCRIPTION + + This method get the new time zone to set and performs + the setting + +=cut + +#============================================================= +sub setTimeZone { + my ($self, $new_time_zone) = @_; + + die "Time zone value required" if !defined($new_time_zone); + + my $object = $self->dbus_timedate1_object; + $object->SetTimezone($new_time_zone, 1); +} + +#============================================================= + +=head2 getTimeZone + +=head3 OUTPUT + + $timezone: current time zone + +=head3 DESCRIPTION + + This method returns the current timezone setting + +=cut + +#============================================================= +sub getTimeZone { + my ($self) = @_; + + my $object = $self->dbus_timedate1_object; + + return $object->Get("org.freedesktop.timedate1", 'Timezone') || ""; +} + + +#============================================================= + +=head2 setLocalRTC + +=head3 INPUT + + $enable: bool value enable/disable real time clock as + localtime + $fix_system: bool read or not the real time clock + +=head3 DESCRIPTION + + This method enables/disables the real time clock as + localtime (e.g. disable means set the rtc to UTC). + NOTE from dbus: + Use SetLocalRTC() to control whether the RTC is in + local time or UTC. It is strongly recommended to maintain + the RTC in UTC. Some OSes (Windows) however maintain the + RTC in local time which might make it necessary to enable + this feature. However, this creates various problems as + daylight changes might be missed. If fix_system is passed + "true" the time from the RTC is read again and the system + clock adjusted according to the new setting. + If fix_system is passed "false" the system time is written + to the RTC taking the new setting into account. + Use fix_system=true in installers and livecds where the + RTC is probably more reliable than the system time. + Use fix_system=false in configuration UIs that are run during + normal operation and where the system clock is probably more + reliable than the RTC. + +=cut + +#============================================================= +sub setLocalRTC { + my ($self, $enable, $fix_system) = @_; + + die "Localtime enable/disable value required" if !defined($enable); + + $fix_system = 0 if !defined($fix_system); + my $object = $self->dbus_timedate1_object; + $object->SetLocalRTC($enable, $fix_system, 1) ; +} + +#============================================================= + +=head2 getLocalRTC + +=head3 OUTPUT + + $localRTC: 1 if RTC is localtime 0 for UTC + +=head3 DESCRIPTION + + This method returns the RTC localtime setting + +=cut + +#============================================================= +sub getLocalRTC { + my $self = shift; + + my $object = $self->dbus_timedate1_object; + + return $object->Get("org.freedesktop.timedate1", 'LocalRTC') ? 1 : 0; +} + + +#============================================================= + +=head2 setTime + +=head3 INPUT + + $sec_since_epoch: Time in seconds since 1/1/1970 + +=head3 DESCRIPTION + + This method set the system time and sets the RTC also + +=cut + +#============================================================= +sub setTime { + my ($self, $sec_since_epoch) = @_; + + die "second since epoch required" if !defined($sec_since_epoch); + + my $object = $self->dbus_timedate1_object; + my $usec = $sec_since_epoch* 1000000; + + $object->SetTime($usec, 0, 1); +} + +#============================================================= + +=head2 readConfiguration + +=head3 OUTPUT + + hash reference containing: + UTC => HW clock is set as UTC + ZONE => Time Zone set + +=head3 DESCRIPTION + + This method returns the time zone system settings as hash + reference + +=cut + +#============================================================= +sub readConfiguration { + my $self = shift; + + my $prefs = {}; + $prefs->{'ZONE'} = $self->getTimeZone(); + $prefs->{'UTC'} = $self->getLocalRTC() ? 0 : 1; + + return $prefs; +} + + +#============================================================= + +=head2 writeConfiguration + +=head3 INPUT + + $info: hash containing: + UTC => HW clock is set as UTC + ZONE => Time Zone + +=head3 DESCRIPTION + + This method sets the passed Time Zone configuration. + If installer_or_livecd attribute is set fix_system is + passed to setLocalRTC + +=cut + +#============================================================= +sub writeConfiguration { + my ($self, $info) = @_; + + die "UTC field required" if !defined($info->{UTC}); + die "ZONE field required" if !defined($info->{ZONE}); + + my $localRTC = $info->{UTC} ? 0 : 1; + $self->setLocalRTC( + $localRTC, + $self->installer_or_livecd + ); + + $self->setTimeZone( + $info->{ZONE} + ); +} + + +#left for back compatibility +sub _get_ntp_server_tree { + my ($self, $zone) = @_; + $zone = "-" if ! $zone; + my $ns = $self->get_ntp_server($zone); + return if !$ns; + + map { + $ns->{$_} => ( + $self->get_ntp_server($_) ? + $zone ? + $self->loc->N($_) . "|" . $self->loc->N("All servers") : + $self->loc->N("All servers") : + $self->loc->N($zone) . "|" . $self->loc->N($_) + ), + $self->_get_ntp_server_tree($_) + } keys %{$ns}; +} + +#============================================================= + +=head2 ntpServers + +=head3 OUTPUT + + HASHREF containing ntp_server => zone info + +=head3 DESCRIPTION + + This method returns an hash ref containing pairs ntp-server, zone + +=cut + +#============================================================= +sub ntpServers { + my ($self) = @_; + # FIXME: missing parameter: + +{$self->_get_ntp_server_tree()}; +} + + +#============================================================= + +=head2 ntpCurrentServer + +=head3 INPUT + +Input_Parameter: in_par_description + +=head3 DESCRIPTION + +Returns the current ntp server address read from configuration file + +=cut + +#============================================================= + +sub ntpCurrentServer { + my $self = shift; + + MDK::Common::Func::find { $_ ne '127.127.1.0' } map { MDK::Common::Func::if_(/^\s*server\s+(\S*)/, $1) } MDK::Common::File::cat_($self->ntp_configuration_file); +} + +#============================================================= + +=head2 isNTPRunning + +=head3 DESCRIPTION + + This method just returns if the given ntp server is running + +=cut + +#============================================================= +sub isNTPRunning { + my $self = shift; + + # TODO is that valid for any ntp program? adding ntp_service_name parameter + my $ntpd = $self->ntp_program . 'd'; + + return $self->sh_services->is_service_running($ntpd); +} + +#============================================================= + +=head2 setNTPServer + +=head3 INPUT + +$server: server address to be configured + +=head3 DESCRIPTION + +This method writes into NTP configuration file new server address +settings + +=cut + +#============================================================= +sub setNTPServer { + my ($self, $server) = @_; + + my $f = $self->ntp_configuration_file; + -f $f or return; + return if (!$server); + + # TODO is that valid for any ntp program? adding ntp_service_name parameter + my $ntpd = $self->ntp_program . 'd'; + + ManaTools::Shared::disable_x_screensaver(); + if ($self->isNTPRunning()) { + $self->sh_services->stopService($ntpd); + } + + my $pool_match = qr/\.pool\.ntp\.org$/; + my @servers = $server =~ $pool_match ? (map { "$_.$server" } 0 .. 2) : $server; + + my $added = 0; + my $servername_config_suffix = $self->servername_config_suffix ? $self->servername_config_suffix : " "; + MDK::Common::File::substInFile { + if (/^#?\s*server\s+(\S*)/ && $1 ne '127.127.1.0') { + $_ = $added ? $_ =~ $pool_match ? undef : "#server $1\n" : join('', map { "server $_$servername_config_suffix\n" } @servers); + $added = 1; + } + } $f; + if ($self->ntp_program eq "ntp") { + my $ntp_prefix = $self->ntp_conf_dir; + MDK::Common::File::output_p("$ntp_prefix/step-tickers", join('', map { "$_\n" } @servers)); + } + + # enable but do not start the service + $self->sh_services->set_status($ntpd, 1, 1); + if ($ntpd eq "chronyd") { + $self->sh_services->startService($ntpd); + $ENV{PATH} = "/usr/bin:/usr/sbin"; + # Wait up to 30s for sync + system('/usr/bin/chronyc', 'waitsync', '30', '0.1'); + } else { + $ENV{PATH} = "/usr/bin:/usr/sbin"; + system('/usr/sbin/ntpdate', $server); + $self->sh_services->startService($ntpd); + } + + ManaTools::Shared::enable_x_screensaver(); +} + +#============================================================= + +=head2 disableAndStopNTP + +=head3 DESCRIPTION + + Disable and stop the ntp server + +=cut + +#============================================================= +sub disableAndStopNTP { + my $self = shift; + + # TODO is that valid for any ntp program? adding ntp_service_name parameter + my $ntpd = $self->ntp_program . 'd'; + + # also stop the service without dont_apply parameter + $self->sh_services->set_status($ntpd, 0); +} + +no Moose; +__PACKAGE__->meta->make_immutable; + + +1; + + diff --git a/lib/ManaTools/Shared/Users.pm b/lib/ManaTools/Shared/Users.pm new file mode 100644 index 0000000..83c6061 --- /dev/null +++ b/lib/ManaTools/Shared/Users.pm @@ -0,0 +1,1612 @@ +# vim: set et ts=4 sw=4: +package ManaTools::Shared::Users; +#============================================================= -*-perl-*- + +=head1 NAME + +ManaTools::Shared::Users - backend to manage users + +=head1 SYNOPSIS + + my $userBackEnd = ManaTools::Shared::Users->new(); + my $userInfo = $userManager->getUserInfo('username'); + +=head1 DESCRIPTION + +This module gives a low level access to the system user management it uses libUSER module. + + +=head1 SUPPORT + +You can find documentation for this module with the perldoc command: + +perldoc ManaTools::Shared::Users + +=head1 SEE ALSO + +libUSER + +=head1 AUTHOR + +Angelo Naselli + +=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 METHODS + +=cut + +use Moose; +use diagnostics; + +use Config::Auto; +use Data::Password::Meter; +use IO::All; +use File::Basename; +use File::Copy; +use File::Remove 'remove'; + +## USER is from userdrake +use USER; +use English; +use POSIX qw/ceil/; + +use ManaTools::Shared::Locales; +use ManaTools::Shared; + + +#============================================================= + +=head2 new - optional parameters + +=head3 face_dir + + optional parameter to set the system face icon directory, + default value is /usr/share/mga/faces/ + +=cut + +#============================================================= + +has 'face_dir' => ( + is => 'rw', + isa => 'Str', + default => "/usr/share/mga/faces/", +); + +#============================================================= + +=head2 new - optional parameters + +=head3 user_face_dir + + optional parameter to set the user face icon directory, + default value is /usr/share/mga/faces/ + +=cut + +#============================================================= +has 'user_face_dir' => ( + is => 'rw', + isa => 'Str', + default => "/usr/share/faces/", +); + + +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' +} + +## Used by USER (for getting values? TODO need explanations, where?) +has 'USER_GetValue' => ( + default => -65533, + is => 'ro', + isa => 'Int', + init_arg => undef, +); + +## Used by USER (for getting values? TODO need explanations, where?) +has 'ctx' => ( + is => 'ro', + init_arg => undef, + builder => '_USERInitialize', +); + +sub _USERInitialize { + my $self = shift; + + # $EUID: effective user identifier + if ($EUID == 0) { + return USER::ADMIN->new; + } + + return undef; +} + +## min (custom) UID was 500 now is 1000, let's change in a single point +has 'min_UID' => ( + default => 1000, + is => 'ro', + isa => 'Int', + init_arg => undef, +); + +## min (custom) GID was 500 now should be 1000 as for users +has 'min_GID' => ( + default => 1000, + is => 'ro', + isa => 'Int', + init_arg => undef, +); + +#============================================================= + +=head2 BUILD + +=head3 INPUT + + $self: this object + +=head3 DESCRIPTION + + The BUILD method is called after a Moose object is created, + Into this method new optional parameters are tested once, + instead of into any other methods. + +=cut + +#============================================================= +sub BUILD { + my $self = shift; + + die "Missing face directory" if (! -d $self->face_dir); + die "Missing user face directory" if (! -d $self->user_face_dir); + + $self->face_dir($self->face_dir . "/") if (substr($self->face_dir, -1) ne "/"); + $self->user_face_dir($self->user_face_dir . "/") if (substr($self->user_face_dir, -1) ne "/"); + +} + + +=head2 facedir + +=head3 OUTPUT + + path to directory containing face icon + +=head3 DESCRIPTION + + Return the directory containing face icons. + +=cut + +#============================================================= + +sub facedir { + my $self = shift; + + return $self->face_dir; +} + + +#============================================================= + +=head2 userfacedir + +=head3 OUTPUT + + path to directory containing user face icons + +=head3 DESCRIPTION + + Return the directory containing user face icons. + +=cut + +#============================================================= + +sub userfacedir { + my $self = shift; + + return $self->user_face_dir; +} + + +#============================================================= + +=head2 face2png + +=head3 INPUT + + $face: face icon name (usually username) + +=head3 OUTPUT + + pathname to $face named icon with png extension + +=head3 DESCRIPTION + + This method returns the face icon pathname related to username + +=cut + +#============================================================= + +sub face2png { + my ($self, $face) = @_; + + return $self->face_dir . $face . ".png" if $face; +} + +#============================================================= + +=head2 facenames + + +=head3 OUTPUT + + $namelist: ARRAY reference containing the face name list + +=head3 DESCRIPTION + + Retrieves the list of icon name from facesdir() + +=cut + +#============================================================= + +sub facenames { + my $self = shift; + + my $dir = $self->face_dir; + my @files = io->dir($dir)->all_files; + my @l = grep { /^[A-Z]/ } @files; + my @namelist = map { my $f = fileparse($_->filename, qr/\Q.png\E/) } (@l ? @l : @files); + + return \@namelist; +} + +#============================================================= + +=head2 addKdmIcon + +=head3 INPUT + + $user: username to add + $icon: chosen icon for username $user + + +=head3 DESCRIPTION + + Add a $user named icon to $self->user_face_dir. It just copies + $icon to $self->user_face_dir, naming it as $user + +=cut + +#============================================================= + +sub addKdmIcon { + my ($self, $user, $icon) = @_; + + if ($icon && $user) { + my $icon_name = $self->face_dir . $icon . ".png"; + my $dest = $self->user_face_dir . $user . ".png"; + + eval { copy($icon_name, $dest) } ; + } +} + +#============================================================= + +=head2 removeKdmIcon + +=head3 INPUT + + $user: username icon to remove + +=head3 DESCRIPTION + + Remove a $user named icon from $self->user_face_dir + +=cut + +#============================================================= +sub removeKdmIcon { + my ($self, $user) = @_; + + if ($user) { + my $icon_name = $self->user_face_dir . $user . ".png"; + eval { remove($icon_name) } ; + } +} + + +#============================================================= + +=head2 _valid + +=head3 INPUT + + $name: User or Group name + $name_length: Max length of $name (default 32) + +=head3 OUTPUT + + 1, locale "Ok" if valid + 0, and explanation string if not valid: + - Name field is empty please provide a name + - The name must contain only lower cased latin letters, numbers, '.', '-' and '_' + - Name is too long + +=head3 DESCRIPTION + + this internal method return if a name is compliant to + a group or user name. + +=cut + +#============================================================= + +sub _valid { + my ($self, $name, $name_length) = @_; + + return (0, $self->loc->N("Name field is empty please provide a name")) if (!$name ); + + $name_length = 32 if !$name_length; + + $name =~ /^[a-z]+?[a-z0-9_\-\.]*?$/ or do { + return (0, $self->loc->N("The name must start with a letter and contain only lower cased latin letters, numbers, '.', '-' and '_'")); + }; + + return (0, $self->loc->N("Name is too long. Maximum length is %d", $name_length)) if (! (length($name) <= $name_length)); + + return (1, $self->loc->N("Ok")); +} + +#============================================================= + +=head2 valid_username + +=head3 INPUT + + $username: user name to check + +=head3 OUTPUT + + 1 if valid, 0 if not (see _valid) + +=head3 DESCRIPTION + + Checks the valididty of the string $username + +=cut + +#============================================================= + +sub valid_username { + my ($self, $username) = @_; + + return $self->_valid($username, 32); +} + +#============================================================= + +=head2 valid_groupname + +=head3 INPUT + + $groupname: user name to check + +=head3 OUTPUT + + 1 if valid, 0 if not (see _valid) + +=head3 DESCRIPTION + + Checks the valididty of the string $groupname + +=cut + +#============================================================= +sub valid_groupname { + my ($self, $groupname) = @_; + + return $self->_valid($groupname, 16); +} + + +#============================================================= + +=head2 updateOrDelUsersInGroup + +=head3 INPUT + + $name: username + +=head3 DESCRIPTION + + Fixes user deletion into groups. + +=cut + +#============================================================= +sub updateOrDelUserInGroup { + my ($self, $name) = @_; + my $groups = $self->ctx->GroupsEnumerateFull; + foreach my $g (@$groups) { + my $members = $g->MemberName(1, 0); + if (ManaTools::Shared::inArray($name, $members)) { + eval { $g->MemberName($name, 2) }; + eval { $self->ctx->GroupModify($g) }; + } + } +} + + +#============================================================= + +=head2 getGoups + +=head3 OUTPUT + + $groups: ARRAY reference containing all the groups + +=head3 DESCRIPTION + + This method return the configured groups + +=cut + +#============================================================= +sub getGoups { + my $self = shift; + + return $self->ctx->GroupsEnumerate; +} + + +#============================================================= + +=head2 groupNameExists + +=head3 INPUT + + $groupname: the name of the group to check + +=head3 OUTPUT + + if group exists + +=head3 DESCRIPTION + + This method return if a given group exists + +=cut + +#============================================================= +sub groupNameExists { + my ($self, $groupname) = @_; + + return 0 if (!defined($groupname)); + + return (defined($self->ctx->LookupGroupByName($groupname))); +} + +#============================================================= + +=head2 groupIDExists + +=head3 INPUT + + $group: the id of the group to check + +=head3 OUTPUT + + if group exists + +=head3 DESCRIPTION + + This method return if a given group exists + +=cut + +#============================================================= +sub groupIDExists { + my ($self, $group) = @_; + + return 0 if (!defined($group)); + + return (defined($self->ctx->LookupGroupById($group))); +} + + +#============================================================= + +=head2 groupID + +=head3 INPUT + + $groupname: group name + +=head3 OUTPUT + + groupid or undef + +=head3 DESCRIPTION + + This method returns the group id for the group name + +=cut + +#============================================================= +sub groupID { + my ($self, $groupname) = @_; + + my $gr = $self->ctx->LookupGroupByName($groupname); + return $gr->Gid($self->USER_GetValue) if ($gr); + + return undef; +} + +#============================================================= + +=head2 groupName + +=head3 INPUT + + $gid group identifier + +=head3 OUTPUT + + group name or undef + +=head3 DESCRIPTION + + This method returns the group name for the given group + identifier + +=cut + +#============================================================= +sub groupName { + my ($self, $gid) = @_; + + my $gr = $self->ctx->LookupGroupById($gid); + return $gr->GroupName($self->USER_GetValue) if ($gr); + + return undef; +} + + +#============================================================= + +=head2 addGroup + +=head3 INPUT + + $params: HASH reference containing: + groupname => name of teh group to be added + gid => group id of the group to be added + is_system => is a system group? + +=head3 OUTPUT + + $gid the actual group id + +=head3 DESCRIPTION + + This method add a group to system + +=cut + +#============================================================= +sub addGroup { + my ($self, $params) = @_; + + my $is_system = defined($params->{is_system}) ? + $params->{is_system} : + 0; + + return -1 if !defined($params->{groupname}); + + my $groupEnt = $self->ctx->InitGroup($params->{groupname}, $is_system); + + return -1 if !defined($groupEnt); + + $groupEnt->Gid($params->{gid}) if defined($params->{gid}); + + $self->ctx->GroupAdd($groupEnt); + + return $groupEnt->Gid($self->USER_GetValue); +} + +#============================================================= + +=head2 groupMembers + +=head3 INPUT + + $groupname: The group name + +=head3 OUTPUT + + $members: ARRAY reference containing all the user belonging + to the given $groupname + +=head3 DESCRIPTION + + This method gets the group name and returns the users + belonging to it + +=cut + +#============================================================= +sub groupMembers { + my ($self, $groupname) = @_; + + return $groupname if !defined($groupname); + + my $members = $self->ctx->EnumerateUsersByGroup($groupname); + + return $members; +} + + +#============================================================= + +=head2 isPrimaryGroup + +=head3 INPUT + + $groupname: the name of the group + +=head3 OUTPUT + + $username: undef if it is primary group or the username for + which the group is the primary one. + +=head3 DESCRIPTION + + This methods check if the given group name is primary group + for any users belonging to the group + +=cut + +#============================================================= +sub isPrimaryGroup { + my ($self, $groupname) = @_; + + return $groupname if !defined($groupname); + + my $groupEnt = $self->ctx->LookupGroupByName($groupname); + my $members = $self->ctx->EnumerateUsersByGroup($groupname); + foreach my $username (@$members) { + my $userEnt = $self->ctx->LookupUserByName($username); + if ($userEnt && $userEnt->Gid($self->USER_GetValue) == $groupEnt->Gid($self->USER_GetValue)) { + return $username; + } + } + return undef; +} + + +#============================================================= + +=head2 deleteGroup + +=head3 INPUT + + $groupname: in_par_description + +=head3 OUTPUT + + 0: if error occurred + 1: if removed + +=head3 DESCRIPTION + + This method remove the group from the system + +=cut + +#============================================================= +sub deleteGroup { + my ($self, $groupname) = @_; + + return 0 if !defined($groupname); + + my $groupEnt = $self->ctx->LookupGroupByName($groupname); + eval { $self->ctx->GroupDel($groupEnt) }; + return 0 if $@; + + return 1; +} + + + +#============================================================= + +=head2 modifyGroup + +=head3 INPUT + + $groupInfo: HASH reference containing: + old_groupname => old name of the group (if renaming) + groupname => group name + members => users belonging to the group + +=head3 OUTPUT + + $retval => HASH reference + status => 1 (ok) 0 (error) + error => error message if status is 0 + +=head3 DESCRIPTION + + This method modifies the group groupname + +=cut + +#============================================================= +sub modifyGroup { + my ($self, $groupInfo) = @_; + + die "group name is mandatory" if !defined($groupInfo->{groupname}); + + my $groupEnt = defined($groupInfo->{old_groupname}) ? + $self->ctx->LookupGroupByName($groupInfo->{old_groupname}) : + $self->ctx->LookupGroupByName($groupInfo->{groupname}); + + my $orig_groupname = $groupInfo->{groupname}; + if (defined($groupInfo->{old_groupname}) && + $groupInfo->{old_groupname} ne $groupInfo->{groupname}) { + $groupEnt->GroupName($groupInfo->{groupname}); + $orig_groupname = $groupInfo->{old_groupname}; + } + + my $members = $groupInfo->{members}; + my $gid = $groupEnt->Gid($self->USER_GetValue); + my $users = $self->getUsers(); + my @susers = sort(@{$users}); + + foreach my $user (@susers) { + my $uEnt = $self->ctx->LookupGroupByName($user); + if ($uEnt) { + my $ugid = $uEnt->Gid($self->USER_GetValue); + my $m = $self->ctx->EnumerateUsersByGroup($orig_groupname); + if (MDK::Common::DataStructure::member($user, @{$members})) { + if (!ManaTools::Shared::inArray($user, $m)) { + if ($ugid != $gid) { + eval { $groupEnt->MemberName($user, 1) }; + } + } + } + else { + if (ManaTools::Shared::inArray($user, $m)) { + if ($ugid == $gid) { + return { + status => 0, + error =>$self->loc->N("You cannot remove user <%s> from their primary group", $user) + }; + } + else { + eval { $groupEnt->MemberName($user, 2) }; + } + } + } + } + } + + $self->ctx->GroupModify($groupEnt); + + return {status => 1,}; +} + +#============================================================= + +=head2 getGroupsInfo + + $options: HASH reference containing + groupname_filter => groupname search string + filter_system => hides system groups + +=head3 OUTPUT + + $groupsInfo: HASH reference containing + groupname-1 => { + gid => group identifier + members => ARRAY of username + } + groupname-2 => { + ... + } + +=head3 DESCRIPTION + + This method get group information (all groups or the + filtered ones) + +=cut + +#============================================================= +sub getGroupsInfo { + my ($self, $options) = @_; + + my $groupsInfo = {}; + return $groupsInfo if !defined $self->ctx; + + my $strfilt = $options->{groupname_filter} if exists($options->{groupname_filter}); + my $filtergroups = $options->{filter_system} if exists($options->{filter_system}); + + my $groups = $self->ctx->GroupsEnumerateFull; + + my @GroupReal; + LOOP: foreach my $g (@{$groups}) { + my $gid = $g->Gid($self->USER_GetValue); + next LOOP if $filtergroups && $gid <= 499 || $gid == 65534; + if ($filtergroups && $gid > 499 && $gid < $self->min_GID) { + my $groupname = $g->GroupName($self->USER_GetValue); + my $l = $self->ctx->LookupUserByName($groupname); + if (!defined($l)) { + my $members = $self->ctx->EnumerateUsersByGroup($groupname); + next LOOP if !scalar(@{$members}); + foreach my $username (@$members) { + my $userEnt = $self->ctx->LookupUserByName($username); + next LOOP if $userEnt->HomeDir($self->USER_GetValue) =~ /^\/($|var\/|run\/)/ || $userEnt->LoginShell($self->USER_GetValue) =~ /(nologin|false)$/; + } + } + else { + next LOOP if $l->HomeDir($self->USER_GetValue) =~ /^\/($|var\/|run\/)/ || $l->LoginShell($self->USER_GetValue) =~ /(nologin|false)$/; + } + } + push @GroupReal, $g if $g->GroupName($self->USER_GetValue) =~ /^\Q$strfilt/; + } + + foreach my $g (@GroupReal) { + my $groupname = $g->GroupName($self->USER_GetValue); + my $u_b_g = $self->ctx->EnumerateUsersByGroup($groupname); + my $group_id = $g->Gid($self->USER_GetValue); + + $groupsInfo->{"$groupname"} = { + gid => $group_id, + members => $u_b_g, + }; + } + + return $groupsInfo; +} + +#============================================================= + +=head2 getUsers + +=head3 OUTPUT + + $users: ARRAY reference containing all the users + +=head3 DESCRIPTION + + This method return the configured users + +=cut + +#============================================================= +sub getUsers { + my $self = shift; + + return $self->ctx->UsersEnumerate; +} + +#============================================================= + +=head2 getUserInfo + +=head3 INPUT + + $username: user name + +=head3 OUTPUT + + $userInfo: HASH reference containing + { + uid => user identifier + gid => group identifier + fullname => user full name + home => home directory + shell => user shell + expire => shadow expire time + locked => is locked? + exp_min => shadow Min + exp_max => shadow Max + exp_warn => shadow Warn + exp_inact => shadow Inact + last_change => Shadow last change + members => groups the user belongs to + } + +=head3 DESCRIPTION + + This method get all the information for the given user + +=cut + +#============================================================= +sub getUserInfo { + my ($self, $username) = @_; + + my $userInfo = {}; + return $userInfo if !defined $self->ctx; + + my $userEnt = $self->ctx->LookupUserByName($username); + return $userInfo if !defined($userEnt); + + my $fullname = $userEnt->Gecos($self->USER_GetValue); + utf8::decode($fullname); + $userInfo->{fullname} = $fullname; + $userInfo->{shell} = $userEnt->LoginShell($self->USER_GetValue); + $userInfo->{home} = $userEnt->HomeDir($self->USER_GetValue); + $userInfo->{uid} = $userEnt->Uid($self->USER_GetValue); + $userInfo->{gid} = $userEnt->Gid($self->USER_GetValue); + $userInfo->{expire} = $userEnt->ShadowExpire($self->USER_GetValue); + $userInfo->{locked} = $self->ctx->IsLocked($userEnt); + + $userInfo->{exp_min} = $userEnt->ShadowMin($self->USER_GetValue); + $userInfo->{exp_max} = $userEnt->ShadowMax($self->USER_GetValue); + $userInfo->{exp_warn} = $userEnt->ShadowWarn($self->USER_GetValue); + $userInfo->{exp_inact} = $userEnt->ShadowInact($self->USER_GetValue); + $userInfo->{last_change} = $userEnt->ShadowLastChange($self->USER_GetValue); + $userInfo->{members} = $self->ctx->EnumerateGroupsByUser($username); + + return $userInfo; +} + +#============================================================= + +=head2 getUsersInfo + +=head3 INPUT + + $options: HASH reference containing + username_filter => username search string + filter_system => hides system users + +=head3 OUTPUT + + $usersInfo: HASH reference containing + username-1 => { + uid => user identifier + group => primary group name + gid => group identifier + fullname => user full name + home => home directory + shell => user shell + status => login status (locked, expired, etc) + } + username-2 => { + ... + } + +=head3 DESCRIPTION + + This method get user information (all users or filtered ones) + +=cut + +#============================================================= +sub getUsersInfo { + my ($self, $options) = @_; + + my $usersInfo = {}; + return $usersInfo if !defined $self->ctx; + + my $strfilt = $options->{username_filter} if exists($options->{username_filter}); + my $filterusers = $options->{filter_system} if exists($options->{filter_system}); + + my ($users, $group, $groupnm, $expr); + $users = $self->ctx->UsersEnumerateFull; + + my @UserReal; + LOOP: foreach my $l (@{$users}) { + my $uid = $l->Uid($self->USER_GetValue); + next LOOP if $filterusers && $uid <= 499 || $uid == 65534; + next LOOP if $filterusers && $uid > 499 && $uid < $self->min_UID && + ($l->HomeDir($self->USER_GetValue) =~ /^\/($|var\/|run\/)/ || $l->LoginShell($self->USER_GetValue) =~ /(nologin|false)$/); + push @UserReal, $l if $l->UserName($self->USER_GetValue) =~ /^\Q$strfilt/; + } + my $i; + my $itemColl = new yui::YItemCollection; + foreach my $l (@UserReal) { + $i++; + my $uid = $l->Uid($self->USER_GetValue); + if (!defined $uid) { + warn "bogus user at line $i\n"; + next; + } + my $gid = $l->Gid($self->USER_GetValue); + $group = $self->ctx->LookupGroupById($gid); + $groupnm = ''; + $expr = $self->computeLockExpire($l); + $group and $groupnm = $group->GroupName($self->USER_GetValue); + my $fulln = $l->Gecos($self->USER_GetValue); + utf8::decode($fulln); + my $username = $l->UserName($self->USER_GetValue); + my $shell = $l->LoginShell($self->USER_GetValue); + my $homedir = $l->HomeDir($self->USER_GetValue); + $usersInfo->{"$username"} = { + uid => $uid, + group => $groupnm, + gid => $gid, + fullname => $fulln, + home => $homedir, + status => $expr, + shell => $shell, + }; + } + + return $usersInfo; +} + +#============================================================= + +=head2 getUserHome + +=head3 INPUT + + $username: given user name + +=head3 OUTPUT + + $homedir: user home directory + +=head3 DESCRIPTION + + This method return the home directory belonging to the given + username + +=cut + +#============================================================= +sub getUserHome { + my ($self, $username) = @_; + + return $username if !defined($username); + + my $userEnt = $self->ctx->LookupUserByName($username); + my $homedir = $userEnt->HomeDir($self->USER_GetValue); + + return $homedir; +} + +#============================================================= + +=head2 userNameExists + +=head3 INPUT + + $username: the name of the user to check + +=head3 OUTPUT + + if user exists + +=head3 DESCRIPTION + + This method return if a given user exists + +=cut + +#============================================================= +sub userNameExists { + my ($self, $username) = @_; + + return 0 if (!defined($username)); + + return (defined($self->ctx->LookupUserByName($username))); +} + +#============================================================= + +=head2 computeLockExpire + +=head3 INPUT + + $l: login user info + +=head3 OUTPUT + + $status: Locked, Expired, or empty string + +=head3 DESCRIPTION + + This method returns if the login is Locked, Expired or ok. + Note this function is meant for internal use only + +=cut + +#============================================================= +sub computeLockExpire { + my ( $self, $l ) = @_; + my $ep = $l->ShadowExpire($self->USER_GetValue); + my $tm = ceil(time()/(24*60*60)); + $ep = -1 if int($tm) <= $ep; + my $status = $self->ctx->IsLocked($l) ? $self->loc->N("Locked") : ($ep != -1 ? $self->loc->N("Expired") : ''); + return $status; +} + +#============================================================= + +=head2 addUser + +=head3 INPUT + + $params: HASH reference containing: + username => name of teh user to be added + uid => user id of the username to be added + is_system => is a system user? + homedir => user home directory + donotcreatehome => do not create the home directory + shell => user shall + fullname => user full name + gid => group id for the user + shadowMin => min time password validity + shadowMax => max time password validity + shadowInact => + shadowWarn => + password => user password + +=head3 OUTPUT + + 0 if errors 1 if ok + +=head3 DESCRIPTION + + This method add a user to system + +=cut + +#============================================================= +sub addUser { + my ($self, $params) = @_; + + return 0 if !defined($params->{username}); + + my $is_system = defined($params->{is_system}) ? + $params->{is_system} : + 0; + + my $userEnt = $self->ctx->InitUser($params->{username}, $is_system); + return 0 if !defined($userEnt); + + + $userEnt->HomeDir($params->{homedir}) if defined($params->{homedir}); + $userEnt->Uid($params->{uid}) if defined($params->{uid}); + $userEnt->Gecos($params->{fullname}) if defined($params->{fullname}); + $userEnt->LoginShell($params->{shell}) if defined($params->{shell}); + $userEnt->Gid($params->{gid}) if defined ($params->{gid}); + my $shd = defined ($params->{shadowMin}) ? $params->{shadowMin} : -1; + $userEnt->ShadowMin($shd); + $shd = defined ($params->{shadowMax}) ? $params->{shadowMax} : 99999; + $userEnt->ShadowMax($shd); + $shd = defined ($params->{shadowWarn}) ? $params->{shadowWarn} : -1; + $userEnt->ShadowWarn($shd); + $shd = defined ($params->{shadowInact}) ? $params->{shadowInact} : -1; + $userEnt->ShadowInact($shd); + $self->ctx->UserAdd($userEnt, $is_system, $params->{donotcreatehome}); + $self->ctx->UserSetPass($userEnt, $params->{password}); + + return 1; +} + + +#============================================================= + +=head2 modifyUser + +=head3 INPUT + + $userInfo: HASH reference containing: + old_username => old name of the user (if renaming) + username => user name + fullname => full name of teh user + password => password + homedir => home directory + shell => user shell + members => groups the user belongs to + gid => primary group identifier + lockuser => lock user + acc_expires => account expire time - containing: + exp_y => year + exp_m => month + exp_d => day + password_expires => password expire time - containing: + exp_min => min + exp_max => max + exp_warn => when warn + exp_inact => when inactive + +=head3 DESCRIPTION + + This method modifies the group groupname + +=cut + +#============================================================= +sub modifyUser { + my ($self, $userInfo) = @_; + + die "user name is mandatory" if !defined($userInfo->{username}); + die "primary group identifier is mandatory" if !defined($userInfo->{gid}); + die "a valid group identifier is mandatory" if $userInfo->{gid} < 0; + + if (defined($userInfo->{acc_expires})) { + die "expiring year is mandatory" if !defined($userInfo->{acc_expires}->{exp_y}); + die "expiring month is mandatory" if !defined($userInfo->{acc_expires}->{exp_m}); + die "expiring day is mandatory" if !defined($userInfo->{acc_expires}->{exp_d}); + } + if (defined($userInfo->{password_expires})) { + die "password expiring min is mandatory" if !($userInfo->{password_expires}->{exp_min}); + die "password expiring max is mandatory" if !($userInfo->{password_expires}->{exp_max}); + die "password expiring warn is mandatory" if !($userInfo->{password_expires}->{exp_warn}); + die "password expiring inactive is mandatory" if !($userInfo->{password_expires}->{exp_inact}); + } + my $userEnt = defined($userInfo->{old_username}) ? + $self->ctx->LookupUserByName($userInfo->{old_username}) : + $self->ctx->LookupUserByName($userInfo->{username}); + + my $orig_username = $userInfo->{username}; + if (defined($userInfo->{old_username}) && + $userInfo->{old_username} ne $userInfo->{username}) { + $userEnt->UserName($userInfo->{username}); + $orig_username = $userInfo->{old_username}; + } + + # $userEnt->UserName($userInfo->{username}); + $userEnt->Gecos($userInfo->{fullname}) if defined($userInfo->{fullname}); + $userEnt->HomeDir($userInfo->{homedir}) if defined($userInfo->{homedir}); + $userEnt->LoginShell($userInfo->{shell}) if defined($userInfo->{shell}); + + + my $username = $userEnt->UserName($self->USER_GetValue); + my $grps = $self->getGoups(); + my @sgroups = sort @{$grps}; + + my $members = $userInfo->{members}; + foreach my $group (@sgroups) { + my $gEnt = $self->ctx->LookupGroupByName($group); + my $ugid = $gEnt->Gid($self->USER_GetValue); + my $m = $gEnt->MemberName(1,0); + if (MDK::Common::DataStructure::member($group, @$members)) { + if (!ManaTools::Shared::inArray($username, $m) && $userInfo->{gid} != $ugid) { + eval { $gEnt->MemberName($username, 1) }; + $self->ctx->GroupModify($gEnt); + } + } + else { + if (ManaTools::Shared::inArray($username, $m)) { + eval { $gEnt->MemberName($username, 2) }; + $self->ctx->GroupModify($gEnt); + } + } + } + + $userEnt->Gid($userInfo->{gid}) if defined($userInfo->{gid}); + + if (defined($userInfo->{acc_expires})) { + my $yr = $userInfo->{acc_expires}->{exp_y}; + my $mo = $userInfo->{acc_expires}->{exp_m}; + my $dy = $userInfo->{acc_expires}->{exp_d}; + my $Exp = _ConvTime($dy, $mo, $yr); + $userEnt->ShadowExpire($Exp); + } + else { + $userEnt->ShadowExpire(ceil(-1)) + } + if (defined($userInfo->{password_expires})) { + my $allowed = $userInfo->{password_expires}->{exp_min}; + my $required = $userInfo->{password_expires}->{exp_max}; + my $warning = $userInfo->{password_expires}->{exp_warn}; + my $inactive = $userInfo->{password_expires}->{exp_inact}; + $userEnt->ShadowMin($allowed); + $userEnt->ShadowMax($required); + $userEnt->ShadowWarn($warning); + $userEnt->ShadowInact($inactive); + } + else { + $userEnt->ShadowMin(-1); + $userEnt->ShadowMax(99999); + $userEnt->ShadowWarn(-1); + $userEnt->ShadowInact(-1); + } + + $self->ctx->UserSetPass($userEnt, $userInfo->{password}) if defined($userInfo->{password}); + $self->ctx->UserModify($userEnt); + + if ($userInfo->{lockuser}) { + !$self->ctx->IsLocked($userEnt) and $self->ctx->Lock($userEnt); + } + else { + $self->ctx->IsLocked($userEnt) and $self->ctx->UnLock($userEnt); + } + + return 1; +} + + +#============================================================= + +=head2 deleteUser + +=head3 INPUT + + $username: username to be deleted + $options: HASH reference containing + clean_home => if home has to be removed + clean_spool => if sppol has to be removed + +=head3 OUTPUT + + error string or undef if no errors occurred + +=head3 DESCRIPTION + + This method delete a user from the system. + +=cut + +#============================================================= +sub deleteUser { + my ($self, $username, $options) = @_; + + return $username if !defined($username); + + my $userEnt = $self->ctx->LookupUserByName($username); + + $self->ctx->UserDel($userEnt); + $self->updateOrDelUserInGroup($username); + #Let's check out the user's primary group + my $usergid = $userEnt->Gid($self->USER_GetValue); + my $groupEnt = $self->ctx->LookupGroupById($usergid); + if ($groupEnt) { + my $member = $groupEnt->MemberName(1, 0); + # TODO check if 499 is ok nowadays + if (scalar(@$member) == 0 && $groupEnt->Gid($self->USER_GetValue) > 499) { + $self->ctx->GroupDel($groupEnt); + } + } + if (defined($options)) { + ## testing jusr if exists also undef is allowed + ## as valid option + if (exists($options->{clean_home})) { + eval { $self->ctx->CleanHome($userEnt) }; + return $@ if $@; + } + if (exists($options->{clean_spool})) { + eval { $self->ctx->CleanSpool($userEnt) }; + return $@ if $@; + } + } + return undef; +} + +#============================================================= + +=head2 getUserShells + + +=head3 OUTPUT + + GetUserShells: from libUSER + +=head3 DESCRIPTION + + This method returns the available shell + +=cut + +#============================================================= + +sub getUserShells { + my $self = shift; + + return $self->ctx->GetUserShells; +} +#============================================================= + +=head2 GetFaceIcon + +=head3 INPUT + + $name: icon name for the given username + $next: if passed means getting next icon from the given $name + +=head3 OUTPUT + + $user_icon: icon name + +=head3 DESCRIPTION + + This method returns the icon for the given user ($name) or the + following one if $next is passed + +=cut + +#============================================================= +sub GetFaceIcon { + my ($self, $name, $next) = @_; + my $icons = $self->facenames(); + my $i; + my $current_icon; + # remove shortcut "&" from label + $name =~ s/&// if ($name); + my $user_icon = $self->user_face_dir . $name . ".png" if ($name); + if ($name) { + $user_icon = $self->face2png($name) unless(-e $user_icon); + } + if ($name && -e $user_icon) { + my $current_md5 = ManaTools::Shared::md5sum($user_icon); + my $found = 0; + for ($i = 0; $i < scalar(@$icons); $i++) { + if (ManaTools::Shared::md5sum($self->face2png($icons->[$i])) eq $current_md5) { + $found = 1; + last; + } + } + if ($found) { #- current icon found in @icons, select it + $current_icon = $icons->[$i]; + } else { #- add and select current icon in @icons + push @$icons, $user_icon; + $current_icon = $user_icon; + $i = scalar(@$icons) - 1; + } + } else { + #- no icon yet, select a random one + $current_icon = $icons->[$i = rand(scalar(@$icons))]; + } + + if ($next) { + $current_icon = $icons->[$i = defined $icons->[$i+1] ? $i+1 : 0]; + } + return $current_icon; +} + + +#============================================================= + +=head2 strongPassword + +=head3 INPUT + + $passwd: password to be checked + +=head3 OUTPUT + + 1: if password is strong + 0: if password is weak + +=head3 DESCRIPTION + + Check for a strong password + +=cut + +#============================================================= +sub strongPassword { + my ($self, $passwd, $threshold) = @_; + + return 0 if !$passwd; + + my $pwdm = $threshold ? Data::Password::Meter->new($threshold) : Data::Password::Meter->new(); + + # Check a password + return $pwdm->strong($passwd); +} + + +# TODO methods not tested in Users.t + +#============================================================= + +=head2 weakPasswordForSecurityLevel + +=head3 INPUT + + $passwd: password to check + +=head3 OUTPUT + + 1: if the password is too weak for security level + +=head3 DESCRIPTION + + Check the security level set if /etc/security/msec/security.conf + exists and the level is not 'standard' and if the password + is not at least 6 characters return true + +=cut + +#============================================================= +sub weakPasswordForSecurityLevel { + my ($self, $passwd) = @_; + + my $sec_conf_file = "/etc/security/msec/security.conf"; + if (-e $sec_conf_file) { + my $prefs = Config::Auto::parse($sec_conf_file); + my $level = $prefs->{BASE_LEVEL}; + if ($level eq 'none' or $level eq 'standard') { + return 0; + } + elsif (length($passwd) < 6) { + return 1; + } + } + + return 0; +} + + +#============================================================= + +=head2 Add2UsersGroup + +=head3 INPUT + + $name: username + +=head3 OUTPUT + + $gid: group id + +=head3 DESCRIPTION + + Adds the given username $name to 'users' group + +=cut + +#============================================================= +sub Add2UsersGroup { + my ($self, $name) = @_; + + my $usersgroup = $self->ctx->LookupGroupByName('users'); + $usersgroup->MemberName($name, 1); + return $usersgroup->Gid($self->USER_GetValue); +} + +sub _ConvTime { + my ($day, $month, $year) = @_; + my ($tm, $days, $mon, $yr); + $mon = $month - 1; $yr = $year - 1900; + $tm = POSIX::mktime(0, 0, 0, $day, $mon, $yr); + $days = ceil($tm / (24 * 60 * 60)); + return $days; +} + +no Moose; +__PACKAGE__->meta->make_immutable; + +1; diff --git a/lib/ManaTools/rpmdragora.pm b/lib/ManaTools/rpmdragora.pm new file mode 100644 index 0000000..ecdf06f --- /dev/null +++ b/lib/ManaTools/rpmdragora.pm @@ -0,0 +1,1165 @@ +# vim: set et ts=4 sw=4: +#***************************************************************************** +# +# Copyright (c) 2002 Guillaume Cottenceau +# Copyright (c) 2002-2007 Thierry Vignaud +# Copyright (c) 2003, 2004, 2005 MandrakeSoft SA +# Copyright (c) 2005, 2007 Mandriva SA +# Copyright (c) 2013 - 2015 Matteo Pasotti +# +# 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. +# +#***************************************************************************** +# +# $Id: rpmdragora.pm 267936 2010-04-26 16:40:21Z jvictor $ + +package ManaTools::rpmdragora; +use warnings::register; + +use urpm; +use urpm::cfg; +use urpm::mirrors; +use urpm::download (); +use urpm::prompt; +use urpm::media; + +# quick fix for mirror.pm +use lib qw(/usr/lib/libDrakX); + +use MDK::Common; +use MDK::Common::System; +use MDK::Common::String; +use MDK::Common::Func; +use MDK::Common::File qw(basename cat_ output); +use URPM; +use URPM::Resolve; +use strict; +use POSIX qw(_exit); + +use feature 'state'; + +use ManaTools::Shared; +use ManaTools::Shared::Locales; +use ManaTools::Shared::GUI; + +use Carp; + +our @ISA = qw(Exporter); +our @EXPORT = qw( + $changelog_first_config + $compute_updates + $filter + $dont_show_selections + $ignore_debug_media + $mandrakeupdate_wanted_categories + $mandrivaupdate_height + $mandrivaupdate_width + $max_info_in_descr + $mode + $NVR_searches + $offered_to_add_sources + $rpmdragora_height + $rpmdragora_width + $tree_flat + $tree_mode + $use_regexp + $typical_width + $clean_cache + $auto_select + locale + add_distrib_update_media + add_medium_and_check + but + but_ + check_update_media_version + choose_mirror + distro_type + fatal_msg + getbanner + get_icon + interactive_list + interactive_list_ + interactive_msg + myexit + readconf + remove_wait_msg + run_drakbug + show_urpm_progress + slow_func + slow_func_statusbar + statusbar_msg + statusbar_msg_remove + strip_first_underscore + update_sources + update_sources_check + update_sources_interactive + update_sources_noninteractive + wait_msg + warn_for_network_need + writeconf +); +our $typical_width = 280; + +our $dont_show_selections; + +# i18n: IMPORTANT: to get correct namespace (rpmdragora instead of libDrakX) +BEGIN { unshift @::textdomains, qw(rpmdragora urpmi rpm-summary-main rpm-summary-contrib rpm-summary-devel rpm-summary-non-free) } + +use yui; +use Glib; +#ugtk2::add_icon_path('/usr/share/rpmdragora/icons'); + +# Locale::gettext::bind_textdomain_codeset('rpmdragora', 'UTF8'); +my $loc = ManaTools::Shared::Locales->new(domain_name => 'rpmdrake');; + +our $mageia_release = MDK::Common::File::cat_( + -e '/etc/mageia-release' ? '/etc/mageia-release' : '/etc/release' +) || ''; +chomp $mageia_release; +our ($distro_version) = $mageia_release =~ /(\d+\.\d+)/; +our ($branded, %distrib); +$branded = -f '/etc/sysconfig/oem' + and %distrib = MDK::Common::System::distrib(); +our $myname_update = $branded ? $loc->N_("Software Update") : $loc->N_("Mageia Update"); + +@rpmdragora::prompt::ISA = 'urpm::prompt'; + + +sub locale() { + + if (!defined($loc)) { + $loc = ManaTools::Shared::Locales->new(domain_name => 'rpmdrake'); + } + + return $loc; +} + +sub rpmdragora::prompt::prompt { + my ($self) = @_; + my @answers; + my $d = ugtk2->new("", grab => 1, if_($::main_window, transient => $::main_window)); + $d->{rwindow}->set_position('center_on_parent'); + gtkadd( + $d->{window}, + gtkpack( + Gtk2::VBox->new(0, 5), + Gtk2::WrappedLabel->new($self->{title}), + (map { gtkpack( + Gtk2::HBox->new(0, 5), + Gtk2::Label->new($self->{prompts}[$_]), + $answers[$_] = gtkset_visibility(gtkentry(), !$self->{hidden}[$_]), + ) } 0 .. $#{$self->{prompts}}), + gtksignal_connect(Gtk2::Button->new($loc->N("Ok")), clicked => sub { Gtk2->main_quit }), + ), + ); + $d->main; + map { $_->get_text } @answers; +} + +$urpm::download::PROMPT_PROXY = new rpmdragora::prompt( + $loc->N_("Please enter your credentials for accessing proxy\n"), + [ $loc->N_("User name:"), $loc->N_("Password:") ], + undef, + [ 0, 1 ], +); + +sub myexit { + writeconf(); + destroy $::main_window if $::main_window; + exit @_; +} + +my ($root) = grep { $_->[2] == 0 } list_passwd(); +$ENV{HOME} = $> == 0 ? $root->[7] : $ENV{HOME} || '/root'; +$ENV{HOME} = $::env if $::env = $ManaTools::Rpmdragora::init::rpmdragora_options{env}[0]; + +our $configfile = "$ENV{HOME}/.rpmdragora"; + +# +# Configuration File Options +# + +# clear download cache after successfull installation of packages +our $clean_cache; + +# automatic select dependencies without user intervention +our $auto_select; + +our ($changelog_first_config, $compute_updates, $filter, $max_info_in_descr, $mode, $NVR_searches, $tree_flat, $tree_mode, $use_regexp); +our ($mandrakeupdate_wanted_categories, $ignore_debug_media, $offered_to_add_sources, $no_confirmation); +our ($rpmdragora_height, $rpmdragora_width, $mandrivaupdate_height, $mandrivaupdate_width); + +our %config = ( + clean_cache => { + var => \$clean_cache, + default => [ 0 ] + }, + auto_select => { + var => \$auto_select, + default => [ 0 ] + }, + changelog_first_config => { var => \$changelog_first_config, default => [ 0 ] }, + compute_updates => { var => \$compute_updates, default => [ 1 ] }, + dont_show_selections => { var => \$dont_show_selections, default => [ $> ? 1 : 0 ] }, + filter => { var => \$filter, default => [ 'all' ] }, + ignore_debug_media => { var => \$ignore_debug_media, default => [ 0 ] }, + mandrakeupdate_wanted_categories => { var => \$mandrakeupdate_wanted_categories, default => [ qw(security) ] }, + mandrivaupdate_height => { var => \$mandrivaupdate_height, default => [ 0 ] }, + mandrivaupdate_width => { var => \$mandrivaupdate_width, default => [ 0 ] }, + max_info_in_descr => { var => \$max_info_in_descr, default => [] }, + mode => { var => \$mode, default => [ 'by_group' ] }, + NVR_searches => { var => \$NVR_searches, default => [ 0 ] }, + 'no-confirmation' => { var => \$no_confirmation, default => [ 0 ] }, + offered_to_add_sources => { var => \$offered_to_add_sources, default => [ 0 ] }, + rpmdragora_height => { var => \$rpmdragora_height, default => [ 0 ] }, + rpmdragora_width => { var => \$rpmdragora_width, default => [ 0 ] }, + tree_flat => { var => \$tree_flat, default => [ 0 ] }, + tree_mode => { var => \$tree_mode, default => [ qw(gui_pkgs) ] }, + use_regexp => { var => \$use_regexp, default => [ 0 ] }, +); + +sub readconf() { + ${$config{$_}{var}} = $config{$_}{default} foreach keys %config; + foreach my $l (MDK::Common::File::cat_($configfile)) { + my ($key, @values) = split ' ', $l; + ${$config{$key}{var}} = \@values if scalar @values; + } + # special cases: + $::rpmdragora_options{'no-confirmation'} = $no_confirmation->[0] if !defined $::rpmdragora_options{'no-confirmation'}; + $ManaTools::Rpmdragora::init::default_list_mode = $tree_mode->[0] if ref $tree_mode && !$ManaTools::Rpmdragora::init::overriding_config; +} + +sub writeconf() { + return if $::env; + unlink $configfile; + + # special case: + $no_confirmation->[0] = $::rpmdragora_options{'no-confirmation'}; + my @config_content = map { "$_ " . (ref ${$config{$_}{var}} ? join(' ', @${$config{$_}{var}}) : '') . "\n" } sort keys %config; + MDK::Common::File::output($configfile, @config_content); + print "writeconf done!\n"; +} + +sub getbanner() { + $::MODE or return undef; + if (0) { + +{ + remove => $loc->N("Software Packages Removal"), + update => $loc->N("Software Packages Update"), + install => $loc->N("Software Packages Installation"), + }; + } +# Gtk2::Banner->new($ugtk2::wm_icon, $::MODE eq 'update' ? $loc->N("Software Packages Update") : $loc->N("Software Management")); +} + + +#============================================================= + +=head2 interactive_msg + +=head3 INPUT + + $title: dialog title + $contents: dialog text + %options: optional HASH containing { + scroll => Rich Text with scroll bar used + yesno => dialog with "yes" and "no" buttons (deafult yes) + dont_ask_again => add a checkbox with "dont ask again text" + main_dialog => create a main dialog instead of a popup one + min_size => {columns => X, lines => Y} for minimum dialog size, + } + +=head3 OUTPUT + + retval: if dont_ask_again HASH reference containig { + value => 1 yes (or ok) pressed, 0 no pressed + dont_ask_again => 1 if checked + } + or if dont_ask_again is not passed: + 1 yes (or ok) pressed, 0 no pressed + +=head3 DESCRIPTION + + This function shows a dialog with contents text and return the button + pressed (1 ok or yes), optionally returns the checkbox value if dont_ask_again is + passed. + If min_size is passed a minimum dialog size is set (default is 75x6) see libyui + createMinSize documenatation for explanation. + +=cut + +#============================================================= +sub interactive_msg { + my ($title, $contents, %options) = @_; + + my $retVal = 0; + + my $info; + + if ($options{scroll}) { + ## richtext needs
instead of '\n' + $contents =~ s/\n/
/g; + } + + my $oldTitle = yui::YUI::app()->applicationTitle(); + yui::YUI::app()->setApplicationTitle($title); + + my $factory = yui::YUI::widgetFactory; + my $dlg = $options{main_dialog} ? + $factory->createMainDialog() : + $factory->createPopupDialog(); + my $columns = $options{min_size}->{columns} || 75; + my $lines = $options{min_size}->{lines} || 6; + my $minSize = $factory->createMinSize( $dlg, $columns, $lines); + my $vbox = $factory->createVBox( $minSize ); + my $midhbox = $factory->createHBox($vbox); + ## app description + my $toprightvbox = $factory->createVBox($midhbox); + $toprightvbox->setWeight($yui::YD_HORIZ, 5); + $factory->createSpacing($toprightvbox,$yui::YD_HORIZ, 0, 5.0); + $factory->createRichText($toprightvbox, $contents, !$options{scroll}); + $factory->createSpacing($toprightvbox, $yui::YD_HORIZ, 0, 5.0); + + if ($options{dont_ask_again}){ + my $hbox = $factory->createHBox($vbox); + my $align = $factory->createRight($hbox); + $info->{checkbox} = $factory->createCheckBox($align, $loc->N("Do not ask me next time")); + } + + my $bottomhbox = $factory->createHBox($vbox); + if ($options{yesno}) { + my $alignRight = $factory->createRight($bottomhbox); + my $buttonBox = $factory->createHBox($alignRight); + + $info->{B1} = $factory->createPushButton($buttonBox, $options{text}{yes} || $loc->N("Yes")); + $info->{B2} = $factory->createPushButton($buttonBox, $options{text}{no} || $loc->N("No")); + } + else { + $info->{B1} = $factory->createPushButton($bottomhbox, $loc->N("Ok")); + } + + $dlg->setDefaultButton($info->{B1}); + + while (1) { + my $event = $dlg->waitForEvent(); + my $eventType = $event->eventType(); + #event type checking + if ($eventType == $yui::YEvent::CancelEvent) { + $retVal = 1; ##default value + last; + } + elsif ($eventType == $yui::YEvent::WidgetEvent) { + # widget selected + my $widget = $event->widget(); + + if ($info->{B1} && $widget == $info->{B1}) { + $retVal = 1; + last; + } + elsif ($info->{B2} && $widget == $info->{B2}) { + last; + } + } + } + + if ($info->{checkbox}) { + my $value = $retVal; + $retVal = undef; + $retVal->{value} = $value; + $retVal->{dont_ask_again} = $info->{checkbox}->isChecked(); + } + + $dlg->destroy(); + yui::YUI::app()->setApplicationTitle($oldTitle); + + return $retVal; +} + +sub interactive_list { + my ($title, $contents, $list, $callback, %options) = @_; + + my $factory = yui::YUI::widgetFactory; + my $mainw = $factory->createPopupDialog(); + my $vbox = $factory->createVBox($mainw); + my $lbltitle = $factory->createLabel($vbox, $loc->N("Dependencies")); + my $left = $factory->createLeft($factory->createHBox($vbox)); + my $radiobuttongroup = $factory->createRadioButtonGroup($left); + my $rbbox = $factory->createVBox($radiobuttongroup); + foreach my $item (@$list) { + my $radiobutton = $factory->createRadioButton($rbbox,$item); + if ($item eq $list->[0]) { + # select first by default + $radiobutton->setValue(1); + } + $radiobutton->setNotify(0); + $radiobuttongroup->addRadioButton($radiobutton); + } + my $submitButton = $factory->createIconButton($vbox,"", $loc->N("OK")); + my $choice; + + while(1) { + my $event = $mainw->waitForEvent(); + my $eventType = $event->eventType(); + #event type checking + if ($eventType == $yui::YEvent::CancelEvent) { + $mainw->destroy(); + last; + } + elsif ($eventType == $yui::YEvent::WidgetEvent) { + # widget selected + my $widget = $event->widget(); + + if($widget == $submitButton) { + # NOTE if for any reason radio button is not checked let's take the first package + $choice = $radiobuttongroup->currentButton() ? $radiobuttongroup->currentButton()->label() : $list->[0]; + $choice =~s/\&//g; + last; + } + } + } + $mainw->destroy(); + return $choice; +} + +sub interactive_list_ { interactive_list(@_, if_($::main_window, transient => $::main_window)) } + +sub fatal_msg { + interactive_msg @_; + myexit -1; +} + +sub wait_msg { + my $msg = shift; + + my $label = $msg ? $msg : $loc->N("Please wait"); + + my $factory = yui::YUI::widgetFactory; + my $mainw = $factory->createPopupDialog(); + my $vbox = $factory->createVBox($mainw); + my $title = $factory->createLabel($vbox, $label); + #$mainw->recalcLayout(); + #$mainw->doneMultipleChanges(); + $mainw->waitForEvent(10); + $mainw->pollEvent(); + #$mainw->recalcLayout(); + #$mainw->doneMultipleChanges(); + yui::YUI::app()->busyCursor(); + + $mainw; +} + +sub remove_wait_msg { + my $w = shift; + #gtkset_mousecursor_normal($w->{rwindow}->window); + $w->destroy; + yui::YUI::app()->normalCursor(); +} + +sub but { " $_[0] " } +sub but_ { " $_[0] " } + +#============================================================= + +=head2 slow_func + +=head3 INPUT + + $func: function to be executed with a busy cursor or waiting + dialog + $msg: message to be shown in ncurses waiting dialog (if any) + +=head3 DESCRIPTION + + This function executes a given function with a busy cursor set + in graphical environment, or with a waiting dialog if in ncurses + text mode + +=cut + +#============================================================= +sub slow_func (&) { + my ($func, $msg) = @_; + + my $retval = 1; + # NOTE busy cursor is not implemented in yui-ncurses + # but we can avoid a waiting dialog in Gtk and QT + if (yui::YUI::app()->isTextMode()) { + my $w = wait_msg($msg); + $retval = $func->(); + remove_wait_msg($w) + } + else { + yui::YUI::app()->busyCursor(); + $retval = $func->(); + yui::YUI::app()->normalCursor(); + } + return $retval; +} + +sub statusbar_msg { + my ($msg, $o_timeout) = @_; + + unless ($::statusbar) { #- fallback if no status bar + return wait_msg($msg); + } + + $::statusbar->setLabel($msg); + #- always use the same context description for now + #my $cx = $::statusbar->get_context_id("foo"); + #$::w and $::w->{rwindow} and gtkset_mousecursor_wait($::w->{rwindow}->window); + #- returns a msg_id to be passed optionnally to statusbar_msg_remove + #my $id = $::statusbar->push($cx, $msg); + #gtkflush(); + #Glib::Timeout->add(5000, sub { statusbar_msg_remove($id); 0 }) if $o_timeout; + $::statusbar->setTimeout ( 5000 ); + Glib::Timeout->add(5000, sub { statusbar_msg_remove(); 0 }) if $o_timeout; + #$id; + return 1; +} + +sub statusbar_msg_remove { + if (!$::statusbar) { #- fallback if no status bar + my $id = shift; + return remove_wait_msg($id);; + } + my ($msg_id) = @_; + #my $cx = $::statusbar->get_context_id("foo"); + #if (defined $msg_id) { + #$::statusbar->remove($cx, $msg_id); + #} else { + #$::statusbar->pop($cx); + #} + #$::w and $::w->{rwindow} and gtkset_mousecursor_normal($::w->{rwindow}->window); + $::statusbar->setLabel(""); +} + +sub slow_func_statusbar ($$&) { + my ($msg, $w, $func) = @_; + yui::YUI::app()->busyCursor(); + + my $msg_id = statusbar_msg($msg); + $func->(); + statusbar_msg_remove($msg_id); + + yui::YUI::app()->normalCursor(); +} + +my %u2l = ( + ar => $loc->N_("Argentina"), + at => $loc->N_("Austria"), + au => $loc->N_("Australia"), + by => $loc->N_("Belarus"), + be => $loc->N_("Belgium"), + br => $loc->N_("Brazil"), + gb => $loc->N_("Britain"), + ca => $loc->N_("Canada"), + ch => $loc->N_("Switzerland"), + cr => $loc->N_("Costa Rica"), + cz => $loc->N_("Czech Republic"), + de => $loc->N_("Germany"), + dk => $loc->N_("Danmark"), + ec => $loc->N_("Ecuador"), + el => $loc->N_("Greece"), + es => $loc->N_("Spain"), + fi => $loc->N_("Finland"), + fr => $loc->N_("France"), + gr => $loc->N_("Greece"), + hu => $loc->N_("Hungary"), + id => $loc->N_("Indonesia"), + il => $loc->N_("Israel"), + it => $loc->N_("Italy"), + jp => $loc->N_("Japan"), + ko => $loc->N_("Korea"), + nl => $loc->N_("Netherlands"), + no => $loc->N_("Norway"), + pl => $loc->N_("Poland"), + pt => $loc->N_("Portugal"), + ru => $loc->N_("Russia"), + se => $loc->N_("Sweden"), + sg => $loc->N_("Singapore"), + sk => $loc->N_("Slovakia"), + za => $loc->N_("South Africa"), + tw => $loc->N_("Taiwan"), + th => $loc->N_("Thailand"), + tr => $loc->N_("Turkey"), + uk => $loc->N_("United Kingdom"), + cn => $loc->N_("China"), + us => $loc->N_("United States"), + com => $loc->N_("United States"), + org => $loc->N_("United States"), + net => $loc->N_("United States"), + edu => $loc->N_("United States"), +); +my $us = [ qw(us com org net edu) ]; +my %t2l = ( + 'America/\w+' => $us, + 'Asia/Tel_Aviv' => [ qw(il ru it cz at de fr se) ], + 'Asia/Tokyo' => [ qw(jp ko tw), @$us ], + 'Asia/Seoul' => [ qw(ko jp tw), @$us ], + 'Asia/Taipei' => [ qw(tw jp), @$us ], + 'Asia/(Shanghai|Beijing)' => [ qw(cn tw sg), @$us ], + 'Asia/Singapore' => [ qw(cn sg), @$us ], + 'Atlantic/Reykjavik' => [ qw(gb uk no se fi dk), @$us, qw(nl de fr at cz it) ], + 'Australia/\w+' => [ qw(au jp ko tw), @$us ], + 'Brazil/\w+' => [ 'br', @$us ], + 'Canada/\w+' => [ 'ca', @$us ], + 'Europe/Amsterdam' => [ qw(nl be de at cz fr se dk it) ], + 'Europe/Athens' => [ qw(gr pl cz de it nl at fr) ], + 'Europe/Berlin' => [ qw(de be at nl cz it fr se) ], + 'Europe/Brussels' => [ qw(be de nl fr cz at it se) ], + 'Europe/Budapest' => [ qw(cz it at de fr nl se) ], + 'Europe/Copenhagen' => [ qw(dk nl de be se at cz it) ], + 'Europe/Dublin' => [ qw(gb uk fr be nl dk se cz it) ], + 'Europe/Helsinki' => [ qw(fi se no nl be de fr at it) ], + 'Europe/Istanbul' => [ qw(il ru it cz it at de fr nl se) ], + 'Europe/Lisbon' => [ qw(pt es fr it cz at de se) ], + 'Europe/London' => [ qw(gb uk fr be nl de at cz se it) ], + 'Europe/Madrid' => [ qw(es fr pt it cz at de se) ], + 'Europe/Moscow' => [ qw(ru de pl cz at se be fr it) ], + 'Europe/Oslo' => [ qw(no se fi dk de be at cz it) ], + 'Europe/Paris' => [ qw(fr be de at cz nl it se) ], + 'Europe/Prague' => [ qw(cz it at de fr nl se) ], + 'Europe/Rome' => [ qw(it fr cz de at nl se) ], + 'Europe/Stockholm' => [ qw(se no dk fi nl de at cz fr it) ], + 'Europe/Vienna' => [ qw(at de cz it fr nl se) ], +); + +#- get distrib release number (2006.0, etc) +sub etc_version() { + (my $v) = split / /, MDK::Common::File::cat_('/etc/version'); + return $v; +} + +#- returns the keyword describing the type of the distribution. +#- the parameter indicates whether we want base or update sources +sub distro_type { + my ($want_base_distro) = @_; + return 'cauldron' if $mageia_release =~ /cauldron/i; + #- we can't use updates for community while official is not out (release ends in ".0") + if ($want_base_distro || $mageia_release =~ /community/i && etc_version() =~ /\.0$/) { + return 'official' if $mageia_release =~ /official|limited/i; + return 'community' if $mageia_release =~ /community/i; + #- unknown: fallback to updates + } + return 'updates'; +} + +sub compat_arch_for_updates($) { + # FIXME: We prefer 64-bit packages to update on biarch platforms, + # since the system is populated with 64-bit packages anyway. + my ($arch) = @_; + return $arch =~ /x86_64|amd64/ if arch() eq 'x86_64'; + MDK::Common::System::compat_arch($arch); +} + +sub add_medium_and_check { + my ($urpm, $options) = splice @_, 0, 2; + my @newnames = ($_[0]); #- names of added media + my $fatal_msg; + my @error_msgs; + local $urpm->{fatal} = sub { printf STDERR "Fatal: %s\n", $_[1]; $fatal_msg = $_[1]; goto fatal_error }; + local $urpm->{error} = sub { printf STDERR "Error: %s\n", $_[0]; push @error_msgs, $_[0] }; + if ($options->{distrib}) { + @newnames = urpm::media::add_distrib_media($urpm, @_); + } else { + urpm::media::add_medium($urpm, @_); + } + if (@error_msgs) { + interactive_msg( + $loc->N("Error"), + $loc->N("Unable to add medium, errors reported:\n\n%s", + join("\n", map { MDK::Common::String::formatAlaTeX($_) } @error_msgs)) . "\n\n" . $loc->N("Medium: ") . "$_[0] ($_[1])", + scroll => 1, + ); + return 0; + } + + foreach my $name (@newnames) { + urpm::download::set_proxy_config($_, $options->{proxy}{$_}, $name) foreach keys %{$options->{proxy} || {}}; + } + + if (update_sources_check($urpm, $options, $loc->N_("Unable to add medium, errors reported:\n\n%s"), @newnames)) { + urpm::media::write_config($urpm); + $options->{proxy} and urpm::download::dump_proxy_config(); + } else { + urpm::media::read_config($urpm, 0); + return 0; + } + + my %newnames; @newnames{@newnames} = (); + if (any { exists $newnames{$_->{name}} } @{$urpm->{media}}) { + return 1; + } else { + interactive_msg($loc->N("Error"), $loc->N("Unable to create medium.")); + return 0; + } + + fatal_error: + interactive_msg($loc->N("Failure when adding medium"), + $loc->N("There was a problem adding medium:\n\n%s", $fatal_msg)); + return 0; +} + +sub update_sources_check { + my ($urpm, $options, $error_msg, @media) = @_; + my @error_msgs; + local $urpm->{fatal} = sub { push @error_msgs, $_[1]; goto fatal_error }; + local $urpm->{error} = sub { push @error_msgs, $_[0] }; + update_sources($urpm, %$options, noclean => 1, medialist => \@media); + fatal_error: + if (@error_msgs) { + interactive_msg($loc->N("Error"), $loc->N($error_msg, join("\n", map { formatAlaTeX($_) } @error_msgs)), scroll => 1); + return 0; + } + return 1; +} + +sub update_sources { + my ($urpm, %options) = @_; + my $cancel = 0; + + + my $factory = yui::YUI::widgetFactory; + + ## set new title to get it in dialog + yui::YUI::app()->setApplicationTitle($loc->N("rpmdragora")); + + my $dlg = $factory->createPopupDialog(); + my $minSize = $factory->createMinSize( $dlg, 80, 5 ); + my $vbox = $factory->createVBox($minSize); + my $hbox = $factory->createHBox($factory->createLeft($vbox)); + my $label = $factory->createRichText($hbox, $loc->N("Please wait, updating media..."), 1 ); + $label->setWeight($yui::YD_HORIZ, 1); + $label->setWeight($yui::YD_VERT, 1); + + my $pb = $factory->createProgressBar( $vbox, ""); + $pb->setValue(0); + # NOTE urpm::media::update_those_media seems not to say anything + # when downloads and tests md5sum + # a fake event (timeout 10 msec) allow to draw the waiting + # dialog + $dlg->waitForEvent(10); + $dlg->pollEvent(); + + my @media; @media = @{$options{medialist}} if ref $options{medialist}; + my $outerfatal = $urpm->{fatal}; + local $urpm->{fatal} = sub { $outerfatal->(@_) }; + urpm::media::update_those_media($urpm, [ urpm::media::select_media_by_name($urpm, \@media) ], + %options, allow_failures => 1, + callback => sub { + $cancel and goto cancel_update; + my ($type, $media) = @_; + goto cancel_update if $type !~ /^(?:start|progress|end)$/ && @media && !member($media, @media); + if ($type eq 'failed') { + $urpm->{fatal}->($loc->N("Error retrieving packages"), +$loc->N("It's impossible to retrieve the list of new packages from the media +`%s'. Either this update media is misconfigured, and in this case +you should use the Software Media Manager to remove it and re-add it in order +to reconfigure it, either it is currently unreachable and you should retry +later.", + $media)); + } else { + show_urpm_progress($label, $pb, @_); + $dlg->pollEvent(); + } + }, + ); + + $pb->setValue(100); + $dlg->waitForEvent(10); + $dlg->pollEvent(); + +cancel_update: + $dlg->destroy(); +} + +sub show_urpm_progress { + my ($label, $pb, $mode, $file, $percent, $total, $eta, $speed) = @_; + $file =~ s|([^:]*://[^/:\@]*:)[^/:\@]*(\@.*)|$1xxxx$2|; #- if needed... + state $medium; + + if ($mode eq 'copy') { + $pb->setValue(0); + $label->setValue($loc->N("Copying file for medium `%s'...", $file)); + } elsif ($mode eq 'parse') { + $pb->setValue(0); + $label->setValue($loc->N("Examining file of medium `%s'...", $file)); + } elsif ($mode eq 'retrieve') { + $pb->setValue(0); + $label->setValue($loc->N("Examining remote file of medium `%s'...", $file)); + $medium = $file; + } elsif ($mode eq 'done') { + $pb->setValue(100); + $label->setValue($label->value() . $loc->N(" done.")); + $medium = undef; + } elsif ($mode eq 'failed') { + $pb->setValue(100); + $label->setValue($label->value() . $loc->N(" failed!")); + $medium = undef; + } else { + # FIXME: we're displaying misplaced quotes such as "downloading `foobar from 'medium Main Updates'´" + $file = $medium && length($file) < 40 ? #-PO: We're downloading the said file from the said medium + $loc->N("%s from medium %s", basename($file), $medium) + : basename($file); + if ($mode eq 'start') { + $pb->setValue(0); + $label->setValue($loc->N("Starting download of `%s'...", $file)); + } elsif ($mode eq 'progress') { + if (defined $total && defined $eta) { + $pb->setValue($percent); + $label->setValue($loc->N("Download of `%s'\ntime to go:%s, speed:%s", $file, $eta, $speed)); + } else { + $pb->setValue($percent); + $label->setValue($loc->N("Download of `%s'\nspeed:%s", $file, $speed)); + } + } + } +} + + +sub update_sources_interactive { + my ($urpm, %options) = @_; + + my @media = grep { ! $_->{ignore} } @{$urpm->{media}}; + unless (@media) { + interactive_msg($loc->N("Warning"), $loc->N("No active medium found. You must enable some media to be able to update them.")); + return 0; + } + + my $appTitle = yui::YUI::app()->applicationTitle(); + + ## set new title to get it in dialog + yui::YUI::app()->setApplicationTitle($loc->N("Update media")); + + my $retVal = 0; + my $mageiaPlugin = "mga"; + my $factory = yui::YUI::widgetFactory; + my $mgaFactory = yui::YExternalWidgets::externalWidgetFactory($mageiaPlugin); + $mgaFactory = yui::YMGAWidgetFactory::getYMGAWidgetFactory($mgaFactory); + + my $dialog = $factory->createPopupDialog(); + my $minSize = $factory->createMinSize( $dialog, 60, 15 ); + my $vbox = $factory->createVBox($minSize); + + my $yTableHeader = new yui::YTableHeader(); + $yTableHeader->addColumn("", $yui::YAlignBegin); + $yTableHeader->addColumn($loc->N("Media"), $yui::YAlignBegin); + + my $mediaTable = $mgaFactory->createCBTable($vbox, $yTableHeader, $yui::YCBTableCheckBoxOnFirstColumn); + + my $itemCollection = new yui::YItemCollection; + foreach (@media) { + my $item = new yui::YCBTableItem($_->{name}); + $item->setLabel($_->{name}); + $itemCollection->push($item); + $item->DISOWN(); + } + $mediaTable->addItems($itemCollection); + + # dialog buttons + $factory->createVSpacing($vbox, 1.0); + ## Window push buttons + my $hbox = $factory->createHBox( $vbox ); + + my $cancelButton = $factory->createPushButton($hbox, $loc->N("Cancel") ); + my $selectButton = $factory->createPushButton($hbox, $loc->N("Select all") ); + my $updateButton = $factory->createPushButton($hbox, $loc->N("Update") ); + + 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 == $cancelButton) { + last; + } + elsif ($widget == $selectButton) { + yui::YUI::app()->busyCursor(); + yui::YUI::ui()->blockEvents(); + $dialog->startMultipleChanges(); + for (my $it = $mediaTable->itemsBegin(); $it != $mediaTable->itemsEnd(); ) { + my $item = $mediaTable->YItemIteratorToYItem($it); + if ($item) { + $mediaTable->checkItem($item, 1); + # NOTE for some reasons it is never == $mediaTable->itemsEnd() + if ($item->index() == $mediaTable->itemsCount()-1) { + last; + } + } + $it = $mediaTable->nextItem($it); + } + $dialog->recalcLayout(); + $dialog->doneMultipleChanges(); + yui::YUI::ui()->unblockEvents(); + yui::YUI::app()->normalCursor(); + + } + elsif ($widget == $updateButton) { + yui::YUI::app()->busyCursor(); + my @checked_media; + for (my $it = $mediaTable->itemsBegin(); $it != $mediaTable->itemsEnd(); ) { + my $item = $mediaTable->YItemIteratorToYItem($it); + $item = $mediaTable->toCBYTableItem($item); + if ($item) { + if ($item->checked()) { + push @checked_media, $item->label(); + } + # NOTE for some reasons it is never == $mediaTable->itemsEnd() + if ($item->index() == $mediaTable->itemsCount()-1) { + last; + } + } + $it = $mediaTable->nextItem($it); + } + + $retVal = update_sources_noninteractive($urpm, \@checked_media, %options); + yui::YUI::app()->normalCursor(); + last; + } + } + } + + $dialog->destroy(); + + #restore old application title + yui::YUI::app()->setApplicationTitle($appTitle) if $appTitle; + + return $retVal; +} + +sub update_sources_noninteractive { + my ($urpm, $media, %options) = @_; + + urpm::media::select_media_by_name($urpm, $media); + update_sources_check( + $urpm, + {}, + $loc->N_("Unable to update medium; it will be automatically disabled.\n\nErrors:\n%s"), + @$media, + ); + return 1; +} + +sub add_distrib_update_media { + my ($urpm, $mirror, %options) = @_; + #- ensure a unique medium name + my $medium_name = $ManaTools::rpmdragora::mageia_release =~ /(\d+\.\d+) \((\w+)\)/ ? $2 . $1 . '-' : 'distrib'; + my $initial_number = 1 + max map { $_->{name} =~ /\(\Q$medium_name\E(\d+)\b/ ? $1 : 0 } @{$urpm->{media}}; + add_medium_and_check( + $urpm, + { nolock => 1, distrib => 1 }, + $medium_name, + ($mirror ? $mirror->{url} : (undef, mirrorlist => '$MIRRORLIST')), + probe_with => 'synthesis', initial_number => $initial_number, %options, + usedistrib => 1, + ); +} + +sub warn_for_network_need { + my ($message, %options) = @_; + $message ||= + $branded + ? $loc->N("I need to access internet to get the mirror list. +Please check that your network is currently running. + +Is it ok to continue?") + : $loc->N("I need to contact the Mageia website to get the mirror list. +Please check that your network is currently running. + +Is it ok to continue?"); + interactive_msg($loc->N("Mirror choice"), $message, yesno => 1, %options) or return ''; +} + +sub choose_mirror { + my ($urpm, %options) = @_; + delete $options{message}; + my @transient_options = exists $options{transient} ? (transient => $options{transient}) : (); + warn_for_network_need($options{message}, %options) or return; + my @mirrors = eval { mirrors($urpm, $options{want_base_distro}) }; + my $error = $@; + if ($error) { + $error = "\n$error\n"; + interactive_msg($loc->N("Error during download"), + ($branded + ? $loc->N("There was an error downloading the mirror list:\n%s\n +The network, or the website, may be unavailable. +Please try again later.", $error) + : $loc->N("There was an error downloading the mirror list:\n%s\n +The network, or the Mageia website, may be unavailable. +Please try again later.", $error)), %options + ); + return ''; + } + + !@mirrors and interactive_msg($loc->N("No mirror"), + ($branded + ? $loc->N("I can't find any suitable mirror.") + : $loc->N("I can't find any suitable mirror.\n +There can be many reasons for this problem; the most frequent is +the case when the architecture of your processor is not supported +by Mageia Official Updates.")), %options + ), return ''; + + my @mirrorlist = map {$_->{country} . "|" . $_->{url}} @mirrors; + + my $sh_gui = ManaTools::Shared::GUI->new(); + my $mirror = $sh_gui->ask_fromTreeList({title => $loc->N("Mirror choice"), + header => $loc->N("Please choose the desired mirror."), + default_button => 1, + item_separator => "|", + default_item => $mirrors[0]->{url}, + skip_path => 1, + list => \@mirrorlist } + ); + + return $mirror ? { url => $mirror} : undef; + +} + + + + + + + +#- Check whether the default update media (added by installation) +#- matches the current mdk version +sub check_update_media_version { + my $urpm = shift; + foreach (@_) { + if ($_->{name} =~ /(\d+\.\d+).*\bftp\du\b/ && $1 ne $distro_version) { + interactive_msg( + $loc->N("Warning"), + $branded + ? $loc->N("Your medium `%s', used for updates, does not match the version of %s you're running (%s). +It will be disabled.", + $_->{name}, $distrib{system}, $distrib{product}) + : $loc->N("Your medium `%s', used for updates, does not match the version of Mageia you're running (%s). +It will be disabled.", + $_->{name}, $distro_version) + ); + $_->{ignore} = 1; + urpm::media::write_config($urpm) if -w $urpm->{config}; + return 0; + } + } + 1; +} + + + +sub mirrors { + my ($urpm, $want_base_distro) = @_; + my $cachedir = $urpm->{cachedir} || '/root'; + require mirror; + mirror::register_downloader( + sub { + my ($url) = @_; + my $file = $url; + $file =~ s!.*/!$cachedir/!; + unlink $file; # prevent "partial file" errors + MDK::Common::Func::before_leaving(sub { unlink $file }); + + my ($gurpm, $id, $canceled); + # display a message in statusbar (if availlable): + $::statusbar and $id = statusbar_msg( + $branded + ? $loc->N("Please wait, downloading mirror addresses.") + : $loc->N("Please wait, downloading mirror addresses from the Mageia website."), + 0); + my $_clean_guard = MDK::Common::Func::before_leaving { + undef $gurpm; + $id and statusbar_msg_remove($id); + }; + + require ManaTools::Rpmdragora::gurpm; + require ManaTools::Rpmdragora::pkg; + + my $res = urpm::download::sync_url($urpm, $url, + dir => $cachedir, + callback => sub { + $gurpm ||= + ManaTools::Rpmdragora::gurpm->new( + text => $loc->N("Please wait"), + ); + $canceled ||= + !ManaTools::Rpmdragora::pkg::download_callback($gurpm, @_); + $gurpm->flush(); + }, + ); + $res or die $loc->N("retrieval of [%s] failed", $file) . "\n"; + return $canceled ? () : MDK::Common::File::cat_($file); + }); + my @mirrors = @{ mirror::list(urpm::mirrors::parse_LDAP_namespace_structure(MDK::Common::File::cat_('/etc/product.id')), 'distrib') || [] }; + + require ManaTools::Shared::TimeZone; + my $tzo = ManaTools::Shared::TimeZone->new(); + my $tz = $tzo->readConfiguration()->{ZONE}; + foreach my $mirror (@mirrors) { + my $goodness = 0; + my $pri_mirr = defined ($t2l{$tz}) ? $t2l{$tz} : $us; + my $ind = 0; + foreach (@{$pri_mirr}) { + if (($_ eq lc($mirror->{zone})) || ($_ eq lc($mirror->{country}))) { + $goodness = scalar(@{$pri_mirr}) - $ind; + } + $ind ++; + } + + $mirror->{goodness} = $goodness + rand(); + $mirror->{country} = $u2l{lc($mirror->{country})} ? $loc->N($u2l{lc($mirror->{country})}) : $mirror->{country}; + } + unless (-x '/usr/bin/rsync') { + @mirrors = grep { $_->{url} !~ /^rsync:/ } @mirrors; + } + return sort { $b->{goodness} <=> $a->{goodness} } @mirrors; +} + + + + + +sub open_help { + my ($mode) = @_; + require ManaTools::Shared::RunProgram; + ManaTools::Shared::RunProgram::raw({ detach => 1, as_user => 1 }, 'drakhelp', '--id', $mode ? "software-management-$mode" : 'software-management'); + my $_s = $loc->N("Help launched in background"); + statusbar_msg($loc->N("The help window has been started, it should appear shortly on your desktop."), 1); +} + +sub run_drakbug { + my ($id) = @_; + require ManaTools::Shared::RunProgram; + ManaTools::Shared::RunProgram::raw({ detach => 1, as_user => 1 }, 'drakbug', '--report', $id); +} + +#mygtk2::add_icon_path('/usr/share/mcc/themes/default/'); +sub get_icon { + my ($mcc_icon, $fallback_icon) = @_; + my $icon = eval { mygtk2::_find_imgfile($mcc_icon) }; + $icon ||= eval { mygtk2::_find_imgfile($fallback_icon) }; + $icon; +} + +sub strip_first_underscore { join '', map { s/_//; $_ } @_ } + +1; diff --git a/po/adminpanel.pot b/po/adminpanel.pot deleted file mode 100644 index ff88697..0000000 --- a/po/adminpanel.pot +++ /dev/null @@ -1,3445 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-01-13 23:36+0100\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME \n" -"Language-Team: LANGUAGE \n" -"Language: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=CHARSET\n" -"Content-Transfer-Encoding: 8bit\n" - -#: lib/ManaTools/Shared/Shorewall.pm:182 -msgid "Keep custom rules" -msgstr "" - -#: lib/ManaTools/Shared/Shorewall.pm:183 -msgid "Drop custom rules" -msgstr "" - -#: lib/ManaTools/Shared/TimeZone.pm:478 lib/ManaTools/Shared/TimeZone.pm:479 -msgid "All servers" -msgstr "" - -#: lib/ManaTools/Shared/Users.pm:379 -msgid "Name field is empty please provide a name" -msgstr "" - -#: lib/ManaTools/Shared/Users.pm:384 -msgid "" -"The name must start with a letter and contain only lower cased latin " -"letters, numbers, '.', '-' and '_'" -msgstr "" - -#: lib/ManaTools/Shared/Users.pm:387 -#, perl-format -msgid "Name is too long. Maximum length is %d" -msgstr "" - -#: lib/ManaTools/Shared/Users.pm:389 lib/ManaTools/Shared/GUI.pm:116 -#: lib/ManaTools/Shared/GUI.pm:162 lib/ManaTools/Shared/GUI.pm:206 -#: lib/ManaTools/Shared/GUI.pm:256 lib/ManaTools/Shared/GUI.pm:1069 -#: lib/ManaTools/Module/AdminMouse.pm:191 lib/ManaTools/Module/Clock.pm:284 -#: lib/ManaTools/Module/Users.pm:335 lib/ManaTools/Module/Users.pm:581 -#: lib/ManaTools/Module/Users.pm:861 lib/ManaTools/Module/Users.pm:1995 -#: lib/ManaTools/Module/Users.pm:2155 lib/ManaTools/Rpmdragora/gui.pm:1281 -#: lib/ManaTools/Rpmdragora/rpmnew.pm:244 -#: lib/ManaTools/Rpmdragora/pkg.pm:652 lib/ManaTools/Rpmdragora/pkg.pm:920 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:309 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:527 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:811 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:939 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1017 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1113 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1186 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1379 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1704 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:2182 -#: lib/ManaTools/rpmdragora.pm:164 lib/ManaTools/rpmdragora.pm:342 -msgid "Ok" -msgstr "" - -#: lib/ManaTools/Shared/Users.pm:815 -#, perl-format -msgid "You cannot remove user <%s> from their primary group" -msgstr "" - -#: lib/ManaTools/Shared/Users.pm:1158 -msgid "Locked" -msgstr "" - -#: lib/ManaTools/Shared/Users.pm:1158 -msgid "Expired" -msgstr "" - -#: lib/ManaTools/Shared/GUI.pm:257 lib/ManaTools/Shared/GUI.pm:491 -#: lib/ManaTools/Shared/GUI.pm:609 lib/ManaTools/Shared/GUI.pm:916 -#: lib/ManaTools/Module/AdminMouse.pm:190 lib/ManaTools/Module/Proxy.pm:339 -#: lib/ManaTools/Module/Clock.pm:283 -#: lib/ManaTools/Module/DisplayManager.pm:255 -#: lib/ManaTools/Module/Firewall.pm:616 lib/ManaTools/Module/Firewall.pm:827 -#: lib/ManaTools/Module/Users.pm:334 lib/ManaTools/Module/Users.pm:405 -#: lib/ManaTools/Module/Users.pm:496 lib/ManaTools/Module/Users.pm:580 -#: lib/ManaTools/Module/Users.pm:860 lib/ManaTools/Module/Users.pm:1994 -#: lib/ManaTools/Module/Users.pm:2154 lib/ManaTools/Module/Hosts.pm:191 -#: lib/ManaTools/Module/Hosts.pm:275 lib/ManaTools/Module/Hosts.pm:462 -#: lib/ManaTools/Rpmdragora/gui.pm:1280 lib/ManaTools/Rpmdragora/pkg.pm:920 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:307 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:525 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:767 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:811 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:941 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1018 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1120 -#: lib/ManaTools/rpmdragora.pm:868 -msgid "Cancel" -msgstr "" - -#: lib/ManaTools/Shared/GUI.pm:309 lib/ManaTools/rpmdragora.pm:338 -msgid "Yes" -msgstr "" - -#: lib/ManaTools/Shared/GUI.pm:310 lib/ManaTools/rpmdragora.pm:339 -msgid "No" -msgstr "" - -#: lib/ManaTools/Shared/GUI.pm:490 lib/ManaTools/Shared/GUI.pm:608 -#: lib/ManaTools/Shared/GUI.pm:915 -msgid "Select" -msgstr "" - -#: lib/ManaTools/MainDisplay.pm:204 lib/ManaTools/Module/Services.pm:465 -#: lib/ManaTools/Module/AdminMouse.pm:221 lib/ManaTools/Module/Clock.pm:465 -#: lib/ManaTools/Module/LogViewer.pm:356 lib/ManaTools/Module/Users.pm:2461 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1725 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:2003 -msgid "_: Translator(s) name(s) & email(s)\n" -msgstr "" - -#: lib/ManaTools/MainDisplay.pm:210 lib/ManaTools/Module/Services.pm:470 -#: lib/ManaTools/Module/AdminMouse.pm:213 lib/ManaTools/Module/Clock.pm:470 -#: lib/ManaTools/Module/LogViewer.pm:361 lib/ManaTools/Module/Users.pm:2466 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1731 -#, perl-format -msgid "Copyright (C) %s Mageia community" -msgstr "" - -#: lib/ManaTools/MainDisplay.pm:211 lib/ManaTools/Module/Services.pm:471 -#: lib/ManaTools/Module/Clock.pm:471 lib/ManaTools/Module/LogViewer.pm:362 -#: lib/ManaTools/Module/Users.pm:2467 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1732 -msgid "GPLv2" -msgstr "" - -#: lib/ManaTools/MainDisplay.pm:212 -msgid "mpan is the mana-tools panel that collects all the utilities." -msgstr "" - -#: lib/ManaTools/MainDisplay.pm:213 lib/ManaTools/Module/Services.pm:474 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1734 -#, perl-format -msgid "" -"

Developers

\n" -"
  • %s
  • \n" -"
  • %s
  • \n" -"
\n" -"

Translators

\n" -"
  • %s
" -msgstr "" - -#: lib/ManaTools/MainDisplay.pm:314 lib/ManaTools/Module/Users.pm:2364 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1580 -msgid "File" -msgstr "" - -#: lib/ManaTools/MainDisplay.pm:315 -msgid "&Exit" -msgstr "" - -#: lib/ManaTools/MainDisplay.pm:326 lib/ManaTools/MainDisplay.pm:327 -#: lib/ManaTools/Module/Users.pm:2378 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1699 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:2181 -msgid "Help" -msgstr "" - -#: lib/ManaTools/MainDisplay.pm:328 lib/ManaTools/Module/Services.pm:426 -#: lib/ManaTools/Module/AdminMouse.pm:187 lib/ManaTools/Module/Proxy.pm:338 -#: lib/ManaTools/Module/Clock.pm:278 -#: lib/ManaTools/Module/DisplayManager.pm:254 -#: lib/ManaTools/Module/LogViewer.pm:333 -#: lib/ManaTools/Module/Firewall.pm:615 lib/ManaTools/Module/Firewall.pm:826 -#: lib/ManaTools/Module/Hosts.pm:461 -msgid "About" -msgstr "" - -#: lib/ManaTools/Module/Services.pm:198 -msgid "adminService" -msgstr "" - -#: lib/ManaTools/Module/Services.pm:305 -msgid "Start when requested" -msgstr "" - -#: lib/ManaTools/Module/Services.pm:308 -msgid "running" -msgstr "" - -#: lib/ManaTools/Module/Services.pm:308 -msgid "stopped" -msgstr "" - -#: lib/ManaTools/Module/Services.pm:386 -msgid "Manage system services by enabling or disabling them" -msgstr "" - -#: lib/ManaTools/Module/Services.pm:394 -msgid "Service" -msgstr "" - -#: lib/ManaTools/Module/Services.pm:395 lib/ManaTools/Module/Users.pm:1049 -msgid "Status" -msgstr "" - -#: lib/ManaTools/Module/Services.pm:396 -msgid "On boot" -msgstr "" - -#: lib/ManaTools/Module/Services.pm:407 lib/ManaTools/Rpmdragora/pkg.pm:1078 -msgid "Information" -msgstr "" - -#: lib/ManaTools/Module/Services.pm:415 -msgid "Start" -msgstr "" - -#: lib/ManaTools/Module/Services.pm:418 -msgid "Stop" -msgstr "" - -#: lib/ManaTools/Module/Services.pm:431 lib/ManaTools/Module/Users.pm:2365 -#: lib/ManaTools/Module/Users.pm:2397 -msgid "Refresh" -msgstr "" - -#: lib/ManaTools/Module/Services.pm:432 -msgid "Close" -msgstr "" - -#: lib/ManaTools/Module/Services.pm:472 -msgid "" -"adminService is the Mageia service and daemon management tool\n" -"\n" -" (from the original " -"idea of Mandriva draxservice)." -msgstr "" - -#: lib/ManaTools/Module/Services.pm:542 -#, perl-format -msgid "Starting %s" -msgstr "" - -#: lib/ManaTools/Module/Services.pm:562 -#, perl-format -msgid "Stopping %s" -msgstr "" - -#: lib/ManaTools/Module/AdminMouse.pm:49 -#: lib/ManaTools/Module/AdminMouse.pm:211 -msgid "AdminMouse" -msgstr "" - -#: lib/ManaTools/Module/AdminMouse.pm:90 -msgid "Please choose your type of mouse." -msgstr "" - -#: lib/ManaTools/Module/AdminMouse.pm:215 -msgid "" -"AdminMouse is the Mageia mouse management tool \n" -"(from the original idea of Mandriva mousedrake)." -msgstr "" - -#: lib/ManaTools/Module/AdminMouse.pm:217 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1998 -msgid "Mageia" -msgstr "" - -#: lib/ManaTools/Module/AdminMouse.pm:243 -msgid "Emulate third button?" -msgstr "" - -#: lib/ManaTools/Module/AdminMouse.pm:250 -msgid "Mouse Port" -msgstr "" - -#: lib/ManaTools/Module/AdminMouse.pm:251 -msgid "Please choose which serial port your mouse is connected to." -msgstr "" - -#: lib/ManaTools/Module/AdminMouse.pm:274 -msgid "Not implemented yet: configuration is not changed" -msgstr "" - -#: lib/ManaTools/Module/Proxy.pm:164 -#: lib/ManaTools/Module/DisplayManager.pm:155 -#: lib/ManaTools/Module/Users.pm:794 lib/ManaTools/Module/Users.pm:2334 -msgid "root privileges required" -msgstr "" - -#: lib/ManaTools/Module/Proxy.pm:192 -#: lib/ManaTools/Module/DisplayManager.pm:186 -msgid "X Restart Required" -msgstr "" - -#: lib/ManaTools/Module/Proxy.pm:192 -#: lib/ManaTools/Module/DisplayManager.pm:186 -msgid "You need to log out and back in again for changes to take effect" -msgstr "" - -#: lib/ManaTools/Module/Proxy.pm:227 -msgid "Proxy should be http://..." -msgstr "" - -#: lib/ManaTools/Module/Proxy.pm:232 -msgid "Proxy should be http://... or https://..." -msgstr "" - -#: lib/ManaTools/Module/Proxy.pm:237 -msgid "URL should begin with 'ftp:' or 'http:'" -msgstr "" - -#: lib/ManaTools/Module/Proxy.pm:250 -msgid "Proxies configuration" -msgstr "" - -#: lib/ManaTools/Module/Proxy.pm:295 -msgid "" -"Here you can set up your proxies configuration (eg: http://" -"my_caching_server:8080)" -msgstr "" - -#: lib/ManaTools/Module/Proxy.pm:303 -msgid "HTTP proxy" -msgstr "" - -#: lib/ManaTools/Module/Proxy.pm:309 -msgid "Use HTTP proxy for HTTPS connections" -msgstr "" - -#: lib/ManaTools/Module/Proxy.pm:315 -msgid "HTTPS proxy" -msgstr "" - -#: lib/ManaTools/Module/Proxy.pm:321 -msgid "FTP proxy" -msgstr "" - -#: lib/ManaTools/Module/Proxy.pm:327 -msgid "No proxy for (comma separated list):" -msgstr "" - -#: lib/ManaTools/Module/Proxy.pm:340 -#: lib/ManaTools/Module/DisplayManager.pm:256 -#: lib/ManaTools/Module/Firewall.pm:617 lib/ManaTools/Module/Firewall.pm:828 -#: lib/ManaTools/Module/Hosts.pm:192 lib/ManaTools/Module/Hosts.pm:276 -#: lib/ManaTools/Module/Hosts.pm:463 lib/ManaTools/rpmdragora.pm:401 -msgid "OK" -msgstr "" - -#: lib/ManaTools/Module/Proxy.pm:362 -msgid "Graphical manager for proxies" -msgstr "" - -#: lib/ManaTools/Module/Clock.pm:140 -msgid "Date, Clock & Time Zone Settings" -msgstr "" - -#: lib/ManaTools/Module/Clock.pm:231 -msgid "Setting date and time" -msgstr "" - -#: lib/ManaTools/Module/Clock.pm:243 -msgid "Enable Network Time Protocol" -msgstr "" - -#: lib/ManaTools/Module/Clock.pm:246 -msgid "Change NTP server" -msgstr "" - -#: lib/ManaTools/Module/Clock.pm:248 lib/ManaTools/Module/Clock.pm:263 -msgid "Current:" -msgstr "" - -#: lib/ManaTools/Module/Clock.pm:250 lib/ManaTools/Module/Clock.pm:265 -#: lib/ManaTools/Module/Clock.pm:454 lib/ManaTools/Module/Clock.pm:460 -msgid "not defined" -msgstr "" - -#: lib/ManaTools/Module/Clock.pm:259 -msgid "TimeZone" -msgstr "" - -#: lib/ManaTools/Module/Clock.pm:261 -msgid "Change Time Zone" -msgstr "" - -#: lib/ManaTools/Module/Clock.pm:279 -msgid "Reset" -msgstr "" - -#: lib/ManaTools/Module/Clock.pm:348 -msgid "Please enter a valid NTP server address." -msgstr "" - -#: lib/ManaTools/Module/Clock.pm:371 -msgid "NTP server - DrakClock" -msgstr "" - -#: lib/ManaTools/Module/Clock.pm:372 -msgid "Choose your NTP server" -msgstr "" - -#: lib/ManaTools/Module/Clock.pm:396 lib/ManaTools/Module/Clock.pm:402 -msgid "Timezone - DrakClock" -msgstr "" - -#: lib/ManaTools/Module/Clock.pm:397 -msgid "Failed to retrieve timezone list" -msgstr "" - -#: lib/ManaTools/Module/Clock.pm:403 -msgid "Which is your timezone?" -msgstr "" - -#: lib/ManaTools/Module/Clock.pm:415 -msgid "GMT - DrakClock" -msgstr "" - -#: lib/ManaTools/Module/Clock.pm:416 -msgid "Is your hardware clock set to GMT?" -msgstr "" - -#: lib/ManaTools/Module/Clock.pm:435 -msgid "Restore data" -msgstr "" - -#: lib/ManaTools/Module/Clock.pm:436 -msgid "Restore date and time only?" -msgstr "" - -#: lib/ManaTools/Module/Clock.pm:472 -msgid "" -"Date, Clock & Time Zone Settings allows to setup time zone and adjust date " -"and time" -msgstr "" - -#: lib/ManaTools/Module/Clock.pm:473 lib/ManaTools/Module/LogViewer.pm:364 -#, perl-format -msgid "" -"

Developers

\n" -"
  • %s
  • \n" -"
  • %s
  • \n" -"
\n" -"

Translators

\n" -"
  • %s
" -msgstr "" - -#: lib/ManaTools/Module/DisplayManager.pm:98 -msgid "LightDM (The Light Display Manager)" -msgstr "" - -#: lib/ManaTools/Module/DisplayManager.pm:99 -msgid "GDM (GNOME Display Manager)" -msgstr "" - -#: lib/ManaTools/Module/DisplayManager.pm:100 -msgid "KDM (KDE Display Manager)" -msgstr "" - -#: lib/ManaTools/Module/DisplayManager.pm:101 -msgid "XDM (X Display Manager)" -msgstr "" - -#: lib/ManaTools/Module/DisplayManager.pm:196 -msgid "Display Manager" -msgstr "" - -#: lib/ManaTools/Module/DisplayManager.pm:222 -msgid "Choosing a display manager" -msgstr "" - -#: lib/ManaTools/Module/DisplayManager.pm:278 -msgid "Graphical configurator for system Display Manager" -msgstr "" - -#: lib/ManaTools/Module/LogViewer.pm:141 -msgid "Log viewer" -msgstr "" - -#: lib/ManaTools/Module/LogViewer.pm:195 -msgid "A tool to monitor your logs" -msgstr "" - -#: lib/ManaTools/Module/LogViewer.pm:199 -msgid "Matching" -msgstr "" - -#: lib/ManaTools/Module/LogViewer.pm:203 -msgid "but not matching" -msgstr "" - -#: lib/ManaTools/Module/LogViewer.pm:207 -msgid "Options" -msgstr "" - -#: lib/ManaTools/Module/LogViewer.pm:212 -msgid "Last boot" -msgstr "" - -#: lib/ManaTools/Module/LogViewer.pm:225 -msgid "Since" -msgstr "" - -#: lib/ManaTools/Module/LogViewer.pm:230 -msgid "Until" -msgstr "" - -#: lib/ManaTools/Module/LogViewer.pm:257 -msgid "Select a unit" -msgstr "" - -#: lib/ManaTools/Module/LogViewer.pm:279 -msgid "From priority" -msgstr "" - -#: lib/ManaTools/Module/LogViewer.pm:299 -msgid "To priority" -msgstr "" - -#: lib/ManaTools/Module/LogViewer.pm:317 -msgid "search" -msgstr "" - -#: lib/ManaTools/Module/LogViewer.pm:320 -msgid "Log content" -msgstr "" - -#: lib/ManaTools/Module/LogViewer.pm:336 -msgid "Save" -msgstr "" - -#: lib/ManaTools/Module/LogViewer.pm:337 -msgid "Quit" -msgstr "" - -#: lib/ManaTools/Module/LogViewer.pm:363 -msgid "Log viewer is a systemd journal viewer" -msgstr "" - -#: lib/ManaTools/Module/LogViewer.pm:382 -msgid "Empty log found" -msgstr "" - -#: lib/ManaTools/Module/LogViewer.pm:475 -#: lib/ManaTools/Rpmdragora/init.pm:165 -msgid "Running in user mode" -msgstr "" - -#: lib/ManaTools/Module/LogViewer.pm:476 -msgid "" -"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." -msgstr "" - -#: lib/ManaTools/Module/LogViewer.pm:499 -msgid "Save as.." -msgstr "" - -#: lib/ManaTools/Module/Firewall.pm:151 -msgid "Web Server" -msgstr "" - -#: lib/ManaTools/Module/Firewall.pm:157 -msgid "Domain Name Server" -msgstr "" - -#: lib/ManaTools/Module/Firewall.pm:163 -msgid "SSH server" -msgstr "" - -#: lib/ManaTools/Module/Firewall.pm:169 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:261 -msgid "FTP server" -msgstr "" - -#: lib/ManaTools/Module/Firewall.pm:175 -msgid "DHCP Server" -msgstr "" - -#: lib/ManaTools/Module/Firewall.pm:182 -msgid "Mail Server" -msgstr "" - -#: lib/ManaTools/Module/Firewall.pm:188 -msgid "POP and IMAP Server" -msgstr "" - -#: lib/ManaTools/Module/Firewall.pm:194 -msgid "Telnet server" -msgstr "" - -#: lib/ManaTools/Module/Firewall.pm:201 -msgid "NFS Server" -msgstr "" - -#: lib/ManaTools/Module/Firewall.pm:210 -msgid "Windows Files Sharing (SMB)" -msgstr "" - -#: lib/ManaTools/Module/Firewall.pm:217 -msgid "Bacula backup" -msgstr "" - -#: lib/ManaTools/Module/Firewall.pm:224 -msgid "Syslog network logging" -msgstr "" - -#: lib/ManaTools/Module/Firewall.pm:231 -msgid "CUPS server" -msgstr "" - -#: lib/ManaTools/Module/Firewall.pm:238 -msgid "MySQL server" -msgstr "" - -#: lib/ManaTools/Module/Firewall.pm:245 -msgid "PostgreSQL server" -msgstr "" - -#: lib/ManaTools/Module/Firewall.pm:252 -msgid "Echo request (ping)" -msgstr "" - -#: lib/ManaTools/Module/Firewall.pm:258 -msgid "Network services autodiscovery (zeroconf and slp)" -msgstr "" - -#: lib/ManaTools/Module/Firewall.pm:264 -msgid "BitTorrent" -msgstr "" - -#: lib/ManaTools/Module/Firewall.pm:271 -msgid "Windows Mobile device synchronization" -msgstr "" - -#: lib/ManaTools/Module/Firewall.pm:285 -msgid "Port scan detection" -msgstr "" - -#: lib/ManaTools/Module/Firewall.pm:423 lib/ManaTools/Module/Firewall.pm:430 -#: lib/ManaTools/Module/Firewall.pm:887 -msgid "Firewall configuration" -msgstr "" - -#: lib/ManaTools/Module/Firewall.pm:424 -msgid "" -"drakfirewall configurator\n" -" This configures a personal firewall for this Mageia " -"machine." -msgstr "" - -#: lib/ManaTools/Module/Firewall.pm:431 -msgid "" -"drakfirewall configurator\n" -"Make sure you have configured your Network/Internet access with\n" -"drakconnect before going any further." -msgstr "" - -#: lib/ManaTools/Module/Firewall.pm:500 -msgid "Interactive Firewall" -msgstr "" - -#: lib/ManaTools/Module/Firewall.pm:504 -msgid "" -"You can be warned when someone accesses to a service or tries to intrude " -"into your computer.\n" -"Please select which network activities should be watched." -msgstr "" - -#: lib/ManaTools/Module/Firewall.pm:510 -msgid "Use Interactive Firewall" -msgstr "" - -#: lib/ManaTools/Module/Firewall.pm:667 -msgid "Graphical manager for interactive firewall rules" -msgstr "" - -#: lib/ManaTools/Module/Firewall.pm:718 lib/ManaTools/Module/Firewall.pm:721 -#: lib/ManaTools/Module/Firewall.pm:969 -msgid "Firewall" -msgstr "" - -#: lib/ManaTools/Module/Firewall.pm:722 -msgid "" -"You can enter miscellaneous ports. \n" -"Valid examples are: 139/tcp 139/udp 600:610/tcp 600:610/udp.\n" -"Have a look at /etc/services for information." -msgstr "" - -#: lib/ManaTools/Module/Firewall.pm:740 -msgid "Which services would you like to allow the Internet to connect to?" -msgstr "" - -#: lib/ManaTools/Module/Firewall.pm:741 -#, perl-format -msgid "Those settings will be saved for the network profile %s" -msgstr "" - -#: lib/ManaTools/Module/Firewall.pm:742 -msgid "Everything (no firewall)" -msgstr "" - -#: lib/ManaTools/Module/Firewall.pm:744 -msgid "Other ports" -msgstr "" - -#: lib/ManaTools/Module/Firewall.pm:745 -msgid "Log firewall messages in system logs" -msgstr "" - -#: lib/ManaTools/Module/Firewall.pm:859 -msgid "Graphical manager for firewall rules" -msgstr "" - -#: lib/ManaTools/Module/Firewall.pm:888 -msgid "" -"Please select the interfaces that will be protected by the firewall.\n" -"\n" -"All interfaces directly connected to Internet should be selected,\n" -"while interfaces connected to a local network may be unselected.\n" -"\n" -"If you intend to use Mageia Internet Connection sharing,\n" -"unselect interfaces which will be connected to local network.\n" -"\n" -"Which interfaces should be protected?\n" -msgstr "" - -#: lib/ManaTools/Module/Firewall.pm:970 -msgid "" -"Your firewall configuration has been manually edited and contains\n" -" rules that may conflict with the configuration that has just been set " -"up.\n" -" What do you want to do?" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:265 -msgid "adminUser" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:269 -msgid "User Data" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:270 -msgid "Account Info" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:271 -msgid "Password Info" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:272 lib/ManaTools/Module/Users.pm:1362 -#: lib/ManaTools/Module/Users.pm:2431 -msgid "Groups" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:275 -msgid "Group Data" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:276 -msgid "Group Users" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:310 -msgid "Choose group" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:318 -msgid "A group with this name already exists. What would you like to do?" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:324 -msgid "Add to the existing group" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:328 -msgid "Add to the 'users' group" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:392 lib/ManaTools/Rpmdragora/gui.pm:390 -#: lib/ManaTools/Rpmdragora/gui.pm:939 lib/ManaTools/Rpmdragora/gui.pm:943 -#: lib/ManaTools/Rpmdragora/gui.pm:948 lib/ManaTools/Rpmdragora/pkg.pm:930 -#: lib/ManaTools/Rpmdragora/pkg.pm:940 lib/ManaTools/Rpmdragora/pkg.pm:954 -#: lib/ManaTools/rpmdragora.pm:829 lib/ManaTools/rpmdragora.pm:1044 -msgid "Warning" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:400 -#, perl-format -msgid "Do you really want to delete the group %s?" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:406 lib/ManaTools/Module/Users.pm:497 -#: lib/ManaTools/Module/Users.pm:2396 -msgid "Delete" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:426 -#, perl-format -msgid "" -"%s is a primary group for user %s\n" -" Remove the user first" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:433 -#, perl-format -msgid "Removing group: %s" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:480 -msgid "Delete files or not?" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:487 -#, perl-format -msgid "" -"Deleting user %s\n" -"Also perform the following actions\n" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:490 -#, perl-format -msgid "Delete Home Directory: %s" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:492 -#, perl-format -msgid "Delete Mailbox: /var/spool/mail/%s" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:520 -#, perl-format -msgid "Removing user: %s" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:552 -msgid "Create New Group" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:562 lib/ManaTools/Module/Users.pm:1578 -msgid "Group Name:" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:572 -msgid "Specify group ID manually" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:574 -msgid "GID" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:607 -msgid "Group already exists, please choose another Group Name" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:615 -#, perl-format -msgid " Group Gid is < %n" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:616 -#, perl-format -msgid "" -"Creating a group with a GID less than %d is not recommended.\n" -" Are you sure you want to do this?\n" -"\n" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:624 -msgid " Group ID is already used " -msgstr "" - -#: lib/ManaTools/Module/Users.pm:625 -msgid "" -"Creating a group with a non unique GID?\n" -"\n" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:637 -#, perl-format -msgid "Adding group: %s " -msgstr "" - -#: lib/ManaTools/Module/Users.pm:693 -msgid "Full Name:" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:702 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:211 -msgid "Login:" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:712 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:218 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:927 -msgid "Password:" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:734 -msgid "Confirm Password:" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:743 -msgid "Login Shell:" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:809 -msgid "Create New User" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:824 -msgid "Create Home Directory" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:828 -msgid "Home Directory:" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:837 -msgid "Create a private group for the user" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:842 -msgid "Specify user ID manually" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:844 -msgid "UID" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:852 -msgid "Click on icon to change it" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:904 -msgid "User already exists, please choose another User Name" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:909 lib/ManaTools/Module/Users.pm:1857 -msgid "Password Mismatch" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:913 lib/ManaTools/Module/Users.pm:1863 -msgid "" -"This password is too simple. \n" -" Good passwords should be > 6 characters" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:920 -#, perl-format -msgid "" -"Home directory <%s> already exists.\n" -"Please uncheck the home creation option, or change the directory path name" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:933 -#, perl-format -msgid "User Uid is < %d" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:934 -#, perl-format -msgid "" -"Creating a user with a UID less than %d is not recommended.\n" -"Are you sure you want to do this?\n" -"\n" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:949 -#, perl-format -msgid "Putting %s to 'users' group" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:963 -#, perl-format -msgid "Creating new group: %s" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:976 -msgid "Adding user: " -msgstr "" - -#: lib/ManaTools/Module/Users.pm:977 -#, perl-format -msgid "Adding user: %s" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:1043 -msgid "User Name" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:1044 -msgid "User ID" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:1045 lib/ManaTools/Module/Users.pm:1792 -msgid "Primary Group" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:1046 -msgid "Full Name" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:1047 -msgid "Login Shell" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:1048 -msgid "Home Directory" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:1089 -msgid "Group Name" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:1090 -msgid "Group ID" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:1091 -msgid "Group Members" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:1274 lib/ManaTools/Module/Users.pm:2227 -#: lib/ManaTools/Module/Users.pm:2242 lib/ManaTools/Module/Users.pm:2258 -#: lib/ManaTools/Module/Users.pm:2427 -msgid "Users" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:1505 -msgid "Home:" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:1604 -msgid "Enable account expiration" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:1607 -msgid "Account expires (YYYY-MM-DD):" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:1614 -msgid "Lock User Account" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:1618 -msgid "Click on the icon to change it" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:1648 -msgid "User last changed password on: " -msgstr "" - -#: lib/ManaTools/Module/Users.pm:1661 -msgid "Enable Password Expiration" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:1665 -msgid "Days before change allowed:" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:1673 -msgid "Days before change required:" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:1681 -msgid "Days warning before change:" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:1689 -msgid "Days before account inactive:" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:1718 -msgid "Select the users to join this group:" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:1722 -msgid "User" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:1763 -msgid "Select groups that the user will be member of:" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:1767 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1139 -msgid "Group" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:1869 -msgid "Please select at least one group for the user" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:1892 -msgid "" -"Please specify Year, Month and Day \n" -" for Account Expiration " -msgstr "" - -#: lib/ManaTools/Module/Users.pm:1908 -msgid "Please fill up all fields in password aging\n" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:1943 -msgid "Strong" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:1943 -msgid "Weak" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:1956 -msgid "Edit User" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:2109 lib/ManaTools/Module/Users.pm:2212 -msgid "Cannot create tab widgets" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:2125 -msgid "Edit Group" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:2293 lib/ManaTools/Module/Users.pm:2393 -msgid "Add User" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:2294 lib/ManaTools/Module/Users.pm:2394 -msgid "Add Group" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:2295 -msgid "&Edit" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:2296 -msgid "&Delete" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:2297 -msgid "Install guest account" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:2366 -msgid "&Quit" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:2373 -msgid "Actions" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:2377 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1607 -msgid "&Help" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:2379 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1609 -msgid "Report Bug" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:2380 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1610 -msgid "&About" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:2395 lib/ManaTools/Module/Hosts.pm:450 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1663 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:2156 -msgid "Edit" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:2410 -msgid "Filter system users" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:2415 -msgid "Search:" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:2417 -msgid "Apply filter" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:2464 -msgid "AdminUser" -msgstr "" - -#: lib/ManaTools/Module/Users.pm:2468 -msgid "" -"AdminUser is a Mageia user management tool \n" -"(from the original idea of Mandriva userdrake)." -msgstr "" - -#: lib/ManaTools/Module/Users.pm:2469 -#, perl-format -msgid "" -"

Developers

\n" -"
  • %s
  • \n" -"
  • %s
  • \n" -"
\n" -"

Translators

\n" -"
  • %s
" -msgstr "" - -#: lib/ManaTools/Module/Hosts.pm:159 lib/ManaTools/Module/Hosts.pm:255 -#: lib/ManaTools/Module/Hosts.pm:435 lib/ManaTools/Module/Hosts.pm:452 -msgid "Hostname" -msgstr "" - -#: lib/ManaTools/Module/Hosts.pm:164 -msgid "Pretty Hostname" -msgstr "" - -#: lib/ManaTools/Module/Hosts.pm:169 -msgid "Static Hostname" -msgstr "" - -#: lib/ManaTools/Module/Hosts.pm:174 -msgid "Chassis" -msgstr "" - -#: lib/ManaTools/Module/Hosts.pm:179 -msgid "Icon Name" -msgstr "" - -#: lib/ManaTools/Module/Hosts.pm:254 lib/ManaTools/Module/Hosts.pm:434 -msgid "IP Address" -msgstr "" - -#: lib/ManaTools/Module/Hosts.pm:256 -msgid "Host aliases" -msgstr "" - -#: lib/ManaTools/Module/Hosts.pm:331 -msgid "Add the information" -msgstr "" - -#: lib/ManaTools/Module/Hosts.pm:365 -msgid "Modify the information" -msgstr "" - -#: lib/ManaTools/Module/Hosts.pm:412 -msgid "Manage hosts definitions" -msgstr "" - -#: lib/ManaTools/Module/Hosts.pm:436 -msgid "Host Aliases" -msgstr "" - -#: lib/ManaTools/Module/Hosts.pm:449 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1095 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1104 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1371 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1664 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:2162 -msgid "Add" -msgstr "" - -#: lib/ManaTools/Module/Hosts.pm:451 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1096 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1105 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1166 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1372 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1662 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:2152 -msgid "Remove" -msgstr "" - -#: lib/ManaTools/Module/Hosts.pm:495 lib/ManaTools/Rpmdragora/pkg.pm:265 -#: lib/ManaTools/Rpmdragora/pkg.pm:803 -msgid "Confirmation" -msgstr "" - -#: lib/ManaTools/Module/Hosts.pm:495 -msgid "Are you sure to drop this host?" -msgstr "" - -#: lib/ManaTools/Module/Hosts.pm:512 -msgid "Graphical manager for hosts definitions" -msgstr "" - -#: lib/ManaTools/Rpmdragora/init.pm:57 -#, perl-format -msgid "Usage: %s [OPTION]..." -msgstr "" - -#: lib/ManaTools/Rpmdragora/init.pm:58 -msgid " --auto assume default answers to questions" -msgstr "" - -#: lib/ManaTools/Rpmdragora/init.pm:59 -msgid "" -" --changelog-first display changelog before filelist in the " -"description window" -msgstr "" - -#: lib/ManaTools/Rpmdragora/init.pm:60 -msgid " --media=medium1,.. limit to given media" -msgstr "" - -#: lib/ManaTools/Rpmdragora/init.pm:61 -msgid "" -" --merge-all-rpmnew propose to merge all .rpmnew/.rpmsave files found" -msgstr "" - -#: lib/ManaTools/Rpmdragora/init.pm:62 -msgid " --mode=MODE set mode (install (default), remove, update)" -msgstr "" - -#: lib/ManaTools/Rpmdragora/init.pm:63 -msgid "" -" --justdb update the database, but do not modify the " -"filesystem" -msgstr "" - -#: lib/ManaTools/Rpmdragora/init.pm:64 -msgid "" -" --no-confirmation don't ask first confirmation question in update mode" -msgstr "" - -#: lib/ManaTools/Rpmdragora/init.pm:65 -msgid " --no-media-update don't update media at startup" -msgstr "" - -#: lib/ManaTools/Rpmdragora/init.pm:66 -msgid " --no-verify-rpm don't verify package signatures" -msgstr "" - -#: lib/ManaTools/Rpmdragora/init.pm:67 -msgid "" -" --parallel=alias,host be in parallel mode, use \"alias\" group, use \"host" -"\" machine to show needed deps" -msgstr "" - -#: lib/ManaTools/Rpmdragora/init.pm:68 -msgid " --rpm-root=path use another root for rpm installation" -msgstr "" - -#: lib/ManaTools/Rpmdragora/init.pm:69 -msgid "" -" --urpmi-root use another root for urpmi db & rpm installation" -msgstr "" - -#: lib/ManaTools/Rpmdragora/init.pm:70 -msgid " --run-as-root force to run as root" -msgstr "" - -#: lib/ManaTools/Rpmdragora/init.pm:71 -msgid " --search=pkg run search for \"pkg\"" -msgstr "" - -#: lib/ManaTools/Rpmdragora/init.pm:72 -msgid "" -" --test only verify if the installation can be achieved " -"correctly" -msgstr "" - -#: lib/ManaTools/Rpmdragora/init.pm:73 -msgid " --version print this tool's version number\n" -msgstr "" - -#: lib/ManaTools/Rpmdragora/init.pm:166 -msgid "" -"You are launching this program as a normal user.\n" -"You will not be able to perform modifications on the system,\n" -"but you may still browse the existing database." -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:41 -msgid "All" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:42 -msgid "Accessibility" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:43 lib/ManaTools/Rpmdragora/icon.pm:44 -#: lib/ManaTools/Rpmdragora/icon.pm:45 lib/ManaTools/Rpmdragora/icon.pm:46 -#: lib/ManaTools/Rpmdragora/icon.pm:47 -msgid "Archiving" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:44 -msgid "Backup" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:45 -msgid "Cd burning" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:46 -msgid "Compression" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:47 lib/ManaTools/Rpmdragora/icon.pm:70 -#: lib/ManaTools/Rpmdragora/icon.pm:86 lib/ManaTools/Rpmdragora/icon.pm:106 -#: lib/ManaTools/Rpmdragora/icon.pm:127 lib/ManaTools/Rpmdragora/icon.pm:147 -msgid "Other" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:48 lib/ManaTools/Rpmdragora/icon.pm:49 -#: lib/ManaTools/Rpmdragora/icon.pm:50 lib/ManaTools/Rpmdragora/icon.pm:51 -#: lib/ManaTools/Rpmdragora/icon.pm:52 lib/ManaTools/Rpmdragora/icon.pm:53 -#: lib/ManaTools/Rpmdragora/icon.pm:54 lib/ManaTools/Rpmdragora/icon.pm:55 -msgid "Communications" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:49 -msgid "Bluetooth" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:50 -msgid "Dial-Up" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:51 -msgid "Fax" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:52 -msgid "Mobile" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:53 -msgid "Radio" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:54 -msgid "Serial" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:55 -msgid "Telephony" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:56 lib/ManaTools/Rpmdragora/icon.pm:62 -msgid "Databases" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:57 lib/ManaTools/Rpmdragora/icon.pm:58 -#: lib/ManaTools/Rpmdragora/icon.pm:59 lib/ManaTools/Rpmdragora/icon.pm:60 -#: lib/ManaTools/Rpmdragora/icon.pm:61 lib/ManaTools/Rpmdragora/icon.pm:62 -#: lib/ManaTools/Rpmdragora/icon.pm:63 lib/ManaTools/Rpmdragora/icon.pm:64 -#: lib/ManaTools/Rpmdragora/icon.pm:65 lib/ManaTools/Rpmdragora/icon.pm:66 -#: lib/ManaTools/Rpmdragora/icon.pm:67 lib/ManaTools/Rpmdragora/icon.pm:68 -#: lib/ManaTools/Rpmdragora/icon.pm:69 lib/ManaTools/Rpmdragora/icon.pm:70 -#: lib/ManaTools/Rpmdragora/icon.pm:71 lib/ManaTools/Rpmdragora/icon.pm:72 -#: lib/ManaTools/Rpmdragora/icon.pm:73 lib/ManaTools/Rpmdragora/icon.pm:74 -#: lib/ManaTools/Rpmdragora/icon.pm:75 lib/ManaTools/Rpmdragora/icon.pm:202 -#: lib/ManaTools/Rpmdragora/icon.pm:203 lib/ManaTools/Rpmdragora/icon.pm:204 -msgid "Development" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:58 -msgid "Basic" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:59 -msgid "C" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:60 -msgid "C++" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:61 -msgid "C#" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:63 -msgid "Debug" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:64 -msgid "Erlang" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:65 -msgid "GNOME and GTK+" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:66 -msgid "Java" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:67 -msgid "KDE and Qt" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:68 -msgid "Kernel" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:69 -msgid "OCaml" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:71 -msgid "Perl" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:72 -msgid "PHP" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:73 -msgid "Python" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:74 -msgid "Tools" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:75 lib/ManaTools/Rpmdragora/icon.pm:175 -msgid "X11" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:76 lib/ManaTools/Rpmdragora/icon.pm:189 -#: lib/ManaTools/Rpmdragora/icon.pm:204 -msgid "Documentation" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:77 -msgid "Editors" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:78 -msgid "Education" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:79 -msgid "Emulators" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:80 -msgid "File tools" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:81 lib/ManaTools/Rpmdragora/icon.pm:82 -#: lib/ManaTools/Rpmdragora/icon.pm:83 lib/ManaTools/Rpmdragora/icon.pm:84 -#: lib/ManaTools/Rpmdragora/icon.pm:85 lib/ManaTools/Rpmdragora/icon.pm:86 -#: lib/ManaTools/Rpmdragora/icon.pm:87 lib/ManaTools/Rpmdragora/icon.pm:88 -#: lib/ManaTools/Rpmdragora/icon.pm:89 lib/ManaTools/Rpmdragora/icon.pm:90 -#: lib/ManaTools/Rpmdragora/icon.pm:91 -msgid "Games" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:82 -msgid "Adventure" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:83 -msgid "Arcade" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:84 -msgid "Boards" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:85 -msgid "Cards" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:87 -msgid "Puzzles" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:88 -msgid "Shooter" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:89 -msgid "Simulation" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:90 -msgid "Sports" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:91 -msgid "Strategy" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:92 -msgid "Geography" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:93 lib/ManaTools/Rpmdragora/icon.pm:94 -#: lib/ManaTools/Rpmdragora/icon.pm:97 lib/ManaTools/Rpmdragora/icon.pm:100 -#: lib/ManaTools/Rpmdragora/icon.pm:103 lib/ManaTools/Rpmdragora/icon.pm:106 -#: lib/ManaTools/Rpmdragora/icon.pm:107 lib/ManaTools/Rpmdragora/icon.pm:110 -msgid "Graphical desktop" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:96 -msgid "Enlightenment" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:99 -msgid "GNOME" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:102 -msgid "Icewm" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:105 -msgid "KDE" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:109 -msgid "WindowMaker" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:112 -msgid "Xfce" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:113 lib/ManaTools/Rpmdragora/icon.pm:114 -#: lib/ManaTools/Rpmdragora/icon.pm:115 lib/ManaTools/Rpmdragora/icon.pm:116 -#: lib/ManaTools/Rpmdragora/icon.pm:117 lib/ManaTools/Rpmdragora/icon.pm:118 -#: lib/ManaTools/Rpmdragora/icon.pm:119 -msgid "Graphics" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:114 -msgid "3D" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:115 lib/ManaTools/Rpmdragora/icon.pm:152 -#: lib/ManaTools/Rpmdragora/icon.pm:180 -msgid "Editors and Converters" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:116 lib/ManaTools/Rpmdragora/icon.pm:135 -#: lib/ManaTools/Rpmdragora/icon.pm:156 lib/ManaTools/Rpmdragora/icon.pm:183 -msgid "Utilities" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:117 -msgid "Photography" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:118 -msgid "Scanning" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:119 -msgid "Viewers" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:120 -msgid "Monitoring" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:121 lib/ManaTools/Rpmdragora/icon.pm:122 -#: lib/ManaTools/Rpmdragora/icon.pm:123 lib/ManaTools/Rpmdragora/icon.pm:124 -#: lib/ManaTools/Rpmdragora/icon.pm:125 lib/ManaTools/Rpmdragora/icon.pm:126 -#: lib/ManaTools/Rpmdragora/icon.pm:127 lib/ManaTools/Rpmdragora/icon.pm:128 -#: lib/ManaTools/Rpmdragora/icon.pm:129 lib/ManaTools/Rpmdragora/icon.pm:169 -msgid "Networking" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:122 -msgid "File transfer" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:123 -msgid "IRC" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:124 -msgid "Instant messaging" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:125 lib/ManaTools/Rpmdragora/icon.pm:209 -msgid "Mail" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:126 -msgid "News" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:128 -msgid "Remote access" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:129 -msgid "WWW" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:130 lib/ManaTools/Rpmdragora/icon.pm:131 -#: lib/ManaTools/Rpmdragora/icon.pm:132 lib/ManaTools/Rpmdragora/icon.pm:133 -#: lib/ManaTools/Rpmdragora/icon.pm:134 lib/ManaTools/Rpmdragora/icon.pm:135 -#: lib/ManaTools/Rpmdragora/icon.pm:136 lib/ManaTools/Rpmdragora/icon.pm:137 -#: lib/ManaTools/Rpmdragora/icon.pm:138 -msgid "Office" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:131 -msgid "Dictionary" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:132 -msgid "Finance" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:133 -msgid "Management" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:134 -msgid "Organizer" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:136 -msgid "Spreadsheet" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:137 -msgid "Suite" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:138 -msgid "Word processor" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:139 -msgid "Publishing" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:140 lib/ManaTools/Rpmdragora/icon.pm:141 -#: lib/ManaTools/Rpmdragora/icon.pm:142 lib/ManaTools/Rpmdragora/icon.pm:143 -#: lib/ManaTools/Rpmdragora/icon.pm:144 lib/ManaTools/Rpmdragora/icon.pm:145 -#: lib/ManaTools/Rpmdragora/icon.pm:146 lib/ManaTools/Rpmdragora/icon.pm:147 -#: lib/ManaTools/Rpmdragora/icon.pm:148 -msgid "Sciences" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:141 -msgid "Astronomy" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:142 -msgid "Biology" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:143 -msgid "Chemistry" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:144 -msgid "Computer science" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:145 -msgid "Geosciences" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:146 -msgid "Mathematics" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:148 -msgid "Physics" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:149 -msgid "Security" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:150 -msgid "Shells" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:151 lib/ManaTools/Rpmdragora/icon.pm:152 -#: lib/ManaTools/Rpmdragora/icon.pm:153 lib/ManaTools/Rpmdragora/icon.pm:154 -#: lib/ManaTools/Rpmdragora/icon.pm:155 lib/ManaTools/Rpmdragora/icon.pm:156 -msgid "Sound" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:153 -msgid "Midi" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:154 -msgid "Mixers" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:155 lib/ManaTools/Rpmdragora/icon.pm:181 -msgid "Players" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:157 lib/ManaTools/Rpmdragora/icon.pm:158 -#: lib/ManaTools/Rpmdragora/icon.pm:159 lib/ManaTools/Rpmdragora/icon.pm:160 -#: lib/ManaTools/Rpmdragora/icon.pm:161 lib/ManaTools/Rpmdragora/icon.pm:162 -#: lib/ManaTools/Rpmdragora/icon.pm:163 lib/ManaTools/Rpmdragora/icon.pm:164 -#: lib/ManaTools/Rpmdragora/icon.pm:165 lib/ManaTools/Rpmdragora/icon.pm:166 -#: lib/ManaTools/Rpmdragora/icon.pm:167 lib/ManaTools/Rpmdragora/icon.pm:168 -#: lib/ManaTools/Rpmdragora/icon.pm:169 lib/ManaTools/Rpmdragora/icon.pm:170 -#: lib/ManaTools/Rpmdragora/icon.pm:171 lib/ManaTools/Rpmdragora/icon.pm:172 -#: lib/ManaTools/Rpmdragora/icon.pm:173 -msgid "System" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:158 -msgid "Base" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:159 -msgid "Boot and Init" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:160 -msgid "Cluster" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:161 lib/ManaTools/Rpmdragora/icon.pm:187 -msgid "Configuration" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:162 lib/ManaTools/Rpmdragora/icon.pm:163 -#: lib/ManaTools/Rpmdragora/icon.pm:164 lib/ManaTools/Rpmdragora/icon.pm:165 -msgid "Fonts" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:163 -msgid "True type" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:164 -msgid "Type1" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:165 -msgid "X11 bitmap" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:166 -msgid "Internationalization" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:167 -msgid "Kernel and hardware" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:168 -msgid "Libraries" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:170 -msgid "Packaging" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:171 -msgid "Printing" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:172 -msgid "Servers" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:176 -msgid "Terminals" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:177 -msgid "Text tools" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:178 -msgid "Toys" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:179 lib/ManaTools/Rpmdragora/icon.pm:180 -#: lib/ManaTools/Rpmdragora/icon.pm:181 lib/ManaTools/Rpmdragora/icon.pm:182 -#: lib/ManaTools/Rpmdragora/icon.pm:183 -msgid "Video" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:182 -msgid "Television" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:186 lib/ManaTools/Rpmdragora/icon.pm:187 -#: lib/ManaTools/Rpmdragora/icon.pm:188 lib/ManaTools/Rpmdragora/icon.pm:189 -#: lib/ManaTools/Rpmdragora/icon.pm:190 lib/ManaTools/Rpmdragora/icon.pm:191 -#: lib/ManaTools/Rpmdragora/icon.pm:192 lib/ManaTools/Rpmdragora/icon.pm:193 -#: lib/ManaTools/Rpmdragora/icon.pm:194 lib/ManaTools/Rpmdragora/icon.pm:195 -msgid "Workstation" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:188 -msgid "Console Tools" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:190 -msgid "Game station" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:191 -msgid "Internet station" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:192 -msgid "Multimedia station" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:193 -msgid "Network Computer (client)" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:194 -msgid "Office Workstation" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:195 -msgid "Scientific Workstation" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:196 lib/ManaTools/Rpmdragora/icon.pm:198 -#: lib/ManaTools/Rpmdragora/icon.pm:199 lib/ManaTools/Rpmdragora/icon.pm:200 -#: lib/ManaTools/Rpmdragora/icon.pm:201 lib/ManaTools/Rpmdragora/gui.pm:133 -msgid "Graphical Environment" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:198 -msgid "GNOME Workstation" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:199 -msgid "IceWm Desktop" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:200 -msgid "KDE Workstation" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:201 -msgid "Other Graphical Desktops" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:205 lib/ManaTools/Rpmdragora/icon.pm:206 -#: lib/ManaTools/Rpmdragora/icon.pm:207 lib/ManaTools/Rpmdragora/icon.pm:208 -#: lib/ManaTools/Rpmdragora/icon.pm:209 lib/ManaTools/Rpmdragora/icon.pm:210 -#: lib/ManaTools/Rpmdragora/icon.pm:211 lib/ManaTools/Rpmdragora/icon.pm:212 -msgid "Server" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:206 -msgid "DNS/NIS" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:207 -msgid "Database" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:208 -msgid "Firewall/Router" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:210 -msgid "Mail/Groupware/News" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:211 -msgid "Network Computer server" -msgstr "" - -#: lib/ManaTools/Rpmdragora/icon.pm:212 -msgid "Web/FTP" -msgstr "" - -#: lib/ManaTools/Rpmdragora/open_db.pm:93 -#: lib/ManaTools/Rpmdragora/gui.pm:1552 -msgid "Fatal error" -msgstr "" - -#: lib/ManaTools/Rpmdragora/open_db.pm:94 -#: lib/ManaTools/Rpmdragora/gui.pm:1553 lib/ManaTools/Rpmdragora/pkg.pm:492 -#, perl-format -msgid "A fatal error occurred: %s." -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:104 -msgid "Search results" -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:104 -msgid "Search results (none)" -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:148 -msgid "Security advisory" -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:158 -msgid "No description" -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:172 -msgid "It is not supported by Mageia." -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:173 -msgid "It may break your system." -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:175 -msgid "This package is not free software" -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:178 -msgid "This package contains a new version that was backported." -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:182 -msgid "This package is a potential candidate for an update." -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:187 -msgid "This is an official update which is supported by Mageia." -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:188 -msgid "This is an unofficial update." -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:192 -msgid "This is an official package supported by Mageia" -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:203 -msgid "Notice: " -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:210 -msgid "Importance: " -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:211 -msgid "Reason for update: " -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:225 -msgid "Version: " -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:226 -msgid "Currently installed version: " -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:227 -msgid "Group: " -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:228 -msgid "Architecture: " -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:229 -msgid "Size: " -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:229 -#, perl-format -msgid "%s KB" -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:230 lib/ManaTools/rpmdragora.pm:675 -msgid "Medium: " -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:252 -msgid "All dependencies installed." -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:270 -msgid "URL: " -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:332 -msgid "Details:" -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:341 -msgid "Files:" -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:347 lib/ManaTools/Rpmdragora/gui.pm:358 -#: lib/ManaTools/Rpmdragora/gui.pm:362 lib/ManaTools/Rpmdragora/pkg.pm:199 -msgid "(Not available)" -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:355 -msgid "Changelog:" -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:372 -msgid "New dependencies:" -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:392 -#, perl-format -msgid "The package \"%s\" was found." -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:393 -msgid "However this package is not in the package list." -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:394 -msgid "You may want to update your urpmi database." -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:396 -msgid "Matching packages:" -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:401 -#, perl-format -msgid "- %s (medium: %s)" -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:939 -#, perl-format -msgid "Removing package %s would break your system" -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:943 -#, perl-format -msgid "" -"The \"%s\" package is in urpmi skip list.\n" -"Do you want to select it anyway?" -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:948 lib/ManaTools/Rpmdragora/pkg.pm:799 -msgid "" -"Rpmdragora or one of its priority dependencies needs to be updated first. " -"Rpmdragora will then restart." -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:1154 -msgid "More information on package..." -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:1156 -msgid "Please choose" -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:1157 -msgid "The following package is needed:" -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:1157 -msgid "One of the following packages is needed:" -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:1269 -msgid "Select package" -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:1367 -msgid "Checking dependencies of package..." -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:1372 -msgid "Some additional packages need to be removed" -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:1383 -msgid "" -"Because of their dependencies, the following package(s) also need to be " -"removed:" -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:1388 -msgid "Some packages cannot be removed" -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:1389 -msgid "" -"Removing these packages would break your system, sorry:\n" -"\n" -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:1397 lib/ManaTools/Rpmdragora/gui.pm:1468 -msgid "" -"Because of their dependencies, the following package(s) must be unselected " -"now:\n" -"\n" -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:1421 -msgid "Additional packages needed" -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:1422 -msgid "" -"To satisfy dependencies, the following package(s) also need to be " -"installed:\n" -"\n" -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:1430 -msgid "Conflicting Packages" -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:1444 -#, perl-format -msgid "%s (belongs to the skip list)" -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:1448 -msgid "One package cannot be installed" -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:1448 -msgid "Some packages cannot be installed" -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:1450 -#, perl-format -msgid "" -"Sorry, the following package cannot be selected:\n" -"\n" -"%s" -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:1451 -#, perl-format -msgid "" -"Sorry, the following packages cannot be selected:\n" -"\n" -"%s" -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:1467 lib/ManaTools/Rpmdragora/pkg.pm:803 -msgid "Some packages need to be removed" -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:1505 -msgid "Some packages are selected." -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:1505 -msgid "Do you really want to quit?" -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:1515 -#, perl-format -msgid "Error: %s appears to be mounted read-only." -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:1519 -msgid "You need to select some packages first." -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:1524 -msgid "Too many packages are selected" -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:1525 -msgid "" -"Warning: it seems that you are attempting to add so many\n" -"packages that your filesystem may run out of free diskspace,\n" -"during or after package installation ; this is particularly\n" -"dangerous and should be considered with care.\n" -"\n" -"Do you really want to install all the selected packages?" -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:1636 -msgid "Please wait, listing packages..." -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:1646 -#: lib/ManaTools/Rpmdragora/rpmnew.pm:138 -#: lib/ManaTools/Rpmdragora/formatting.pm:150 -#: lib/ManaTools/Rpmdragora/pkg.pm:125 lib/ManaTools/Rpmdragora/pkg.pm:174 -#: lib/ManaTools/Rpmdragora/pkg.pm:187 lib/ManaTools/Rpmdragora/pkg.pm:206 -#: lib/ManaTools/Rpmdragora/pkg.pm:684 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1150 -msgid "(none)" -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:1649 -msgid "No update" -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:1650 -msgid "" -"The list of updates is empty. This means that either there is\n" -"no available update for the packages installed on your computer,\n" -"or you already installed all of them." -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:1689 -msgid "Upgradable" -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:1689 -msgid "Installed" -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:1690 -msgid "Addable" -msgstr "" - -#: lib/ManaTools/Rpmdragora/gui.pm:1724 -msgid "Description not available for this package\n" -msgstr "" - -#: lib/ManaTools/Rpmdragora/rpmnew.pm:197 -msgid "Installation finished" -msgstr "" - -#: lib/ManaTools/Rpmdragora/rpmnew.pm:218 -#: lib/ManaTools/Rpmdragora/pkg.pm:642 -msgid "Select a package" -msgstr "" - -#: lib/ManaTools/Rpmdragora/rpmnew.pm:228 -msgid "Remove new file" -msgstr "" - -#: lib/ManaTools/Rpmdragora/rpmnew.pm:229 -msgid "Use new file" -msgstr "" - -#: lib/ManaTools/Rpmdragora/rpmnew.pm:230 -msgid "Do nothing" -msgstr "" - -#: lib/ManaTools/Rpmdragora/rpmnew.pm:347 -msgid "Please wait, searching..." -msgstr "" - -#: lib/ManaTools/Rpmdragora/formatting.pm:126 -msgid "None (installed)" -msgstr "" - -#: lib/ManaTools/Rpmdragora/formatting.pm:127 -msgid "Unknown" -msgstr "" - -#: lib/ManaTools/Rpmdragora/formatting.pm:196 -#, perl-format -msgid "%s of additional disk space will be used." -msgstr "" - -#: lib/ManaTools/Rpmdragora/formatting.pm:197 -#, perl-format -msgid "%s of disk space will be freed." -msgstr "" - -#: lib/ManaTools/Rpmdragora/formatting.pm:202 -#, perl-format -msgid "%s of packages will be retrieved." -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:139 -#, perl-format -msgid "Getting information from %s..." -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:143 -#, perl-format -msgid "Getting '%s' from XML meta-data..." -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:147 lib/ManaTools/Rpmdragora/pkg.pm:463 -#: lib/ManaTools/Rpmdragora/pkg.pm:823 lib/ManaTools/Rpmdragora/pkg.pm:1036 -#: lib/ManaTools/rpmdragora.pm:438 lib/ManaTools/rpmdragora.pm:1095 -msgid "Please wait" -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:160 -#, perl-format -msgid "No xml info for medium \"%s\", only partial result for package %s" -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:162 -#, perl-format -msgid "" -"No xml info for medium \"%s\", unable to return any result for package %s" -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:217 lib/ManaTools/Rpmdragora/pkg.pm:222 -#, perl-format -msgid "Downloading package `%s'..." -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:224 -#, perl-format -msgid " %s%% of %s completed, ETA = %s, speed = %s" -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:225 -#, perl-format -msgid " %s%% completed, speed = %s" -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:266 -msgid "" -"I need to contact the mirror to get latest update packages.\n" -"Please check that your network is currently running.\n" -"\n" -"Is it ok to continue?" -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:284 -msgid "Already existing update media" -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:285 -#, perl-format -msgid "" -"You already have at least one update medium configured, but\n" -"all of them are currently disabled. You should run the Software\n" -"Media Manager to enable at least one (check it in the \"%s\"\n" -"column).\n" -"\n" -"Then, restart \"%s\"." -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:290 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:760 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1642 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1669 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:2058 -msgid "Enabled" -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:295 -msgid "" -"You have no configured update media. MageiaUpdate cannot operate without any " -"update media." -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:296 lib/ManaTools/rpmdragora.pm:978 -msgid "" -"I need to contact the Mageia website to get the mirror list.\n" -"Please check that your network is currently running.\n" -"\n" -"Is it ok to continue?" -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:303 -msgid "How to choose manually your mirror" -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:304 -#, perl-format -msgid "" -"You may also choose your desired mirror manually: to do so,\n" -"launch the Software Media Manager, and then add a `Security\n" -"updates' medium.\n" -"\n" -"Then, restart %s." -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:476 -msgid "Reading updates description" -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:481 lib/ManaTools/Rpmdragora/pkg.pm:517 -msgid "Please wait, finding available packages..." -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:487 -msgid "Please wait, listing base packages..." -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:492 lib/ManaTools/Rpmdragora/pkg.pm:959 -#: lib/ManaTools/Rpmdragora/pkg.pm:984 lib/ManaTools/rpmdragora.pm:673 -#: lib/ManaTools/rpmdragora.pm:697 lib/ManaTools/rpmdragora.pm:715 -msgid "Error" -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:500 -msgid "Please wait, finding installed packages..." -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:625 -msgid "Upgrade information" -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:641 -msgid "These packages come with upgrade information" -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:714 lib/ManaTools/Rpmdragora/pkg.pm:976 -msgid "All requested packages were installed successfully." -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:718 lib/ManaTools/Rpmdragora/pkg.pm:945 -msgid "Problem during installation" -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:719 lib/ManaTools/Rpmdragora/pkg.pm:739 -#: lib/ManaTools/Rpmdragora/pkg.pm:947 -#, perl-format -msgid "" -"There was a problem during the installation:\n" -"\n" -"%s" -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:738 -msgid "Installation failed" -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:761 -msgid "Checking validity of requested packages..." -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:780 -msgid "Unable to get source packages." -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:781 -#, perl-format -msgid "Unable to get source packages, sorry. %s" -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:782 -#, perl-format -msgid "" -"\n" -"\n" -"Error(s) reported:\n" -"%s" -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:808 -msgid "The following package has to be removed for others to be upgraded:" -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:809 -msgid "The following packages have to be removed for others to be upgraded:" -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:813 -msgid "Is it ok to continue?" -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:824 -msgid "Initializing..." -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:832 lib/ManaTools/Rpmdragora/pkg.pm:1019 -msgid "Orphan packages" -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:848 lib/ManaTools/Rpmdragora/pkg.pm:849 -msgid "Preparing package installation..." -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:848 -msgid "Preparing package installation transaction..." -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:852 lib/ManaTools/Rpmdragora/pkg.pm:853 -#, perl-format -msgid "Installing package `%s' (%s/%s)..." -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:852 lib/ManaTools/Rpmdragora/pkg.pm:854 -#, perl-format -msgid "Total: %s/%s" -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:918 -msgid "Change medium" -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:919 -#, perl-format -msgid "Please insert the medium named \"%s\"" -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:923 -msgid "Verifying package signatures..." -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:946 -#, perl-format -msgid "%d installation transactions failed" -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:960 -msgid "Unrecoverable error: no package found for installation, sorry." -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:963 -msgid "Inspecting configuration files..." -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:971 -msgid "" -"The installation is finished; everything was installed correctly.\n" -"\n" -"Some configuration files were created as `.rpmnew' or `.rpmsave',\n" -"you may now inspect some in order to take actions:" -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:977 -msgid "Looking for \"README\" files..." -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:1010 -#, perl-format -msgid "RPM transaction %d/%d" -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:1011 -msgid "Unselect all" -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:1012 -msgid "Details" -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:1057 -msgid "Please wait, removing packages..." -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:1070 -msgid "Problem during removal" -msgstr "" - -#: lib/ManaTools/Rpmdragora/pkg.pm:1071 -#, perl-format -msgid "" -"There was a problem during the removal of packages:\n" -"\n" -"%s" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:73 -msgid "CD-ROM" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:74 -msgid "FTP" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:75 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:85 -msgid "Local" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:76 -msgid "HTTP" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:77 -msgid "HTTPS" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:78 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:81 -msgid "NFS" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:79 -msgid "Removable" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:80 -msgid "rsync" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:83 -msgid "Mirror list" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:125 -msgid "Choose media type" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:126 -msgid "" -"In order to keep your system secure and stable, you must at a minimum set " -"up\n" -"sources for official security and stability updates. You can also choose to " -"set\n" -"up a fuller set of sources which includes the complete official Mageia\n" -"repositories, giving you access to more software than can fit on the Mageia\n" -"discs. Please choose whether to configure update sources only, or the full " -"set\n" -"of sources." -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:134 -msgid "Full set of sources" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:134 -msgid "Update sources only" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:147 -#, perl-format -msgid "" -"This will attempt to install all official sources corresponding to your\n" -"distribution (%s).\n" -"\n" -"I need to contact the Mageia website to get the mirror list.\n" -"Please check that your network is currently running.\n" -"\n" -"Is it ok to continue?" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:155 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:170 -msgid "Please wait, adding media..." -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:206 -msgid "Browse..." -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:239 -msgid "Add a medium" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:250 -msgid "Adding a medium:" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:255 -msgid "Type of medium:" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:260 -msgid "Local files" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:260 -msgid "Medium path:" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:261 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:262 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:263 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:724 -msgid "URL:" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:262 -msgid "RSYNC server" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:263 -msgid "HTTP server" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:264 -msgid "Removable device (CD-ROM, DVD, ...)" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:265 -msgid "Path or mount point:" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:283 -msgid "Medium name:" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:298 -msgid "Create media for a whole distribution" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:301 -msgid "Tag this medium as an update medium" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:344 -msgid "You need to fill up at least the two first entries." -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:347 -#, perl-format -msgid "" -"There is already a medium called <%s>,\n" -"do you really want to replace it?" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:425 -msgid "Global options for package installation" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:435 -msgid "Verify RPMs to be installed:" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:439 -msgid "never" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:439 -msgid "always" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:457 -msgid "Download program to use:" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:480 -msgid "XML meta-data download policy:" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:485 -msgid "Never" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:485 -msgid "On-demand" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:485 -msgid "Update-only" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:485 -msgid "Always" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:609 -msgid "Source Removal" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:611 -#, perl-format -msgid "Are you sure you want to remove source \"%s\"?" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:612 -msgid "Are you sure you want to remove the following sources?" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:617 -msgid "Please wait, removing medium..." -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:710 -msgid "Edit a medium" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:719 -#, perl-format -msgid "Editing medium \"%s\":" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:731 -msgid "Downloader:" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:762 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1643 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1670 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:2061 -msgid "Updates" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:769 -msgid "Save changes" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:771 -msgid "Proxy..." -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:809 -msgid "You need to insert the medium to continue" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:810 -msgid "" -"In order to save the changes, you need to insert the medium in the drive." -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:878 -msgid "Configure proxies" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:889 -#, perl-format -msgid "Proxy settings for media \"%s\"" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:890 -msgid "Global proxy settings" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:895 -msgid "" -"If you need a proxy, enter the hostname and an optional port (syntax: " -"):" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:901 -msgid "Enable proxy" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:905 -msgid "Proxy hostname:" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:910 -msgid "You may specify a username/password for the proxy authentication:" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:918 -msgid "User:" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1028 -msgid "Add a parallel group" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1028 -msgid "Edit a parallel group" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1052 -msgid "Add a medium limit" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1052 -msgid "Choose a medium to add to the media limit:" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1069 -msgid "Add a host" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1069 -msgid "Type in the hostname or IP address of the host to add:" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1083 -#, perl-format -msgid "Editing parallel group \"%s\":" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1087 -msgid "Group name:" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1088 -msgid "Protocol:" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1090 -msgid "Media limit:" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1099 -msgid "Hosts:" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1135 -msgid "Configure parallel urpmi (distributed execution of urpmi)" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1139 -msgid "Protocol" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1139 -msgid "Media limit" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1140 -msgid "Command" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1170 -msgid "Edit..." -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1178 -msgid "Add..." -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1198 -msgid "Manage keys for digital signatures of packages" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1224 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1645 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:2068 -msgid "Medium" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1249 -msgid "Keys" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1273 -msgid "no name found, key doesn't exist in rpm keyring!" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1319 -msgid "Add a key" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1320 -#, perl-format -msgid "Choose a key to add to the medium %s" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1343 -msgid "Remove a key" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1344 -#, perl-format -msgid "" -"Are you sure you want to remove the key
%s
from medium %s?
(name " -"of the key: %s)" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1563 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1968 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:2145 -msgid "Configure media" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1581 -#: lib/ManaTools/rpmdragora.pm:870 -msgid "Update" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1582 -msgid "Add a specific media mirror" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1583 -msgid "Add a custom medium" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1584 -msgid "&Close" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1594 -msgid "&Options" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1595 -msgid "Global options" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1596 -msgid "Manage keys" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1597 -msgid "Parallel" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1598 -msgid "Proxy" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1608 -msgid "Manual" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1644 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:2065 -msgid "Type" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1680 -msgid "Up" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1681 -msgid "Down" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1733 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1996 -msgid "Rpmdragora is the Mageia package management tool." -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1833 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1897 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:2092 -msgid "This medium needs to be updated to be usable. Update it now?" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1975 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1976 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1977 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1978 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1979 -msgid "/_File" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1976 -msgid "/_Update" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1976 -msgid "U" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1977 -msgid "/Add a specific _media mirror" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1977 -msgid "M" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1978 -msgid "/_Add a custom medium" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1978 -msgid "A" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1979 -msgid "/Close" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1979 -msgid "W" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1980 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1981 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1982 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1983 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1984 -msgid "/_Options" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1981 -msgid "/_Global options" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1981 -msgid "G" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1982 -msgid "/Manage _keys" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1982 -msgid "K" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1983 -msgid "/_Parallel" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1983 -msgid "P" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1984 -msgid "/P_roxy" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1984 -msgid "R" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1986 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1987 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1988 -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1989 -msgid "/_Help" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1987 -msgid "/_Report Bug" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1989 -msgid "/_About..." -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1992 -msgid "Rpmdragora" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1994 -#, perl-format -msgid "Copyright (C) %s by Mandriva" -msgstr "" - -#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:2204 -msgid "" -"The Package Database is locked. Please close other applications\n" -"working with the Package Database. Do you have another media\n" -"manager on another desktop, or are you currently installing\n" -"packages as well?" -msgstr "" - -#: lib/ManaTools/rpmdragora.pm:259 -msgid "Software Packages Removal" -msgstr "" - -#: lib/ManaTools/rpmdragora.pm:260 -msgid "Software Packages Update" -msgstr "" - -#: lib/ManaTools/rpmdragora.pm:261 -msgid "Software Packages Installation" -msgstr "" - -#: lib/ManaTools/rpmdragora.pm:330 -msgid "Do not ask me next time" -msgstr "" - -#: lib/ManaTools/rpmdragora.pm:388 -msgid "Dependencies" -msgstr "" - -#: lib/ManaTools/rpmdragora.pm:674 -#, perl-format -msgid "" -"Unable to add medium, errors reported:\n" -"\n" -"%s" -msgstr "" - -#: lib/ManaTools/rpmdragora.pm:697 -msgid "Unable to create medium." -msgstr "" - -#: lib/ManaTools/rpmdragora.pm:702 -msgid "Failure when adding medium" -msgstr "" - -#: lib/ManaTools/rpmdragora.pm:703 -#, perl-format -msgid "" -"There was a problem adding medium:\n" -"\n" -"%s" -msgstr "" - -#: lib/ManaTools/rpmdragora.pm:729 -msgid "rpmdragora" -msgstr "" - -#: lib/ManaTools/rpmdragora.pm:735 -msgid "Please wait, updating media..." -msgstr "" - -#: lib/ManaTools/rpmdragora.pm:758 -msgid "Error retrieving packages" -msgstr "" - -#: lib/ManaTools/rpmdragora.pm:759 -#, perl-format -msgid "" -"It's impossible to retrieve the list of new packages from the media\n" -"`%s'. Either this update media is misconfigured, and in this case\n" -"you should use the Software Media Manager to remove it and re-add it in " -"order\n" -"to reconfigure it, either it is currently unreachable and you should retry\n" -"later." -msgstr "" - -#: lib/ManaTools/rpmdragora.pm:787 -#, perl-format -msgid "Copying file for medium `%s'..." -msgstr "" - -#: lib/ManaTools/rpmdragora.pm:790 -#, perl-format -msgid "Examining file of medium `%s'..." -msgstr "" - -#: lib/ManaTools/rpmdragora.pm:793 -#, perl-format -msgid "Examining remote file of medium `%s'..." -msgstr "" - -#: lib/ManaTools/rpmdragora.pm:797 -msgid " done." -msgstr "" - -#: lib/ManaTools/rpmdragora.pm:801 -msgid " failed!" -msgstr "" - -#: lib/ManaTools/rpmdragora.pm:806 -#, perl-format -msgid "%s from medium %s" -msgstr "" - -#: lib/ManaTools/rpmdragora.pm:810 -#, perl-format -msgid "Starting download of `%s'..." -msgstr "" - -#: lib/ManaTools/rpmdragora.pm:814 -#, perl-format -msgid "" -"Download of `%s'\n" -"time to go:%s, speed:%s" -msgstr "" - -#: lib/ManaTools/rpmdragora.pm:817 -#, perl-format -msgid "" -"Download of `%s'\n" -"speed:%s" -msgstr "" - -#: lib/ManaTools/rpmdragora.pm:829 -msgid "" -"No active medium found. You must enable some media to be able to update them." -msgstr "" - -#: lib/ManaTools/rpmdragora.pm:836 -msgid "Update media" -msgstr "" - -#: lib/ManaTools/rpmdragora.pm:850 -msgid "Media" -msgstr "" - -#: lib/ManaTools/rpmdragora.pm:869 -msgid "Select all" -msgstr "" - -#: lib/ManaTools/rpmdragora.pm:974 -msgid "" -"I need to access internet to get the mirror list.\n" -"Please check that your network is currently running.\n" -"\n" -"Is it ok to continue?" -msgstr "" - -#: lib/ManaTools/rpmdragora.pm:982 lib/ManaTools/rpmdragora.pm:1018 -msgid "Mirror choice" -msgstr "" - -#: lib/ManaTools/rpmdragora.pm:994 -msgid "Error during download" -msgstr "" - -#: lib/ManaTools/rpmdragora.pm:996 -#, perl-format -msgid "" -"There was an error downloading the mirror list:\n" -"%s\n" -"\n" -"The network, or the website, may be unavailable.\n" -"Please try again later." -msgstr "" - -#: lib/ManaTools/rpmdragora.pm:999 -#, perl-format -msgid "" -"There was an error downloading the mirror list:\n" -"%s\n" -"\n" -"The network, or the Mageia website, may be unavailable.\n" -"Please try again later." -msgstr "" - -#: lib/ManaTools/rpmdragora.pm:1006 -msgid "No mirror" -msgstr "" - -#: lib/ManaTools/rpmdragora.pm:1008 -msgid "I can't find any suitable mirror." -msgstr "" - -#: lib/ManaTools/rpmdragora.pm:1009 -msgid "" -"I can't find any suitable mirror.\n" -"\n" -"There can be many reasons for this problem; the most frequent is\n" -"the case when the architecture of your processor is not supported\n" -"by Mageia Official Updates." -msgstr "" - -#: lib/ManaTools/rpmdragora.pm:1019 -msgid "Please choose the desired mirror." -msgstr "" - -#: lib/ManaTools/rpmdragora.pm:1046 -#, perl-format -msgid "" -"Your medium `%s', used for updates, does not match the version of %s you're " -"running (%s).\n" -"It will be disabled." -msgstr "" - -#: lib/ManaTools/rpmdragora.pm:1049 -#, perl-format -msgid "" -"Your medium `%s', used for updates, does not match the version of Mageia " -"you're running (%s).\n" -"It will be disabled." -msgstr "" - -#: lib/ManaTools/rpmdragora.pm:1079 -msgid "Please wait, downloading mirror addresses." -msgstr "" - -#: lib/ManaTools/rpmdragora.pm:1080 -msgid "Please wait, downloading mirror addresses from the Mageia website." -msgstr "" - -#: lib/ManaTools/rpmdragora.pm:1102 -#, perl-format -msgid "retrieval of [%s] failed" -msgstr "" - -#: lib/ManaTools/rpmdragora.pm:1138 -msgid "Help launched in background" -msgstr "" - -#: lib/ManaTools/rpmdragora.pm:1139 -msgid "" -"The help window has been started, it should appear shortly on your desktop." -msgstr "" diff --git a/po/manatools.pot b/po/manatools.pot new file mode 100644 index 0000000..ff88697 --- /dev/null +++ b/po/manatools.pot @@ -0,0 +1,3445 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-13 23:36+0100\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: lib/ManaTools/Shared/Shorewall.pm:182 +msgid "Keep custom rules" +msgstr "" + +#: lib/ManaTools/Shared/Shorewall.pm:183 +msgid "Drop custom rules" +msgstr "" + +#: lib/ManaTools/Shared/TimeZone.pm:478 lib/ManaTools/Shared/TimeZone.pm:479 +msgid "All servers" +msgstr "" + +#: lib/ManaTools/Shared/Users.pm:379 +msgid "Name field is empty please provide a name" +msgstr "" + +#: lib/ManaTools/Shared/Users.pm:384 +msgid "" +"The name must start with a letter and contain only lower cased latin " +"letters, numbers, '.', '-' and '_'" +msgstr "" + +#: lib/ManaTools/Shared/Users.pm:387 +#, perl-format +msgid "Name is too long. Maximum length is %d" +msgstr "" + +#: lib/ManaTools/Shared/Users.pm:389 lib/ManaTools/Shared/GUI.pm:116 +#: lib/ManaTools/Shared/GUI.pm:162 lib/ManaTools/Shared/GUI.pm:206 +#: lib/ManaTools/Shared/GUI.pm:256 lib/ManaTools/Shared/GUI.pm:1069 +#: lib/ManaTools/Module/AdminMouse.pm:191 lib/ManaTools/Module/Clock.pm:284 +#: lib/ManaTools/Module/Users.pm:335 lib/ManaTools/Module/Users.pm:581 +#: lib/ManaTools/Module/Users.pm:861 lib/ManaTools/Module/Users.pm:1995 +#: lib/ManaTools/Module/Users.pm:2155 lib/ManaTools/Rpmdragora/gui.pm:1281 +#: lib/ManaTools/Rpmdragora/rpmnew.pm:244 +#: lib/ManaTools/Rpmdragora/pkg.pm:652 lib/ManaTools/Rpmdragora/pkg.pm:920 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:309 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:527 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:811 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:939 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1017 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1113 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1186 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1379 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1704 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:2182 +#: lib/ManaTools/rpmdragora.pm:164 lib/ManaTools/rpmdragora.pm:342 +msgid "Ok" +msgstr "" + +#: lib/ManaTools/Shared/Users.pm:815 +#, perl-format +msgid "You cannot remove user <%s> from their primary group" +msgstr "" + +#: lib/ManaTools/Shared/Users.pm:1158 +msgid "Locked" +msgstr "" + +#: lib/ManaTools/Shared/Users.pm:1158 +msgid "Expired" +msgstr "" + +#: lib/ManaTools/Shared/GUI.pm:257 lib/ManaTools/Shared/GUI.pm:491 +#: lib/ManaTools/Shared/GUI.pm:609 lib/ManaTools/Shared/GUI.pm:916 +#: lib/ManaTools/Module/AdminMouse.pm:190 lib/ManaTools/Module/Proxy.pm:339 +#: lib/ManaTools/Module/Clock.pm:283 +#: lib/ManaTools/Module/DisplayManager.pm:255 +#: lib/ManaTools/Module/Firewall.pm:616 lib/ManaTools/Module/Firewall.pm:827 +#: lib/ManaTools/Module/Users.pm:334 lib/ManaTools/Module/Users.pm:405 +#: lib/ManaTools/Module/Users.pm:496 lib/ManaTools/Module/Users.pm:580 +#: lib/ManaTools/Module/Users.pm:860 lib/ManaTools/Module/Users.pm:1994 +#: lib/ManaTools/Module/Users.pm:2154 lib/ManaTools/Module/Hosts.pm:191 +#: lib/ManaTools/Module/Hosts.pm:275 lib/ManaTools/Module/Hosts.pm:462 +#: lib/ManaTools/Rpmdragora/gui.pm:1280 lib/ManaTools/Rpmdragora/pkg.pm:920 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:307 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:525 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:767 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:811 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:941 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1018 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1120 +#: lib/ManaTools/rpmdragora.pm:868 +msgid "Cancel" +msgstr "" + +#: lib/ManaTools/Shared/GUI.pm:309 lib/ManaTools/rpmdragora.pm:338 +msgid "Yes" +msgstr "" + +#: lib/ManaTools/Shared/GUI.pm:310 lib/ManaTools/rpmdragora.pm:339 +msgid "No" +msgstr "" + +#: lib/ManaTools/Shared/GUI.pm:490 lib/ManaTools/Shared/GUI.pm:608 +#: lib/ManaTools/Shared/GUI.pm:915 +msgid "Select" +msgstr "" + +#: lib/ManaTools/MainDisplay.pm:204 lib/ManaTools/Module/Services.pm:465 +#: lib/ManaTools/Module/AdminMouse.pm:221 lib/ManaTools/Module/Clock.pm:465 +#: lib/ManaTools/Module/LogViewer.pm:356 lib/ManaTools/Module/Users.pm:2461 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1725 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:2003 +msgid "_: Translator(s) name(s) & email(s)\n" +msgstr "" + +#: lib/ManaTools/MainDisplay.pm:210 lib/ManaTools/Module/Services.pm:470 +#: lib/ManaTools/Module/AdminMouse.pm:213 lib/ManaTools/Module/Clock.pm:470 +#: lib/ManaTools/Module/LogViewer.pm:361 lib/ManaTools/Module/Users.pm:2466 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1731 +#, perl-format +msgid "Copyright (C) %s Mageia community" +msgstr "" + +#: lib/ManaTools/MainDisplay.pm:211 lib/ManaTools/Module/Services.pm:471 +#: lib/ManaTools/Module/Clock.pm:471 lib/ManaTools/Module/LogViewer.pm:362 +#: lib/ManaTools/Module/Users.pm:2467 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1732 +msgid "GPLv2" +msgstr "" + +#: lib/ManaTools/MainDisplay.pm:212 +msgid "mpan is the mana-tools panel that collects all the utilities." +msgstr "" + +#: lib/ManaTools/MainDisplay.pm:213 lib/ManaTools/Module/Services.pm:474 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1734 +#, perl-format +msgid "" +"

Developers

\n" +"
  • %s
  • \n" +"
  • %s
  • \n" +"
\n" +"

Translators

\n" +"
  • %s
" +msgstr "" + +#: lib/ManaTools/MainDisplay.pm:314 lib/ManaTools/Module/Users.pm:2364 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1580 +msgid "File" +msgstr "" + +#: lib/ManaTools/MainDisplay.pm:315 +msgid "&Exit" +msgstr "" + +#: lib/ManaTools/MainDisplay.pm:326 lib/ManaTools/MainDisplay.pm:327 +#: lib/ManaTools/Module/Users.pm:2378 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1699 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:2181 +msgid "Help" +msgstr "" + +#: lib/ManaTools/MainDisplay.pm:328 lib/ManaTools/Module/Services.pm:426 +#: lib/ManaTools/Module/AdminMouse.pm:187 lib/ManaTools/Module/Proxy.pm:338 +#: lib/ManaTools/Module/Clock.pm:278 +#: lib/ManaTools/Module/DisplayManager.pm:254 +#: lib/ManaTools/Module/LogViewer.pm:333 +#: lib/ManaTools/Module/Firewall.pm:615 lib/ManaTools/Module/Firewall.pm:826 +#: lib/ManaTools/Module/Hosts.pm:461 +msgid "About" +msgstr "" + +#: lib/ManaTools/Module/Services.pm:198 +msgid "adminService" +msgstr "" + +#: lib/ManaTools/Module/Services.pm:305 +msgid "Start when requested" +msgstr "" + +#: lib/ManaTools/Module/Services.pm:308 +msgid "running" +msgstr "" + +#: lib/ManaTools/Module/Services.pm:308 +msgid "stopped" +msgstr "" + +#: lib/ManaTools/Module/Services.pm:386 +msgid "Manage system services by enabling or disabling them" +msgstr "" + +#: lib/ManaTools/Module/Services.pm:394 +msgid "Service" +msgstr "" + +#: lib/ManaTools/Module/Services.pm:395 lib/ManaTools/Module/Users.pm:1049 +msgid "Status" +msgstr "" + +#: lib/ManaTools/Module/Services.pm:396 +msgid "On boot" +msgstr "" + +#: lib/ManaTools/Module/Services.pm:407 lib/ManaTools/Rpmdragora/pkg.pm:1078 +msgid "Information" +msgstr "" + +#: lib/ManaTools/Module/Services.pm:415 +msgid "Start" +msgstr "" + +#: lib/ManaTools/Module/Services.pm:418 +msgid "Stop" +msgstr "" + +#: lib/ManaTools/Module/Services.pm:431 lib/ManaTools/Module/Users.pm:2365 +#: lib/ManaTools/Module/Users.pm:2397 +msgid "Refresh" +msgstr "" + +#: lib/ManaTools/Module/Services.pm:432 +msgid "Close" +msgstr "" + +#: lib/ManaTools/Module/Services.pm:472 +msgid "" +"adminService is the Mageia service and daemon management tool\n" +"\n" +" (from the original " +"idea of Mandriva draxservice)." +msgstr "" + +#: lib/ManaTools/Module/Services.pm:542 +#, perl-format +msgid "Starting %s" +msgstr "" + +#: lib/ManaTools/Module/Services.pm:562 +#, perl-format +msgid "Stopping %s" +msgstr "" + +#: lib/ManaTools/Module/AdminMouse.pm:49 +#: lib/ManaTools/Module/AdminMouse.pm:211 +msgid "AdminMouse" +msgstr "" + +#: lib/ManaTools/Module/AdminMouse.pm:90 +msgid "Please choose your type of mouse." +msgstr "" + +#: lib/ManaTools/Module/AdminMouse.pm:215 +msgid "" +"AdminMouse is the Mageia mouse management tool \n" +"(from the original idea of Mandriva mousedrake)." +msgstr "" + +#: lib/ManaTools/Module/AdminMouse.pm:217 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1998 +msgid "Mageia" +msgstr "" + +#: lib/ManaTools/Module/AdminMouse.pm:243 +msgid "Emulate third button?" +msgstr "" + +#: lib/ManaTools/Module/AdminMouse.pm:250 +msgid "Mouse Port" +msgstr "" + +#: lib/ManaTools/Module/AdminMouse.pm:251 +msgid "Please choose which serial port your mouse is connected to." +msgstr "" + +#: lib/ManaTools/Module/AdminMouse.pm:274 +msgid "Not implemented yet: configuration is not changed" +msgstr "" + +#: lib/ManaTools/Module/Proxy.pm:164 +#: lib/ManaTools/Module/DisplayManager.pm:155 +#: lib/ManaTools/Module/Users.pm:794 lib/ManaTools/Module/Users.pm:2334 +msgid "root privileges required" +msgstr "" + +#: lib/ManaTools/Module/Proxy.pm:192 +#: lib/ManaTools/Module/DisplayManager.pm:186 +msgid "X Restart Required" +msgstr "" + +#: lib/ManaTools/Module/Proxy.pm:192 +#: lib/ManaTools/Module/DisplayManager.pm:186 +msgid "You need to log out and back in again for changes to take effect" +msgstr "" + +#: lib/ManaTools/Module/Proxy.pm:227 +msgid "Proxy should be http://..." +msgstr "" + +#: lib/ManaTools/Module/Proxy.pm:232 +msgid "Proxy should be http://... or https://..." +msgstr "" + +#: lib/ManaTools/Module/Proxy.pm:237 +msgid "URL should begin with 'ftp:' or 'http:'" +msgstr "" + +#: lib/ManaTools/Module/Proxy.pm:250 +msgid "Proxies configuration" +msgstr "" + +#: lib/ManaTools/Module/Proxy.pm:295 +msgid "" +"Here you can set up your proxies configuration (eg: http://" +"my_caching_server:8080)" +msgstr "" + +#: lib/ManaTools/Module/Proxy.pm:303 +msgid "HTTP proxy" +msgstr "" + +#: lib/ManaTools/Module/Proxy.pm:309 +msgid "Use HTTP proxy for HTTPS connections" +msgstr "" + +#: lib/ManaTools/Module/Proxy.pm:315 +msgid "HTTPS proxy" +msgstr "" + +#: lib/ManaTools/Module/Proxy.pm:321 +msgid "FTP proxy" +msgstr "" + +#: lib/ManaTools/Module/Proxy.pm:327 +msgid "No proxy for (comma separated list):" +msgstr "" + +#: lib/ManaTools/Module/Proxy.pm:340 +#: lib/ManaTools/Module/DisplayManager.pm:256 +#: lib/ManaTools/Module/Firewall.pm:617 lib/ManaTools/Module/Firewall.pm:828 +#: lib/ManaTools/Module/Hosts.pm:192 lib/ManaTools/Module/Hosts.pm:276 +#: lib/ManaTools/Module/Hosts.pm:463 lib/ManaTools/rpmdragora.pm:401 +msgid "OK" +msgstr "" + +#: lib/ManaTools/Module/Proxy.pm:362 +msgid "Graphical manager for proxies" +msgstr "" + +#: lib/ManaTools/Module/Clock.pm:140 +msgid "Date, Clock & Time Zone Settings" +msgstr "" + +#: lib/ManaTools/Module/Clock.pm:231 +msgid "Setting date and time" +msgstr "" + +#: lib/ManaTools/Module/Clock.pm:243 +msgid "Enable Network Time Protocol" +msgstr "" + +#: lib/ManaTools/Module/Clock.pm:246 +msgid "Change NTP server" +msgstr "" + +#: lib/ManaTools/Module/Clock.pm:248 lib/ManaTools/Module/Clock.pm:263 +msgid "Current:" +msgstr "" + +#: lib/ManaTools/Module/Clock.pm:250 lib/ManaTools/Module/Clock.pm:265 +#: lib/ManaTools/Module/Clock.pm:454 lib/ManaTools/Module/Clock.pm:460 +msgid "not defined" +msgstr "" + +#: lib/ManaTools/Module/Clock.pm:259 +msgid "TimeZone" +msgstr "" + +#: lib/ManaTools/Module/Clock.pm:261 +msgid "Change Time Zone" +msgstr "" + +#: lib/ManaTools/Module/Clock.pm:279 +msgid "Reset" +msgstr "" + +#: lib/ManaTools/Module/Clock.pm:348 +msgid "Please enter a valid NTP server address." +msgstr "" + +#: lib/ManaTools/Module/Clock.pm:371 +msgid "NTP server - DrakClock" +msgstr "" + +#: lib/ManaTools/Module/Clock.pm:372 +msgid "Choose your NTP server" +msgstr "" + +#: lib/ManaTools/Module/Clock.pm:396 lib/ManaTools/Module/Clock.pm:402 +msgid "Timezone - DrakClock" +msgstr "" + +#: lib/ManaTools/Module/Clock.pm:397 +msgid "Failed to retrieve timezone list" +msgstr "" + +#: lib/ManaTools/Module/Clock.pm:403 +msgid "Which is your timezone?" +msgstr "" + +#: lib/ManaTools/Module/Clock.pm:415 +msgid "GMT - DrakClock" +msgstr "" + +#: lib/ManaTools/Module/Clock.pm:416 +msgid "Is your hardware clock set to GMT?" +msgstr "" + +#: lib/ManaTools/Module/Clock.pm:435 +msgid "Restore data" +msgstr "" + +#: lib/ManaTools/Module/Clock.pm:436 +msgid "Restore date and time only?" +msgstr "" + +#: lib/ManaTools/Module/Clock.pm:472 +msgid "" +"Date, Clock & Time Zone Settings allows to setup time zone and adjust date " +"and time" +msgstr "" + +#: lib/ManaTools/Module/Clock.pm:473 lib/ManaTools/Module/LogViewer.pm:364 +#, perl-format +msgid "" +"

Developers

\n" +"
  • %s
  • \n" +"
  • %s
  • \n" +"
\n" +"

Translators

\n" +"
  • %s
" +msgstr "" + +#: lib/ManaTools/Module/DisplayManager.pm:98 +msgid "LightDM (The Light Display Manager)" +msgstr "" + +#: lib/ManaTools/Module/DisplayManager.pm:99 +msgid "GDM (GNOME Display Manager)" +msgstr "" + +#: lib/ManaTools/Module/DisplayManager.pm:100 +msgid "KDM (KDE Display Manager)" +msgstr "" + +#: lib/ManaTools/Module/DisplayManager.pm:101 +msgid "XDM (X Display Manager)" +msgstr "" + +#: lib/ManaTools/Module/DisplayManager.pm:196 +msgid "Display Manager" +msgstr "" + +#: lib/ManaTools/Module/DisplayManager.pm:222 +msgid "Choosing a display manager" +msgstr "" + +#: lib/ManaTools/Module/DisplayManager.pm:278 +msgid "Graphical configurator for system Display Manager" +msgstr "" + +#: lib/ManaTools/Module/LogViewer.pm:141 +msgid "Log viewer" +msgstr "" + +#: lib/ManaTools/Module/LogViewer.pm:195 +msgid "A tool to monitor your logs" +msgstr "" + +#: lib/ManaTools/Module/LogViewer.pm:199 +msgid "Matching" +msgstr "" + +#: lib/ManaTools/Module/LogViewer.pm:203 +msgid "but not matching" +msgstr "" + +#: lib/ManaTools/Module/LogViewer.pm:207 +msgid "Options" +msgstr "" + +#: lib/ManaTools/Module/LogViewer.pm:212 +msgid "Last boot" +msgstr "" + +#: lib/ManaTools/Module/LogViewer.pm:225 +msgid "Since" +msgstr "" + +#: lib/ManaTools/Module/LogViewer.pm:230 +msgid "Until" +msgstr "" + +#: lib/ManaTools/Module/LogViewer.pm:257 +msgid "Select a unit" +msgstr "" + +#: lib/ManaTools/Module/LogViewer.pm:279 +msgid "From priority" +msgstr "" + +#: lib/ManaTools/Module/LogViewer.pm:299 +msgid "To priority" +msgstr "" + +#: lib/ManaTools/Module/LogViewer.pm:317 +msgid "search" +msgstr "" + +#: lib/ManaTools/Module/LogViewer.pm:320 +msgid "Log content" +msgstr "" + +#: lib/ManaTools/Module/LogViewer.pm:336 +msgid "Save" +msgstr "" + +#: lib/ManaTools/Module/LogViewer.pm:337 +msgid "Quit" +msgstr "" + +#: lib/ManaTools/Module/LogViewer.pm:363 +msgid "Log viewer is a systemd journal viewer" +msgstr "" + +#: lib/ManaTools/Module/LogViewer.pm:382 +msgid "Empty log found" +msgstr "" + +#: lib/ManaTools/Module/LogViewer.pm:475 +#: lib/ManaTools/Rpmdragora/init.pm:165 +msgid "Running in user mode" +msgstr "" + +#: lib/ManaTools/Module/LogViewer.pm:476 +msgid "" +"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." +msgstr "" + +#: lib/ManaTools/Module/LogViewer.pm:499 +msgid "Save as.." +msgstr "" + +#: lib/ManaTools/Module/Firewall.pm:151 +msgid "Web Server" +msgstr "" + +#: lib/ManaTools/Module/Firewall.pm:157 +msgid "Domain Name Server" +msgstr "" + +#: lib/ManaTools/Module/Firewall.pm:163 +msgid "SSH server" +msgstr "" + +#: lib/ManaTools/Module/Firewall.pm:169 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:261 +msgid "FTP server" +msgstr "" + +#: lib/ManaTools/Module/Firewall.pm:175 +msgid "DHCP Server" +msgstr "" + +#: lib/ManaTools/Module/Firewall.pm:182 +msgid "Mail Server" +msgstr "" + +#: lib/ManaTools/Module/Firewall.pm:188 +msgid "POP and IMAP Server" +msgstr "" + +#: lib/ManaTools/Module/Firewall.pm:194 +msgid "Telnet server" +msgstr "" + +#: lib/ManaTools/Module/Firewall.pm:201 +msgid "NFS Server" +msgstr "" + +#: lib/ManaTools/Module/Firewall.pm:210 +msgid "Windows Files Sharing (SMB)" +msgstr "" + +#: lib/ManaTools/Module/Firewall.pm:217 +msgid "Bacula backup" +msgstr "" + +#: lib/ManaTools/Module/Firewall.pm:224 +msgid "Syslog network logging" +msgstr "" + +#: lib/ManaTools/Module/Firewall.pm:231 +msgid "CUPS server" +msgstr "" + +#: lib/ManaTools/Module/Firewall.pm:238 +msgid "MySQL server" +msgstr "" + +#: lib/ManaTools/Module/Firewall.pm:245 +msgid "PostgreSQL server" +msgstr "" + +#: lib/ManaTools/Module/Firewall.pm:252 +msgid "Echo request (ping)" +msgstr "" + +#: lib/ManaTools/Module/Firewall.pm:258 +msgid "Network services autodiscovery (zeroconf and slp)" +msgstr "" + +#: lib/ManaTools/Module/Firewall.pm:264 +msgid "BitTorrent" +msgstr "" + +#: lib/ManaTools/Module/Firewall.pm:271 +msgid "Windows Mobile device synchronization" +msgstr "" + +#: lib/ManaTools/Module/Firewall.pm:285 +msgid "Port scan detection" +msgstr "" + +#: lib/ManaTools/Module/Firewall.pm:423 lib/ManaTools/Module/Firewall.pm:430 +#: lib/ManaTools/Module/Firewall.pm:887 +msgid "Firewall configuration" +msgstr "" + +#: lib/ManaTools/Module/Firewall.pm:424 +msgid "" +"drakfirewall configurator\n" +" This configures a personal firewall for this Mageia " +"machine." +msgstr "" + +#: lib/ManaTools/Module/Firewall.pm:431 +msgid "" +"drakfirewall configurator\n" +"Make sure you have configured your Network/Internet access with\n" +"drakconnect before going any further." +msgstr "" + +#: lib/ManaTools/Module/Firewall.pm:500 +msgid "Interactive Firewall" +msgstr "" + +#: lib/ManaTools/Module/Firewall.pm:504 +msgid "" +"You can be warned when someone accesses to a service or tries to intrude " +"into your computer.\n" +"Please select which network activities should be watched." +msgstr "" + +#: lib/ManaTools/Module/Firewall.pm:510 +msgid "Use Interactive Firewall" +msgstr "" + +#: lib/ManaTools/Module/Firewall.pm:667 +msgid "Graphical manager for interactive firewall rules" +msgstr "" + +#: lib/ManaTools/Module/Firewall.pm:718 lib/ManaTools/Module/Firewall.pm:721 +#: lib/ManaTools/Module/Firewall.pm:969 +msgid "Firewall" +msgstr "" + +#: lib/ManaTools/Module/Firewall.pm:722 +msgid "" +"You can enter miscellaneous ports. \n" +"Valid examples are: 139/tcp 139/udp 600:610/tcp 600:610/udp.\n" +"Have a look at /etc/services for information." +msgstr "" + +#: lib/ManaTools/Module/Firewall.pm:740 +msgid "Which services would you like to allow the Internet to connect to?" +msgstr "" + +#: lib/ManaTools/Module/Firewall.pm:741 +#, perl-format +msgid "Those settings will be saved for the network profile %s" +msgstr "" + +#: lib/ManaTools/Module/Firewall.pm:742 +msgid "Everything (no firewall)" +msgstr "" + +#: lib/ManaTools/Module/Firewall.pm:744 +msgid "Other ports" +msgstr "" + +#: lib/ManaTools/Module/Firewall.pm:745 +msgid "Log firewall messages in system logs" +msgstr "" + +#: lib/ManaTools/Module/Firewall.pm:859 +msgid "Graphical manager for firewall rules" +msgstr "" + +#: lib/ManaTools/Module/Firewall.pm:888 +msgid "" +"Please select the interfaces that will be protected by the firewall.\n" +"\n" +"All interfaces directly connected to Internet should be selected,\n" +"while interfaces connected to a local network may be unselected.\n" +"\n" +"If you intend to use Mageia Internet Connection sharing,\n" +"unselect interfaces which will be connected to local network.\n" +"\n" +"Which interfaces should be protected?\n" +msgstr "" + +#: lib/ManaTools/Module/Firewall.pm:970 +msgid "" +"Your firewall configuration has been manually edited and contains\n" +" rules that may conflict with the configuration that has just been set " +"up.\n" +" What do you want to do?" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:265 +msgid "adminUser" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:269 +msgid "User Data" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:270 +msgid "Account Info" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:271 +msgid "Password Info" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:272 lib/ManaTools/Module/Users.pm:1362 +#: lib/ManaTools/Module/Users.pm:2431 +msgid "Groups" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:275 +msgid "Group Data" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:276 +msgid "Group Users" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:310 +msgid "Choose group" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:318 +msgid "A group with this name already exists. What would you like to do?" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:324 +msgid "Add to the existing group" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:328 +msgid "Add to the 'users' group" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:392 lib/ManaTools/Rpmdragora/gui.pm:390 +#: lib/ManaTools/Rpmdragora/gui.pm:939 lib/ManaTools/Rpmdragora/gui.pm:943 +#: lib/ManaTools/Rpmdragora/gui.pm:948 lib/ManaTools/Rpmdragora/pkg.pm:930 +#: lib/ManaTools/Rpmdragora/pkg.pm:940 lib/ManaTools/Rpmdragora/pkg.pm:954 +#: lib/ManaTools/rpmdragora.pm:829 lib/ManaTools/rpmdragora.pm:1044 +msgid "Warning" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:400 +#, perl-format +msgid "Do you really want to delete the group %s?" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:406 lib/ManaTools/Module/Users.pm:497 +#: lib/ManaTools/Module/Users.pm:2396 +msgid "Delete" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:426 +#, perl-format +msgid "" +"%s is a primary group for user %s\n" +" Remove the user first" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:433 +#, perl-format +msgid "Removing group: %s" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:480 +msgid "Delete files or not?" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:487 +#, perl-format +msgid "" +"Deleting user %s\n" +"Also perform the following actions\n" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:490 +#, perl-format +msgid "Delete Home Directory: %s" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:492 +#, perl-format +msgid "Delete Mailbox: /var/spool/mail/%s" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:520 +#, perl-format +msgid "Removing user: %s" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:552 +msgid "Create New Group" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:562 lib/ManaTools/Module/Users.pm:1578 +msgid "Group Name:" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:572 +msgid "Specify group ID manually" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:574 +msgid "GID" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:607 +msgid "Group already exists, please choose another Group Name" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:615 +#, perl-format +msgid " Group Gid is < %n" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:616 +#, perl-format +msgid "" +"Creating a group with a GID less than %d is not recommended.\n" +" Are you sure you want to do this?\n" +"\n" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:624 +msgid " Group ID is already used " +msgstr "" + +#: lib/ManaTools/Module/Users.pm:625 +msgid "" +"Creating a group with a non unique GID?\n" +"\n" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:637 +#, perl-format +msgid "Adding group: %s " +msgstr "" + +#: lib/ManaTools/Module/Users.pm:693 +msgid "Full Name:" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:702 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:211 +msgid "Login:" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:712 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:218 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:927 +msgid "Password:" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:734 +msgid "Confirm Password:" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:743 +msgid "Login Shell:" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:809 +msgid "Create New User" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:824 +msgid "Create Home Directory" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:828 +msgid "Home Directory:" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:837 +msgid "Create a private group for the user" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:842 +msgid "Specify user ID manually" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:844 +msgid "UID" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:852 +msgid "Click on icon to change it" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:904 +msgid "User already exists, please choose another User Name" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:909 lib/ManaTools/Module/Users.pm:1857 +msgid "Password Mismatch" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:913 lib/ManaTools/Module/Users.pm:1863 +msgid "" +"This password is too simple. \n" +" Good passwords should be > 6 characters" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:920 +#, perl-format +msgid "" +"Home directory <%s> already exists.\n" +"Please uncheck the home creation option, or change the directory path name" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:933 +#, perl-format +msgid "User Uid is < %d" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:934 +#, perl-format +msgid "" +"Creating a user with a UID less than %d is not recommended.\n" +"Are you sure you want to do this?\n" +"\n" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:949 +#, perl-format +msgid "Putting %s to 'users' group" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:963 +#, perl-format +msgid "Creating new group: %s" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:976 +msgid "Adding user: " +msgstr "" + +#: lib/ManaTools/Module/Users.pm:977 +#, perl-format +msgid "Adding user: %s" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:1043 +msgid "User Name" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:1044 +msgid "User ID" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:1045 lib/ManaTools/Module/Users.pm:1792 +msgid "Primary Group" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:1046 +msgid "Full Name" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:1047 +msgid "Login Shell" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:1048 +msgid "Home Directory" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:1089 +msgid "Group Name" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:1090 +msgid "Group ID" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:1091 +msgid "Group Members" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:1274 lib/ManaTools/Module/Users.pm:2227 +#: lib/ManaTools/Module/Users.pm:2242 lib/ManaTools/Module/Users.pm:2258 +#: lib/ManaTools/Module/Users.pm:2427 +msgid "Users" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:1505 +msgid "Home:" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:1604 +msgid "Enable account expiration" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:1607 +msgid "Account expires (YYYY-MM-DD):" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:1614 +msgid "Lock User Account" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:1618 +msgid "Click on the icon to change it" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:1648 +msgid "User last changed password on: " +msgstr "" + +#: lib/ManaTools/Module/Users.pm:1661 +msgid "Enable Password Expiration" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:1665 +msgid "Days before change allowed:" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:1673 +msgid "Days before change required:" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:1681 +msgid "Days warning before change:" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:1689 +msgid "Days before account inactive:" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:1718 +msgid "Select the users to join this group:" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:1722 +msgid "User" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:1763 +msgid "Select groups that the user will be member of:" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:1767 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1139 +msgid "Group" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:1869 +msgid "Please select at least one group for the user" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:1892 +msgid "" +"Please specify Year, Month and Day \n" +" for Account Expiration " +msgstr "" + +#: lib/ManaTools/Module/Users.pm:1908 +msgid "Please fill up all fields in password aging\n" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:1943 +msgid "Strong" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:1943 +msgid "Weak" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:1956 +msgid "Edit User" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:2109 lib/ManaTools/Module/Users.pm:2212 +msgid "Cannot create tab widgets" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:2125 +msgid "Edit Group" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:2293 lib/ManaTools/Module/Users.pm:2393 +msgid "Add User" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:2294 lib/ManaTools/Module/Users.pm:2394 +msgid "Add Group" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:2295 +msgid "&Edit" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:2296 +msgid "&Delete" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:2297 +msgid "Install guest account" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:2366 +msgid "&Quit" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:2373 +msgid "Actions" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:2377 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1607 +msgid "&Help" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:2379 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1609 +msgid "Report Bug" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:2380 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1610 +msgid "&About" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:2395 lib/ManaTools/Module/Hosts.pm:450 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1663 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:2156 +msgid "Edit" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:2410 +msgid "Filter system users" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:2415 +msgid "Search:" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:2417 +msgid "Apply filter" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:2464 +msgid "AdminUser" +msgstr "" + +#: lib/ManaTools/Module/Users.pm:2468 +msgid "" +"AdminUser is a Mageia user management tool \n" +"(from the original idea of Mandriva userdrake)." +msgstr "" + +#: lib/ManaTools/Module/Users.pm:2469 +#, perl-format +msgid "" +"

Developers

\n" +"
  • %s
  • \n" +"
  • %s
  • \n" +"
\n" +"

Translators

\n" +"
  • %s
" +msgstr "" + +#: lib/ManaTools/Module/Hosts.pm:159 lib/ManaTools/Module/Hosts.pm:255 +#: lib/ManaTools/Module/Hosts.pm:435 lib/ManaTools/Module/Hosts.pm:452 +msgid "Hostname" +msgstr "" + +#: lib/ManaTools/Module/Hosts.pm:164 +msgid "Pretty Hostname" +msgstr "" + +#: lib/ManaTools/Module/Hosts.pm:169 +msgid "Static Hostname" +msgstr "" + +#: lib/ManaTools/Module/Hosts.pm:174 +msgid "Chassis" +msgstr "" + +#: lib/ManaTools/Module/Hosts.pm:179 +msgid "Icon Name" +msgstr "" + +#: lib/ManaTools/Module/Hosts.pm:254 lib/ManaTools/Module/Hosts.pm:434 +msgid "IP Address" +msgstr "" + +#: lib/ManaTools/Module/Hosts.pm:256 +msgid "Host aliases" +msgstr "" + +#: lib/ManaTools/Module/Hosts.pm:331 +msgid "Add the information" +msgstr "" + +#: lib/ManaTools/Module/Hosts.pm:365 +msgid "Modify the information" +msgstr "" + +#: lib/ManaTools/Module/Hosts.pm:412 +msgid "Manage hosts definitions" +msgstr "" + +#: lib/ManaTools/Module/Hosts.pm:436 +msgid "Host Aliases" +msgstr "" + +#: lib/ManaTools/Module/Hosts.pm:449 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1095 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1104 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1371 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1664 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:2162 +msgid "Add" +msgstr "" + +#: lib/ManaTools/Module/Hosts.pm:451 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1096 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1105 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1166 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1372 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1662 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:2152 +msgid "Remove" +msgstr "" + +#: lib/ManaTools/Module/Hosts.pm:495 lib/ManaTools/Rpmdragora/pkg.pm:265 +#: lib/ManaTools/Rpmdragora/pkg.pm:803 +msgid "Confirmation" +msgstr "" + +#: lib/ManaTools/Module/Hosts.pm:495 +msgid "Are you sure to drop this host?" +msgstr "" + +#: lib/ManaTools/Module/Hosts.pm:512 +msgid "Graphical manager for hosts definitions" +msgstr "" + +#: lib/ManaTools/Rpmdragora/init.pm:57 +#, perl-format +msgid "Usage: %s [OPTION]..." +msgstr "" + +#: lib/ManaTools/Rpmdragora/init.pm:58 +msgid " --auto assume default answers to questions" +msgstr "" + +#: lib/ManaTools/Rpmdragora/init.pm:59 +msgid "" +" --changelog-first display changelog before filelist in the " +"description window" +msgstr "" + +#: lib/ManaTools/Rpmdragora/init.pm:60 +msgid " --media=medium1,.. limit to given media" +msgstr "" + +#: lib/ManaTools/Rpmdragora/init.pm:61 +msgid "" +" --merge-all-rpmnew propose to merge all .rpmnew/.rpmsave files found" +msgstr "" + +#: lib/ManaTools/Rpmdragora/init.pm:62 +msgid " --mode=MODE set mode (install (default), remove, update)" +msgstr "" + +#: lib/ManaTools/Rpmdragora/init.pm:63 +msgid "" +" --justdb update the database, but do not modify the " +"filesystem" +msgstr "" + +#: lib/ManaTools/Rpmdragora/init.pm:64 +msgid "" +" --no-confirmation don't ask first confirmation question in update mode" +msgstr "" + +#: lib/ManaTools/Rpmdragora/init.pm:65 +msgid " --no-media-update don't update media at startup" +msgstr "" + +#: lib/ManaTools/Rpmdragora/init.pm:66 +msgid " --no-verify-rpm don't verify package signatures" +msgstr "" + +#: lib/ManaTools/Rpmdragora/init.pm:67 +msgid "" +" --parallel=alias,host be in parallel mode, use \"alias\" group, use \"host" +"\" machine to show needed deps" +msgstr "" + +#: lib/ManaTools/Rpmdragora/init.pm:68 +msgid " --rpm-root=path use another root for rpm installation" +msgstr "" + +#: lib/ManaTools/Rpmdragora/init.pm:69 +msgid "" +" --urpmi-root use another root for urpmi db & rpm installation" +msgstr "" + +#: lib/ManaTools/Rpmdragora/init.pm:70 +msgid " --run-as-root force to run as root" +msgstr "" + +#: lib/ManaTools/Rpmdragora/init.pm:71 +msgid " --search=pkg run search for \"pkg\"" +msgstr "" + +#: lib/ManaTools/Rpmdragora/init.pm:72 +msgid "" +" --test only verify if the installation can be achieved " +"correctly" +msgstr "" + +#: lib/ManaTools/Rpmdragora/init.pm:73 +msgid " --version print this tool's version number\n" +msgstr "" + +#: lib/ManaTools/Rpmdragora/init.pm:166 +msgid "" +"You are launching this program as a normal user.\n" +"You will not be able to perform modifications on the system,\n" +"but you may still browse the existing database." +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:41 +msgid "All" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:42 +msgid "Accessibility" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:43 lib/ManaTools/Rpmdragora/icon.pm:44 +#: lib/ManaTools/Rpmdragora/icon.pm:45 lib/ManaTools/Rpmdragora/icon.pm:46 +#: lib/ManaTools/Rpmdragora/icon.pm:47 +msgid "Archiving" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:44 +msgid "Backup" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:45 +msgid "Cd burning" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:46 +msgid "Compression" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:47 lib/ManaTools/Rpmdragora/icon.pm:70 +#: lib/ManaTools/Rpmdragora/icon.pm:86 lib/ManaTools/Rpmdragora/icon.pm:106 +#: lib/ManaTools/Rpmdragora/icon.pm:127 lib/ManaTools/Rpmdragora/icon.pm:147 +msgid "Other" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:48 lib/ManaTools/Rpmdragora/icon.pm:49 +#: lib/ManaTools/Rpmdragora/icon.pm:50 lib/ManaTools/Rpmdragora/icon.pm:51 +#: lib/ManaTools/Rpmdragora/icon.pm:52 lib/ManaTools/Rpmdragora/icon.pm:53 +#: lib/ManaTools/Rpmdragora/icon.pm:54 lib/ManaTools/Rpmdragora/icon.pm:55 +msgid "Communications" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:49 +msgid "Bluetooth" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:50 +msgid "Dial-Up" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:51 +msgid "Fax" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:52 +msgid "Mobile" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:53 +msgid "Radio" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:54 +msgid "Serial" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:55 +msgid "Telephony" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:56 lib/ManaTools/Rpmdragora/icon.pm:62 +msgid "Databases" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:57 lib/ManaTools/Rpmdragora/icon.pm:58 +#: lib/ManaTools/Rpmdragora/icon.pm:59 lib/ManaTools/Rpmdragora/icon.pm:60 +#: lib/ManaTools/Rpmdragora/icon.pm:61 lib/ManaTools/Rpmdragora/icon.pm:62 +#: lib/ManaTools/Rpmdragora/icon.pm:63 lib/ManaTools/Rpmdragora/icon.pm:64 +#: lib/ManaTools/Rpmdragora/icon.pm:65 lib/ManaTools/Rpmdragora/icon.pm:66 +#: lib/ManaTools/Rpmdragora/icon.pm:67 lib/ManaTools/Rpmdragora/icon.pm:68 +#: lib/ManaTools/Rpmdragora/icon.pm:69 lib/ManaTools/Rpmdragora/icon.pm:70 +#: lib/ManaTools/Rpmdragora/icon.pm:71 lib/ManaTools/Rpmdragora/icon.pm:72 +#: lib/ManaTools/Rpmdragora/icon.pm:73 lib/ManaTools/Rpmdragora/icon.pm:74 +#: lib/ManaTools/Rpmdragora/icon.pm:75 lib/ManaTools/Rpmdragora/icon.pm:202 +#: lib/ManaTools/Rpmdragora/icon.pm:203 lib/ManaTools/Rpmdragora/icon.pm:204 +msgid "Development" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:58 +msgid "Basic" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:59 +msgid "C" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:60 +msgid "C++" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:61 +msgid "C#" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:63 +msgid "Debug" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:64 +msgid "Erlang" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:65 +msgid "GNOME and GTK+" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:66 +msgid "Java" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:67 +msgid "KDE and Qt" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:68 +msgid "Kernel" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:69 +msgid "OCaml" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:71 +msgid "Perl" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:72 +msgid "PHP" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:73 +msgid "Python" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:74 +msgid "Tools" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:75 lib/ManaTools/Rpmdragora/icon.pm:175 +msgid "X11" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:76 lib/ManaTools/Rpmdragora/icon.pm:189 +#: lib/ManaTools/Rpmdragora/icon.pm:204 +msgid "Documentation" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:77 +msgid "Editors" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:78 +msgid "Education" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:79 +msgid "Emulators" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:80 +msgid "File tools" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:81 lib/ManaTools/Rpmdragora/icon.pm:82 +#: lib/ManaTools/Rpmdragora/icon.pm:83 lib/ManaTools/Rpmdragora/icon.pm:84 +#: lib/ManaTools/Rpmdragora/icon.pm:85 lib/ManaTools/Rpmdragora/icon.pm:86 +#: lib/ManaTools/Rpmdragora/icon.pm:87 lib/ManaTools/Rpmdragora/icon.pm:88 +#: lib/ManaTools/Rpmdragora/icon.pm:89 lib/ManaTools/Rpmdragora/icon.pm:90 +#: lib/ManaTools/Rpmdragora/icon.pm:91 +msgid "Games" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:82 +msgid "Adventure" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:83 +msgid "Arcade" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:84 +msgid "Boards" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:85 +msgid "Cards" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:87 +msgid "Puzzles" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:88 +msgid "Shooter" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:89 +msgid "Simulation" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:90 +msgid "Sports" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:91 +msgid "Strategy" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:92 +msgid "Geography" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:93 lib/ManaTools/Rpmdragora/icon.pm:94 +#: lib/ManaTools/Rpmdragora/icon.pm:97 lib/ManaTools/Rpmdragora/icon.pm:100 +#: lib/ManaTools/Rpmdragora/icon.pm:103 lib/ManaTools/Rpmdragora/icon.pm:106 +#: lib/ManaTools/Rpmdragora/icon.pm:107 lib/ManaTools/Rpmdragora/icon.pm:110 +msgid "Graphical desktop" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:96 +msgid "Enlightenment" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:99 +msgid "GNOME" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:102 +msgid "Icewm" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:105 +msgid "KDE" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:109 +msgid "WindowMaker" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:112 +msgid "Xfce" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:113 lib/ManaTools/Rpmdragora/icon.pm:114 +#: lib/ManaTools/Rpmdragora/icon.pm:115 lib/ManaTools/Rpmdragora/icon.pm:116 +#: lib/ManaTools/Rpmdragora/icon.pm:117 lib/ManaTools/Rpmdragora/icon.pm:118 +#: lib/ManaTools/Rpmdragora/icon.pm:119 +msgid "Graphics" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:114 +msgid "3D" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:115 lib/ManaTools/Rpmdragora/icon.pm:152 +#: lib/ManaTools/Rpmdragora/icon.pm:180 +msgid "Editors and Converters" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:116 lib/ManaTools/Rpmdragora/icon.pm:135 +#: lib/ManaTools/Rpmdragora/icon.pm:156 lib/ManaTools/Rpmdragora/icon.pm:183 +msgid "Utilities" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:117 +msgid "Photography" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:118 +msgid "Scanning" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:119 +msgid "Viewers" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:120 +msgid "Monitoring" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:121 lib/ManaTools/Rpmdragora/icon.pm:122 +#: lib/ManaTools/Rpmdragora/icon.pm:123 lib/ManaTools/Rpmdragora/icon.pm:124 +#: lib/ManaTools/Rpmdragora/icon.pm:125 lib/ManaTools/Rpmdragora/icon.pm:126 +#: lib/ManaTools/Rpmdragora/icon.pm:127 lib/ManaTools/Rpmdragora/icon.pm:128 +#: lib/ManaTools/Rpmdragora/icon.pm:129 lib/ManaTools/Rpmdragora/icon.pm:169 +msgid "Networking" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:122 +msgid "File transfer" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:123 +msgid "IRC" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:124 +msgid "Instant messaging" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:125 lib/ManaTools/Rpmdragora/icon.pm:209 +msgid "Mail" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:126 +msgid "News" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:128 +msgid "Remote access" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:129 +msgid "WWW" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:130 lib/ManaTools/Rpmdragora/icon.pm:131 +#: lib/ManaTools/Rpmdragora/icon.pm:132 lib/ManaTools/Rpmdragora/icon.pm:133 +#: lib/ManaTools/Rpmdragora/icon.pm:134 lib/ManaTools/Rpmdragora/icon.pm:135 +#: lib/ManaTools/Rpmdragora/icon.pm:136 lib/ManaTools/Rpmdragora/icon.pm:137 +#: lib/ManaTools/Rpmdragora/icon.pm:138 +msgid "Office" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:131 +msgid "Dictionary" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:132 +msgid "Finance" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:133 +msgid "Management" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:134 +msgid "Organizer" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:136 +msgid "Spreadsheet" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:137 +msgid "Suite" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:138 +msgid "Word processor" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:139 +msgid "Publishing" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:140 lib/ManaTools/Rpmdragora/icon.pm:141 +#: lib/ManaTools/Rpmdragora/icon.pm:142 lib/ManaTools/Rpmdragora/icon.pm:143 +#: lib/ManaTools/Rpmdragora/icon.pm:144 lib/ManaTools/Rpmdragora/icon.pm:145 +#: lib/ManaTools/Rpmdragora/icon.pm:146 lib/ManaTools/Rpmdragora/icon.pm:147 +#: lib/ManaTools/Rpmdragora/icon.pm:148 +msgid "Sciences" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:141 +msgid "Astronomy" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:142 +msgid "Biology" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:143 +msgid "Chemistry" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:144 +msgid "Computer science" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:145 +msgid "Geosciences" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:146 +msgid "Mathematics" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:148 +msgid "Physics" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:149 +msgid "Security" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:150 +msgid "Shells" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:151 lib/ManaTools/Rpmdragora/icon.pm:152 +#: lib/ManaTools/Rpmdragora/icon.pm:153 lib/ManaTools/Rpmdragora/icon.pm:154 +#: lib/ManaTools/Rpmdragora/icon.pm:155 lib/ManaTools/Rpmdragora/icon.pm:156 +msgid "Sound" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:153 +msgid "Midi" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:154 +msgid "Mixers" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:155 lib/ManaTools/Rpmdragora/icon.pm:181 +msgid "Players" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:157 lib/ManaTools/Rpmdragora/icon.pm:158 +#: lib/ManaTools/Rpmdragora/icon.pm:159 lib/ManaTools/Rpmdragora/icon.pm:160 +#: lib/ManaTools/Rpmdragora/icon.pm:161 lib/ManaTools/Rpmdragora/icon.pm:162 +#: lib/ManaTools/Rpmdragora/icon.pm:163 lib/ManaTools/Rpmdragora/icon.pm:164 +#: lib/ManaTools/Rpmdragora/icon.pm:165 lib/ManaTools/Rpmdragora/icon.pm:166 +#: lib/ManaTools/Rpmdragora/icon.pm:167 lib/ManaTools/Rpmdragora/icon.pm:168 +#: lib/ManaTools/Rpmdragora/icon.pm:169 lib/ManaTools/Rpmdragora/icon.pm:170 +#: lib/ManaTools/Rpmdragora/icon.pm:171 lib/ManaTools/Rpmdragora/icon.pm:172 +#: lib/ManaTools/Rpmdragora/icon.pm:173 +msgid "System" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:158 +msgid "Base" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:159 +msgid "Boot and Init" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:160 +msgid "Cluster" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:161 lib/ManaTools/Rpmdragora/icon.pm:187 +msgid "Configuration" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:162 lib/ManaTools/Rpmdragora/icon.pm:163 +#: lib/ManaTools/Rpmdragora/icon.pm:164 lib/ManaTools/Rpmdragora/icon.pm:165 +msgid "Fonts" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:163 +msgid "True type" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:164 +msgid "Type1" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:165 +msgid "X11 bitmap" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:166 +msgid "Internationalization" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:167 +msgid "Kernel and hardware" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:168 +msgid "Libraries" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:170 +msgid "Packaging" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:171 +msgid "Printing" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:172 +msgid "Servers" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:176 +msgid "Terminals" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:177 +msgid "Text tools" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:178 +msgid "Toys" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:179 lib/ManaTools/Rpmdragora/icon.pm:180 +#: lib/ManaTools/Rpmdragora/icon.pm:181 lib/ManaTools/Rpmdragora/icon.pm:182 +#: lib/ManaTools/Rpmdragora/icon.pm:183 +msgid "Video" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:182 +msgid "Television" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:186 lib/ManaTools/Rpmdragora/icon.pm:187 +#: lib/ManaTools/Rpmdragora/icon.pm:188 lib/ManaTools/Rpmdragora/icon.pm:189 +#: lib/ManaTools/Rpmdragora/icon.pm:190 lib/ManaTools/Rpmdragora/icon.pm:191 +#: lib/ManaTools/Rpmdragora/icon.pm:192 lib/ManaTools/Rpmdragora/icon.pm:193 +#: lib/ManaTools/Rpmdragora/icon.pm:194 lib/ManaTools/Rpmdragora/icon.pm:195 +msgid "Workstation" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:188 +msgid "Console Tools" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:190 +msgid "Game station" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:191 +msgid "Internet station" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:192 +msgid "Multimedia station" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:193 +msgid "Network Computer (client)" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:194 +msgid "Office Workstation" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:195 +msgid "Scientific Workstation" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:196 lib/ManaTools/Rpmdragora/icon.pm:198 +#: lib/ManaTools/Rpmdragora/icon.pm:199 lib/ManaTools/Rpmdragora/icon.pm:200 +#: lib/ManaTools/Rpmdragora/icon.pm:201 lib/ManaTools/Rpmdragora/gui.pm:133 +msgid "Graphical Environment" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:198 +msgid "GNOME Workstation" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:199 +msgid "IceWm Desktop" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:200 +msgid "KDE Workstation" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:201 +msgid "Other Graphical Desktops" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:205 lib/ManaTools/Rpmdragora/icon.pm:206 +#: lib/ManaTools/Rpmdragora/icon.pm:207 lib/ManaTools/Rpmdragora/icon.pm:208 +#: lib/ManaTools/Rpmdragora/icon.pm:209 lib/ManaTools/Rpmdragora/icon.pm:210 +#: lib/ManaTools/Rpmdragora/icon.pm:211 lib/ManaTools/Rpmdragora/icon.pm:212 +msgid "Server" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:206 +msgid "DNS/NIS" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:207 +msgid "Database" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:208 +msgid "Firewall/Router" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:210 +msgid "Mail/Groupware/News" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:211 +msgid "Network Computer server" +msgstr "" + +#: lib/ManaTools/Rpmdragora/icon.pm:212 +msgid "Web/FTP" +msgstr "" + +#: lib/ManaTools/Rpmdragora/open_db.pm:93 +#: lib/ManaTools/Rpmdragora/gui.pm:1552 +msgid "Fatal error" +msgstr "" + +#: lib/ManaTools/Rpmdragora/open_db.pm:94 +#: lib/ManaTools/Rpmdragora/gui.pm:1553 lib/ManaTools/Rpmdragora/pkg.pm:492 +#, perl-format +msgid "A fatal error occurred: %s." +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:104 +msgid "Search results" +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:104 +msgid "Search results (none)" +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:148 +msgid "Security advisory" +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:158 +msgid "No description" +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:172 +msgid "It is not supported by Mageia." +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:173 +msgid "It may break your system." +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:175 +msgid "This package is not free software" +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:178 +msgid "This package contains a new version that was backported." +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:182 +msgid "This package is a potential candidate for an update." +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:187 +msgid "This is an official update which is supported by Mageia." +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:188 +msgid "This is an unofficial update." +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:192 +msgid "This is an official package supported by Mageia" +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:203 +msgid "Notice: " +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:210 +msgid "Importance: " +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:211 +msgid "Reason for update: " +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:225 +msgid "Version: " +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:226 +msgid "Currently installed version: " +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:227 +msgid "Group: " +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:228 +msgid "Architecture: " +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:229 +msgid "Size: " +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:229 +#, perl-format +msgid "%s KB" +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:230 lib/ManaTools/rpmdragora.pm:675 +msgid "Medium: " +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:252 +msgid "All dependencies installed." +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:270 +msgid "URL: " +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:332 +msgid "Details:" +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:341 +msgid "Files:" +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:347 lib/ManaTools/Rpmdragora/gui.pm:358 +#: lib/ManaTools/Rpmdragora/gui.pm:362 lib/ManaTools/Rpmdragora/pkg.pm:199 +msgid "(Not available)" +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:355 +msgid "Changelog:" +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:372 +msgid "New dependencies:" +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:392 +#, perl-format +msgid "The package \"%s\" was found." +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:393 +msgid "However this package is not in the package list." +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:394 +msgid "You may want to update your urpmi database." +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:396 +msgid "Matching packages:" +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:401 +#, perl-format +msgid "- %s (medium: %s)" +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:939 +#, perl-format +msgid "Removing package %s would break your system" +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:943 +#, perl-format +msgid "" +"The \"%s\" package is in urpmi skip list.\n" +"Do you want to select it anyway?" +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:948 lib/ManaTools/Rpmdragora/pkg.pm:799 +msgid "" +"Rpmdragora or one of its priority dependencies needs to be updated first. " +"Rpmdragora will then restart." +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:1154 +msgid "More information on package..." +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:1156 +msgid "Please choose" +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:1157 +msgid "The following package is needed:" +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:1157 +msgid "One of the following packages is needed:" +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:1269 +msgid "Select package" +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:1367 +msgid "Checking dependencies of package..." +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:1372 +msgid "Some additional packages need to be removed" +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:1383 +msgid "" +"Because of their dependencies, the following package(s) also need to be " +"removed:" +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:1388 +msgid "Some packages cannot be removed" +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:1389 +msgid "" +"Removing these packages would break your system, sorry:\n" +"\n" +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:1397 lib/ManaTools/Rpmdragora/gui.pm:1468 +msgid "" +"Because of their dependencies, the following package(s) must be unselected " +"now:\n" +"\n" +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:1421 +msgid "Additional packages needed" +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:1422 +msgid "" +"To satisfy dependencies, the following package(s) also need to be " +"installed:\n" +"\n" +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:1430 +msgid "Conflicting Packages" +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:1444 +#, perl-format +msgid "%s (belongs to the skip list)" +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:1448 +msgid "One package cannot be installed" +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:1448 +msgid "Some packages cannot be installed" +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:1450 +#, perl-format +msgid "" +"Sorry, the following package cannot be selected:\n" +"\n" +"%s" +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:1451 +#, perl-format +msgid "" +"Sorry, the following packages cannot be selected:\n" +"\n" +"%s" +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:1467 lib/ManaTools/Rpmdragora/pkg.pm:803 +msgid "Some packages need to be removed" +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:1505 +msgid "Some packages are selected." +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:1505 +msgid "Do you really want to quit?" +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:1515 +#, perl-format +msgid "Error: %s appears to be mounted read-only." +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:1519 +msgid "You need to select some packages first." +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:1524 +msgid "Too many packages are selected" +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:1525 +msgid "" +"Warning: it seems that you are attempting to add so many\n" +"packages that your filesystem may run out of free diskspace,\n" +"during or after package installation ; this is particularly\n" +"dangerous and should be considered with care.\n" +"\n" +"Do you really want to install all the selected packages?" +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:1636 +msgid "Please wait, listing packages..." +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:1646 +#: lib/ManaTools/Rpmdragora/rpmnew.pm:138 +#: lib/ManaTools/Rpmdragora/formatting.pm:150 +#: lib/ManaTools/Rpmdragora/pkg.pm:125 lib/ManaTools/Rpmdragora/pkg.pm:174 +#: lib/ManaTools/Rpmdragora/pkg.pm:187 lib/ManaTools/Rpmdragora/pkg.pm:206 +#: lib/ManaTools/Rpmdragora/pkg.pm:684 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1150 +msgid "(none)" +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:1649 +msgid "No update" +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:1650 +msgid "" +"The list of updates is empty. This means that either there is\n" +"no available update for the packages installed on your computer,\n" +"or you already installed all of them." +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:1689 +msgid "Upgradable" +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:1689 +msgid "Installed" +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:1690 +msgid "Addable" +msgstr "" + +#: lib/ManaTools/Rpmdragora/gui.pm:1724 +msgid "Description not available for this package\n" +msgstr "" + +#: lib/ManaTools/Rpmdragora/rpmnew.pm:197 +msgid "Installation finished" +msgstr "" + +#: lib/ManaTools/Rpmdragora/rpmnew.pm:218 +#: lib/ManaTools/Rpmdragora/pkg.pm:642 +msgid "Select a package" +msgstr "" + +#: lib/ManaTools/Rpmdragora/rpmnew.pm:228 +msgid "Remove new file" +msgstr "" + +#: lib/ManaTools/Rpmdragora/rpmnew.pm:229 +msgid "Use new file" +msgstr "" + +#: lib/ManaTools/Rpmdragora/rpmnew.pm:230 +msgid "Do nothing" +msgstr "" + +#: lib/ManaTools/Rpmdragora/rpmnew.pm:347 +msgid "Please wait, searching..." +msgstr "" + +#: lib/ManaTools/Rpmdragora/formatting.pm:126 +msgid "None (installed)" +msgstr "" + +#: lib/ManaTools/Rpmdragora/formatting.pm:127 +msgid "Unknown" +msgstr "" + +#: lib/ManaTools/Rpmdragora/formatting.pm:196 +#, perl-format +msgid "%s of additional disk space will be used." +msgstr "" + +#: lib/ManaTools/Rpmdragora/formatting.pm:197 +#, perl-format +msgid "%s of disk space will be freed." +msgstr "" + +#: lib/ManaTools/Rpmdragora/formatting.pm:202 +#, perl-format +msgid "%s of packages will be retrieved." +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:139 +#, perl-format +msgid "Getting information from %s..." +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:143 +#, perl-format +msgid "Getting '%s' from XML meta-data..." +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:147 lib/ManaTools/Rpmdragora/pkg.pm:463 +#: lib/ManaTools/Rpmdragora/pkg.pm:823 lib/ManaTools/Rpmdragora/pkg.pm:1036 +#: lib/ManaTools/rpmdragora.pm:438 lib/ManaTools/rpmdragora.pm:1095 +msgid "Please wait" +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:160 +#, perl-format +msgid "No xml info for medium \"%s\", only partial result for package %s" +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:162 +#, perl-format +msgid "" +"No xml info for medium \"%s\", unable to return any result for package %s" +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:217 lib/ManaTools/Rpmdragora/pkg.pm:222 +#, perl-format +msgid "Downloading package `%s'..." +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:224 +#, perl-format +msgid " %s%% of %s completed, ETA = %s, speed = %s" +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:225 +#, perl-format +msgid " %s%% completed, speed = %s" +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:266 +msgid "" +"I need to contact the mirror to get latest update packages.\n" +"Please check that your network is currently running.\n" +"\n" +"Is it ok to continue?" +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:284 +msgid "Already existing update media" +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:285 +#, perl-format +msgid "" +"You already have at least one update medium configured, but\n" +"all of them are currently disabled. You should run the Software\n" +"Media Manager to enable at least one (check it in the \"%s\"\n" +"column).\n" +"\n" +"Then, restart \"%s\"." +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:290 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:760 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1642 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1669 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:2058 +msgid "Enabled" +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:295 +msgid "" +"You have no configured update media. MageiaUpdate cannot operate without any " +"update media." +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:296 lib/ManaTools/rpmdragora.pm:978 +msgid "" +"I need to contact the Mageia website to get the mirror list.\n" +"Please check that your network is currently running.\n" +"\n" +"Is it ok to continue?" +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:303 +msgid "How to choose manually your mirror" +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:304 +#, perl-format +msgid "" +"You may also choose your desired mirror manually: to do so,\n" +"launch the Software Media Manager, and then add a `Security\n" +"updates' medium.\n" +"\n" +"Then, restart %s." +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:476 +msgid "Reading updates description" +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:481 lib/ManaTools/Rpmdragora/pkg.pm:517 +msgid "Please wait, finding available packages..." +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:487 +msgid "Please wait, listing base packages..." +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:492 lib/ManaTools/Rpmdragora/pkg.pm:959 +#: lib/ManaTools/Rpmdragora/pkg.pm:984 lib/ManaTools/rpmdragora.pm:673 +#: lib/ManaTools/rpmdragora.pm:697 lib/ManaTools/rpmdragora.pm:715 +msgid "Error" +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:500 +msgid "Please wait, finding installed packages..." +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:625 +msgid "Upgrade information" +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:641 +msgid "These packages come with upgrade information" +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:714 lib/ManaTools/Rpmdragora/pkg.pm:976 +msgid "All requested packages were installed successfully." +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:718 lib/ManaTools/Rpmdragora/pkg.pm:945 +msgid "Problem during installation" +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:719 lib/ManaTools/Rpmdragora/pkg.pm:739 +#: lib/ManaTools/Rpmdragora/pkg.pm:947 +#, perl-format +msgid "" +"There was a problem during the installation:\n" +"\n" +"%s" +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:738 +msgid "Installation failed" +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:761 +msgid "Checking validity of requested packages..." +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:780 +msgid "Unable to get source packages." +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:781 +#, perl-format +msgid "Unable to get source packages, sorry. %s" +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:782 +#, perl-format +msgid "" +"\n" +"\n" +"Error(s) reported:\n" +"%s" +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:808 +msgid "The following package has to be removed for others to be upgraded:" +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:809 +msgid "The following packages have to be removed for others to be upgraded:" +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:813 +msgid "Is it ok to continue?" +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:824 +msgid "Initializing..." +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:832 lib/ManaTools/Rpmdragora/pkg.pm:1019 +msgid "Orphan packages" +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:848 lib/ManaTools/Rpmdragora/pkg.pm:849 +msgid "Preparing package installation..." +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:848 +msgid "Preparing package installation transaction..." +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:852 lib/ManaTools/Rpmdragora/pkg.pm:853 +#, perl-format +msgid "Installing package `%s' (%s/%s)..." +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:852 lib/ManaTools/Rpmdragora/pkg.pm:854 +#, perl-format +msgid "Total: %s/%s" +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:918 +msgid "Change medium" +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:919 +#, perl-format +msgid "Please insert the medium named \"%s\"" +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:923 +msgid "Verifying package signatures..." +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:946 +#, perl-format +msgid "%d installation transactions failed" +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:960 +msgid "Unrecoverable error: no package found for installation, sorry." +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:963 +msgid "Inspecting configuration files..." +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:971 +msgid "" +"The installation is finished; everything was installed correctly.\n" +"\n" +"Some configuration files were created as `.rpmnew' or `.rpmsave',\n" +"you may now inspect some in order to take actions:" +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:977 +msgid "Looking for \"README\" files..." +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:1010 +#, perl-format +msgid "RPM transaction %d/%d" +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:1011 +msgid "Unselect all" +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:1012 +msgid "Details" +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:1057 +msgid "Please wait, removing packages..." +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:1070 +msgid "Problem during removal" +msgstr "" + +#: lib/ManaTools/Rpmdragora/pkg.pm:1071 +#, perl-format +msgid "" +"There was a problem during the removal of packages:\n" +"\n" +"%s" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:73 +msgid "CD-ROM" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:74 +msgid "FTP" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:75 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:85 +msgid "Local" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:76 +msgid "HTTP" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:77 +msgid "HTTPS" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:78 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:81 +msgid "NFS" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:79 +msgid "Removable" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:80 +msgid "rsync" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:83 +msgid "Mirror list" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:125 +msgid "Choose media type" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:126 +msgid "" +"In order to keep your system secure and stable, you must at a minimum set " +"up\n" +"sources for official security and stability updates. You can also choose to " +"set\n" +"up a fuller set of sources which includes the complete official Mageia\n" +"repositories, giving you access to more software than can fit on the Mageia\n" +"discs. Please choose whether to configure update sources only, or the full " +"set\n" +"of sources." +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:134 +msgid "Full set of sources" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:134 +msgid "Update sources only" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:147 +#, perl-format +msgid "" +"This will attempt to install all official sources corresponding to your\n" +"distribution (%s).\n" +"\n" +"I need to contact the Mageia website to get the mirror list.\n" +"Please check that your network is currently running.\n" +"\n" +"Is it ok to continue?" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:155 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:170 +msgid "Please wait, adding media..." +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:206 +msgid "Browse..." +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:239 +msgid "Add a medium" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:250 +msgid "Adding a medium:" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:255 +msgid "Type of medium:" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:260 +msgid "Local files" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:260 +msgid "Medium path:" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:261 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:262 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:263 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:724 +msgid "URL:" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:262 +msgid "RSYNC server" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:263 +msgid "HTTP server" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:264 +msgid "Removable device (CD-ROM, DVD, ...)" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:265 +msgid "Path or mount point:" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:283 +msgid "Medium name:" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:298 +msgid "Create media for a whole distribution" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:301 +msgid "Tag this medium as an update medium" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:344 +msgid "You need to fill up at least the two first entries." +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:347 +#, perl-format +msgid "" +"There is already a medium called <%s>,\n" +"do you really want to replace it?" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:425 +msgid "Global options for package installation" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:435 +msgid "Verify RPMs to be installed:" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:439 +msgid "never" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:439 +msgid "always" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:457 +msgid "Download program to use:" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:480 +msgid "XML meta-data download policy:" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:485 +msgid "Never" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:485 +msgid "On-demand" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:485 +msgid "Update-only" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:485 +msgid "Always" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:609 +msgid "Source Removal" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:611 +#, perl-format +msgid "Are you sure you want to remove source \"%s\"?" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:612 +msgid "Are you sure you want to remove the following sources?" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:617 +msgid "Please wait, removing medium..." +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:710 +msgid "Edit a medium" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:719 +#, perl-format +msgid "Editing medium \"%s\":" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:731 +msgid "Downloader:" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:762 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1643 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1670 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:2061 +msgid "Updates" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:769 +msgid "Save changes" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:771 +msgid "Proxy..." +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:809 +msgid "You need to insert the medium to continue" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:810 +msgid "" +"In order to save the changes, you need to insert the medium in the drive." +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:878 +msgid "Configure proxies" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:889 +#, perl-format +msgid "Proxy settings for media \"%s\"" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:890 +msgid "Global proxy settings" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:895 +msgid "" +"If you need a proxy, enter the hostname and an optional port (syntax: " +"):" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:901 +msgid "Enable proxy" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:905 +msgid "Proxy hostname:" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:910 +msgid "You may specify a username/password for the proxy authentication:" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:918 +msgid "User:" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1028 +msgid "Add a parallel group" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1028 +msgid "Edit a parallel group" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1052 +msgid "Add a medium limit" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1052 +msgid "Choose a medium to add to the media limit:" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1069 +msgid "Add a host" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1069 +msgid "Type in the hostname or IP address of the host to add:" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1083 +#, perl-format +msgid "Editing parallel group \"%s\":" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1087 +msgid "Group name:" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1088 +msgid "Protocol:" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1090 +msgid "Media limit:" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1099 +msgid "Hosts:" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1135 +msgid "Configure parallel urpmi (distributed execution of urpmi)" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1139 +msgid "Protocol" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1139 +msgid "Media limit" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1140 +msgid "Command" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1170 +msgid "Edit..." +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1178 +msgid "Add..." +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1198 +msgid "Manage keys for digital signatures of packages" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1224 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1645 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:2068 +msgid "Medium" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1249 +msgid "Keys" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1273 +msgid "no name found, key doesn't exist in rpm keyring!" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1319 +msgid "Add a key" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1320 +#, perl-format +msgid "Choose a key to add to the medium %s" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1343 +msgid "Remove a key" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1344 +#, perl-format +msgid "" +"Are you sure you want to remove the key
%s
from medium %s?
(name " +"of the key: %s)" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1563 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1968 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:2145 +msgid "Configure media" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1581 +#: lib/ManaTools/rpmdragora.pm:870 +msgid "Update" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1582 +msgid "Add a specific media mirror" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1583 +msgid "Add a custom medium" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1584 +msgid "&Close" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1594 +msgid "&Options" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1595 +msgid "Global options" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1596 +msgid "Manage keys" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1597 +msgid "Parallel" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1598 +msgid "Proxy" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1608 +msgid "Manual" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1644 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:2065 +msgid "Type" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1680 +msgid "Up" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1681 +msgid "Down" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1733 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1996 +msgid "Rpmdragora is the Mageia package management tool." +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1833 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1897 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:2092 +msgid "This medium needs to be updated to be usable. Update it now?" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1975 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1976 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1977 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1978 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1979 +msgid "/_File" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1976 +msgid "/_Update" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1976 +msgid "U" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1977 +msgid "/Add a specific _media mirror" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1977 +msgid "M" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1978 +msgid "/_Add a custom medium" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1978 +msgid "A" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1979 +msgid "/Close" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1979 +msgid "W" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1980 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1981 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1982 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1983 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1984 +msgid "/_Options" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1981 +msgid "/_Global options" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1981 +msgid "G" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1982 +msgid "/Manage _keys" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1982 +msgid "K" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1983 +msgid "/_Parallel" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1983 +msgid "P" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1984 +msgid "/P_roxy" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1984 +msgid "R" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1986 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1987 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1988 +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1989 +msgid "/_Help" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1987 +msgid "/_Report Bug" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1989 +msgid "/_About..." +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1992 +msgid "Rpmdragora" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:1994 +#, perl-format +msgid "Copyright (C) %s by Mandriva" +msgstr "" + +#: lib/ManaTools/Rpmdragora/edit_urpm_sources.pm:2204 +msgid "" +"The Package Database is locked. Please close other applications\n" +"working with the Package Database. Do you have another media\n" +"manager on another desktop, or are you currently installing\n" +"packages as well?" +msgstr "" + +#: lib/ManaTools/rpmdragora.pm:259 +msgid "Software Packages Removal" +msgstr "" + +#: lib/ManaTools/rpmdragora.pm:260 +msgid "Software Packages Update" +msgstr "" + +#: lib/ManaTools/rpmdragora.pm:261 +msgid "Software Packages Installation" +msgstr "" + +#: lib/ManaTools/rpmdragora.pm:330 +msgid "Do not ask me next time" +msgstr "" + +#: lib/ManaTools/rpmdragora.pm:388 +msgid "Dependencies" +msgstr "" + +#: lib/ManaTools/rpmdragora.pm:674 +#, perl-format +msgid "" +"Unable to add medium, errors reported:\n" +"\n" +"%s" +msgstr "" + +#: lib/ManaTools/rpmdragora.pm:697 +msgid "Unable to create medium." +msgstr "" + +#: lib/ManaTools/rpmdragora.pm:702 +msgid "Failure when adding medium" +msgstr "" + +#: lib/ManaTools/rpmdragora.pm:703 +#, perl-format +msgid "" +"There was a problem adding medium:\n" +"\n" +"%s" +msgstr "" + +#: lib/ManaTools/rpmdragora.pm:729 +msgid "rpmdragora" +msgstr "" + +#: lib/ManaTools/rpmdragora.pm:735 +msgid "Please wait, updating media..." +msgstr "" + +#: lib/ManaTools/rpmdragora.pm:758 +msgid "Error retrieving packages" +msgstr "" + +#: lib/ManaTools/rpmdragora.pm:759 +#, perl-format +msgid "" +"It's impossible to retrieve the list of new packages from the media\n" +"`%s'. Either this update media is misconfigured, and in this case\n" +"you should use the Software Media Manager to remove it and re-add it in " +"order\n" +"to reconfigure it, either it is currently unreachable and you should retry\n" +"later." +msgstr "" + +#: lib/ManaTools/rpmdragora.pm:787 +#, perl-format +msgid "Copying file for medium `%s'..." +msgstr "" + +#: lib/ManaTools/rpmdragora.pm:790 +#, perl-format +msgid "Examining file of medium `%s'..." +msgstr "" + +#: lib/ManaTools/rpmdragora.pm:793 +#, perl-format +msgid "Examining remote file of medium `%s'..." +msgstr "" + +#: lib/ManaTools/rpmdragora.pm:797 +msgid " done." +msgstr "" + +#: lib/ManaTools/rpmdragora.pm:801 +msgid " failed!" +msgstr "" + +#: lib/ManaTools/rpmdragora.pm:806 +#, perl-format +msgid "%s from medium %s" +msgstr "" + +#: lib/ManaTools/rpmdragora.pm:810 +#, perl-format +msgid "Starting download of `%s'..." +msgstr "" + +#: lib/ManaTools/rpmdragora.pm:814 +#, perl-format +msgid "" +"Download of `%s'\n" +"time to go:%s, speed:%s" +msgstr "" + +#: lib/ManaTools/rpmdragora.pm:817 +#, perl-format +msgid "" +"Download of `%s'\n" +"speed:%s" +msgstr "" + +#: lib/ManaTools/rpmdragora.pm:829 +msgid "" +"No active medium found. You must enable some media to be able to update them." +msgstr "" + +#: lib/ManaTools/rpmdragora.pm:836 +msgid "Update media" +msgstr "" + +#: lib/ManaTools/rpmdragora.pm:850 +msgid "Media" +msgstr "" + +#: lib/ManaTools/rpmdragora.pm:869 +msgid "Select all" +msgstr "" + +#: lib/ManaTools/rpmdragora.pm:974 +msgid "" +"I need to access internet to get the mirror list.\n" +"Please check that your network is currently running.\n" +"\n" +"Is it ok to continue?" +msgstr "" + +#: lib/ManaTools/rpmdragora.pm:982 lib/ManaTools/rpmdragora.pm:1018 +msgid "Mirror choice" +msgstr "" + +#: lib/ManaTools/rpmdragora.pm:994 +msgid "Error during download" +msgstr "" + +#: lib/ManaTools/rpmdragora.pm:996 +#, perl-format +msgid "" +"There was an error downloading the mirror list:\n" +"%s\n" +"\n" +"The network, or the website, may be unavailable.\n" +"Please try again later." +msgstr "" + +#: lib/ManaTools/rpmdragora.pm:999 +#, perl-format +msgid "" +"There was an error downloading the mirror list:\n" +"%s\n" +"\n" +"The network, or the Mageia website, may be unavailable.\n" +"Please try again later." +msgstr "" + +#: lib/ManaTools/rpmdragora.pm:1006 +msgid "No mirror" +msgstr "" + +#: lib/ManaTools/rpmdragora.pm:1008 +msgid "I can't find any suitable mirror." +msgstr "" + +#: lib/ManaTools/rpmdragora.pm:1009 +msgid "" +"I can't find any suitable mirror.\n" +"\n" +"There can be many reasons for this problem; the most frequent is\n" +"the case when the architecture of your processor is not supported\n" +"by Mageia Official Updates." +msgstr "" + +#: lib/ManaTools/rpmdragora.pm:1019 +msgid "Please choose the desired mirror." +msgstr "" + +#: lib/ManaTools/rpmdragora.pm:1046 +#, perl-format +msgid "" +"Your medium `%s', used for updates, does not match the version of %s you're " +"running (%s).\n" +"It will be disabled." +msgstr "" + +#: lib/ManaTools/rpmdragora.pm:1049 +#, perl-format +msgid "" +"Your medium `%s', used for updates, does not match the version of Mageia " +"you're running (%s).\n" +"It will be disabled." +msgstr "" + +#: lib/ManaTools/rpmdragora.pm:1079 +msgid "Please wait, downloading mirror addresses." +msgstr "" + +#: lib/ManaTools/rpmdragora.pm:1080 +msgid "Please wait, downloading mirror addresses from the Mageia website." +msgstr "" + +#: lib/ManaTools/rpmdragora.pm:1102 +#, perl-format +msgid "retrieval of [%s] failed" +msgstr "" + +#: lib/ManaTools/rpmdragora.pm:1138 +msgid "Help launched in background" +msgstr "" + +#: lib/ManaTools/rpmdragora.pm:1139 +msgid "" +"The help window has been started, it should appear shortly on your desktop." +msgstr "" -- cgit v1.2.1