| 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 | } |