- Timestamp:
- 2021-02-26T19:39:51+13:00 (3 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
main/trunk/greenstone2/perllib/cpan/Image/ExifTool/ZIP.pm
r24107 r34921 10 10 # 3) http://www.gzip.org/zlib/rfc-gzip.html 11 11 # 4) http://DataCompression.info/ArchiveFormats/RAR202.txt 12 # 5) https://jira.atlassian.com/browse/CONF-21706 13 # 6) http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/indesign/cs55-docs/IDML/idml-specification.pdf 12 14 #------------------------------------------------------------------------------ 13 15 … … 18 20 use Image::ExifTool qw(:DataAccess :Utils); 19 21 20 $VERSION = '1. 07';22 $VERSION = '1.26'; 21 23 22 24 sub WarnProc($) { $warnString = $_[0]; } … … 24 26 # file types for recognized Open Document "mimetype" values 25 27 my %openDocType = ( 28 'application/vnd.oasis.opendocument.database' => 'ODB', #5 29 'application/vnd.oasis.opendocument.chart' => 'ODC', #5 30 'application/vnd.oasis.opendocument.formula' => 'ODF', #5 31 'application/vnd.oasis.opendocument.graphics' => 'ODG', #5 32 'application/vnd.oasis.opendocument.image' => 'ODI', #5 26 33 'application/vnd.oasis.opendocument.presentation' => 'ODP', 27 34 'application/vnd.oasis.opendocument.spreadsheet' => 'ODS', 28 35 'application/vnd.oasis.opendocument.text' => 'ODT', 36 'application/vnd.adobe.indesign-idml-package' => 'IDML', #6 (not open doc) 37 'application/epub+zip' => 'EPUB', #PH (not open doc) 38 ); 39 40 # iWork file types based on names of files found in the zip archive 41 my %iWorkFile = ( 42 'Index/Slide.iwa' => 'KEY', 43 'Index/Tables/DataList.iwa' => 'NUMBERS', 44 ); 45 46 my %iWorkType = ( 47 NUMBERS => 'NUMBERS', 48 PAGES => 'PAGES', 49 KEY => 'KEY', 50 KTH => 'KTH', 51 NMBTEMPLATE => 'NMBTEMPLATE', 29 52 ); 30 53 … … 37 60 The following tags are extracted from ZIP archives. ExifTool also extracts 38 61 additional meta information from compressed documents inside some ZIP-based 39 files such Office Open XML (DOCX, PPTX and XLSX), Open Document (ODP, ODS 40 and ODT), iWork (KEY, PAGES, NUMBERS), and Capture One Enhanced Image 41 Package (EIP). The ExifTool family 3 groups may be used to organize the 42 output by embedded document number (ie. the exiftool C<-g3> option). 62 files such Office Open XML (DOCX, PPTX and XLSX), Open Document (ODB, ODC, 63 ODF, ODG, ODI, ODP, ODS and ODT), iWork (KEY, PAGES, NUMBERS), Capture One 64 Enhanced Image Package (EIP), Adobe InDesign Markup Language (IDML), 65 Electronic Publication (EPUB), and Sketch design files (SKETCH). The 66 ExifTool family 3 groups may be used to organize ZIP tags by embedded 67 document number (ie. the exiftool C<-g3> option). 43 68 }, 44 69 2 => 'ZipRequiredVersion', … … 82 107 ($val >> 11) & 0x1f, # hour 83 108 ($val >> 5) & 0x3f, # minute 84 $val & 0x1f# second109 ($val & 0x1f) * 2 # second 85 110 ); 86 111 }, … … 200 225 ($val >> 11) & 0x1f, # hour 201 226 ($val >> 5) & 0x3f, # minute 202 $val & 0x1f# second227 ($val & 0x1f) * 2 # second 203 228 ); 204 229 }, … … 235 260 sub ProcessRAR($$) 236 261 { 237 my ($e xifTool, $dirInfo) = @_;262 my ($et, $dirInfo) = @_; 238 263 my $raf = $$dirInfo{RAF}; 239 264 my ($flags, $buff); … … 241 266 return 0 unless $raf->Read($buff, 7) and $buff eq "Rar!\x1a\x07\0"; 242 267 243 $e xifTool->SetFileType();268 $et->SetFileType(); 244 269 SetByteOrder('II'); 245 270 my $tagTablePtr = GetTagTable('Image::ExifTool::ZIP::RAR'); … … 258 283 next unless $size; # ignore blocks with no data 259 284 # don't try to read very large blocks unless LargeFileSupport is enabled 260 if ($size > 0x80000000 and not $exifTool->Options('LargeFileSupport')) {261 $e xifTool->Warn('Large block encountered. Aborting.');285 if ($size >= 0x80000000 and not $et->Options('LargeFileSupport')) { 286 $et->Warn('Large block encountered. Aborting.'); 262 287 last; 263 288 } … … 269 294 # add compressed size to start of data so we can extract it with the other tags 270 295 $buff = pack('V',$size) . $buff; 271 $$e xifTool{DOC_NUM} = ++$docNum;272 $e xifTool->ProcessDirectory({ DataPt => \$buff }, $tagTablePtr);296 $$et{DOC_NUM} = ++$docNum; 297 $et->ProcessDirectory({ DataPt => \$buff }, $tagTablePtr); 273 298 $size -= $n; 274 299 } elsif ($type == 0x75 and $size > 6) { # comment block … … 276 301 # save comment, only if "Stored" (this is untested) 277 302 if (Get8u(\$buff, 3) == 0x30) { 278 $e xifTool->FoundTag('Comment', substr($buff, 6));303 $et->FoundTag('Comment', substr($buff, 6)); 279 304 } 280 305 next; … … 283 308 $raf->Seek($size, 1) or last if $size; 284 309 } 285 $$exifTool{DOC_NUM} = 0; 310 $$et{DOC_NUM} = 0; 311 if ($docNum > 1 and not $et->Options('Duplicates')) { 312 $et->Warn("Use the Duplicates option to extract tags for all $docNum files", 1); 313 } 286 314 287 315 return 1; … … 294 322 sub ProcessGZIP($$) 295 323 { 296 my ($e xifTool, $dirInfo) = @_;324 my ($et, $dirInfo) = @_; 297 325 my $raf = $$dirInfo{RAF}; 298 326 my ($flags, $buff); … … 300 328 return 0 unless $raf->Read($buff, 10) and $buff =~ /^\x1f\x8b\x08/; 301 329 302 $e xifTool->SetFileType();330 $et->SetFileType(); 303 331 SetByteOrder('II'); 304 332 305 333 my $tagTablePtr = GetTagTable('Image::ExifTool::ZIP::GZIP'); 306 $e xifTool->HandleTag($tagTablePtr, 2, Get8u(\$buff, 2));307 $e xifTool->HandleTag($tagTablePtr, 3, $flags = Get8u(\$buff, 3));308 $e xifTool->HandleTag($tagTablePtr, 4, Get32u(\$buff, 4));309 $e xifTool->HandleTag($tagTablePtr, 8, Get8u(\$buff, 8));310 $e xifTool->HandleTag($tagTablePtr, 9, Get8u(\$buff, 9));334 $et->HandleTag($tagTablePtr, 2, Get8u(\$buff, 2)); 335 $et->HandleTag($tagTablePtr, 3, $flags = Get8u(\$buff, 3)); 336 $et->HandleTag($tagTablePtr, 4, Get32u(\$buff, 4)); 337 $et->HandleTag($tagTablePtr, 8, Get8u(\$buff, 8)); 338 $et->HandleTag($tagTablePtr, 9, Get8u(\$buff, 9)); 311 339 312 340 # extract file name and comment if they exist … … 330 358 # it because I could just as easily screw it up) 331 359 my $str = substr($buff, $pos, $end - $pos); 332 $e xifTool->HandleTag($tagTablePtr, $tagID, $str);360 $et->HandleTag($tagTablePtr, $tagID, $str); 333 361 last if $end >= length $buff; 334 362 $pos = $end + 1; … … 343 371 sub HandleMember($$;$) 344 372 { 345 my ($e xifTool, $member, $tagTablePtr) = @_;373 my ($et, $member, $tagTablePtr) = @_; 346 374 $tagTablePtr or $tagTablePtr = GetTagTable('Image::ExifTool::ZIP::Main'); 347 $e xifTool->HandleTag($tagTablePtr, 2, $member->versionNeededToExtract());348 $e xifTool->HandleTag($tagTablePtr, 3, $member->bitFlag());349 $e xifTool->HandleTag($tagTablePtr, 4, $member->compressionMethod());350 $e xifTool->HandleTag($tagTablePtr, 5, $member->lastModFileDateTime());351 $e xifTool->HandleTag($tagTablePtr, 7, $member->crc32());352 $e xifTool->HandleTag($tagTablePtr, 9, $member->compressedSize());353 $e xifTool->HandleTag($tagTablePtr, 11, $member->uncompressedSize());354 $e xifTool->HandleTag($tagTablePtr, 15, $member->fileName());375 $et->HandleTag($tagTablePtr, 2, $member->versionNeededToExtract()); 376 $et->HandleTag($tagTablePtr, 3, $member->bitFlag()); 377 $et->HandleTag($tagTablePtr, 4, $member->compressionMethod()); 378 $et->HandleTag($tagTablePtr, 5, $member->lastModFileDateTime()); 379 $et->HandleTag($tagTablePtr, 7, $member->crc32()); 380 $et->HandleTag($tagTablePtr, 9, $member->compressedSize()); 381 $et->HandleTag($tagTablePtr, 11, $member->uncompressedSize()); 382 $et->HandleTag($tagTablePtr, 15, $member->fileName()); 355 383 } 356 384 357 385 #------------------------------------------------------------------------------ 358 # Extract information from a nZIP file386 # Extract information from a ZIP file 359 387 # Inputs: 0) ExifTool object reference, 1) dirInfo reference 360 388 # Returns: 1 on success, 0 if this wasn't a valid ZIP file 361 389 sub ProcessZIP($$) 362 390 { 363 my ($e xifTool, $dirInfo) = @_;391 my ($et, $dirInfo) = @_; 364 392 my $raf = $$dirInfo{RAF}; 365 my ($buff, $buf2, $zip , $docNum);366 367 return 0 unless $raf->Read($buff, 30) and $buff =~ /^PK\x03\x04/;393 my ($buff, $buf2, $zip); 394 395 return 0 unless $raf->Read($buff, 30) == 30 and $buff =~ /^PK\x03\x04/; 368 396 369 397 my $tagTablePtr = GetTagTable('Image::ExifTool::ZIP::Main'); 370 371 # use Archive::Zip if avilable 398 my $docNum = 0; 399 400 # use Archive::Zip if available 372 401 for (;;) { 373 unless (eval 'require Archive::Zip' and eval 'require IO::File') {374 if ($$e xifTool{FILE_EXT} and $$exifTool{FILE_EXT} ne 'ZIP') {375 $e xifTool->Warn("Install Archive::Zip to decode compressed ZIP information");402 unless (eval { require Archive::Zip } and eval { require IO::File }) { 403 if ($$et{FILE_EXT} and $$et{FILE_EXT} ne 'ZIP') { 404 $et->Warn("Install Archive::Zip to decode compressed ZIP information"); 376 405 } 377 406 last; 378 407 } 379 408 # Archive::Zip requires a seekable IO::File object 380 my $fh = $raf->{FILE_PT};381 if ($ fh and seek($fh, 0, 0)) {382 unless (eval 'require IO::File') {409 my $fh; 410 if ($raf->{TESTED} >= 0) { 411 unless (eval { require IO::File }) { 383 412 # (this shouldn't happen because IO::File is a prerequisite of Archive::Zip) 384 $e xifTool->Warn("Install IO::File to decode compressed ZIP information");413 $et->Warn("Install IO::File to decode compressed ZIP information"); 385 414 last; 386 415 } 416 $raf->Seek(0,0); 417 $fh = $raf->{FILE_PT}; 387 418 bless $fh, 'IO::File'; # Archive::Zip expects an IO::File object 388 } elsif (eval 'require IO::String') {419 } elsif (eval { require IO::String }) { 389 420 # read the whole file into memory (what else can I do?) 390 421 $raf->Slurp(); 391 422 $fh = new IO::String ${$raf->{BUFF_PT}}; 392 423 } else { 393 my $type = $ fh? 'pipe or socket' : 'scalar reference';394 $e xifTool->Warn("Install IO::String to decode compressed ZIP information from a $type");424 my $type = $raf->{FILE_PT} ? 'pipe or socket' : 'scalar reference'; 425 $et->Warn("Install IO::String to decode compressed ZIP information from a $type"); 395 426 last; 396 427 } 397 $e xifTool->VPrint(1, " --- using Archive::Zip ---\n");428 $et->VPrint(1, " --- using Archive::Zip ---\n"); 398 429 $zip = new Archive::Zip; 399 430 # catch all warnings! (Archive::Zip is bad for this) 400 431 local $SIG{'__WARN__'} = \&WarnProc; 401 432 my $status = $zip->readFromFileHandle($fh); 433 if ($status eq '4' and $raf->{TESTED} >= 0 and eval { require IO::String } and 434 $raf->Seek(0,2) and $raf->Tell() < 100000000) 435 { 436 # try again, reading it ourself this time in an attempt to avoid 437 # a failed test with Perl 5.6.2 GNU/Linux 2.6.32-5-686 i686-linux-64int-ld 438 $raf->Seek(0,0); 439 $raf->Slurp(); 440 $fh = new IO::String ${$raf->{BUFF_PT}}; 441 $zip = new Archive::Zip; 442 $status = $zip->readFromFileHandle($fh); 443 } 402 444 if ($status) { 403 445 undef $zip; 404 446 my %err = ( 1=>'Stream end error', 3=>'Format error', 4=>'IO error' ); 405 447 my $err = $err{$status} || "Error $status"; 406 $e xifTool->Warn("$err reading ZIP file");448 $et->Warn("$err reading ZIP file"); 407 449 last; 408 450 } … … 415 457 if ($cType) { 416 458 ($buff, $status) = $zip->contents($cType); 417 if (not $status and $buff =~ /ContentType\s*=\s*(['"])([^"']+)\.main(\+xml)?\1/) { 459 if (not $status and ( 460 # first look for the main document with the expected name 461 $buff =~ m{\sPartName\s*=\s*['"](?:/ppt/presentation.xml|/word/document.xml|/xl/workbook.xml)['"][^>]*\sContentType\s*=\s*(['"])([^"']+)\.main(\+xml)?\1} or 462 # then look for the main part 463 $buff =~ /<Override[^>]*\sPartName[^<]+\sContentType\s*=\s*(['"])([^"']+)\.main(\+xml)?\1/ or 464 # and if all else fails, use the default main 465 $buff =~ /ContentType\s*=\s*(['"])([^"']+)\.main(\+xml)?\1/)) 466 { 418 467 $mime = $2; 419 468 } … … 424 473 $$dirInfo{MIME} = $mime; 425 474 require Image::ExifTool::OOXML; 426 Image::ExifTool::OOXML::ProcessDOCX($e xifTool, $dirInfo);475 Image::ExifTool::OOXML::ProcessDOCX($et, $dirInfo); 427 476 delete $$dirInfo{MIME}; 428 477 last; … … 433 482 if (@members) { 434 483 require Image::ExifTool::CaptureOne; 435 Image::ExifTool::CaptureOne::ProcessEIP($e xifTool, $dirInfo);484 Image::ExifTool::CaptureOne::ProcessEIP($et, $dirInfo); 436 485 last; 437 486 } 438 487 439 488 # check for an iWork file 440 @members = $zip->membersMatching(' ^(index\.(xml|apxl)|QuickLook/Thumbnail\.jpg)$');489 @members = $zip->membersMatching('(?i)^(index\.(xml|apxl)|QuickLook/Thumbnail\.jpg|[^/]+\.(pages|numbers|key)/Index.(zip|xml|apxl))$'); 441 490 if (@members) { 442 491 require Image::ExifTool::iWork; 443 Image::ExifTool::iWork::Process_iWork($e xifTool, $dirInfo);492 Image::ExifTool::iWork::Process_iWork($et, $dirInfo); 444 493 last; 445 494 } 446 495 447 # check for an Open Document file496 # check for an Open Document, IDML or EPUB file 448 497 my $mType = $zip->memberNamed('mimetype'); 449 498 if ($mType) { 450 499 ($mime, $status) = $zip->contents($mType); 451 unless ($status) { 452 chomp $mime; 453 if ($openDocType{$mime}) { 454 $exifTool->SetFileType($openDocType{$mime}, $mime); 455 # extract Open Document metadata from "meta.xml" 456 my $meta = $zip->memberNamed('meta.xml'); 457 if ($meta) { 458 ($buff, $status) = $zip->contents($meta); 459 unless ($status) { 460 my %dirInfo = ( 461 DataPt => \$buff, 462 DirLen => length $buff, 463 DataLen => length $buff, 464 ); 465 my $xmpTable = GetTagTable('Image::ExifTool::XMP::Main'); 466 $exifTool->ProcessDirectory(\%dirInfo, $xmpTable); 467 } 500 if (not $status and $mime =~ /([\x21-\xfe]+)/s) { 501 # clean up MIME type just in case (note that MIME is case insensitive) 502 $mime = lc $1; 503 $et->SetFileType($openDocType{$mime} || 'ZIP', $mime); 504 $et->Warn("Unrecognized MIMEType $mime") unless $openDocType{$mime}; 505 # extract Open Document metadata from "meta.xml" 506 my $meta = $zip->memberNamed('meta.xml'); 507 # IDML files have metadata in a different place (ref 6) 508 $meta or $meta = $zip->memberNamed('META-INF/metadata.xml'); 509 if ($meta) { 510 ($buff, $status) = $zip->contents($meta); 511 unless ($status) { 512 my %dirInfo = ( 513 DirName => 'XML', 514 DataPt => \$buff, 515 DirLen => length $buff, 516 DataLen => length $buff, 517 ); 518 # (avoid structure warnings when copying from XML) 519 my $oldWarn = $$et{NO_STRUCT_WARN}; 520 $$et{NO_STRUCT_WARN} = 1; 521 $et->ProcessDirectory(\%dirInfo, GetTagTable('Image::ExifTool::XMP::Main')); 522 $$et{NO_STRUCT_WARN} = $oldWarn; 468 523 } 469 # extract preview image(s) from "Thumbnails" directory 524 } 525 # process rootfile of EPUB container if applicable 526 for (;;) { 527 last if $meta and $mime ne 'application/epub+zip'; 528 my $container = $zip->memberNamed('META-INF/container.xml'); 529 ($buff, $status) = $zip->contents($container); 530 last if $status; 531 $buff =~ /<rootfile\s+[^>]*?\bfull-path=(['"])(.*?)\1/s or last; 532 # load the rootfile data (OPF extension; contains XML metadata) 533 my $meta2 = $zip->memberNamed($2) or last; 534 $meta = $meta2; 535 ($buff, $status) = $zip->contents($meta); 536 last if $status; 537 # use opf:event to generate more meaningful tag names for dc:date 538 while ($buff =~ s{<dc:date opf:event="(\w+)">([^<]+)</dc:date>}{<dc:${1}Date>$2</dc:${1}Date>}s) { 539 my $dcTable = GetTagTable('Image::ExifTool::XMP::dc'); 540 my $tag = "${1}Date"; 541 AddTagToTable($dcTable, $tag, { 542 Name => ucfirst $tag, 543 Groups => { 2 => 'Time' }, 544 List => 'Seq', 545 %Image::ExifTool::XMP::dateTimeInfo 546 }) unless $$dcTable{$tag}; 547 } 548 my %dirInfo = ( 549 DataPt => \$buff, 550 DirLen => length $buff, 551 DataLen => length $buff, 552 IgnoreProp => { 'package' => 1, metadata => 1 }, 553 ); 554 # (avoid structure warnings when copying from XML) 555 my $oldWarn = $$et{NO_STRUCT_WARN}; 556 $$et{NO_STRUCT_WARN} = 1; 557 $et->ProcessDirectory(\%dirInfo, GetTagTable('Image::ExifTool::XMP::XML')); 558 $$et{NO_STRUCT_WARN} = $oldWarn; 559 last; 560 } 561 if ($openDocType{$mime} or $meta) { 562 # extract preview image(s) from "Thumbnails" directory if they exist 470 563 my $type; 471 564 my %tag = ( jpg => 'PreviewImage', png => 'PreviewPNG' ); … … 474 567 next unless $thumb; 475 568 ($buff, $status) = $zip->contents($thumb); 476 $e xifTool->FoundTag($tag{$type}, $buff) unless $status;569 $et->FoundTag($tag{$type}, $buff) unless $status; 477 570 } 478 last; 571 last; # all done since we recognized the MIME type or found metadata 479 572 } 573 # continue on to list ZIP contents... 480 574 } 481 575 } 482 576 483 577 # otherwise just extract general ZIP information 484 $e xifTool->SetFileType();578 $et->SetFileType(); 485 579 @members = $zip->members(); 486 $docNum = 0; 487 my $member; 580 my ($member, $iWorkType); 581 # special files to extract 582 my %extract = ( 583 'meta.json' => 1, 584 'previews/preview.png' => 'PreviewPNG', 585 'preview.jpg' => 'PreviewImage', # (iWork 2013 files) 586 'preview-web.jpg' => 'OtherImage', # (iWork 2013 files) 587 'preview-micro.jpg' => 'ThumbnailImage', # (iWork 2013 files) 588 'QuickLook/Thumbnail.jpg' => 'ThumbnailImage', # (iWork 2009 files) 589 'QuickLook/Preview.pdf' => 'PreviewPDF', # (iWork 2009 files) 590 ); 488 591 foreach $member (@members) { 489 $$exifTool{DOC_NUM} = ++$docNum; 490 HandleMember($exifTool, $member, $tagTablePtr); 491 } 592 $$et{DOC_NUM} = ++$docNum; 593 HandleMember($et, $member, $tagTablePtr); 594 my $file = $member->fileName(); 595 # extract things from Sketch files 596 if ($extract{$file}) { 597 ($buff, $status) = $zip->contents($member); 598 $status and $et->Warn("Error extracting $file"), next; 599 if ($file eq 'meta.json') { 600 $et->ExtractInfo(\$buff, { ReEntry => 1 }); 601 if ($$et{VALUE}{App} and $$et{VALUE}{App} =~ /sketch/i) { 602 $et->OverrideFileType('SKETCH'); 603 } 604 } else { 605 $et->FoundTag($extract{$file} => $buff); 606 } 607 } elsif ($file eq 'Index/Document.iwa' and not $iWorkType) { 608 my $type = $iWorkType{$$et{FILE_EXT} || ''}; 609 $iWorkType = $type || 'PAGES'; 610 } elsif ($iWorkFile{$file}) { 611 $iWorkType = $iWorkFile{$file}; 612 } 613 } 614 $et->OverrideFileType($iWorkType) if $iWorkType; 492 615 last; 493 616 } … … 495 618 if ($zip) { 496 619 delete $$dirInfo{ZIP}; 497 delete $$exifTool{DOC_NUM}; 620 delete $$et{DOC_NUM}; 621 if ($docNum > 1 and not $et->Options('Duplicates')) { 622 $et->Warn("Use the Duplicates option to extract tags for all $docNum files", 1); 623 } 498 624 return 1; 499 625 } … … 501 627 # process the ZIP file by hand (funny, but this seems easier than using Archive::Zip) 502 628 # 503 $docNum = 0; 504 $exifTool->VPrint(1, " -- processing as binary data --\n"); 629 $et->VPrint(1, " -- processing as binary data --\n"); 505 630 $raf->Seek(30, 0); 506 $e xifTool->SetFileType();631 $et->SetFileType(); 507 632 SetByteOrder('II'); 508 633 … … 523 648 $raf->Read($buf2, $len) == $len or last; 524 649 525 $$e xifTool{DOC_NUM} = ++$docNum;650 $$et{DOC_NUM} = ++$docNum; 526 651 $buff .= $buf2; 527 652 my %dirInfo = ( … … 532 657 DirLen => 30 + $len, 533 658 ); 534 $e xifTool->ProcessDirectory(\%dirInfo, $tagTablePtr);659 $et->ProcessDirectory(\%dirInfo, $tagTablePtr); 535 660 my $flags = Get16u(\$buff, 6); 536 661 if ($flags & 0x08) { … … 539 664 # sizes are set to 0 in the header. Instead, they are stored 540 665 # after the compressed data with an optional header of 0x08074b50) 541 $e xifTool->Warn('Stream mode data encountered, file list may be incomplete');666 $et->Warn('Stream mode data encountered, file list may be incomplete'); 542 667 last; 543 668 } … … 546 671 $raf->Read($buff, 30) == 30 and $buff =~ /^PK\x03\x04/ or last; 547 672 } 548 delete $$exifTool{DOC_NUM}; 673 delete $$et{DOC_NUM}; 674 if ($docNum > 1 and not $et->Options('Duplicates')) { 675 $et->Warn("Use the Duplicates option to extract tags for all $docNum files", 1); 676 } 549 677 return 1; 550 678 } … … 566 694 This module contains definitions required by Image::ExifTool to extract meta 567 695 information from ZIP, GZIP and RAR archives. This includes ZIP-based file 568 types like DOCX, PPTX, XLSX, ODP, ODS, ODT and EIP. 696 types like Office Open XML (DOCX, PPTX and XLSX), Open Document (ODB, ODC, 697 ODF, ODG, ODI, ODP, ODS and ODT), iWork (KEY, PAGES, NUMBERS), Capture One 698 Enhanced Image Package (EIP), Adobe InDesign Markup Language (IDML), 699 Electronic Publication (EPUB), and Sketch design files (SKETCH). 569 700 570 701 =head1 AUTHOR 571 702 572 Copyright 2003-20 11, Phil Harvey (phil at owl.phy.queensu.ca)703 Copyright 2003-2021, Phil Harvey (philharvey66 at gmail.com) 573 704 574 705 This library is free software; you can redistribute it and/or modify it
Note:
See TracChangeset
for help on using the changeset viewer.