Index: trunk/phase3/RELEASE-NOTES |
— | — | @@ -222,6 +222,7 @@ |
223 | 223 | * (bug 22784) Normalise underscores and spaces in autocomments. |
224 | 224 | * (bug 19910) Headings of the form ===+\s+ are now displayed as valid headings |
225 | 225 | * (bug 24022) Only check file extensions on the uploadpage when needed. |
| 226 | +* (bug 24076) Recognize Office 2003 files with OpenXML trailers |
226 | 227 | |
227 | 228 | === API changes in 1.17 === |
228 | 229 | * (bug 22738) Allow filtering by action type on query=logevent. |
Index: trunk/phase3/includes/MimeMagic.php |
— | — | @@ -545,10 +545,10 @@ |
546 | 546 | } |
547 | 547 | } |
548 | 548 | |
549 | | - // Check for ZIP (before getimagesize) |
| 549 | + // Check for ZIP variants (before getimagesize) |
550 | 550 | if ( strpos( $tail, "PK\x05\x06" ) !== false ) { |
551 | | - wfDebug( __METHOD__.": ZIP header present at end of $file\n" ); |
552 | | - return $this->detectZipType( $head, $ext ); |
| 551 | + wfDebug( __METHOD__.": ZIP header present in $file\n" ); |
| 552 | + return $this->detectZipType( $head, $tail, $ext ); |
553 | 553 | } |
554 | 554 | |
555 | 555 | wfSuppressWarnings(); |
— | — | @@ -573,16 +573,17 @@ |
574 | 574 | |
575 | 575 | /** |
576 | 576 | * Detect application-specific file type of a given ZIP file from its |
577 | | - * header data. Currently works for OpenDocument types... |
| 577 | + * header data. Currently works for OpenDocument and OpenXML types... |
578 | 578 | * If can't tell, returns 'application/zip'. |
579 | 579 | * |
580 | 580 | * @param $header String: some reasonably-sized chunk of file header |
| 581 | + * @param $tail String: the tail of the file |
581 | 582 | * @param $ext Mixed: the file extension, or true to extract it from the filename. |
582 | 583 | * Set it to false to ignore the extension. |
583 | 584 | * |
584 | 585 | * @return string |
585 | 586 | */ |
586 | | - function detectZipType( $header, $ext = false ) { |
| 587 | + function detectZipType( $header, $tail = null, $ext = false ) { |
587 | 588 | $mime = 'application/zip'; |
588 | 589 | $opendocTypes = array( |
589 | 590 | 'chart-template', |
— | — | @@ -605,14 +606,13 @@ |
606 | 607 | // http://lists.oasis-open.org/archives/office/200505/msg00006.html |
607 | 608 | $types = '(?:' . implode( '|', $opendocTypes ) . ')'; |
608 | 609 | $opendocRegex = "/^mimetype(application\/vnd\.oasis\.opendocument\.$types)/"; |
609 | | - wfDebug( __METHOD__.": $opendocRegex\n" ); |
610 | 610 | |
611 | 611 | $openxmlRegex = "/^\[Content_Types\].xml/"; |
612 | | - |
| 612 | + |
613 | 613 | if( preg_match( $opendocRegex, substr( $header, 30 ), $matches ) ) { |
614 | 614 | $mime = $matches[1]; |
615 | 615 | wfDebug( __METHOD__.": detected $mime from ZIP archive\n" ); |
616 | | - } elseif( preg_match( $openxmlRegex, substr( $header, 30 ), $matches ) ) { |
| 616 | + } elseif( preg_match( $openxmlRegex, substr( $header, 30 ) ) ) { |
617 | 617 | $mime = "application/x-opc+zip"; |
618 | 618 | if( $ext !== true && $ext !== false ) { |
619 | 619 | /** This is the mode used by getPropsFromPath |
— | — | @@ -624,11 +624,39 @@ |
625 | 625 | * find the proper mime type for that file extension */ |
626 | 626 | $mime = $this->guessTypesForExtension( $ext ); |
627 | 627 | } else { |
628 | | - $mime = 'application/zip'; |
| 628 | + $mime = "application/zip"; |
629 | 629 | } |
630 | | - |
631 | 630 | } |
632 | 631 | wfDebug( __METHOD__.": detected an Open Packaging Conventions archive: $mime\n" ); |
| 632 | + } else if( substr( $header, 0, 8 ) == "\xd0\xcf\x11\xe0\xa1\xb1\x1a\xe1" && |
| 633 | + ($headerpos = strpos( $tail, "PK\x03\x04" ) ) !== false && |
| 634 | + preg_match( $openxmlRegex, substr( $tail, $headerpos + 30 ) ) ) { |
| 635 | + if( substr( $header, 512, 4) == "\xEC\xA5\xC1\x00" ) { |
| 636 | + $mime = "application/msword"; |
| 637 | + } |
| 638 | + switch( substr( $header, 512, 6) ) { |
| 639 | + case "\xEC\xA5\xC1\x00\x0E\x00": |
| 640 | + case "\xEC\xA5\xC1\x00\x1C\x00": |
| 641 | + case "\xEC\xA5\xC1\x00\x43\x00": |
| 642 | + $mime = "application/vnd.ms-powerpoint"; |
| 643 | + break; |
| 644 | + case "\xFD\xFF\xFF\xFF\x10\x00": |
| 645 | + case "\xFD\xFF\xFF\xFF\x1F\x00": |
| 646 | + case "\xFD\xFF\xFF\xFF\x22\x00": |
| 647 | + case "\xFD\xFF\xFF\xFF\x23\x00": |
| 648 | + case "\xFD\xFF\xFF\xFF\x28\x00": |
| 649 | + case "\xFD\xFF\xFF\xFF\x29\x00": |
| 650 | + case "\xFD\xFF\xFF\xFF\x10\x02": |
| 651 | + case "\xFD\xFF\xFF\xFF\x1F\x02": |
| 652 | + case "\xFD\xFF\xFF\xFF\x22\x02": |
| 653 | + case "\xFD\xFF\xFF\xFF\x23\x02": |
| 654 | + case "\xFD\xFF\xFF\xFF\x28\x02": |
| 655 | + case "\xFD\xFF\xFF\xFF\x29\x02": |
| 656 | + $mime = "application/vnd.msexcel"; |
| 657 | + break; |
| 658 | + } |
| 659 | + |
| 660 | + wfDebug( __METHOD__.": detected a MS Office document with OPC trailer\n"); |
633 | 661 | } else { |
634 | 662 | wfDebug( __METHOD__.": unable to identify type of ZIP archive\n" ); |
635 | 663 | } |