exiftool_vendored 12.56.0 → 12.58.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/bin/Changes +35 -2
  3. data/bin/META.json +1 -1
  4. data/bin/META.yml +1 -1
  5. data/bin/README +2 -2
  6. data/bin/config_files/rotate_regions.config +1 -1
  7. data/bin/exiftool +95 -47
  8. data/bin/lib/Image/ExifTool/AIFF.pm +2 -2
  9. data/bin/lib/Image/ExifTool/APE.pm +2 -2
  10. data/bin/lib/Image/ExifTool/BuildTagLookup.pm +19 -15
  11. data/bin/lib/Image/ExifTool/Canon.pm +26 -6
  12. data/bin/lib/Image/ExifTool/DJI.pm +28 -2
  13. data/bin/lib/Image/ExifTool/Exif.pm +24 -5
  14. data/bin/lib/Image/ExifTool/FlashPix.pm +6 -2
  15. data/bin/lib/Image/ExifTool/FujiFilm.pm +1 -0
  16. data/bin/lib/Image/ExifTool/GPS.pm +7 -2
  17. data/bin/lib/Image/ExifTool/JPEG.pm +14 -2
  18. data/bin/lib/Image/ExifTool/Jpeg2000.pm +5 -5
  19. data/bin/lib/Image/ExifTool/LNK.pm +5 -4
  20. data/bin/lib/Image/ExifTool/MIE.pm +3 -3
  21. data/bin/lib/Image/ExifTool/MPEG.pm +2 -2
  22. data/bin/lib/Image/ExifTool/MakerNotes.pm +2 -2
  23. data/bin/lib/Image/ExifTool/Minolta.pm +6 -7
  24. data/bin/lib/Image/ExifTool/Nikon.pm +998 -903
  25. data/bin/lib/Image/ExifTool/NikonCustom.pm +2 -2
  26. data/bin/lib/Image/ExifTool/NikonSettings.pm +1 -1
  27. data/bin/lib/Image/ExifTool/Olympus.pm +3 -1
  28. data/bin/lib/Image/ExifTool/Pentax.pm +8 -5
  29. data/bin/lib/Image/ExifTool/Photoshop.pm +38 -7
  30. data/bin/lib/Image/ExifTool/QuickTime.pm +23 -7
  31. data/bin/lib/Image/ExifTool/QuickTimeStream.pl +3 -1
  32. data/bin/lib/Image/ExifTool/README +19 -2
  33. data/bin/lib/Image/ExifTool/RIFF.pm +3 -3
  34. data/bin/lib/Image/ExifTool/Rawzor.pm +2 -2
  35. data/bin/lib/Image/ExifTool/Sigma.pm +5 -4
  36. data/bin/lib/Image/ExifTool/Sony.pm +23 -1
  37. data/bin/lib/Image/ExifTool/TagLookup.pm +4670 -4628
  38. data/bin/lib/Image/ExifTool/TagNames.pod +261 -89
  39. data/bin/lib/Image/ExifTool/Validate.pm +5 -5
  40. data/bin/lib/Image/ExifTool/WriteExif.pl +42 -0
  41. data/bin/lib/Image/ExifTool/Writer.pl +39 -17
  42. data/bin/lib/Image/ExifTool/XMP.pm +2 -2
  43. data/bin/lib/Image/ExifTool.pm +94 -33
  44. data/bin/lib/Image/ExifTool.pod +4 -4
  45. data/bin/perl-Image-ExifTool.spec +1 -1
  46. data/lib/exiftool_vendored/version.rb +1 -1
  47. metadata +2 -2
@@ -1419,6 +1419,8 @@ sub SetNewValuesFromFile($$;@)
1419
1419
  $tag =~ s/(.+?)\s*(>|<) ?//;
1420
1420
  $$opts{EXPR} = 1; # flag this expression
1421
1421
  } else {
1422
+ # (not sure why this is here because sign should be before '<')
1423
+ # (--> allows "<+" or "<-", which is an undocumented feature)
1422
1424
  $opt = $1 if $tag =~ s/^([-+])\s*//;
1423
1425
  }
1424
1426
  }
@@ -2727,8 +2729,10 @@ sub GetAllGroups($;$)
2727
2729
 
2728
2730
  my @tableNames = keys %allTables;
2729
2731
 
2730
- # loop through all tag tables and get all group names
2731
2732
  my %allGroups;
