# script di redirect documenti di Mago.Net su file PDF/A
# by Lorenzo Monti
#
# rel 0.2 del 11-06-2012
#
# Principio di funzionamento:
# i metadati necessari alla creazione del file PDF vengono inseriti nel flusso
# PostScript, tramite dei testi di colore bianco e con un apposito prefisso
# e suffisso che ne permettono il riconoscimento (§§§, carattere ASCII dec 167 oct 247).
# Questi tag vengono intercettati dal presente script perl, ma non compaiono
# sul documento, essendo di colore bianco.

use strict;
use File::Path qw(make_path);
use File::Basename qw(dirname);
use File::Spec qw(rel2abs);

# modificare secondo la propria configurazione
use constant GS => "C:\\Program Files\\gs\\gs9.05\\bin\\gswin64c.exe";

# la seguente routine sostituisce con degli underscore
# tutti i caratteri non validi per un nome di file
sub sanitize {
	# caratteri non validi
	$_[0] =~ s/[\\\/*?"<>|:]/_/g;
	# strip extra spazi
	$_[0] =~ s/^[[:space:]]*//g;
	$_[0] =~ s/[[:space:]]*$//g;
}

# variabili locali
my ($line, $file, %params, $year, $path, $gsparams, $title);

# devo ricevere il nome del file temporaneo sulla command line
die 'Sintassi: ' . __FILE__ . ' <tempfile>'
	unless (@ARGV > 0);

# apro il file temporaneo in scrittura
open(HFILE, '>', $ARGV[0])
	or die $!;

# i dati PostScript arrivano da standard input
while ($line = <STDIN>) {
	# cerca i parametri all'interno del flusso PostScript tramite una espressione regolare.
	# i parametri sono passati nella forma:
	# (\247\247\247NOME:VALORE\247\247\247)
	# vi possono essere spazi immediatamente vicino alle parentesi di apertura e chiusura
	if ($line =~ m/\([[:blank:]]*(?:\\247){3}([[:alpha:]]+):((?:[^\\]|\\(?!247))+)(?:\\247){3}[[:blank:]]*\)/) {
		# il primo match è il nome del parametro, il secondo match (dopo i due punti) è il valore
		$params{$1} = $2;
	}
	
	# scrivo la riga sul file temporaneo
	print HFILE $line;
}

close(HFILE);

# abbiamo trovato i parametri che cercavamo?
die 'Impossibile trovare alcuni parametri necessari all\'interno del flusso PostScript!'
	unless (defined($params{'TIPO'}) &&
			defined($params{'DOCNO'}) &&
			defined($params{'DATA'}));

# il titolo del PDF - obbligatorio per file conformi alla specifica PDF/A
$title = "$params{'TIPO'} numero $params{'DOCNO'} del $params{'DATA'}";

# eliminiamo caratteri non validi per il nome file
sanitize($params{'TIPO'});
sanitize($params{'DOCNO'});
sanitize($params{'DATA'});

# componiamo il nome del file PDF
$year = substr($params{'DATA'}, 6, 4);
$path = dirname(File::Spec->rel2abs(__FILE__)) . "\\files\\$year\\$params{'TIPO'}";
$file = "$path\\$params{'DOCNO'}-$params{'DATA'}.pdf";

# assicuriamoci che il path esiste
unless (-d $path) {
	make_path($path)
		or die 'Impossibile creare la directory di output!';
}

#
# avvio del Ghostscript
#

# parametri tarati per la produzione di un file conforme PDF/A
$gsparams = "-dPDFA -dBATCH -dNOPAUSE -dUseCIEColor -dSAFER -dQUIET " .
			"-sDEVICE=pdfwrite -dPDFSETTINGS=/prepress -dAutoRotatePages=/PageByPage -r600 " .
			"-sOutputFile=\"$file\" -";

# apriamo una pipe verso Ghostscript
open(HGS, "| \"" . GS . "\" $gsparams")
	or die $!;

# riapriamo il file PostScript temporaneo in lettura
open(HFILE, '<', $ARGV[0])
	or die $!;

# come prima cosa iniettiamo il titolo del PDF/A
print HGS <<__EOT__;
%!
[ /Title ($title)
  /DOCINFO pdfmark
__EOT__

# passiamo a Ghostscript il contenuto del file PostScript temporaneo
while ($line = <HFILE>) {
	print HGS $line;
}

# chiudiamo i vari handle
close(HFILE)
	or die $!;
close(HGS)
	or die $!;

# cancelliamo il file temporaneo
unlink($ARGV[0]);

__END__
