aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ManaTools/rpmdragora.pm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ManaTools/rpmdragora.pm')
-rw-r--r--lib/ManaTools/rpmdragora.pm1165
1 files changed, 1165 insertions, 0 deletions
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 <tvignaud@mandriva.com>
+# Copyright (c) 2003, 2004, 2005 MandrakeSoft SA
+# Copyright (c) 2005, 2007 Mandriva SA
+# Copyright (c) 2013 - 2015 Matteo Pasotti <matteo.pasotti@gmail.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2, as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+#*****************************************************************************
+#
+# $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 <br> instead of '\n'
+ $contents =~ s/\n/<br>/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;