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.

Files changed (205) hide show
  1. checksums.yaml +4 -4
  2. data/bin/Changes +818 -19
  3. data/bin/MANIFEST +38 -0
  4. data/bin/META.json +1 -1
  5. data/bin/META.yml +1 -1
  6. data/bin/README +48 -44
  7. data/bin/arg_files/exif2xmp.args +4 -1
  8. data/bin/arg_files/gps2xmp.args +4 -1
  9. data/bin/arg_files/iptcCore.args +8 -0
  10. data/bin/arg_files/xmp2exif.args +4 -1
  11. data/bin/arg_files/xmp2gps.args +4 -1
  12. data/bin/config_files/dji.config +131 -0
  13. data/bin/config_files/example.config +6 -2
  14. data/bin/config_files/gps2utm.config +256 -256
  15. data/bin/config_files/nksc.config +146 -0
  16. data/bin/config_files/picasa_faces.config +382 -382
  17. data/bin/exiftool +688 -408
  18. data/bin/fmt_files/gpx.fmt +10 -6
  19. data/bin/fmt_files/gpx_wpt.fmt +10 -6
  20. data/bin/fmt_files/kml.fmt +8 -5
  21. data/bin/lib/File/RandomAccess.pm +48 -8
  22. data/bin/lib/File/RandomAccess.pod +21 -2
  23. data/bin/lib/Image/ExifTool.pm +645 -256
  24. data/bin/lib/Image/ExifTool.pod +219 -164
  25. data/bin/lib/Image/ExifTool/AES.pm +1 -1
  26. data/bin/lib/Image/ExifTool/AFCP.pm +3 -8
  27. data/bin/lib/Image/ExifTool/AIFF.pm +12 -4
  28. data/bin/lib/Image/ExifTool/APE.pm +1 -1
  29. data/bin/lib/Image/ExifTool/APP12.pm +1 -1
  30. data/bin/lib/Image/ExifTool/ASF.pm +19 -6
  31. data/bin/lib/Image/ExifTool/Apple.pm +13 -5
  32. data/bin/lib/Image/ExifTool/Audible.pm +1 -1
  33. data/bin/lib/Image/ExifTool/BMP.pm +1 -1
  34. data/bin/lib/Image/ExifTool/BPG.pm +17 -15
  35. data/bin/lib/Image/ExifTool/BZZ.pm +1 -1
  36. data/bin/lib/Image/ExifTool/BigTIFF.pm +30 -15
  37. data/bin/lib/Image/ExifTool/BuildTagLookup.pm +103 -52
  38. data/bin/lib/Image/ExifTool/Canon.pm +684 -112
  39. data/bin/lib/Image/ExifTool/CanonCustom.pm +119 -9
  40. data/bin/lib/Image/ExifTool/CanonRaw.pm +1 -1
  41. data/bin/lib/Image/ExifTool/CanonVRD.pm +13 -26
  42. data/bin/lib/Image/ExifTool/CaptureOne.pm +1 -1
  43. data/bin/lib/Image/ExifTool/Casio.pm +1 -1
  44. data/bin/lib/Image/ExifTool/Charset.pm +1 -1
  45. data/bin/lib/Image/ExifTool/DICOM.pm +12 -5
  46. data/bin/lib/Image/ExifTool/DJI.pm +51 -3
  47. data/bin/lib/Image/ExifTool/DNG.pm +15 -8
  48. data/bin/lib/Image/ExifTool/DPX.pm +1 -1
  49. data/bin/lib/Image/ExifTool/DV.pm +1 -1
  50. data/bin/lib/Image/ExifTool/DarwinCore.pm +63 -23
  51. data/bin/lib/Image/ExifTool/DjVu.pm +4 -2
  52. data/bin/lib/Image/ExifTool/EXE.pm +30 -6
  53. data/bin/lib/Image/ExifTool/Exif.pm +351 -109
  54. data/bin/lib/Image/ExifTool/FITS.pm +148 -0
  55. data/bin/lib/Image/ExifTool/FLAC.pm +2 -2
  56. data/bin/lib/Image/ExifTool/FLIF.pm +1 -1
  57. data/bin/lib/Image/ExifTool/FLIR.pm +109 -13
  58. data/bin/lib/Image/ExifTool/Fixup.pm +1 -1
  59. data/bin/lib/Image/ExifTool/Flash.pm +3 -3
  60. data/bin/lib/Image/ExifTool/FlashPix.pm +433 -9
  61. data/bin/lib/Image/ExifTool/Font.pm +2 -2
  62. data/bin/lib/Image/ExifTool/FotoStation.pm +1 -1
  63. data/bin/lib/Image/ExifTool/FujiFilm.pm +336 -16
  64. data/bin/lib/Image/ExifTool/GE.pm +1 -1
  65. data/bin/lib/Image/ExifTool/GIF.pm +5 -7
  66. data/bin/lib/Image/ExifTool/GIMP.pm +39 -3
  67. data/bin/lib/Image/ExifTool/GPS.pm +48 -22
  68. data/bin/lib/Image/ExifTool/GeoTiff.pm +23 -23
  69. data/bin/lib/Image/ExifTool/Geotag.pm +80 -45
  70. data/bin/lib/Image/ExifTool/GoPro.pm +709 -0
  71. data/bin/lib/Image/ExifTool/H264.pm +40 -18
  72. data/bin/lib/Image/ExifTool/HP.pm +1 -1
  73. data/bin/lib/Image/ExifTool/HTML.pm +19 -12
  74. data/bin/lib/Image/ExifTool/HtmlDump.pm +37 -26
  75. data/bin/lib/Image/ExifTool/ICC_Profile.pm +297 -23
  76. data/bin/lib/Image/ExifTool/ID3.pm +12 -7
  77. data/bin/lib/Image/ExifTool/IPTC.pm +48 -19
  78. data/bin/lib/Image/ExifTool/ISO.pm +1 -1
  79. data/bin/lib/Image/ExifTool/ITC.pm +1 -1
  80. data/bin/lib/Image/ExifTool/Import.pm +13 -9
  81. data/bin/lib/Image/ExifTool/InDesign.pm +3 -5
  82. data/bin/lib/Image/ExifTool/JPEG.pm +22 -11
  83. data/bin/lib/Image/ExifTool/JPEGDigest.pm +1 -1
  84. data/bin/lib/Image/ExifTool/JSON.pm +3 -3
  85. data/bin/lib/Image/ExifTool/JVC.pm +1 -1
  86. data/bin/lib/Image/ExifTool/Jpeg2000.pm +2 -2
  87. data/bin/lib/Image/ExifTool/Kodak.pm +1233 -58
  88. data/bin/lib/Image/ExifTool/KyoceraRaw.pm +1 -1
  89. data/bin/lib/Image/ExifTool/LNK.pm +1 -1
  90. data/bin/lib/Image/ExifTool/Lang/cs.pm +1 -1
  91. data/bin/lib/Image/ExifTool/Lang/de.pm +33 -24
  92. data/bin/lib/Image/ExifTool/Lang/en_ca.pm +64 -2
  93. data/bin/lib/Image/ExifTool/Lang/en_gb.pm +64 -2
  94. data/bin/lib/Image/ExifTool/Lang/es.pm +8 -4
  95. data/bin/lib/Image/ExifTool/Lang/fi.pm +46 -4
  96. data/bin/lib/Image/ExifTool/Lang/fr.pm +5 -3
  97. data/bin/lib/Image/ExifTool/Lang/it.pm +6 -3
  98. data/bin/lib/Image/ExifTool/Lang/ja.pm +15 -3
  99. data/bin/lib/Image/ExifTool/Lang/ko.pm +5 -2
  100. data/bin/lib/Image/ExifTool/Lang/nl.pm +6 -3
  101. data/bin/lib/Image/ExifTool/Lang/pl.pm +2 -2
  102. data/bin/lib/Image/ExifTool/Lang/ru.pm +1 -1
  103. data/bin/lib/Image/ExifTool/Lang/sv.pm +1 -1
  104. data/bin/lib/Image/ExifTool/Lang/tr.pm +4 -2
  105. data/bin/lib/Image/ExifTool/Lang/zh_cn.pm +1 -1
  106. data/bin/lib/Image/ExifTool/Lang/zh_tw.pm +1 -1
  107. data/bin/lib/Image/ExifTool/Leaf.pm +1 -1
  108. data/bin/lib/Image/ExifTool/Lytro.pm +4 -8
  109. data/bin/lib/Image/ExifTool/M2TS.pm +10 -9
  110. data/bin/lib/Image/ExifTool/MIE.pm +12 -8
  111. data/bin/lib/Image/ExifTool/MIEUnits.pod +1 -1
  112. data/bin/lib/Image/ExifTool/MIFF.pm +1 -1
  113. data/bin/lib/Image/ExifTool/MNG.pm +1 -1
  114. data/bin/lib/Image/ExifTool/MOI.pm +1 -1
  115. data/bin/lib/Image/ExifTool/MPC.pm +1 -1
  116. data/bin/lib/Image/ExifTool/MPEG.pm +2 -3
  117. data/bin/lib/Image/ExifTool/MPF.pm +6 -6
  118. data/bin/lib/Image/ExifTool/MWG.pm +4 -4
  119. data/bin/lib/Image/ExifTool/MXF.pm +2 -2
  120. data/bin/lib/Image/ExifTool/MacOS.pm +184 -34
  121. data/bin/lib/Image/ExifTool/MakerNotes.pm +101 -18
  122. data/bin/lib/Image/ExifTool/Matroska.pm +1 -1
  123. data/bin/lib/Image/ExifTool/Microsoft.pm +5 -3
  124. data/bin/lib/Image/ExifTool/Minolta.pm +89 -62
  125. data/bin/lib/Image/ExifTool/MinoltaRaw.pm +1 -1
  126. data/bin/lib/Image/ExifTool/Motorola.pm +1 -1
  127. data/bin/lib/Image/ExifTool/Nikon.pm +1511 -380
  128. data/bin/lib/Image/ExifTool/NikonCapture.pm +1 -1
  129. data/bin/lib/Image/ExifTool/NikonCustom.pm +2758 -2935
  130. data/bin/lib/Image/ExifTool/Nintendo.pm +1 -1
  131. data/bin/lib/Image/ExifTool/OOXML.pm +1 -1
  132. data/bin/lib/Image/ExifTool/Ogg.pm +1 -1
  133. data/bin/lib/Image/ExifTool/Olympus.pm +47 -8
  134. data/bin/lib/Image/ExifTool/OpenEXR.pm +1 -1
  135. data/bin/lib/Image/ExifTool/Opus.pm +1 -1
  136. data/bin/lib/Image/ExifTool/PCX.pm +138 -0
  137. data/bin/lib/Image/ExifTool/PDF.pm +58 -42
  138. data/bin/lib/Image/ExifTool/PGF.pm +1 -1
  139. data/bin/lib/Image/ExifTool/PICT.pm +1 -1
  140. data/bin/lib/Image/ExifTool/PLIST.pm +12 -5
  141. data/bin/lib/Image/ExifTool/PLUS.pm +1 -1
  142. data/bin/lib/Image/ExifTool/PNG.pm +108 -10
  143. data/bin/lib/Image/ExifTool/PPM.pm +3 -3
  144. data/bin/lib/Image/ExifTool/PSP.pm +1 -1
  145. data/bin/lib/Image/ExifTool/Palm.pm +1 -1
  146. data/bin/lib/Image/ExifTool/Panasonic.pm +299 -31
  147. data/bin/lib/Image/ExifTool/PanasonicRaw.pm +201 -19
  148. data/bin/lib/Image/ExifTool/Pentax.pm +164 -143
  149. data/bin/lib/Image/ExifTool/PhaseOne.pm +12 -5
  150. data/bin/lib/Image/ExifTool/PhotoCD.pm +9 -10
  151. data/bin/lib/Image/ExifTool/PhotoMechanic.pm +1 -1
  152. data/bin/lib/Image/ExifTool/Photoshop.pm +230 -60
  153. data/bin/lib/Image/ExifTool/PostScript.pm +29 -4
  154. data/bin/lib/Image/ExifTool/PrintIM.pm +1 -1
  155. data/bin/lib/Image/ExifTool/Qualcomm.pm +2 -2
  156. data/bin/lib/Image/ExifTool/QuickTime.pm +1539 -279
  157. data/bin/lib/Image/ExifTool/QuickTimeStream.pl +1857 -0
  158. data/bin/lib/Image/ExifTool/README +84 -46
  159. data/bin/lib/Image/ExifTool/RIFF.pm +116 -23
  160. data/bin/lib/Image/ExifTool/RSRC.pm +1 -1
  161. data/bin/lib/Image/ExifTool/RTF.pm +6 -4
  162. data/bin/lib/Image/ExifTool/Radiance.pm +1 -1
  163. data/bin/lib/Image/ExifTool/Rawzor.pm +3 -2
  164. data/bin/lib/Image/ExifTool/Real.pm +1 -1
  165. data/bin/lib/Image/ExifTool/Reconyx.pm +261 -7
  166. data/bin/lib/Image/ExifTool/Red.pm +325 -0
  167. data/bin/lib/Image/ExifTool/Ricoh.pm +3 -7
  168. data/bin/lib/Image/ExifTool/Samsung.pm +95 -25
  169. data/bin/lib/Image/ExifTool/Sanyo.pm +1 -1
  170. data/bin/lib/Image/ExifTool/Scalado.pm +1 -1
  171. data/bin/lib/Image/ExifTool/Shift.pl +26 -12
  172. data/bin/lib/Image/ExifTool/Shortcuts.pm +9 -2
  173. data/bin/lib/Image/ExifTool/Sigma.pm +36 -30
  174. data/bin/lib/Image/ExifTool/SigmaRaw.pm +3 -8
  175. data/bin/lib/Image/ExifTool/Sony.pm +531 -177
  176. data/bin/lib/Image/ExifTool/SonyIDC.pm +63 -3
  177. data/bin/lib/Image/ExifTool/Stim.pm +2 -2
  178. data/bin/lib/Image/ExifTool/TagInfoXML.pm +23 -23
  179. data/bin/lib/Image/ExifTool/TagLookup.pm +6352 -5062
  180. data/bin/lib/Image/ExifTool/TagNames.pod +3024 -565
  181. data/bin/lib/Image/ExifTool/Theora.pm +1 -1
  182. data/bin/lib/Image/ExifTool/Torrent.pm +2 -2
  183. data/bin/lib/Image/ExifTool/Unknown.pm +1 -1
  184. data/bin/lib/Image/ExifTool/VCard.pm +47 -9
  185. data/bin/lib/Image/ExifTool/Validate.pm +391 -99
  186. data/bin/lib/Image/ExifTool/Vorbis.pm +1 -1
  187. data/bin/lib/Image/ExifTool/WTV.pm +319 -0
  188. data/bin/lib/Image/ExifTool/WriteCanonRaw.pl +1 -1
  189. data/bin/lib/Image/ExifTool/WriteExif.pl +91 -18
  190. data/bin/lib/Image/ExifTool/WriteIPTC.pl +6 -6
  191. data/bin/lib/Image/ExifTool/WritePDF.pl +13 -12
  192. data/bin/lib/Image/ExifTool/WritePNG.pl +1 -1
  193. data/bin/lib/Image/ExifTool/WritePhotoshop.pl +1 -1
  194. data/bin/lib/Image/ExifTool/WritePostScript.pl +2 -2
  195. data/bin/lib/Image/ExifTool/WriteQuickTime.pl +764 -121
  196. data/bin/lib/Image/ExifTool/WriteXMP.pl +176 -67
  197. data/bin/lib/Image/ExifTool/Writer.pl +490 -246
  198. data/bin/lib/Image/ExifTool/XMP.pm +216 -76
  199. data/bin/lib/Image/ExifTool/XMP2.pl +54 -10
  200. data/bin/lib/Image/ExifTool/XMPStruct.pl +14 -11
  201. data/bin/lib/Image/ExifTool/ZIP.pm +60 -15
  202. data/bin/lib/Image/ExifTool/iWork.pm +12 -5
  203. data/bin/perl-Image-ExifTool.spec +46 -44
  204. data/lib/exiftool_vendored/version.rb +1 -1
  205. metadata +14 -4
