# 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;

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 (<IN>) {
    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 = <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;
$_ = <IN>;
close(IN);

my $wrong_directory_detected = 0;

if (m,\<fill in (http/)?ftp site\>, or m/\<Must follow here\>/) {
    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 (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/
    || $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{\# 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 ($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,) {
        if (open(DEP, '<', 'fields/depends')) {
            my @depends = split (/\s*,\s*/, scalar <DEP>);
            close DEP;
            if (grep { /^libssl[0-9.]+(\s|\z)/ && !/\|/ } @depends) {
                tag 'possible-gpl-code-linked-with-openssl';
            }
        }
    }
}

} # </run>

# -----------------------------------

# 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 = <I>);
	close(I);
    }

    $f = "fields/pre-depends";
    if (-f $f) {
	open(I, '<', $f) or die "cannot open pre-depends file $f: $!";
	chop($predeps = <I>);
	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
