<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">#!/usr/local/bin/perl -w

use strict; use warnings;
use Data::Dumper;
use Carp;

#======================================================
# need to convert CC licenses to a list of granted rights.
# see data section at end of file in depth description.
#======================================================
# A) the right to NOT =A=attribute the author
# 
# R) the right to add license =R=estrictions to derivatives
# 
# the right to copy/distribute the =O=riginal work:
# 
# O1) commercially (excluding advertising)
# O2) commercially as advertising
# O3) noncommercially
# or no rights granted
# 
# the right to copy/distribute =D=erivative works:
#
# D1) commercially (excluding advertising)
# D2) commercially as advertising
# D3) noncommercially
# or no rights granted
#======================================================

# note that the keys (i.e. BY-NC-SA) are in alphabetical order

my @AllPossibleLetters = qw (A R O1 O2 O3 D1 D2 D3);

my %ConversionTable =
(
	'PD'		=&gt; [qw (A R O1 O2 O3 D1 D2 D3)],
	'BY'		=&gt; [qw (  R O1 O2 O3 D1 D2 D3)],
	'SA'		=&gt; [qw (A   O1 O2 O3 D1 D2 D3)], 
	'BY-SA'		=&gt; [qw (    O1 O2 O3 D1 D2 D3)],
	'NC'		=&gt; [qw (A R       O3       D3)],
	'NC-SA'		=&gt; [qw (A         O3       D3)],
	'BY-NC'		=&gt; [qw (  R       O3       D3)],
	'BY-NC-SA'	=&gt; [qw (          O3       D3)],
	'Sampling+'	=&gt; [qw (A R       O3 D1    D3)], 
	'NC-Sampling+'	=&gt; [qw (A R       O3       D3)],
	'Sampling'	=&gt; [qw (A R          D1    D3)],
	'ND'		=&gt; [qw (A R O1 O2 O3         )], 
	'BY-ND'		=&gt; [qw (  R O1 O2 O3         )], 
);

# print Dumper \%licenses;

########################################################################
# must be at least two licenses on command line. otherwise print help
########################################################################
unless(scalar(@ARGV)&gt;1) {
print&lt;&lt;'HELP';
########################################################################
This script takes in two or more CreativeCommons licenses
and determines what the resulting license would be if they
can be combined. This might be useful for taking two different
works licensed under two different CC licenses and figuring
out if you can combine the two in some useful way.

To run the script, pass in the CC licenses that you want to combine
on the command line when you run the script.

cc.pl BY-NC ND

A list of currently supported licenses is given here:
HELP
;

foreach my $key (keys(%ConversionTable))
	{
	print "\t$key\n";
	}

print&lt;&lt;'HELP';

Copyright 2005 Greg London, All Rights Reserved

This module is free software. It may be used, redistributed
and/or modified under the terms of the Perl Artistic License
  (see http://www.perl.com/perl/misc/Artistic.html)

http://www.GregLondon.com
########################################################################
HELP
;
exit;
}

print "Copyright 2005 Greg London, All Rights Reserved\n";
print "http://www.GregLondon.com\n";

########################################################################
# may want to add cleanup to the inputs before processing.
########################################################################

my %translation_table = 
(
        cc=&gt;'cc',
        pd=&gt;'pd',
        sa=&gt;'sa',
        samplingplus=&gt;'samplingplus',
        sampling=&gt;'sampling',
        nd=&gt;'nd',

        creativecommons=&gt;'cc',
        publicdomain=&gt;'pd',
        sharealike=&gt;'sa',
        'sampling+'=&gt;'samplingplus',
        noderivatives=&gt;'nd',
        noderivs=&gt;'nd',

        nc=&gt;'nc',
        by=&gt;'by',

        noncommercial=&gt;'nc',
        attribution=&gt;'by',
);

my @ProcessedCommandLineArguments;

foreach my $raw_license (@ARGV)
	{
	my $lowercase = lc($raw_license);
	my @elements = split(/\-/, $lowercase);

	my @translated_license;
	foreach my $element (@elements)
		{
		unless(exists($translation_table{$element}))
			{
			die "Error: unknown element '$element' in license '$raw_license'";
			}
		my $translated_element = $translation_table{$element};
		push(@translated_license, $translated_element);
		}
	my @sorted_license = sort(@translated_license);
	my $sorted_string = join("-", @sorted_license);
	my $uppercase = uc($sorted_string);
	push(@ProcessedCommandLineArguments, $uppercase);
	}

########################################################################
# go through all the input licenses and convert them to LUT letters.
########################################################################
my @input_licenses;

foreach my $license (@ProcessedCommandLineArguments)
	{
	unless(exists($ConversionTable{$license}))
		{
		die "Error: don't know nothing about $license";
		}

	my @letter_columns = @{$ConversionTable{$license}};
	my %hash = map{$_,1} @letter_columns;
	push(@input_licenses, \%hash);
	}

# print Dumper \@input_licenses;

########################################################################
# now go through all the licenses and see if they have any letters in common
########################################################################
my %resulting_license;

LETTER: foreach my $letter (@AllPossibleLetters)
	{
	#warn "testing letter '$letter'";
	LICENSE: foreach my $lic_in (@input_licenses)
		{
		#print "checking in "; print Dumper $lic_in;
		unless(exists($lic_in-&gt;{$letter}))
			{
			next LETTER;
			}
		}
	$resulting_license{$letter}=1;
	}

# print Dumper \%resulting_license;

########################################################################
# now go through the conversion table and find license that fits the
# one we just generated.
########################################################################


my %ReversibleTable;

while (my($ccname, $arr_ref) = each(%ConversionTable))
	{
	my @array = sort(@$arr_ref);
	my $arrstr = join("", @array);
	$ReversibleTable{$arrstr}=$ccname;
	}

my @result_arr = sort(keys(%resulting_license));
my $resulting_key = join("",@result_arr);

my $resulting_name = $ReversibleTable{$resulting_key};

# print "resulting_name is '$resulting_name'\n";

########################################################################
# now check for ShareAlike restrictions.
# if any license is share alike, all other licenses must be teh same.
########################################################################

# first generate a list of all the granted rights and how many times granted
my %master_list_of_all_granted_rights;

foreach my $hash_ref (@input_licenses)
	{
	foreach my $letter (keys(%$hash_ref))
		{
		$master_list_of_all_granted_rights{$letter}++;
		}
	}

# now look to see if "R" was a right granted by any license.
# if it wasnt, then someone had a sharealike license, and
# counts on all other rights should all be equal
unless(exists($master_list_of_all_granted_rights{'R'}))
	{
	my $number_of_licenses = scalar(@input_licenses);

	RIGHT: foreach my $right (keys(%master_list_of_all_granted_rights))
		{
		next RIGHT if(($right eq 'R') or ($right eq 'A'));
		my $granted_count = $master_list_of_all_granted_rights{$right};
		unless($granted_count ==$number_of_licenses)
			{
			die "Error: ShareAlike license prohibits this combination";
			}
		}
	}


print "The license of the combined works would be is '$resulting_name'\n";



__DATA__ 

This script is meant to be used to determine
if two or more CreativeCommons licenses can be combined,
and if they can be combined, what the resulting
license for teh work would be.

How to do it:

Some CC two-letter-acronyms grant
rights and some restrict rights,
so you can't just come up with a
simple rule without knowing what
each acronym means.

PD grants rights to downstream folks.
BY restricts rights from downstream poeple.

The way to programmatically determine
license combinations is to rewrite all
the two-letter-acronyms in terms of what
rights they GRANT to downstream people.

Then, license combination becomes extremely
simple. You simply take whatever rights
are granted by BOTH licenses, and that
goes into your combined license.

(of course, you have to do a check for
sharealike's special conditions, but oh well)

Attribution is a restriction.
It is not the granting of a right,
it is witholding the right for downstream
poeple to copy/distribute/derive the original
work WITHOUT giving the orignal author credit.
But that means you could re-phrase all the
licenses that do/do-not have attribution
into whether or not the allow poeple to use
the work without attributing the original author.

So, here are all the rights that can
be granted by the author under the
various CC licenses:



======================================================
A) the right to NOT =A=attribute the author

R) the right to add license =R=estrictions to derivatives