@@ -0,0 +1,148 @@
1
+ #------------------------------------------------------------------------------
2
+ # File: FITS.pm
3
+ #
4
+ # Description: Read Flexible Image Transport System metadata
5
+ #
6
+ # Revisions: 2018/03/07 - P. Harvey Created
7
+ #
8
+ # References: 1) https://fits.gsfc.nasa.gov/fits_standard.html
9
+ #------------------------------------------------------------------------------
10
+
11
+ package Image::ExifTool::FITS;
12
+
13
+ use strict;
14
+ use vars qw($VERSION);
15
+ use Image::ExifTool qw(:DataAccess :Utils);
16
+
17
+ $VERSION = '1.00';
18
+
19
+ # FITS tags (ref 1)
20
+ %Image::ExifTool::FITS::Main = (
21
+ GROUPS => { 2 => 'Image' },
22
+ NOTES => q{
23
+ This table lists some standard Flexible Image Transport System (FITS) tags,
24
+ but ExifTool will extract any other tags found. See
25
+ L<https://fits.gsfc.nasa.gov/fits_standard.html> for the specification.
26
+ },
27
+ TELESCOP => 'Telescope',
28
+ BACKGRND => 'Background',
29
+ INSTRUME => 'Instrument',
30
+ OBJECT => 'Object',
31
+ OBSERVER => 'Observer',
32
+ DATE => { Name => 'CreateDate', Groups => { 2 => 'Time' } },
33
+ AUTHOR => { Name => 'Author', Groups => { 2 => 'Author' } },
34
+ REFERENC => 'Reference',
35
+ 'DATE-OBS'=> { Name => 'ObservationDate', Groups => { 2 => 'Time' } },
36
+ 'TIME-OBS'=> { Name => 'ObservationTime', Groups => { 2 => 'Time' } },
37
+ 'DATE-END'=> { Name => 'ObservationDateEnd', Groups => { 2 => 'Time' } },
38
+ 'TIME-END'=> { Name => 'ObservationTimeEnd', Groups => { 2 => 'Time' } },
39
+ );
40
+
41
+ #------------------------------------------------------------------------------
42
+ # Read information in a FITS document
43
+ # Inputs: 0) ExifTool ref, 1) dirInfo ref
44
+ # Returns: 1 on success, 0 if this wasn't a valid FITS file
45
+ sub ProcessFITS($$)
46
+ {
47
+ my ($et, $dirInfo) = @_;
48
+ my $raf = $$dirInfo{RAF};
49
+ my ($buff, $tag, $continue);
50
+
51
+ return 0 unless $raf->Read($buff, 80) == 80 and $buff =~ /^SIMPLE = {20}T/;
52
+ $et->SetFileType();
53
+ my $tagTablePtr = GetTagTable('Image::ExifTool::FITS::Main');
54
+
55
+ for (;;) {
56
+ $raf->Read($buff, 80) == 80 or $et->Warn('Truncated FITS header'), last;
57
+ my $key = substr($buff, 0, 8);
58
+ $key =~ s/ +$//; # remove trailing space from key
59
+ if ($key eq 'CONTINUE') {
60
+ defined $continue or $et->WarnOnce('Unexpected FITS CONTINUE keyword'), next;
61
+ } else {
62
+ if (defined $continue) {
63
+ # the previous value wasn't continued, so store with the trailing '&'
64
+ $et->HandleTag($tagTablePtr, $tag, $continue . '&');
65
+ undef $continue;
66
+ }
67
+ last if $key eq 'END';
68
+ # make sure the key is valid
69
+ $key =~ /^[-_A-Z0-9]*$/ or $et->Warn('Format error in FITS header'), last;
70
+ next unless substr($buff,8,2) eq '= '; # ignore comment lines
71
+ # save tag name (avoiding potential conflict with ExifTool variables)
72
+ $tag = $Image::ExifTool::specialTags{$key} ? "_$key" : $key;
73
+ # add to tag table if necessary
74
+ unless ($$tagTablePtr{$tag}) {
75
+ my $name = ucfirst lc $tag; # make tag name lower case with leading capital
76
+ $name =~ s/_(.)/\U$1/g; # remove all '_' and capitalize subsquent letter
77
+ AddTagToTable($tagTablePtr, $tag, { Name => $name });
78
+ }
79
+ }
80
+ my $val = substr($buff, 10);
81
+ # parse quoted values
82
+ if ($val =~ /^'(.*?)'(.*)/) {
83
+ ($val, $buff) = ($1, $2);
84
+ while ($buff =~ /^('.*?)'(.*)/) { # handle escaped quotes
85
+ $val .= $1;
86
+ $buff = $2;
87
+ }
88
+ $val =~ s/ +$//; # remove trailing spaces
89
+ if (defined $continue) {
90
+ $val = $continue . $val;
91
+ undef $continue;
92
+ }
93
+ # check for possible continuation, removing trailing '&'
94
+ $val =~ s/\&$// and $continue = $val, next;
95
+ } elsif (defined $continue) {
96
+ $et->WarnOnce('Invalid FITS CONTINUE value');
97
+ next;
98
+ } else {
99
+ $val =~ s/ *(\/.*)?$//; # remove trailing spaces and comment
100
+ next unless length $val; # ignore undefined values
101
+ $val =~ s/^ +//; # remove leading spaces
102
+ # re-format floating-point values to use 'e'
103
+ $val =~ tr/DE/e/ if $val =~ /^[+-]?(?=\d|\.\d)\d*(\.\d*)?([ED]([+-]?\d+))?$/;
104
+ }
105
+ $et->HandleTag($tagTablePtr, $tag, $val);
106
+ }
107
+ return 1;
108
+ }
109
+
110
+ 1; # end
111
+
112
+ __END__
113
+
114
+ =head1 NAME
115
+
116
+ Image::ExifTool::FITS - Read Flexible Image Transport System metadata
117
+
118
+ =head1 SYNOPSIS
119
+
120
+ This module is used by Image::ExifTool
121
+
122
+ =head1 DESCRIPTION
123
+
124
+ This module contains definitions required by Image::ExifTool to read meta
125
+ information from FITS (Flexible Image Transport System) images.
126
+
127
+ =head1 AUTHOR
128
+
129
+ Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca)
130
+
131
+ This library is free software; you can redistribute it and/or modify it
132
+ under the same terms as Perl itself.
133
+
134
+ =head1 REFERENCES
135
+
136
+ =over 4
137
+
138
+ =item L<https://fits.gsfc.nasa.gov/fits_standard.html>
139
+
140
+ =back
141
+
142
+ =head1 SEE ALSO
143
+
144
+ L<Image::ExifTool::TagNames/FITS Tags>,
145
+ L<Image::ExifTool(3pm)|Image::ExifTool>
146
+
147
+ =cut
148
+
@@ -155,7 +155,7 @@ sub ProcessBitStream($$$)
155
155
  my $tag;
