Add X-Content-Dimensions support to DjVu

Bug: T150741
Change-Id: I4a3bae9bf056a7ba332f2f0a330697cdf59b4d04
This commit is contained in:
Gilles Dubuc 2017-05-11 13:12:55 +02:00 committed by Gilles Dubuc
parent 1fdc4c6f53
commit 4511f6fa9f

View file

@ -304,11 +304,28 @@ class DjVuHandler extends ImageHandler {
return false;
}
$trees = $this->extractTreesFromMetadata( $metadata );
$image->djvuTextTree = $trees['TextTree'];
$image->dejaMetaTree = $trees['MetaTree'];
if ( $gettext ) {
return $image->djvuTextTree;
} else {
return $image->dejaMetaTree;
}
}
/**
* Extracts metadata and text trees from metadata XML in string form
* @param string $metadata XML metadata as a string
* @return array
*/
protected function extractTreesFromMetadata( $metadata ) {
MediaWiki\suppressWarnings();
try {
// Set to false rather than null to avoid further attempts
$image->dejaMetaTree = false;
$image->djvuTextTree = false;
$metaTree = false;
$textTree = false;
$tree = new SimpleXMLElement( $metadata, LIBXML_PARSEHUGE );
if ( $tree->getName() == 'mw-djvu' ) {
/** @var SimpleXMLElement $b */
@ -316,23 +333,20 @@ class DjVuHandler extends ImageHandler {
if ( $b->getName() == 'DjVuTxt' ) {
// @todo File::djvuTextTree and File::dejaMetaTree are declared
// dynamically. Add a public File::$data to facilitate this?
$image->djvuTextTree = $b;
$textTree = $b;
} elseif ( $b->getName() == 'DjVuXML' ) {
$image->dejaMetaTree = $b;
$metaTree = $b;
}
}
} else {
$image->dejaMetaTree = $tree;
$metaTree = $tree;
}
} catch ( Exception $e ) {
wfDebug( "Bogus multipage XML metadata on '{$image->getName()}'\n" );
wfDebug( "Bogus multipage XML metadata\n" );
}
MediaWiki\restoreWarnings();
if ( $gettext ) {
return $image->djvuTextTree;
} else {
return $image->dejaMetaTree;
}
return [ 'MetaTree' => $metaTree, 'TextTree' => $textTree ];
}
function getImageSize( $image, $path ) {
@ -394,14 +408,26 @@ class DjVuHandler extends ImageHandler {
$cache::TTL_INDEFINITE,
function () use ( $file ) {
$tree = $this->getMetaTree( $file );
if ( !$tree ) {
return $this->getDimensionInfoFromMetaTree( $tree );
},
[ 'pcTTL' => $cache::TTL_INDEFINITE ]
);
}
/**
* Given an XML metadata tree, returns dimension information about the document
* @param bool|SimpleXMLElement $metatree The file's XML metadata tree
* @return bool|array
*/
protected function getDimensionInfoFromMetaTree( $metatree ) {
if ( !$metatree ) {
return false;
}
$dimsByPage = [];
$count = count( $tree->xpath( '//OBJECT' ) );
$count = count( $metatree->xpath( '//OBJECT' ) );
for ( $i = 0; $i < $count; $i++ ) {
$o = $tree->BODY[0]->OBJECT[$i];
$o = $metatree->BODY[0]->OBJECT[$i];
if ( $o ) {
$dimsByPage[$i] = [
'width' => (int)$o['width'],
@ -413,9 +439,6 @@ class DjVuHandler extends ImageHandler {
}
return [ 'pageCount' => $count, 'dimensionsByPage' => $dimsByPage ];
},
[ 'pcTTL' => $cache::TTL_INDEFINITE ]
);
}
/**
@ -438,4 +461,40 @@ class DjVuHandler extends ImageHandler {
return false;
}
}
/**
* Get useful response headers for GET/HEAD requests for a file with the given metadata
* @param $metadata Array Contains this handler's unserialized getMetadata() for a file
* @return array
*/
public function getContentHeaders( $metadata ) {
if ( !is_array( $metadata ) || !isset( $metadata['xml'] ) ) {
return [];
}
$trees = $this->extractTreesFromMetadata( $metadata['xml'] );
$dimensionInfo = $this->getDimensionInfoFromMetaTree( $trees['MetaTree'] );
if ( !$dimensionInfo ) {
return [];
}
$pagesByDimensions = [];
$count = $dimensionInfo['pageCount'];
for ( $i = 1; $i <= $count; $i++ ) {
$dimensions = $dimensionInfo['dimensionsByPage'][ $i - 1 ];
$dimensionString = $dimensions['width'] . 'x' . $dimensions['height'];
if ( isset ( $pagesByDimensions[ $dimensionString ] ) ) {
$pagesByDimensions[ $dimensionString ][] = $i;
} else {
$pagesByDimensions[ $dimensionString ] = [ $i ];
}
}
$pageRangesByDimensions = MediaHandler::getPageRangesByDimensions( $pagesByDimensions );
return [ 'X-Content-Dimensions' => $pageRangesByDimensions ];
}
}