24 private const EXPENSIVE_SIZE_LIMIT = 10_485_760;
27 private const STATE_DJVU_IMAGE =
'djvuImage';
28 private const STATE_TEXT_TREE =
'djvuTextTree';
29 private const STATE_META_TREE =
'djvuMetaTree';
30 private const CACHE_VERSION =
'v2';
38 if ( !$djvuRenderer || !$djvuDump ) {
39 wfDebug(
"DjVu is disabled, please set \$wgDjvuRenderer and \$wgDjvuDump" );
60 return $file->getSize() > static::EXPENSIVE_SIZE_LIMIT;
76 'img_width' =>
'width',
87 if ( $name ===
'page' && trim( $value ) !== (
string)intval( $value ) ) {
92 return in_array( $name, [
'width',
'height',
'page' ] ) && $value > 0;
100 $page = $params[
'page'] ?? 1;
101 if ( !isset( $params[
'width'] ) ) {
105 return "page{$page}-{$params['width']}px";
114 if ( preg_match(
'/^page(\d+)-(\d+)px$/', $str, $m ) ) {
115 return [
'width' => $m[2],
'page' => $m[1] ];
126 'width' => $params[
'width'],
127 'page' => $params[
'page'],
139 public function doTransform( $image, $dstPath, $dstUrl, $params, $flags = 0 ) {
146 $width = $params[
'width'];
147 $height = $params[
'height'];
148 $page = $params[
'page'];
150 if ( $flags & self::TRANSFORM_LATER ) {
172 if ( $image->getSize() >= 1e7 ) {
175 'doWork' =>
static function () use ( $image ) {
176 return $image->getLocalRefPath();
182 $srcPath = $image->getLocalRefPath();
185 if ( $srcPath ===
false ) {
187 sprintf(
'Thumbnail failed on %s: could not get local copy of "%s"',
191 $params[
'width'], $params[
'height'],
196 # Use a subshell (brackets) to aggregate stderr from both pipeline commands
197 # before redirecting it to the overall stdout. This works in both Linux and Windows XP.
198 $cmd =
'(' . Shell::escape(
202 "-size={$params['physicalWidth']}x{$params['physicalHeight']}",
204 if ( $djvuPostProcessor ) {
205 $cmd .=
" | {$djvuPostProcessor}";
207 $cmd .=
' > ' . Shell::escape( $dstPath ) .
') 2>&1';
208 wfDebug( __METHOD__ .
": $cmd" );
213 if ( $retval !== 0 || $removed ) {
234 private function getDjVuImage( $state,
$path ) {
235 $deja = $state->getHandlerState( self::STATE_DJVU_IMAGE );
238 $state->setHandlerState( self::STATE_DJVU_IMAGE, $deja );
250 private function getMetadataInternal( File $file, $gettext ) {
251 $itemNames = [
'error',
'_error',
'data' ];
253 $itemNames[] =
'text';
255 $unser = $file->getMetadataItems( $itemNames );
257 if ( isset( $unser[
'error'] ) ) {
260 if ( isset( $unser[
'_error'] ) ) {
273 if ( $gettext && $image->getHandlerState( self::STATE_TEXT_TREE ) ) {
274 return $image->getHandlerState( self::STATE_TEXT_TREE );
276 if ( !$gettext && $image->getHandlerState( self::STATE_META_TREE ) ) {
277 return $image->getHandlerState( self::STATE_META_TREE );
280 $metadata = $this->getMetadataInternal( $image, $gettext );
286 unset( $metadata[
'text'] );
295 static $djvuMime =
null;
296 if ( $djvuMime ===
null ) {
298 $djvuMime = $magic->getMimeTypeFromExtensionOrNull( $djvuOutputExtension );
301 return [ $djvuOutputExtension, $djvuMime ];
306 wfDebug(
"Getting DjVu metadata for $path" );
308 $djvuImage = $this->getDjVuImage( $state,
$path );
309 $metadata = $djvuImage->retrieveMetaData();
310 if ( $metadata ===
false ) {
312 $metadata = [
'error' =>
'Error extracting metadata' ];
314 return [
'metadata' => $metadata ] + $djvuImage->getImageSize();
332 return $info ? $info[
'pageCount'] :
false;
340 if ( $info && isset( $info[
'dimensionsByPage'][$index] ) ) {
341 return $info[
'dimensionsByPage'][$index];
350 return $cache->getWithSetCallback(
351 $cache->makeKey(
'file-djvu',
'dimensions', self::CACHE_VERSION, $file->
getSha1() ),
352 $cache::TTL_INDEFINITE,
353 function () use ( $file ) {
357 [
'pcTTL' => $cache::TTL_INDEFINITE ]
372 if ( !isset( $metatree[
'data'] ) || !$metatree[
'data'] ) {
375 foreach ( $metatree[
'data'][
'pages'] as $page ) {
377 $dimsByPage[] =
false;
380 'width' => (int)$page[
'width'],
381 'height' => (
int)$page[
'height'],
386 'pageCount' => count( $metatree[
'data'][
'pages'] ),
387 'dimensionsByPage' => $dimsByPage
401 if ( isset( $tree[
'text'] ) && isset( $tree[
'text'][$page - 1] ) ) {
402 return $tree[
'text'][$page - 1];
414class_alias( DjVuHandler::class,
'DjVuHandler' );
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
wfShellExec( $cmd, &$retval=null, $environ=[], $limits=[], $options=[])
Execute a shell command, with time and memory limits mirrored from the PHP configuration if supported...
wfHostname()
Get host name of the current machine, for use in error reporting.
wfDebugLog( $logGroup, $text, $dest='all', array $context=[])
Send a line to a supplementary debug log file, if configured, or main debug log if not.
wfMkdirParents( $dir, $mode=null, $caller=null)
Make directory, and make all parent directories if they don't exist.
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
A class containing constants representing the names of configuration variables.
const DjvuPostProcessor
Name constant for the DjvuPostProcessor setting, for use with Config::get()
const DjvuDump
Name constant for the DjvuDump setting, for use with Config::get()
const DjvuRenderer
Name constant for the DjvuRenderer setting, for use with Config::get()
const DjvuOutputExtension
Name constant for the DjvuOutputExtension setting, for use with Config::get()