exiftool_vendored 13.02.0 → 13.04.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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 $advFmtSelf);
31
31
 
32
- $VERSION = '13.02';
32
+ $VERSION = '13.04';
33
33
  $RELEASE = '';
34
34
  @ISA = qw(Exporter);
35
35
  %EXPORT_TAGS = (
@@ -2583,7 +2583,7 @@ sub Options($$;@)
2583
2583
  warn("Can't set $param to undef\n");
2584
2584
  }
2585
2585
  } elsif (lc $param eq 'geodir') {
2586
- $Image::ExifTool::Geolocation::geoDir = $newVal; # (undocumented)
2586
+ $Image::ExifTool::Geolocation::geoDir = $newVal;
2587
2587
  } else {
2588
2588
  if ($param eq 'Escape') {
2589
2589
  # set ESCAPE_PROC
@@ -4404,6 +4404,7 @@ sub DoneExtract($)
4404
4404
  local $SIG{'__WARN__'} = \&SetWarning;
4405
4405
  undef $evalWarning;
4406
4406
  $$opts{GeolocMulti} = $$opts{Duplicates};
4407
+ $self->VPrint(0, "Geolocation arguments: '${arg}'\n");
4407
4408
  my ($cities, $dist) = Image::ExifTool::Geolocation::Geolocate($arg, $opts);
4408
4409
  delete $$opts{GeolocMulti};
4409
4410
  if ($cities and (@$cities < 2 or $dist or not $self->Warn('Multiple Geolocation cities are possible',2))) {
@@ -4660,74 +4661,56 @@ sub EncodeFileName($$;$)
4660
4661
  # References:
4661
4662
  # - https://learn.microsoft.com/en-us/dotnet/standard/io/file-path-formats
4662
4663
  # - https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation
4664
+ # GetFullPathName supported by Windows XP and later. It handles:
4665
+ # full path names EG: c:\foto\sub\abc.jpg
4666
+ # relative EG: .\abc.jpg, ..\abc.jpg
4667
+ # full UNC paths EG: \\server\share\abc.jpg
4668
+ # relative UNC paths EG: .\abc.jpg, ..\abc.jpg
4669
+ # Dos device paths EG: \\.\c:\fotoabc.jpg
4670
+ # relative path on other drives EG: z:abc.jpg (working dir on z: z:\foto called from c:\foto)
4671
+ # Wide chars EG: Chars that need UTF8.
4672
+ my $k32GetFullPathName;
4663
4673
  sub WindowsLongPath($$)
4664
4674
  {
4665
4675
  my ($self, $path) = @_;
4666
4676
  my $debug = $$self{OPTIONS}{Debug};
4667
4677
  my $out = $$self{OPTIONS}{TextOut};
4668
- my @fullParts;
4669
- my $prefixLen = 0;
4670
4678
 
4671
4679
  $debug and print $out "WindowsLongPath input : $path\n";
4672
- $path =~ tr(/)(\\); # convert slashes to backslashes
4673
- my @pathParts = split /\\/, $path;
4674
4680
 
4675
- if ($path =~ /^\\\\\?\\/ or # already a device path in the format we want
4676
- $path =~ s/^\\\\\.\\/\\\\?\\/) # convert //./ to //?/
4677
- {
4678
- # path is already long-path compatible
4679
- $prefixLen = 3; # path already contains prefix of 3 parts ('', '' and '?')
4680
- } elsif ($path =~ /[*?]/) {
4681
- return $path; # do nothing because we don't support wildcards
4682
- } elsif ($path =~ /^\\\\/) {
4683
- # UNC path starts with two slashes change to "\\?\UNC\"
4684
- splice @pathParts, 2, 0, '?', 'UNC';
4685
- $prefixLen = (@pathParts > 6 ? 6 : @pathParts); # ('', '', '?', 'UNC', <server>, <share>)
4686
- } elsif ($path =~ /^[a-z]:\\/i) {
4687
- # path is already absolute but we need to add the device path prefix
4688
- unshift @pathParts, '', '', '?';
4689
- $prefixLen = 4;
4690
- } elsif ({ eval { require Cwd } }) {
4691
- my $drive;
4692
- $drive = $1 if $pathParts[0] =~ s/^([a-z]:)//;
4693
- my $cwd = Cwd::getdcwd($drive); # ($drive is undef for current working drive)
4694
- $debug and print $out "WindowsLongPath getcwd: $cwd\n";
4695
- @fullParts = split /[\\\/]/, $cwd;
4696
- # UNC path starts with "\\", so first 2 elements are empty
4697
- # --> shift and put UNC in first element.
4698
- if (@fullParts > 1 and $fullParts[0] eq '' and $fullParts[1] eq '') {
4699
- shift @fullParts;
4700
- $fullParts[0] = 'UNC';
4701
- unshift @fullParts, '', '', '?';
4702
- $prefixLen = (@fullParts > 6 ? 6 : @fullParts);
4703
- } else {
4704
- $prefixLen = 1; # drive designator only
4681
+ for (;;) { # (cheap goto)
4682
+ $path =~ tr(/)(\\); # convert slashes to backslashes
4683
+ last if $path =~ /^\\\\\?\\/; # already a device path in the format we want
4684
+
4685
+ unless ($k32GetFullPathName) { # need to import (once) GetFullPathNameW
4686
+ last if defined $k32GetFullPathName;
4687
+ unless (eval { require Win32::API }) {
4688
+ $self->WarnOnce('Install Win32::API to use WindowsLongPath option');
4689
+ last;
4690
+ }
4691
+ $k32GetFullPathName = Win32::API->new('KERNEL32', 'GetFullPathNameW', 'PNPP', 'I');
4692
+ unless ($k32GetFullPathName) {
4693
+ $k32GetFullPathName = 0;
4694
+ $self->Warn('Error loading Win32::API GetFullPathNameW');
4695
+ last;
4696
+ }
4705
4697
  }
4706
- # if absolute path on current drive starts with "\"
4707
- # just keep prefix and drop the rest of the cwd
4708
- $#fullParts = $prefixLen - 1 if $pathParts[0] eq '';
4709
- } else {
4710
- $prefixLen = @pathParts; # (nothing more we can do)
4711
- }
4712
- # remove "." and ".." from path (not handled for device paths)
4713
- my $part;
4714
- foreach $part (@pathParts) {
4715
- if ($part eq '.') {
4716
- next;
4717
- } elsif ($part eq '') {
4718
- # only allow double slashes at start of path name (max 2)
4719
- push @fullParts, $part if not @fullParts or (@fullParts == 1 and $fullParts[0] eq '');
4720
- } elsif ($part eq '..') {
4721
- # step up one directory, but not into the prefix
4722
- pop @fullParts if @fullParts > $prefixLen;
4698
+ my $enc = $$self{OPTIONS}{CharsetFileName};
4699
+ my $encPath = $self->Encode($path, 'UTF16', 'II', $enc); # need to encode to UTF16
4700
+ my $lenReq = $k32GetFullPathName->Call($encPath,0,0,0) + 1; # first pass gets length required, +1 for safety (null?)
4701
+ my $fullPath = "\0" x $lenReq x 2; # create buffer to hold full path
4702
+ $k32GetFullPathName->Call($encPath, $lenReq, $fullPath, 0); # fullPath is UTF16 now
4703
+ $path = $self->Decode($fullPath, 'UTF16', 'II', $enc);
4704
+
4705
+ last if length($path) <= 247;
4706
+
4707
+ if ($path =~ /^\\\\/) {
4708
+ $path = '\\\\?\\UNC' . substr($path, 1);
4723
4709
  } else {
4724
- push @fullParts, $part;
4710
+ $path = '\\\\?\\' . $path;
4725
4711
  }
4712
+ last;
4726
4713
  }
4727
- $path = join '\\', @fullParts;
4728
- # add device path prefix ("\\?\") if path length near the limit (the most
4729
- # conservative limit I can find is 247, which is the limit on the directory name)
4730
- $path = '\\\\?\\' . $path unless $prefixLen > 1 or length($path) <= 247;
4731
4714
  $debug and print $out "WindowsLongPath return: $path\n";
4732
4715
  return $path;
4733
4716
  }
@@ -4861,16 +4844,16 @@ sub CreateDirectory($$)
4861
4844
  my $d2 = $dir; # (must make a copy in case EncodeFileName recodes it)
4862
4845
  if ($self->EncodeFileName($d2)) {
4863
4846
  # handle Windows Unicode directory names
4864
- unless (eval { require Win32::API }) {
4865
- $err = 'Install Win32::API to create directories with Unicode names';
4866
- last;
4867
- }
4868
4847
  unless (defined $k32CreateDir) {
4848
+ unless (eval { require Win32::API }) {
4849
+ $err = 'Install Win32::API to create directories with Unicode names';
4850
+ last;
4851
+ }
4869
4852
  $k32CreateDir = Win32::API->new('KERNEL32', 'CreateDirectoryW', 'PP', 'I');
4870
4853
  unless ($k32CreateDir) {
4871
4854
  $k32CreateDir = 0;
4872
4855
  # give this error once, then just "Error creating" for subsequent attempts
4873
- return 'Error accessing Win32::API::CreateDirectoryW';
4856
+ return 'Error loading Win32::API CreateDirectoryW';
4874
4857
  }
4875
4858
  }
4876
4859
  $success = $k32CreateDir->Call($d2, 0) if $k32CreateDir;
@@ -4928,13 +4911,13 @@ sub GetFileTime($$)
4928
4911
  return () if defined $k32GetFileTime;
4929
4912
  $k32GetFileTime = Win32::API->new('KERNEL32', 'GetFileTime', 'NPPP', 'I');
4930
4913
  unless ($k32GetFileTime) {
4931
- $self->Warn('Error calling Win32::API::GetFileTime');
4914
+ $self->Warn('Error loading Win32::API GetFileTime');
4932
4915
  $k32GetFileTime = 0;
4933
4916
  return ();
4934
4917
  }
4935
4918
  }
4936
4919
  unless ($k32GetFileTime->Call($win32Handle, $ctime, $atime, $mtime)) {
4937
- $self->Warn("Win32::API::GetFileTime returned " . Win32::GetLastError());
4920
+ $self->Warn("Win32::API GetFileTime returned " . Win32::GetLastError());
4938
4921
  return ();
4939
4922
  }
4940
4923
  # convert FILETIME structs to Unix seconds
@@ -5085,7 +5068,7 @@ sub IsSameID($$)
5085
5068
 
5086
5069
  #------------------------------------------------------------------------------
5087
5070
  # Get list of tags in specified group
5088
- # Inputs: 0) ExifTool ref, 1) group spec, 2) tag key or reference to list of tag keys
5071
+ # Inputs: 0) ExifTool ref, 1) group spec (case insensitive), 2) tag key or reference to list of tag keys
5089
5072
  # Returns: list of matching tags in list context, or first match in scalar context
5090
5073
  # Notes: Group spec may contain multiple groups separated by colons, each
5091
5074
  # possibly with a leading family number
@@ -6450,9 +6433,45 @@ sub ConvertDateTime($$)
6450
6433
  my $fmt = $$self{OPTIONS}{DateFormat};
6451
6434
  my $shift = $$self{OPTIONS}{GlobalTimeShift};
6452
6435
  if ($shift) {
6453
- my $dir = ($shift =~ s/^([-+])// and $1 eq '-') ? -1 : 1;
6454
6436
  my $offset = $$self{GLOBAL_TIME_OFFSET};
6455
- $offset or $offset = $$self{GLOBAL_TIME_OFFSET} = { };
6437
+ my ($g, $t, $dir, @matches);
6438
+ if ($shift =~ s/^((\d?[A-Z][-\w]*\w:)*)([A-Z][-\w]*\w)([-+])//i) {
6439
+ ($g, $t, $dir) = ($1, $3, ($4 eq '-' ? -1 : 1));
6440
+ } else {
6441
+ $dir = ($shift =~ s/^([-+])// and $1 eq '-') ? -1 : 1;
6442
+ }
6443
+ unless ($offset) {
6444
+ $offset = $$self{GLOBAL_TIME_OFFSET} = { };
6445
+ # (see forum16692 for a discussion about why this code was added)
6446
+ if ($t) {
6447
+ # determine initial shift from specified tag
6448
+ @matches = sort grep(/^$t( \(|$)/i, keys %{$$self{VALUE}});
6449
+ if ($g and @matches) {
6450
+ $g =~ s/:$//;
6451
+ @matches = $self->GroupMatches($g, \@matches);
6452
+ }
6453
+ }
6454
+ if (not @matches and $$self{TAGS_FROM_FILE} and $$self{OPTIONS}{RequestTags}) {
6455
+ # determine initial shift from first requested date/time tag
6456
+ my @reqDate = grep /date/i, @{$$self{OPTIONS}{RequestTags}};
6457
+ while (@reqDate) {
6458
+ $t = shift @reqDate;
6459
+ @matches = sort grep(/^$t( \(|$)/i, keys %{$$self{VALUE}});
6460
+ my $ti = $$self{TAG_INFO};
6461
+ for (; @matches; shift @matches) {
6462
+ # select the first tag that calls this routine in its PrintConv
6463
+ next unless $$ti{$matches[0]}{PrintConv};
6464
+ next unless $$ti{$matches[0]}{PrintConv} =~ /ConvertDateTime/;
6465
+ undef @reqDate;
6466
+ last;
6467
+ }
6468
+ }
6469
+ }
6470
+ if (@matches) {
6471
+ my $val = $self->GetValue($matches[0], 'ValueConv');
6472
+ ShiftTime($val, $shift, $dir, $offset) if defined $val;
6473
+ }
6474
+ }
6456
6475
  ShiftTime($date, $shift, $dir, $offset);
6457
6476
  }
6458
6477
  # only convert date if a format was specified and the date is recognizable
@@ -7952,6 +7971,10 @@ sub ProcessJPEG($$;$)
7952
7971
  SetByteOrder('II');
7953
7972
  my $tagTablePtr = GetTagTable('Image::ExifTool::InfiRay::Isothermal');
7954
7973
  $self->ProcessDirectory(\%dirInfo, $tagTablePtr);
7974
+ } elsif ($$segDataPt =~ /^SEAL\0/) {
7975
+ $dumpType = 'SEAL';
7976
+ DirStart(\%dirInfo, 5);
7977
+ $self->ProcessDirectory(\%dirInfo, GetTagTable("Image::ExifTool::XMP::SEAL"));
7955
7978
  }
7956
7979
  } elsif ($marker == 0xe9) { # APP9 (InfiRay, Media Jukebox)
7957
7980
  if ($$segDataPt =~ /^Media Jukebox\0/ and $length > 22) {
@@ -7967,6 +7990,10 @@ sub ProcessJPEG($$;$)
7967
7990
  SetByteOrder('II');
7968
7991
  my $tagTablePtr = GetTagTable('Image::ExifTool::InfiRay::Sensor');
7969
7992
  $self->ProcessDirectory(\%dirInfo, $tagTablePtr);
7993
+ } elsif ($$segDataPt =~ /^SEAL\0/) {
7994
+ $dumpType = 'SEAL';
7995
+ DirStart(\%dirInfo, 5);
7996
+ $self->ProcessDirectory(\%dirInfo, GetTagTable("Image::ExifTool::XMP::SEAL"));
7970
7997
  }
7971
7998
  } elsif ($marker == 0xea) { # APP10 (PhotoStudio Unicode comments)
7972
7999
  if ($$segDataPt =~ /^UNICODE\0/) {
@@ -8889,6 +8916,7 @@ sub GetTagInfo($$$;$$$)
8889
8916
  my ($valPt, $format, $count);
8890
8917
 
8891
8918
  my @infoArray = GetTagInfoList($tagTablePtr, $tagID);
8919
+ my $options = $$self{OPTIONS};
8892
8920
  # evaluate condition
8893
8921
  my $tagInfo;
8894
8922
  foreach $tagInfo (@infoArray) {
@@ -8907,9 +8935,9 @@ sub GetTagInfo($$$;$$$)
8907
8935
  }
8908
8936
  }
8909
8937
  # don't return Unknown tags unless that option is set (also see forum13716)
8910
- if ($$tagInfo{Unknown} and not $$self{OPTIONS}{Unknown} and not
8911
- ($$self{OPTIONS}{Verbose} or $$self{HTML_DUMP} or
8912
- ($$self{OPTIONS}{Validate} and not $$tagInfo{AddedUnknown})))
8938
+ if ($$tagInfo{Unknown} and not $$options{Unknown} and not
8939
+ ($$options{Verbose} or $$self{HTML_DUMP} or
8940
+ ($$options{Validate} and not $$tagInfo{AddedUnknown})))
8913
8941
  {
8914
8942
  return undef;
8915
8943
  }
@@ -8917,7 +8945,7 @@ sub GetTagInfo($$$;$$$)
8917
8945
  return $tagInfo;
8918
8946
  }
8919
8947
  # generate information for unknown tags (numerical only) if required
8920
- if (not $tagInfo and ($$self{OPTIONS}{Unknown} or $$self{OPTIONS}{Verbose}) and
8948
+ if (not $tagInfo and ($$options{Unknown} or $$options{Verbose} or $$self{HTML_DUMP}) and
8921
8949
  $tagID =~ /^\d+$/ and not $$self{NO_UNKNOWN})
8922
8950
  {
8923
8951
  my $printConv;
@@ -9102,6 +9130,7 @@ sub HandleTag($$$$;%)
9102
9130
  Base => $parms{Base},
9103
9131
  Multi => $$subdir{Multi},
9104
9132
  TagInfo => $tagInfo,
9133
+ IgnoreProp => $$subdir{IgnoreProp},
9105
9134
  RAF => $parms{RAF},
9106
9135
  );
9107
9136
  my $oldOrder = GetByteOrder();
@@ -809,8 +809,21 @@ Reference units for writing GPSSpeed when geotagging:
809
809
 
810
810
  Time shift to apply to all extracted date/time PrintConv values. Does not
811
811
  affect ValueConv values. Value is a date/time shift string (see
812
- L<Image::ExifTool::Shift(3pm)|Image::ExifTool::Shift.pl>), with a leading
813
- '-' for negative shifts. Default is undef.
812
+ L<Image::ExifTool::Shift(3pm)|Image::ExifTool::Shift.pl>) with a leading
813
+ '-' for negative shifts, or a tag name with option group prefix followed
814
+ by '+' or '-' then the shift string. Default is undef.
815
+
816
+ Note: When specifying a number of months and/or years to shift, the tag for
817
+ the starting date should be specified so the number of days can be
818
+ determined unambiguously. For example:
819
+
820
+ 'createdate-1:0:0 0:0:0' - shift back by the length of the
821
+ year before the CreateDate value
822
+ 'xmp:createdate+0:2:0 0' - shift forward by the length of
823
+ the 2 months after XMP:CreateDate
824
+
825
+ If the starting tag is not specified, or the specified tag isn't available,
826
+ then the shift is calculated based on the first shifted tag.
814
827
 
815
828
  =item Group#
816
829
 
@@ -2563,7 +2576,7 @@ Pentax, PhaseOne, PhotoCD, PhotoMechanic, Photoshop, PictureInfo,
2563
2576
  PostScript, PreviewIFD, PrintIM, ProfileIFD, Qualcomm, QuickTime, RAF, RAF2,
2564
2577
  RIFF, RMETA, RSRC, RTF, Radiance, Rawzor, Real, Real-CONT, Real-MDPR,
2565
2578
  Real-PROP, Real-RA3, Real-RA4, Real-RA5, Real-RJMD, Reconyx, Red, Ricoh,
2566
- SPIFF, SR2, SR2DataIFD, SR2SubIFD, SRF#, SVG, Samsung, Sanyo, Scalado,
2579
+ SEAL, SPIFF, SR2, SR2DataIFD, SR2SubIFD, SRF#, SVG, Samsung, Sanyo, Scalado,
2567
2580
  Sigma, SigmaRaw, Sony, SonyIDC, Stim, SubIFD, System, Theora, Torrent,
2568
2581
  Track#, UserData, VCalendar, VCard, VNote, Version0, Vorbis, WTV, XML, XMP,
2569
2582
  XMP-DICOM, XMP-Device, XMP-GAudio, XMP-GCamera, XMP-GContainer,
@@ -1,6 +1,6 @@
1
1
  Summary: perl module for image data extraction
2
2
  Name: perl-Image-ExifTool
3
- Version: 13.02
3
+ Version: 13.04
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('13.02.0')
4
+ VERSION = Gem::Version.new('13.04.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: 13.02.0
4
+ version: 13.04.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: 2024-11-11 00:00:00.000000000 Z
12
+ date: 2024-11-27 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: exiftool