# copyright-file -- lintian check script -*- perl -*- # Copyright (C) 1998 Christian Schwarz # # 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. package Lintian::copyright_file; use strict; use Dep; use Spelling; use Tags; use Util; use Encode qw(decode); sub run { my $pkg = shift; my $type = shift; my $ppkg = quotemeta($pkg); my $found = 0; my $linked = 0; use lib "$ENV{'LINTIAN_ROOT'}/checks/"; use common_data; # Read package contents... open(IN, '<', "index") or fail("cannot open index file index: $!"); while () { chop; if (m,usr/(share/)?doc/$ppkg/copyright(\.\S+)?(\s+\-\>\s+.*)?$,) { my ($ext,$link) = ($2,$3); $ext = '' if (! defined $ext); #an extension other than .gz doesn't count as copyright file next unless ($ext eq '') or ($ext eq '.gz'); $found = 1; #search for an extension if ($ext eq '.gz') { tag "copyright-file-compressed", ""; last; } #make sure copyright is not a symlink if ($link) { tag "copyright-file-is-symlink", ""; last; } #otherwise, pass if (($ext eq '') and not $link) { # everything is ok. last; } fail("unhandled case: $_"); } elsif (m,usr/share/doc/$ppkg \-\>\s+(\S+),) { my ($link) = ($1); $found = 1; $linked = 1; # check if this symlink references a directory elsewhere if ($link =~ m,^(\.\.)?/,) { tag "usr-share-doc-symlink-points-outside-of-usr-share-doc", "$link"; last; } # link might point to a subdirectory of another /usr/share/doc # directory $link =~ s,/.*,,; # this case is allowed, if this package depends on link # and both packages come from the same source package if (not open (VERSION, '<', "fields/version")) { fail("Can't open fields/version: $!"); } else { chomp(my $our_version = ); close VERSION; # depend on $link pkg? if ((not depends_on($link, $our_version)) && not (exists($known_essential{$link}) && defined($known_essential{$link}))) { # no, it does not. tag "usr-share-doc-symlink-without-dependency", "$link"; last; } } # We can only check if both packages come from the same source # if our source package is currently unpacked in the lab, too! if (-d "source") { # yes, it's unpacked # $link from the same source pkg? if (-l "source/binary/$link") { # yes, everything is ok. } else { # no, it is not. tag "usr-share-doc-symlink-to-foreign-package", "$link"; } } else { # no, source is not available tag "cannot-check-whether-usr-share-doc-symlink-points-to-foreign-package", ""; } # everything is ok. last; } elsif (m,usr/doc/copyright/$ppkg$,) { tag "old-style-copyright-file", ""; $found = 1; last; } } close(IN); if (not $found) { tag "no-copyright-file", ""; } # check that copyright is UTF-8 encoded my $line = file_is_encoded_in_non_utf8("copyright", $type, $pkg); if ($line) { tag "debian-copyright-file-uses-obsolete-national-encoding", "at line $line" } # check contents of copyright file open(IN, '<', "copyright") or fail("cannot open copyright file copyright: $!"); # gulp whole file local $/ = undef; $_ = ; close(IN); # We have to decode into UTF-8 to get the right length for the length # check. For some reason, use open ':utf8' isn't sufficient. If the # file uses a non-UTF-8 encoding, this will mangle it, but it doesn't # matter for the length check. my @lines = split ("\n", decode ('utf-8', $_)); for my $i (0 .. $#lines) { if (length ($lines[$i]) > 80) { tag "debian-copyright-line-too-long", "line " . ($i+1); } } my $wrong_directory_detected = 0; if (m,\, or m/\/) { tag "helper-templates-in-copyright", ""; } if (m,usr/share/common-licenses/(GPL|LGPL|BSD|Artistic)\.gz,) { tag "copyright-refers-to-compressed-license", "$&"; } if (m,usr/share/common-licences,) { tag "copyright-refers-to-incorrect-directory", "$&"; $wrong_directory_detected = 1; } if (m,usr/share/doc/copyright,) { tag "copyright-refers-to-old-directory", ""; $wrong_directory_detected = 1; } if (m,usr/doc/copyright,) { tag "copyright-refers-to-old-directory", ""; $wrong_directory_detected = 1; } # Lame check for old FSF zip code. Try to avoid false positives from other # Cambridge, MA addresses. if (m/(Free\s*Software\s*Foundation.*02139|02111-1307)/s) { tag "old-fsf-address-in-copyright-file", ""; } # Whether the package is covered by the GPL, used later for the libssl check. my $gpl; if (length($_) > 12000 and ((m/\bGNU GENERAL PUBLIC LICENSE\s*TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\b/m and m/\bVersion 2\s/) or (m/\bGNU GENERAL PUBLIC LICENSE\s*Version 3/ and m/\bTERMS AND CONDITIONS\s/))) { tag "copyright-file-contains-full-gpl-license"; $gpl = 1; } if (length($_) > 12000 and m/\bGNU Free Documentation License\s*Version 1\.2/ and m/\b1\. APPLICABILITY AND DEFINITIONS/) { tag "copyright-file-contains-full-gfdl-license"; } if (length($_) > 10000 and m/\bApache License\s+Version 2\.0,/ and m/TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION/) { tag "copyright-file-contains-full-apache-2-license"; } if (m/^This copyright info was automatically extracted from the perl module\./) { tag "helper-templates-in-copyright", ""; } if (m,(under )?(the )?(same )?(terms )?as Perl itself,i && !m,usr/share/common-licenses/,) { tag "copyright-file-lacks-pointer-to-perl-license", ""; } # wtf? if ((m,common-licenses(/\S+),) && (! m,/usr/share/common-licenses/,)) { tag "copyright-does-not-refer-to-common-license-file", "$1"; } # This check is a bit prone to false positives, since some other licenses # mention the GPL. Also exclude any mention of the GPL following what looks # like mail headers, since sometimes e-mail discussions of licensing are # included in the copyright file but aren't referring to the license of the # package. if (m,/usr/share/common-licenses, || m/Zope Public License/ || m/LICENSE AGREEMENT FOR PYTHON 1.6.1/ || m/LaTeX Project Public License/ || m/(^From:.*^To:|^To:.*^From:).*(GNU General Public License|GPL)/ms || m/AFFERO GENERAL PUBLIC LICENSE/ || m/GNU Free Documentation License\s*Version 1\.1/ || m/CeCILL FREE SOFTWARE LICENSE AGREEMENT/ || m/CNRI OPEN SOURCE GPL-COMPATIBLE LICENSE AGREEMENT/ || $wrong_directory_detected) { # False positive or correct reference. Ignore. } elsif (m/GNU Free Documentation License/i or m/\bGFDL\b/) { tag "copyright-should-refer-to-common-license-file-for-gfdl"; } elsif (m/GNU (Lesser|Library) General Public License/i or m/\bLGPL\b/) { tag "copyright-should-refer-to-common-license-file-for-lgpl"; } elsif (m/GNU General Public License/i or m/\bGPL\b/) { tag "copyright-should-refer-to-common-license-file-for-gpl"; $gpl = 1; } if (m,Upstream Author\(s\),) { tag "copyright-lists-upstream-authors-with-dh_make-boilerplate"; } if (m,url://example\.com,) { tag "copyright-has-url-from-dh_make-boilerplate"; } if (m{\# Please also look if there are files or directories which have a\n\# different copyright/license attached and list them here\.}) { tag "copyright-contains-dh_make-todo-boilerplate", ""; } if (m{This copyright info was automatically extracted from the perl module\.\nIt may not be accurate, so you better check the module sources\nif you don\'t want to get into legal troubles\.}) { tag "copyright-contains-dh-make-perl-boilerplate", ""; } if ($found && !$linked && !/(Copyright|Copr\.|\302\251)(.*|[\(C\):\s]+)\b\d{4}\b|\bpublic\s+domain\b/i) { tag 'copyright-without-copyright-notice'; } spelling_check('spelling-error-in-copyright', $_); # Now, check for linking against libssl if the package is covered by the GPL. # (This check was requested by ftp-master.) First, see if the package is # under the GPL alone and try to exclude packages with a mix of GPL and LGPL # or Artistic licensing or with an exception or exemption. if ($gpl || m,/usr/share/common-licenses/GPL,) { unless (m,exception|exemption|/usr/share/common-licenses/(?!GPL)\S,) { my @depends; if (open(DEP, '<', 'fields/depends')) { @depends = split (/\s*,\s*/, scalar ); } if (open(DEP, '<', 'fields/pre-depends')) { push @depends, split (/\s*,\s*/, scalar ); } close DEP; if (grep { /^libssl[0-9.]+(\s|\z)/ && !/\|/ } @depends) { tag 'possible-gpl-code-linked-with-openssl'; } } } } # # ----------------------------------- # returns true, if $foo depends on $bar sub depends_on { my ($package, $version) = @_; my ($deps, $predeps) = ("", ""); my $f = "fields/depends"; if (-f $f) { open(I, '<', $f) or die "cannot open depends file $f: $!"; chop($deps = ); close(I); } $f = "fields/pre-depends"; if (-f $f) { open(I, '<', $f) or die "cannot open pre-depends file $f: $!"; chop($predeps = ); close(I); } return 1 if Dep::implies(Dep::parse($deps), Dep::parse($package)); return 1 if Dep::implies(Dep::parse($predeps), Dep::parse($package)); return 0; } 1; # Local Variables: # indent-tabs-mode: t # cperl-indent-level: 4 # End: # vim: syntax=perl ts=8 sw=4