156
156
 
157
157
  if ($verbose) {
158
- $et->VPrint(0, " + [BitStream directory, $dirLen bytes, '$byteOrder' order]\n");
158
+ $et->VPrint(0, " + [BitStream directory, $dirLen bytes, '${byteOrder}' order]\n");
159
159
  }
160
160
  foreach $tag (sort keys %$tagTablePtr) {
161
161
  next unless $tag =~ /^Bit(\d+)-?(\d+)?/;
@@ -284,7 +284,7 @@ information from Free Lossless Audio Codec (FLAC) audio files.
284
284
 
285
285
  =head1 AUTHOR
286
286
 
287
- Copyright 2003-2017, Phil Harvey (phil at owl.phy.queensu.ca)
287
+ Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca)
288
288
 
289
289
  This library is free software; you can redistribute it and/or modify it
290
290
  under the same terms as Perl itself.
@@ -329,7 +329,7 @@ meta information in FLIF (Free Lossless Image Format) images.
329
329
 
330
330
  =head1 AUTHOR
331
331
 
332
- Copyright 2003-2017, Phil Harvey (phil at owl.phy.queensu.ca)
332
+ Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca)
333
333
 
334
334
  This library is free software; you can redistribute it and/or modify it
335
335
  under the same terms as Perl itself.
