exiftool_vendored 12.56.0 → 12.58.0

Sign up to get free protection for your applications and to get access to all the features.
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