2733
+ # add family 1 groups not in tables
2734
+ $family == 1 and map { $allGroups{$_} = 1 } qw(Garmin);
2735
+ # loop through all tag tables and get all group names
2732
2736
  while (@tableNames) {
2733
2737
  my $table = GetTagTable(pop @tableNames);
2734
2738
  my ($grps, $grp, $tag, $tagInfo);
@@ -4202,7 +4206,7 @@ sub WriteDirectory($$$;$)
4202
4206
  return '' unless $dataPt or $$dirInfo{RAF}; # nothing to do if block never existed
4203
4207
  # don't allow MakerNotes to be removed from RAW files
4204
4208
  if ($blockName eq 'MakerNotes' and $rawType{$$self{FileType}}) {
4205
- $self->Warn("Can't delete MakerNotes from $$self{VALUE}{FileType}",1);
4209
+ $self->Warn("Can't delete MakerNotes from $$self{FileType}",1);
4206
4210
  return undef;
4207
4211
  }
4208
4212
  $verb = 'Deleting';
@@ -4267,7 +4271,7 @@ sub WriteDirectory($$$;$)
4267
4271
  if ($out) {
4268
4272
  print $out " Deleting $name\n" if defined $newData and not length $newData;
4269
4273
  if ($$self{CHANGED} == $oldChanged and $$self{OPTIONS}{Verbose} > 2) {
4270
- print $out "$$self{INDENT} [nothing changed in $dirName]\n";
4274
+ print $out "$$self{INDENT} [nothing changed in $name]\n";
4271
4275
  }
4272
4276
  }
4273
4277
  return $newData;
@@ -5432,7 +5436,6 @@ sub WriteJPEG($$)
5432
5436
  my $verbose = $$self{OPTIONS}{Verbose};
5433
5437
  my $out = $$self{OPTIONS}{TextOut};
5434
5438
  my $rtnVal = 0;
5435
- my %dumpParms = ( Out => $out );
5436
5439
  my ($writeBuffer, $oldOutfile); # used to buffer writing until PreviewImage position is known
5437
5440
 
5438
5441
  # check to be sure this is a valid JPG or EXV file
@@ -5447,7 +5450,6 @@ sub WriteJPEG($$)
5447
5450
  Write($outfile,"\xff\x01") or $err = 1;
5448
5451
  $isEXV = 1;
5449
5452
  }
5450
- $dumpParms{MaxLen} = 128 unless $verbose > 3;
5451
5453
 
5452
5454
  delete $$self{PREVIEW_INFO}; # reset preview information
5453
5455
  delete $$self{DEL_PREVIEW}; # reset flag to delete preview
@@ -6017,12 +6019,7 @@ sub WriteJPEG($$)
6017
6019
  #
6018
6020
  my $segDataPt = \$segData;
6019
6021
  $length = length($segData);
6020
- if ($verbose) {
6021
- print $out "JPEG $markerName ($length bytes):\n";
6022
- if ($verbose > 2 and $markerName =~ /^APP/) {
6023
- HexDump($segDataPt, undef, %dumpParms);
6024
- }
6025
- }
6022
+ print $out "JPEG $markerName ($length bytes)\n" if $verbose;
6026
6023
  # group delete of APP segments
6027
6024
  if ($$delGroup{$dirName}) {
6028
6025
  $verbose and print $out " Deleting $dirName segment\n";
@@ -6870,6 +6867,7 @@ sub WriteBinaryData($$$)
6870
6867
 
6871
6868
  # get default format ('int8u' unless specified)
6872
6869
  my $dataPt = $$dirInfo{DataPt} or return undef;
6870
+ my $dataLen = length $$dataPt;
6873
6871
  my $defaultFormat = $$tagTablePtr{FORMAT} || 'int8u';
6874
6872
  my $increment = FormatSize($defaultFormat);
6875
6873
  unless ($increment) {
@@ -6886,7 +6884,8 @@ sub WriteBinaryData($$$)
6886
6884
  delete $$dirInfo{VarFormatData};
6887
6885
  }
6888
6886
  my $dirStart = $$dirInfo{DirStart} || 0;
6889
- my $dirLen = $$dirInfo{DirLen} || length($$dataPt) - $dirStart;
6887
+ my $dirLen = $$dirInfo{DirLen};
6888
+ $dirLen = $dataLen - $dirStart if not defined $dirLen or $dirLen > $dataLen - $dirStart;
6890
6889
  my $newData = substr($$dataPt, $dirStart, $dirLen) or return undef;
6891
6890
  my $dirName = $$dirInfo{DirName};
6892
6891
  my $varSize = 0;
@@ -7022,11 +7021,34 @@ sub WriteBinaryData($$$)
7022
7021
  $tagInfo = $self->GetTagInfo($tagTablePtr, $tagID, \$v);
7023
7022
  next unless $tagInfo;
7024
7023
  }