@@ -24,7 +24,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
24
24
  use Image::ExifTool::Exif;
25
25
  use Image::ExifTool::GPS;
26
26
 
27
- $VERSION = '1.16';
27
+ $VERSION = '1.18';
28
28
 
29
29
  sub ProcessFLIR($$;$);
30
30
  sub ProcessFLIRText($$$);
@@ -97,7 +97,7 @@ my %float8g = ( Format => 'float', PrintConv => 'sprintf("%.8g",$val)' );
97
97
  PROCESS_PROC => \&ProcessFLIR,
98
98
  VARS => { ALPHA_FIRST => 1 },
99
99
  NOTES => q{
100
- Information extracted from FLIR FFF images and the FLIR APP1 segment of JPEG
100
+ Information extracted from FLIR FFF images and the APP1 FLIR segment of JPEG
101
101
  images. These tags may also be extracted from the first frame of an FLIR
102
102
  SEQ file.
103
103
  },
@@ -165,7 +165,10 @@ my %float8g = ( Format => 'float', PrintConv => 'sprintf("%.8g",$val)' );
165
165
  },
166
166
  0x2b => {
167
167
  Name => 'GPSInfo',
168
- SubDirectory => { TagTable => 'Image::ExifTool::FLIR::GPSInfo' },
168
+ SubDirectory => {
169
+ TagTable => 'Image::ExifTool::FLIR::GPSInfo',
170
+ ByteOrder => 'LittleEndian',
171
+ },
169
172
  },
170
173
  0x2c => {
171
174
  Name => 'MeterLink',
@@ -443,6 +446,8 @@ my %float8g = ( Format => 'float', PrintConv => 'sprintf("%.8g",$val)' );
443
446
  0x21c => { Name => 'FilterSerialNumber',Format => 'string[32]' },
444
447
  0x308 => { Name => 'PlanckO', Format => 'int32s' }, #1
445
448
  0x30c => { Name => 'PlanckR2', %float8g }, #1
449
+ 0x310 => { Name => 'RawValueRangeMin', Format => 'int16u', Groups => { 2 => 'Image' } }, #forum10060
450
+ 0x312 => { Name => 'RawValueRangeMax', Format => 'int16u', Groups => { 2 => 'Image' } }, #forum10060
446
451
  0x338 => { Name => 'RawValueMedian', Format => 'int16u', Groups => { 2 => 'Image' } },
447
452
  0x33c => { Name => 'RawValueRange', Format => 'int16u', Groups => { 2 => 'Image' } },
448
453
  0x384 => {
@@ -602,15 +607,111 @@ my %float8g = ( Format => 'float', PrintConv => 'sprintf("%.8g",$val)' );
602
607
  7 => { Name => 'PiPY2', Description => 'PiP Y2' },
603
608
  );
604
609
 
605
- # FLIR GPS record (ref PH/JD)
610
+ # FLIR GPS record (ref PH/JD/forum9615)
606
611
  %Image::ExifTool::FLIR::GPSInfo = (
607
- GROUPS => { 0 => 'APP1', 2 => 'Image' },
612
+ GROUPS => { 0 => 'APP1', 2 => 'Location' },
608
613
  PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
609
614
  FIRST_ENTRY => 0,
615
+ 0x00 => {
616
+ Name => 'GPSValid',
617
+ Format => 'int32u',
618
+ RawConv => '$$self{GPSValid} = $val',
619
+ PrintConv => { 0 => 'No', 1 => 'Yes' },
620
+ },
621
+ 0x04 => {
622
+ Name => 'GPSVersionID',
623
+ Format => 'undef[4]',
624
+ RawConv => '$val eq "\0\0\0\0" ? undef : $val',
625
+ PrintConv => 'join ".", split //, $val',
626
+ },
627
+ 0x08 => {
628
+ Name => 'GPSLatitudeRef',
629
+ Format => 'string[2]',
630
+ RawConv => 'length($val) ? $val : undef',
631
+ PrintConv => {
632
+ N => 'North',
633
+ S => 'South',
634
+ },
635
+ },
636
+ 0x0a => {
637
+ Name => 'GPSLongitudeRef',
638
+ Format => 'string[2]',
639
+ RawConv => 'length($val) ? $val : undef',
640
+ PrintConv => {
641
+ E => 'East',
642
+ W => 'West',
643
+ },
644
+ },
645
+ # 0x0c - 4 unknown bytes
646
+ 0x10 => {
647
+ Name => 'GPSLatitude',
648
+ Condition => '$$self{GPSValid}', # valid only if GPSValid is 1
649
+ Format => 'double', # (signed)
650
+ PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")',
651
+ },
652
+ 0x18 => {
653
+ Name => 'GPSLongitude',
654
+ Condition => '$$self{GPSValid}', # valid only if GPSValid is 1
655
+ Format => 'double', # (signed)
656
+ PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")',
657
+ },
658
+ 0x20 => {
659
+ Name => 'GPSAltitude',
660
+ Condition => '$$self{GPSValid}', # valid only if GPSValid is 1
661
+ Format => 'float',
662
+ # (have seen likely invalid value of -1 when GPSValid is 1)
663
+ PrintConv => 'sprintf("%.2f m", $val)',
664
+ },
665
+ # 0x24 - 28 unknown bytes:
666
+ # 0x28 - int8u: seen 0,49,51,55,57 (ASCII "1","3","7","9")
667
+ # 0x29 - int8u: seen 0,48 (ASCII "0")
668
+ 0x40 => {
669
+ Name => 'GPSDOP',
670
+ Description => 'GPS Dilution Of Precision',
671
+ Format => 'float',
672
+ RawConv => '$val > 0 ? $val : undef', # (have also seen likely invalid value of 1)
673
+ PrintConv => 'sprintf("%.2f", $val)',
674
+ },
675
+ 0x44 => {
676
+ Name => 'GPSSpeedRef',
677
+ Format => 'string[2]',
678
+ RawConv => 'length($val) ? $val : undef',
679
+ PrintConv => {
680
+ K => 'km/h',
681
+ M => 'mph',
682
+ N => 'knots',
683
+ },
684
+ },
685
+ 0x46 => {
686
+ Name => 'GPSTrackRef',
687
+ Format => 'string[2]',
688
+ RawConv => 'length($val) ? $val : undef',
689
+ PrintConv => {
690
+ M => 'Magnetic North',
691
+ T => 'True North',
692
+ },
693
+ },
694
+ # 0x48 - int32u: seen 0,77
695
+ 0x4c => {
696
+ Name => 'GPSSpeed',
697
+ %float2f,
698
+ RawConv => '$val < 0 ? undef : $val',
699
+ },
700
+ 0x50 => {
701
+ Name => 'GPSTrack',
702
+ %float2f,
703
+ RawConv => '$val < 0 ? undef : $val',
704
+ },
705
+ # 0x54 - float: seen 0,-1
610
706
  0x58 => {
611
707
  Name => 'GPSMapDatum',
612
708
  Format => 'string[16]',
709
+ RawConv => 'length($val) ? $val : undef',
613
710
  },
711
+ # 0xa4 - string[6]: seen 000208,081210,020409,000608,010408,020808,091011
712
+ # 0x78 - double[2]: seen "-1 -1","0 0"
713
+ # 0x78 - float[2]: seen "-1 -1","0 0"
714
+ # 0xb2 - string[2]?: seen "5\0"
614
715
  );
615
716
 
616
717
  # humidity meter information
@@ -1311,10 +1412,7 @@ sub ProcessMeasInfo($$$)
1311
1412
  last if $recLen < 0x28 or $pos + $recLen > $dirEnd;
1312
1413
  my $pre = 'Meas' . $i;
1313
1414
  $et->VerboseDir("MeasInfo $i", undef, $recLen);
1314
- if ($verbose > 2) {
1315
- HexDump($dataPt, $recLen,
1316
- Start=>$pos, Prefix=>$$et{INDENT}, DataPos=>$dataPos);
1317
- }
1415
+ $et->VerboseDump($dataPt, Len => $recLen, Start=>$pos, DataPos=>$dataPos);
1318
1416
  my $coordLen = Get16u($dataPt, $pos+4);
1319
1417
  # generate tag table entries for this tool if necessary
1320
1418
  foreach $t ('Type', 'Params', 'Label') {
@@ -1448,9 +1546,7 @@ sub ProcessFLIR($$;$)
1448
1546
  Size => $recLen,
1449
1547
  );
1450
1548
  } elsif ($verbose > 2) {
1451
- my %parms = ( DataPos => $recPos, Prefix => $$et{INDENT} );
1452
- $parms{MaxLen} = 96 if $verbose < 4;
1453
- HexDump(\$rec, $recLen, %parms);
1549
+ $et->VerboseDump(\$rec, Len => $recLen, DataPos => $recPos);
1454
1550
  }
