--- Begin Message ---
Package: lintian
Version: 1.23.32
Priority: wishlist
Tags: patch
Following the recent discussion at debian-devel related to .desktop files
I've noticed that we lack some lintian checks for common issues in desktop
files (mispelled categories, wrong key value pairs, etc...)
Even though we don't have a policy for Desktop files, since most Desktop
environments (KDE, GNOME) are using them it might be sane to have a check for
desktop files just like we have for menu files.
I've written a first attempt at such check, heavily based on the current
menu-format method and reusing some of its code. It is capable of detecting
wrong Categories and invalid Type values and should be useful to detect
.desktop files which need to be fixed.
Notice that it could be improved to do much more tests, I'm not sure I'll
handle them myself but maybe this will help others scratch their itch..
Please consider its inclusion into the lintian lab.
Thanks,
Javier
# desktop format -- lintian check script -*- perl -*-
# Copyright (C) 2007 by Javier Fernandez-Sanguino
# based on the menu lintian check written by
# Copyright (C) 1998 by Joey Hess
#
# 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
# the 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.
#
# 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 http://www.gnu.org/copyleft/gpl.html, or write to the Free
# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
# MA 02110-1301, USA.
#
#
# This lintian check aims at implement some standard check for Desktop files
# which are currently not covered by Debian Policy (only menu entries are)
#
# This is a barebones module, it should be extended to check for some more things
# from FreeDesktop's standard:
#
# - Look for Deprecated Items
# - Check field codes in the Exec key
# - Check fields with locales
# - Check Group headers
# - ....
#
package Lintian::desktop_format;
use strict;
use Tags;
use Util;
use File::Basename;
# Authorative source of desktop keys:
# http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.0.html
#
# This is a list of all keys that should be in every desktop entry.
my @req_keys=qw(Type Name);
# This is a list of all known keys.
my @known_keys=qw(
Type
Name
Version
GenericName
NoDisplay
Comment
Icon
Hidden
OnlyShowIn
NotShowIn
TryExec
Exec
Path
Terminal
MimeType
Categories
StartupNotify
StartupWMClass
URL
);
my @deprecated_keys=qw(
Encoding
MiniIcon
TerminalOptions
Protocols
Extensions
BinaryPattern
MapNotify
SwallowTitle
SwallowExec
SortOrder
FilePattern
);
# Authorative source of desktop categories
# http://standards.freedesktop.org/menu-spec/menu-spec-1.0.html#category-registry
# This is a list of all valid section on the root menu.
my @root_categories=qw(AudioVideo Audio Video Development Education Game Graphics Network Office Settings System Utility);
# This is a list of all additional categories
my @categories=qw(
Building
Debugger
IDE
GUIDesigner
Profiling
RevisionControl
Translation
Calendar
ContactManagement
Database
Dictionary
Chart
Email
Finance
FlowChart
PDA
ProjectManagement
Presentation
Spreadsheet
WordProcessor
2DGraphics
VectorGraphics
RasterGraphics
3DGraphics
Scanning
OCR
Photography
Publishing
Viewer
TextTools
DesktopSettings
HardwareSettings
Printing
PackageManager
Dialup
InstantMessaging
Chat
IRCClient
FileTransfer
HamRadio
News
P2P
RemoteAccess
Telephony
TelephonyTools
VideoConference
WebBrowser
WebDevelopment
Midi
Mixer
Sequencer
Tuner
TV
AudioVideoEditing
Player
Recorder
DiscBurning
ActionGame
AdventureGame
ArcadeGame
BoardGame
BlocksGame
CardGame
KidsGame
LogicGame
RolePlaying
Simulation
SportsGame
StrategyGame
Art
Construction
Music
Languages
Science
ArtificialIntelligence
Astronomy
Biology
Chemistry
ComputerScience
DataVisualization
Economy
Electricity
Geography
Geology
Geoscience
History
ImageProcessing
Literature
Math
NumericalAnalysis
MedicalSoftware
Physics
Robotics
Sports
ParallelComputing
Amusement
Archiving
Compression
Electronics
Emulator
Engineering
FileTools
FileManager
TerminalEmulator
Filesystem
Monitor
Security
Accessibility
Calculator
Clock
TextEditor
Documentation
Core
KDE
GNOME
GTK
Qt
Motif
Java
ConsoleOnly
);
# Path in which to search for binaries referenced in menu entries.
my @path = qw(/usr/local/bin/ /usr/bin/ /bin/ /usr/X11R6/bin/ /usr/games/);
my %known_keys_hash;
my %deprecated_keys_hash;
my %root_categories_hash;
my %categories_hash;
my %all_files = ();
my %all_links = ();
# -----------------------------------
sub run {
my $pkg = shift;
my $type = shift;
# Things worth hashing.
foreach my $tag (@known_keys) {
$known_keys_hash{$tag}=1;
}
foreach my $tag (@deprecated_keys) {
$deprecated_keys_hash{$tag}=1;
}
foreach my $section (@root_categories) {
$root_categories_hash{$section}=1;
}
foreach my $section (@categories) {
$categories_hash{$section}=1;
}
# read package contents
open(IN,"index") or fail("cannot open index file index: $!");
while (<IN>) {
chomp;
my ($perm,$owner,$size,$date,$time,$file) = split(' ', $_, 6);
$file =~ s,^(\./),,;
add_file_link_info ($file);
$file =~ s/ link to .*//;
$file =~ s/ -> .*//;
my $operm = perm2oct($perm);
if ($perm =~ m,^-,o) { # file checks
# desktop file?
if ($file =~ m/\.desktop$/o) { # correct permissions?
if ($perm =~ m,x,o) {
tag "executable-desktop-file", sprintf("$file %04o",$operm);
}
# TODO: This should provide the
VerifyFile($file, $file);
}
}
}
close IN;
}
# -----------------------------------
# Pass this a line of a menu file, it sanitizes it and
# verifies that it is correct.
sub VerifyFile {
my ( $desktopfile, $fullname ) = @_;
my %vals;
open (DESKTOP, "unpacked/$fullname") or fail("cannot open desktop file $fullname: $!");
my $linecount = 0;
while ( my $line = <DESKTOP> ) {
chomp $line;
$linecount++;
next if ( $line =~ m/^\s*\#/ or $line = ~ m/^\s*$/);
# Tag = Value
# TODO: We do not check for properly formatted localised values for keys
# but might be worth checking if they are properly formatted (not their value)
if ( $line =~ /^(.*?)\s*=\s*(.*?)$/ ) {
my $tag = $1;
my $value = $2;
if (exists $vals{$tag}) {
tag "duplicated-key-in-desktop-entry", "$fullname $1:$linecount";
}
$vals{$tag} = $value;
}
}
close DESKTOP;
# Now validate the data in the desktop file.
# Test for important keys.
foreach my $tag (@req_keys) {
unless ( exists($vals{$tag}) && defined($vals{$tag}) ) {
tag "desktop-entry-missing-required-key", "$tag $fullname:$linecount";
}
}
# Make sure all keys are known and no deprecated keys are being used
foreach my $tag (keys %vals) {
if ( $deprecated_keys_hash{$tag} ) {
tag "desktop-entry-contains-deprecated-key", "$tag $fullname:$linecount";
} elsif (! $known_keys_hash{$tag} && $tag !~ /^X-/ ) {
# TODO: Will produce false positives for keys reserved by KDE
# which do not use X-KDE (see Standard)
tag "desktop-entry-contains-unknown-key", "$tag $fullname:$linecount";
}
}
# TODO: Check for deprecated keys: Encoding, MiniIcon, TerminalOptions, Protocols,
# Extensions, BinaryPattern, MapNotify, SwallowTitle, SwallowExec, SortOrder
# FilePattern,
if (exists($vals{'Exec'})) {
VerifyExec( $fullname, $linecount, $vals{'Exec'});
}
if (exists($vals{'Icon'})) {
VerifyIcon( $fullname, $linecount, $vals{'Icon'}, 32);
}
# Check the category tag
if (exists($vals{'Categories'})) {
# Is the main category there?
my $ccats = 0;
foreach my $cat (keys %root_categories_hash) {
$ccats++ if $vals{'Categories'} =~ /$cat;?/;
}
if ( $ccats == 0 ) {
tag "desktop-entry-lacks-main-category", "$fullname:$linecount";
} elsif ( $ccats > 1 ) {
tag "desktop-entry-multiple-main-category", "$fullname:$linecount";
}
foreach my $cat (split(';',$vals{'Categories'})) {
if (not $categories_hash{$cat}) {
tag "desktop-entry-invalid-category", "$cat $fullname:$linecount";
}
}
}
# TODO:
# - Check if the values correspond to the allowed type for a given key (boolean,
# integer...)
}
sub VerifyCmd {
# Verify if commands are installed with the package.
# TODO: Should check quoting and the check special field codes in Exec
my ( $fullname, $linecount, $exec) = @_;
# Read the file index:
my %file_index;
open(FILE_INDEX,"index") or fail("cannot open index file index: $!");
while(<FILE_INDEX>) {
$file_index{(split /\s+/, $_)[5]} = 1;
}
close FILE_INDEX;
# This routine handles su wrappers. The option parsing here is ugly and dead-simple,
# but it's hopefully good enough for what will show up in desktop files.
# su-to-root and sux require -c options, kdesu optionally allows one, and
# gksu has the command at the end of its arguments.
my @com = split(' ',$exec);
my $cmd;
if ($com[0] eq "/usr/sbin/su-to-root") {
tag "su-to-root-with-usr-sbin", "$fullname:$linecount";
} elsif ($com[0] =~ m,^(?:/usr/bin/)?(su-to-root|gksu|kdesu|sux)$,) {
my $wrapper = $1;
shift @com;
while (@com) {
unless ($com[0]) {
shift @com;
next;
}
if ($com[0] eq '-c') {
$cmd = $com[1];
last;
} elsif ($com[0] =~ /^-[Dfmupi]|^--(user|description|message)/) {
shift @com;
shift @com;
} elsif ($com[0] =~ /^-/) {
shift @com;
} else {
last;
}
}
if (!$cmd && $wrapper =~ /^(gk|kde)su$/) {
$cmd = $com[0];
} elsif (!$cmd) {
tag "su-wrapper-without--c", "$fullname:$linecount $wrapper";
}
} else {
$cmd = $com[0];
}
tag "desktop-command-not-in-package", "$fullname:$linecount $cmd"
if ($cmd
&& !($file_index{".$cmd"} || grep {$file_index{".".$_.$cmd}} @path));
}
# TODO: Shouldn't this allow PNG files too?
sub VerifyIcon {
my ( $fullname, $linecount, $icon, $size) = @_;
local *IN;
if ($icon eq 'none') {
tag "desktop-entry-uses-icon-none", "$fullname:$linecount";
return;
}
if (not ($icon =~ m/\.xpm$/i)) {
tag "desktop-icon-not-in-xpm-format", "$icon";
return;
}
# Try the explicit location, and if that fails, try the standard path.
my $iconfile = "unpacked/$icon";
if (! -f $iconfile) {
$iconfile = "unpacked/usr/share/pixmaps/$icon";
}
if (! open IN, $iconfile) {
tag "desktop-icon-missing", "$icon";
return;
}
my $parse = "XPM header";
my $line;
do { defined ($line = <IN>) or goto parse_error; }
until ($line =~ /\/\*\s*XPM\s*\*\//);
$parse = "size line";
do { defined ($line = <IN>) or goto parse_error; }
until ($line =~ /"\s*([0-9]+)\s*([0-9]+)\s*([0-9]+)\s*([0-9]+)\s*"/);
my $width = $1 + 0;
my $height = $2 + 0;
my $numcolours = $3 + 0;
my $cpp = $4 + 0;
if ($width > $size || $height > $size) {
tag "desktop-icon-too-big", "$icon: ${width}x${height} > ${size}x${size}";
}
close IN or die;
return;
parse_error:
close IN or die;
tag "desktop-icon-cannot-be-parsed", "$icon: looking for $parse";
return;
}
1;
# -----------------------------------
# Add file and link to %all_files and %all_links. Note that both files and
# links have to include a leading /.
sub add_file_link_info {
my $file = shift;
my $link = undef;
$file = "/" . $file if (not $file =~ m%^/%); # make file absolute
$file =~ s%/+%/%g; # remove duplicated `/'
($file, $link) = split(/ -> /, $file);
$all_files{$file} = 1;
if (defined $link) {
if (not $link =~ m,^/,) { # not absolute link
$link = "/" . $link; # make sure link starts with '/'
$link =~ s,/+\./+,/,g; # remove all /./ parts
my $dcount = 1;
while ($link =~ s,^/+\.\./+,/,) { #\ count & remove
$dcount++; #/ any leading /../ parts
}
my $f = $file;
while ($dcount--) { #\ remove last $dcount
$f =~ s,/[^/]*$,,; #/ path components from $file
}
$link = $f . $link; # now we should have absolute link
}
$all_links{$file} = $link unless ($link eq $file);
}
}
1;
# vim: syntax=perl ts=8 sw=4
Check-Script: desktop-format
Author: Javier Fernandez-Sanguino Pen~a <jfs@debian.rog>
Abbrev: dkf
Standards-Version: 3.6.1
Type: binary
Unpack-Level: 1
Info: This script validates the format of desktop files.
Tag: unparsable-desktop-entry
Type: error
Info: An entry of the desktop file cannot be parsed as a series of key=value
pairs.
Tag: duplicated-key-in-desktop-entry
Type: warning
Info: The desktop entry contains two instances of the same key. This is just a
waste of space, as only one will be used.
Tag: desktop-entry-missing-required-key
Type: error
Info: The desktop entry has a line that is missing a required key.
See: http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.0.html#recognized-keys
Tag: desktop-entry-contains-unknown-key
Type: warning
Info: The desktop entry has a line that has a key in it that is not one
of the standard keys defined in the FreeDesktop specification and this
key does not conform to the preferred method for introducing changes
(via the 'X-' prefix). It's more likely the key's name is misspelled.
See: http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.0.html#recognized-keys
Tag: desktop-entry-contains-deprecated-key
Type: warning
Info: The desktop entry has a line that has a key in it that has been
deprecated in the FreeDesktop specification.
See: http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.0.html#deprecated-items
Tag: desktop-icon-not-in-xpm-format
Type: error
Info: Icons in the Debian desktop system should be in XPM format.
Ref: desktop manual 3.7
Tag: desktop-icon-missing
Type: warning
Info: This icon file couldn't be found. If the path to the icon in the
desktop file is an absolute path, make sure that icon exists at that path in
the package. If the path is relative or a simple filename, make sure the
icon is installed in <tt>/usr/share/pixmaps</tt>, the default location.
.
If the icon is in a package this package depends on, add a lintian
override for this warning. lintian cannot check icons in other packages.
Ref: desktop manual 3.7
Tag: desktop-icon-too-big
Type: error
Info: Icons in the Debian desktop system should be at most 32x32 pixels
(icon16x16 icons should of course be at most 16x16 pixels)
Ref: desktop manual 3.7
Tag: desktop-icon-cannot-be-parsed
Type: warning
Info: The icon file could not be parsed. Perhaps this means a bad XPM file,
or perhaps it means the lintian parsing needs to be improved. If the
window managers and standard tools accept the file then probably it's the
latter; please file a bug on lintian then.
Tag: desktop-command-not-in-package
Type: warning
Info: The desktop entry specifies a command which is not available in the package.
In most cases this is a typo or after you moved a binary around, but forgot
to update the desktop file.
--- End Message ---
--- Begin Message ---
Source: lintian
Source-Version: 1.23.33
We believe that the bug you reported is fixed in the latest version of
lintian, which is due to be installed in the Debian FTP archive:
lintian_1.23.33.dsc
to pool/main/l/lintian/lintian_1.23.33.dsc
lintian_1.23.33.tar.gz
to pool/main/l/lintian/lintian_1.23.33.tar.gz
lintian_1.23.33_all.deb
to pool/main/l/lintian/lintian_1.23.33_all.deb
A summary of the changes between this version and the previous one is
attached.
Thank you for reporting the bug, which will now be closed. If you
have further comments please address them to 433411@bugs.debian.org,
and the maintainer will reopen the bug report if appropriate.
Debian distribution maintenance software
pp.
Russ Allbery <rra@debian.org> (supplier of updated lintian package)
(This message was generated automatically at their request; if you
believe that there is a problem with it please contact the archive
administrators by mailing ftpmaster@debian.org)
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Format: 1.7
Date: Sun, 05 Aug 2007 11:59:15 -0700
Source: lintian
Binary: lintian
Architecture: source all
Version: 1.23.33
Distribution: unstable
Urgency: low
Maintainer: Debian Lintian Maintainers <lintian-maint@debian.org>
Changed-By: Russ Allbery <rra@debian.org>
Description:
lintian - Debian package checker
Closes: 277441 431259 431395 431545 431629 431844 432268 432959 433411 433516 434744 434978 436058
Changes:
lintian (1.23.33) unstable; urgency=low
.
The "menu and cruft reorganization" release.
.
* checks/common_data.pm:
+ [CW] Add automaken as a known virtual package.
+ [CW] Update architectures to dpkg 1.14.5, adding solaris-* and lpia.
+ [RA] Add %known_obsolete_emacs.
* checks/cruft{.desc,}:
+ [RA] Check for .git directories in source packages. Thanks, Julien
Cristau. (Closes: #433516)
+ [RA] Substantially rewrite how all cruft checking against source
packages is done, incorporating debdiff in the process. There are
now two tags for most source package cruft problems: one for files
introduced in the Debian diff or in a native package, and one for
files present upstream. The former is at warning severity and the
latter is at info severity, since it's usually not worth repackaging
the upstream source to remove such files. In the process,
standardize the names of all of the tags and pull the regexes out
into data instead of code for easier maintenance. (Closes: #434744)
* checks/debdiff{.desc}:
+ [RA] Removed, incorporated into checks/cruft.
* checks/debian-readme:
+ [RA] Replace all uses of tag_error and tag_warn with just tag.
* checks/fields{.desc,}:
+ [RA] Tag packages listing emacs21 as the preferred Emacs flavor in a
dependency. Thanks, Tatsuya Kinoshita. (Closes: #434978)
+ [RA] Start tagging unversioned dependencies on coreutils again since
the transition from fileutils is long-since finished. Thanks,
Guillem Jover. (Closes: #436058)
* checks/files{.desc,}:
+ [RA] Check for .git directories in binary packages.
* checks/menu-format{.desc,}:
+ [RA] Switch to the new menu hierarchy, which will be in the next
release of Policy. Add specific checks for the major renamings to
hopefully cut down on the confusion and provide some specific
guidance. Remove the code that allowed for applications to create
new sub-menus, since the current menu documentation says not to do
that. (Closes: #431844)
+ [RA] Add checks of desktop files. The checks so far are basic, but
do include key and category verification. Based heavily on work by
Javier Fernández-Sanguino Peña. (Closes: #277441, #433411)
* checks/scripts{.desc,}:
+ [RA] If rm output is redirected to /dev/null, don't think that rm is
removing /dev/null. Thanks, Robert Luberda. (Closes: #431259)
+ [RA] xjed also provides jed-script. Thanks, Jörg Sommer.
(Closes: #431629)
+ [RA] Don't complain about ruby libraries in /usr/lib/ruby that have
shebang lines. This is a common means for embedding unit tests in
Ruby libraries. Thanks, Paul van Tilburg. (Closes: #431545)
+ [RA] Don't push depending directly on update-inetd in the long
description of maintainer-script-needs-depends-on-update-inetd.
Most packages should depend on inet-superserver. Leave the check
the same for the time being, however.
+ [RA] Replace all uses of tag_error and tag_warn with just tag.
* checks/shared-libs:
+ [RA] Exclude udebs from dependency checking in the shlibs files
since binary packages may legitimately declare udeb dependencies on
other packages. Thanks, Loïc Minier. (Closes: #431395)
* checks/spelling:
+ [RA] Replace all uses of tag_error and tag_warn with just tag.
* checks/version-substvars:
+ [RA] Don't skip other checks for binNMUability when warning about
the deprecated ${Source-Version} substvar. Thanks, Lior Kaplan.
(Closes: #432959)
.
* frontend/lintian:
+ [RA] Add \w+-backports to the known distribution list. Thanks,
Vincent Danjean. (Closes: #432268)
.
* lib/Tags.pm:
+ [RA] Replace any newlines in the extra information to the tag
function with \n.
.
* man/lintian.1:
+ [RA] Remove the mention of the debdiff check script.
Files:
8e2cba86358bff5966ca25742e17c624 803 devel optional lintian_1.23.33.dsc
5b162f95452ff5f2b7101584a70f682f 345211 devel optional lintian_1.23.33.tar.gz
303ef4f6699670f5a1208359ad6cebc9 292624 devel optional lintian_1.23.33_all.deb
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)
iD8DBQFGtiKM+YXjQAr8dHYRAmDBAJ9qWZiVIIh/y1Tq3Vnb47hwrTMRwwCfWcVx
7mAbjW1OHk1PIqZG5giSqUw=
=J3wO
-----END PGP SIGNATURE-----
--- End Message ---