# duck - check for upstream metadata files # Copyright (C) 2016 Simon Kainz # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # he Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # 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. # # On Debian GNU/Linux systems, the complete text of the GNU General # Public License can be found in `/usr/share/common-licenses/GPL-2'. # # You should have received a copy of the GNU General Public License # along with this program. If not, you can find it on the World Wide # Web at https://www.gnu.org/copyleft/gpl.html, or write to the Free # Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, # MA 02110-1301, USA. package DUCK::appstream; use strict; use warnings; use autodie; use Path::Class; use XML::XPath; use XML::XPath::XMLParser; my @xmlfiles; my @elements=('//screenshots/screenshot','//url','//icon[@type="remote"]','//updatecontact'); # mappings for element -> check method my $defaultmethod="URL"; my $mapping= { "updatecontact" => "Email", }; sub proc($;$;$;$;$); sub guess_type($); my %options=( "A" => " -A\t\tskip processing of appstream file"); sub opts() { return keys %options; } sub desc() { my $r; foreach (sort keys %options) { $r.=$options{$_}."\n"; } return $r; } sub run() { my ($sname,$params,$entries_ref)=@_; my %opt=%$params; if (!$opt{A} ) { #get list of all *appstream* files dir('.')->recurse( callback => sub { my $file=shift; if ($file =~ /\.appdata/ ) { push @xmlfiles,$file; } } ); } foreach my $f (@xmlfiles) { foreach my $ex (@elements) { my $xp; undef $@; eval {$xp=XML::XPath->new(filename=>$f);}; if ($@) { next; } my $nodeset; eval {$nodeset = $xp->find($ex);}; if ($@) { next; } if (!$nodeset) {next;} foreach my $node ($nodeset->get_nodelist) { my $parent=$node->getParentNode(); my @pfad; push @pfad,$node->getName(); while ($parent->getName()) { push @pfad,$parent->getName(); $parent=$parent->getParentNode(); } my @childNodes=$node->getChildNodes(); foreach my $cn (@childNodes) { my $s=DUCK->extract_url($cn->string_value); my $method=$defaultmethod; if ($mapping->{$node->getName()}) { $method=$mapping->{$node->getName()};} if ($s && $cn->getName()) { push (@$entries_ref, [$f.": ".join("->",$method,reverse @pfad)."->".$cn->getName(), $method,$s,$s,{filename=>$f, certainty=>"certain", url=>$s, verbose=>$f.": ".join("->",$method,reverse @pfad)."->".$cn->getName(), checkmethod =>$method} ] ); } } } } } return; } 1;