1455
1551
  }
1456
1552
  delete $$et{SET_GROUP0};
@@ -1499,7 +1595,7 @@ Systems Inc. thermal image files (FFF, FPF and JPEG format).
1499
1595
 
1500
1596
  =head1 AUTHOR
1501
1597
 
1502
- Copyright 2003-2017, Phil Harvey (phil at owl.phy.queensu.ca)
1598
+ Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca)
1503
1599
 
1504
1600
  This library is free software; you can redistribute it and/or modify it
1505
1601
  under the same terms as Perl itself.
@@ -354,7 +354,7 @@ linear list when ApplyFixups() is called.
354
354
 
355
355
  =head1 AUTHOR
356
356
 
357
- Copyright 2003-2017, Phil Harvey (phil at owl.phy.queensu.ca)
357
+ Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca)
358
358
 
359
359
  This library is free software; you can redistribute it and/or modify it
360
360
  under the same terms as Perl itself.
@@ -363,7 +363,7 @@ Record: for ($rec=0; ; ++$rec) {
363
363
  $pos += 2 + $len;
364
364
  # first string of a typed object is the object name
365
365
  if ($getName) {
366
- $et->VPrint(1," | (object name '$tag')\n");
366
+ $et->VPrint(1," | (object name '${tag}')\n");
367
367
  undef $getName;
368
368
  next; # (ignore name for now)
369
369
  }
@@ -454,7 +454,7 @@ Record: for ($rec=0; ; ++$rec) {
454
454
  } else {
455
455
  # give verbose indication if we ignore a lone value
456
456
  my $t = $amfType[$type] || sprintf('type 0x%x',$type);
457
- $et->VPrint(1, " | (ignored lone $t value '$val')\n");
457
+ $et->VPrint(1, " | (ignored lone $t value '${val}')\n");
458
458
  }
459
459
  }
460
460
  }
@@ -721,7 +721,7 @@ will add AMF3 support.
721
721
 
722
722
  =head1 AUTHOR
723
723
 
724
- Copyright 2003-2017, Phil Harvey (phil at owl.phy.queensu.ca)
724
+ Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca)
725
725
 
726
726
  This library is free software; you can redistribute it and/or modify it
727
727
  under the same terms as Perl itself.
@@ -9,6 +9,8 @@
9
9
  # 2) http://www.graphcomp.com/info/specs/livepicture/fpx.pdf
10
10
  # 3) http://search.cpan.org/~jdb/libwin32/
11
11
  # 4) http://msdn.microsoft.com/en-us/library/aa380374.aspx
12
+ # 5) http://www.cpan.org/modules/by-authors/id/H/HC/HCARVEY/File-MSWord-0.1.zip
13
+ # 6) https://msdn.microsoft.com/en-us/library/cc313153(v=office.12).aspx
12
14
  #------------------------------------------------------------------------------
13
15
 
14
16
  package Image::ExifTool::FlashPix;
@@ -19,7 +21,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
19
21
  use Image::ExifTool::Exif;
20
22
  use Image::ExifTool::ASF; # for GetGUID()
21
23
 
22
- $VERSION = '1.29';
24
+ $VERSION = '1.36';
23
25
 
24
26
  sub ProcessFPX($$);
25
27
  sub ProcessFPXR($$$);
@@ -27,7 +29,12 @@ sub ProcessProperties($$$);
27
29
  sub ReadFPXValue($$$$$;$$);
28
30
  sub ProcessHyperlinks($$);
29
31
  sub ProcessContents($$$);
32
+ sub ProcessWordDocument($$$);
33
+ sub ProcessDocumentTable($);
34
+ sub ProcessCommentBy($$$);
35
+ sub ProcessLastSavedBy($$$);
30
36
  sub SetDocNum($$;$$$);
37
+ sub ConvertDTTM($);
31
38
 
32
39
  # sector type constants
33
40
  sub HDR_SIZE () { 512; }
@@ -425,6 +432,21 @@ my %fpxFileType = (
425
432
  return substr($val, 8 + $pos, $len);
426
433
  },
427
434
  },
435
+ 'WordDocument' => {
436
+ Name => 'WordDocument',
437
+ SubDirectory => { TagTable => 'Image::ExifTool::FlashPix::WordDocument' },
438
+ },
439
+ # save these tables until after the WordDocument was processed
440
+ '0Table' => {
441
+ Name => 'Table0',
442
+ Hidden => 1, # (used only as temporary storage until table is processed)
443
+ Binary => 1,
444
+ },
445
+ '1Table' => {
446
+ Name => 'Table1',
447
+ Hidden => 1, # (used only as temporary storage until table is processed)
448
+ Binary => 1,
449
+ },
428
450
  Preview => {
429
451
  Name => 'PreviewImage',
430
452
  Groups => { 2 => 'Preview' },
@@ -1031,6 +1053,216 @@ my %fpxFileType = (
1031
1053
  },
1032
1054
  );
1033
1055
 
