exiftool-vendored.exe 13.0.0 → 13.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (208) hide show
  1. package/bin/exiftool.exe +0 -0
  2. package/bin/exiftool_files/exiftool.pl +169 -65
  3. package/bin/exiftool_files/lib/File/RandomAccess.pm +1 -1
  4. package/bin/exiftool_files/lib/File/RandomAccess.pod +2 -2
  5. package/bin/exiftool_files/lib/Image/ExifTool/AAC.pm +1 -1
  6. package/bin/exiftool_files/lib/Image/ExifTool/AES.pm +1 -1
  7. package/bin/exiftool_files/lib/Image/ExifTool/AFCP.pm +6 -6
  8. package/bin/exiftool_files/lib/Image/ExifTool/AIFF.pm +2 -2
  9. package/bin/exiftool_files/lib/Image/ExifTool/APE.pm +2 -2
  10. package/bin/exiftool_files/lib/Image/ExifTool/APP12.pm +1 -1
  11. package/bin/exiftool_files/lib/Image/ExifTool/ASF.pm +2 -2
  12. package/bin/exiftool_files/lib/Image/ExifTool/Apple.pm +11 -9
  13. package/bin/exiftool_files/lib/Image/ExifTool/Audible.pm +1 -1
  14. package/bin/exiftool_files/lib/Image/ExifTool/BMP.pm +1 -1
  15. package/bin/exiftool_files/lib/Image/ExifTool/BPG.pm +1 -1
  16. package/bin/exiftool_files/lib/Image/ExifTool/BZZ.pm +1 -1
  17. package/bin/exiftool_files/lib/Image/ExifTool/BigTIFF.pm +1 -1
  18. package/bin/exiftool_files/lib/Image/ExifTool/BuildTagLookup.pm +46 -26
  19. package/bin/exiftool_files/lib/Image/ExifTool/CBOR.pm +5 -2
  20. package/bin/exiftool_files/lib/Image/ExifTool/Canon.pm +68 -28
  21. package/bin/exiftool_files/lib/Image/ExifTool/CanonCustom.pm +1 -1
  22. package/bin/exiftool_files/lib/Image/ExifTool/CanonRaw.pm +1 -1
  23. package/bin/exiftool_files/lib/Image/ExifTool/CanonVRD.pm +1 -1
  24. package/bin/exiftool_files/lib/Image/ExifTool/CaptureOne.pm +1 -1
  25. package/bin/exiftool_files/lib/Image/ExifTool/Casio.pm +1 -1
  26. package/bin/exiftool_files/lib/Image/ExifTool/Charset.pm +1 -1
  27. package/bin/exiftool_files/lib/Image/ExifTool/DICOM.pm +1 -1
  28. package/bin/exiftool_files/lib/Image/ExifTool/DJI.pm +196 -30
  29. package/bin/exiftool_files/lib/Image/ExifTool/DNG.pm +1 -1
  30. package/bin/exiftool_files/lib/Image/ExifTool/DPX.pm +1 -1
  31. package/bin/exiftool_files/lib/Image/ExifTool/DV.pm +1 -1
  32. package/bin/exiftool_files/lib/Image/ExifTool/DarwinCore.pm +1 -1
  33. package/bin/exiftool_files/lib/Image/ExifTool/DjVu.pm +1 -1
  34. package/bin/exiftool_files/lib/Image/ExifTool/EXE.pm +138 -33
  35. package/bin/exiftool_files/lib/Image/ExifTool/Exif.pm +29 -16
  36. package/bin/exiftool_files/lib/Image/ExifTool/FITS.pm +3 -3
  37. package/bin/exiftool_files/lib/Image/ExifTool/FLAC.pm +1 -1
  38. package/bin/exiftool_files/lib/Image/ExifTool/FLIF.pm +3 -3
  39. package/bin/exiftool_files/lib/Image/ExifTool/FLIR.pm +1 -1
  40. package/bin/exiftool_files/lib/Image/ExifTool/Fixup.pm +1 -1
  41. package/bin/exiftool_files/lib/Image/ExifTool/Flash.pm +1 -1
  42. package/bin/exiftool_files/lib/Image/ExifTool/FlashPix.pm +17 -21
  43. package/bin/exiftool_files/lib/Image/ExifTool/Font.pm +2 -2
  44. package/bin/exiftool_files/lib/Image/ExifTool/FotoStation.pm +1 -1
  45. package/bin/exiftool_files/lib/Image/ExifTool/FujiFilm.pm +1 -1
  46. package/bin/exiftool_files/lib/Image/ExifTool/GE.pm +1 -1
  47. package/bin/exiftool_files/lib/Image/ExifTool/GIF.pm +144 -93
  48. package/bin/exiftool_files/lib/Image/ExifTool/GIMP.pm +1 -1
  49. package/bin/exiftool_files/lib/Image/ExifTool/GM.pm +1 -1
  50. package/bin/exiftool_files/lib/Image/ExifTool/GPS.pm +34 -30
  51. package/bin/exiftool_files/lib/Image/ExifTool/GeoTiff.pm +1 -1
  52. package/bin/exiftool_files/lib/Image/ExifTool/Geolocation.dat +0 -0
  53. package/bin/exiftool_files/lib/Image/ExifTool/Geolocation.pm +19 -9
  54. package/bin/exiftool_files/lib/Image/ExifTool/Geotag.pm +46 -12
  55. package/bin/exiftool_files/lib/Image/ExifTool/GoPro.pm +120 -8
  56. package/bin/exiftool_files/lib/Image/ExifTool/H264.pm +1 -1
  57. package/bin/exiftool_files/lib/Image/ExifTool/HP.pm +2 -2
  58. package/bin/exiftool_files/lib/Image/ExifTool/HTML.pm +1 -1
  59. package/bin/exiftool_files/lib/Image/ExifTool/HtmlDump.pm +1 -1
  60. package/bin/exiftool_files/lib/Image/ExifTool/ICC_Profile.pm +81 -2
  61. package/bin/exiftool_files/lib/Image/ExifTool/ICO.pm +1 -1
  62. package/bin/exiftool_files/lib/Image/ExifTool/ID3.pm +8 -8
  63. package/bin/exiftool_files/lib/Image/ExifTool/IPTC.pm +10 -7
  64. package/bin/exiftool_files/lib/Image/ExifTool/ISO.pm +1 -1
  65. package/bin/exiftool_files/lib/Image/ExifTool/ITC.pm +1 -1
  66. package/bin/exiftool_files/lib/Image/ExifTool/Import.pm +5 -4
  67. package/bin/exiftool_files/lib/Image/ExifTool/InDesign.pm +2 -2
  68. package/bin/exiftool_files/lib/Image/ExifTool/InfiRay.pm +1 -1
  69. package/bin/exiftool_files/lib/Image/ExifTool/JPEG.pm +38 -5
  70. package/bin/exiftool_files/lib/Image/ExifTool/JPEGDigest.pm +1 -1
  71. package/bin/exiftool_files/lib/Image/ExifTool/JSON.pm +1 -1
  72. package/bin/exiftool_files/lib/Image/ExifTool/JVC.pm +1 -1
  73. package/bin/exiftool_files/lib/Image/ExifTool/Jpeg2000.pm +10 -9
  74. package/bin/exiftool_files/lib/Image/ExifTool/Kodak.pm +1 -1
  75. package/bin/exiftool_files/lib/Image/ExifTool/KyoceraRaw.pm +1 -1
  76. package/bin/exiftool_files/lib/Image/ExifTool/LIF.pm +1 -1
  77. package/bin/exiftool_files/lib/Image/ExifTool/LNK.pm +2 -2
  78. package/bin/exiftool_files/lib/Image/ExifTool/Lang/cs.pm +1 -1
  79. package/bin/exiftool_files/lib/Image/ExifTool/Lang/de.pm +1 -1
  80. package/bin/exiftool_files/lib/Image/ExifTool/Lang/en_ca.pm +1 -1
  81. package/bin/exiftool_files/lib/Image/ExifTool/Lang/en_gb.pm +1 -1
  82. package/bin/exiftool_files/lib/Image/ExifTool/Lang/es.pm +1 -1
  83. package/bin/exiftool_files/lib/Image/ExifTool/Lang/fi.pm +1 -1
  84. package/bin/exiftool_files/lib/Image/ExifTool/Lang/fr.pm +1 -1
  85. package/bin/exiftool_files/lib/Image/ExifTool/Lang/it.pm +1 -1
  86. package/bin/exiftool_files/lib/Image/ExifTool/Lang/ja.pm +1 -1
  87. package/bin/exiftool_files/lib/Image/ExifTool/Lang/ko.pm +1 -1
  88. package/bin/exiftool_files/lib/Image/ExifTool/Lang/nl.pm +1 -1
  89. package/bin/exiftool_files/lib/Image/ExifTool/Lang/pl.pm +1 -1
  90. package/bin/exiftool_files/lib/Image/ExifTool/Lang/ru.pm +1 -1
  91. package/bin/exiftool_files/lib/Image/ExifTool/Lang/sk.pm +1 -1
  92. package/bin/exiftool_files/lib/Image/ExifTool/Lang/sv.pm +1 -1
  93. package/bin/exiftool_files/lib/Image/ExifTool/Lang/tr.pm +1 -1
  94. package/bin/exiftool_files/lib/Image/ExifTool/Lang/zh_cn.pm +1 -1
  95. package/bin/exiftool_files/lib/Image/ExifTool/Lang/zh_tw.pm +1 -1
  96. package/bin/exiftool_files/lib/Image/ExifTool/Leaf.pm +1 -1
  97. package/bin/exiftool_files/lib/Image/ExifTool/LigoGPS.pm +409 -0
  98. package/bin/exiftool_files/lib/Image/ExifTool/Lytro.pm +1 -1
  99. package/bin/exiftool_files/lib/Image/ExifTool/M2TS.pm +57 -18
  100. package/bin/exiftool_files/lib/Image/ExifTool/MIE.pm +15 -6
  101. package/bin/exiftool_files/lib/Image/ExifTool/MIEUnits.pod +1 -1
  102. package/bin/exiftool_files/lib/Image/ExifTool/MIFF.pm +1 -1
  103. package/bin/exiftool_files/lib/Image/ExifTool/MISB.pm +1 -1
  104. package/bin/exiftool_files/lib/Image/ExifTool/MNG.pm +1 -1
  105. package/bin/exiftool_files/lib/Image/ExifTool/MOI.pm +1 -1
  106. package/bin/exiftool_files/lib/Image/ExifTool/MPC.pm +1 -1
  107. package/bin/exiftool_files/lib/Image/ExifTool/MPEG.pm +1 -1
  108. package/bin/exiftool_files/lib/Image/ExifTool/MPF.pm +1 -1
  109. package/bin/exiftool_files/lib/Image/ExifTool/MRC.pm +1 -1
  110. package/bin/exiftool_files/lib/Image/ExifTool/MWG.pm +1 -1
  111. package/bin/exiftool_files/lib/Image/ExifTool/MXF.pm +3 -3
  112. package/bin/exiftool_files/lib/Image/ExifTool/MacOS.pm +3 -2
  113. package/bin/exiftool_files/lib/Image/ExifTool/MakerNotes.pm +1 -1
  114. package/bin/exiftool_files/lib/Image/ExifTool/Matroska.pm +22 -6
  115. package/bin/exiftool_files/lib/Image/ExifTool/Microsoft.pm +2 -2
  116. package/bin/exiftool_files/lib/Image/ExifTool/Minolta.pm +1 -1
  117. package/bin/exiftool_files/lib/Image/ExifTool/MinoltaRaw.pm +1 -1
  118. package/bin/exiftool_files/lib/Image/ExifTool/Motorola.pm +1 -1
  119. package/bin/exiftool_files/lib/Image/ExifTool/Nikon.pm +457 -103
  120. package/bin/exiftool_files/lib/Image/ExifTool/NikonCapture.pm +1 -1
  121. package/bin/exiftool_files/lib/Image/ExifTool/NikonCustom.pm +6 -6
  122. package/bin/exiftool_files/lib/Image/ExifTool/NikonSettings.pm +1 -1
  123. package/bin/exiftool_files/lib/Image/ExifTool/Nintendo.pm +1 -1
  124. package/bin/exiftool_files/lib/Image/ExifTool/OOXML.pm +8 -8
  125. package/bin/exiftool_files/lib/Image/ExifTool/Ogg.pm +1 -1
  126. package/bin/exiftool_files/lib/Image/ExifTool/Olympus.pm +1 -1
  127. package/bin/exiftool_files/lib/Image/ExifTool/OpenEXR.pm +1 -1
  128. package/bin/exiftool_files/lib/Image/ExifTool/Opus.pm +1 -1
  129. package/bin/exiftool_files/lib/Image/ExifTool/Other.pm +1 -1
  130. package/bin/exiftool_files/lib/Image/ExifTool/PCX.pm +1 -1
  131. package/bin/exiftool_files/lib/Image/ExifTool/PDF.pm +49 -18
  132. package/bin/exiftool_files/lib/Image/ExifTool/PGF.pm +1 -1
  133. package/bin/exiftool_files/lib/Image/ExifTool/PICT.pm +1 -1
  134. package/bin/exiftool_files/lib/Image/ExifTool/PLIST.pm +4 -4
  135. package/bin/exiftool_files/lib/Image/ExifTool/PLUS.pm +1 -1
  136. package/bin/exiftool_files/lib/Image/ExifTool/PNG.pm +20 -8
  137. package/bin/exiftool_files/lib/Image/ExifTool/PPM.pm +12 -3
  138. package/bin/exiftool_files/lib/Image/ExifTool/PSP.pm +1 -1
  139. package/bin/exiftool_files/lib/Image/ExifTool/Palm.pm +1 -1
  140. package/bin/exiftool_files/lib/Image/ExifTool/Panasonic.pm +27 -3
  141. package/bin/exiftool_files/lib/Image/ExifTool/PanasonicRaw.pm +1 -1
  142. package/bin/exiftool_files/lib/Image/ExifTool/Parrot.pm +1 -1
  143. package/bin/exiftool_files/lib/Image/ExifTool/Pentax.pm +1 -1
  144. package/bin/exiftool_files/lib/Image/ExifTool/PhaseOne.pm +4 -4
  145. package/bin/exiftool_files/lib/Image/ExifTool/PhotoCD.pm +1 -1
  146. package/bin/exiftool_files/lib/Image/ExifTool/PhotoMechanic.pm +1 -1
  147. package/bin/exiftool_files/lib/Image/ExifTool/Photoshop.pm +65 -4
  148. package/bin/exiftool_files/lib/Image/ExifTool/PostScript.pm +1 -1
  149. package/bin/exiftool_files/lib/Image/ExifTool/PrintIM.pm +1 -1
  150. package/bin/exiftool_files/lib/Image/ExifTool/Protobuf.pm +270 -0
  151. package/bin/exiftool_files/lib/Image/ExifTool/Qualcomm.pm +1 -1
  152. package/bin/exiftool_files/lib/Image/ExifTool/QuickTime.pm +327 -88
  153. package/bin/exiftool_files/lib/Image/ExifTool/QuickTimeStream.pl +199 -195
  154. package/bin/exiftool_files/lib/Image/ExifTool/README +12 -2
  155. package/bin/exiftool_files/lib/Image/ExifTool/RIFF.pm +21 -6
  156. package/bin/exiftool_files/lib/Image/ExifTool/RSRC.pm +1 -1
  157. package/bin/exiftool_files/lib/Image/ExifTool/RTF.pm +2 -2
  158. package/bin/exiftool_files/lib/Image/ExifTool/Radiance.pm +1 -1
  159. package/bin/exiftool_files/lib/Image/ExifTool/Rawzor.pm +1 -1
  160. package/bin/exiftool_files/lib/Image/ExifTool/Real.pm +1 -1
  161. package/bin/exiftool_files/lib/Image/ExifTool/Reconyx.pm +1 -1
  162. package/bin/exiftool_files/lib/Image/ExifTool/Red.pm +1 -1
  163. package/bin/exiftool_files/lib/Image/ExifTool/Ricoh.pm +4 -4
  164. package/bin/exiftool_files/lib/Image/ExifTool/Samsung.pm +6 -2
  165. package/bin/exiftool_files/lib/Image/ExifTool/Sanyo.pm +1 -1
  166. package/bin/exiftool_files/lib/Image/ExifTool/Scalado.pm +1 -1
  167. package/bin/exiftool_files/lib/Image/ExifTool/Shift.pl +1 -1
  168. package/bin/exiftool_files/lib/Image/ExifTool/Shortcuts.pm +1 -1
  169. package/bin/exiftool_files/lib/Image/ExifTool/Sigma.pm +1 -1
  170. package/bin/exiftool_files/lib/Image/ExifTool/SigmaRaw.pm +1 -1
  171. package/bin/exiftool_files/lib/Image/ExifTool/Sony.pm +6 -5
  172. package/bin/exiftool_files/lib/Image/ExifTool/SonyIDC.pm +1 -1
  173. package/bin/exiftool_files/lib/Image/ExifTool/Stim.pm +1 -1
  174. package/bin/exiftool_files/lib/Image/ExifTool/TagInfoXML.pm +6 -5
  175. package/bin/exiftool_files/lib/Image/ExifTool/TagLookup.pm +7028 -6968
  176. package/bin/exiftool_files/lib/Image/ExifTool/TagNames.pod +12079 -11630
  177. package/bin/exiftool_files/lib/Image/ExifTool/Text.pm +4 -3
  178. package/bin/exiftool_files/lib/Image/ExifTool/Theora.pm +1 -1
  179. package/bin/exiftool_files/lib/Image/ExifTool/Torrent.pm +3 -3
  180. package/bin/exiftool_files/lib/Image/ExifTool/Trailer.pm +318 -0
  181. package/bin/exiftool_files/lib/Image/ExifTool/Unknown.pm +1 -1
  182. package/bin/exiftool_files/lib/Image/ExifTool/VCard.pm +3 -3
  183. package/bin/exiftool_files/lib/Image/ExifTool/Validate.pm +6 -6
  184. package/bin/exiftool_files/lib/Image/ExifTool/Vorbis.pm +1 -1
  185. package/bin/exiftool_files/lib/Image/ExifTool/WPG.pm +1 -1
  186. package/bin/exiftool_files/lib/Image/ExifTool/WTV.pm +1 -1
  187. package/bin/exiftool_files/lib/Image/ExifTool/WriteCanonRaw.pl +1 -1
  188. package/bin/exiftool_files/lib/Image/ExifTool/WriteExif.pl +3 -3
  189. package/bin/exiftool_files/lib/Image/ExifTool/WriteIPTC.pl +1 -1
  190. package/bin/exiftool_files/lib/Image/ExifTool/WritePDF.pl +1 -1
  191. package/bin/exiftool_files/lib/Image/ExifTool/WritePNG.pl +1 -1
  192. package/bin/exiftool_files/lib/Image/ExifTool/WritePhotoshop.pl +1 -1
  193. package/bin/exiftool_files/lib/Image/ExifTool/WritePostScript.pl +1 -1
  194. package/bin/exiftool_files/lib/Image/ExifTool/WriteQuickTime.pl +170 -79
  195. package/bin/exiftool_files/lib/Image/ExifTool/WriteRIFF.pl +17 -6
  196. package/bin/exiftool_files/lib/Image/ExifTool/WriteXMP.pl +3 -3
  197. package/bin/exiftool_files/lib/Image/ExifTool/Writer.pl +89 -96
  198. package/bin/exiftool_files/lib/Image/ExifTool/XISF.pm +1 -1
  199. package/bin/exiftool_files/lib/Image/ExifTool/XMP.pm +28 -13
  200. package/bin/exiftool_files/lib/Image/ExifTool/XMP2.pl +106 -3
  201. package/bin/exiftool_files/lib/Image/ExifTool/XMPStruct.pl +2 -3
  202. package/bin/exiftool_files/lib/Image/ExifTool/ZIP.pm +2 -2
  203. package/bin/exiftool_files/lib/Image/ExifTool/ZISRAW.pm +1 -1
  204. package/bin/exiftool_files/lib/Image/ExifTool/iWork.pm +1 -1
  205. package/bin/exiftool_files/lib/Image/ExifTool.pm +467 -228
  206. package/bin/exiftool_files/lib/Image/ExifTool.pod +118 -72
  207. package/bin/exiftool_files/windows_exiftool.txt +96 -51
  208. package/package.json +8 -8
