#!/usr/bin/perl use strict; use warnings; use IO::Prompter; use File::Which qw( which ); # Configurable variables my $lang = 'en-CA'; my $install = "$ENV{HOME}/.local/bin"; my $working = "/tmp/firefox.new"; # Download link as provided by https://www.mozilla.org/$lang/firefox/developer/ my $url = 'https://download.mozilla.org/?product=firefox-devedition-latest-ssl' . '&os=linux64&lang='.$lang; # Ensure that we can unzip unless (which("bunzip2")) { die "Requires bunzip2. Try:\n" . "sudo apt install zutils or your distro's equivalent\n"; } # Only understood argument is to not bother verifying the package my ($download_key, $verify) = (0,1); if (defined $ARGV[0]) { if ($ARGV[0] eq '--no-verify') { $verify = 0; } else { die "Didn't understand argument $ARGV[0]\n"; } } # If verification is to be done, make sure we have the key unless ($verify) { print "Checking for Mozilla GPG key in keyring...\n"; system("gpg --list-keys release\@mozillla.com 2>&1 > /dev/null"); if ($?) { my $YN = prompt (-in => *STDIN, "You don't currently have " . "Mozilla's GPG key in your keyring.\n" . "Would you like to install it? If not, installation " . "will not be verified. [y/N]: ", -single ); if ($YN eq 'y' || $YN eq 'Y') { $download_key = 1; } else { $verify = 0; } } } # If a previous download still exists remove it if ( -e $working ) { system("rm -rf $working"); if ($?) { die "Working directory " . $working . "already exists and failed to remove: $!\n"; } } # Get version currently installed my $current = `$install/firefox/firefox-bin --version`; $current =~ s/.*\s([^\s])/$1/; chomp $current; use WWW::Mechanize; my $mech = WWW::Mechanize->new(); # $url is actually going to redirect to the proper current dowload so just get # the redirect. my $head = $mech->head($url); my ($location, $version); # This redirect will have the version id, so we can use that to determine if a # new version actually exists if ($head->{'_msg'}) { $version = $location = $head->{'_previous'}->{'_headers'}->{'location'}; $version =~ s/^.*\-([^\-]*)\.tar\.bz2$/$1/; if ($version eq $current) { die "Current ($current) is the same as New ($version)\n"; } } else { print "unable to find new download\n"; } mkdir($working) || die "Couldn't make $working: $!\n"; # Download package print "Fetching package $location...\n"; $mech->get($location); $mech->save_content( $working."/firefox-".$version.".tar.bz2", binmode => ':raw', decoded_by_headers => 1 ); # If verification is required, get signature as well if ($verify) { $location .= '.asc'; print "Fetching GPG signature $location...\n"; $mech->get($location); $mech->save_content( $working."/firefox-".$version.".tar.bz2.asc", binmode => ':raw', decoded_by_headers => 1 ); } # If key still needs to be fetched, get it if ($download_key) { $location =~ s/linux-x86_64.*$/KEY/; print "Fetching GPG key $location...\n"; $mech->get($location); $mech->save_content( $working."/mozilla.pgp", binmode => ':raw', decoded_by_headers => 1 ); # And install it print "Installing Mozilla GPG key in keyring...\n"; system("gpg --import $working/mozilla.pgp 2>&1 > /dev/null"); if ($?) { die "Warning: failed to import key. Cannot verify integrity.\n" . "Downloaded to " . $working . ". You can check and install it to " . $install . "manually: " . $! . "\n"; } unlink("$working/mozilla.pgp"); } # Verify the package if ($verify) { print "Verifying download with Mozilla GPG key...\n"; system("gpg --verify $working/firefox-$version.tar.bz2.asc"); if ($?) { die "Warning: failed to verify download. Signing failed.\n" . "Downloaded to " . $working . ". You can check and install it to " . $install . " manually: " . $! . "\n"; } } # Uncompress print "Uncompressing download with bunzip2...\n"; system("bunzip2 $working/firefox-$version.tar.bz2"); if ($?) { die "Failed to uncompress: $!\n"; } # Extract print "Extracting from TAR archive...\n"; system("tar -xf $working/firefox-$version.tar -C $working"); if ($?) { die "Failed to extract: $!\n"; } # Bin the old backup if (-e "$install/.firefox.old") { print "Removing previous backup folder...\n"; system("rm -rf $install/.firefox.old"); if ($?) { die "Failed to remove: $!\n"; } } # Move current to old print "Backing up currently installed version (" . $current . ") to " . $install . "/.firefox.old...\n"; system("mv $install/firefox $install/.firefox.old"); if ($?) { die "Failed to move: $!\n"; } # Move new to current print "Moving new version to $install for final installation...\n"; system("mv $working/firefox $install/"); if ($?) { die "Failed to move: $!\n"; } # Hurray! print "Installation of version " . $version . " complete. You should restart firefox whenever it is convenient.\n"; exit();