1056
+ # decode Word document FIB header (ref [MS-DOC].pdf)
1057
+ %Image::ExifTool::FlashPix::WordDocument = (
1058
+ PROCESS_PROC => \&ProcessWordDocument,
1059
+ GROUPS => { 2 => 'Other' },
1060
+ FORMAT => 'int16u',
1061
+ NOTES => 'Tags extracted from the Microsoft Word document stream.',
1062
+ 0 => {
1063
+ Name => 'Identification',
1064
+ PrintHex => 1,
1065
+ PrintConv => {
1066
+ 0x6a62 => 'MS Word 97',
1067
+ 0x626a => 'Word 98 Mac',
1068
+ 0xa5dc => 'Word 6.0/7.0',
1069
+ 0xa5ec => 'Word 8.0',
1070
+ },
1071
+ },
1072
+ 3 => {
1073
+ Name => 'LanguageCode',
1074
+ PrintHex => 1,
1075
+ PrintConv => {
1076
+ 0x0400 => 'None',
1077
+ 0x0401 => 'Arabic',
1078
+ 0x0402 => 'Bulgarian',
1079
+ 0x0403 => 'Catalan',
1080
+ 0x0404 => 'Traditional Chinese',
1081
+ 0x0804 => 'Simplified Chinese',
1082
+ 0x0405 => 'Czech',
1083
+ 0x0406 => 'Danish',
1084
+ 0x0407 => 'German',
1085
+ 0x0807 => 'German (Swiss)',
1086
+ 0x0408 => 'Greek',
1087
+ 0x0409 => 'English (US)',
1088
+ 0x0809 => 'English (British)',
1089
+ 0x0c09 => 'English (Australian)',
1090
+ 0x040a => 'Spanish (Castilian)',
1091
+ 0x080a => 'Spanish (Mexican)',
1092
+ 0x040b => 'Finnish',
1093
+ 0x040c => 'French',
1094
+ 0x080c => 'French (Belgian)',
1095
+ 0x0c0c => 'French (Canadian)',
1096
+ 0x100c => 'French (Swiss)',
1097
+ 0x040d => 'Hebrew',
1098
+ 0x040e => 'Hungarian',
1099
+ 0x040f => 'Icelandic',
1100
+ 0x0410 => 'Italian',
1101
+ 0x0810 => 'Italian (Swiss)',
1102
+ 0x0411 => 'Japanese',
1103
+ 0x0412 => 'Korean',
1104
+ 0x0413 => 'Dutch',
1105
+ 0x0813 => 'Dutch (Belgian)',
1106
+ 0x0414 => 'Norwegian (Bokmal)',
1107
+ 0x0814 => 'Norwegian (Nynorsk)',
1108
+ 0x0415 => 'Polish',
1109
+ 0x0416 => 'Portuguese (Brazilian)',
1110
+ 0x0816 => 'Portuguese',
1111
+ 0x0417 => 'Rhaeto-Romanic',
1112
+ 0x0418 => 'Romanian',
1113
+ 0x0419 => 'Russian',
1114
+ 0x041a => 'Croato-Serbian (Latin)',
1115
+ 0x081a => 'Serbo-Croatian (Cyrillic)',
1116
+ 0x041b => 'Slovak',
1117
+ 0x041c => 'Albanian',
1118
+ 0x041d => 'Swedish',
1119
+ 0x041e => 'Thai',
1120
+ 0x041f => 'Turkish',
1121
+ 0x0420 => 'Urdu',
1122
+ 0x0421 => 'Bahasa',
1123
+ 0x0422 => 'Ukrainian',
1124
+ 0x0423 => 'Byelorussian',
1125
+ 0x0424 => 'Slovenian',
1126
+ 0x0425 => 'Estonian',
1127
+ 0x0426 => 'Latvian',
1128
+ 0x0427 => 'Lithuanian',
1129
+ 0x0429 => 'Farsi',
1130
+ 0x042d => 'Basque',
1131
+ 0x042f => 'Macedonian',
1132
+ 0x0436 => 'Afrikaans',
1133
+ 0x043e => 'Malaysian',
1134
+ },
1135
+ },
1136
+ 5 => {
1137
+ Name => 'DocFlags',
1138
+ Mask => 0xff0f, # ignore save count
1139
+ RawConv => '$$self{DocFlags} = $val',
1140
+ PrintConv => { BITMASK => {
1141
+ 0 => 'Template',
1142
+ 1 => 'AutoText only',
1143
+ 2 => 'Complex',
1144
+ 3 => 'Has picture',
1145
+ # 4-7 = number of incremental saves
1146
+ 8 => 'Encrypted',
1147
+ 9 => '1Table',
1148
+ 10 => 'Read only',
1149
+ 11 => 'Passworded',
1150
+ 12 => 'ExtChar',
1151
+ 13 => 'Load override',
1152
+ 14 => 'Far east',
1153
+ 15 => 'Obfuscated',
1154
+ }},
1155
+ },
1156
+ 9.1 => {
1157
+ Name => 'System',
1158
+ Mask => 0x0001,
1159
+ PrintConv => {
1160
+ 0x0000 => 'Windows',
1161
+ 0x0001 => 'Macintosh',
1162
+ },
1163
+ },
1164
+ 9.2 => {
1165
+ Name => 'Word97',
1166
+ Mask => 0x0010,
1167
+ PrintConv => { 0 => 'No', 1 => 'Yes' },
1168
+ },
1169
+ );
1170
+
1171
+ # tags decoded from Word document table
1172
+ %Image::ExifTool::FlashPix::DocTable = (
1173
+ GROUPS => { 1 => 'MS-DOC', 2 => 'Document' },
1174
+ NOTES => 'Tags extracted from the Microsoft Word document table.',
1175
+ VARS => { NO_ID => 1 },
1176
+ CommentBy => {
1177
+ Groups => { 2 => 'Author' },
1178
+ Notes => 'enable Duplicates option to extract all entries',
1179
+ },
1180
+ LastSavedBy => {
1181
+ Groups => { 2 => 'Author' },
1182
+ Notes => 'enable Duplicates option to extract history of up to 10 entries',
1183
+ },
1184
+ DOP => { SubDirectory => { TagTable => 'Image::ExifTool::FlashPix::DOP' } },
1185
+ ModifyDate => {
1186
+ Groups => { 2 => 'Time' },
1187
+ Format => 'int64u',
1188
+ Priority => 0,
1189
+ RawConv => q{
1190
+ $val = $val * 1e-7 - 11644473600; # convert to seconds since 1970
1191
+ return $val > 0 ? $val : undef;
1192
+ },
1193
+ ValueConv => 'ConvertUnixTime($val)',
1194
+ PrintConv => '$self->ConvertDateTime($val)',
1195
+ },
1196
+ #
1197
+ # tags below are used internally in intermediate steps to extract the tags above
1198
+ #
1199
+ TableOffsets => { Hidden => 1 }, # stores offsets to extract data from document table
1200
+ CommentByBlock => { # entire block of CommentBy entries
1201
+ SubDirectory => {
1202
+ TagTable => 'Image::ExifTool::FlashPix::DocTable',
1203
+ ProcessProc => \&ProcessCommentBy,
1204
+ },
1205
+ Hidden => 1,
1206
+ },
1207
+ LastSavedByBlock => { # entire block of LastSavedBy entries
1208
+ SubDirectory => {
1209
+ TagTable => 'Image::ExifTool::FlashPix::DocTable',
1210
+ ProcessProc => \&ProcessLastSavedBy,
1211
+ },
1212
+ Hidden => 1,
1213
+ },
1214
+ );
1215
+
1216
+ # Microsoft Office Document Properties (ref [MS-DOC].pdf)
1217
+ %Image::ExifTool::FlashPix::DOP = (
1218
+ PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
1219
+ GROUPS => { 1 => 'MS-DOC', 2 => 'Document' },
1220
+ NOTES => 'Microsoft office document properties.',
1221
+ 20 => {
1222
+ Name => 'CreateDate',
1223
+ Format => 'int32u',
1224
+ Groups => { 2 => 'Time' },
1225
+ Priority => 0,
1226
+ RawConv => \&ConvertDTTM,
1227
+ PrintConv => '$self->ConvertDateTime($val)',
1228
+ },
1229
+ 24 => {
1230
+ Name => 'ModifyDate',
1231
+ Format => 'int32u',
1232
+ Groups => { 2 => 'Time' },
1233
+ Priority => 0,
1234
+ RawConv => \&ConvertDTTM,
1235
+ PrintConv => '$self->ConvertDateTime($val)',
1236
+ },
1237
+ 28 => {
1238
+ Name => 'LastPrinted',
1239
+ Format => 'int32u',
1240
+ Groups => { 2 => 'Time' },
1241
+ RawConv => \&ConvertDTTM,
1242
+ PrintConv => '$self->ConvertDateTime($val)',
1243
+ },
1244
+ 32 => { Name => 'RevisionNumber', Format => 'int16u' },
1245
+ 34 => {
1246
+ Name => 'TotalEditTime',
1247
+ Format => 'int32u',
1248
+ PrintConv => 'ConvertTimeSpan($val,60)',
1249
+ },
1250
+ # (according to the MS-DOC specification, the following are accurate only if
1251
+ # flag 'X' is set, and flag 'u' specifies whether the main or subdoc tags are
1252
+ # used, but in my tests it seems that both are filled in with reasonable values,
1253
+ # so just extract the main counts and ignore the subdoc counts for now - PH)
1254
+ 38 => { Name => 'Words', Format => 'int32u' },
1255
+ 42 => { Name => 'Characters', Format => 'int32u' },
1256
+ 46 => { Name => 'Pages', Format => 'int16u' },
1257
+ 48 => { Name => 'Paragraphs', Format => 'int32u' },
1258
+ 56 => { Name => 'Lines', Format => 'int32u' },
1259
+ #60 => { Name => 'WordsWithSubdocs', Format => 'int32u' },
1260
+ #64 => { Name => 'CharactersWithSubdocs', Format => 'int32u' },
1261
+ #68 => { Name => 'PagesWithSubdocs', Format => 'int16u' },
1262
+ #70 => { Name => 'ParagraphsWithSubdocs', Format => 'int32u' },
1263
+ #74 => { Name => 'LinesWithSubdocs', Format => 'int32u' },
1264
+ );
1265
+
1034
1266
  # FujiFilm "Property" information (ref PH)