@@ -15,7 +15,7 @@ use strict;
15
15
  use vars qw($VERSION);
16
16
  use Image::ExifTool qw(:DataAccess :Utils);
17
17
 
18
- $VERSION = '1.04';
18
+ $VERSION = '1.05';
19
19
 
20
20
  # Text tags
21
21
  %Image::ExifTool::Text::Main = (
@@ -191,7 +191,8 @@ sub ProcessTXT($$)
191
191
  $enc = 'unknown-8bit';
192
192
  }
193
193
  }
194
- if ($$et{VALUE}{MIMEEncoding} ne $enc) {
194
+ # ($$et{VALUE}{MIMEEncoding} may be undef if it was ignored)
195
+ if (defined $$et{VALUE}{MIMEEncoding} and $$et{VALUE}{MIMEEncoding} ne $enc) {
195
196
  $$et{VALUE}{MIMEEncoding} = $enc;
196
197
  $et->VPrint(0," MIMEEncoding [override] = $enc\n");
197
198
  }
@@ -221,7 +222,7 @@ characteristics of TXT and CSV files.
221
222
 
222
223
  =head1 AUTHOR
223
224
 
224
- Copyright 2003-2024, Phil Harvey (philharvey66 at gmail.com)
225
+ Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
225
226
 
226
227
  This library is free software; you can redistribute it and/or modify it
227
228
  under the same terms as Perl itself.
@@ -122,7 +122,7 @@ information from Theora video streams.
122
122
 
123
123
  =head1 AUTHOR
124
124
 
125
- Copyright 2003-2024, Phil Harvey (philharvey66 at gmail.com)
125
+ Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
126
126
 
127
127
  This library is free software; you can redistribute it and/or modify it
128
128
  under the same terms as Perl itself.
@@ -14,7 +14,7 @@ use strict;
14
14
  use vars qw($VERSION);
15
15
  use Image::ExifTool qw(:DataAccess :Utils);
16
16
 
17
- $VERSION = '1.06';
17
+ $VERSION = '1.07';
18
18
 
19
19
  sub ReadBencode($$$);
20
20
  sub ExtractTags($$$;$$@);
@@ -282,7 +282,7 @@ sub ProcessTorrent($$)
282
282
  my $dict = ReadBencode($et, $raf, \$buff);
283
283
  my $err = $$raf{BencodeError};
284
284
  $et->Warn("Bencode error: $err") if $err;
285
- if (ref $dict eq 'HASH' and ($$dict{announce} or $$dict{'created by'})) {
285
+ if (ref $dict eq 'HASH' and ($$dict{announce} or $$dict{'created by'} or $$dict{info})) {
286
286
  $et->SetFileType();
287
287
  my $tagTablePtr = GetTagTable('Image::ExifTool::Torrent::Main');
288
288
  ExtractTags($et, $dict, $tagTablePtr) and $success = 1;
@@ -309,7 +309,7 @@ bencoded information from BitTorrent files.
309
309
 
310
310
  =head1 AUTHOR
311
311
 
312
- Copyright 2003-2024, Phil Harvey (philharvey66 at gmail.com)
312
+ Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
313
313
 
314
314
  This library is free software; you can redistribute it and/or modify it
315
315
  under the same terms as Perl itself.
@@ -0,0 +1,318 @@
1
+ #------------------------------------------------------------------------------
2
+ # File: Trailer.pm
3
+ #
4
+ # Description: Read JPEG trailer written by various makes of phone
5
+ #
6
+ # Revisions: 2025-01-27 - P. Harvey Created
7
+ #------------------------------------------------------------------------------
8
+
9
+ package Image::ExifTool::Trailer;
10
+
11
+ use strict;
12
+ use vars qw($VERSION);
13
+ use Image::ExifTool qw(:DataAccess :Utils);
14
+
15
+ $VERSION = '1.00';
16
+
17
+ %Image::ExifTool::Trailer::Vivo = (
18
+ GROUPS => { 0 => 'Trailer', 1 => 'Vivo', 2 => 'Image' },
19
+ VARS => { NO_ID => 1 },
20
+ NOTES => 'Information written in JPEG trailer by some Vivo phones.',
21
+ # (don't know for sure what type of image this is, but it is in JPEG format)
22
+ HDRImage => {
23
+ Notes => 'highlights of HDR image',
24
+ Groups => { 2 => 'Preview' },
25
+ Binary => 1,
26
+ },
27
+ JSONInfo => { },
28
+ HiddenData => {
29
+ Notes => 'hidden in EXIF, not in trailer. This data is lost if the file is edited',
30
+ Groups => { 0 => 'EXIF' },
31
+ },
32
+ );
33
+
34
+ %Image::ExifTool::Trailer::OnePlus = (
35
+ GROUPS => { 0 => 'Trailer', 1 => 'OnePlus', 2 => 'Image' },
36
+ NOTES => 'Information written in JPEG trailer by some OnePlus phones.',
37
+ JSONInfo => { },
38
+ 'private.emptyspace' => { # length of the entire OnePlus trailer
39
+ Name => 'OnePlusTrailerLen',
40
+ ValueConv => 'length $val == 4 ? unpack("N", $val) : $val',
41
+ Unknown => 1,
42
+ },
43
+ 'watermark.device' => {
44
+ Name => 'Device',
45
+ ValueConv => '"0x" . join(" ", unpack("H10Z*", $val))',
46
+ Format => 'string',
47
+ },
48
+ );
49
+
50
+ # Google and/or Android information in JPEG trailer
51
+ %Image::ExifTool::Trailer::Google = (
52
+ GROUPS => { 0 => 'Trailer', 1 => 'Google', 2 => 'Image' },
53
+ NOTES => q{
54
+ Google-defined information written in the trailer of JPEG images by some
55
+ phones. This information is referenced by DirectoryItem entries in the XMP.
56
+ Note that some of this information may also be referenced from other
57
+ metadata formats, and hence may be extracted twice. For example,
58
+ MotionPhotoVideo may also exist within a Samsung trailer as
59
+ EmbbededVideoFile, or GainMapImage may also exist in an MPF trailer as
60
+ MPImage2.
61
+ },
62
+ MotionPhoto => { Name => 'MotionPhotoVideo', Groups => { 2 => 'Video' } },
63
+ GainMap => { Name => 'GainMapImage', Groups => { 2 => 'Preview' } },
64
+ Depth => { Name => 'DepthMapImage', Groups => { 2 => 'Preview' } },
65
+ Confidence => { Name => 'ConfidenceMapImage',Groups => { 2 => 'Preview' } },
66
+ 'android/depthmap' => { Name => 'DepthMapImage', Groups => { 2 => 'Preview' } },
67
+ 'android/confidencemap' => { Name => 'ConfidenceMapImage', Groups => { 2 => 'Preview' } },
68
+ );
69
+
70
+ #------------------------------------------------------------------------------
71
+ # Process Vivo trailer
72
+ # Inputs: 0) ExifTool object reference, 1) dirInfo reference
73
+ # Returns: 1 on success, 0 on failure, -1 if we must scan for the start
74
+ # of the trailer to set the ExifTool TrailerStart member
75
+ # - takes Offset as positive offset from end of trailer to end of file,
76
+ # and returns DataPos and DirLen, and updates OutFile when writing
77
+ sub ProcessVivo($$)
78
+ {
79
+ my ($et, $dirInfo) = @_;
80
+ my $raf = $$dirInfo{RAF};
81
+ my $buff;
82
+
83
+ # return now unless we are at a position to scan for the trailer
84
+ # (must scan because the trailer footer doesn't indicate the trailer length)
85
+ return -1 unless $$dirInfo{ScanForTrailer};
86
+
87
+ my $pos = $$et{TrailerStart} or return 0;
88
+ my $len = $$et{FileEnd} - $pos - $$dirInfo{Offset};
89
+ $raf->Seek($pos, 0) or return 0;
90
+ return 0 unless $len > 0 and $len < 1e7 and $raf->Read($buff, $len) == $len and
91
+ $buff =~ /\xff{4}\x1b\*9HWfu\x84\x93\xa2\xb1$/ and # validate footer
92
+ $buff =~ /(streamdata|vivo\{")/g; # find start
93
+ my $start = pos($buff) - length($1);
94
+ if ($start) {
95
+ $pos += $start;
96
+ $len -= $start;
97
+ $buff = substr($buff, $start);
98
+ }
99
+ # set trailer position and length
100
+ @$dirInfo{'DataPos','DirLen'} = ($pos, $len);
101
+
102
+ # let ProcessTrailers copy or delete this trailer
103
+ return -1 if $$dirInfo{OutFile};
104
+
105
+ $et->DumpTrailer($dirInfo) if $$et{OPTIONS}{Verbose} or $$et{HTML_DUMP};
106
+ my $tbl = GetTagTable('Image::ExifTool::Trailer::Vivo');
107
+ pos($buff) = 0; # rewind search to start of buffer
108
+ if ($buff =~ /^streamdata\xff\xd8\xff/ and $buff =~ /\xff\xd9stream(info|coun)/g) {
109
+ $et->HandleTag($tbl, HDRImage => substr($buff, 10, pos($buff)-20));
110
+ }
111
+ # continue looking for Vivo JSON data
112
+ if ($buff =~ /vivo\{"/g) {
113
+ my $jsonStart = pos($buff) - 2;
114
+ if ($buff =~ /\}\0/g) {
115
+ my $jsonLen = pos($buff) - 1 - $jsonStart;
116
+ $et->HandleTag($tbl, JSONInfo => substr($buff, $jsonStart, $jsonLen));
117
+ }
118
+ }
119
+ return 1;
120
+ }
121
+
122
+ #------------------------------------------------------------------------------
123
+ # Process OnePlus trailer
124
+ # Inputs: 0) ExifTool object reference, 1) dirInfo reference
125
+ # Returns: 1 on success, 0 on failure, -1 if we must scan for the start
126
+ # of the trailer to set the ExifTool TrailerStart member
127
+ # - takes Offset as positive offset from end of trailer to end of file,
128
+ # and returns DataPos and DirLen, and updates OutFile when writing
129
+ sub ProcessOnePlus($$)
130
+ {
131
+ my ($et, $dirInfo) = @_;
132
+ my $raf = $$dirInfo{RAF};
133
+ my ($buff, $buf2);
134
+
135
+ # return now unless we are at a position to scan for the trailer
136
+ # (must scan because the trailer footer doesn't indicate the entire trailer length)
137
+ return -1 unless $$dirInfo{ScanForTrailer};
138
+
139
+ # return -1 to let ProcessTrailers copy or delete the entire trailer
140
+ return -1 if $$dirInfo{OutFile};
141
+
142
+ my $start = $$et{TrailerStart} or return 0;
143
+ $raf->Seek(-8-$$dirInfo{Offset}, 2) and $raf->Read($buff, 8) == 8 or return 0;
144
+ my $end = $raf->Tell(); # (same as FileEnd - Offset)
145
+
146
+ my $dump = ($$et{OPTIONS}{Verbose} or $$et{HTML_DUMP});
147
+ my $tagTable = GetTagTable('Image::ExifTool::Trailer::OnePlus');
148
+ my $trailLen = 0;
149
+ if ($buff =~ /^jxrs...\0$/) {
150
+ my $jlen = unpack('x4V', $buff);
151
+ my $maxOff = 0;
152
+ if ($jlen < $end-$start and $jlen > 8 and $raf->Seek($end-$jlen) and
153
+ $raf->Read($buff, $jlen-8) == $jlen-8)
154
+ {
155
+ $buff =~ s/\0+$//; # remove trailing null(s)
156
+ require Image::ExifTool::Import;
157
+ my $list = Image::ExifTool::Import::ReadJSONObject(undef, \$buff);
158
+ if (ref $list eq 'ARRAY') {
159
+ $$_{offset} and $$_{offset} > $maxOff and $maxOff = $$_{offset} foreach @$list;
160
+ $trailLen = $maxOff + $jlen;
161
+ if ($dump and $trailLen) {
162
+ $et->DumpTrailer({
163
+ RAF => $raf,
164
+ DirName => 'OnePlus',
165
+ DataPos => $end-$trailLen,
166
+ DirLen => $trailLen,
167
+ });
168
+ }
169
+ $et->HandleTag($tagTable, JSONInfo => $buff);
170
+ foreach (@$list) {
171
+ my ($off, $name, $len) = @$_{qw(offset name length)};
172
+ next unless $off and $name and $len;
173
+ if ($raf->Seek($end-$jlen-$off) and $raf->Read($buf2, $len) == $len) {
174
+ $et->HandleTag($tagTable, $name, $buf2, DataPos => $end-$jlen-$off, DataPt => \$buf2);
175
+ }
176
+ }
177
+ } else {
178
+ $et->HandleTag($tagTable, JSONInfo => $buff);
179
+ $et->Warn('Error parsing OnePlus JSON information');
180
+ }
181
+ }
182
+ }
183
+ @$dirInfo{'DataPos','DirLen'} = ($end - $trailLen, $trailLen);
184
+
185
+ return 1;
186
+ }
187
+
188
+ #------------------------------------------------------------------------------
189
+ # Process Google trailer
190
+ # Inputs: 0) ExifTool object reference, 1) dirInfo reference
191
+ # Returns: 1 on success, 0 on failure, -1 if we must scan for the start
192
+ # of the trailer to set the ExifTool TrailerStart member
193
+ # - this trailer won't be identified when writing because XMP isn't extracted then
194
+ sub ProcessGoogle($$)
195
+ {
196
+ my ($et, $dirInfo) = @_;
197
+ my $raf = $$dirInfo{RAF};
198
+ my $info = $$et{VALUE};
199
+
200
+ my ($tag, $mime, $len, $pad) = @$info{qw(DirectoryItemSemantic DirectoryItemMime
201
+ DirectoryItemLength DirectoryItemPadding)};
202
+
203
+ unless (ref $tag eq 'ARRAY' and ref $mime eq 'ARRAY') {
204
+ undef $pad;
205
+ ($tag, $mime, $len) = @$info{qw(ContainerDirectoryItemDataURI
206
+ ContainerDirectoryItemMime ContainerDirectoryItemLength)};
207
+ unless (ref $mime eq 'ARRAY' and ref $tag eq 'ARRAY') {
208
+ delete $$et{ProcessGoogleTrailer};
209
+ return 0;
210
+ }
211
+ }
212
+ # we need to know TrailerStart to be able to read/write this trailer
213
+ return -1 unless $$dirInfo{ScanForTrailer};
214
+
215
+ delete $$et{ProcessGoogleTrailer}; # reset flag to process the Google trailer
216
+
217
+ return -1 if $$dirInfo{OutFile};
218
+
219
+ # sometimes DirectoryItemLength is missing the Primary entry
220
+ $len = [ $len ] unless ref $len eq 'ARRAY';
221
+ unshift @$len, 0 while @$len < @$mime;
222
+
223
+ my $start = $$et{TrailerStart} or return 0;
224
+ my $end = $$et{FileEnd}; # (ignore Offset for now because some entries may run into other trailers)
225
+
226
+ my $dump = ($$et{OPTIONS}{Verbose} or $$et{HTML_DUMP});
227
+ my $tagTable = GetTagTable('Image::ExifTool::Trailer::Google');
228
+
229
+ # (ignore first entry: "Primary" or "primary_image")
230
+ my ($i, $pos, $buff, $regex, $grp, $type);
231
+ for ($i=1, $pos=0; defined $$mime[$i]; ++$i) {
232
+ my $more = $end - $start - $pos;
233
+ last if $more < 16;
234
+ next unless $$len[$i] and defined $$tag[$i];
235
+ last if $$len[$i] > $more;
236
+ $raf->Seek($start+$pos) and $raf->Read($buff, 16) == 16 and $raf->Seek($start+$pos) or last;
237
+ if ($$mime[$i] eq 'image/jpeg') {
238
+ $regex = '\xff\xd8\xff[\xdb\xe0\xe1]';
239
+ } elsif ($$mime[$i] eq 'video/mp4') {
240
+ $regex = '\0\0\0.ftyp(mp42|isom)';
241
+ } else {
242
+ $et->Warn("Google trailer $$tag[$i] $$mime[$i] not handled");
243
+ next;
244
+ }
245
+ if ($buff =~ /^$regex/s) {
246
+ last unless $raf->Read($buff, $$len[$i]) == $$len[$i];
247
+ } else {
248
+ last if $pos; # don't skip unknown information again
249
+ last unless $raf->Read($buff, $more) == $more;
250
+ last unless $buff =~ /($regex)/sg;
251
+ $pos += pos($buff) - length($1);
252
+ $more = $end - $start - $pos;
253
+ last if $$len[$i] > $end - $start - $pos;
254
+ $buff = substr($buff, $pos, $$len[$i]);
255
+ }
256
+ unless ($$tagTable{$$tag[$i]}) {
257
+ my $name = $$tag[$i];
258
+ $name =~ s/([^A-Za-z])([a-z])/$1\u$2/g; # capitalize words
259
+ $name = Image::ExifTool::MakeTagName($$tag[$i]);
260
+ if ($$mime[$i] eq 'image/jpeg') {
261
+ ($type, $grp) = ('Image', 'Preview');
262
+ } else {
263
+ ($type, $grp) = ('Video', 'Video');
264
+ }
265
+ $et->VPrint(0, $$et{INDENT}, "[adding Google:$name]\n");
266
+ AddTagToTable($tagTable, $$tag[$i], { Name => "$name$type", Groups => { 2 => $grp } });
267
+ }
268
+ $dump and $et->DumpTrailer({
269
+ RAF => $raf,
270
+ DirName => $$tag[$i],
271
+ DataPos => $start + $pos,
272
+ DirLen => $$len[$i],
273
+ });
274
+ $et->HandleTag($tagTable, $$tag[$i], \$buff, { DataPos => $start + $pos, DataPt => \$buff });
275
+ # (haven't seen non-zero padding, but I assume this is how it works
276
+ $pos += $$len[$i] + (($pad and $$pad[$i]) ? $$pad[$i] : 0);
277
+ }
278
+ if (defined $$tag[$i] and defined $$mime[$i]) {
279
+ $et->Warn("Error reading $$tag[$i] $$mime[$i] from trailer", 1);
280
+ }
281
+ return 0 unless $pos;
282
+
283
+ @$dirInfo{'DataPos','DirLen'} = ($start, $pos);
284
+
285
+ return 1;
286
+ }
287
+
288
+ 1; # end
289
+
290
+ __END__
291
+
292
+ =head1 NAME
293
+
294
+ Image::ExifTool::Trailer - Read JPEG trailer written by various phone makes
295
+
296
+ =head1 SYNOPSIS
297
+
298
+ This module is used by Image::ExifTool
299
+
300
+ =head1 DESCRIPTION
301
+
302
+ This module contains definitions required by Image::ExifTool to read
303
+ metadata the trailer written by some Vivo, OnePlus and Google phones.
304
+
305
+ =head1 AUTHOR
306
+
307
+ Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
308
+
309
+ This library is free software; you can redistribute it and/or modify it
310
+ under the same terms as Perl itself.
311
+
312
+ =head1 SEE ALSO
313
+
314
+ L<Image::ExifTool::TagNames/Trailer Tags>,
315
+ L<Image::ExifTool(3pm)|Image::ExifTool>
316
+
317
+ =cut
318
+
@@ -53,7 +53,7 @@ unknown manufacturers.
53
53
 
54
54
  =head1 AUTHOR
55
55
 
56
- Copyright 2003-2024, Phil Harvey (philharvey66 at gmail.com)
56
+ Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
57
57
 
58
58
  This library is free software; you can redistribute it and/or modify it
59
59
  under the same terms as Perl itself.
@@ -325,7 +325,7 @@ sub ProcessVCard($$)
325
325
  $$et{DOC_NUM} = ++$$et{DOC_COUNT}; # read next card as a new document
326
326
  }
327
327
  unless ($val =~ s/^([-A-Za-z0-9.]+)//) {
328
- $et->WarnOnce("Unrecognized line in $lbl file");
328
+ $et->Warn("Unrecognized line in $lbl file");
329
329
  next;
330
330
  }
331
331
  my $tag = $1;
@@ -379,7 +379,7 @@ sub ProcessVCard($$)
379
379
  $param{$p} = '';
380
380
  }
381
381
  }
382
- $val =~ s/^:// or $et->WarnOnce("Invalid line in $lbl file"), next;
382
+ $val =~ s/^:// or $et->Warn("Invalid line in $lbl file"), next;
383
383
  # add 'Type' parameter to id and name if it exists
384
384
  $param{Type} and $tag .= $param{Type}, $name .= $param{Type};
385
385
  # convert base64-encoded data
@@ -430,7 +430,7 @@ information from vCard VCF and iCalendar ICS files.
430
430
 
431
431
  =head1 AUTHOR
432
432
 
433
- Copyright 2003-2024, Phil Harvey (philharvey66 at gmail.com)
433
+ Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
434
434
 
435
435
  This library is free software; you can redistribute it and/or modify it
436
436
  under the same terms as Perl itself.
@@ -17,7 +17,7 @@ package Image::ExifTool::Validate;
17
17
  use strict;
18
18
  use vars qw($VERSION %exifSpec);
19
19
 
20
- $VERSION = '1.23';
20
+ $VERSION = '1.24';
21
21
 
22
22
  use Image::ExifTool qw(:Utils);
23
23
  use Image::ExifTool::Exif;
@@ -421,7 +421,7 @@ sub ValidateExif($$$$$$$$)
421
421
  {
422
422
  my ($et, $tagTablePtr, $tag, $tagInfo, $lastTag, $ifd, $count, $formatStr) = @_;
423
423
 
424
- $et->WarnOnce("Entries in $ifd are out of order") if $tag <= $lastTag;
424
+ $et->Warn("Entries in $ifd are out of order") if $tag <= $lastTag;
425
425
 
426
426
  # (get tagInfo for unknown tags if Unknown option not used)
427
427
  if (not defined $tagInfo and $$tagTablePtr{$tag} and ref $$tagTablePtr{$tag} eq 'HASH') {
@@ -532,8 +532,8 @@ sub ValidateOffsetInfo($$$;$)
532
532
  while (@offsets) {
533
533
  my $start = pop @offsets;
534
534
  my $end = $start + pop @sizes;
535
- $et->WarnOnce("$dirName:$$offsets[0]{Name} is zero", $minor) if $start == 0;
536
- $et->WarnOnce("$dirName:$$sizes[0]{Name} is zero", $minor) if $start == $end;
535
+ $et->Warn("$dirName:$$offsets[0]{Name} is zero", $minor) if $start == 0;
536
+ $et->Warn("$dirName:$$sizes[0]{Name} is zero", $minor) if $start == $end;
537
537
  next unless $end > $fileSize;
538
538
  if ($start >= $fileSize) {
539
539
  if ($start == 0xffffffff) {
@@ -575,7 +575,7 @@ sub FinishValidate($$)
575
575
  # get all tags in this group
576
576
  foreach $key (sort keys %{$$et{VALUE}}) {
577
577
  next unless $et->GetGroup($key, 1) eq $grp;
578
- next if $$et{TAG_EXTRA}{$key} and $$et{TAG_EXTRA}{$key}{G3}; # ignore sub-documents
578
+ next if $$et{TAG_EXTRA}{$key}{G3}; # ignore sub-documents
579
579
  # fill in %val lookup with values based on tag ID
580
580
  my $tag = $$et{TAG_INFO}{$key}{TagID};
581
581
  $val{$tag} = $$et{VALUE}{$key};
@@ -678,7 +678,7 @@ ExifTool Validate option is enabled.
678
678
 
679
679
  =head1 AUTHOR
680
680
 
681
- Copyright 2003-2024, Phil Harvey (philharvey66 at gmail.com)
681
+ Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
682
682
 
683
683
  This library is free software; you can redistribute it and/or modify it
684
684
  under the same terms as Perl itself.
@@ -228,7 +228,7 @@ information from Ogg Vorbis audio headers.
228
228
 
229
229
  =head1 AUTHOR
230
230
 
231
- Copyright 2003-2024, Phil Harvey (philharvey66 at gmail.com)
231
+ Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
232
232
 
233
233
  This library is free software; you can redistribute it and/or modify it
234
234
  under the same terms as Perl itself.
@@ -271,7 +271,7 @@ This module contains definitions required by Image::ExifTool to read WPG
271
271
 
272
272
  =head1 AUTHOR
273
273
 
274
- Copyright 2003-2024, Phil Harvey (philharvey66 at gmail.com)
274
+ Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
275
275
 
276
276
  This library is free software; you can redistribute it and/or modify it
277
277
  under the same terms as Perl itself.
@@ -297,7 +297,7 @@ This module contains definitions required by Image::ExifTool to read WTV
297
297
 
298
298
  =head1 AUTHOR
299
299
 
300
- Copyright 2003-2024, Phil Harvey (philharvey66 at gmail.com)
300
+ Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
301
301
 
302
302
  This library is free software; you can redistribute it and/or modify it
303
303
  under the same terms as Perl itself.
@@ -630,7 +630,7 @@ JPEG files, and would lead to far fewer problems with corrupted metadata.
630
630
 
631
631
  =head1 AUTHOR
632
632
 
633
- Copyright 2003-2024, Phil Harvey (philharvey66 at gmail.com)
633
+ Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
634
634
 
635
635
  This library is free software; you can redistribute it and/or modify it
636
636
  under the same terms as Perl itself.
@@ -387,8 +387,8 @@ sub ValidateImageData($$$;$)
387
387
  }
388
388
  push @bitsPerSample, $bitsPerSample[0] while @bitsPerSample < $samplesPerPix;
389
389
  foreach (@bitsPerSample) {
390
- $et->WarnOnce("$dirName BitsPerSample values are different", $minor) if $_ ne $bitsPerSample[0];
391
- $et->WarnOnce("Invalid $dirName BitsPerSample value", $minor) if $_ < 1 or $_ > 32;
390
+ $et->Warn("$dirName BitsPerSample values are different", $minor) if $_ ne $bitsPerSample[0];
391
+ $et->Warn("Invalid $dirName BitsPerSample value", $minor) if $_ < 1 or $_ > 32;
392
392
  }
393
393
  }
394
394
  my $bitsPerPixel = 0;
@@ -2725,7 +2725,7 @@ This file contains routines to write EXIF metadata.
2725
2725
 
2726
2726
  =head1 AUTHOR
2727
2727
 
2728
- Copyright 2003-2024, Phil Harvey (philharvey66 at gmail.com)
2728
+ Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
2729
2729
 
2730
2730
  This library is free software; you can redistribute it and/or modify it
2731
2731
  under the same terms as Perl itself.
@@ -711,7 +711,7 @@ seldom-used routines.
711
711
 
712
712
  =head1 AUTHOR
713
713
 
714
- Copyright 2003-2024, Phil Harvey (philharvey66 at gmail.com)
714
+ Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
715
715
 
716
716
  This library is free software; you can redistribute it and/or modify it
717
717
  under the same terms as Perl itself.
@@ -779,7 +779,7 @@ C<PDF-update> pseudo group).
779
779
 
780
780
  =head1 AUTHOR
781
781
 
782
- Copyright 2003-2024, Phil Harvey (philharvey66 at gmail.com)
782
+ Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
783
783
 
784
784
  This library is free software; you can redistribute it and/or modify it
785
785
  under the same terms as Perl itself.
@@ -401,7 +401,7 @@ strings).
401
401
 
402
402
  =head1 AUTHOR
403
403
 
404
- Copyright 2003-2024, Phil Harvey (philharvey66 at gmail.com)
404
+ Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
405
405
 
406
406
  This library is free software; you can redistribute it and/or modify it
407
407
  under the same terms as Perl itself.
@@ -257,7 +257,7 @@ default resource name, and applied if no appended name is provided.
257
257
 
258
258
  =head1 AUTHOR
259
259
 
260
- Copyright 2003-2024, Phil Harvey (philharvey66 at gmail.com)
260
+ Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
261
261
 
262
262
  This library is free software; you can redistribute it and/or modify it
263
263
  under the same terms as Perl itself.
@@ -687,7 +687,7 @@ Thanks to Tim Kordick for his help testing the EPS writer.
687
687
 
688
688
  =head1 AUTHOR
689
689
 
690
- Copyright 2003-2024, Phil Harvey (philharvey66 at gmail.com)
690
+ Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
691
691
 
692
692
  This library is free software; you can redistribute it and/or modify it
693
693
  under the same terms as Perl itself.