File firefox-mkextpkg of Package firefox-pkggen

#!/usr/bin/perl -w

use Cwd;
use strict;

my $apiurl = "https://services.addons.mozilla.org/en-US/firefox/api/1.3/";

# http://www.spdx.org/licenses/
my %licenses = (
	"Mozilla Public License, version 1.1" => "MPL-1.1",
	"GNU General Public License, version 2.0" => "GPL-2.0",
);

use IO::Socket::SSL;

# load IO:Socket:SSL before LWP::UserAgent so it uses that instead
# of NET::SSL.
# We prefer IO:Socket:SSL as it does the host name verification for
# us already.
IO::Socket::SSL::set_ctx_defaults( 
	SSL_verifycn_scheme => {
		wildcards_in_cn => 'anywhere',
		wildcards_in_alt => 'anywhere',
		check_cn => 'when_only'
	}, 
	SSL_verify_mode => 1,
	SSL_ca_file => undef,
	SSL_ca_path => "/etc/ssl/certs",
);

use LWP::UserAgent;
use XML::Simple;
use Template;
use Getopt::Long;

use Data::Dumper;

my %options;
Getopt::Long::Configure("no_ignore_case");
GetOptions (
    \%options,
    "update",
    "force",
    "oldversion",
    "check",
    "debug",
) or die "invalid arguments\n";

my $ua = LWP::UserAgent->new();
$ua->timeout(20);

my $newsuffix = '';
my $oldversion;
my $pkgname;
my $specfile;

my $id = shift @ARGV || die "usage: $0 appid\n";
if (!-d $id) {
	die "id must be numeric\n" unless ($id =~ /\d+/);
} else {
	$pkgname = $id;
	$id = undef;
	if ($pkgname eq '.') {
		$pkgname = getcwd;
		$pkgname =~ s,.*/,,;
	}
	die "$pkgname already exists, use --update to update\n" unless ($options{'update'} || $options{'check'});
	$specfile = "$pkgname.spec";
       	if (-d  $pkgname) {
		$specfile = "$pkgname/$specfile";
	}
	die "$!\n" unless open(I, '<', $specfile);
	while(<I>) {
		if (/^Version:\s*(.+)\n/) {
			$oldversion = $1;
		} elsif (/^URL:.*\/(\d+)\n/) {
			$id = $1;
			last;
		}
	}
	close(I);
	die "can't determine id for $pkgname\n" unless $id;
}

my $data;
if (@ARGV) {
	$data = join('', <>);
} else {
	my $req = HTTP::Request->new('GET' => $apiurl."addon/$id");
	my $res = $ua->request($req);
	die $res->status_line."\n" unless $res->is_success;
	$data = $res->content;
}

my $xml = XML::Simple->new();
my $tree = $xml->XMLin($data);

my %variables;
print Dumper($tree) if $options{'debug'};
for my $tag (qw/name version summary description/) {
	next unless exists $tree->{$tag};
	if (!ref $tree->{$tag}) {
		$variables{$tag} = $tree->{$tag}
	} elsif(ref $tree->{$tag} eq 'HASH') {
		$variables{$tag} = $tree->{$tag}->{'content'};
	} else {
		print STDERR "tag $tag not found\n";
	}
}

if ($tree->{'license'} && $tree->{'license'}->{'name'}) {
	my $license = $tree->{'license'}->{'name'};
	$license = $licenses{$license} if exists $licenses{$license};
	$variables{'license'} = $license;
}

print Dumper(\%variables) if $options{'debug'};

if ($options{'check'}) {
	exit 1 unless $oldversion;
	if ($variables{'version'} eq $oldversion) {
		print "$oldversion up to date\n";
		exit 0;
	} else {
		printf "new version %s available\n", $variables{'version'};
		exit 1;
	}
}

unless ($options{'check'}) {
	if ($oldversion && $variables{'version'} eq $oldversion) {
		print "$oldversion is up to date\n";
		exit 0 unless $options{'force'};
	}
}

# upstream summary is too verbose
$variables{'summary'} = sprintf("%s extension for Firefox", $variables{'name'});
unless ($pkgname) {
	$pkgname = lc $variables{'name'};
	$pkgname =~ s/[^a-zA-Z0-9]/_/g;
	$pkgname =~ s/_+/_/g;
	$pkgname =~ s/_+$//g;
	$pkgname = sprintf("firefox-ext-%s", lc $pkgname);
	$specfile = "$pkgname/$pkgname.spec";
}
$variables{'pkgname'} = $pkgname;

