exiftool_vendored 10.65.0 → 11.41.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 +818 -19
- data/bin/MANIFEST +38 -0
- data/bin/META.json +1 -1
- data/bin/META.yml +1 -1
- data/bin/README +48 -44
- data/bin/arg_files/exif2xmp.args +4 -1
- data/bin/arg_files/gps2xmp.args +4 -1
- data/bin/arg_files/iptcCore.args +8 -0
- data/bin/arg_files/xmp2exif.args +4 -1
- data/bin/arg_files/xmp2gps.args +4 -1
- data/bin/config_files/dji.config +131 -0
- data/bin/config_files/example.config +6 -2
- data/bin/config_files/gps2utm.config +256 -256
- data/bin/config_files/nksc.config +146 -0
- data/bin/config_files/picasa_faces.config +382 -382
- data/bin/exiftool +688 -408
- data/bin/fmt_files/gpx.fmt +10 -6
- data/bin/fmt_files/gpx_wpt.fmt +10 -6
- data/bin/fmt_files/kml.fmt +8 -5
- data/bin/lib/File/RandomAccess.pm +48 -8
- data/bin/lib/File/RandomAccess.pod +21 -2
- data/bin/lib/Image/ExifTool.pm +645 -256
- data/bin/lib/Image/ExifTool.pod +219 -164
- data/bin/lib/Image/ExifTool/AES.pm +1 -1
- data/bin/lib/Image/ExifTool/AFCP.pm +3 -8
- data/bin/lib/Image/ExifTool/AIFF.pm +12 -4
- data/bin/lib/Image/ExifTool/APE.pm +1 -1
- data/bin/lib/Image/ExifTool/APP12.pm +1 -1
- data/bin/lib/Image/ExifTool/ASF.pm +19 -6
- data/bin/lib/Image/ExifTool/Apple.pm +13 -5
- data/bin/lib/Image/ExifTool/Audible.pm +1 -1
- data/bin/lib/Image/ExifTool/BMP.pm +1 -1
- data/bin/lib/Image/ExifTool/BPG.pm +17 -15
- data/bin/lib/Image/ExifTool/BZZ.pm +1 -1
- data/bin/lib/Image/ExifTool/BigTIFF.pm +30 -15
- data/bin/lib/Image/ExifTool/BuildTagLookup.pm +103 -52
- data/bin/lib/Image/ExifTool/Canon.pm +684 -112
- data/bin/lib/Image/ExifTool/CanonCustom.pm +119 -9
- data/bin/lib/Image/ExifTool/CanonRaw.pm +1 -1
- data/bin/lib/Image/ExifTool/CanonVRD.pm +13 -26
- data/bin/lib/Image/ExifTool/CaptureOne.pm +1 -1
- data/bin/lib/Image/ExifTool/Casio.pm +1 -1
- data/bin/lib/Image/ExifTool/Charset.pm +1 -1
- data/bin/lib/Image/ExifTool/DICOM.pm +12 -5
- data/bin/lib/Image/ExifTool/DJI.pm +51 -3
- data/bin/lib/Image/ExifTool/DNG.pm +15 -8
- data/bin/lib/Image/ExifTool/DPX.pm +1 -1
- data/bin/lib/Image/ExifTool/DV.pm +1 -1
- data/bin/lib/Image/ExifTool/DarwinCore.pm +63 -23
- data/bin/lib/Image/ExifTool/DjVu.pm +4 -2
- data/bin/lib/Image/ExifTool/EXE.pm +30 -6
- data/bin/lib/Image/ExifTool/Exif.pm +351 -109
- data/bin/lib/Image/ExifTool/FITS.pm +148 -0
- data/bin/lib/Image/ExifTool/FLAC.pm +2 -2
- data/bin/lib/Image/ExifTool/FLIF.pm +1 -1
- data/bin/lib/Image/ExifTool/FLIR.pm +109 -13
- data/bin/lib/Image/ExifTool/Fixup.pm +1 -1
- data/bin/lib/Image/ExifTool/Flash.pm +3 -3
- data/bin/lib/Image/ExifTool/FlashPix.pm +433 -9
- data/bin/lib/Image/ExifTool/Font.pm +2 -2
- data/bin/lib/Image/ExifTool/FotoStation.pm +1 -1
- data/bin/lib/Image/ExifTool/FujiFilm.pm +336 -16
- data/bin/lib/Image/ExifTool/GE.pm +1 -1
- data/bin/lib/Image/ExifTool/GIF.pm +5 -7
- data/bin/lib/Image/ExifTool/GIMP.pm +39 -3
- data/bin/lib/Image/ExifTool/GPS.pm +48 -22
- data/bin/lib/Image/ExifTool/GeoTiff.pm +23 -23
- data/bin/lib/Image/ExifTool/Geotag.pm +80 -45
- data/bin/lib/Image/ExifTool/GoPro.pm +709 -0
- data/bin/lib/Image/ExifTool/H264.pm +40 -18
- data/bin/lib/Image/ExifTool/HP.pm +1 -1
- data/bin/lib/Image/ExifTool/HTML.pm +19 -12
- data/bin/lib/Image/ExifTool/HtmlDump.pm +37 -26
- data/bin/lib/Image/ExifTool/ICC_Profile.pm +297 -23
- data/bin/lib/Image/ExifTool/ID3.pm +12 -7
- data/bin/lib/Image/ExifTool/IPTC.pm +48 -19
- data/bin/lib/Image/ExifTool/ISO.pm +1 -1
- data/bin/lib/Image/ExifTool/ITC.pm +1 -1
- data/bin/lib/Image/ExifTool/Import.pm +13 -9
- data/bin/lib/Image/ExifTool/InDesign.pm +3 -5
- data/bin/lib/Image/ExifTool/JPEG.pm +22 -11
- data/bin/lib/Image/ExifTool/JPEGDigest.pm +1 -1
- data/bin/lib/Image/ExifTool/JSON.pm +3 -3
- data/bin/lib/Image/ExifTool/JVC.pm +1 -1
- data/bin/lib/Image/ExifTool/Jpeg2000.pm +2 -2
- data/bin/lib/Image/ExifTool/Kodak.pm +1233 -58
- data/bin/lib/Image/ExifTool/KyoceraRaw.pm +1 -1
- data/bin/lib/Image/ExifTool/LNK.pm +1 -1
- data/bin/lib/Image/ExifTool/Lang/cs.pm +1 -1
- data/bin/lib/Image/ExifTool/Lang/de.pm +33 -24
- data/bin/lib/Image/ExifTool/Lang/en_ca.pm +64 -2
- data/bin/lib/Image/ExifTool/Lang/en_gb.pm +64 -2
- data/bin/lib/Image/ExifTool/Lang/es.pm +8 -4
- data/bin/lib/Image/ExifTool/Lang/fi.pm +46 -4
- data/bin/lib/Image/ExifTool/Lang/fr.pm +5 -3
- data/bin/lib/Image/ExifTool/Lang/it.pm +6 -3
- data/bin/lib/Image/ExifTool/Lang/ja.pm +15 -3
- data/bin/lib/Image/ExifTool/Lang/ko.pm +5 -2
- data/bin/lib/Image/ExifTool/Lang/nl.pm +6 -3
- data/bin/lib/Image/ExifTool/Lang/pl.pm +2 -2
- data/bin/lib/Image/ExifTool/Lang/ru.pm +1 -1
- data/bin/lib/Image/ExifTool/Lang/sv.pm +1 -1
- data/bin/lib/Image/ExifTool/Lang/tr.pm +4 -2
- data/bin/lib/Image/ExifTool/Lang/zh_cn.pm +1 -1
- data/bin/lib/Image/ExifTool/Lang/zh_tw.pm +1 -1
- data/bin/lib/Image/ExifTool/Leaf.pm +1 -1
- data/bin/lib/Image/ExifTool/Lytro.pm +4 -8
- data/bin/lib/Image/ExifTool/M2TS.pm +10 -9
- data/bin/lib/Image/ExifTool/MIE.pm +12 -8
- data/bin/lib/Image/ExifTool/MIEUnits.pod +1 -1
- data/bin/lib/Image/ExifTool/MIFF.pm +1 -1
- data/bin/lib/Image/ExifTool/MNG.pm +1 -1
- data/bin/lib/Image/ExifTool/MOI.pm +1 -1
- data/bin/lib/Image/ExifTool/MPC.pm +1 -1
- data/bin/lib/Image/ExifTool/MPEG.pm +2 -3
- data/bin/lib/Image/ExifTool/MPF.pm +6 -6
- data/bin/lib/Image/ExifTool/MWG.pm +4 -4
- data/bin/lib/Image/ExifTool/MXF.pm +2 -2
- data/bin/lib/Image/ExifTool/MacOS.pm +184 -34
- data/bin/lib/Image/ExifTool/MakerNotes.pm +101 -18
- data/bin/lib/Image/ExifTool/Matroska.pm +1 -1
- data/bin/lib/Image/ExifTool/Microsoft.pm +5 -3
- data/bin/lib/Image/ExifTool/Minolta.pm +89 -62
- data/bin/lib/Image/ExifTool/MinoltaRaw.pm +1 -1
- data/bin/lib/Image/ExifTool/Motorola.pm +1 -1
- data/bin/lib/Image/ExifTool/Nikon.pm +1511 -380
- data/bin/lib/Image/ExifTool/NikonCapture.pm +1 -1
- data/bin/lib/Image/ExifTool/NikonCustom.pm +2758 -2935
- data/bin/lib/Image/ExifTool/Nintendo.pm +1 -1
- data/bin/lib/Image/ExifTool/OOXML.pm +1 -1
- data/bin/lib/Image/ExifTool/Ogg.pm +1 -1
- data/bin/lib/Image/ExifTool/Olympus.pm +47 -8
- data/bin/lib/Image/ExifTool/OpenEXR.pm +1 -1
- data/bin/lib/Image/ExifTool/Opus.pm +1 -1
- data/bin/lib/Image/ExifTool/PCX.pm +138 -0
- data/bin/lib/Image/ExifTool/PDF.pm +58 -42
- data/bin/lib/Image/ExifTool/PGF.pm +1 -1
- data/bin/lib/Image/ExifTool/PICT.pm +1 -1
- data/bin/lib/Image/ExifTool/PLIST.pm +12 -5
- data/bin/lib/Image/ExifTool/PLUS.pm +1 -1
- data/bin/lib/Image/ExifTool/PNG.pm +108 -10
- data/bin/lib/Image/ExifTool/PPM.pm +3 -3
- data/bin/lib/Image/ExifTool/PSP.pm +1 -1
- data/bin/lib/Image/ExifTool/Palm.pm +1 -1
- data/bin/lib/Image/ExifTool/Panasonic.pm +299 -31
- data/bin/lib/Image/ExifTool/PanasonicRaw.pm +201 -19
- data/bin/lib/Image/ExifTool/Pentax.pm +164 -143
- data/bin/lib/Image/ExifTool/PhaseOne.pm +12 -5
- data/bin/lib/Image/ExifTool/PhotoCD.pm +9 -10
- data/bin/lib/Image/ExifTool/PhotoMechanic.pm +1 -1
- data/bin/lib/Image/ExifTool/Photoshop.pm +230 -60
- data/bin/lib/Image/ExifTool/PostScript.pm +29 -4
- data/bin/lib/Image/ExifTool/PrintIM.pm +1 -1
- data/bin/lib/Image/ExifTool/Qualcomm.pm +2 -2
- data/bin/lib/Image/ExifTool/QuickTime.pm +1539 -279
- data/bin/lib/Image/ExifTool/QuickTimeStream.pl +1857 -0
- data/bin/lib/Image/ExifTool/README +84 -46
- data/bin/lib/Image/ExifTool/RIFF.pm +116 -23
- data/bin/lib/Image/ExifTool/RSRC.pm +1 -1
- data/bin/lib/Image/ExifTool/RTF.pm +6 -4
- data/bin/lib/Image/ExifTool/Radiance.pm +1 -1
- data/bin/lib/Image/ExifTool/Rawzor.pm +3 -2
- data/bin/lib/Image/ExifTool/Real.pm +1 -1
- data/bin/lib/Image/ExifTool/Reconyx.pm +261 -7
- data/bin/lib/Image/ExifTool/Red.pm +325 -0
- data/bin/lib/Image/ExifTool/Ricoh.pm +3 -7
- data/bin/lib/Image/ExifTool/Samsung.pm +95 -25
- data/bin/lib/Image/ExifTool/Sanyo.pm +1 -1
- data/bin/lib/Image/ExifTool/Scalado.pm +1 -1
- data/bin/lib/Image/ExifTool/Shift.pl +26 -12
- data/bin/lib/Image/ExifTool/Shortcuts.pm +9 -2
- data/bin/lib/Image/ExifTool/Sigma.pm +36 -30
- data/bin/lib/Image/ExifTool/SigmaRaw.pm +3 -8
- data/bin/lib/Image/ExifTool/Sony.pm +531 -177
- data/bin/lib/Image/ExifTool/SonyIDC.pm +63 -3
- data/bin/lib/Image/ExifTool/Stim.pm +2 -2
- data/bin/lib/Image/ExifTool/TagInfoXML.pm +23 -23
- data/bin/lib/Image/ExifTool/TagLookup.pm +6352 -5062
- data/bin/lib/Image/ExifTool/TagNames.pod +3024 -565
- data/bin/lib/Image/ExifTool/Theora.pm +1 -1
- data/bin/lib/Image/ExifTool/Torrent.pm +2 -2
- data/bin/lib/Image/ExifTool/Unknown.pm +1 -1
- data/bin/lib/Image/ExifTool/VCard.pm +47 -9
- data/bin/lib/Image/ExifTool/Validate.pm +391 -99
- data/bin/lib/Image/ExifTool/Vorbis.pm +1 -1
- data/bin/lib/Image/ExifTool/WTV.pm +319 -0
- data/bin/lib/Image/ExifTool/WriteCanonRaw.pl +1 -1
- data/bin/lib/Image/ExifTool/WriteExif.pl +91 -18
- data/bin/lib/Image/ExifTool/WriteIPTC.pl +6 -6
- data/bin/lib/Image/ExifTool/WritePDF.pl +13 -12
- data/bin/lib/Image/ExifTool/WritePNG.pl +1 -1
- data/bin/lib/Image/ExifTool/WritePhotoshop.pl +1 -1
- data/bin/lib/Image/ExifTool/WritePostScript.pl +2 -2
- data/bin/lib/Image/ExifTool/WriteQuickTime.pl +764 -121
- data/bin/lib/Image/ExifTool/WriteXMP.pl +176 -67
- data/bin/lib/Image/ExifTool/Writer.pl +490 -246
- data/bin/lib/Image/ExifTool/XMP.pm +216 -76
- data/bin/lib/Image/ExifTool/XMP2.pl +54 -10
- data/bin/lib/Image/ExifTool/XMPStruct.pl +14 -11
- data/bin/lib/Image/ExifTool/ZIP.pm +60 -15
- data/bin/lib/Image/ExifTool/iWork.pm +12 -5
- data/bin/perl-Image-ExifTool.spec +46 -44
- data/lib/exiftool_vendored/version.rb +1 -1
- metadata +14 -4
@@ -25,6 +25,7 @@
|
|
25
25
|
# 10) http://www.adobe.com/devnet/xmp/pdfs/XMPSpecificationPart2.pdf (Oct 2008)
|
26
26
|
# 11) http://www.extensis.com/en/support/kb_article.jsp?articleNumber=6102211
|
27
27
|
# 12) http://www.cipa.jp/std/documents/e/DC-010-2012_E.pdf
|
28
|
+
# 13) http://www.cipa.jp/std/documents/e/DC-010-2017_E.pdf
|
28
29
|
#
|
29
30
|
# Notes: - Property qualifiers are handled as if they were separate
|
30
31
|
# properties (with no associated namespace).
|
@@ -48,7 +49,7 @@ use Image::ExifTool::Exif;
|
|
48
49
|
use Image::ExifTool::GPS;
|
49
50
|
require Exporter;
|
50
51
|
|
51
|
-
$VERSION = '3.
|
52
|
+
$VERSION = '3.22';
|
52
53
|
@ISA = qw(Exporter);
|
53
54
|
@EXPORT_OK = qw(EscapeXML UnescapeXML);
|
54
55
|
|
@@ -61,7 +62,8 @@ sub EncodeBase64($;$);
|
|
61
62
|
sub SaveBlankInfo($$$;$);
|
62
63
|
sub ProcessBlankInfo($$$;$);
|
63
64
|
sub ValidateXMP($;$);
|
64
|
-
sub
|
65
|
+
sub ValidateProperty($$);
|
66
|
+
sub UnescapeChar($$;$);
|
65
67
|
sub AddFlattenedTags($;$$);
|
66
68
|
sub FormatXMPDate($);
|
67
69
|
sub ConvertRational($);
|
@@ -173,8 +175,10 @@ my %xmpNS = (
|
|
173
175
|
GPano => 'http://ns.google.com/photos/1.0/panorama/',
|
174
176
|
GSpherical=> 'http://ns.google.com/videos/1.0/spherical/',
|
175
177
|
GDepth => 'http://ns.google.com/photos/1.0/depthmap/',
|
178
|
+
GFocus => 'http://ns.google.com/photos/1.0/focus/',
|
176
179
|
dwc => 'http://rs.tdwg.org/dwc/index.htm',
|
177
180
|
GettyImagesGIFT => 'http://xmp.gettyimages.com/gift/1.0/',
|
181
|
+
LImage => 'http://ns.leiainc.com/photos/1.0/image/',
|
178
182
|
);
|
179
183
|
|
180
184
|
# build reverse namespace lookup
|
@@ -203,6 +207,7 @@ my %uri2ns;
|
|
203
207
|
# NOTE: Do NOT put "Groups" here because Groups hash must not be common!
|
204
208
|
Writable => 'date',
|
205
209
|
Shift => 'Time',
|
210
|
+
Validate => 'ValidateXMPDate($val)',
|
206
211
|
PrintConv => '$self->ConvertDateTime($val)',
|
207
212
|
PrintConvInv => '$self->InverseDateTime($val,undef,1)',
|
208
213
|
);
|
@@ -737,6 +742,10 @@ my %sRetouchArea = (
|
|
737
742
|
Name => 'GDepth',
|
738
743
|
SubDirectory => { TagTable => 'Image::ExifTool::XMP::GDepth' },
|
739
744
|
},
|
745
|
+
GFocus => {
|
746
|
+
Name => 'GFocus',
|
747
|
+
SubDirectory => { TagTable => 'Image::ExifTool::XMP::GFocus' },
|
748
|
+
},
|
740
749
|
dwc => {
|
741
750
|
Name => 'dwc',
|
742
751
|
SubDirectory => { TagTable => 'Image::ExifTool::DarwinCore::Main' },
|
@@ -749,6 +758,10 @@ my %sRetouchArea = (
|
|
749
758
|
Name => 'drone-dji',
|
750
759
|
SubDirectory => { TagTable => 'Image::ExifTool::DJI::XMP' },
|
751
760
|
},
|
761
|
+
LImage => {
|
762
|
+
Name => 'LImage',
|
763
|
+
SubDirectory => { TagTable => 'Image::ExifTool::XMP::LImage' },
|
764
|
+
},
|
752
765
|
);
|
753
766
|
|
754
767
|
# hack to allow XML containing Dublin Core metadata to be handled like XMP (eg. EPUB - see ZIP.pm)
|
@@ -1439,6 +1452,7 @@ my %sPantryItem = (
|
|
1439
1452
|
PerspectiveX => { Writable => 'real' },
|
1440
1453
|
PerspectiveY => { Writable => 'real' },
|
1441
1454
|
UprightFourSegmentsCount => { Writable => 'integer' },
|
1455
|
+
AutoTone => { Writable => 'boolean' },
|
1442
1456
|
);
|
1443
1457
|
|
1444
1458
|
# Tiff namespace properties (tiff)
|
@@ -1450,7 +1464,7 @@ my %sPantryItem = (
|
|
1450
1464
|
TABLE_DESC => 'XMP TIFF',
|
1451
1465
|
NOTES => q{
|
1452
1466
|
EXIF namespace for TIFF tags. See
|
1453
|
-
L<http://www.cipa.jp/std/documents/e/DC-010-
|
1467
|
+
L<http://www.cipa.jp/std/documents/e/DC-010-2017_E.pdf> for the
|
1454
1468
|
specification.
|
1455
1469
|
},
|
1456
1470
|
ImageWidth => { Writable => 'integer' },
|
@@ -1541,7 +1555,7 @@ my %sPantryItem = (
|
|
1541
1555
|
PRIORITY => 0, # not as reliable as actual EXIF tags
|
1542
1556
|
NOTES => q{
|
1543
1557
|
EXIF namespace for EXIF tags. See
|
1544
|
-
L<http://www.cipa.jp/std/documents/e/DC-010-
|
1558
|
+
L<http://www.cipa.jp/std/documents/e/DC-010-2017_E.pdf> for the
|
1545
1559
|
specification.
|
1546
1560
|
},
|
1547
1561
|
ExifVersion => { },
|
@@ -1994,8 +2008,8 @@ my %sPantryItem = (
|
|
1994
2008
|
NAMESPACE => 'exifEX',
|
1995
2009
|
PRIORITY => 0, # not as reliable as actual EXIF tags
|
1996
2010
|
NOTES => q{
|
1997
|
-
EXIF tags added by the EXIF 2.
|
1998
|
-
L<http://www.cipa.jp/std/documents/e/DC-010-
|
2011
|
+
EXIF tags added by the EXIF 2.31 for XMP specification (see
|
2012
|
+
L<http://www.cipa.jp/std/documents/e/DC-010-2017_E.pdf>).
|
1999
2013
|
},
|
2000
2014
|
Gamma => { Writable => 'rational' },
|
2001
2015
|
PhotographicSensitivity => { Writable => 'integer' },
|
@@ -2063,6 +2077,13 @@ my %sPantryItem = (
|
|
2063
2077
|
THM => 'THM - DCF thumbnail file',
|
2064
2078
|
},
|
2065
2079
|
},
|
2080
|
+
# new in Exif 2.31
|
2081
|
+
Temperature => { Writable => 'rational', Name => 'AmbientTemperature' },
|
2082
|
+
Humidity => { Writable => 'rational' },
|
2083
|
+
Pressure => { Writable => 'rational' },
|
2084
|
+
WaterDepth => { Writable => 'rational' },
|
2085
|
+
Acceleration => { Writable => 'rational' },
|
2086
|
+
CameraElevationAngle=> { Writable => 'rational' },
|
2066
2087
|
);
|
2067
2088
|
|
2068
2089
|
# Auxiliary namespace properties (aux) - not fully documented (ref PH)
|
@@ -2198,27 +2219,43 @@ my %sPantryItem = (
|
|
2198
2219
|
# (used to set EXIF GPS position from XMP tags)
|
2199
2220
|
GPSLatitudeRef => {
|
2200
2221
|
Require => 'XMP:GPSLatitude',
|
2222
|
+
Inhibit => 'GPSLatitudeRef',
|
2201
2223
|
ValueConv => q{
|
2202
2224
|
IsFloat($val[0]) and return $val[0] < 0 ? "S" : "N";
|
2203
2225
|
$val[0] =~ /^.*([NS])/;
|
2204
2226
|
return $1;
|
2205
2227
|
},
|
2206
|
-
PrintConv => {
|
2207
|
-
N => 'North',
|
2208
|
-
S => 'South',
|
2209
|
-
},
|
2228
|
+
PrintConv => { N => 'North', S => 'South' },
|
2210
2229
|
},
|
2211
2230
|
GPSLongitudeRef => {
|
2212
2231
|
Require => 'XMP:GPSLongitude',
|
2232
|
+
Inhibit => 'GPSLongitudeRef',
|
2213
2233
|
ValueConv => q{
|
2214
2234
|
IsFloat($val[0]) and return $val[0] < 0 ? "W" : "E";
|
2215
2235
|
$val[0] =~ /^.*([EW])/;
|
2216
2236
|
return $1;
|
2217
2237
|
},
|
2218
|
-
PrintConv => {
|
2219
|
-
|
2220
|
-
|
2238
|
+
PrintConv => { E => 'East', W => 'West' },
|
2239
|
+
},
|
2240
|
+
GPSDestLatitudeRef => {
|
2241
|
+
Require => 'XMP:GPSDestLatitude',
|
2242
|
+
Inhibit => 'GPSDestLatitudeRef',
|
2243
|
+
ValueConv => q{
|
2244
|
+
IsFloat($val[0]) and return $val[0] < 0 ? "S" : "N";
|
2245
|
+
$val[0] =~ /^.*([NS])/;
|
2246
|
+
return $1;
|
2247
|
+
},
|
2248
|
+
PrintConv => { N => 'North', S => 'South' },
|
2249
|
+
},
|
2250
|
+
GPSDestLongitudeRef => {
|
2251
|
+
Require => 'XMP:GPSDestLongitude',
|
2252
|
+
Inhibit => 'GPSDestLongitudeRef',
|
2253
|
+
ValueConv => q{
|
2254
|
+
IsFloat($val[0]) and return $val[0] < 0 ? "W" : "E";
|
2255
|
+
$val[0] =~ /^.*([EW])/;
|
2256
|
+
return $1;
|
2221
2257
|
},
|
2258
|
+
PrintConv => { E => 'East', W => 'West' },
|
2222
2259
|
},
|
2223
2260
|
LensID => {
|
2224
2261
|
Notes => 'attempt to convert numerical XMP-aux:LensID stored by Adobe applications',
|
@@ -2301,13 +2338,14 @@ sub EscapeXML($)
|
|
2301
2338
|
# Unescape XML character references (entities and numerical)
|
2302
2339
|
# Inputs: 0) string to be unescaped
|
2303
2340
|
# 1) optional hash reference to convert entity names to numbers
|
2341
|
+
# 2) optional character encoding
|
2304
2342
|
# Returns: unescaped string
|
2305
2343
|
my %charNum = ('quot'=>34, 'amp'=>38, 'apos'=>39, 'lt'=>60, 'gt'=>62);
|
2306
|
-
sub UnescapeXML(
|
2344
|
+
sub UnescapeXML($;$$)
|
2307
2345
|
{
|
2308
|
-
my ($str, $conv) = @_;
|
2346
|
+
my ($str, $conv, $enc) = @_;
|
2309
2347
|
$conv = \%charNum unless $conv;
|
2310
|
-
$str =~ s/&(#?\w+);/UnescapeChar($1,$conv)/sge;
|
2348
|
+
$str =~ s/&(#?\w+);/UnescapeChar($1,$conv,$enc)/sge;
|
2311
2349
|
return $str;
|
2312
2350
|
}
|
2313
2351
|
|
@@ -2345,10 +2383,11 @@ sub FullUnescapeXML($)
|
|
2345
2383
|
# Convert XML character reference to UTF-8
|
2346
2384
|
# Inputs: 0) XML character reference stripped of the '&' and ';' (eg. 'quot', '#34', '#x22')
|
2347
2385
|
# 1) hash reference for looking up character numbers by name
|
2386
|
+
# 2) optional character encoding (default 'UTF8')
|
2348
2387
|
# Returns: UTF-8 equivalent (or original character on conversion error)
|
2349
|
-
sub UnescapeChar(
|
2388
|
+
sub UnescapeChar($$;$)
|
2350
2389
|
{
|
2351
|
-
my ($ch, $conv) = @_;
|
2390
|
+
my ($ch, $conv, $enc) = @_;
|
2352
2391
|
my $val = $$conv{$ch};
|
2353
2392
|
unless (defined $val) {
|
2354
2393
|
if ($ch =~ /^#x([0-9a-fA-F]+)$/) {
|
@@ -2360,8 +2399,9 @@ sub UnescapeChar($$)
|
|
2360
2399
|
}
|
2361
2400
|
}
|
2362
2401
|
return chr($val) if $val < 0x80; # simple ASCII
|
2363
|
-
|
2364
|
-
|
2402
|
+
$val = $] >= 5.006001 ? pack('C0U', $val) : Image::ExifTool::PackUTF8($val);
|
2403
|
+
$val = Image::ExifTool::Decode(undef, $val, 'UTF8', undef, $enc) if $enc and $enc ne 'UTF8';
|
2404
|
+
return $val;
|
2365
2405
|
}
|
2366
2406
|
|
2367
2407
|
#------------------------------------------------------------------------------
|
@@ -2395,7 +2435,17 @@ sub IsUTF8($)
|
|
2395
2435
|
# were required in the UTF-8 character
|
2396
2436
|
$rtnVal = 2;
|
2397
2437
|
}
|
2398
|
-
return -1 unless $$strPt =~ /\G[\x80-\xbf]{$n}/g;
|
2438
|
+
return -1 unless $$strPt =~ /\G([\x80-\xbf]{$n})/g;
|
2439
|
+
# the following is ref https://www.cl.cam.ac.uk/%7Emgk25/ucs/utf8_check.c
|
2440
|
+
if ($n == 2) {
|
2441
|
+
return -1 if ($ch == 0xe0 and (ord($1) & 0xe0) == 0x80) or
|
2442
|
+
($ch == 0xed and (ord($1) & 0xe0) == 0xa0) or
|
2443
|
+
($ch == 0xef and ord($1) == 0xbf and
|
2444
|
+
(ord(substr $1, 1) & 0xfe) == 0xbe);
|
2445
|
+
} else {
|
2446
|
+
return -1 if ($ch == 0xf0 and (ord($1) & 0xf0) == 0x80) or
|
2447
|
+
($ch == 0xf4 and ord($1) > 0x8f) or $ch > 0xf4;
|
2448
|
+
}
|
2399
2449
|
last unless $$strPt =~ /([\x80-\xff])/g;
|
2400
2450
|
}
|
2401
2451
|
return $rtnVal;
|
@@ -2418,7 +2468,18 @@ sub FixUTF8($;$)
|
|
2418
2468
|
# (see comments in IsUTF8() above)
|
2419
2469
|
if ($ch >= 0xc2 and $ch < 0xf8) {
|
2420
2470
|
my $n = $ch < 0xe0 ? 1 : ($ch < 0xf0 ? 2 : 3);
|
2421
|
-
|
2471
|
+
if ($$strPt =~ /\G([\x80-\xbf]{$n})/g) {
|
2472
|
+
next if $n == 1;
|
2473
|
+
if ($n == 2) {
|
2474
|
+
next unless ($ch == 0xe0 and (ord($1) & 0xe0) == 0x80) or
|
2475
|
+
($ch == 0xed and (ord($1) & 0xe0) == 0xa0) or
|
2476
|
+
($ch == 0xef and ord($1) == 0xbf and
|
2477
|
+
(ord(substr $1, 1) & 0xfe) == 0xbe);
|
2478
|
+
} else {
|
2479
|
+
next unless ($ch == 0xf0 and (ord($1) & 0xf0) == 0x80) or
|
2480
|
+
($ch == 0xf4 and ord($1) > 0x8f) or $ch > 0xf4;
|
2481
|
+
}
|
2482
|
+
}
|
2422
2483
|
}
|
2423
2484
|
# replace bad character
|
2424
2485
|
$bad = '?' unless defined $bad;
|
@@ -2480,6 +2541,7 @@ sub GetXMPTagID($;$$)
|
|
2480
2541
|
my ($ns, $nm) = ($prop =~ /(.*?):(.*)/) ? ($1, $2) : ('', $prop);
|
2481
2542
|
if ($ignoreNamespace{$ns} or $ignoreProp{$prop}) {
|
2482
2543
|
# special case: don't ignore rdf numbered items
|
2544
|
+
# (not technically allowed in XMP, but used in RDF/XML)
|
2483
2545
|
unless ($prop =~ /^rdf:(_\d+)$/) {
|
2484
2546
|
# save list index if necessary for structures
|
2485
2547
|
if ($structProps and @$structProps and $prop =~ /^rdf:li (\d+)$/) {
|
@@ -2544,7 +2606,7 @@ sub RegisterNamespace($)
|
|
2544
2606
|
while (@ns) {
|
2545
2607
|
$ns = pop @ns;
|
2546
2608
|
if ($nsURI{$ns} and $nsURI{$ns} ne $$nsRef{$ns}) {
|
2547
|
-
warn "User-defined namespace prefix '$ns' conflicts with existing namespace\n";
|
2609
|
+
warn "User-defined namespace prefix '${ns}' conflicts with existing namespace\n";
|
2548
2610
|
}
|
2549
2611
|
$nsURI{$ns} = $$nsRef{$ns};
|
2550
2612
|
$uri2ns{$$nsRef{$ns}} = $ns;
|
@@ -3106,6 +3168,26 @@ NoLoop:
|
|
3106
3168
|
my $key = $et->FoundTag($tagInfo, $val) or return 0;
|
3107
3169
|
# save original components of rational numbers (used when copying)
|
3108
3170
|
$$et{RATIONAL}{$key} = $rational if defined $rational;
|
3171
|
+
# allow read-only subdirectories (eg. embedded base64 XMP/IPTC in NKSC files)
|
3172
|
+
if ($$tagInfo{SubDirectory} and not $$et{IsWriting}) {
|
3173
|
+
my $subdir = $$tagInfo{SubDirectory};
|
3174
|
+
my $dataPt = ref $$et{VALUE}{$key} ? $$et{VALUE}{$key} : \$$et{VALUE}{$key};
|
3175
|
+
# process subdirectory information
|
3176
|
+
my %dirInfo = (
|
3177
|
+
DirName => $$subdir{DirName} || $$tagInfo{Name},
|
3178
|
+
DataPt => $dataPt,
|
3179
|
+
DirLen => length $$dataPt,
|
3180
|
+
IsExtended => 1, # (hack to avoid Duplicate warning for embedded XMP)
|
3181
|
+
);
|
3182
|
+
my $oldOrder = GetByteOrder();
|
3183
|
+
SetByteOrder($$subdir{ByteOrder}) if $$subdir{ByteOrder};
|
3184
|
+
my $oldNS = $$et{definedNS};
|
3185
|
+
delete $$et{definedNS};
|
3186
|
+
my $subTablePtr = GetTagTable($$subdir{TagTable}) || $tagTablePtr;
|
3187
|
+
$et->ProcessDirectory(\%dirInfo, $subTablePtr, $$subdir{ProcessProc});
|
3188
|
+
SetByteOrder($oldOrder);
|
3189
|
+
$$et{definedNS} = $oldNS;
|
3190
|
+
}
|
3109
3191
|
# save structure/list information if necessary
|
3110
3192
|
if (@structProps and (@structProps > 1 or defined $structProps[0][1]) and
|
3111
3193
|
not $$et{NO_STRUCT})
|
@@ -3137,11 +3219,13 @@ NoLoop:
|
|
3137
3219
|
# Returns: Number of contained XMP elements
|
3138
3220
|
sub ParseXMPElement($$$;$$$$)
|
3139
3221
|
{
|
3140
|
-
|
3222
|
+
local $_;
|
3223
|
+
my ($et, $tagTablePtr, $dataPt, $start, $end, $propList, $blankInfo) = @_;
|
3141
3224
|
my ($count, $nItems) = (0, 0);
|
3142
3225
|
my $isWriting = $$et{XMP_CAPTURE};
|
3143
3226
|
my $isSVG = $$et{XMP_IS_SVG};
|
3144
3227
|
my $saveNS; # save xlatNS lookup if changed for the scope of this element
|
3228
|
+
my (%definedNS, %usedNS); # namespaces defined and used in this scope
|
3145
3229
|
|
3146
3230
|
# get our parse procs
|
3147
3231
|
my ($attrProc, $foundProc);
|
@@ -3153,7 +3237,7 @@ sub ParseXMPElement($$$;$$$$)
|
|
3153
3237
|
}
|
3154
3238
|
$start or $start = 0;
|
3155
3239
|
$end or $end = length $$dataPt;
|
3156
|
-
$
|
3240
|
+
$propList or $propList = [ ];
|
3157
3241
|
|
3158
3242
|
my $processBlankInfo;
|
3159
3243
|
# create empty blank node information hash if necessary
|
@@ -3225,6 +3309,8 @@ sub ParseXMPElement($$$;$$$$)
|
|
3225
3309
|
if ($1 eq 'xmlns') {
|
3226
3310
|
my $ns = substr($attr, 6);
|
3227
3311
|
my $stdNS = $uri2ns{$val};
|
3312
|
+
# keep track of namespace prefixes defined in this scope (for Validate)
|
3313
|
+
$$et{definedNS}{$ns} = $definedNS{$ns} = 1 unless $$et{definedNS}{$ns};
|
3228
3314
|
unless ($stdNS) {
|
3229
3315
|
my $try = $val;
|
3230
3316
|
# patch for Nikon NX2 URI bug for Microsoft PhotoInfo namespace
|
@@ -3280,26 +3366,36 @@ sub ParseXMPElement($$$;$$$$)
|
|
3280
3366
|
# use the new namespace prefix
|
3281
3367
|
$$xlatNS{$ns} = $newNS;
|
3282
3368
|
$attr = 'xmlns:' . $newNS;
|
3369
|
+
# must go through previous attributes and change prefixes if necessary
|
3370
|
+
foreach (@attrs) {
|
3371
|
+
next unless /(.*?):/ and $1 eq $ns and $1 ne $newNS;
|
3372
|
+
my $newAttr = $newNS . substr($_, length($ns));
|
3373
|
+
$attrs{$newAttr} = $attrs{$_};
|
3374
|
+
delete $attrs{$_};
|
3375
|
+
$_ = $newAttr;
|
3376
|
+
}
|
3283
3377
|
} else {
|
3284
3378
|
delete $$xlatNS{$ns};
|
3285
3379
|
}
|
3286
3380
|
}
|
3287
|
-
}
|
3288
|
-
$attr = $$xlatNS{$1} . substr($attr, length($1));
|
3381
|
+
} else {
|
3382
|
+
$attr = $$xlatNS{$1} . substr($attr, length($1)) if $$xlatNS{$1};
|
3383
|
+
$usedNS{$1} = 1;
|
3289
3384
|
}
|
3290
3385
|
}
|
3291
3386
|
push @attrs, $attr; # preserve order
|
3292
3387
|
$attrs{$attr} = $val;
|
3293
3388
|
}
|
3294
|
-
|
3295
|
-
|
3296
|
-
|
3389
|
+
if ($prop =~ /(.*?):/) {
|
3390
|
+
$usedNS{$1} = 1;
|
3391
|
+
# tame wild namespace prefixes (patch for Microsoft stupidity)
|
3392
|
+
$prop = $$xlatNS{$1} . substr($prop, length($1)) if $$xlatNS{$1};
|
3297
3393
|
}
|
3298
3394
|
|
3299
3395
|
if ($prop eq 'rdf:li') {
|
3300
3396
|
# impose a reasonable maximum on the number of items in a list
|
3301
3397
|
if ($nItems == 1000) {
|
3302
|
-
my ($tg,$ns) = GetXMPTagID($
|
3398
|
+
my ($tg,$ns) = GetXMPTagID($propList);
|
3303
3399
|
if ($isWriting) {
|
3304
3400
|
$et->Warn("Excessive number of items for $ns:$tg. Processing may be slow", 1);
|
3305
3401
|
} elsif (not $$et{OPTIONS}{IgnoreMinorErrors}) {
|
@@ -3318,17 +3414,18 @@ sub ParseXMPElement($$$;$$$$)
|
|
3318
3414
|
$prop .= ' ' . length($nItems) . $nItems;
|
3319
3415
|
# reset LIST_TAGS at the start of the outtermost list
|
3320
3416
|
# (avoids accumulating incorrectly-written elements in a correctly-written list)
|
3321
|
-
if (not $nItems and not grep /^rdf:li /, @$
|
3417
|
+
if (not $nItems and not grep /^rdf:li /, @$propList) {
|
3322
3418
|
$$et{LIST_TAGS} = { };
|
3323
3419
|
}
|
3324
3420
|
++$nItems;
|
3325
3421
|
} elsif ($prop eq 'rdf:Description') {
|
3326
3422
|
# remove unnecessary rdf:Description elements since parseType='Resource'
|
3327
3423
|
# is more efficient (also necessary to make property path consistent)
|
3328
|
-
$parseResource = 1 if grep /^rdf:Description$/, @$
|
3424
|
+
$parseResource = 1 if grep /^rdf:Description$/, @$propList;
|
3329
3425
|
} elsif ($prop eq 'xmp:xmpmeta') {
|
3330
3426
|
# patch MicrosoftPhoto unconformity
|
3331
3427
|
$prop = 'x:xmpmeta';
|
3428
|
+
$et->Warn('Wrong namespace for xmpmeta') if $$et{XmpValidate};
|
3332
3429
|
}
|
3333
3430
|
|
3334
3431
|
# hook for special parsing of attributes
|
@@ -3350,19 +3447,19 @@ sub ParseXMPElement($$$;$$$$)
|
|
3350
3447
|
}
|
3351
3448
|
|
3352
3449
|
# push this property name onto our hierarchy list
|
3353
|
-
push @$
|
3450
|
+
push @$propList, $prop unless $parseResource;
|
3354
3451
|
|
3355
3452
|
if ($isSVG) {
|
3356
3453
|
# ignore everything but top level SVG tags and metadata unless Unknown set
|
3357
3454
|
unless ($$et{OPTIONS}{Unknown} > 1 or $$et{OPTIONS}{Verbose}) {
|
3358
|
-
if (@$
|
3359
|
-
pop @$
|
3455
|
+
if (@$propList > 1 and $$propList[1] !~ /\b(metadata|desc|title)$/) {
|
3456
|
+
pop @$propList;
|
3360
3457
|
next;
|
3361
3458
|
}
|
3362
3459
|
}
|
3363
3460
|
if ($prop eq 'svg' or $prop eq 'metadata') {
|
3364
3461
|
# add svg namespace prefix if missing to ignore these entries in the tag name
|
3365
|
-
$$
|
3462
|
+
$$propList[-1] = "svg:$prop";
|
3366
3463
|
}
|
3367
3464
|
}
|
3368
3465
|
|
@@ -3387,6 +3484,21 @@ sub ParseXMPElement($$$;$$$$)
|
|
3387
3484
|
$ns = '';
|
3388
3485
|
$name = $propName;
|
3389
3486
|
}
|
3487
|
+
if ($propName eq 'rdf:about') {
|
3488
|
+
if (not $$et{XmpAbout}) {
|
3489
|
+
$$et{XmpAbout} = $attrs{$shortName};
|
3490
|
+
} elsif ($$et{XmpAbout} ne $attrs{$shortName}) {
|
3491
|
+
if ($isWriting) {
|
3492
|
+
my $str = "Different 'rdf:about' attributes not handled";
|
3493
|
+
unless ($$et{WARNED_ONCE}{$str}) {
|
3494
|
+
$et->Error($str, 1);
|
3495
|
+
$$et{WARNED_ONCE}{$str} = 1;
|
3496
|
+
}
|
3497
|
+
} elsif ($$et{XmpValidate}) {
|
3498
|
+
$et->WarnOnce("Different 'rdf:about' attributes");
|
3499
|
+
}
|
3500
|
+
}
|
3501
|
+
}
|
3390
3502
|
if ($isWriting) {
|
3391
3503
|
# keep track of our namespaces when writing
|
3392
3504
|
if ($ns eq 'xmlns') {
|
@@ -3398,14 +3510,6 @@ sub ParseXMPElement($$$;$$$$)
|
|
3398
3510
|
delete $attrs{$shortName}; # (handled by namespace logic)
|
3399
3511
|
next;
|
3400
3512
|
} elsif ($recognizedAttrs{$propName}) {
|
3401
|
-
# save UUID to use same ID when writing
|
3402
|
-
if ($propName eq 'rdf:about') {
|
3403
|
-
if (not $$et{XMP_ABOUT}) {
|
3404
|
-
$$et{XMP_ABOUT} = $attrs{$shortName};
|
3405
|
-
} elsif ($$et{XMP_ABOUT} ne $attrs{$shortName}) {
|
3406
|
-
$et->Error("Different 'rdf:about' attributes not handled", 1);
|
3407
|
-
}
|
3408
|
-
}
|
3409
3513
|
next;
|
3410
3514
|
}
|
3411
3515
|
}
|
@@ -3423,25 +3527,26 @@ sub ParseXMPElement($$$;$$$$)
|
|
3423
3527
|
next;
|
3424
3528
|
}
|
3425
3529
|
delete $attrs{$shortName}; # don't re-use this attribute
|
3426
|
-
push @$
|
3530
|
+
push @$propList, $propName;
|
3427
3531
|
# save this shorthand XMP property
|
3428
3532
|
if (defined $nodeID) {
|
3429
|
-
SaveBlankInfo($blankInfo, $
|
3533
|
+
SaveBlankInfo($blankInfo, $propList, $shortVal);
|
3430
3534
|
} elsif ($isWriting) {
|
3431
|
-
CaptureXMP($et, $
|
3535
|
+
CaptureXMP($et, $propList, $shortVal);
|
3432
3536
|
} else {
|
3433
|
-
|
3537
|
+
ValidateProperty($et, $propList) if $$et{XmpValidate};
|
3538
|
+
&$foundProc($et, $tagTablePtr, $propList, $shortVal);
|
3434
3539
|
}
|
3435
|
-
pop @$
|
3540
|
+
pop @$propList;
|
3436
3541
|
$shorthand = 1;
|
3437
3542
|
}
|
3438
3543
|
if ($isWriting) {
|
3439
3544
|
if (ParseXMPElement($et, $tagTablePtr, $dataPt, $valStart, $valEnd,
|
3440
|
-
$
|
3545
|
+
$propList, $blankInfo))
|
3441
3546
|
{
|
3442
3547
|
# (no value since we found more properties within this one)
|
3443
3548
|
# set an error on any ignored attributes here, because they will be lost
|
3444
|
-
$$et{XMP_ERROR} = "Can't handle XMP attribute '$ignored'" if $ignored;
|
3549
|
+
$$et{XMP_ERROR} = "Can't handle XMP attribute '${ignored}'" if $ignored;
|
3445
3550
|
} elsif (not $shorthand or $valEnd != $valStart) {
|
3446
3551
|
$val = substr($$dataPt, $valStart, $valEnd - $valStart);
|
3447
3552
|
# remove comments and whitespace from rdf:Description only
|
@@ -3449,16 +3554,16 @@ sub ParseXMPElement($$$;$$$$)
|
|
3449
3554
|
$val =~ s/<!--.*?-->//g; $val =~ s/^\s+//; $val =~ s/\s+$//;
|
3450
3555
|
}
|
3451
3556
|
if (defined $nodeID) {
|
3452
|
-
SaveBlankInfo($blankInfo, $
|
3557
|
+
SaveBlankInfo($blankInfo, $propList, $val, \%attrs);
|
3453
3558
|
} else {
|
3454
|
-
CaptureXMP($et, $
|
3559
|
+
CaptureXMP($et, $propList, $val, \%attrs);
|
3455
3560
|
}
|
3456
3561
|
}
|
3457
3562
|
} else {
|
3458
3563
|
# look for additional elements contained within this one
|
3459
3564
|
if ($valStart == $valEnd or
|
3460
3565
|
!ParseXMPElement($et, $tagTablePtr, $dataPt, $valStart, $valEnd,
|
3461
|
-
$
|
3566
|
+
$propList, $blankInfo))
|
3462
3567
|
{
|
3463
3568
|
my $wasEmpty;
|
3464
3569
|
unless (defined $val) {
|
@@ -3467,10 +3572,10 @@ sub ParseXMPElement($$$;$$$$)
|
|
3467
3572
|
if ($prop eq 'rdf:Description' and $val) {
|
3468
3573
|
$val =~ s/<!--.*?-->//g; $val =~ s/^\s+//; $val =~ s/\s+$//;
|
3469
3574
|
}
|
3470
|
-
# if element value is empty, take value from 'resource' attribute
|
3471
|
-
# (preferentially) or 'about' attribute (if no 'resource')
|
3472
|
-
if ($val eq '' and ($attrs =~ /\
|
3473
|
-
$attrs =~ /\
|
3575
|
+
# if element value is empty, take value from RDF 'value' or 'resource' attribute
|
3576
|
+
# (preferentially) or 'about' attribute (if no 'value' or 'resource')
|
3577
|
+
if ($val eq '' and ($attrs =~ /\brdf:(?:value|resource)=(['"])(.*?)\1/ or
|
3578
|
+
$attrs =~ /\brdf:about=(['"])(.*?)\1/))
|
3474
3579
|
{
|
3475
3580
|
$val = $2;
|
3476
3581
|
$wasEmpty = 1;
|
@@ -3479,22 +3584,41 @@ sub ParseXMPElement($$$;$$$$)
|
|
3479
3584
|
# there are no contained elements, so this must be a simple property value
|
3480
3585
|
# (unless we already extracted shorthand values from this element)
|
3481
3586
|
if (length $val or not $shorthand) {
|
3482
|
-
my $lastProp = $$
|
3587
|
+
my $lastProp = $$propList[-1];
|
3483
3588
|
if (defined $nodeID) {
|
3484
|
-
SaveBlankInfo($blankInfo, $
|
3589
|
+
SaveBlankInfo($blankInfo, $propList, $val);
|
3485
3590
|
} elsif ($lastProp eq 'rdf:type' and $wasEmpty) {
|
3486
3591
|
# do not extract empty structure types (for now)
|
3487
3592
|
} elsif ($lastProp =~ /^et:(desc|prt|val)$/ and ($count or $1 eq 'desc')) {
|
3488
3593
|
# ignore et:desc, and et:val if preceded by et:prt
|
3489
3594
|
--$count;
|
3490
3595
|
} else {
|
3491
|
-
|
3596
|
+
ValidateProperty($et, $propList) if $$et{XmpValidate};
|
3597
|
+
&$foundProc($et, $tagTablePtr, $propList, $val, \%attrs);
|
3492
3598
|
}
|
3493
3599
|
}
|
3494
3600
|
}
|
3495
3601
|
}
|
3496
|
-
pop @$
|
3602
|
+
pop @$propList unless $parseResource;
|
3497
3603
|
++$count;
|
3604
|
+
|
3605
|
+
# validate namespace prefixes used at this level if necessary
|
3606
|
+
if ($$et{XmpValidate}) {
|
3607
|
+
foreach (sort keys %usedNS) {
|
3608
|
+
next if $$et{definedNS}{$_} or $_ eq 'xml';
|
3609
|
+
if (defined $$et{definedNS}{$_}) {
|
3610
|
+
$et->Warn("XMP namespace $_ is used out of scope");
|
3611
|
+
} else {
|
3612
|
+
$et->Warn("Undefined XMP namespace: $_");
|
3613
|
+
}
|
3614
|
+
$$et{definedNS}{$_} = -1; # (don't warn again for this namespace)
|
3615
|
+
}
|
3616
|
+
# reset namespaces that went out of scope
|
3617
|
+
$$et{definedNS}{$_} = 0 foreach keys %definedNS;
|
3618
|
+
undef %usedNS;
|
3619
|
+
undef %definedNS;
|
3620
|
+
}
|
3621
|
+
|
3498
3622
|
last if $start >= $end;
|
3499
3623
|
pos($$dataPt) = $start;
|
3500
3624
|
$$dataPt =~ /\G\s+/gc; # skip white space after closing token
|
@@ -3540,19 +3664,30 @@ sub ProcessXMP($$;$)
|
|
3540
3664
|
$$et{curURI} = { };
|
3541
3665
|
$$et{curNS} = { };
|
3542
3666
|
$$et{xlatNS} = { };
|
3667
|
+
$$et{definedNS} = { };
|
3668
|
+
delete $$et{XmpAbout};
|
3669
|
+
delete $$et{XmpValidate}; # don't validate by default
|
3543
3670
|
|
3544
3671
|
# ignore non-standard XMP while in strict MWG compatibility mode
|
3545
|
-
if (($Image::ExifTool::MWG::strict or
|
3546
|
-
$$et{
|
3672
|
+
if (($Image::ExifTool::MWG::strict or $$et{OPTIONS}{Validate}) and
|
3673
|
+
not ($$et{XMP_CAPTURE} or $$et{DOC_NUM}) and
|
3674
|
+
(($$dirInfo{DirName} || '') eq 'XMP' or $$et{FILE_TYPE} eq 'XMP'))
|
3547
3675
|
{
|
3676
|
+
$$et{XmpValidate} = { } if $$et{OPTIONS}{Validate};
|
3548
3677
|
my $path = $et->MetadataPath();
|
3549
|
-
|
3550
|
-
|
3551
|
-
|
3552
|
-
|
3553
|
-
|
3554
|
-
|
3555
|
-
|
3678
|
+
my $nonStd;
|
3679
|
+
if ($$et{FILE_TYPE} =~ /^(JPEG|TIFF|PSD)$/ and $path !~ /^(JPEG-APP1-XMP|TIFF-IFD0-XMP|PSD-XMP)$/) {
|
3680
|
+
$nonStd = 1;
|
3681
|
+
}
|
3682
|
+
if ($nonStd and $Image::ExifTool::MWG::strict) {
|
3683
|
+
$et->Warn("Ignored non-standard XMP at $path");
|
3684
|
+
return 1;
|
3685
|
+
}
|
3686
|
+
if ($nonStd) {
|
3687
|
+
$et->Warn("Non-standard XMP at $path", 1);
|
3688
|
+
} elsif (not $$dirInfo{IsExtended}) {
|
3689
|
+
$et->Warn("Duplicate XMP at $path") if $$et{DIR_COUNT}{XMP};
|
3690
|
+
$$et{DIR_COUNT}{XMP} = ($$et{DIR_COUNT}{XMP} || 0) + 1; # count standard XMP
|
3556
3691
|
}
|
3557
3692
|
}
|
3558
3693
|
if ($dataPt) {
|
@@ -3563,7 +3698,7 @@ sub ProcessXMP($$;$)
|
|
3563
3698
|
pos($$dataPt) = $dirStart;
|
3564
3699
|
$double = $1 if $$dataPt =~ /\G((\0\0)?\xfe\xff|\xff\xfe(\0\0)?|\xef\xbb\xbf)\0*<\0*\?\0*x\0*p\0*a\0*c\0*k\0*e\0*t/g;
|
3565
3700
|
} else {
|
3566
|
-
my ($type, $buf2, $buf3);
|
3701
|
+
my ($type, $mime, $buf2, $buf3);
|
3567
3702
|
# read information from XMP file
|
3568
3703
|
my $raf = $$dirInfo{RAF} or return 0;
|
3569
3704
|
$raf->Read($buff, 256) or return 0;
|
@@ -3603,6 +3738,7 @@ sub ProcessXMP($$;$)
|
|
3603
3738
|
$bom = 1 if $1;
|
3604
3739
|
if ($2 eq '<?xml') {
|
3605
3740
|
if (defined $fmt and not $fmt and $buf2 =~ /^[^\n\r]*[\n\r]+<\?aid /s) {
|
3741
|
+
undef $$et{XmpValidate}; # don't validate INX
|
3606
3742
|
if ($$et{XMP_CAPTURE}) {
|
3607
3743
|
$et->Error("ExifTool does not yet support writing of INX files");
|
3608
3744
|
return 0;
|
@@ -3611,6 +3747,7 @@ sub ProcessXMP($$;$)
|
|
3611
3747
|
} elsif ($buf2 =~ /<x(mp)?:x[ma]pmeta/) {
|
3612
3748
|
$hasXMP = 1;
|
3613
3749
|
} else {
|
3750
|
+
undef $$et{XmpValidate}; # don't validate XML
|
3614
3751
|
# identify SVG images and PLIST files by DOCTYPE if available
|
3615
3752
|
if ($buf2 =~ /<!DOCTYPE\s+(\w+)/) {
|
3616
3753
|
if ($1 eq 'svg') {
|
@@ -3619,6 +3756,7 @@ sub ProcessXMP($$;$)
|
|
3619
3756
|
$type = 'PLIST';
|
3620
3757
|
} elsif ($1 eq 'REDXIF') {
|
3621
3758
|
$type = 'RMD';
|
3759
|
+
$mime = 'application/xml';
|
3622
3760
|
} else {
|
3623
3761
|
return 0;
|
3624
3762
|
}
|
@@ -3667,7 +3805,7 @@ sub ProcessXMP($$;$)
|
|
3667
3805
|
$type = $ext if $ext and $ext eq 'COS'; # recognize COS by extension
|
3668
3806
|
}
|
3669
3807
|
}
|
3670
|
-
$et->SetFileType($type);
|
3808
|
+
$et->SetFileType($type, $mime);
|
3671
3809
|
|
3672
3810
|
my $fast = $et->Options('FastScan');
|
3673
3811
|
return 1 if $fast and $fast == 3;
|
@@ -3739,7 +3877,8 @@ sub ProcessXMP($$;$)
|
|
3739
3877
|
# extract XMP as a block if specified
|
3740
3878
|
my $blockName = $$dirInfo{BlockInfo} ? $$dirInfo{BlockInfo}{Name} : 'XMP';
|
3741
3879
|
if (($$et{REQ_TAG_LOOKUP}{lc $blockName} or ($$et{TAGS_FROM_FILE} and
|
3742
|
-
not $$et{EXCL_TAG_LOOKUP}{lc $blockName})) and
|
3880
|
+
not $$et{EXCL_TAG_LOOKUP}{lc $blockName})) and
|
3881
|
+
($$dirInfo{DirName} and $$dirInfo{DirName} eq 'XMP'))
|
3743
3882
|
{
|
3744
3883
|
$et->FoundTag($$dirInfo{BlockInfo} || 'XMP', substr($$dataPt, $dirStart, $dirLen));
|
3745
3884
|
}
|
@@ -3874,6 +4013,7 @@ sub ProcessXMP($$;$)
|
|
3874
4013
|
delete $$et{curURI};
|
3875
4014
|
delete $$et{curNS};
|
3876
4015
|
delete $$et{xlatNS};
|
4016
|
+
delete $$et{definedNS};
|
3877
4017
|
|
3878
4018
|
return $rtnVal;
|
3879
4019
|
}
|
@@ -3900,7 +4040,7 @@ information.
|
|
3900
4040
|
|
3901
4041
|
=head1 AUTHOR
|
3902
4042
|
|
3903
|
-
Copyright 2003-
|
4043
|
+
Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca)
|
3904
4044
|
|
3905
4045
|
This library is free software; you can redistribute it and/or modify it
|
3906
4046
|
under the same terms as Perl itself.
|