#!/usr/bin/perl use strict; use warnings; use Getopt::Long; use Pod::Usage; use File::Spec; use FindBin; use lib "$FindBin::Bin/../lib"; use Crypt::TSD; # Command line options my $help = 0; my $version = 0; my $output_file; my $extract_timestamps = 0; my $timestamp_dir = "timestamps"; my $verbose = 0; # Parse command line options GetOptions( 'help|h' => \$help, 'version' => \$version, 'output|o=s' => \$output_file, 'timestamps|t' => \$extract_timestamps, 'timestamp-dir|d=s' => \$timestamp_dir, 'verbose|v' => \$verbose, ) or pod2usage(2); # Show help if ($help) { pod2usage(-verbose => 2); exit 0; } # Show version if ($version) { print "tsd-extract version $Crypt::TSD::VERSION\n"; exit 0; } # Get input file from command line my $input_file = shift @ARGV; if (!$input_file) { print "Error: Input TSD file required\n"; pod2usage(1); } # Check if input file exists unless (-f $input_file) { die "Error: Input file '$input_file' not found\n"; } print "Extracting from TSD file...\n" if $verbose; print "Input file: $input_file\n" if $verbose; # Read TSD file my $tsd_data; eval { $tsd_data = Crypt::TSD->read_file($input_file); }; if ($@) { die "Error reading TSD file: $@\n"; } print "TSD file read successfully\n" if $verbose; print "Version: " . $tsd_data->{version} . "\n" if $verbose; # Extract content my $content = Crypt::TSD->extract_content_der($tsd_data); if (defined $content) { # Generate output filename if not provided unless ($output_file) { $output_file = $input_file; $output_file =~ s/\.tsd$/.extracted/; } print "Extracting content to: $output_file\n" if $verbose; # Write content to file open my $fh, '>:raw', $output_file or die "Cannot create output file '$output_file': $!\n"; print $fh $content; close $fh; print "Content extracted successfully: $output_file\n"; print "Content size: " . length($content) . " bytes\n" if $verbose; } else { print "No embedded content found in TSD file\n"; } # Extract timestamps if requested if ($extract_timestamps) { print "Extracting timestamps...\n" if $verbose; # Create timestamp directory unless (-d $timestamp_dir) { mkdir $timestamp_dir or die "Cannot create timestamp directory '$timestamp_dir': $!\n"; } my $token_count = Crypt::TSD->write_tst_files($tsd_data, $timestamp_dir); if ($token_count > 0) { print "Extracted $token_count timestamp(s) to directory: $timestamp_dir\n"; } else { print "No timestamps found in TSD file\n"; } } print "Done!\n"; __END__ =head1 NAME tsd-extract - Extract content and timestamps from a TimeStampedData (.tsd) file =head1 SYNOPSIS tsd-extract [options] input_file.tsd Options: -o, --output FILE Output file for extracted content -t, --timestamps Extract timestamp tokens to files -d, --timestamp-dir DIR Directory for timestamp files (default: timestamps) -v, --verbose Verbose output -h, --help Show this help --version Show version =head1 DESCRIPTION Extracts the embedded content and optionally timestamp tokens from a TimeStampedData (.tsd) file. The extracted content is saved to a file, and timestamp tokens can be saved as separate .tsr files. =head1 EXAMPLES # Extract content only tsd-extract document.tsd # Extract content to specific file tsd-extract -o original.pdf document.tsd # Extract content and timestamps tsd-extract -t document.tsd # Extract with custom timestamp directory tsd-extract -t -d my_timestamps document.tsd # Verbose output tsd-extract -v -t document.tsd =head1 SEE ALSO L, L =cut