sub makearray
{
	my $ref = shift;
	return $ref if ref $ref eq 'ARRAY';
	return [ $ref ];
}

my $source;
my $dlfile;
my $hash;
for my $i (@{makearray($tree->{'install'})}) {
	next unless ($i->{'os'} || 'nomatch') eq 'ALL';
	$source = $i->{'content'};
	$hash = $i->{'hash'} if ($i->{'hash'});
}

if (!$source) {
	print STDERR "no suitable source found\n";
	$source = 'FIXME';
} else {
	my $version = $variables{'version'};
	$dlfile = $source;
	$source =~ s/\?.*//;
	$source =~ s/\Q$version\E/%{version}/;
	$variables{'hash'} = $hash;
}

# https://wiki.mozilla.org/Update:Remora_API_Docs
$variables{'url'} = sprintf("https://addons.mozilla.org/en-US/addon/%d", $id);
$variables{'source'} = $source;

if (-e $specfile) {
	# reuse license if existing
	#!defined $variables{'license'} && 
	if (open(I, '<', $specfile)) {
		while(<I>) {
			if (/^License:\s*(.+)\n/) {
				print "using license $1 from spec file\n";
				$variables{'license'} = $1;
				last;
			}
		}
		close I;
	}
} elsif ($specfile =~ /\//) {
	mkdir($pkgname) || die "mkdir: $!\n";
}

$variables{'license'} ||= 'FIXME';

open(O, '>', "$specfile$newsuffix") or die "open: $!\n";

my $spec = '';
my %tmplcfg;
my $tt = Template->new(\%tmplcfg) || die Template->error(), "\n";
$tt->process(\*DATA, \%variables, \*O) || die $tt->error(), "\n";

close O;


sub get_file($$)
{
	my ($url, $dest) = @_;
	print "downloading $dest\n";
	my $res = $ua->mirror($url, $dest);
	die $res->status_line."\n" unless $res->is_success || $res->code == 304;
}

if ($dlfile) {
	my $dest = $dlfile;
	$dest =~ s/.*\///;
	$dest =~ s/\?.*//;
	$dest = $pkgname."/".$dest if $specfile =~ /\//;
	get_file($dlfile, $dest);
	if (!$hash || $hash !~ /^(sha\d+):(.*)/) {
		print "Warning: can't verify hash!\n";
	} else {
		use Digest::SHA;
		my $sha = Digest::SHA->new($1);
		$sha->addfile($dest);
		my $digest = $sha->hexdigest;
		if ($digest ne $2) {
			print STDERR "ERROR: digest doesn't match! ($digest != $2)\n";
		}
	}
}

printf "%s\n", $variables{'url'};
unless ($options{'update'}) {
	print "\nDon't forget to fix up the License tag!\n";
	print "osc mkpac $pkgname\n";
}
print "cd $pkgname\n" if $specfile =~ /\//;
unless ($options{'update'}) {
	print "vi $pkgname.spec\n";
	print "osc vc -m \"new package version $variables{version}\"\n";
} else {
	print "osc diff\n";
	print "osc vc -m \"update to version $variables{version}\"\n";
}
print "osc addremove\n";
print "osc ci\n";
print "osc metafromspec\n";

__END__
Name:           [% pkgname %]
Version:        [% version %]
Release:        1
License:        [% license %]
Summary:        [% summary %]
Group:          Productivity/Networking/Web/Browsers
URL:            [% url %]
Source0:        [% source %]
[% IF hash -%]
#Hash:          [% hash %]
[% END -%]
BuildRoot:      %{_tmppath}/%{name}-%{version}-buildroot
Requires:       firefox >= %{firefox_version}
BuildRequires:  firefox-devel
BuildRequires:  unzip
BuildRequires:  fdupes
Buildarch:      noarch

%description
[% description %]

%prep
%setup -qTcn %{name}-%{version}

%build

%install
%firefox_ext_install %SOURCE0
%fdupes "%{buildroot}%{firefox_extdir}"

%clean
rm -rf %{buildroot}

%files
%defattr(0644,root,root,0755)
%{firefox_extdir}

%changelog
openSUSE Build Service is sponsored by