7025
- next unless $$tagInfo{SubDirectory}; # (just to be safe)
7026
- my %subdirInfo = ( DataPt => \$newData, DirStart => $entry );
7027
- my $subTablePtr = GetTagTable($$tagInfo{SubDirectory}{TagTable});
7028
- my $dat = $self->WriteDirectory(\%subdirInfo, $subTablePtr);
7029
- substr($newData, $entry) = $dat if defined $dat and length $dat;
7024
+ my $subdir = $$tagInfo{SubDirectory} or next;
7025
+ my $start = $$subdir{Start};
7026
+ my $len;
7027
+ if (not $start) {
7028
+ $start = $entry;
7029
+ $len = $dirLen - $start;
7030
+ } elsif ($start =~ /\$/) {
7031
+ my $count = 1;
7032
+ my $format = $$tagInfo{Format} || $defaultFormat;
7033
+ $format =~ /(.*)\[(.*)\]/ and ($format, $count) = ($1, $2);
7034
+ my $val = ReadValue($dataPt, $entry, $format, $count, $dirLen - $entry);
7035
+ # ignore directories with a zero offset (ie. missing Nikon ShotInfo entries)
7036
+ next unless $val;
7037
+ my $dirStart = 0;
7038
+ #### eval Start ($val, $dirStart)
7039
+ $start = eval($start);
7040
+ next if $start < $dirStart or $start > $dataLen;
7041
+ $len = $$subdir{DirLen};
7042
+ $len = $dataLen - $start unless $len and $len <= $dataLen - $start;
7043
+ }
7044
+ my %subdirInfo = (
7045
+ DataPt => \$newData,
7046
+ DirStart => $start,
7047
+ DirLen => $len,
7048
+ TagInfo => $tagInfo,
7049
+ );
7050
+ my $dat = $self->WriteDirectory(\%subdirInfo, GetTagTable($$subdir{TagTable}));
7051
+ substr($newData, $start, $len) = $dat if defined $dat and length $dat;
7030
7052
  }
7031
7053
  }
7032
7054
  return $newData;
@@ -50,7 +50,7 @@ use Image::ExifTool::Exif;
50
50
  use Image::ExifTool::GPS;
51
51
  require Exporter;
52
52
 
53
- $VERSION = '3.56';
53
+ $VERSION = '3.57';
54
54
  @ISA = qw(Exporter);
55
55
  @EXPORT_OK = qw(EscapeXML UnescapeXML);
56
56
 
@@ -3097,7 +3097,7 @@ sub ScanForXMP($$)
3097
3097
  undef $buff;
3098
3098
  }
3099
3099
  }
3100
- unless ($$et{VALUE}{FileType}) {
3100
+ unless ($$et{FileType}) {
3101
3101
  $$et{FILE_TYPE} = $$et{FILE_EXT};
3102
3102
  $et->SetFileType('<unknown file containing XMP>', undef, '');
3103
3103
  }
@@ -29,7 +29,7 @@ use vars qw($VERSION $RELEASE @ISA @EXPORT_OK %EXPORT_TAGS $AUTOLOAD @fileTypes
29
29
  %jpegMarker %specialTags %fileTypeLookup $testLen $exeDir
30
30
  %static_vars);
31
31
 
32
- $VERSION = '12.56';
32
+ $VERSION = '12.58';
33
33
  $RELEASE = '';
34
34
  @ISA = qw(Exporter);
35
35
  %EXPORT_TAGS = (
@@ -1821,6 +1821,13 @@ my %systemTagsNotes = (
1821
1821
  if specifically requested
1822
1822
  },
1823
1823
  },
1824
+ ImageDataMD5 => {
1825
+ Notes => q{
1826
+ MD5 of image data. Generated only if specifically requested for JPEG and
1827
+ TIFF-based images, except Panasonic raw for now. Includes image data,
1828
+ OtherImage and JpgFromRaw in the MD5, but not ThumbnailImage or PreviewImage
1829
+ },
1830
+ },
1824
1831
  );
1825
1832
 
1826
1833
  # tags defined by UserParam option (added at runtime)
@@ -2043,6 +2050,7 @@ sub new
2043
2050
  $$self{DEL_GROUP} = { }; # lookup for groups to delete when writing
2044
2051
  $$self{SAVE_COUNT} = 0; # count calls to SaveNewValues()
2045
2052
  $$self{FILE_SEQUENCE} = 0; # sequence number for files when reading
2053
+ $$self{FILES_WRITTEN} = 0; # count of files successfully written
2046
2054
  $$self{INDENT2} = ''; # indentation of verbose messages from SetNewValue
2047
2055
 
2048
2056
  # initialize our new groups for writing
@@ -2478,7 +2486,15 @@ sub ExtractInfo($;@)
2478
2486
  $self->WarnOnce('Install Time::HiRes to generate ProcessingTime');
2479
2487
  }
2480
2488
  }
2481
-
2489
+
2490
+ # create MD5 object if ImageDataMD5 is requested
2491
+ if ($$req{imagedatamd5} and not $$self{ImageDataMD5}) {
2492
+ if (require Digest::MD5) {
2493
+ $$self{ImageDataMD5} = Digest::MD5->new;
2494
+ } else {
2495
+ $self->WarnOnce('Install Digest::MD5 to calculate image data MD5');
2496
+ }
2497
+ }
2482
2498
  ++$$self{FILE_SEQUENCE}; # count files read
2483
2499
  }
2484
2500
 
@@ -2869,6 +2885,10 @@ sub ExtractInfo($;@)
2869
2885
  # restore necessary members when exiting re-entrant code
