exiftool_vendored 11.96.0 → 12.08.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of exiftool_vendored might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/bin/Changes +172 -2
- data/bin/MANIFEST +8 -0
- data/bin/META.json +1 -1
- data/bin/META.yml +1 -1
- data/bin/README +43 -42
- data/bin/exiftool +148 -69
- data/bin/lib/Image/ExifTool.pm +159 -110
- data/bin/lib/Image/ExifTool.pod +114 -87
- data/bin/lib/Image/ExifTool/AIFF.pm +2 -2
- data/bin/lib/Image/ExifTool/APE.pm +2 -2
- data/bin/lib/Image/ExifTool/BuildTagLookup.pm +13 -7
- data/bin/lib/Image/ExifTool/Canon.pm +37 -11
- data/bin/lib/Image/ExifTool/CanonCustom.pm +82 -16
- data/bin/lib/Image/ExifTool/DPX.pm +56 -2
- data/bin/lib/Image/ExifTool/DarwinCore.pm +20 -3
- data/bin/lib/Image/ExifTool/EXE.pm +8 -5
- data/bin/lib/Image/ExifTool/Exif.pm +15 -6
- data/bin/lib/Image/ExifTool/Font.pm +9 -2
- data/bin/lib/Image/ExifTool/GIF.pm +5 -0
- data/bin/lib/Image/ExifTool/GeoTiff.pm +2 -0
- data/bin/lib/Image/ExifTool/Geotag.pm +2 -2
- data/bin/lib/Image/ExifTool/GoPro.pm +56 -22
- data/bin/lib/Image/ExifTool/H264.pm +1 -1
- data/bin/lib/Image/ExifTool/HtmlDump.pm +2 -2
- data/bin/lib/Image/ExifTool/ID3.pm +91 -12
- data/bin/lib/Image/ExifTool/IPTC.pm +1 -0
- data/bin/lib/Image/ExifTool/Lang/de.pm +3 -1
- data/bin/lib/Image/ExifTool/Lang/es.pm +1 -1
- data/bin/lib/Image/ExifTool/M2TS.pm +44 -24
- data/bin/lib/Image/ExifTool/MacOS.pm +152 -38
- data/bin/lib/Image/ExifTool/Minolta.pm +6 -2
- data/bin/lib/Image/ExifTool/MinoltaRaw.pm +11 -10
- data/bin/lib/Image/ExifTool/Nikon.pm +162 -18
- data/bin/lib/Image/ExifTool/Olympus.pm +39 -17
- data/bin/lib/Image/ExifTool/PNG.pm +14 -3
- data/bin/lib/Image/ExifTool/PPM.pm +5 -5
- data/bin/lib/Image/ExifTool/Panasonic.pm +148 -14
- data/bin/lib/Image/ExifTool/PanasonicRaw.pm +33 -0
- data/bin/lib/Image/ExifTool/Parrot.pm +2 -1
- data/bin/lib/Image/ExifTool/Pentax.pm +3 -1
- data/bin/lib/Image/ExifTool/Photoshop.pm +2 -1
- data/bin/lib/Image/ExifTool/QuickTime.pm +269 -29
- data/bin/lib/Image/ExifTool/QuickTimeStream.pl +463 -75
- data/bin/lib/Image/ExifTool/README +21 -20
- data/bin/lib/Image/ExifTool/RIFF.pm +15 -3
- data/bin/lib/Image/ExifTool/RSRC.pm +17 -11
- data/bin/lib/Image/ExifTool/RTF.pm +12 -7
- data/bin/lib/Image/ExifTool/Ricoh.pm +19 -1
- data/bin/lib/Image/ExifTool/Shift.pl +1 -0
- data/bin/lib/Image/ExifTool/SigmaRaw.pm +40 -33
- data/bin/lib/Image/ExifTool/Sony.pm +425 -34
- data/bin/lib/Image/ExifTool/TagLookup.pm +1961 -1874
- data/bin/lib/Image/ExifTool/TagNames.pod +394 -86
- data/bin/lib/Image/ExifTool/Validate.pm +4 -4
- data/bin/lib/Image/ExifTool/WriteExif.pl +3 -2
- data/bin/lib/Image/ExifTool/WriteQuickTime.pl +23 -15
- data/bin/lib/Image/ExifTool/Writer.pl +44 -21
- data/bin/lib/Image/ExifTool/XMP.pm +42 -5
- data/bin/lib/Image/ExifTool/XMPStruct.pl +3 -1
- data/bin/lib/Image/ExifTool/ZISRAW.pm +123 -0
- data/bin/perl-Image-ExifTool.spec +42 -41
- data/lib/exiftool_vendored/version.rb +1 -1
- metadata +8 -7
@@ -13,7 +13,7 @@ package Image::ExifTool::Parrot;
|
|
13
13
|
use strict;
|
14
14
|
use vars qw($VERSION);
|
15
15
|
|
16
|
-
$VERSION = '1.
|
16
|
+
$VERSION = '1.01';
|
17
17
|
|
18
18
|
sub Process_mett($$$);
|
19
19
|
|
@@ -703,6 +703,7 @@ sub Process_mett($$$)
|
|
703
703
|
$et->HandleTag($tagTbl, $id, undef,
|
704
704
|
DataPt => $dataPt,
|
705
705
|
DataPos => $dataPos,
|
706
|
+
Base => $$dirInfo{Base},
|
706
707
|
Start => $pos,
|
707
708
|
Size => $size,
|
708
709
|
);
|
@@ -58,7 +58,7 @@ use Image::ExifTool::Exif;
|
|
58
58
|
use Image::ExifTool::GPS;
|
59
59
|
use Image::ExifTool::HP;
|
60
60
|
|
61
|
-
$VERSION = '3.
|
61
|
+
$VERSION = '3.34';
|
62
62
|
|
63
63
|
sub CryptShutterCount($$);
|
64
64
|
sub PrintFilter($$$);
|
@@ -338,6 +338,7 @@ sub DecodeAFPoints($$$$;$);
|
|
338
338
|
'8 63' => 'HD PENTAX-D FA 15-30mm F2.8 ED SDM WR', #PH
|
339
339
|
'8 64' => 'HD PENTAX-D FA* 50mm F1.4 SDM AW', #27
|
340
340
|
'8 65' => 'HD PENTAX-D FA 70-210mm F4 ED SDM WR', #PH
|
341
|
+
'8 66' => 'HD PENTAX-D FA 85mm F1.4 ED SDM AW', #James O'Neill
|
341
342
|
'8 196' => 'HD PENTAX-DA* 11-18mm F2.8 ED DC AW', #29
|
342
343
|
'8 197' => 'HD PENTAX-DA 55-300mm F4.5-6.3 ED PLM WR RE', #29
|
343
344
|
'8 198' => 'smc PENTAX-DA L 18-50mm F4-5.6 DC WR RE', #29
|
@@ -546,6 +547,7 @@ my %pentaxModelID = (
|
|
546
547
|
0x13222 => 'K-70', #29 (Ricoh)
|
547
548
|
0x1322c => 'KP', #29 (Ricoh)
|
548
549
|
0x13240 => 'K-1 Mark II', # (Ricoh)
|
550
|
+
0x13290 => 'WG-70', # (Ricoh)
|
549
551
|
);
|
550
552
|
|
551
553
|
# Pentax city codes - (PH, Optio WP)
|
@@ -28,7 +28,7 @@ use strict;
|
|
28
28
|
use vars qw($VERSION $AUTOLOAD $iptcDigestInfo);
|
29
29
|
use Image::ExifTool qw(:DataAccess :Utils);
|
30
30
|
|
31
|
-
$VERSION = '1.
|
31
|
+
$VERSION = '1.65';
|
32
32
|
|
33
33
|
sub ProcessPhotoshop($$$);
|
34
34
|
sub WritePhotoshop($$$);
|
@@ -982,6 +982,7 @@ sub ProcessPhotoshop($$$)
|
|
982
982
|
DataPos => $$dirInfo{DataPos},
|
983
983
|
Size => $size,
|
984
984
|
Start => $pos,
|
985
|
+
Base => $$dirInfo{Base},
|
985
986
|
Parent => $$dirInfo{DirName},
|
986
987
|
);
|
987
988
|
$size += 1 if $size & 0x01; # size is padded to an even # bytes
|
@@ -36,6 +36,7 @@
|
|
36
36
|
# 24) https://github.com/sergiomb2/libmp4v2/wiki/iTunesMetadata
|
37
37
|
# 25) https://cconcolato.github.io/mp4ra/atoms.html
|
38
38
|
# 26) https://github.com/SamsungVR/android_upload_sdk/blob/master/SDKLib/src/main/java/com/samsung/msca/samsungvr/sdk/UserVideo.java
|
39
|
+
# 27) https://exiftool.org/forum/index.php?topic=11517.0
|
39
40
|
#------------------------------------------------------------------------------
|
40
41
|
|
41
42
|
package Image::ExifTool::QuickTime;
|
@@ -46,7 +47,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
|
|
46
47
|
use Image::ExifTool::Exif;
|
47
48
|
use Image::ExifTool::GPS;
|
48
49
|
|
49
|
-
$VERSION = '2.
|
50
|
+
$VERSION = '2.53';
|
50
51
|
|
51
52
|
sub ProcessMOV($$;$);
|
52
53
|
sub ProcessKeys($$$);
|
@@ -105,7 +106,9 @@ my %mimeLookup = (
|
|
105
106
|
MQV => 'video/quicktime',
|
106
107
|
HEIC => 'image/heic',
|
107
108
|
HEVC => 'image/heic-sequence',
|
109
|
+
HEICS=> 'image/heic-sequence',
|
108
110
|
HEIF => 'image/heif',
|
111
|
+
HEIFS=> 'image/heif-sequence',
|
109
112
|
AVIF => 'image/avif', #PH (NC)
|
110
113
|
CRX => 'video/x-canon-crx', # (will get overridden)
|
111
114
|
);
|
@@ -418,7 +421,8 @@ my %eeBox = (
|
|
418
421
|
sbtl => { %eeStd },
|
419
422
|
data => { %eeStd },
|
420
423
|
camm => { %eeStd }, # (Insta360)
|
421
|
-
|
424
|
+
ctbx => { %eeStd }, # (GM cars)
|
425
|
+
'' => { 'gps ' => 'moov', 'GPS ' => 'main' }, # (no handler -- in top level 'moov' box, and main)
|
422
426
|
);
|
423
427
|
|
424
428
|
# QuickTime atoms
|
@@ -555,6 +559,20 @@ my %eeBox = (
|
|
555
559
|
Start => 16,
|
556
560
|
},
|
557
561
|
},
|
562
|
+
{ # (ref https://github.com/JamesHeinrich/getID3/blob/master/getid3/module.audio-video.quicktime.php)
|
563
|
+
Name => 'SensorData', # sensor data for the 360Fly
|
564
|
+
Condition => '$$valPt=~/^\xef\xe1\x58\x9a\xbb\x77\x49\xef\x80\x95\x27\x75\x9e\xb1\xdc\x6f/ and $$self{OPTIONS}{ExtractEmbedded}',
|
565
|
+
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Tags360Fly' },
|
566
|
+
},
|
567
|
+
{
|
568
|
+
Name => 'SensorData',
|
569
|
+
Condition => '$$valPt=~/^\xef\xe1\x58\x9a\xbb\x77\x49\xef\x80\x95\x27\x75\x9e\xb1\xdc\x6f/',
|
570
|
+
Notes => 'raw 360Fly sensor data without ExtractEmbedded option',
|
571
|
+
RawConv => q{
|
572
|
+
$self->WarnOnce('Use the ExtractEmbedded option to decode timed SensorData',3);
|
573
|
+
return \$val;
|
574
|
+
},
|
575
|
+
},
|
558
576
|
{ #PH (Canon CR3)
|
559
577
|
Name => 'PreviewImage',
|
560
578
|
Condition => '$$valPt=~/^\xea\xf4\x2b\x5e\x1c\x98\x4b\x88\xb9\xfb\xb7\xdc\x40\x6e\x4d\x16/',
|
@@ -589,6 +607,11 @@ my %eeBox = (
|
|
589
607
|
Groups => { 2 => 'Preview' },
|
590
608
|
Binary => 1,
|
591
609
|
},
|
610
|
+
'thm ' => { #PH (70mai A800)
|
611
|
+
Name => 'ThumbnailImage',
|
612
|
+
Groups => { 2 => 'Preview' },
|
613
|
+
Binary => 1,
|
614
|
+
},
|
592
615
|
ardt => { #PH
|
593
616
|
Name => 'ARDroneFile',
|
594
617
|
ValueConv => 'length($val) > 4 ? substr($val,4) : $val', # remove length
|
@@ -667,6 +690,11 @@ my %eeBox = (
|
|
667
690
|
},
|
668
691
|
# gpsa - seen hex "01 20 00 00" (DuDuBell M1, VSYS M6L)
|
669
692
|
# gsea - 20 bytes hex "05 00's..." (DuDuBell M1) "05 08 02 01 ..." (VSYS M6L)
|
693
|
+
'GPS ' => { # GPS data written by 70mai dashcam (parsed in QuickTimeStream.pl)
|
694
|
+
Name => 'GPSDataList2',
|
695
|
+
Unknown => 1,
|
696
|
+
Binary => 1,
|
697
|
+
},
|
670
698
|
);
|
671
699
|
|
672
700
|
# MPEG-4 'ftyp' atom
|
@@ -962,7 +990,7 @@ my %eeBox = (
|
|
962
990
|
%Image::ExifTool::QuickTime::CleanAperture = (
|
963
991
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
|
964
992
|
GROUPS => { 2 => 'Video' },
|
965
|
-
FORMAT => '
|
993
|
+
FORMAT => 'rational64s',
|
966
994
|
0 => 'CleanApertureWidth',
|
967
995
|
1 => 'CleanApertureHeight',
|
968
996
|
2 => 'CleanApertureOffsetX',
|
@@ -1307,6 +1335,7 @@ my %eeBox = (
|
|
1307
1335
|
Format => 'fixed32s[9]',
|
1308
1336
|
Notes => 'writable for the video track via the Composite Rotation tag',
|
1309
1337
|
Writable => 1,
|
1338
|
+
Protected => 1,
|
1310
1339
|
Permanent => 1,
|
1311
1340
|
# only set rotation if image size is non-zero
|
1312
1341
|
RawConvInv => \&GetMatrixStructure,
|
@@ -1371,8 +1400,8 @@ my %eeBox = (
|
|
1371
1400
|
},
|
1372
1401
|
ValueConvInv => q{
|
1373
1402
|
require Image::ExifTool::XMP;
|
1374
|
-
$
|
1375
|
-
$val =~ s/([-+]\d{2}):(\d{2})$/$1$2
|
1403
|
+
my $tmp = Image::ExifTool::XMP::FormatXMPDate($val);
|
1404
|
+
($val = $tmp) =~ s/([-+]\d{2}):(\d{2})$/$1$2/ if defined $tmp; # remove time zone colon
|
1376
1405
|
return $val;
|
1377
1406
|
},
|
1378
1407
|
PrintConv => '$self->ConvertDateTime($val)',
|
@@ -1628,10 +1657,14 @@ my %eeBox = (
|
|
1628
1657
|
Avoid => 1,
|
1629
1658
|
Format => 'string', # (necessary to remove the trailing NULL)
|
1630
1659
|
},
|
1631
|
-
date => {
|
1660
|
+
date => {
|
1632
1661
|
Name => 'DateTimeOriginal',
|
1633
1662
|
Description => 'Date/Time Original',
|
1634
1663
|
Groups => { 2 => 'Time' },
|
1664
|
+
Notes => q{
|
1665
|
+
Apple Photos has been reported to show a crazy date/time for some MP4 files
|
1666
|
+
containing this tag, but perhaps only if it is missing a time zone
|
1667
|
+
}, #forum10690/11125
|
1635
1668
|
Shift => 'Time',
|
1636
1669
|
ValueConv => q{
|
1637
1670
|
require Image::ExifTool::XMP;
|
@@ -1853,6 +1886,25 @@ my %eeBox = (
|
|
1853
1886
|
ByteOrder => 'LittleEndian',
|
1854
1887
|
},
|
1855
1888
|
},
|
1889
|
+
# ---- Garmin ---- (ref PH)
|
1890
|
+
uuid => [{
|
1891
|
+
Name => 'GarminSoftware', # (NC)
|
1892
|
+
Condition => '$$valPt =~ /^VIRBactioncamera/',
|
1893
|
+
RawConv => 'substr($val, 16)',
|
1894
|
+
RawConvInv => '"VIRBactioncamera$val"',
|
1895
|
+
},{
|
1896
|
+
# have seen "28 f3 11 e2 b7 91 4f 6f 94 e2 4f 5d ea cb 3c 01" for RicohThetaZ1 accelerometer RADT data (not yet decoded)
|
1897
|
+
Name => 'UUID-Unknown',
|
1898
|
+
Writable => 0,
|
1899
|
+
%unknownInfo,
|
1900
|
+
}],
|
1901
|
+
pmcc => {
|
1902
|
+
Name => 'GarminSettings',
|
1903
|
+
ValueConv => 'substr($val, 4)',
|
1904
|
+
ValueConvInv => '"\0\0\0\x01$val"',
|
1905
|
+
},
|
1906
|
+
# hmtp - "\0\0\0\x01" followed by 408 bytes of zero
|
1907
|
+
# vrin - "\0\0\0\x01" followed by 8 bytes of zero
|
1856
1908
|
# ---- GoPro ---- (ref PH)
|
1857
1909
|
GoPr => 'GoProType', # (Hero3+)
|
1858
1910
|
FIRM => { Name => 'FirmwareVersion', Avoid => 1 }, # (Hero4)
|
@@ -1866,7 +1918,7 @@ my %eeBox = (
|
|
1866
1918
|
# SETT? 12 bytes (Hero4)
|
1867
1919
|
# MUID? 32 bytes (Hero4, starts with serial number hash)
|
1868
1920
|
# HMMT? 404 bytes (Hero4, all zero)
|
1869
|
-
# BCID? 26 bytes (Hero5, all zero)
|
1921
|
+
# BCID? 26 bytes (Hero5, all zero), 36 bytes GoPro Max
|
1870
1922
|
# GUMI? 16 bytes (Hero5)
|
1871
1923
|
"FOV\0" => 'FieldOfView', #forum8938 (Hero2) seen: "Wide"
|
1872
1924
|
GPMF => {
|
@@ -2036,6 +2088,63 @@ my %eeBox = (
|
|
2036
2088
|
ProcessProc => \&Image::ExifTool::ProcessTIFF, # (because ProcessMOV is default)
|
2037
2089
|
},
|
2038
2090
|
},
|
2091
|
+
'@mak' => { Name => 'Make', Avoid => 1 },
|
2092
|
+
'@mod' => { Name => 'Model', Avoid => 1 },
|
2093
|
+
'@swr' => { Name => 'SoftwareVersion', Avoid => 1 },
|
2094
|
+
'@day' => {
|
2095
|
+
Name => 'ContentCreateDate',
|
2096
|
+
Notes => q{
|
2097
|
+
some stupid Ricoh programmer used the '@' symbol instead of the copyright
|
2098
|
+
symbol in these tag ID's for the Ricoh Theta Z1 and maybe other models
|
2099
|
+
},
|
2100
|
+
Groups => { 2 => 'Time' },
|
2101
|
+
Shift => 'Time',
|
2102
|
+
Avoid => 1,
|
2103
|
+
# handle values in the form "2010-02-12T13:27:14-0800"
|
2104
|
+
ValueConv => q{
|
2105
|
+
require Image::ExifTool::XMP;
|
2106
|
+
$val = Image::ExifTool::XMP::ConvertXMPDate($val);
|
2107
|
+
$val =~ s/([-+]\d{2})(\d{2})$/$1:$2/; # add colon to timezone if necessary
|
2108
|
+
return $val;
|
2109
|
+
},
|
2110
|
+
ValueConvInv => q{
|
2111
|
+
require Image::ExifTool::XMP;
|
2112
|
+
my $tmp = Image::ExifTool::XMP::FormatXMPDate($val);
|
2113
|
+
($val = $tmp) =~ s/([-+]\d{2}):(\d{2})$/$1$2/ if defined $tmp; # remove time zone colon
|
2114
|
+
return $val;
|
2115
|
+
},
|
2116
|
+
PrintConv => '$self->ConvertDateTime($val)',
|
2117
|
+
PrintConvInv => '$self->InverseDateTime($val)',
|
2118
|
+
},
|
2119
|
+
'@xyz' => { #PH (iPhone 3GS)
|
2120
|
+
Name => 'GPSCoordinates',
|
2121
|
+
Groups => { 2 => 'Location' },
|
2122
|
+
Avoid => 1,
|
2123
|
+
ValueConv => \&ConvertISO6709,
|
2124
|
+
ValueConvInv => \&ConvInvISO6709,
|
2125
|
+
PrintConv => \&PrintGPSCoordinates,
|
2126
|
+
PrintConvInv => \&PrintInvGPSCoordinates,
|
2127
|
+
},
|
2128
|
+
# RDT1 - pairs of int32u_BE, starting at byte 8: "458275 471846"
|
2129
|
+
# RDT2 - pairs of int32u_BE, starting at byte 8: "472276 468526"
|
2130
|
+
# RDT3 - pairs of int32u_BE, starting at byte 8: "876603 482191"
|
2131
|
+
# RDT4 - pairs of int32u_BE, starting at byte 8: "1955 484612"
|
2132
|
+
# RDT6 - empty
|
2133
|
+
# RDT7 - empty
|
2134
|
+
# RDT8 - empty
|
2135
|
+
# RDT9 - only 16-byte header?
|
2136
|
+
# the boxes below all have a similar header (little-endian):
|
2137
|
+
# 0 int32u - number of records
|
2138
|
+
# 4 ? - "1e 00"
|
2139
|
+
# 6 int16u - record length in bytes
|
2140
|
+
# 8 ? - "23 01 00 00 00 00 00 00"
|
2141
|
+
# 16 - start of records (each record ends in an int64u timestamp in ns)
|
2142
|
+
# RDTA - float[4],ts: "-0.31289672 -0.2245330 11.303817 0 775.780"
|
2143
|
+
# RDTB - float[4],ts: "-0.04841613 -0.2166595 0.0724792 0 775.780"
|
2144
|
+
# RDTC - float[4],ts: "27.60925 -27.10037 -13.27285 0 775.829"
|
2145
|
+
# RDTD - int16s[3],ts: "353 -914 16354 0 775.829"
|
2146
|
+
# RDTG - ts: "775.825"
|
2147
|
+
# RDTI - float[4],ts: "0.00165951 0.005770059 0.06838259 0.1744695 775.862"
|
2039
2148
|
# ---- Samsung ----
|
2040
2149
|
vndr => 'Vendor', #PH (Samsung PL70)
|
2041
2150
|
SDLN => 'PlayMode', #PH (NC, Samsung ST80 "SEQ_PLAY")
|
@@ -2512,6 +2621,7 @@ my %eeBox = (
|
|
2512
2621
|
Name => 'Rotation',
|
2513
2622
|
Format => 'int8u',
|
2514
2623
|
Writable => 'int8u',
|
2624
|
+
Protected => 1,
|
2515
2625
|
ValueConv => '$val * 90',
|
2516
2626
|
ValueConvInv => 'int($val / 90 + 0.5)',
|
2517
2627
|
},
|
@@ -2543,6 +2653,7 @@ my %eeBox = (
|
|
2543
2653
|
Name => 'PixelAspectRatio',
|
2544
2654
|
Format => 'int32u',
|
2545
2655
|
Writable => 'int32u',
|
2656
|
+
Protected => 1,
|
2546
2657
|
},
|
2547
2658
|
rloc => {
|
2548
2659
|
Name => 'RelativeLocation',
|
@@ -2551,7 +2662,7 @@ my %eeBox = (
|
|
2551
2662
|
},
|
2552
2663
|
clap => {
|
2553
2664
|
Name => 'CleanAperture',
|
2554
|
-
Format => '
|
2665
|
+
Format => 'rational64s',
|
2555
2666
|
Notes => '4 numbers: width, height, left and top',
|
2556
2667
|
},
|
2557
2668
|
hvcC => {
|
@@ -2889,10 +3000,25 @@ my %eeBox = (
|
|
2889
3000
|
"\xa9grp" => 'Grouping',
|
2890
3001
|
"\xa9lyr" => 'Lyrics',
|
2891
3002
|
"\xa9nam" => 'Title',
|
2892
|
-
# "\xa9st3" ? #10
|
2893
3003
|
"\xa9too" => 'Encoder',
|
2894
3004
|
"\xa9trk" => 'Track',
|
2895
3005
|
"\xa9wrt" => 'Composer',
|
3006
|
+
#
|
3007
|
+
# the following tags written by AtomicParsley 0.9.6
|
3008
|
+
# (ref https://exiftool.org/forum/index.php?topic=11455.0)
|
3009
|
+
#
|
3010
|
+
"\xa9st3" => 'Subtitle',
|
3011
|
+
"\xa9con" => 'Conductor',
|
3012
|
+
"\xa9sol" => 'Soloist',
|
3013
|
+
"\xa9arg" => 'Arranger',
|
3014
|
+
"\xa9ope" => 'OriginalArtist',
|
3015
|
+
"\xa9dir" => 'Director',
|
3016
|
+
"\xa9ard" => 'ArtDirector',
|
3017
|
+
"\xa9sne" => 'SoundEngineer',
|
3018
|
+
"\xa9prd" => 'Producer',
|
3019
|
+
"\xa9xpd" => 'ExecutiveProducer',
|
3020
|
+
sdes => 'StoreDescription',
|
3021
|
+
#
|
2896
3022
|
'----' => {
|
2897
3023
|
Name => 'iTunesInfo',
|
2898
3024
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::iTunesInfo' },
|
@@ -2901,18 +3027,29 @@ my %eeBox = (
|
|
2901
3027
|
covr => { Name => 'CoverArt', Groups => { 2 => 'Preview' } },
|
2902
3028
|
cpil => { #10
|
2903
3029
|
Name => 'Compilation',
|
2904
|
-
Format => 'int8u', #23
|
3030
|
+
Format => 'int8u', #27 (ref 23 contradicts what AtomicParsley actually writes, which is int8s)
|
3031
|
+
Writable => 'int8s',
|
2905
3032
|
PrintConv => { 0 => 'No', 1 => 'Yes' },
|
2906
3033
|
},
|
2907
3034
|
disk => {
|
2908
3035
|
Name => 'DiskNumber',
|
2909
3036
|
Format => 'undef', # (necessary to prevent decoding as string!)
|
2910
|
-
ValueConv =>
|
2911
|
-
|
3037
|
+
ValueConv => q{
|
3038
|
+
return \$val unless length($val) >= 6;
|
3039
|
+
my @a = unpack 'x2nn', $val;
|
3040
|
+
return $a[1] ? join(' of ', @a) : $a[0];
|
3041
|
+
},
|
3042
|
+
ValueConvInv => q{
|
3043
|
+
my @a = $val =~ /\d+/g;
|
3044
|
+
return undef if @a == 0 or @a > 2;
|
3045
|
+
push @a, 0 if @a == 1;
|
3046
|
+
return pack('n3', 0, @a);
|
3047
|
+
},
|
2912
3048
|
},
|
2913
3049
|
pgap => { #10
|
2914
3050
|
Name => 'PlayGap',
|
2915
3051
|
Format => 'int8u', #23
|
3052
|
+
Writable => 'int8s', #27
|
2916
3053
|
PrintConv => {
|
2917
3054
|
0 => 'Insert Gap',
|
2918
3055
|
1 => 'No Gap',
|
@@ -2920,13 +3057,26 @@ my %eeBox = (
|
|
2920
3057
|
},
|
2921
3058
|
tmpo => {
|
2922
3059
|
Name => 'BeatsPerMinute',
|
2923
|
-
|
3060
|
+
# marked as boolean but really int16u in my sample
|
3061
|
+
# (but written as int16s by iTunes and AtomicParsley, ref forum11506)
|
3062
|
+
Format => 'int16u',
|
3063
|
+
Writable => 'int16s',
|
2924
3064
|
},
|
2925
3065
|
trkn => {
|
2926
3066
|
Name => 'TrackNumber',
|
2927
3067
|
Format => 'undef', # (necessary to prevent decoding as string!)
|
2928
|
-
ValueConv =>
|
2929
|
-
|
3068
|
+
ValueConv => q{
|
3069
|
+
return \$val unless length($val) >= 6;
|
3070
|
+
my @a = unpack 'x2nn', $val;
|
3071
|
+
return $a[1] ? join(' of ', @a) : $a[0];
|
3072
|
+
},
|
3073
|
+
# (see forum11501 for discussion about the format used)
|
3074
|
+
ValueConvInv => q{
|
3075
|
+
my @a = $val =~ /\d+/g;
|
3076
|
+
return undef if @a == 0 or @a > 2;
|
3077
|
+
push @a, 0 if @a == 1;
|
3078
|
+
return pack('n4', 0, @a, 0);
|
3079
|
+
},
|
2930
3080
|
},
|
2931
3081
|
#
|
2932
3082
|
# Note: it is possible that the tags below are not being decoded properly
|
@@ -2935,6 +3085,7 @@ my %eeBox = (
|
|
2935
3085
|
akID => { #10
|
2936
3086
|
Name => 'AppleStoreAccountType',
|
2937
3087
|
Format => 'int8u', #24
|
3088
|
+
Writable => 'int8s', #27
|
2938
3089
|
PrintConv => {
|
2939
3090
|
0 => 'iTunes',
|
2940
3091
|
1 => 'AOL',
|
@@ -2945,12 +3096,14 @@ my %eeBox = (
|
|
2945
3096
|
atID => { #10 (or TV series)
|
2946
3097
|
Name => 'AlbumTitleID',
|
2947
3098
|
Format => 'int32u',
|
3099
|
+
Writable => 'int32s', #27
|
2948
3100
|
},
|
2949
3101
|
auth => { Name => 'Author', Groups => { 2 => 'Author' } },
|
2950
3102
|
catg => 'Category', #7
|
2951
3103
|
cnID => { #10
|
2952
3104
|
Name => 'AppleStoreCatalogID',
|
2953
3105
|
Format => 'int32u',
|
3106
|
+
Writable => 'int32s', #27
|
2954
3107
|
},
|
2955
3108
|
cprt => { Name => 'Copyright', Groups => { 2 => 'Author' } },
|
2956
3109
|
dscp => { Name => 'Description', Avoid => 1 },
|
@@ -2958,22 +3111,28 @@ my %eeBox = (
|
|
2958
3111
|
gnre => { #10
|
2959
3112
|
Name => 'Genre',
|
2960
3113
|
Avoid => 1,
|
2961
|
-
# (Note:
|
3114
|
+
# (Note: see https://exiftool.org/forum/index.php?topic=11537.0)
|
3115
|
+
Format => 'undef',
|
3116
|
+
ValueConv => 'unpack("n",$val)',
|
3117
|
+
ValueConvInv => '$val =~ /^\d+$/ ? pack("n",$val) : undef',
|
2962
3118
|
PrintConv => q{
|
2963
3119
|
return $val unless $val =~ /^\d+$/;
|
2964
3120
|
require Image::ExifTool::ID3;
|
2965
3121
|
Image::ExifTool::ID3::PrintGenre($val - 1); # note the "- 1"
|
2966
3122
|
},
|
2967
3123
|
PrintConvInv => q{
|
3124
|
+
return $val if $val =~ /^[0-9]+$/;
|
2968
3125
|
require Image::ExifTool::ID3;
|
2969
3126
|
my $id = Image::ExifTool::ID3::GetGenreID($val);
|
2970
|
-
return defined $id
|
2971
|
-
|
3127
|
+
return unless defined $id and $id =~ /^\d+$/;
|
3128
|
+
return $id + 1;
|
3129
|
+
},
|
2972
3130
|
},
|
2973
3131
|
egid => 'EpisodeGlobalUniqueID', #7
|
2974
3132
|
geID => { #10
|
2975
3133
|
Name => 'GenreID',
|
2976
3134
|
Format => 'int32u',
|
3135
|
+
Writable => 'int32s', #27
|
2977
3136
|
SeparateTable => 1,
|
2978
3137
|
# the following lookup is based on http://itunes.apple.com/WebObjects/MZStoreServices.woa/ws/genres
|
2979
3138
|
# (see scripts/parse_genre to parse genre JSON file from above)
|
@@ -5626,6 +5785,7 @@ my %eeBox = (
|
|
5626
5785
|
hdvd => { #10
|
5627
5786
|
Name => 'HDVideo',
|
5628
5787
|
Format => 'int8u', #24
|
5788
|
+
Writable => 'int8s', #27
|
5629
5789
|
PrintConv => { 0 => 'No', 1 => 'Yes' },
|
5630
5790
|
},
|
5631
5791
|
keyw => 'Keyword', #7
|
@@ -5633,18 +5793,21 @@ my %eeBox = (
|
|
5633
5793
|
pcst => { #7
|
5634
5794
|
Name => 'Podcast',
|
5635
5795
|
Format => 'int8u', #23
|
5796
|
+
Writable => 'int8s', #27
|
5636
5797
|
PrintConv => { 0 => 'No', 1 => 'Yes' },
|
5637
5798
|
},
|
5638
5799
|
perf => 'Performer',
|
5639
5800
|
plID => { #10 (or TV season)
|
5640
5801
|
Name => 'PlayListID',
|
5641
5802
|
Format => 'int8u', # actually int64u, but split it up
|
5803
|
+
Writable => 'int32s', #27
|
5642
5804
|
},
|
5643
5805
|
purd => 'PurchaseDate', #7
|
5644
5806
|
purl => 'PodcastURL', #7
|
5645
5807
|
rtng => { #10
|
5646
5808
|
Name => 'Rating',
|
5647
5809
|
Format => 'int8u', #23
|
5810
|
+
Writable => 'int8s', #27
|
5648
5811
|
PrintConv => {
|
5649
5812
|
0 => 'none',
|
5650
5813
|
1 => 'Explicit',
|
@@ -5655,6 +5818,7 @@ my %eeBox = (
|
|
5655
5818
|
sfID => { #10
|
5656
5819
|
Name => 'AppleStoreCountry',
|
5657
5820
|
Format => 'int32u',
|
5821
|
+
Writable => 'int32s', #27
|
5658
5822
|
SeparateTable => 1,
|
5659
5823
|
PrintConv => { #21
|
5660
5824
|
143441 => 'United States', # US
|
@@ -5823,6 +5987,7 @@ my %eeBox = (
|
|
5823
5987
|
stik => { #10
|
5824
5988
|
Name => 'MediaType',
|
5825
5989
|
Format => 'int8u', #23
|
5990
|
+
Writable => 'int8s', #27
|
5826
5991
|
PrintConvColumns => 2,
|
5827
5992
|
PrintConv => { #(http://weblog.xanga.com/gryphondwb/615474010/iphone-ringtones---what-did-itunes-741-really-do.html)
|
5828
5993
|
0 => 'Movie (old)', #forum9059 (was Movie)
|
@@ -5844,6 +6009,7 @@ my %eeBox = (
|
|
5844
6009
|
tves => { #7/10
|
5845
6010
|
Name => 'TVEpisode',
|
5846
6011
|
Format => 'int32u',
|
6012
|
+
Writable => 'int32s', #27
|
5847
6013
|
},
|
5848
6014
|
tvnn => 'TVNetworkName', #7
|
5849
6015
|
tvsh => 'TVShow', #10
|
@@ -5854,7 +6020,8 @@ my %eeBox = (
|
|
5854
6020
|
yrrc => 'Year', #(ffmpeg source)
|
5855
6021
|
itnu => { #PH (iTunes 10.5)
|
5856
6022
|
Name => 'iTunesU',
|
5857
|
-
Format => '
|
6023
|
+
Format => 'int8u', #27
|
6024
|
+
Writable => 'int8s', #27
|
5858
6025
|
Description => 'iTunes U',
|
5859
6026
|
PrintConv => { 0 => 'No', 1 => 'Yes' },
|
5860
6027
|
},
|
@@ -5904,6 +6071,27 @@ my %eeBox = (
|
|
5904
6071
|
PrintConv => \&PrintGPSCoordinates,
|
5905
6072
|
PrintConvInv => \&PrintInvGPSCoordinates,
|
5906
6073
|
},
|
6074
|
+
# the following tags written by iTunes 12.5.1.21
|
6075
|
+
# (ref https://www.ventismedia.com/mantis/view.php?id=14963
|
6076
|
+
# https://community.mp3tag.de/t/x-mp4-new-tag-problems/19488)
|
6077
|
+
"\xa9wrk" => 'Work', #PH
|
6078
|
+
"\xa9mvn" => 'MovementName', #PH
|
6079
|
+
"\xa9mvi" => { #PH
|
6080
|
+
Name => 'MovementNumber',
|
6081
|
+
Format => 'int16u', #27
|
6082
|
+
Writable => 'int16s', #27
|
6083
|
+
},
|
6084
|
+
"\xa9mvc" => { #PH
|
6085
|
+
Name => 'MovementCount',
|
6086
|
+
Format => 'int16u', #27
|
6087
|
+
Writable => 'int16s', #27
|
6088
|
+
},
|
6089
|
+
shwm => { #PH
|
6090
|
+
Name => 'ShowMovement',
|
6091
|
+
Format => 'int8u', #27
|
6092
|
+
Writable => 'int8s', #27
|
6093
|
+
PrintConv => { 0 => 'No', 1 => 'Yes' },
|
6094
|
+
},
|
5907
6095
|
);
|
5908
6096
|
|
5909
6097
|
# tag decoded from timed face records
|
@@ -6123,6 +6311,21 @@ my %eeBox = (
|
|
6123
6311
|
'detected-face.roll-angle' => { Name => 'DetectedFaceRollAngle', Writable => 0 },
|
6124
6312
|
# (fiel)com.apple.quicktime.detected-face.yaw-angle (dtyp=23, float)
|
6125
6313
|
'detected-face.yaw-angle' => { Name => 'DetectedFaceYawAngle', Writable => 0 },
|
6314
|
+
#
|
6315
|
+
# seen in Apple ProRes RAW file
|
6316
|
+
#
|
6317
|
+
# (mdta)com.apple.proapps.manufacturer (eg. "Sony")
|
6318
|
+
# (mdta)com.apple.proapps.exif.{Exif}.FNumber (float, eg. 1.0)
|
6319
|
+
# (mdta)org.smpte.rdd18.lens.irisfnumber (eg. "F1.0")
|
6320
|
+
# (mdta)com.apple.proapps.exif.{Exif}.ShutterSpeedValue (float, eg. 1.006)
|
6321
|
+
# (mdta)org.smpte.rdd18.camera.shutterspeed_angle (eg. "179.2deg")
|
6322
|
+
# (mdta)org.smpte.rdd18.camera.neutraldensityfilterwheelsetting (eg. "ND1")
|
6323
|
+
# (mdta)org.smpte.rdd18.camera.whitebalance (eg. "4300K")
|
6324
|
+
# (mdta)com.apple.proapps.exif.{Exif}.ExposureIndex (float, eg. 4000)
|
6325
|
+
# (mdta)org.smpte.rdd18.camera.isosensitivity (eg. "4000")
|
6326
|
+
# (mdta)com.apple.proapps.image.{TIFF}.Make (eg. "Atmos")
|
6327
|
+
# (mdta)com.apple.proapps.image.{TIFF}.Model (eg. "ShogunInferno")
|
6328
|
+
# (mdta)com.apple.proapps.image.{TIFF}.Software (eg. "9.0")
|
6126
6329
|
);
|
6127
6330
|
|
6128
6331
|
# iTunes info ('----') atoms
|
@@ -6663,7 +6866,7 @@ my %eeBox = (
|
|
6663
6866
|
#
|
6664
6867
|
# AudioFormat Offset Child atoms
|
6665
6868
|
# ----------- ------ ----------------
|
6666
|
-
# mp4a 52 * wave, chan, esds, SA3D(Insta360 spherical video params
|
6869
|
+
# mp4a 52 * wave, chan, esds, SA3D(Insta360 spherical video params?,also GoPro Max)
|
6667
6870
|
# in24 52 wave, chan
|
6668
6871
|
# "ms\0\x11" 52 wave
|
6669
6872
|
# sowt 52 chan
|
@@ -6700,6 +6903,7 @@ my %eeBox = (
|
|
6700
6903
|
# alac - 28 bytes
|
6701
6904
|
# adrm - AAX DRM atom? 148 bytes
|
6702
6905
|
# aabd - AAX unknown 17kB (contains 'aavd' strings)
|
6906
|
+
# SA3D - written by Garmin VIRB360
|
6703
6907
|
);
|
6704
6908
|
|
6705
6909
|
# AMR decode config box (ref 3)
|
@@ -6730,13 +6934,28 @@ my %eeBox = (
|
|
6730
6934
|
Name => 'SchemeInfo',
|
6731
6935
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::SchemeInfo' },
|
6732
6936
|
},
|
6937
|
+
enda => {
|
6938
|
+
Name => 'Endianness',
|
6939
|
+
Format => 'int16u',
|
6940
|
+
PrintConv => {
|
6941
|
+
0 => 'Big-endian (Motorola, MM)',
|
6942
|
+
1 => 'Little-endian (Intel, II)',
|
6943
|
+
},
|
6944
|
+
},
|
6733
6945
|
# skcr
|
6734
|
-
# enda
|
6735
6946
|
);
|
6736
6947
|
|
6737
6948
|
%Image::ExifTool::QuickTime::Wave = (
|
6738
6949
|
PROCESS_PROC => \&ProcessMOV,
|
6739
6950
|
frma => 'PurchaseFileFormat',
|
6951
|
+
enda => {
|
6952
|
+
Name => 'Endianness',
|
6953
|
+
Format => 'int16u',
|
6954
|
+
PrintConv => {
|
6955
|
+
0 => 'Big-endian (Motorola, MM)',
|
6956
|
+
1 => 'Little-endian (Intel, II)',
|
6957
|
+
},
|
6958
|
+
},
|
6740
6959
|
# "ms\0\x11" - 20 bytes
|
6741
6960
|
);
|
6742
6961
|
|
@@ -7171,6 +7390,20 @@ my %eeBox = (
|
|
7171
7390
|
#
|
7172
7391
|
ftab => { Name => 'FontTable', Format => 'undef', ValueConv => 'substr($val, 5)' },
|
7173
7392
|
name => { Name => 'OtherName', Format => 'undef', ValueConv => 'substr($val, 4)' },
|
7393
|
+
# mrlh = GM header?
|
7394
|
+
# mrlv = GM data
|
7395
|
+
# mrld = GM data (448-byte records):
|
7396
|
+
# 0 - int32u count
|
7397
|
+
# 4 - int32u ? (related to units) 0=none,1=m/km,2=L,3=kph,4=C,7=deg,8=rpm,9=kPa,10=G,11=V,15=Nm,16=%
|
7398
|
+
# 8 - int32u ? (0,1,3,4,5)
|
7399
|
+
# 12 - string[64] units
|
7400
|
+
# 76 - int32u ? (1,3,7,15)
|
7401
|
+
# 80 - int32u 0
|
7402
|
+
# 84 - undef[4] ?
|
7403
|
+
# 88 - int16u[6] ?
|
7404
|
+
# 100 - undef[32] ?
|
7405
|
+
# 132 - string[64] measurement name
|
7406
|
+
# 196 - string[64] measurement name
|
7174
7407
|
);
|
7175
7408
|
|
7176
7409
|
# MP4 data information box (ref 5)
|
@@ -7467,6 +7700,7 @@ my %eeBox = (
|
|
7467
7700
|
1 => 'QuickTime:HandlerType',
|
7468
7701
|
},
|
7469
7702
|
Writable => 1,
|
7703
|
+
Protected => 1,
|
7470
7704
|
WriteAlso => {
|
7471
7705
|
MatrixStructure => 'Image::ExifTool::QuickTime::GetRotationMatrix($val)',
|
7472
7706
|
},
|
@@ -8232,6 +8466,11 @@ sub HandleItemInfo($)
|
|
8232
8466
|
if ($buff =~ /^(MM\0\x2a|II\x2a\0)/) {
|
8233
8467
|
$et->Warn('Missing Exif header');
|
8234
8468
|
$start = 0;
|
8469
|
+
} elsif ($buff =~ /^Exif\0\0/) {
|
8470
|
+
# (haven't seen this yet, but it is just a matter of time
|
8471
|
+
# until someone screws it up like this)
|
8472
|
+
$et->Warn('Missing Exif header size');
|
8473
|
+
$start = 6;
|
8235
8474
|
} else {
|
8236
8475
|
my $n = unpack('N', $buff);
|
8237
8476
|
$start = 4 + $n; # skip "Exif\0\0" header if it exists
|
@@ -8296,7 +8535,7 @@ sub EEWarn($)
|
|
8296
8535
|
#------------------------------------------------------------------------------
|
8297
8536
|
# Get quicktime format from flags word
|
8298
8537
|
# Inputs: 0) quicktime atom flags, 1) data length
|
8299
|
-
# Returns:
|
8538
|
+
# Returns: ExifTool format string
|
8300
8539
|
sub QuickTimeFormat($$)
|
8301
8540
|
{
|
8302
8541
|
my ($flags, $len) = @_;
|
@@ -8523,7 +8762,7 @@ sub ProcessKeys($$$)
|
|
8523
8762
|
my $ns = substr($$dataPt, $pos + 4, 4);
|
8524
8763
|
my $tag = substr($$dataPt, $pos + 8, $len - 8);
|
8525
8764
|
$tag =~ s/\0.*//s; # truncate at null
|
8526
|
-
$tag =~ s/^com\.apple\.quicktime
|
8765
|
+
$tag =~ s/^com\.(apple\.quicktime\.)?// if $ns eq 'mdta'; # remove apple quicktime domain
|
8527
8766
|
$tag = "Tag_$ns" unless $tag;
|
8528
8767
|
# (I have some samples where the tag is a reversed ItemList or UserData tag ID)
|
8529
8768
|
my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag);
|
@@ -8555,9 +8794,10 @@ sub ProcessKeys($$$)
|
|
8555
8794
|
$$newInfo{Groups} = $groups ? { %$groups } : { };
|
8556
8795
|
$$newInfo{Groups}{$_} or $$newInfo{Groups}{$_} = $$tagTablePtr{GROUPS}{$_} foreach 0..2;
|
8557
8796
|
$$newInfo{Groups}{1} = 'Keys';
|
8558
|
-
} elsif ($tag =~ /^[-\w. ]+$/) {
|
8797
|
+
} elsif ($tag =~ /^[-\w. ]+$/ or $tag =~ /\w{4}/) {
|
8559
8798
|
# create info for tags with reasonable id's
|
8560
8799
|
my $name = ucfirst $tag;
|
8800
|
+
$name =~ tr/-0-9a-zA-Z_. //dc;
|
8561
8801
|
$name =~ s/[. ]+(.?)/\U$1/g;
|
8562
8802
|
$name =~ s/_([a-z])/_\U$1/g;
|
8563
8803
|
$name =~ s/([a-z])_([A-Z])/$1$2/g;
|
@@ -8578,7 +8818,7 @@ sub ProcessKeys($$$)
|
|
8578
8818
|
if ($newInfo) {
|
8579
8819
|
AddTagToTable($itemList, $id, $newInfo);
|
8580
8820
|
$msg or $msg = '';
|
8581
|
-
$out and print $out "$$et{INDENT}Added ItemList Tag $id = $tag$msg\n";
|
8821
|
+
$out and print $out "$$et{INDENT}Added ItemList Tag $id = ($ns) $tag$msg\n";
|
8582
8822
|
}
|
8583
8823
|
$pos += $len;
|
8584
8824
|
++$index;
|
@@ -9033,10 +9273,10 @@ ItemID: foreach $id (keys %$items) {
|
|
9033
9273
|
}
|
9034
9274
|
}
|
9035
9275
|
if ($ctry or $lang) {
|
9036
|
-
$
|
9037
|
-
if ($
|
9276
|
+
my $langCode = GetLangCode($lang, $ctry);
|
9277
|
+
if ($langCode) {
|
9038
9278
|
# get tagInfo for other language
|
9039
|
-
$langInfo = GetLangInfoQT($et, $tagInfo, $
|
9279
|
+
$langInfo = GetLangInfoQT($et, $tagInfo, $langCode);
|
9040
9280
|
# save other language tag ID's so we can delete later if necessary
|
9041
9281
|
if ($langInfo) {
|
9042
9282
|
$$tagInfo{OtherLang} or $$tagInfo{OtherLang} = [ ];
|
@@ -9053,7 +9293,7 @@ ItemID: foreach $id (keys %$items) {
|
|
9053
9293
|
Size => $len,
|
9054
9294
|
Format => $format,
|
9055
9295
|
Index => $index,
|
9056
|
-
Extra => sprintf(", Type='${type}', Flags=0x%x
|
9296
|
+
Extra => sprintf(", Type='${type}', Flags=0x%x, Lang=0x%.4x",$flags,$lang),
|
9057
9297
|
) if $verbose;
|
9058
9298
|
# use "Keys" in path instead of ItemList if this was defined by a Keys tag
|
9059
9299
|
my $isKey = $$tagInfo{Groups} && $$tagInfo{Groups}{1} && $$tagInfo{Groups}{1} eq 'Keys';
|