1#------------------------------------------------------------------------------ 2# File: ISO.pm 3# 4# Description: Read information from ISO 9660 disk images 5# 6# Revisions: 2016-04-07 - P. Harvey created 7# 8# References: 1) http://wiki.osdev.org/ISO_9660 9#------------------------------------------------------------------------------ 10 11package Image::ExifTool::ISO; 12 13use strict; 14use vars qw($VERSION); 15use Image::ExifTool qw(:DataAccess :Utils); 16 17$VERSION = '1.01'; 18 19# trim trailing spaces and ignore tag if empty 20my %rawStr = ( 21 RawConv => sub { 22 my $val = shift; 23 $val =~ s/ +$//; 24 return length($val) ? $val : undef; 25 }, 26); 27 28# tag info for date/time tags 29my %dateInfo = ( 30 Format => 'undef[17]', 31 Groups => { 2 => 'Time' }, 32 ValueConv => q{ 33 return undef if $val !~ /[^0\0 ]/; # ignore if empty 34 if ($val =~ s/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})(.)/$1:$2:$3 $4:$5:$6.$7/s) { 35 $val .= TimeZoneString(unpack('c', $8) * 15); 36 } 37 return $val; 38 }, 39 PrintConv => '$self->ConvertDateTime($val)', 40); 41 42# lookup for volume descriptor types 43my %volumeDescriptorType = ( 44 0 => 'Boot Record', 45 1 => 'Primary Volume', 46 2 => 'Supplementary Volume', 47 3 => 'Volume Partition', 48 255 => 'Terminator', 49); 50 51# ISO tags 52%Image::ExifTool::ISO::Main = ( 53 GROUPS => { 2 => 'Other' }, 54 NOTES => 'Tags extracted from ISO 9660 disk images.', 55 0 => { 56 Name => 'BootRecord', 57 SubDirectory => { TagTable => 'Image::ExifTool::ISO::BootRecord' }, 58 }, 59 1 => { 60 Name => 'PrimaryVolume', 61 SubDirectory => { TagTable => 'Image::ExifTool::ISO::PrimaryVolume' }, 62 }, 63); 64 65%Image::ExifTool::ISO::BootRecord = ( 66 GROUPS => { 2 => 'Other' }, 67 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, 68 # 0 => { Name => 'VolumeType', PrintConv => \%volumeDescriptorType }, # (0 for boot record) 69 # 1 => { Name => 'Identifier', Format => 'undef[5]' }, # (always "CD001") 70 # 6 => 'VolumeDesriptorVersion', # (always 1) 71 # always extract BootSystem, even if empty, as an indication that this is bootable 72 7 => { Name => 'BootSystem', Format => 'string[32]', ValueConv => '$val=~s/ +$//; $val' }, 73 39 => { Name => 'BootIdentifier', Format => 'string[32]', %rawStr }, 74); 75 76%Image::ExifTool::ISO::PrimaryVolume = ( 77 GROUPS => { 2 => 'Other' }, 78 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, 79 # 0 => { Name => 'VolumeType', PrintConv => \%volumeDescriptorType }, # (1 for primary volume) 80 # 1 => { Name => 'Identifier', Format => 'undef[5]' }, # (always "CD001") 81 # 6 => 'VolumeDesriptorVersion', # (always 1) 82 8 => { Name => 'System', Format => 'string[32]', %rawStr }, 83 40 => { Name => 'VolumeName', Format => 'string[32]', %rawStr }, 84 80 => { Name => 'VolumeBlockCount', Format => 'int32u' }, 85 120 => { Name => 'VolumeSetDiskCount', Format => 'int16u', Unknown => 1 }, 86 124 => { Name => 'VolumeSetDiskNumber', Format => 'int16u', Unknown => 1 }, 87 128 => { Name => 'VolumeBlockSize', Format => 'int16u' }, 88 132 => { Name => 'PathTableSize', Format => 'int32u', Unknown => 1 }, 89 140 => { Name => 'PathTableLocation', Format => 'int32u', Unknown => 1 }, 90 174 => { 91 Name => 'RootDirectoryCreateDate', 92 Format => 'undef[7]', 93 Groups => { 2 => 'Time' }, 94 ValueConv => q{ 95 my @a = unpack('C6c', $val); 96 $a[0] += 1900; 97 $a[6] = TimeZoneString($a[6] * 15); 98 return sprintf('%.4d:%.2d:%.2d %.2d:%.2d:%.2d%s', @a); 99 }, 100 PrintConv => '$self->ConvertDateTime($val)', 101 }, 102 190 => { Name => 'VolumeSetName', Format => 'string[128]', %rawStr }, 103 318 => { Name => 'Publisher', Format => 'string[128]', %rawStr }, 104 446 => { Name => 'DataPreparer', Format => 'string[128]', %rawStr }, 105 574 => { Name => 'Software', Format => 'string[128]', %rawStr }, 106 702 => { Name => 'CopyrightFileName', Format => 'string[38]', %rawStr }, 107 740 => { Name => 'AbstractFileName', Format => 'string[36]', %rawStr }, 108 776 => { Name => 'BibligraphicFileName',Format => 'string[37]', %rawStr }, 109 813 => { Name => 'VolumeCreateDate', %dateInfo }, 110 830 => { Name => 'VolumeModifyDate', %dateInfo }, 111 847 => { Name => 'VolumeExpirationDate',%dateInfo }, 112 864 => { Name => 'VolumeEffectiveDate', %dateInfo }, 113 #881 => 'FileStructureVersion', # (always 1) 114); 115 116# ISO Composite tags 117%Image::ExifTool::ISO::Composite = ( 118 GROUPS => { 2 => 'Other' }, 119 VolumeSize => { 120 Require => { 121 0 => 'ISO:VolumeBlockCount', 122 1 => 'ISO:VolumeBlockSize', 123 }, 124 ValueConv => '$val[0] * $val[1]', 125 PrintConv => \&Image::ExifTool::ConvertFileSize, 126 }, 127); 128 129# add our composite tags 130Image::ExifTool::AddCompositeTags('Image::ExifTool::ISO'); 131 132#------------------------------------------------------------------------------ 133# Extract information from an ISO 9660 disk image 134# Inputs: 0) ExifTool object reference, 1) dirInfo reference 135# Returns: 1 on success, 0 if this wasn't a valid ISO 9660 image 136sub ProcessISO($$) 137{ 138 my ($et, $dirInfo) = @_; 139 my $raf = $$dirInfo{RAF}; 140 my ($buff, $tagTablePtr); 141 142 # verify this is a valid ISO file 143 return 0 unless $raf->Seek(32768, 0); 144 145 while ($raf->Read($buff, 2048) == 2048) { 146 last unless $buff =~ /^[\0-\x03\xff]CD001/; 147 unless ($tagTablePtr) { 148 $et->SetFileType(); # set the FileType tag 149 SetByteOrder('II'); # read little-endian values only 150 $tagTablePtr = GetTagTable('Image::ExifTool::ISO::Main'); 151 } 152 my $type = unpack('C', $buff); 153 $et->VPrint(0, "Volume descriptor type $type ($volumeDescriptorType{$type})\n"); 154 last if $type == 255; # stop at terminator 155 next unless $$tagTablePtr{$type}; 156 my $subTablePtr = GetTagTable($$tagTablePtr{$type}{SubDirectory}{TagTable}); 157 my %dirInfo = ( 158 DataPt => \$buff, 159 DataPos => $raf->Tell() - 2048, 160 DirStart => 0, 161 DirLen => length($buff), 162 ); 163 $et->ProcessDirectory(\%dirInfo, $subTablePtr); 164 } 165 return $tagTablePtr ? 1 : 0; 166} 167 1681; # end 169 170__END__ 171 172=head1 NAME 173 174Image::ExifTool::ISO - Read information from ISO 9660 disk images 175 176=head1 SYNOPSIS 177 178This module is used by Image::ExifTool 179 180=head1 DESCRIPTION 181 182This module contains definitions required by Image::ExifTool to read 183information from ISO 9660 disk images. 184 185=head1 AUTHOR 186 187Copyright 2003-2021, Phil Harvey (philharvey66 at gmail.com) 188 189This library is free software; you can redistribute it and/or modify it 190under the same terms as Perl itself. 191 192=head1 REFERENCES 193 194=over 4 195 196=item L<http://wiki.osdev.org/ISO_9660> 197 198=back 199 200=head1 SEE ALSO 201 202L<Image::ExifTool::TagNames/ISO Tags>, 203L<Image::ExifTool(3pm)|Image::ExifTool> 204 205=cut 206 207