Package: strip-nondeterminism
Version: 0.003-1
Severity: wishlist
Tags: patch
User: reproducible-builds@lists.alioth.debian.org
Usertags: toolchain timestamps
X-Debbugs-Cc: reproducible-builds@lists.alioth.debian.org

Hi,

A patch attached with initial support for overriding timestamps
in PNG files.

Possible limitations:

 * Other tEXt free-form formats; eg. "date:create" and "date:modify"
   are ImageMagick specific, apparently

 * Timestamps in compressed or "international" text chunks (zTXt/iTXt)


Regards,

-- 
      ,''`.
     : :'  :     Chris Lamb
     `. `'`      la...@debian.org / chris-lamb.co.uk
       `-
From 79a50129221d10bccee38c5e4d8cd6c59e69fd02 Mon Sep 17 00:00:00 2001
From: Chris Lamb <la...@debian.org>
Date: Wed, 11 Feb 2015 12:24:49 +0000
Subject: [PATCH] Add initial support for PNG

---
 lib/File/StripNondeterminism.pm              |  6 +++
 lib/File/StripNondeterminism/handlers/png.pm | 81 ++++++++++++++++++++++++++++
 2 files changed, 87 insertions(+)
 create mode 100644 lib/File/StripNondeterminism/handlers/png.pm

diff --git a/lib/File/StripNondeterminism.pm b/lib/File/StripNondeterminism.pm
index 8f4d4b7..8d17640 100644
--- a/lib/File/StripNondeterminism.pm
+++ b/lib/File/StripNondeterminism.pm
@@ -27,6 +27,7 @@ use File::StripNondeterminism::handlers::jar;
 use File::StripNondeterminism::handlers::javadoc;
 use File::StripNondeterminism::handlers::pe;
 use File::StripNondeterminism::handlers::pearregistry;
+use File::StripNondeterminism::handlers::png;
 use File::StripNondeterminism::handlers::javaproperties;
 use File::StripNondeterminism::handlers::zip;
 
@@ -73,6 +74,10 @@ sub get_normalizer_for_file {
 	if (m/\.(exe|dll|cpl|ocx|sys|scr|drv|efi|fon)/ && _get_file_type($_) =~ m/PE32.? executable/) {
 		return \&File::StripNondeterminism::handlers::pe::normalize;
 	}
+	# PNG
+	if (m/\.png$/ && _get_file_type($_) =~ m/PNG image data/) {
+		return \&File::StripNondeterminism::handlers::png::normalize;
+	}
 	# pom.properties, version.properties
 	if (m/(pom|version)\.properties$/ && File::StripNondeterminism::handlers::javaproperties::is_java_properties_file($_)) {
 		return \&File::StripNondeterminism::handlers::javaproperties::normalize;
@@ -92,6 +97,7 @@ sub get_normalizer_by_name {
 	return \&File::StripNondeterminism::handlers::javadoc::normalize if $_ eq 'javadoc';
 	return \&File::StripNondeterminism::handlers::pe::normalize if $_ eq 'pe';
 	return \&File::StripNondeterminism::handlers::pearregistry::normalize if $_ eq 'pearregistry';
+	return \&File::StripNondeterminism::handlers::png::normalize if $_ eq 'png';
 	return \&File::StripNondeterminism::handlers::javaproperties::normalize if $_ eq 'javaproperties';
 	return \&File::StripNondeterminism::handlers::zip::normalize if $_ eq 'zip';
 	return undef;
diff --git a/lib/File/StripNondeterminism/handlers/png.pm b/lib/File/StripNondeterminism/handlers/png.pm
new file mode 100644
index 0000000..2b300b3
--- /dev/null
+++ b/lib/File/StripNondeterminism/handlers/png.pm
@@ -0,0 +1,81 @@
+#
+# Copyright 2015 Chris Lamb <la...@debian.org>
+#
+# This file is part of strip-nondeterminism.
+#
+# strip-nondeterminism 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 3 of the License, or
+# (at your option) any later version.
+#
+# strip-nondeterminism 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 strip-nondeterminism.  If not, see <http://www.gnu.org/licenses/>.
+#
+package File::StripNondeterminism::handlers::png;
+
+use strict;
+use warnings;
+
+use Fcntl qw/:seek/;
+use POSIX qw/strftime/;
+use Digest::CRC qw/crc32/;
+
+sub normalize {
+	my ($filename) = @_;
+
+	my $buffer = "";
+	my $canonical_time = $File::StripNondeterminism::canonical_time // 0;
+
+	open PNG, '+<', $filename
+		|| die "Could not open '$filename' for reading: $!";
+
+	# Check magic
+	read PNG, $buffer, 8;
+	$buffer eq "\x89PNG\r\n\x1a\n"
+		|| die "'$filename' does not appear to be a PNG file";
+
+	while (1) {
+		read PNG, $buffer, 8;
+		last if length($buffer) < 8;
+
+		# Parse chunk header
+		my ($len, $type) = unpack('Na4', $buffer);
+
+		if ($type eq "tIME") {
+			my $val = pack('nC5', $canonical_time);
+			print PNG $val;
+			print PNG pack('N', crc32($type . $val));
+		} elsif ($type eq "tEXt") {
+			# Read entire field
+			read PNG, $buffer, $len + 4;
+
+			# Split contents by null byte
+			if (my ($tag) = $buffer =~ /^(date:[^\0]+)/) {
+				# Join with new timestamp
+				my $val = "$tag\0". strftime("%Y-%m-%dT%H:%M:%S%z",
+					gmtime($canonical_time));
+
+				# +0100 (%z) -> +01:00
+				$val =~ s/(?<=[+-]\d\d)(?=\d\d$)/:/;
+
+				# Seek backwards as we already read the field
+				seek PNG, -($len + 4), SEEK_CUR;
+
+				print PNG $val;
+				print PNG pack('N', crc32($type . $val));
+			}
+		} else {
+			# Skip chunk data and CRC
+			seek PNG, $len + 4, SEEK_CUR;
+		}
+	}
+
+	close PNG;
+}
+
+1;
-- 
2.1.0

_______________________________________________
Reproducible-builds mailing list
Reproducible-builds@lists.alioth.debian.org
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/reproducible-builds

Reply via email to