2870
2886
  $$self{$_} = $$reEntry{$_} foreach keys %$reEntry;
2871
2887
  SetByteOrder($saveOrder);
2888
+ } elsif ($$self{ImageDataMD5}) {
2889
+ my $digest = $$self{ImageDataMD5}->hexdigest;
2890
+ # (don't store empty digest)
2891
+ $self->FoundTag(ImageDataMD5 => $digest) unless $digest eq 'd41d8cd98f00b204e9800998ecf8427e';
2872
2892
  }
2873
2893
 
2874
2894
  # ($type may be undef without an Error when processing sub-documents)
@@ -4296,9 +4316,9 @@ sub GetFileTime($$)
4296
4316
  # on Windows, try to work around incorrect file times when daylight saving time is in effect
4297
4317
  if ($^O eq 'MSWin32') {
4298
4318
  if (not eval { require Win32::API }) {
4299
- $self->WarnOnce('Install Win32::API for proper handling of Windows file times');
4319
+ $self->WarnOnce('Install Win32::API for proper handling of Windows file times', 1);
4300
4320
  } elsif (not eval { require Win32API::File }) {
4301
- $self->WarnOnce('Install Win32API::File for proper handling of Windows file times');
4321
+ $self->WarnOnce('Install Win32API::File for proper handling of Windows file times', 1);
4302
4322
  } else {
4303
4323
  # get Win32 handle, needed for GetFileTime
4304
4324
  my $win32Handle = eval { Win32API::File::GetOsFHandle($file) };
@@ -5867,7 +5887,8 @@ sub ConvertTimeSpan($;$)
5867
5887
  #------------------------------------------------------------------------------
5868
5888
  # Patched timelocal() that fixes ActivePerl timezone bug
5869
5889
  # Inputs/Returns: same as timelocal()
5870
- # Notes: must 'require Time::Local' before calling this routine
5890
+ # Notes: must 'require Time::Local' before calling this routine.
5891
+ # Also note that year should be full year, and not relative to 1900 as with localtime
5871
5892
  sub TimeLocal(@)
5872
5893
  {
5873
5894
  my $tm = Time::Local::timelocal(@_);
@@ -6337,7 +6358,10 @@ sub ProcessJPEG($$)
6337
6358
  my %dumpParms = ( Out => $out );
6338
6359
  my ($success, $wantTrailer, $trailInfo, $foundSOS, %jumbfChunk);
6339
6360
  my (@iccChunk, $iccChunkCount, $iccChunksTotal, @flirChunk, $flirCount, $flirTotal);
6340
- my ($preview, $scalado, @dqt, $subSampling, $dumpEnd, %extendedXMP);
6361
+ my ($preview, $scalado, @dqt, $subSampling, $dumpEnd, %extendedXMP, $md5);
6362
+
6363
+ # get pointer to MD5 object if it exists and we are the top-level JPEG
6364
+ $md5 = $$self{ImageDataMD5} if $$self{FILE_TYPE} eq 'JPEG' and not $$self{DOC_NUM};
6341
6365
 
6342
6366
  # check to be sure this is a valid JPG (or J2C, or EXV) file
6343
6367
  return 0 unless $raf->Read($s, 2) == 2 and $s =~ /^\xff[\xd8\x4f\x01]/;
@@ -6385,7 +6409,9 @@ sub ProcessJPEG($$)
6385
6409
  #
6386
6410
  # read ahead to the next segment unless we have reached EOI, SOS or SOD
6387
6411
  #
6388
- unless ($marker and ($marker==0xd9 or ($marker==0xda and not $wantTrailer) or $marker==0x93)) {
6412
+ unless ($marker and ($marker==0xd9 or ($marker==0xda and not $wantTrailer and not $md5) or
6413
+ $marker==0x93))
6414
+ {
6389
6415
  # read up to next marker (JPEG markers begin with 0xff)
6390
6416
  my $buff;
6391
6417
  $raf->ReadLine($buff) or last;
@@ -6415,6 +6441,8 @@ sub ProcessJPEG($$)
6415
6441
  $nextSegPos = $raf->Tell();
6416
6442
  $len -= 4; # subtract size of length word
6417
6443
  last unless $raf->Seek($len, 1);
6444
+ } elsif ($md5 and defined $marker and ($marker == 0x00 or $marker == 0xda)) {
6445
+ $md5->add($buff); # (note: this includes the terminating 0xff's)
6418
6446
  }
6419
6447
  # read second segment too if this was the first
6420
6448
  next unless defined $marker;
@@ -6625,7 +6653,7 @@ sub ProcessJPEG($$)
6625
6653
  next if $trailInfo or $wantTrailer or $verbose > 2 or $htmlDump;
6626
6654
  }
6627
6655
  # must scan to EOI if Validate or JpegCompressionFactor used
6628
- next if $$options{Validate} or $calcImageLen or $$req{trailer};
6656
+ next if $$options{Validate} or $calcImageLen or $$req{trailer} or $md5;
6629
6657
  # nothing interesting to parse after start of scan (SOS)
6630
6658
  $success = 1;
6631
6659
  last; # all done parsing file
@@ -7008,7 +7036,7 @@ sub ProcessJPEG($$)
7008
7036
  $self->FoundTag('PreviewImage', $preview);
7009
7037
  undef $preview;
7010
7038
  }
7011
- } elsif ($marker == 0xe4) { # APP4 (InfiRay, "SCALADO", FPXR, PreviewImage)
7039
+ } elsif ($marker == 0xe4) { # APP4 (InfiRay, "SCALADO", FPXR, DJI, PreviewImage)
7012
7040
  if ($$segDataPt =~ /^SCALADO\0/ and $length >= 16) {
7013
7041
  $dumpType = 'SCALADO';
7014
7042
  my ($num, $idx, $len) = unpack('x8n2N', $$segDataPt);
@@ -7039,6 +7067,16 @@ sub ProcessJPEG($$)
7039
7067
  DirStart(\%dirInfo, 0, 0);
7040
7068
  my $tagTablePtr = GetTagTable('Image::ExifTool::DJI::ThermalParams');
7041
7069
  $self->ProcessDirectory(\%dirInfo, $tagTablePtr);
7070
+ } elsif ($$self{Make} eq 'DJI' and $$segDataPt =~ /^(.{32})?.{32}\x2c\x01\x20\0/s) {
7071
+ $dumpType = 'DJI ThermalParams2';
7072
+ DirStart(\%dirInfo, $1 ? 32 : 0, 0);
7073
+ my $tagTablePtr = GetTagTable('Image::ExifTool::DJI::ThermalParams2');
7074
+ $self->ProcessDirectory(\%dirInfo, $tagTablePtr);
7075
+ } elsif ($$self{Make} eq 'DJI' and $$segDataPt =~ /^.{32}\xaa\x55\x38\0/s) {
7076
+ $dumpType = 'DJI ThermalParams3';
7077
+ DirStart(\%dirInfo, 32, 0);
7078
+ my $tagTablePtr = GetTagTable('Image::ExifTool::DJI::ThermalParams3');
7079
+ $self->ProcessDirectory(\%dirInfo, $tagTablePtr);
7042
7080
  } elsif ($$self{HasIJPEG} and $length >= 120) {
7043
7081
  $dumpType = 'InfiRay Factory';
7044
7082
  SetByteOrder('II');
@@ -7152,6 +7190,13 @@ sub ProcessJPEG($$)
7152
7190
  $self->ProcessDirectory(\%dirInfo, $tagTablePtr);
7153
7191
  delete $$self{SET_GROUP0};
7154
7192
  delete $$self{SET_GROUP1};
7193
+ } elsif ($$segDataPt =~ /^DJI-DBG\0/) {
7194
+ $dumpType = 'DJI Info';
7195
+ my $tagTablePtr = GetTagTable('Image::ExifTool::DJI::Info');
7196
+ DirStart(\%dirInfo, 8, 0);
7197
+ $$self{SET_GROUP0} = 'APP7';
7198
+ $self->ProcessDirectory(\%dirInfo, $tagTablePtr);
7199
+ delete $$self{SET_GROUP0};
7155
7200
  } elsif ($$segDataPt =~ /^\x1aQualcomm Camera Attributes/) {
7156
7201
  # found in HP iPAQ_VoiceMessenger
7157
7202
  $dumpType = 'Qualcomm';
@@ -7680,7 +7725,7 @@ sub DoProcessTIFF($$;$)
7680
7725
  }
7681
7726
  }
7682
7727
  # update FileType if necessary now that we know more about the file
7683
- if ($$self{DNGVersion} and $$self{VALUE}{FileType} !~ /^(DNG|GPR)$/) {
7728
+ if ($$self{DNGVersion} and $$self{FileType} !~ /^(DNG|GPR)$/) {
7684
7729
  # override whatever FileType we set since we now know it is DNG
7685
7730
  $self->OverrideFileType($$self{TIFF_TYPE} = 'DNG');
7686
7731
  }
@@ -7988,7 +8033,7 @@ sub ProcessDirectory($$$;$)
7988
8033
  # patch for bug in Windows phone 7.5 O/S that writes incorrect InteropIFD pointer
7989
8034
  return 0 unless $dirName eq 'GPS' and $$self{PROCESSED}{$addr} eq 'InteropIFD';
7990
8035
  }
7991
- $$self{PROCESSED}{$addr} = $dirName;
8036
+ $$self{PROCESSED}{$addr} = $dirName unless $$tagTablePtr{VARS} and $$tagTablePtr{VARS}{ALLOW_REPROCESS};
7992
8037
  }