the right to copy/distribute the =O=riginal work:

O1) commercially (excluding advertising)
O2) commercially as advertising
O3) noncommercially
or no rights granted

the right to copy/distribute =D=erivative works:

D1) commercially (excluding advertising)
D2) commercially as advertising
D3) noncommercially
or no rights granted
======================================================

just to explain the letter choices:
A=Attribution not required
R=Restrictions are further allowed
O=Original work restrictions
D=Derivative work restrictions



so:
CC-PD = A,R,O1,O2,O3,D1,D2,D3,

Note that PD GRANTS all the rights listed above.

Now, compare that to the attribution license:

CC-BY =  ,R,O1,O2,O3,D1,D2,D3,

Attribution grants everythign that PD grants
EXCEPT "A", the right to NOT credit the author.

This approach can be followed with all the licenses:

CC-PD        = A,R,O1,O2,O3,D1,D2,D3,
CC-BY        =   R,O1,O2,O3,D1,D2,D3,
CC-SA        = A, ,O1,O2,O3,D1,D2,D3,
CC-SA-BY     =  , ,O1,O2,O3,D1,D2,D3,
CC-NC        = A,R,  ,  ,O3,  ,  ,D3,
CC-NC-BY     =  ,R,  ,  ,O3,  ,  ,D3,
CC-NC-BY-SA  =  , ,  ,  ,O3,  ,  ,D3,
CC-Sampling+ = A,R,  ,  ,O3,D1,  ,D3,
CC-NC-SAMP+  = A,R,  ,  ,O3,  ,  ,D3,
CC-Sampling  = A,R,  ,  ,  ,D1,  ,D3,
CC-ND        = A,R,O1,O2,O3,  ,  ,  ,
CC-BY-ND     =  ,R,O1,O2,O3,  ,  ,  ,

(I think this table describes all the CC licenses.
 Did I miss any?)

What you then do when you combine licenses
is put the two side by side, carry over
all the letters that exist in both,
and you've got your resulting license.
Combining CC-NC with CC-BY gives:

CC-BY        =   R,O1,O2,O3,D1,D2,D3,
CC-NC        = A,R,  ,  ,O3,  ,  ,D3,
-------------------------------------
equals       =  ,R,  ,  ,O3,  ,  ,D3,

and then you look up the resulting license
in the table to translate it back to a
Creative Commons license. In the above
example, the result matches CC-BY-NC

This makes it simple enough for a perl script
to calculate.

The only other check you need to do is check
the "R" column so see if the right to put the
work under a more Restrictive license has been
granted or not. (i.e. if ShareAlike is present)

If the "R" right is not present, then the
license can only be combine with other licenses
that are exactly the same. No fewer rights,
no more rights.

Hm, with the exception of attribution,
which is may not be present in one license
but could be combined with a work that does
have attribution.

You also need to do some checks at the end
because you can combine some CC licenses
and get a result that does not translate
back to a CC license.

(cc-Sampling) + (CC-NC-Sampling+) = garbage

</pre></body></html>