exiftool_vendored 12.06.0 → 12.08.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.
Potentially problematic release.
This version of exiftool_vendored might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/bin/Changes +26 -2
- data/bin/MANIFEST +3 -0
- data/bin/META.json +1 -1
- data/bin/META.yml +1 -1
- data/bin/README +43 -42
- data/bin/exiftool +47 -43
- data/bin/lib/Image/ExifTool.pm +8 -5
- data/bin/lib/Image/ExifTool.pod +41 -40
- data/bin/lib/Image/ExifTool/BuildTagLookup.pm +3 -2
- data/bin/lib/Image/ExifTool/Canon.pm +31 -8
- data/bin/lib/Image/ExifTool/DarwinCore.pm +6 -2
- data/bin/lib/Image/ExifTool/EXE.pm +8 -5
- data/bin/lib/Image/ExifTool/Geotag.pm +2 -2
- data/bin/lib/Image/ExifTool/GoPro.pm +47 -22
- data/bin/lib/Image/ExifTool/IPTC.pm +1 -0
- data/bin/lib/Image/ExifTool/MacOS.pm +151 -37
- data/bin/lib/Image/ExifTool/Minolta.pm +4 -1
- data/bin/lib/Image/ExifTool/Nikon.pm +7 -1
- data/bin/lib/Image/ExifTool/Olympus.pm +6 -1
- data/bin/lib/Image/ExifTool/Panasonic.pm +12 -12
- data/bin/lib/Image/ExifTool/QuickTime.pm +8 -3
- data/bin/lib/Image/ExifTool/QuickTimeStream.pl +18 -8
- data/bin/lib/Image/ExifTool/RSRC.pm +17 -11
- data/bin/lib/Image/ExifTool/Sony.pm +52 -28
- data/bin/lib/Image/ExifTool/TagLookup.pm +4 -0
- data/bin/lib/Image/ExifTool/TagNames.pod +51 -33
- data/bin/lib/Image/ExifTool/XMP.pm +1 -1
- data/bin/perl-Image-ExifTool.spec +42 -41
- data/lib/exiftool_vendored/version.rb +1 -1
- metadata +7 -7
@@ -35,7 +35,7 @@ use Image::ExifTool::Sony;
|
|
35
35
|
use Image::ExifTool::Validate;
|
36
36
|
use Image::ExifTool::MacOS;
|
37
37
|
|
38
|
-
$VERSION = '3.
|
38
|
+
$VERSION = '3.38';
|
39
39
|
@ISA = qw(Exporter);
|
40
40
|
|
41
41
|
sub NumbersFirst($$);
|
@@ -633,7 +633,8 @@ L<http://www.metadataworkinggroup.org/> for the official MWG specification.
|
|
633
633
|
MacOS => q{
|
634
634
|
On MacOS systems, the there are additional MDItem and XAttr Finder tags that
|
635
635
|
may be extracted. These tags are not extracted by default -- they must be
|
636
|
-
specifically requested or enabled via an API option.
|
636
|
+
specifically requested or enabled via an API option. (Except when reading
|
637
|
+
MacOS "._" files directly, see below.)
|
637
638
|
|
638
639
|
The tables below list some of the tags that may be extracted, but ExifTool
|
639
640
|
will extract all available information even for tags not listed.
|
@@ -566,14 +566,27 @@ $VERSION = '4.39';
|
|
566
566
|
61494 => 'Canon CN-E 85mm T1.3 L F', #PH
|
567
567
|
61495 => 'Canon CN-E 135mm T2.2 L F', #PH
|
568
568
|
61496 => 'Canon CN-E 35mm T1.5 L F', #PH
|
569
|
-
|
570
|
-
61182
|
571
|
-
61182.
|
572
|
-
61182.
|
573
|
-
61182.
|
574
|
-
61182.
|
575
|
-
61182.
|
576
|
-
61182.
|
569
|
+
# see RFLensType tag for master list of 61182 RF lenses
|
570
|
+
61182 => 'Canon RF 50mm F1.2L USM or other Canon RF Lens',
|
571
|
+
61182.1 => 'Canon RF 24-105mm F4L IS USM',
|
572
|
+
61182.2 => 'Canon RF 28-70mm F2L USM',
|
573
|
+
61182.3 => 'Canon RF 35mm F1.8 MACRO IS STM',
|
574
|
+
61182.4 => 'Canon RF 85mm F1.2L USM',
|
575
|
+
61182.5 => 'Canon RF 85mm F1.2L USM DS',
|
576
|
+
61182.6 => 'Canon RF 24-70mm F2.8L IS USM',
|
577
|
+
61182.7 => 'Canon RF 15-35mm F2.8L IS USM',
|
578
|
+
61182.8 => 'Canon RF 24-240mm F4-6.3 IS USM',
|
579
|
+
61182.9 => 'Canon RF 70-200mm F2.8L IS USM',
|
580
|
+
61182.10 => 'Canon RF 600mm F11 IS STM',
|
581
|
+
61182.11 => 'Canon RF 600mm F11 IS STM + RF1.4x',
|
582
|
+
61182.12 => 'Canon RF 600mm F11 IS STM + RF2x',
|
583
|
+
61182.13 => 'Canon RF 800mm F11 IS STM',
|
584
|
+
61182.14 => 'Canon RF 800mm F11 IS STM + RF1.4x',
|
585
|
+
61182.15 => 'Canon RF 800mm F11 IS STM + RF2x',
|
586
|
+
61182.16 => 'Canon RF 24-105mm F4-7.1 IS STM',
|
587
|
+
61182.17 => 'Canon RF 100-500mm F4.5-7.1L IS USM',
|
588
|
+
61182.18 => 'Canon RF 100-500mm F4.5-7.1L IS USM + RF1.4x',
|
589
|
+
61182.19 => 'Canon RF 100-500mm F4.5-7.1L IS USM + RF2x',
|
577
590
|
65535 => 'n/a',
|
578
591
|
);
|
579
592
|
|
@@ -6694,7 +6707,17 @@ my %ciMaxFocal = (
|
|
6694
6707
|
264 => 'Canon RF 15-35mm F2.8L IS USM',
|
6695
6708
|
265 => 'Canon RF 24-240mm F4-6.3 IS USM',
|
6696
6709
|
266 => 'Canon RF 70-200mm F2.8L IS USM',
|
6710
|
+
268 => 'Canon RF 600mm F11 IS STM',
|
6711
|
+
269 => 'Canon RF 600mm F11 IS STM + RF1.4x',
|
6712
|
+
270 => 'Canon RF 600mm F11 IS STM + RF2x',
|
6713
|
+
271 => 'Canon RF 800mm F11 IS STM',
|
6714
|
+
272 => 'Canon RF 800mm F11 IS STM + RF1.4x',
|
6715
|
+
273 => 'Canon RF 800mm F11 IS STM + RF2x',
|
6697
6716
|
274 => 'Canon RF 24-105mm F4-7.1 IS STM',
|
6717
|
+
275 => 'Canon RF 100-500mm F4.5-7.1L IS USM',
|
6718
|
+
276 => 'Canon RF 100-500mm F4.5-7.1L IS USM + RF1.4x',
|
6719
|
+
277 => 'Canon RF 100-500mm F4.5-7.1L IS USM + RF2x',
|
6720
|
+
# Note: add new RF lenses to %canonLensTypes with ID 61182
|
6698
6721
|
},
|
6699
6722
|
},
|
6700
6723
|
);
|
@@ -44,14 +44,18 @@ my %event = (
|
|
44
44
|
Groups => { 2 => 'Time' },
|
45
45
|
Writable => 'string', # (so we can format this ourself)
|
46
46
|
Shift => 'Time',
|
47
|
-
# (
|
47
|
+
# (allow date/time or just time value)
|
48
48
|
ValueConv => 'Image::ExifTool::XMP::ConvertXMPDate($val)',
|
49
49
|
PrintConv => '$self->ConvertDateTime($val)',
|
50
50
|
ValueConvInv => 'Image::ExifTool::XMP::FormatXMPDate($val) or $val',
|
51
51
|
PrintConvInv => q{
|
52
52
|
my $v = $self->InverseDateTime($val,undef,1);
|
53
53
|
undef $Image::ExifTool::evalWarning;
|
54
|
-
return $v
|
54
|
+
return $v if $v;
|
55
|
+
my @a = ($val =~ /\d{1,2}/g); # get HH, MM and maybe SS
|
56
|
+
return undef unless @a >= 2;
|
57
|
+
$a[2] or $a[2] = 0;
|
58
|
+
return sprintf('%.2d:%.2d:%.2d', @a);
|
55
59
|
},
|
56
60
|
},
|
57
61
|
fieldNotes => { },
|
@@ -21,7 +21,7 @@ use strict;
|
|
21
21
|
use vars qw($VERSION);
|
22
22
|
use Image::ExifTool qw(:DataAccess :Utils);
|
23
23
|
|
24
|
-
$VERSION = '1.
|
24
|
+
$VERSION = '1.17';
|
25
25
|
|
26
26
|
sub ProcessPEResources($$);
|
27
27
|
sub ProcessPEVersion($$);
|
@@ -1009,7 +1009,7 @@ sub ProcessPEDict($$)
|
|
1009
1009
|
my $raf = $$dirInfo{RAF};
|
1010
1010
|
my $dataPt = $$dirInfo{DataPt};
|
1011
1011
|
my $dirLen = length($$dataPt);
|
1012
|
-
my ($pos, @sections, %dirInfo);
|
1012
|
+
my ($pos, @sections, %dirInfo, $rsrcFound);
|
1013
1013
|
|
1014
1014
|
# loop through all sections
|
1015
1015
|
for ($pos=0; $pos+40<=$dirLen; $pos+=40) {
|
@@ -1019,14 +1019,16 @@ sub ProcessPEDict($$)
|
|
1019
1019
|
my $offset = Get32u($dataPt, $pos + 20);
|
1020
1020
|
# remember the section offsets for the VirtualAddress lookup later
|
1021
1021
|
push @sections, { Base => $offset, Size => $size, VirtualAddress => $va };
|
1022
|
-
# save details of the first resource section
|
1022
|
+
# save details of the first resource section (or .text if .rsrc not found, ref forum11465)
|
1023
|
+
next unless ($name eq ".rsrc\0\0\0" and not $rsrcFound and defined($rsrcFound = 1)) or
|
1024
|
+
($name eq ".text\0\0\0" and not %dirInfo);
|
1023
1025
|
%dirInfo = (
|
1024
1026
|
RAF => $raf,
|
1025
1027
|
Base => $offset,
|
1026
1028
|
DirStart => 0, # (relative to Base)
|
1027
1029
|
DirLen => $size,
|
1028
1030
|
Sections => \@sections,
|
1029
|
-
)
|
1031
|
+
);
|
1030
1032
|
}
|
1031
1033
|
# process the first resource section
|
1032
1034
|
ProcessPEResources($et, \%dirInfo) or return 0 if %dirInfo;
|
@@ -1144,7 +1146,8 @@ sub ProcessEXE($$)
|
|
1144
1146
|
my $fileSize = ($cp - ($cblp ? 1 : 0)) * 512 + $cblp;
|
1145
1147
|
#(patch to accommodate observed 64-bit files)
|
1146
1148
|
#return 0 if $fileSize < 0x40 or $fileSize < $lfarlc;
|
1147
|
-
return 0 if $fileSize < 0x40;
|
1149
|
+
#return 0 if $fileSize < 0x40; (changed to warning in ExifTool 12.08)
|
1150
|
+
$et->Warn('Invalid file size in DOS header') if $fileSize < 0x40;
|
1148
1151
|
# read the Windows NE, PE or LE (virtual device driver) header
|
1149
1152
|
#if ($lfarlc == 0x40 and $fileSize > $lfanew + 2 and ...
|
1150
1153
|
if ($raf->Seek($lfanew, 0) and $raf->Read($buff, 0x40) and $buff =~ /^(NE|PE|LE)/) {
|
@@ -27,7 +27,7 @@ use vars qw($VERSION);
|
|
27
27
|
use Image::ExifTool qw(:Public);
|
28
28
|
use Image::ExifTool::GPS;
|
29
29
|
|
30
|
-
$VERSION = '1.
|
30
|
+
$VERSION = '1.63';
|
31
31
|
|
32
32
|
sub JITTER() { return 2 } # maximum time jitter
|
33
33
|
|
@@ -217,7 +217,7 @@ sub LoadTrackLog($$;$)
|
|
217
217
|
# (don't set format yet because we want to read HFDTE first)
|
218
218
|
$nmeaStart = 'B' ;
|
219
219
|
next;
|
220
|
-
} elsif (/^HFDTE(\d{2})(\d{2})(\d{2})/) {
|
220
|
+
} elsif (/^HFDTE(?:DATE:)?(\d{2})(\d{2})(\d{2})/) {
|
221
221
|
my $year = $3 + ($3 >= 70 ? 1900 : 2000);
|
222
222
|
$dateFlarm = Time::Local::timegm(0,0,0,$1,$2-1,$year);
|
223
223
|
$nmeaStart = 'B' ;
|
@@ -16,7 +16,7 @@ use vars qw($VERSION);
|
|
16
16
|
use Image::ExifTool qw(:DataAccess :Utils);
|
17
17
|
use Image::ExifTool::QuickTime;
|
18
18
|
|
19
|
-
$VERSION = '1.
|
19
|
+
$VERSION = '1.05';
|
20
20
|
|
21
21
|
sub ProcessGoPro($$$);
|
22
22
|
sub ProcessString($$$);
|
@@ -77,6 +77,9 @@ my %addUnits = (
|
|
77
77
|
Notes => 'accelerator readings in m/s2',
|
78
78
|
Binary => 1,
|
79
79
|
},
|
80
|
+
# ANGX (GPMF-GEOC) - seen -0.05 (fmt d, Max)
|
81
|
+
# ANGY (GPMF-GEOC) - seen 179.9 (fmt d, Max)
|
82
|
+
# ANGZ (GPMF-GEOC) - seen 0.152 (fmt d, Max)
|
80
83
|
ALLD => 'AutoLowLightDuration', #1 (gpmd) (untested)
|
81
84
|
# APTO (GPMF) - seen: 'RAW', 'DYNM' (fmt c)
|
82
85
|
ATTD => { #PH (Karma)
|
@@ -105,16 +108,14 @@ my %addUnits = (
|
|
105
108
|
},
|
106
109
|
# BRID (GPMF) - seen: 0 (fmt B)
|
107
110
|
# BROD (GPMF) - seen: 'ASK','' (fmt c)
|
111
|
+
# CALH (GPMF-GEOC) - seen 3040 (fmt L, Max)
|
112
|
+
# CALW (GPMF-GEOC) - seen 4056 (fmt L, Max)
|
108
113
|
CASN => 'CameraSerialNumber', #PH (GPMF - seen: 'C3221324545448', fmt c)
|
109
|
-
# CINF (GPMF) - seen: 0x67376be7709bc8876a8baf3940908618, 0xe230988539b30cf5f016627ae8fc5395
|
110
|
-
#
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
# TYPE=LLLLLfffBB
|
115
|
-
# SCAL=1000 1 1 1 1 1 1 1 1 1
|
116
|
-
Binary => 1,
|
117
|
-
},
|
114
|
+
# CINF (GPMF) - seen: 0x67376be7709bc8876a8baf3940908618, 0xe230988539b30cf5f016627ae8fc5395,
|
115
|
+
# 0x8bcbe424acc5b37d7d77001635198b3b (fmt B) (Camera INFormation?)
|
116
|
+
# CMOD (GPMF) - seen: 12,13,17 [12 360 video, 13 time-laps video, 17 JPEG] (fmt B)
|
117
|
+
# CRTX (GPMF-BACK/FRNT) - double[1]
|
118
|
+
# CRTY (GPMF-BACK/FRNT) - double[1]
|
118
119
|
CSEN => { #PH (Karma)
|
119
120
|
Name => 'CoyoteSense',
|
120
121
|
# UNIT=s,rad/s,rad/s,rad/s,g,g,g,,,,
|
@@ -122,13 +123,27 @@ my %addUnits = (
|
|
122
123
|
# SCAL=1000 1 1 1 1 1 1 1 1 1 1
|
123
124
|
Binary => 1,
|
124
125
|
},
|
126
|
+
CYTS => { #PH (Karma)
|
127
|
+
Name => 'CoyoteStatus',
|
128
|
+
# UNIT=s,,,,,rad,rad,rad,,
|
129
|
+
# TYPE=LLLLLfffBB
|
130
|
+
# SCAL=1000 1 1 1 1 1 1 1 1 1
|
131
|
+
Binary => 1,
|
132
|
+
},
|
125
133
|
DEVC => { #PH (gpmd,GPMF, fmt \0)
|
126
134
|
Name => 'DeviceContainer',
|
127
135
|
SubDirectory => { TagTable => 'Image::ExifTool::GoPro::GPMF' },
|
128
|
-
|
129
|
-
|
136
|
+
# (Max) DVID=1,DVNM='Global Settings',VERS,FMWR,LINF,CINF,CASN,MINF,MUID,CMOD,MTYP,OREN,
|
137
|
+
# DZOM,DZST,SMTR,PRTN,PTWB,PTSH,PTCL,EXPT,PIMX,PIMN,PTEV,RATE,SROT,ZFOV,VLTE,VLTA,
|
138
|
+
# EISE,EISA,AUPT,AUDO,BROD,BRID,PVUL,PRJT,SOFF
|
139
|
+
# (Max) DVID='GEOC',DVNM='Geometry Calibrations',SHFX,SHFY,SHFZ,ANGX,ANGY,ANGZ,CALW,CALH
|
140
|
+
# (Max) DVID='BACK',DVNM='Back Lens',KLNS,CTRX,CTRY,MFOV,SFTR
|
141
|
+
# (Max) DVID='FRNT',DVNM='Front Lens',KLNS,CTRX,CTRY,MFOV,SFTR
|
142
|
+
# (Max) DVID='HLMT',DVNM='Highlights'
|
143
|
+
},
|
144
|
+
# DVID (GPMF) - DeviceID; seen: 1 (fmt L), HLMT (fmt F), GEOC (fmt F), 'BACK' (fmt F, Max)
|
130
145
|
DVID => { Name => 'DeviceID', Unknown => 1 }, #2 (gpmd)
|
131
|
-
# DVNM (GPMF) seen: 'Video Global Settings' (fmt c), 'Highlights' (fmt c)
|
146
|
+
# DVNM (GPMF) seen: 'Video Global Settings' (fmt c), 'Highlights' (fmt c), 'Geometry Calibrations' (Max)
|
132
147
|
# DVNM (gpmd) seen: 'Camera' (Hero5), 'Hero6 Black' (Hero6), 'GoPro Karma v1.0' (Karma)
|
133
148
|
DVNM => 'DeviceName', #PH (n/c)
|
134
149
|
DZOM => { #PH (GPMF - seen: 'Y', fmt c)
|
@@ -136,10 +151,10 @@ my %addUnits = (
|
|
136
151
|
PrintConv => { N => 'No', Y => 'Yes' },
|
137
152
|
},
|
138
153
|
# DZST (GPMF) - seen: 0 (fmt L) (something to do with digital zoom maybe?)
|
139
|
-
EISA => { #PH (GPMF) - seen: 'Y','N',
|
154
|
+
EISA => { #PH (GPMF) - seen: 'Y','N','HS EIS','N/A' (fmt c) [N was for a time-lapse video]
|
140
155
|
Name => 'ElectronicImageStabilization',
|
141
156
|
},
|
142
|
-
# EISE (GPMF) - seen: 'Y' (fmt c)
|
157
|
+
# EISE (GPMF) - seen: 'Y','N' (fmt c)
|
143
158
|
EMPT => { Name => 'Empty', Unknown => 1 }, #2 (gpmd)
|
144
159
|
ESCS => { #PH (Karma)
|
145
160
|
Name => 'EscapeStatus',
|
@@ -215,7 +230,8 @@ my %addUnits = (
|
|
215
230
|
RawConv => '$val', # necessary to use scaled value instead of raw data as subdir data
|
216
231
|
SubDirectory => { TagTable => 'Image::ExifTool::GoPro::KBAT' },
|
217
232
|
},
|
218
|
-
#
|
233
|
+
# KLNS (GPMF-BACK/FRNT) - double[5] (fmt d, Max)
|
234
|
+
# LINF (GPMF) - seen: LAJ7061916601668,C3341326002180,C33632245450981 (fmt c) (Lens INFormation?)
|
219
235
|
LNED => { #PH (Karma)
|
220
236
|
Name => 'LocalPositionNED',
|
221
237
|
# UNIT=s,m,m,m,m/s,m/s,m/s
|
@@ -224,12 +240,13 @@ my %addUnits = (
|
|
224
240
|
Binary => 1,
|
225
241
|
},
|
226
242
|
MAGN => 'Magnetometer', #1 (gpmd) (units of uT)
|
243
|
+
# MFOV (GPMF-BACK/FRNT) - seen: 100 (fmt d, Max)
|
227
244
|
MINF => { #PH (GPMF - seen: HERO6 Black, fmt c)
|
228
245
|
Name => 'Model',
|
229
246
|
Groups => { 2 => 'Camera' },
|
230
247
|
Description => 'Camera Model Name',
|
231
248
|
},
|
232
|
-
# MTYP (GPMF) - seen: 0,1,11 [1 for time-lapse video, 11 for JPEG] (fmt B)
|
249
|
+
# MTYP (GPMF) - seen: 0,1,5,11 [1 for time-lapse video, 5 for 360 video, 11 for JPEG] (fmt B)
|
233
250
|
# MUID (GPMF) - seen: 3882563431 2278071152 967805802 411471936 0 0 0 0 (fmt L)
|
234
251
|
OREN => { #PH (GPMF - seen: 'U', fmt c)
|
235
252
|
Name => 'AutoRotation',
|
@@ -245,7 +262,7 @@ my %addUnits = (
|
|
245
262
|
PIMX => 'AutoISOMax', #PH (GPMF - seen: 1600, fmt L)
|
246
263
|
# PRAW (APP6) - seen: 0, 'N', 'Y' (fmt c)
|
247
264
|
PRES => 'PhotoResolution', #PH (APP6 - seen: '12MP_W')
|
248
|
-
# PRJT (APP6) - seen: 'GPRO' (fmt F, Hero8)
|
265
|
+
# PRJT (APP6) - seen: 'GPRO','EACO' (fmt F, Hero8, Max)
|
249
266
|
PRTN => { #PH (GPMF - seen: 'N', fmt c)
|
250
267
|
Name => 'ProTune',
|
251
268
|
PrintConv => {
|
@@ -257,7 +274,7 @@ my %addUnits = (
|
|
257
274
|
PTEV => 'ExposureCompensation', #PH (GPMF - seen: '0.0', fmt c)
|
258
275
|
PTSH => 'Sharpness', #PH (GPMF - seen: 'HIGH', fmt c)
|
259
276
|
PTWB => 'WhiteBalance', #PH (GPMF - seen: 'AUTO', fmt c)
|
260
|
-
# PVUL (APP6) - seen: 'F' (fmt c, Hero8)
|
277
|
+
# PVUL (APP6) - seen: 'F' (fmt c, Hero8, Max)
|
261
278
|
RATE => 'Rate', #PH (GPMF - seen: '0_5SEC', fmt c; APP6 - seen: '4_1SEC')
|
262
279
|
RMRK => { #2 (gpmd)
|
263
280
|
Name => 'Comments',
|
@@ -274,6 +291,10 @@ my %addUnits = (
|
|
274
291
|
# SCAL=1000 0.00999999977648258 0.00999999977648258 100
|
275
292
|
%addUnits,
|
276
293
|
},
|
294
|
+
# SFTR (GPMF-BACK/FRNT) - seen 0.999,1.00004 (fmt d, Max)
|
295
|
+
# SHFX (GPMF-GEOC) - seen 22.92 (fmt d, Max)
|
296
|
+
# SHFY (GPMF-GEOC) - seen 0.123 (fmt d, Max)
|
297
|
+
# SHFZ (GPMF-GEOC) - seen 36.06 (fmt d, Max)
|
277
298
|
SHUT => { #2 (gpmd)
|
278
299
|
Name => 'ExposureTimes',
|
279
300
|
PrintConv => q{
|
@@ -295,7 +316,8 @@ my %addUnits = (
|
|
295
316
|
ValueConv => '$self->Decode($val, "Latin")',
|
296
317
|
},
|
297
318
|
# SMTR (GPMF) - seen: 'N' (fmt c)
|
298
|
-
# SOFF (APP6) - seen: 0 (fmt L, Hero8)
|
319
|
+
# SOFF (APP6) - seen: 0 (fmt L, Hero8, Max)
|
320
|
+
# SROT (GPMF) - seen 20.60 (fmt f, Max)
|
299
321
|
STMP => { #1 (gpmd)
|
300
322
|
Name => 'TimeStamp',
|
301
323
|
ValueConv => '$val / 1e6',
|
@@ -338,7 +360,10 @@ my %addUnits = (
|
|
338
360
|
Unknown => 1,
|
339
361
|
ValueConv => '$self->Decode($val, "Latin")',
|
340
362
|
},
|
341
|
-
|
363
|
+
VERS => {
|
364
|
+
Name => 'MetadataVersion',
|
365
|
+
PrintConv => '$val =~ tr/ /./; $val',
|
366
|
+
},
|
342
367
|
VFOV => { #PH (GPMF - seen: 'W', fmt c)
|
343
368
|
Name => 'FieldOfView',
|
344
369
|
PrintConv => {
|
@@ -360,7 +385,7 @@ my %addUnits = (
|
|
360
385
|
Name => 'WhiteBalanceRGB',
|
361
386
|
Binary => 1,
|
362
387
|
},
|
363
|
-
# ZFOV (APP6) - seen: 148.34 (fmt f, Hero8)
|
388
|
+
# ZFOV (APP6,GPMF) - seen: 148.34, 0 (fmt f, Hero8, Max)
|
364
389
|
);
|
365
390
|
|
366
391
|
# GoPro GPS5 tags (ref 2) (Hero5,Hero6)
|
@@ -4,6 +4,7 @@
|
|
4
4
|
# Description: Read/write MacOS system tags
|
5
5
|
#
|
6
6
|
# Revisions: 2017/03/01 - P. Harvey Created
|
7
|
+
# 2020/10/13 - PH Added ability to read MacOS "._" files
|
7
8
|
#------------------------------------------------------------------------------
|
8
9
|
|
9
10
|
package Image::ExifTool::MacOS;
|
@@ -11,15 +12,38 @@ use strict;
|
|
11
12
|
use vars qw($VERSION);
|
12
13
|
use Image::ExifTool qw(:DataAccess :Utils);
|
13
14
|
|
14
|
-
$VERSION = '1.
|
15
|
+
$VERSION = '1.10';
|
15
16
|
|
16
17
|
sub MDItemLocalTime($);
|
18
|
+
sub ProcessATTR($$$);
|
17
19
|
|
18
20
|
my %mdDateInfo = (
|
19
21
|
ValueConv => \&MDItemLocalTime,
|
20
22
|
PrintConv => '$self->ConvertDateTime($val)',
|
21
23
|
);
|
22
24
|
|
25
|
+
# Information decoded from Mac OS sidecar files
|
26
|
+
%Image::ExifTool::MacOS::Main = (
|
27
|
+
GROUPS => { 0 => 'File', 1 => 'MacOS' },
|
28
|
+
NOTES => q{
|
29
|
+
Note that on some filesystems, MacOS creates sidecar files with names that
|
30
|
+
begin with "._". ExifTool will read these files if specified, and extract
|
31
|
+
the information listed in the following table without the need for extra
|
32
|
+
options, but these files are not writable directly.
|
33
|
+
},
|
34
|
+
2 => {
|
35
|
+
Name => 'RSRC',
|
36
|
+
SubDirectory => { TagTable => 'Image::ExifTool::RSRC::Main' },
|
37
|
+
},
|
38
|
+
9 => {
|
39
|
+
Name => 'ATTR',
|
40
|
+
SubDirectory => {
|
41
|
+
TagTable => 'Image::ExifTool::MacOS::XAttr',
|
42
|
+
ProcessProc => \&ProcessATTR,
|
43
|
+
},
|
44
|
+
},
|
45
|
+
);
|
46
|
+
|
23
47
|
# "mdls" tags (ref PH)
|
24
48
|
%Image::ExifTool::MacOS::MDItem = (
|
25
49
|
WRITE_PROC => \&Image::ExifTool::DummyWriteProc,
|
@@ -221,6 +245,8 @@ my %mdDateInfo = (
|
|
221
245
|
XAttr tags are extracted using the "xattr" utility. They are extracted if
|
222
246
|
any "XAttr*" tag or the MacOS group is specifically requested, or by setting
|
223
247
|
the L<XAttrTags|../ExifTool.html#XAttrTags> API option to 1 or the L<RequestAll|../ExifTool.html#RequestAll> API option to 2 or higher.
|
248
|
+
And they extracted by default from MacOS "._" files when reading
|
249
|
+
these files directly.
|
224
250
|
},
|
225
251
|
'com.apple.FinderInfo' => {
|
226
252
|
Name => 'XAttrFinderInfo',
|
@@ -486,8 +512,50 @@ sub ExtractMDItemTags($$)
|
|
486
512
|
$$et{INDENT} =~ s/\| $//;
|
487
513
|
}
|
488
514
|
|
515
|
+
|
489
516
|
#------------------------------------------------------------------------------
|
490
|
-
#
|
517
|
+
# Read MacOS XAttr value
|
518
|
+
# Inputs: 0) ExifTool object ref, 1) file name
|
519
|
+
sub ReadXAttrValue($$$$)
|
520
|
+
{
|
521
|
+
my ($et, $tagTablePtr, $tag, $val) = @_;
|
522
|
+
# add to our table if necessary
|
523
|
+
unless ($$tagTablePtr{$tag}) {
|
524
|
+
my $name;
|
525
|
+
# generate tag name from attribute name
|
526
|
+
if ($tag =~ /^com\.apple\.(.*)$/) {
|
527
|
+
($name = $1) =~ s/^metadata:_?k//;
|
528
|
+
$name =~ s/^metadata:(com_)?//;
|
529
|
+
} else {
|
530
|
+
$name = $tag;
|
531
|
+
}
|
532
|
+
$name =~ s/[.:_]([a-z])/\U$1/g;
|
533
|
+
$name = 'XAttr' . ucfirst $name;
|
534
|
+
my %tagInfo = ( Name => $name );
|
535
|
+
$tagInfo{Groups} = { 2 => 'Time' } if $tag=~/Date$/;
|
536
|
+
$et->VPrint(0, " [adding $tag]\n");
|
537
|
+
AddTagToTable($tagTablePtr, $tag, \%tagInfo);
|
538
|
+
}
|
539
|
+
if ($val =~ /^bplist0/) {
|
540
|
+
my %dirInfo = ( DataPt => \$val );
|
541
|
+
require Image::ExifTool::PLIST;
|
542
|
+
if (Image::ExifTool::PLIST::ProcessBinaryPLIST($et, \%dirInfo, $tagTablePtr)) {
|
543
|
+
return undef if ref $dirInfo{Value} eq 'HASH';
|
544
|
+
$val = $dirInfo{Value}
|
545
|
+
} else {
|
546
|
+
$et->Warn("Error decoding $$tagTablePtr{$tag}{Name}");
|
547
|
+
return undef;
|
548
|
+
}
|
549
|
+
}
|
550
|
+
if (not ref $val and ($val =~ /\0/ or length($val) > 200) or $tag eq 'XAttrMDLabel') {
|
551
|
+
my $buff = $val;
|
552
|
+
$val = \$buff;
|
553
|
+
}
|
554
|
+
return $val;
|
555
|
+
}
|
556
|
+
|
557
|
+
#------------------------------------------------------------------------------
|
558
|
+
# Read MacOS extended attribute tags using 'xattr' utility
|
491
559
|
# Inputs: 0) ExifTool object ref, 1) file name
|
492
560
|
sub ExtractXAttrTags($$)
|
493
561
|
{
|
@@ -517,39 +585,8 @@ sub ExtractXAttrTags($$)
|
|
517
585
|
$val .= pack('H*', $_);
|
518
586
|
next;
|
519
587
|
} elsif ($tag and defined $val) {
|
520
|
-
|
521
|
-
|
522
|
-
my $name;
|
523
|
-
# generate tag name from attribute name
|
524
|
-
if ($tag =~ /^com\.apple\.(.*)$/) {
|
525
|
-
($name = $1) =~ s/^metadata:_?k//;
|
526
|
-
$name =~ s/^metadata:(com_)?//;
|
527
|
-
} else {
|
528
|
-
$name = $tag;
|
529
|
-
}
|
530
|
-
$name =~ s/[.:_]([a-z])/\U$1/g;
|
531
|
-
$name = 'XAttr' . ucfirst $name;
|
532
|
-
my %tagInfo = ( Name => $name );
|
533
|
-
$tagInfo{Groups} = { 2 => 'Time' } if $tag=~/Date$/;
|
534
|
-
$et->VPrint(0, " [adding $tag]\n");
|
535
|
-
AddTagToTable($tagTablePtr, $tag, \%tagInfo);
|
536
|
-
}
|
537
|
-
if ($val =~ /^bplist0/) {
|
538
|
-
my %dirInfo = ( DataPt => \$val );
|
539
|
-
require Image::ExifTool::PLIST;
|
540
|
-
if (Image::ExifTool::PLIST::ProcessBinaryPLIST($et, \%dirInfo, $tagTablePtr)) {
|
541
|
-
next if ref $dirInfo{Value} eq 'HASH';
|
542
|
-
$val = $dirInfo{Value}
|
543
|
-
} else {
|
544
|
-
$et->Warn("Error decoding $$tagTablePtr{$tag}{Name}");
|
545
|
-
next;
|
546
|
-
}
|
547
|
-
}
|
548
|
-
if (not ref $val and ($val =~ /\0/ or length($val) > 200) or $tag eq 'XAttrMDLabel') {
|
549
|
-
my $buff = $val;
|
550
|
-
$val = \$buff;
|
551
|
-
}
|
552
|
-
$et->HandleTag($tagTablePtr, $tag, $val);
|
588
|
+
$val = ReadXAttrValue($et, $tagTablePtr, $tag, $val);
|
589
|
+
$et->HandleTag($tagTablePtr, $tag, $val) if defined $val;
|
553
590
|
undef $tag;
|
554
591
|
undef $val;
|
555
592
|
}
|
@@ -584,6 +621,82 @@ sub GetFileCreateDate($$)
|
|
584
621
|
delete $$et{SET_GROUP1};
|
585
622
|
}
|
586
623
|
|
624
|
+
#------------------------------------------------------------------------------
|
625
|
+
# Read ATTR metadata from "._" file
|
626
|
+
# Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref
|
627
|
+
# Return: 1 on success
|
628
|
+
# (ref https://www.swiftforensics.com/2018/11/the-dot-underscore-file-format.html)
|
629
|
+
sub ProcessATTR($$$)
|
630
|
+
{
|
631
|
+
my ($et, $dirInfo, $tagTablePtr) = @_;
|
632
|
+
my $dataPt = $$dirInfo{DataPt};
|
633
|
+
my $dataPos = $$dirInfo{DataPos};
|
634
|
+
my $dataLen = length $$dataPt;
|
635
|
+
|
636
|
+
$dataLen >= 58 and $$dataPt =~ /^.{34}ATTR/s or $et->Warn('Invalid ATTR header'), return 0;
|
637
|
+
my $entries = Get32u($dataPt, 66);
|
638
|
+
$et->VerboseDir('ATTR', $entries);
|
639
|
+
# (Note: The RAF is not in $dirInfo because it would break RSRC reading --
|
640
|
+
# the RSCR block uses relative offsets, while the ATTR block uses absolute! grrr!)
|
641
|
+
my $raf = $$et{RAF};
|
642
|
+
my $pos = 70; # first entry is after ATTR header
|
643
|
+
my $i;
|
644
|
+
for ($i=0; $i<$entries; ++$i) {
|
645
|
+
$pos + 12 > $dataLen and $et->Warn('Truncated ATTR entry'), last;
|
646
|
+
my $off = Get32u($dataPt, $pos);
|
647
|
+
my $len = Get32u($dataPt, $pos + 4);
|
648
|
+
my $n = Get8u($dataPt, $pos + 10); # number of characters in tag name
|
649
|
+
$pos + 11 + $n > $dataLen and $et->Warn('Truncated ATTR name'), last;
|
650
|
+
$off -= $dataPos; # convert to relative offset (grrr!)
|
651
|
+
$off < 0 or $off > $dataLen and $et->Warn('Invalid ATTR offset'), last;
|
652
|
+
my $tag = substr($$dataPt, $pos + 11, $n);
|
653
|
+
$tag =~ s/\0+$//; # remove null terminator
|
654
|
+
$off + $len > $dataLen and $et->Warn('Truncated ATTR value'), last;
|
655
|
+
my $val = ReadXAttrValue($et, $tagTablePtr, $tag, substr($$dataPt, $off, $len));
|
656
|
+
$et->HandleTag($tagTablePtr, $tag, $val,
|
657
|
+
DataPt => $dataPt,
|
658
|
+
DataPos => $dataPos,
|
659
|
+
Start => $off,
|
660
|
+
Size => $len,
|
661
|
+
) if defined $val;
|
662
|
+
$pos += (11 + $n + 3) & -4; # step to next entry (on even 4-byte boundary)
|
663
|
+
}
|
664
|
+
return 1;
|
665
|
+
}
|
666
|
+
|
667
|
+
#------------------------------------------------------------------------------
|
668
|
+
# Read information from a MacOS "._" sidecar file
|
669
|
+
# Inputs: 0) ExifTool ref, 1) dirInfo ref
|
670
|
+
# Returns: 1 on success, 0 if this wasn't a valid "._" file
|
671
|
+
# (ref https://www.swiftforensics.com/2018/11/the-dot-underscore-file-format.html)
|
672
|
+
sub ProcessMacOS($$)
|
673
|
+
{
|
674
|
+
my ($et, $dirInfo) = @_;
|
675
|
+
my $raf = $$dirInfo{RAF};
|
676
|
+
my ($hdr, $buff, $i);
|
677
|
+
|
678
|
+
return 0 unless $raf->Read($hdr, 26) == 26 and $hdr =~ /^\0\x05\x16\x07\0(.)\0\0Mac OS X /s;
|
679
|
+
my $ver = ord $1;
|
680
|
+
# (extension may be anything, so just echo back the incoming file extension if it exists)
|
681
|
+
$et->SetFileType(undef, undef, $$et{FILE_EXT});
|
682
|
+
$ver == 2 or $et->Warn("Unsupported file version $ver"), return 1;
|
683
|
+
SetByteOrder('MM');
|
684
|
+
my $tagTablePtr = GetTagTable('Image::ExifTool::MacOS::Main');
|
685
|
+
my $entries = Get16u(\$hdr, 0x18);
|
686
|
+
$et->VerboseDir('MacOS', $entries);
|
687
|
+
$raf->Read($hdr, $entries * 12) == $entries * 12 or $et->Warn('Truncated header'), return 1;
|
688
|
+
for ($i=0; $i<$entries; ++$i) {
|
689
|
+
my $pos = $i * 12;
|
690
|
+
my $tag = Get32u(\$hdr, $pos);
|
691
|
+
my $off = Get32u(\$hdr, $pos + 4);
|
692
|
+
my $len = Get32u(\$hdr, $pos + 8);
|
693
|
+
$len > 100000000 and $et->Warn('Record size too large'), last;
|
694
|
+
$raf->Seek($off,0) and $raf->Read($buff,$len) == $len or $et->Warn('Truncated record'), last;
|
695
|
+
$et->HandleTag($tagTablePtr, $tag, undef, DataPt => \$buff, DataPos => $off, Index => $i);
|
696
|
+
}
|
697
|
+
return 1;
|
698
|
+
}
|
699
|
+
|
587
700
|
1; # end
|
588
701
|
|
589
702
|
__END__
|
@@ -600,8 +713,9 @@ This module is used by Image::ExifTool
|
|
600
713
|
|
601
714
|
This module contains definitions required by Image::ExifTool to extract
|
602
715
|
MDItem* and XAttr* tags on MacOS systems using the "mdls" and "xattr"
|
603
|
-
utilities respectively.
|
604
|
-
|
716
|
+
utilities respectively. It also reads metadata directly from the MacOS "_."
|
717
|
+
sidecar files that are used on some filesystems to store file attributes.
|
718
|
+
Writable tags use "xattr", "setfile" or "osascript" for writing.
|
605
719
|
|
606
720
|
=head1 AUTHOR
|
607
721
|
|