1035
1267
  %Image::ExifTool::FlashPix::PreviewInfo = (
1036
1268
  PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
@@ -1072,6 +1304,22 @@ my %fpxFileType = (
1072
1304
  # add our composite tags
1073
1305
  Image::ExifTool::AddCompositeTags('Image::ExifTool::FlashPix');
1074
1306
 
1307
+ #------------------------------------------------------------------------------
1308
+ # Convert Microsoft DTTM structure to date/time
1309
+ # Inputs: 0) DTTM value
1310
+ # Returns: EXIF-format date/time string ("0000:00:00 00:00:00" for zero date/time)
1311
+ sub ConvertDTTM($)
1312
+ {
1313
+ my $val = shift;
1314
+ my $yr = ($val >> 20) & 0x1ff;
1315
+ my $mon = ($val >> 16) & 0x0f;
1316
+ my $day = ($val >> 11) & 0x1f;
1317
+ my $hr = ($val >> 6) & 0x1f;
1318
+ my $min = ($val & 0x3f);
1319
+ $yr += 1900 if $val;
1320
+ return sprintf("%.4d:%.2d:%.2d %.2d:%.2d:00%s",$yr,$mon,$day,$hr,$min,$val ? 'Z' : '');
1321
+ }
1322
+
1075
1323
  #------------------------------------------------------------------------------
1076
1324
  # Process hyperlinks from PID_HYPERLINKS array
1077
1325
  # (ref http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/dnaro97ta/html/msdn_hyper97.asp)
@@ -1263,6 +1511,181 @@ sub ProcessContents($$$)
1263
1511
  return 1;
1264
1512
  }
1265
1513
 
1514
+ #------------------------------------------------------------------------------
1515
+ # Process WordDocument stream of MSWord doc file (ref 6)
1516
+ # Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
1517
+ # Returns: 1 on success
1518
+ sub ProcessWordDocument($$$)
1519
+ {
1520
+ my ($et, $dirInfo, $tagTablePtr) = @_;
1521
+ my $dataPt = $$dirInfo{DataPt} or return 0;
1522
+ my $dirLen = length $$dataPt;
1523
+ # validate the FIB signature
1524
+ unless ($dirLen > 2 and Get16u($dataPt,0) == 0xa5ec) {
1525
+ $et->WarnOnce('Invalid FIB signature', 1);
1526
+ return 0;
1527
+ }
1528
+ $et->ProcessBinaryData($dirInfo, $tagTablePtr); # process FIB
1529
+ # continue parsing the WordDocument stream until we find the FibRgFcLcb
1530
+ my $pos = 32;
1531
+ return 0 if $pos + 2 > $dirLen;
1532
+ my $n = Get16u($dataPt, $pos); # read csw
1533
+ $pos += 2 + $n * 2; # skip fibRgW
1534
+ return 0 if $pos + 2 > $dirLen;
1535
+ $n = Get16u($dataPt, $pos); # read cslw
1536
+ $pos += 2 + $n * 4; # skip fibRgLw
1537
+ return 0 if $pos + 2 > $dirLen;
1538
+ $n = Get16u($dataPt, $pos); # read cbRgFcLcb
1539
+ $pos += 2; # point to start of fibRgFcLcbBlob
1540
+ return 0 if $pos + $n * 8 > $dirLen;
1541
+ my ($off, @tableOffsets);
1542
+ # save necessary entries for later processing of document table
1543
+ # (DOP, CommentBy, LastSavedBy)
1544
+ foreach $off (0xf8, 0x120, 0x238) {
1545
+ last if $off + 8 > $n * 8;
1546
+ push @tableOffsets, Get32u($dataPt, $pos + $off);
1547
+ push @tableOffsets, Get32u($dataPt, $pos + $off + 4);
1548
+ }
1549
+ my $tbl = GetTagTable('Image::ExifTool::FlashPix::DocTable');
1550
+ # extract ModifyDate if it exists
1551
+ $et->HandleTag($tbl, 'ModifyDate', undef,
1552
+ DataPt => $dataPt,
1553
+ Start => $pos + 0x2b8,
1554
+ Size => 8,
1555
+ );
1556
+ $et->HandleTag($tbl, TableOffsets => \@tableOffsets); # save for later
1557
+ # $pos += $n * 8; # skip fibRgFcLcbBlob
1558
+ # return 0 if $pos + 2 > $dirLen;
1559
+ # $n = Get16u($dataPt, $pos); # read cswNew
1560
+ # return 0 if $pos + 2 + $n * 2 > $dirLen;
1561
+ # my $nFib = Get16u($dataPt, 2 + ($n ? $pos : 0));
1562
+ # $pos += 2 + $n * 2; # skip fibRgCswNew
1563
+ return 1;
1564
+ }
1565
+
1566
+ #------------------------------------------------------------------------------
1567
+ # Process Microsoft Word Document Table
1568
+ # Inputs: 0) ExifTool object ref
1569
+ sub ProcessDocumentTable($)
1570
+ {
1571
+ my $et = shift;
1572
+ my $value = $$et{VALUE};
1573
+ my $extra = $$et{TAG_EXTRA};
1574
+ my ($i, $j, $tag);
1575
+ # loop through TableOffsets for each sub-document
1576
+ for ($i=0; ; ++$i) {
1577
+ my $key = 'TableOffsets' . ($i ? " ($i)" : '');
1578
+ my $offsets = $$value{$key};
1579
+ last unless defined $offsets;
1580
+ my $doc = $$extra{$key}{G3} if $$extra{$key};
1581
+ $doc = '' unless $doc;
1582
+ # get DocFlags for this sub-document
1583
+ my ($docFlags, $docTable);
1584
+ for ($j=0; ; ++$j) {
1585
+ my $key = 'DocFlags' . ($j ? " ($j)" : '');
1586
+ last unless defined $$value{$key};
1587
+ my $tmp = $$extra{$key}{G3} if $$extra{$key};
1588
+ $tmp = '' unless $tmp;
1589
+ if ($tmp eq $doc) {
1590
+ $docFlags = $$value{$key};
1591
+ last;
1592
+ }
1593
+ }
1594
+ next unless defined $docFlags;
1595
+ $tag = $docFlags & 0x200 ? 'Table1' : 'Table0';
1596
+ # get table for this sub-document
1597
+ for ($j=0; ; ++$j) {
1598
+ my $key = $tag . ($j ? " ($j)" : '');
1599
+ last unless defined $$value{$key};
1600
+ my $tmp = $$extra{$key}{G3} if $$extra{$key};
1601
+ $tmp = '' unless $tmp;
1602
+ if ($tmp eq $doc) {
1603
+ $docTable = \$$value{$key};
1604
+ last;
1605
+ }
1606
+ }
1607
+ next unless defined $docTable;
1608
+ # extract DOP and LastSavedBy information from document table
1609
+ $$et{DOC_NUM} = $doc; # use same document number
1610
+ my $tagTablePtr = GetTagTable('Image::ExifTool::FlashPix::DocTable');
1611
+ foreach $tag (qw(DOP CommentByBlock LastSavedByBlock)) {
1612
+ last unless @$offsets;
1613
+ my $off = shift @$offsets;
1614
+ my $len = shift @$offsets;
1615
+ next unless $len and $off + $len <= length $$docTable;
1616
+ $et->HandleTag($tagTablePtr, $tag, undef,
1617
+ DataPt => $docTable,
1618
+ Start => $off,
1619
+ Size => $len,
1620
+ );
1621
+ }
1622
+ delete $$et{DOC_NUM};
1623
+ }
1624
+ # delete intermediate tags
1625
+ foreach $tag (qw(TableOffsets Table0 Table1)) {
1626
+ for ($i=0; ; ++$i) {
1627
+ my $key = $tag . ($i ? " ($i)" : '');
1628
+ last unless defined $$value{$key};
1629
+ $et->DeleteTag($key);
1630
+ }
1631
+ }
1632
+ }
1633
+
1634
+ #------------------------------------------------------------------------------
1635
+ # Extract names of comment authors (ref 6)
1636
+ # Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
1637
+ # Returns: 1 on success
1638
+ sub ProcessCommentBy($$$)
1639
+ {
1640
+ my ($et, $dirInfo, $tagTablePtr) = @_;
1641
+ my $dataPt = $$dirInfo{DataPt};
1642
+ my $pos = $$dirInfo{DirStart};
1643
+ my $end = $$dirInfo{DirLen} + $pos;
1644
+ $et->VerboseDir($$dirInfo{DirName});
1645
+ while ($pos + 2 < $end) {
1646
+ my $len = Get16u($dataPt, $pos);
1647
+ $pos += 2;
1648
+ last if $pos + $len * 2 > $end;
1649
+ my $author = $et->Decode(substr($$dataPt, $pos, $len*2), 'UCS2');
1650
+ $pos += $len * 2;
1651
+ $et->HandleTag($tagTablePtr, CommentBy => $author);
1652
+ }
1653
+ return 1;
1654
+ }
1655
+
1656
+ #------------------------------------------------------------------------------
1657
+ # Extract last-saved-by names (ref 5)
1658
+ # Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
1659
+ # Returns: 1 on success
1660
+ sub ProcessLastSavedBy($$$)
1661
+ {
1662
+ my ($et, $dirInfo, $tagTablePtr) = @_;
1663
+ my $dataPt = $$dirInfo{DataPt};
1664
+ my $pos = $$dirInfo{DirStart};
1665
+ my $end = $$dirInfo{DirLen} + $pos;
1666
+ return 0 if $pos + 6 > $end;
1667
+ $et->VerboseDir($$dirInfo{DirName});
1668
+ my $num = Get16u($dataPt, $pos+2);
1669
+ $pos += 6;
1670
+ while ($num >= 2) {
1671
+ last if $pos + 2 > $end;
1672
+ my $len = Get16u($dataPt, $pos);
1673
+ $pos += 2;
1674
+ last if $pos + $len * 2 > $end;
1675
+ my $author = $et->Decode(substr($$dataPt, $pos, $len*2), 'UCS2');
1676
+ $pos += $len * 2;
1677
+ last if $pos + 2 > $end;
1678
+ $len = Get16u($dataPt, $pos);
1679
+ $pos += 2;
1680
+ last if $pos + $len * 2 > $end;
1681
+ my $path = $et->Decode(substr($$dataPt, $pos, $len*2), 'UCS2');
1682
+ $pos += $len * 2;
1683
+ $et->HandleTag($tagTablePtr, LastSavedBy => "$author ($path)");
1684
+ $num -= 2;
1685
+ }
1686
+ return 1;
1687
+ }
1688
+
1266
1689
  #------------------------------------------------------------------------------
1267
1690
  # Check FPX byte order mark (BOM) and set byte order appropriately
1268
1691
  # Inputs: 0) data ref, 1) offset to BOM
@@ -1482,7 +1905,7 @@ sub ProcessFPXR($$$)
1482
1905
  my $name = Image::ExifTool::Decode(undef, $1, 'UCS2', 'II', 'Latin');
1483
1906
  if ($verbose) {
1484
1907
  my $psize = ($size == 0xffffffff) ? 'storage' : "$size bytes";
1485
- $et->VPrint(0," | $entry) Name: '$name' [$psize]\n");
1908
+ $et->VPrint(0," | $entry) Name: '${name}' [$psize]\n");
1486
1909
  }
1487
1910
  # remove directory specification
1488
1911
  $name =~ s{.*/}{}s;
@@ -1637,7 +2060,7 @@ sub ProcessFPX($$)
1637
2060
  {
1638
2061
  my ($et, $dirInfo) = @_;
1639
2062
  my $raf = $$dirInfo{RAF};
1640
- my ($buff, $out, %dumpParms, $oldIndent, $miniStreamBuff);
2063
+ my ($buff, $out, $oldIndent, $miniStreamBuff);
1641
2064
  my ($tag, %hier, %objIndex, %loadedDifSect);
1642
2065
 
1643
2066
  # read header
@@ -1667,8 +2090,6 @@ sub ProcessFPX($$)
1667
2090
 
1668
2091
  if ($verbose) {
1669
2092
  $out = $et->Options('TextOut');
1670
- $dumpParms{Out} = $out;
1671
- $dumpParms{MaxLen} = 96 if $verbose == 3;
1672
2093
  print $out " Sector size=$sectSize\n FAT: Count=$fatCount\n";
1673
2094
  print $out " DIR: Start=$dirStart\n";
1674
2095
  print $out " MiniFAT: Mini-sector size=$miniSize Start=$miniStart Count=$miniCount Cutoff=$miniCutoff\n";
@@ -1736,11 +2157,11 @@ sub ProcessFPX($$)
1736
2157
  }
1737
2158
  if ($verbose) {
1738
2159
  print $out " FAT [",length($fat)," bytes]:\n";
1739
- HexDump(\$fat, undef, %dumpParms) if $verbose > 2;
2160
+ $et->VerboseDump(\$fat);
1740
2161
  print $out " Mini-FAT [",length($miniFat)," bytes]:\n";
1741
- HexDump(\$miniFat, undef, %dumpParms) if $verbose > 2;
2162
+ $et->VerboseDump(\$miniFat);
1742
2163
  print $out " Directory [",length($dir)," bytes]:\n";
1743
- HexDump(\$dir, undef, %dumpParms) if $verbose > 2;
2164
+ $et->VerboseDump(\$dir);
1744
2165
  }
1745
2166
  #
1746
2167
  # process the directory
@@ -1919,6 +2340,9 @@ sub ProcessFPX($$)
1919
2340
  }
1920
2341
  }
1921
2342
  }
2343
+ # process Word document table
2344
+ ProcessDocumentTable($et);
2345
+
1922
2346
  return 1;
1923
2347
  }
1924
2348
 
@@ -1942,7 +2366,7 @@ JPEG images.
1942
2366
 
1943
2367
  =head1 AUTHOR
1944
2368
 
1945
- Copyright 2003-2017, Phil Harvey (phil at owl.phy.queensu.ca)
2369
+ Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca)
1946
2370
 
1947
2371
  This library is free software; you can redistribute it and/or modify it
1948
2372
  under the same terms as Perl itself.