7993
8038
  my $oldOrder = GetByteOrder();
7994
8039
  my @save = @$self{'INDENT','DIR_NAME','Compression','SubfileType'};
@@ -8566,7 +8611,7 @@ sub DoEscape($$)
8566
8611
  sub SetFileType($;$$$)
8567
8612
  {
8568
8613
  my ($self, $fileType, $mimeType, $normExt) = @_;
8569
- unless ($$self{VALUE}{FileType} and not $$self{DOC_NUM}) {
8614
+ unless ($$self{FileType} and not $$self{DOC_NUM}) {
8570
8615
  my $baseType = $$self{FILE_TYPE};
8571
8616
  my $ext = $$self{FILE_EXT};
8572
8617
  $fileType or $fileType = $baseType;
@@ -8585,7 +8630,8 @@ sub SetFileType($;$$$)
8585
8630
  $normExt = $fileTypeExt{$fileType};
8586
8631
  $normExt = $fileType unless defined $normExt;
8587
8632
  }
8588
- $$self{FileType} = $fileType;
8633
+ # ($$self{FileType} is the file type of the main document)
8634
+ $$self{FileType} = $fileType unless $$self{DOC_NUM};
8589
8635
  $self->FoundTag('FileType', $fileType);
8590
8636
  $self->FoundTag('FileTypeExtension', uc $normExt);
8591
8637
  $self->FoundTag('MIMEType', $mimeType || 'application/unknown');
@@ -8749,13 +8795,16 @@ sub ProcessBinaryData($$$)
8749
8795
  {
8750
8796
  my ($self, $dirInfo, $tagTablePtr) = @_;
8751
8797
  my $dataPt = $$dirInfo{DataPt};
8752
- my $offset = $$dirInfo{DirStart} || 0;
8753
- my $size = $$dirInfo{DirLen} || (length($$dataPt) - $offset);
8798
+ my $dataLen = length $$dataPt;
8799
+ my $dirStart = $$dirInfo{DirStart} || 0;
8800
+ my $maxLen = $dataLen - $dirStart;
8801
+ my $size = $$dirInfo{DirLen};
8754
8802
  my $base = $$dirInfo{Base} || 0;
8755
8803
  my $verbose = $$self{OPTIONS}{Verbose};
8756
8804
  my $unknown = $$self{OPTIONS}{Unknown};
8757
8805
  my $dataPos = $$dirInfo{DataPos} || 0;
8758
8806
 
8807
+ $size = $maxLen if not defined $size or $size > $maxLen;
8759
8808
  # get default format ('int8u' unless specified)
8760
8809
  my $defaultFormat = $$tagTablePtr{FORMAT} || 'int8u';
8761
8810
  my $increment = $formatSize{$defaultFormat};
@@ -8797,6 +8846,7 @@ sub ProcessBinaryData($$$)
8797
8846
  $tagInfo = $self->GetTagInfo($tagTablePtr, $index);
8798
8847
  unless ($tagInfo) {
8799
8848
  next unless defined $tagInfo;
8849
+ # $entry = offset of value relative to directory start (or end if negative)
8800
8850
  my $entry = int($index) * $increment + $varSize;
8801
8851
  if ($entry < 0) {
8802
8852
  $entry += $size;
@@ -8805,7 +8855,7 @@ sub ProcessBinaryData($$$)
8805
8855
  next if $entry >= $size;
8806
8856
  my $more = $size - $entry;
8807
8857
  $more = 128 if $more > 128;
8808
- my $v = substr($$dataPt, $entry+$offset, $more);
8858
+ my $v = substr($$dataPt, $entry+$dirStart, $more);
8809
8859
  $tagInfo = $self->GetTagInfo($tagTablePtr, $index, \$v);
8810
8860
  next unless $tagInfo;
8811
8861
  }
@@ -8838,7 +8888,7 @@ sub ProcessBinaryData($$$)
8838
8888
  $count = $more;
8839
8889
  } elsif ($format eq 'pstring') {
8840
8890
  $format = 'string';
8841
- $count = Get8u($dataPt, ($entry++)+$offset);
8891
+ $count = Get8u($dataPt, ($entry++)+$dirStart);
8842
8892
  --$more;
8843
8893
  } elsif (not $formatSize{$format}) {
8844
8894
  if ($format =~ /(.*)\[(.*)\]/) {
@@ -8867,17 +8917,17 @@ sub ProcessBinaryData($$$)
8867
8917
  } elsif ($format =~ /^var_/) {
8868
8918
  # handle variable-length string formats
8869
8919
  $format = substr($format, 4);
8870
- pos($$dataPt) = $entry + $offset;
8920
+ pos($$dataPt) = $entry + $dirStart;
8871
8921
  undef $count;
8872
8922
  if ($format eq 'ustring') {
8873
- $count = pos($$dataPt) - ($entry+$offset) if $$dataPt =~ /\G(..)*?\0\0/sg;
8923
+ $count = pos($$dataPt) - ($entry+$dirStart) if $$dataPt =~ /\G(..)*?\0\0/sg;
8874
8924
  $varSize -= 2; # ($count includes base size of 2 bytes)
8875
8925
  } elsif ($format eq 'pstring') {
8876
- $count = Get8u($dataPt, ($entry++)+$offset);
8926
+ $count = Get8u($dataPt, ($entry++)+$dirStart);
8877
8927
  --$more;
8878
8928
  } elsif ($format eq 'pstr32' or $format eq 'ustr32') {
8879
8929
  last if $more < 4;
8880
- $count = Get32u($dataPt, $entry + $offset);
8930
+ $count = Get32u($dataPt, $entry + $dirStart);
8881
8931
  $count *= 2 if $format eq 'ustr32';
8882
8932
  $entry += 4;
8883
8933
  $more -= 4;
@@ -8885,22 +8935,22 @@ sub ProcessBinaryData($$$)
8885
8935
  } elsif ($format eq 'int16u') {
8886
8936
  # int16u size of binary data to follow
8887
8937
  last if $more < 2;
8888
- $count = Get16u($dataPt, $entry + $offset) + 2;
8938
+ $count = Get16u($dataPt, $entry + $dirStart) + 2;
8889
8939
  $varSize -= 2; # ($count includes size word)
8890
8940
  $format = 'undef';
8891
8941
  } elsif ($format eq 'ue7') {
8892
8942
  require Image::ExifTool::BPG;
8893
- ($val, $count) = Image::ExifTool::BPG::Get_ue7($dataPt, $entry + $offset);
8943
+ ($val, $count) = Image::ExifTool::BPG::Get_ue7($dataPt, $entry + $dirStart);
8894
8944
  last unless defined $val;
8895
8945
  --$varSize; # ($count includes base size of 1 byte)
8896
8946
  } elsif ($$dataPt =~ /\0/g) {
8897
- $count = pos($$dataPt) - ($entry+$offset);
8947
+ $count = pos($$dataPt) - ($entry+$dirStart);
8898
8948
  --$varSize; # ($count includes base size of 1 byte)
8899
8949
  }
8900
8950
  $count = $more if not defined $count or $count > $more;
8901
8951
  $varSize += $count; # shift subsequent indices
8902
8952
  unless (defined $val) {
8903
- $val = substr($$dataPt, $entry+$offset, $count);
8953
+ $val = substr($$dataPt, $entry+$dirStart, $count);
8904
8954
  $val = $self->Decode($val, 'UCS2') if $format eq 'ustring' or $format eq 'ustr32';
8905
8955
  $val =~ s/\0.*//s unless $format eq 'undef'; # truncate at null
8906
8956
  }
@@ -8914,7 +8964,7 @@ sub ProcessBinaryData($$$)
8914
8964
  # hook to allow format, etc to be set dynamically
8915
8965
  if (defined $$tagInfo{Hook}) {
8916
8966
  my $oldVarSize = $varSize;
8917
- my $pos = $entry + $offset;
8967
+ my $pos = $entry + $dirStart;
8918
8968
  #### eval Hook ($format, $varSize, $size, $dataPt, $pos)
8919
8969
  eval $$tagInfo{Hook};
8920
8970
  # save variable size data if required for writing (in case changed by Hook)
@@ -8939,7 +8989,7 @@ sub ProcessBinaryData($$$)
8939
8989
  next if $$tagInfo{LargeTag} and $$self{EXCL_TAG_LOOKUP}{lc $$tagInfo{Name}};
8940
8990
  # read value now if necessary
8941
8991
  unless (defined $val and not $$tagInfo{SubDirectory}) {
8942
- $val = ReadValue($dataPt, $entry+$offset, $format, $count, $more, \$rational);
8992
+ $val = ReadValue($dataPt, $entry+$dirStart, $format, $count, $more, \$rational);
8943
8993
  next unless defined $val;
8944
8994
  $mask = $$tagInfo{Mask};
8945
8995
  $val = ($val & $mask) >> $$tagInfo{BitShift} if $mask;
@@ -8956,8 +9006,8 @@ sub ProcessBinaryData($$$)
8956
9006
  Value => $val,
8957
9007
  DataPt => $dataPt,
8958
9008
  Size => $len,
8959
- Start => $entry+$offset,
8960
- Addr => $entry+$offset+$base+$dataPos,
9009
+ Start => $entry+$dirStart,
9010
+ Addr => $entry+$dirStart+$base+$dataPos,
8961
9011
  Format => $format,
8962
9012
  Count => $count,
8963
9013
  Extra => $mask ? sprintf(', mask 0x%.2x',$mask) : undef,
@@ -8983,16 +9033,27 @@ sub ProcessBinaryData($$$)
8983
9033
  my $subdirBase = $base;
8984
9034
  if (defined $$subdir{Base}) {
8985
9035
  #### eval Base ($start,$base)
8986
- my $start = $entry + $offset + $dataPos;
9036
+ my $start = $entry + $dirStart + $dataPos;
8987
9037
  $subdirBase = eval($$subdir{Base}) + $base;
8988
9038
  }
8989
9039
  my $start = $$subdir{Start} || 0;
9040
+ if ($start =~ /\$/) {
9041
+ # ignore directories with a zero offset (ie. missing Nikon ShotInfo entries)
9042
+ next unless $val;
9043
+ #### eval Start ($val, $dirStart)
9044
+ $start = eval($start);
9045
+ next if $start < $dirStart or $start > $dataLen;
9046
+ $len = $$subdir{DirLen};
9047
+ $len = $dataLen - $start unless $len and $len <= $dataLen - $start;
9048
+ } else {
9049
+ $start += $dirStart + $entry;
9050
+ }
8990
9051
  my %subdirInfo = (
8991
9052
  DataPt => $dataPt,
8992
9053
  DataPos => $dataPos,
8993
- DataLen => length $$dataPt,
8994
- DirStart => $entry + $offset + $start,
8995
- DirLen => $len - $start,
9054
+ DataLen => $dataLen,
9055
+ DirStart => $start,
9056
+ DirLen => $len,
8996
9057
  Base => $subdirBase,
8997
9058
  );
8998
9059
  delete $$self{NO_UNKNOWN};
@@ -2327,9 +2327,9 @@ CBOR, CIFF, CameraIFD, Canon, CanonCustom, CanonDR4, CanonRaw, CanonVRD,
2327
2327
  Casio, Chapter#, Composite, DICOM, DJI, DNG, DV, DjVu, DjVu-Meta, Ducky,
2328
2328
  EPPIM, EXE, EXIF, ExifIFD, ExifTool, FITS, FLAC, FLIR, File, Flash,
2329
2329
  FlashPix, Font, FotoStation, FujiFilm, FujiIFD, GE, GIF, GIMP, GPS,
2330
- GSpherical, GeoTiff, GlobParamIFD, GoPro, GraphConv, H264, HP, HTC, HTML,
2331
- HTML-dc, HTML-ncc, HTML-office, HTML-prod, HTML-vw96, HTTP-equiv, ICC-chrm,
2332
- ICC-clrt, ICC-header, ICC-meas, ICC-meta, ICC-view, ICC_Profile,
2330
+ GSpherical, Garmin, GeoTiff, GlobParamIFD, GoPro, GraphConv, H264, HP, HTC,
2331
+ HTML, HTML-dc, HTML-ncc, HTML-office, HTML-prod, HTML-vw96, HTTP-equiv,
2332
+ ICC-chrm, ICC-clrt, ICC-header, ICC-meas, ICC-meta, ICC-view, ICC_Profile,
2333
2333
  ICC_Profile#, ID3, ID3v1, ID3v1_Enh, ID3v2_2, ID3v2_3, ID3v2_4, IFD0, IFD1,
2334
2334
  IPTC, IPTC#, ISO, ITC, InfiRay, Insta360, InteropIFD, ItemList, JFIF, JFXX,
2335
2335
  JPEG, JPEG-HDR, JPS, JSON, JUMBF, JVC, Jpeg2000, KDC_IFD, Keys, Kodak,
@@ -2349,7 +2349,7 @@ RMETA, RSRC, RTF, Radiance, Rawzor, Real, Real-CONT, Real-MDPR, Real-PROP,
2349
2349
  Real-RA3, Real-RA4, Real-RA5, Real-RJMD, Reconyx, Red, Ricoh, SPIFF, SR2,
2350
2350
  SR2DataIFD, SR2SubIFD, SRF#, SVG, Samsung, Sanyo, Scalado, Sigma, SigmaRaw,
2351
2351
  Sony, SonyIDC, Stim, SubIFD, System, Theora, Torrent, Track#, UserData,
2352
- VCalendar, VCard, Version0, VNote, Vorbis, WTV, XML, XMP, XMP-DICOM,
2352
+ VCalendar, VCard, VNote, Version0, Vorbis, WTV, XML, XMP, XMP-DICOM,
2353
2353
  XMP-Device, XMP-GAudio, XMP-GCamera, XMP-GCreations, XMP-GDepth, XMP-GFocus,
2354
2354
  XMP-GImage, XMP-GPano, XMP-GSpherical, XMP-LImage, XMP-MP, XMP-MP1,
2355
2355
  XMP-PixelLive, XMP-aas, XMP-acdsee, XMP-album, XMP-apple-fi, XMP-ast,
@@ -1,6 +1,6 @@
1
1
  Summary: perl module for image data extraction
2
2
  Name: perl-Image-ExifTool
3
- Version: 12.56
3
+ Version: 12.58
4
4
  Release: 1
5
5
  License: Artistic/GPL
6
6
  Group: Development/Libraries/Perl
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ExiftoolVendored
4
- VERSION = Gem::Version.new('12.56.0')
4
+ VERSION = Gem::Version.new('12.58.0')
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: exiftool_vendored
3
3
  version: !ruby/object:Gem::Version
4
- version: 12.56.0
4
+ version: 12.58.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthew McEachen
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2023-02-09 00:00:00.000000000 Z
12
+ date: 2023-03-15 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: exiftool