#!/usr/bin/perl -w
use strict;
use Data::Dumper;
# wherever you start, you can't go any further left.
my @spectrum = qw ( cc pd sa samplingplus sampling nd fc );
# once you add a restrictor, you cannot remove it.
my @restrictors = qw ( nc by );
my %valid = map {$_, 1} (@spectrum, @restrictors);
#######################################################
my @licenses;
unless(scalar(@ARGV)>1)
{
my $help =<<'HELP';
Copyright 2005 Greg London
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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
This script takes two or more Creative Commons licenses
and will tell you if they are compatible or not.
If the licenses are compatible, this script will print
out the license that results from combining them.
For example, to test out CC-NC-SA combined with CC-PD,
%> cc.pl cc-nc-sa cc-by
%> The licenses combine to 'cc-sa-nc-by'
Error: expected at least two licenses on command line.
http://www.greglondon.com
HELP
;
print $help;
exit;
}
# go through @ARGV and modify it to fit valid input
my %translation_table =
(
cc=>'cc',
pd=>'pd',
sa=>'sa',
samplingplus=>'samplingplus',
sampling=>'sampling',
nd=>'nd',
fc=>'fc',
creativecommons=>'cc',
publicdomain=>'pd',
sharealike=>'sa',
noderivatives=>'nd',
noderivs=>'nd',
founders=>'fc',
founderscopyright=>'fc',
nc=>'nc',
by=>'by',
noncommercial=>'nc',
attribution=>'by',
);
foreach my $lici (@ARGV)
{
my @elements;
my @arguments = sort(split(/\-/, $lici));
foreach my $arg (@arguments)
{
$arg = lc($arg); # warn "arg is $arg";
my $tla = $translation_table{$arg};
unless(exists($valid{$tla}))
{ die "dont know $arg ($tla)"; }
push(@elements, $tla);
}
push(@licenses,
{
elements => \@elements,
string => $lici,
} );
}
# print Dumper \@licenses;
#######################################################
# create a spectrum lookup table
my %spectrum_lookup;
for (my $i=0; $i<scalar(@spectrum); $i++)
{
my $key = $spectrum[$i];
$spectrum_lookup{$key} = $i;
}
#######################################################
# go through each license and locate it on spectrum
foreach my $licinfo (@licenses)
{
$licinfo->{location}=0;
my $location;
my @restrictions;
$licinfo->{restrictors}=\@restrictions;
foreach my $ele (@{$licinfo->{elements}})
{
next if ($ele eq 'cc');
if(exists($spectrum_lookup{$ele}))
{
if(defined($location))
{
my $lic = $licinfo->{string};
die "Error: $ele in $lic";
}
$location = $spectrum_lookup{$ele};
$licinfo->{location}=$location;
# warn "ele '$ele' at location '$location'";
}
else
{
push(@restrictions, $ele);
}
}
}
#######################################################
# go through each license and see if it is sharealike
foreach my $licinfo1 (@licenses)
{
$licinfo1->{sharealike}=0;
foreach my $ele (@{$licinfo1->{elements}})
{
$licinfo1->{sharealike}=1 if($ele eq 'sa');
}
}
#######################################################
# go through all the licenses. if there is a share alike
# license, make sure all the other licenses are to the left
# of the sharealike license. If there is another sharealike,
# make sure it has the same restrictors.
# if either of these rules are broken, then licenses
# cannot be combined.
for(my $i=0; $i<scalar(@licenses); $i++)
{
my $lic_i = $licenses[$i];
my $sa_i = $lic_i->{sharealike};
my $str_i = $lic_i->{string};
if($sa_i)
{
for(my $j=$i+1; $j<scalar(@licenses); $j++)
{
next if ($j == $i);
my $lic_j = $licenses[$j];
my $sa_j = $lic_j->{sharealike};
my $str_j = $lic_j->{string};
if($sa_j)
{
# if two sharealike licenses,
# then restrictors must be the same
my @res_i = sort(@{$lic_i->{restrictors}});
my @res_j = sort(@{$lic_j->{restrictors}});
warn "comparing $str_i and $str_j";
unless(scalar(@res_i) == scalar(@res_j))
{
die "Error: conflicting ShareAlike licenses, $str_i and $str_j";
}
for(my $k=0; $k<scalar(@res_i); $k++)
{
my $i_restrictor = $res_i[$k];
my $j_restrictor = $res_j[$k];
unless($i_restrictor eq $j_restrictor)
{
die "Error: conflicting ShareAlike licenses, $str_i and $str_j";
}
}
}
else
{
# j is not sharealike, make sure it is to the left of i
my $spectrum_i = $lic_i->{location};
my $spectrum_j = $lic_j->{location};
unless($spectrum_j < $spectrum_i)
{
die "Error: ShareAlike license '$str_i' cannot combine with more restrictive license '$str_j'";
}
}
}
}
}
#######################################################
# go through all the licenses and find most restrictive position on spectrum
# this will be the spectrum location of final license
my $location = 0;
foreach my $licinfo (@licenses)
{
my $thisloc = $licinfo->{location};
if($thisloc > $location)
{
$location = $thisloc;
}
}
my @final_license = ( 'cc', $spectrum[$location] );
#######################################################
# go through all the licenses and get all the restrictors
# all restrictors in original license must carry over to final license.
my %final_restrictors;
foreach my $licinfo (@licenses)
{
my @these_restrictors = @{$licinfo->{restrictors}};
foreach my $this_restrictor (@these_restrictors)
{
$final_restrictors{$this_restrictor}=1;
}
}
push(@final_license, keys(%final_restrictors));
#######################################################
#print Dumper \@licenses;
#print Dumper \@final_license;
# now print out the final license
my $final_lic_str = join('-', @final_license);
print "The licenses combine to '$final_lic_str'\n";