summaryrefslogtreecommitdiffstats
path: root/mgaapplet
diff options
context:
space:
mode:
Diffstat (limited to 'mgaapplet')
-rwxr-xr-xmgaapplet1070
1 files changed, 1070 insertions, 0 deletions
diff --git a/mgaapplet b/mgaapplet
new file mode 100755
index 00000000..a440ef49
--- /dev/null
+++ b/mgaapplet
@@ -0,0 +1,1070 @@
+#!/usr/bin/perl
+################################################################################
+# Mandriva Online #
+# #
+# Copyright (C) 2003-2010 Mandriva #
+# #
+# Daouda Lo #
+# Thierry Vignaud <tvignaud at mandriva dot 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. #
+################################################################################
+
+use strict;
+use POSIX ":sys_wait_h";
+use lib qw(/usr/lib/libDrakX);
+use standalone; # for explanations
+use common;
+use run_program;
+
+BEGIN { unshift @::textdomains, 'mgaonline' }
+
+use mygtk2 qw(gtknew); #- do not import gtkadd which conflicts with ugtk2 version
+use ugtk2 qw(:all);
+use lib qw(/usr/lib/libDrakX/drakfirsttime);
+use mgaonline;
+use mgaapplet_gui;
+use Gtk2::Notify '-init', 'mgaapplet';
+use Rpmdrake::open_db;
+
+if (!find { $_ eq '--auto-update' } @ARGV) {
+ if (my $pid = mgaonline::is_running('mgaapplet')) {
+ if ($::testing) {
+ warn "mgaapplet already running ($pid)\n";
+ } else {
+ die "mgaapplet already running ($pid)\n";
+ }
+ }
+}
+
+
+my $online_site = "http://www.mageia.org/";
+my ($menu, $timeout, $network_timeout, $state_global, $sub_state);
+
+read_sys_config();
+$config{UPDATE_FREQUENCY} ||= 3*60*60; # default to 3hours
+if ($::testing) {
+ $config{FIRST_CHECK_DELAY} = 1 * 1000; # 1 second
+} else {
+ $config{FIRST_CHECK_DELAY} ||= 5 * 60 * 1000; # default to 5 minutes
+}
+$config{DISTRO_CHECK_DELAY} ||= 60*60*24; # default : one day
+
+my %state = (
+ delayed => {
+ colour => [ 'busy' ],
+ menu => [ 'check' ],
+ do_not_use_bubble => 1,
+ tt => [
+ #-PO: here %s will be replaced by the local time (eg: "Will check updates at 14:03:50"
+ N("Will check updates at %s", POSIX::strftime("%T", localtime(time() + $config{FIRST_CHECK_DELAY}/1000)))
+ ],
+ },
+
+ okay => {
+ colour => [ 'okay' ],
+ menu => [ 'check' ],
+ do_not_use_bubble => 1,
+ tt => [ N_("Your system is up-to-date") ]
+ },
+ critical => {
+ colour => [ 'noconf' ],
+ menu => [ 'check' ],
+ tt => [ N_("Service configuration problem. Please check logs and send mail to support\@mageiaonline.com") ]
+ },
+ busy => {
+ colour => [ 'busy' ],
+ menu => [],
+ do_not_use_bubble => 1,
+ tt => [ N_("Please wait, finding available packages...") ]
+ },
+ updates => {
+ colour => [ 'error' ],
+ menu => [ 'update', 'check' ],
+ tt => [ N_("New updates are available for your system") ]
+ },
+ new_distribution => {
+ colour => [ 'bundle' ],
+ menu => [ 'upgrade_distro', 'check' ],
+ urgency => 'low',
+ tt => [ N("A new version of Mageia Linux distribution has been released") ]
+ },
+ no_more_supported => {
+ colour => [ 'disabled' ],
+ menu => [ 'check' ],
+ urgency => 'low',
+ tt => []
+ },
+ extended_support_is_enabled => {
+ colour => [ 'okay' ],
+ menu => [ 'check' ],
+ urgency => 'low',
+ tt => []
+ },
+ unconfigured_restricted_media => {
+ colour => [ 'bundle' ],
+ menu => [ 'add_restricted_media', 'check' ],
+ urgency => 'low',
+ tt => [ N("An additional package medium is available for your distribution.") ]
+ },
+ disconnected => {
+ colour => [ 'disconnect' ],
+ menu => [ 'confNetwork' ],
+ tt => [ N_("Network is down. Please configure your network") ],
+ do_not_use_bubble => mgaonline::is_running('net_applet'),
+ },
+ disabled => {
+ colour => [ 'disabled' ],
+ menu => [],
+ tt => [ N_("Service is not activated. Please click on \"Online Website\"") ]
+ },
+ locked => {
+ colour => [ 'noconf' ],
+ menu => [ 'check' ],
+ tt => [ N_("urpmi database locked") ],
+ do_not_use_bubble => 1,
+ },
+ loop_locked => {
+ colour => [ 'noconf' ],
+ menu => [ 'check' ],
+ tt => [ N_("urpmi database locked") ],
+ },
+ notsupported => {
+ colour => [ 'disabled' ],
+ menu => [],
+ tt => [ N_("Release not supported (too old release, or development release)") ]
+ },
+ end_of_extended_support => {
+ colour => [ 'disabled' ],
+ menu => [],
+ tt => [ get_obsolete_message_() ]
+ },
+ no_update_medium => {
+ colour => [ 'noconf' ],
+ menu => [ 'check' ],
+ tt => [ N_("No medium found. You must add some media through 'Software Media Manager'.") ],
+ },
+ no_enterprise_update_medium => {
+ colour => [ 'noconf' ],
+ menu => [ 'add_enterprise_update_medium' , 'check' ],
+ tt => [ N("An additional package medium is available for your distribution.") ]
+ },
+ no_enabled_medium => {
+ colour => [ 'noconf' ],
+ menu => [ 'check' ],
+ tt => [ 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\".", N("Enabled"), 'mgaapplet') ],
+ },
+ );
+
+my %comm_codes = (
+ locked => {
+ code => 2,
+ status => 'locked',
+ log => "urpmi database locked, skipping updating urpmi database",
+ },
+ error_updating => {
+ code => 3,
+ status => 'critical',
+ log => N_("Error updating media"),
+ },
+ no_update_medium => {
+ code => 4,
+ status => 'no_update_medium',
+ log => "no update media configured",
+ },
+ no_enabled_medium => {
+ code => 5,
+ status => 'no_enabled_medium',
+ log => "all update media are disabled",
+ },
+ updates => {
+ code => 6,
+ status => 'updates',
+ log => "Checking... Updates are available\n\n",
+ },
+ uptodate => {
+ code => 7,
+ status => 'okay',
+ log => "Packages are up to date\n",
+ },
+ db_not_open => {
+ code => 8,
+ status => 'critical',
+ log => "Failed to open urpmi database\n",
+ },
+ unconfigured_restricted_media => {
+ code => 9,
+ status => 'unconfigured_restricted_media',
+ log => "Missing restricted media\n",
+ },
+ no_enterprise_update_medium => {
+ code => 10,
+ status => 'no_enterprise_update_medium',
+ log => "Missing enterprise update media\n",
+ },
+);
+
+my %actions = (
+ 'update' => { name => N("Install updates"), launch => \&installUpdates },
+ 'add_restricted_media' => { name => N("Add additional package medium"), launch => \&prepare_add_restricted },
+ 'add_enterprise_update_medium' => { name => N("Add additional package medium"), launch => \&prepare_add_enterprise_update_media },
+ 'check' => { name => N("Check Updates"), launch => \&checkUpdates },
+ 'confNetwork' => { name => N("Configure Network"), launch => \&configNetwork },
+ 'upgrade_distro' => { name => N("Upgrade the system"), launch => \&upgrade },
+ );
+
+my $icon = Gtk2::StatusIcon->new;
+#$icon->shape_combine_mask($img, 0, 0);
+$icon->signal_connect(popup_menu => sub {
+ my ($_icon, $button, $time) = @_;
+ $menu and $menu->popup(undef, undef, undef, undef, $button, $time);
+ });
+$icon->signal_connect(activate => sub {
+ my %click_actions = (
+ unconfigured_restricted_media => \&prepare_add_restricted,
+ no_update_medium => \&add_media,
+ no_enterprise_update_medium => \&prepare_add_enterprise_update_media,
+ no_enabled_medium => \&add_media,
+ updates => \&installUpdates,
+ new_distribution => \&upgrade,
+ no_more_supported => \&no_more_supported,
+ );
+ my $action = $state_global;
+ # default to updates rather than distro upgrade:
+ if ($action eq 'new_distribution' && $sub_state eq 'updates') {
+ $action = 'updates';
+ }
+
+ $click_actions{$action}->() if ref $click_actions{$action};
+ });
+foreach my $opt (@ARGV) {
+ if ($opt eq '--force' || $opt eq '-f') { setAutoStart('TRUE') }
+ if ($opt =~ /--(rpm-root|urpmi-root)=(.*)/) {
+ $::rpmdrake_options{$1}[0] = $2;
+ }
+}
+
+my ($download_dir, $download_all);
+{
+ my $temp_urpm = Rpmdrake::open_db::fast_open_urpmi_db();
+ $root = $temp_urpm->{root};
+ $download_dir = $temp_urpm->{cachedir};
+}
+
+my ($new_distro, $no_more_supported, $extended_maintenance_url, $extended_maintenance_end);
+my ($current_apimdv_distro);
+
+get_product_id();
+
+shouldStart() or die "$localfile should be set to TRUE: please use --force or -f option to launch applet\n";
+
+go2State('delayed');
+
+Glib::Timeout->add_seconds($config{FIRST_CHECK_DELAY}/1000, sub {
+ # schedule future checks:
+ setup_cyclic_check();
+ # perform a test after initial delay:
+ checkNetwork();
+ checkUpdates();
+ 0;
+ });
+
+
+$SIG{USR1} = 'IGNORE';
+$SIG{USR2} = 'IGNORE';
+$SIG{CHLD} = \&harvester;
+$SIG{HUP} = \&restart_applet;
+
+run_program::raw({ detach => 1 }, 'ionice', '-p', $$, '-n7');
+
+
+Gtk2->main;
+
+ugtk2::exit(0);
+
+sub is_extended_support_not_ended() {
+ return if !is_extmaint_supported();
+ require POSIX;
+ my $d = POSIX::strftime("%G%m%d", localtime(time()));
+ $d < $extended_maintenance_end;
+}
+
+
+sub is_there_a_new_distributions() {
+ # sanity check for cooker:
+ # (2008.0 wrongly reports 'Devel' instead of 'Official'):
+ return if $product_id->{branch} eq 'Devel' && !is_it_2008_0();
+ # some OEM Philco systems have no specific updates repo
+ # so we can only blacklist them here directly
+ return if cat_("/etc/oem-release") =~ /philco/i;
+
+ my @distros = get_distro_list();
+ return if !@distros;
+
+ # do not do anything if current distribution isn't listed on api.mdv.com:
+ return if !member($product_id->{version}, map { $_->{version} } @distros);
+
+ # only compare first distro: if it's not the same as the currently installed one,
+ # then it's the most recent release:
+ my $new_distribution = $distros[0];
+
+ if (-e get_stale_upgrade_filename()) {
+ $new_distro = $new_distribution;
+ return 1;
+ }
+
+ $current_apimdv_distro = find_current_distro(@distros);
+ $no_more_supported = $current_apimdv_distro->{obsoleted_by} if !is_extmaint_supported();
+ ($extended_maintenance_url, $extended_maintenance_end) = @$current_apimdv_distro{qw(extended-maintenance extended-maintenance-end)};
+ refresh_no_more_supported_msg();
+ if ($no_more_supported) {
+ $new_distro = find { $_->{version} eq $no_more_supported } @distros;
+ return if is_extended_support_not_ended();
+ }
+
+ # the "live upgrade" is not available on 2008.0:
+ return if is_it_2008_0();
+
+ # no if we're using the extended maintenance:
+ return if is_extended_support_not_ended();
+
+ if ($new_distribution && $new_distribution->{version} ne $product_id->{version}) {
+ $new_distro = $new_distribution;
+ log::explanations(sprintf("new '%s' distribution was released on %s", $new_distro->{version}, $new_distro->{release_date}));
+ return 1;
+ }
+}
+
+
+my ($mdv_update_pid, $checker_pid, $media_manager_pid, $locked_count);
+
+# FIXME: flushing a hash would be less error prone when adding new stuff:
+sub clean_distro_cache() {
+ undef $new_distro;
+ undef $no_more_supported;
+ undef $extended_maintenance_url;
+ undef $extended_maintenance_end;
+ }
+
+sub is_false {
+ my ($s) = @_;
+ !text2bool($s) && $s != 1;
+}
+
+sub process_state {
+ my ($state) = @_;
+ log::explanations($state->{log});
+ $sub_state = $state->{status};
+
+ if ($sub_state eq 'locked') {
+ $locked_count++;
+ $sub_state = 'loop_locked' if $locked_count > 10;
+ } else {
+ $locked_count = 0;
+ }
+
+ # busy critical delayed disabled disconnected locked loop_locked new_distribution no_enabled_medium no_enterprise_update_medium no_more_supported no_update_medium notsupported okay unconfigured_restricted_media update
+ if (!member($sub_state, qw(okay))) {
+ go2State($sub_state);
+ } elsif ($no_more_supported
+ && !text2bool($local_config{DO_NOT_ASK_FOR_NO_MORE_SUPPORTED})
+ && !text2bool($config{EXTENDED_SUPPORT})
+ && !text2bool($local_config{EXTENDED_SUPPORT_OFFERED})) {
+ go2State('no_more_supported');
+ } elsif ($current_apimdv_distro->{obsoleted_by} && text2bool($config{EXTENDED_SUPPORT})
+ && is_extmaint_supported()
+ && !text2bool($local_config{EXTENDED_SUPPORT_SPLASHED})) {
+ $state{extended_support_is_enabled}{tt}[0] =
+ N("Basic maintenance for this distribution has expired. Thanks to your subscription to extended maintenance, your system will be kept up to date until %s", iso8601_date_to_locale($extended_maintenance_end));
+ go2State('extended_support_is_enabled');
+ setVar('EXTENDED_SUPPORT_SPLASHED', bool2yesno(1));
+ # FIXME: just drop this state once upgrade from 2009.0 has been tested:
+ } elsif (is_extmaint_supported() && !is_extended_support_not_ended()) {
+ go2State('end_of_extended_support');
+ } elsif ($new_distro && is_false($config{DO_NOT_ASK_FOR_DISTRO_UPGRADE})
+ && is_false($local_config{DO_NOT_ASK_FOR_DISTRO_UPGRADE})) {
+ go2State('new_distribution');
+ } else {
+ go2State($sub_state);
+ }
+}
+
+# Signal management
+sub harvester {
+ my ($_signame, $_clean) = @_;
+ my ($childpid, @pids);
+ my $schedule_checks;
+ do {
+ $childpid = waitpid(-1, &WNOHANG);
+ my $status = $? >> 8;
+ if ($mdv_update_pid && $mdv_update_pid == $childpid) {
+ undef $mdv_update_pid;
+ # make sure to not report new distro after distro upgrade:
+ clean_distro_cache();
+ $schedule_checks = 1;
+ } elsif ($checker_pid && $checker_pid == $childpid) {
+ undef $checker_pid;
+ my ($state) = grep { $_->{code} eq $status } values %comm_codes;
+ if ($state) {
+ process_state($state);
+ }
+ } elsif ($media_manager_pid && $media_manager_pid == $childpid) {
+ undef $media_manager_pid;
+ $schedule_checks = 1;
+ }
+ push @pids, $childpid;
+ } while $childpid > 0;
+ Glib::Timeout->add(200, sub { silentCheck(); 0 }) if $schedule_checks;
+ return @pids;
+}
+
+sub restart_applet() {
+ local $SIG{CHLD} = 'DEFAULT';
+ log::explanations(N("Received SIGHUP (probably an upgrade has finished), restarting applet."));
+ { redo if wait() > 0 }
+ exec($0, '--auto-update');
+}
+
+# FIXME: we can run many drakconnect when network is down:
+sub configNetwork() {
+ log::explanations(N_("Launching drakconnect\n"));
+ fork_exec("/usr/sbin/drakconnect");
+}
+
+# only enable 'download all packages at once' on 2010.1 and further:
+sub is_download_all_enabled() {
+ # prevent crashing on 2008.1 and 2009.0:
+ eval { is_it_a_devel_distro() } || !member($product_id->{version}, qw(2008.0 2008.1 2009.0 2009.1));
+}
+
+sub confirm_upgrade() {
+ local $mygtk2::left_padding = 0;
+ my $warn_me = text2bool($local_config{DO_NOT_ASK_FOR_DISTRO_UPGRADE});
+ my $w = new_portable_dialog(N("New version of Mageia Linux distribution"));
+ my ($temp_dir, $box);
+
+ my $browse;
+ $browse = gtksignal_connect(
+ Gtk2::FileChooserButton->new(N("Browse"), 'select-folder'),
+ 'current-folder-changed' => sub {
+ $temp_dir = $_[0]->get_current_folder;
+ });
+ $browse->set_current_folder($download_dir);
+
+ my $res = fill_n_run_portable_dialog($w,
+ [
+ get_banner(),
+ gtknew('Label_Left', text => N("A new version of Mageia Linux distribution has been released."), @common),
+ gtknew('HButtonBox', layout => 'start', children_tight => [
+ new_link_button($new_distro->{url}, N("More info about this new version")),
+ ]),
+ gtknew('Label_Left', text => N("Do you want to upgrade to the '\%s' distribution?",
+ $new_distro->{name} || $new_distro->{version}), @common),
+ gtknew('CheckButton', text => N("Do not ask me next time"), active_ref => \$warn_me),
+ # active_ref option is missing on 2008.0:
+ (is_download_all_enabled() ?
+ (gtknew('CheckButton', text => N("Download all packages at once") . "\n" .
+ N("(Warning: You will need quite a lot of free space)"),
+ active_ref => \$download_all, sensitive_ref => \$browse,
+ toggled => sub { $box and $box->set_sensitive($download_all) },
+ ),
+ $box = gtknew('HBox', sensitive => $download_all,
+ children => [
+ 0, gtknew('Label_Left', text => N("Where to download packages:")),
+ 1 , $browse,
+ ]),
+ ) : ()),
+ create_okcancel($w, N("Next"), N("Cancel")),
+ ]);
+
+ setVar('DO_NOT_ASK_FOR_DISTRO_UPGRADE', bool2text($warn_me));
+ $local_config{DO_NOT_ASK_FOR_DISTRO_UPGRADE} = bool2text($warn_me);
+ if ($res) {
+ $download_dir = $temp_dir;
+ really_confirm_upgrade();
+ } else {
+ return 0;
+ }
+}
+
+
+sub get_obsolete_message_() {
+ N("Maintenance for this Mageia Linux version has ended. No more updates will be delivered for this system.");
+}
+
+sub get_obsolete_message() {
+ join("\n\n",
+ get_obsolete_message_(),
+ N("In order to keep your system secure, you can:"),
+ );
+}
+
+sub refresh_no_more_supported_msg() {
+ my $basic_msg = get_obsolete_message_();
+ my $distro = N("Mageia Linux");
+ my $msg;
+
+ # is extended maintenance available?
+ if ($extended_maintenance_url) {
+ if ($no_more_supported eq 'none') {
+ $msg = N("You should get extended maintenance.");
+ } else {
+ $msg = N("You should either get extended maintenance or upgrade to a newer version of the %s distribution.",
+ $distro);
+ }
+ } else {
+ $msg = N("You should upgrade to a newer version of the %s distribution.", $distro);
+ }
+ $state{no_more_supported}{tt}[0] = join(' ', $basic_msg, $msg);
+}
+
+sub no_more_supported_choice() {
+ local $mygtk2::left_padding = 0;
+ my $warn_me = text2bool($local_config{DO_NOT_ASK_FOR_NO_MORE_SUPPORTED});
+ # FIXME: just tell radio buttons' children to wrap instead:
+ local $mgaapplet_gui::width = 580;
+ my $w = new_portable_dialog(N("Your distribution is no longer supported"));
+ my ($b1, $b2, $b3);
+ my $choice = $extended_maintenance_url ? 'extended' : ($no_more_supported ne 'none' ? 'upgrade' : undef);
+
+ my @widgets = (
+ get_banner(N("Extended Maintenance")),
+ gtknew('Label_Left',
+ text => get_obsolete_message() . "\n", @common),
+ if_($extended_maintenance_url,
+ $b1 = gtknew('RadioButton',
+ text => N("Purchase a maintenance extension for this version (%s) and keep it running until %s.",
+ $product_id->{version},
+ iso8601_date_to_locale($extended_maintenance_end)),
+
+ toggled => sub {
+ ($choice, $warn_me) = ('extended', undef) if $_[0]->get_active;
+ },
+
+ ),
+ gtknew('HSeparator'),
+ ),
+ ($no_more_supported ne 'none' ? (
+ gtknew('VBox', children_tight => [
+ $b2 = gtknew('RadioButton',
+ text => N("Do you want to upgrade to the '\%s' distribution?",
+ $new_distro->{name} || $new_distro->{version}),
+ toggled => sub {
+ ($choice, $warn_me) = ('upgrade', undef) if $_[0]->get_active;
+ },
+ if_($b1, group => $b1)),
+ new_link_button($new_distro->{url}, N("More info about this new version")),
+ ]),
+ gtknew('HSeparator'),
+ ) : ()),
+ $b3 = gtknew('RadioButton', text => N("Do not ask me next time"),
+ toggled => sub {
+ $choice = 'nothing' if $_[0]->get_active;
+ $warn_me = $_[0]->get_active },
+ group => $b1 || $b2),
+ create_okcancel($w, N("Next"), N("Cancel")),
+ );
+
+ #$_ and $_->set_border_width(8) foreach $b1, $b2, $b3;
+
+ # explicitely wrap too long message:
+ foreach ($b1, $b2) {
+ next if !$_ || !$_->child;
+ $_->child->set_line_wrap(1);
+ $_->child->set_size_request($width-50, -1);
+ }
+
+ my $res = fill_n_run_portable_dialog($w, \@widgets);
+
+ setVar('EXTENDED_SUPPORT_OFFERED', bool2yesno(1));
+ setVar('DO_NOT_ASK_FOR_NO_MORE_SUPPORTED', bool2text($warn_me));
+ $local_config{DO_NOT_ASK_FOR_NO_MORE_SUPPORTED} = bool2text($warn_me);
+ if ($res) {
+ return $choice;
+ } else {
+ return 0;
+ }
+}
+
+
+my $no_more_supported_wip;
+sub no_more_supported() {
+ return if $mdv_update_pid || $no_more_supported_wip;
+ $no_more_supported_wip = 1;
+ my $choice = no_more_supported_choice();
+ if ($choice eq 'upgrade') {
+ really_confirm_upgrade() and real_upgrade();
+ } elsif ($choice eq 'extended') {
+ get_extended_maintenance();
+ } elsif ($choice eq 'nothing') {
+ $icon->set_visible(0);
+ }
+ undef $no_more_supported_wip;
+}
+
+
+sub get_extended_maintenance() {
+ $mdv_update_pid = fork_exec('mgaapplet-add-media-helper',
+ if_($::testing, '--testing'),
+ if_($root, "--urpmi-root=$root"),
+ '--product=extended',
+ $product_id->{version});
+}
+
+
+sub really_confirm_upgrade() {
+ local $mygtk2::left_padding = 0;
+ my $w = ugtk2->new(N("New version of Mageia Linux distribution"), width => $width + 20);
+
+ # estimated package size:
+ my $c;
+ foreach (run_program::get_stdout('rpm', '-qa', '--qf', '%{Archivesize}\n')) {
+ $c += $_;
+ }
+ $c = formatXiB($c);
+
+ {
+ # use wizard button order (for both 2008.1 & 2009.0):
+ local $::isWizard = 1;
+ local $w->{pop_it} = 0;
+ local $::isInstall = 1;
+ gtkadd($w->{window},
+ gtknew('VBox', children_tight => [
+ get_banner(),
+ gtknew('Label_Left', text => N("This upgrade requires high bandwidth network connection (cable, xDSL, ...) and may take several hours to complete."),
+ @common),
+ gtknew('Label_Left', text => N("Estimated download data will be %s", $c), @common),
+ gtknew('Label_Left', text => N("You should close all other running applications before continuing.") .
+ (detect_devices::isLaptop() ?
+ ' ' .
+ N("You should put your laptop on AC and favor ethernet connection over wifi, if available.")
+ : ''),
+ @common),
+ create_okcancel($w, N("Next"), N("Cancel")),
+ ]),
+ );
+ }
+ $w->{ok}->grab_focus;
+ return $w->main;
+}
+
+sub upgrade() {
+ return if $mdv_update_pid;
+ return if !confirm_upgrade();
+ real_upgrade();
+}
+
+sub real_upgrade() {
+ $mdv_update_pid = fork_exec('mgaapplet-upgrade-helper', "--new_distro_version=$new_distro->{version}",
+ if_($::testing, '--testing'),
+ if_($download_all, "--download-all=$download_dir"),
+ if_($root, "--urpmi-root=$root"));
+}
+
+sub add_media() {
+ return if $media_manager_pid;
+ log::explanations("Launching 'Software Media Manager'");
+ $media_manager_pid = fork_exec('/usr/sbin/edit-urpm-sources.pl', '--no-splash', if_($root, "--urpmi-root=$root"));
+}
+
+sub installUpdates() {
+ return if $mdv_update_pid;
+ log::explanations(N_("Launching MageiaUpdate\n"));
+ $mdv_update_pid = fork_exec('MandrivaUpdate', '--no-media-update', '--no-confirmation', '--no-splash',
+ if_($root, "--urpmi-root=$root"));
+ silentCheck(); gtkflush();
+}
+
+sub checker_exit {
+ my ($state) = @_;
+ POSIX::_exit($comm_codes{$state}{code});
+}
+
+sub update_backport_media {
+ my ($urpm) = @_;
+ # update inactive backport media:
+ my @inactive_backport_media = Rpmdrake::open_db::get_inactive_backport_media($urpm);
+ return if !@inactive_backport_media;
+ log::explanations("updating inactive backport media " . join(', ', @inactive_backport_media));
+ foreach (@inactive_backport_media) {
+ run_program::run('urpmi.update', if_($root, "--urpmi-root=$root"), $_);
+ }
+}
+
+sub silentCheck() {
+ my $check_time if 0;
+ my $new_time = time();
+ if (!$check_time || $new_time - $check_time > $config{DISTRO_CHECK_DELAY}) {
+ clean_distro_cache();
+ $check_time = $new_time;
+ is_there_a_new_distributions();
+ }
+
+ return if $mdv_update_pid || $checker_pid;
+ log::explanations(N_("Computing new updates...\n"));
+ go2State('busy');
+
+ # are there any updates ?
+
+ $checker_pid = fork();
+ if (defined $checker_pid) {
+ return if $checker_pid; # parent
+
+ # immediate exit, else forked gtk+ object destructors will badly catch up parent applet
+ my $_safe = before_leaving {
+ my $err = $@;
+ log::explanations("mgaapplet check crashed: $err ");
+ warn "Error: $err\n" . common::backtrace();
+ POSIX::_exit(0);
+ };
+
+ # be nice with other processes:
+ setpriority(0, $$, 7); # 0 is PRIO_PROCESS
+
+ my $will_not_update_media;
+ require urpm;
+ require urpm::lock;
+ # so that get_inactive_backport_media() doesn't vivify $urpm->{media}:
+ my $urpm = Rpmdrake::open_db::fast_open_urpmi_db();
+ {
+ local $urpm->{fatal} = sub {
+ print "Fatal: @_\n";
+ $will_not_update_media = 1;
+ };
+ local $urpm->{error} = $urpm->{fatal};
+
+ urpm::lock::urpmi_db($urpm, 'exclusive', 1);
+ }
+ checker_exit('locked') if $will_not_update_media;
+
+ # prevent crashing on 2008.1 and 2009.0:
+ my $is_it_a_devel_distro = eval { is_it_a_devel_distro() };
+
+ my $media = $is_it_a_devel_distro ? '-a' : '--update';
+ if (!run_program::run('urpmi.update', $media, if_($root, "--urpmi-root=$root"))) {
+ checker_exit('error_updating') if $will_not_update_media;
+ }
+
+ if (!is_it_2008_0()) {
+ update_backport_media($urpm);
+ }
+
+ require urpm::select;
+ require urpm::media;
+ # this eats 52Mb of RAM on 64bit:
+ # (hence we do it in the forked helper so that the applet doesn't eat too much RAM)
+ urpm::media::configure($urpm, if_(!$is_it_a_devel_distro, update => 1));
+
+ # prevent crashing on 2008.1 and 2009.0:
+ my @update_medias = eval { get_update_medias($urpm) };
+ if ($@) {
+ @update_medias = grep { $_->{update} } @{$urpm->{media}};
+ }
+
+ if (!@update_medias) {
+ if (is_enterprise_media_supported()) {
+ checker_exit('no_enterprise_update_medium');
+ } else {
+ checker_exit('no_update_medium');
+ }
+ } elsif (!any { ! $_->{ignore} } @update_medias) {
+ checker_exit('no_enabled_medium');
+ }
+
+ if (my $_db = urpm::db_open_or_die($urpm)) {
+ my $requested = {};
+ my $state = {};
+ my $need_restart = urpm::select::resolve_dependencies(
+ $urpm, $state, $requested,
+ callback_choices => sub { 0 },
+ priority_upgrade => $urpm->{options}{'priority-upgrade'},
+ auto_select => 1,
+ );
+ my @requested_strict = map { scalar $_->fullname } @{$urpm->{depslist}}[keys %{$state->{selected}}];
+
+ if ($need_restart || @requested_strict) {
+ # FIXME: log first found pkgs?
+ warn ">> need_restart=$need_restart, updates=" . join(', ', @requested_strict) . "\n";
+ checker_exit('updates');
+ } else {
+ if (!text2bool($local_config{DO_NOT_ASK_FOR_RESTRICTED})) {
+ if (is_restricted_media_configured($urpm)) {
+ checker_exit('uptodate');
+ } else {
+ checker_exit('unconfigured_restricted_media');
+ }
+ } else {
+ checker_exit('uptodate');
+ }
+ }
+ } else {
+ checker_exit('db_not_open');
+ }
+ checker_exit('updates');
+ } else {
+ log::explanations("cannot fork: %s", "update checker ($!)");
+ go2State('critical');
+ }
+}
+
+sub okState() { log::explanations(N_("System is up-to-date\n")); go2State('okay') }
+
+
+sub setup_cyclic_check() {
+ $network_timeout = Glib::Timeout->add(2000, sub { checkNetwork(); 1 });
+ $timeout = Glib::Timeout->add_seconds($config{UPDATE_FREQUENCY}, sub {
+ checkUpdates();
+ 1;
+ });
+}
+
+sub getTime() {
+ my $d = localtime();
+ $d =~ s/\s+/_/g;
+ $d;
+}
+
+sub setLastTime() {
+ my $date = getTime();
+ setVar('LASTCHECK', $date);
+}
+
+sub has_network_connection_2008() {
+ require network::network;
+ require network::tools;
+ my $net = {};
+ network::network::read_net_conf($net);
+ my ($_gw_intf, $_is_up, $gw_address, $_dns_server) = network::tools::get_internet_connection($net);
+ to_bool($gw_address);
+}
+
+sub checkNetwork() {
+ return if $checker_pid;
+ require network::tools;
+ # alternatively we could have used 2008.0's network::tools::connected()
+ my $has_network = is_it_2008_0() ? has_network_connection_2008()
+ : network::tools::has_network_connection();
+ if (!$has_network) {
+ # do not notify if already done:
+ return if member($state_global, qw(disconnected));
+ log::explanations(N_("Checking Network: seems disabled\n"));
+ go2State('disconnected');
+ } elsif (member($state_global, qw(disconnected))) {
+ silentCheck(); #- state has changed, update
+ }
+}
+
+sub checkUpdates() {
+ member($state_global, qw(disconnected)) or silentCheck();
+}
+
+sub go2State {
+ my ($state) = @_;
+ $menu->destroy if $menu;
+ $menu = setState($state);
+ $state_global = $state;
+ gtkflush();
+}
+
+sub shouldStart() {
+ to_bool($local_config{AUTOSTART} ne 'FALSE');
+}
+
+sub about_dialog() {
+ my $ver = 1; # automatically set from spec file
+ my $url = $online_site;
+ $url =~ s/^https:/http:/;
+ my $w = gtknew('AboutDialog', name => N("Mageia Online %s", $ver),
+ copyright => N("Copyright (C) %s by %s", 'Mandriva', '2001-2010') . "\n" .
+ N("Copyright (C) %s by %s", 'Mageia', '2010-2011'),
+ license => join('', cat_('/usr/share/common-licenses/GPL')),
+ icon => '/usr/share/icons/mini/mgaonline.png',
+ comments => N("Mageia Online gives access to Mageia web services."),
+ website => $url,
+ website_label => N("Online WebSite"),
+ authors => 'Thierry Vignaud <vignaud@mandriva.com>',
+ artists => 'Hélène Durosini',
+ translator_credits =>
+ #-PO: put here name(s) and email(s) of translator(s) (eg: "John Smith <jsmith@nowhere.com>")
+ N("_: Translator(s) name(s) & email(s)\n"),
+ transient_for => $::main_window, modal => 1, position_policy => 'center-on-parent',
+ );
+
+ $w->show_all;
+ $w->run;
+ return 1;
+}
+
+sub setState {
+ my ($state) = @_;
+ my $checkme;
+ my $previous_state if 0;
+ my @arr = @{$state{$state}{menu}};
+ my $tmp = eval { gtkcreate_pixbuf($state{$state}{colour}[0]) };
+ $icon->set_from_pixbuf($tmp) if $tmp;
+ $icon->set_tooltip(formatAlaTeX(translate($state{$state}{tt}[0])));
+ my @invisible_states = qw(delayed okay disconnected locked);
+ $icon->set_visible(!member($state, @invisible_states));
+
+ # do not show icon while checking if previously hidden:
+ $icon->set_visible(0) if $state eq 'busy' && member($previous_state, @invisible_states);
+
+ $previous_state = $state;
+
+ gtkflush(); # so that bubbles are displayed on right icon
+
+ if ($state{$state}{tt}[0] && $icon->isa('Gtk2::StatusIcon') && !$state{$state}{do_not_use_bubble}) {
+ my $bubble = Gtk2::Notify->new_with_status_icon(N("Warning"), formatAlaTeX(translate($state{$state}{tt}[0])) . "\n",
+ '/usr/share/icons/mgaonline.png', $icon);
+ if ($state eq 'new_distribution') {
+ $bubble->add_action('clicked', N("More Information"), \&upgrade);
+ if ($sub_state eq 'updates') {
+ push @arr, 'update';
+ }
+ } elsif ($state eq 'no_more_supported') {
+ $bubble->add_action('clicked', N("More Information"), \&no_more_supported);
+ if ($sub_state eq 'updates') {
+ push @arr, 'update';
+ }
+ } elsif ($state eq 'updates') {
+ unshift @arr, 'upgrade_distro' if $new_distro;
+ $bubble->add_action('clicked', N("Install updates"), \&installUpdates);
+ } elsif ($state eq 'unconfigured_restricted_media') {
+ $bubble->add_action('clicked', N("More Information"), \&prepare_add_restricted);
+ } elsif ($state eq 'no_enterprise_update_medium') {
+ $bubble->add_action('clicked', N("More Information"), \&prepare_add_enterprise_update_media);
+ } elsif (member($state, qw(no_enabled_medium no_update_medium))) {
+ $bubble->add_action('clicked', N("Add media"), \&add_media);
+ }
+
+ $bubble->set_urgency($state{$state}{urgency}) if $state{$state}{urgency};
+ $bubble->set_timeout(5000);
+ eval { $bubble->show };
+ }
+
+ my $menu = Gtk2::Menu->new;
+ foreach (@arr) {
+ my $action = $actions{$_};
+ next if !ref($action->{launch});
+ $menu->append(gtksignal_connect(gtkshow(Gtk2::MenuItem->new_with_label($action->{name})), activate => $action->{launch}));
+ }
+ $menu->append(gtkshow(Gtk2::SeparatorMenuItem->new));
+ $menu->append(gtksignal_connect(gtkshow(Gtk2::MenuItem->new_with_label(N("About..."))),
+ activate => \&about_dialog));
+ $menu->append(gtksignal_connect(gtkshow(Gtk2::MenuItem->new_with_label(N("Updates Configuration"))),
+ activate => sub { run_program::raw({ detach => 1 }, 'mgaapplet-config') }));
+ $menu->append(gtksignal_connect(gtkset_active($checkme = Gtk2::CheckMenuItem->new_with_label(N("Always launch on startup")), shouldStart()), toggled => sub { setAutoStart(uc(bool2text($checkme->get_active))) }));
+ $checkme->show;
+ $menu->append(gtksignal_connect(gtkshow(Gtk2::MenuItem->new_with_label(N("Quit"))), activate => sub { mainQuit() }));
+ $menu;
+}
+
+sub setAutoStart {
+ my $state = shift;
+ my $date = getTime();
+ if (-f $localfile) {
+ setVar('AUTOSTART', $state);
+ } else {
+ output_p($localfile,
+ qq(AUTOSTART=$state
+LASTCHECK=$date
+));
+ }
+}
+
+sub mainQuit() {
+# setAutoStart('FALSE');
+ Glib::Source->remove($timeout) if $timeout;
+ Glib::Source->remove($network_timeout) if $network_timeout;
+ Gtk2->main_quit;
+}
+
+sub get_enabled_restricted_media {
+ my ($urpm) = @_;
+ grep { $_->{name} =~ /restricted/i && !$_->{ignore} } @{$urpm->{media}};
+}
+
+sub is_restricted_media_configured {
+ my ($urpm) = @_;
+ return 1 if !is_restricted_media_supported();
+
+ my @restricted_media = get_enabled_restricted_media($urpm);
+ my @names = map { $_->{name} } @restricted_media;
+ # we need both 'Restricted' & 'Restricted Updates' media
+ # those who did online update trough mgaapplet do not have restricted medium, hence the test for 2 medium:
+ @restricted_media >= (urpm::cfg::get_arch() =~ /64/ ? 4 : 2)
+ && (grep { /Restricted Updates/ } @names) && (grep { /Restricted/ && !/Updates/ } @names);
+}
+
+sub really_prepare_add_restricted() {
+ $mdv_update_pid = run_program::raw({ detach => 1 },
+ 'mgaapplet-add-media-helper',
+ $product_id->{version});
+}
+
+sub prepare_add_restricted() {
+ my $warn_me = text2bool($local_config{DO_NOT_ASK_FOR_RESTRICTED});
+ return if $warn_me;
+ my $w = new_portable_dialog(N("New medium available"));
+ my $res =
+ fill_n_run_portable_dialog(
+ $w,
+ [
+ get_banner(N("New medium available")),
+ gtknew('Label_Left', text =>
+ N("You use '%s' distribution and therefore have privileged access to additional software.",
+ translate_product($product_id->{version})) . "\n\n" .
+ N("Do you want to install this additional software repository?"), @common),
+ gtknew('CheckButton', text => N("Do not ask me next time"), active_ref => \$warn_me),
+ create_okcancel($w, N("Next"), N("Cancel")),
+ ]);
+ setVar('DO_NOT_ASK_FOR_RESTRICTED', bool2text($warn_me));
+ $local_config{DO_NOT_ASK_FOR_RESTRICTED} = bool2text($warn_me);
+ $res ? really_prepare_add_restricted() : 0;
+}
+
+
+sub really_prepare_add_enterprise() {
+ $mdv_update_pid = run_program::raw(
+ { detach => 1 },
+ 'mgaapplet-add-media-helper',
+ join('', @$product_id{qw(type product version)})
+ );
+}
+
+sub prepare_add_enterprise_update_media() {
+ my $warn_me = text2bool($local_config{DO_NOT_ASK_FOR_ENTERPRISE_UPDATE_MEDIA});
+ return if $warn_me;
+ my $w = new_portable_dialog(N("New medium available"));
+ my $res =
+ fill_n_run_portable_dialog(
+ $w,
+ [
+ get_banner(N("New medium available")),
+ gtknew('Label_Left', text =>
+ N("You use '%s' distribution and therefore have privileged access to additional software.",
+ N_("Mageia Enterprise Server")) . "\n\n" .
+ N("Do you want to install this additional software repository?"), @common),
+ gtknew('CheckButton', text => N("Do not ask me next time"), active_ref => \$warn_me),
+ create_okcancel($w, N("Next"), N("Cancel")),
+ ]);
+ setVar('DO_NOT_ASK_FOR_ENTERPRISE_UPDATE_MEDIA', bool2text($warn_me));
+ $local_config{DO_NOT_ASK_FOR_ENTERPRISE_UPDATE_MEDIA} = bool2text($warn_me);
+ $res ? really_prepare_add_enterprise() : 0;
+}