MediaWiki  REL1_20
DjVu.php
Go to the documentation of this file.
00001 <?php
00029 class DjVuHandler extends ImageHandler {
00030 
00034         function isEnabled() {
00035                 global $wgDjvuRenderer, $wgDjvuDump, $wgDjvuToXML;
00036                 if ( !$wgDjvuRenderer || ( !$wgDjvuDump && !$wgDjvuToXML ) ) {
00037                         wfDebug( "DjVu is disabled, please set \$wgDjvuRenderer and \$wgDjvuDump\n" );
00038                         return false;
00039                 } else {
00040                         return true;
00041                 }
00042         }
00043 
00048         function mustRender( $file ) {
00049                 return true;
00050         }
00051 
00056         function isMultiPage( $file ) {
00057                 return true;
00058         }
00059 
00063         function getParamMap() {
00064                 return array(
00065                         'img_width' => 'width',
00066                         'img_page' => 'page',
00067                 );
00068         }
00069 
00075         function validateParam( $name, $value ) {
00076                 if ( in_array( $name, array( 'width', 'height', 'page' ) ) ) {
00077                         if ( $value <= 0 ) {
00078                                 return false;
00079                         } else {
00080                                 return true;
00081                         }
00082                 } else {
00083                         return false;
00084                 }
00085         }
00086 
00091         function makeParamString( $params ) {
00092                 $page = isset( $params['page'] ) ? $params['page'] : 1;
00093                 if ( !isset( $params['width'] ) ) {
00094                         return false;
00095                 }
00096                 return "page{$page}-{$params['width']}px";
00097         }
00098 
00103         function parseParamString( $str ) {
00104                 $m = false;
00105                 if ( preg_match( '/^page(\d+)-(\d+)px$/', $str, $m ) ) {
00106                         return array( 'width' => $m[2], 'page' => $m[1] );
00107                 } else {
00108                         return false;
00109                 }
00110         }
00111 
00116         function getScriptParams( $params ) {
00117                 return array(
00118                         'width' => $params['width'],
00119                         'page' => $params['page'],
00120                 );
00121         }
00122 
00131         function doTransform( $image, $dstPath, $dstUrl, $params, $flags = 0 ) {
00132                 global $wgDjvuRenderer, $wgDjvuPostProcessor;
00133 
00134                 // Fetch XML and check it, to give a more informative error message than the one which
00135                 // normaliseParams will inevitably give.
00136                 $xml = $image->getMetadata();
00137                 if ( !$xml ) {
00138                         $width = isset( $params['width'] ) ? $params['width'] : 0;
00139                         $height = isset( $params['height'] ) ? $params['height'] : 0;
00140                         return new MediaTransformError( 'thumbnail_error', $width, $height,
00141                                 wfMessage( 'djvu_no_xml' )->text() );
00142                 }
00143 
00144                 if ( !$this->normaliseParams( $image, $params ) ) {
00145                         return new TransformParameterError( $params );
00146                 }
00147                 $width = $params['width'];
00148                 $height = $params['height'];
00149                 $page = $params['page'];
00150                 if ( $page > $this->pageCount( $image ) ) {
00151                         return new MediaTransformError(
00152                                 'thumbnail_error',
00153                                 $width,
00154                                 $height,
00155                                 wfMessage( 'djvu_page_error' )->text()
00156                         );
00157                 }
00158 
00159                 if ( $flags & self::TRANSFORM_LATER ) {
00160                         $params = array(
00161                                 'width' => $width,
00162                                 'height' => $height,
00163                                 'page' => $page
00164                         );
00165                         return new ThumbnailImage( $image, $dstUrl, $dstPath, $params );
00166                 }
00167 
00168                 if ( !wfMkdirParents( dirname( $dstPath ), null, __METHOD__ ) ) {
00169                         return new MediaTransformError(
00170                                 'thumbnail_error',
00171                                 $width,
00172                                 $height,
00173                                 wfMessage( 'thumbnail_dest_directory' )->text()
00174                         );
00175                 }
00176 
00177                 $srcPath = $image->getLocalRefPath();
00178                 # Use a subshell (brackets) to aggregate stderr from both pipeline commands
00179                 # before redirecting it to the overall stdout. This works in both Linux and Windows XP.
00180                 $cmd = '(' . wfEscapeShellArg( $wgDjvuRenderer ) . " -format=ppm -page={$page}" .
00181                         " -size={$params['physicalWidth']}x{$params['physicalHeight']} " .
00182                         wfEscapeShellArg( $srcPath );
00183                 if ( $wgDjvuPostProcessor ) {
00184                         $cmd .= " | {$wgDjvuPostProcessor}";
00185                 }
00186                 $cmd .= ' > ' . wfEscapeShellArg($dstPath) . ') 2>&1';
00187                 wfProfileIn( 'ddjvu' );
00188                 wfDebug( __METHOD__.": $cmd\n" );
00189                 $retval = '';
00190                 $err = wfShellExec( $cmd, $retval );
00191                 wfProfileOut( 'ddjvu' );
00192 
00193                 $removed = $this->removeBadFile( $dstPath, $retval );
00194                 if ( $retval != 0 || $removed ) {
00195                         wfDebugLog( 'thumbnail',
00196                                 sprintf( 'thumbnail failed on %s: error %d "%s" from "%s"',
00197                                         wfHostname(), $retval, trim($err), $cmd ) );
00198                         return new MediaTransformError( 'thumbnail_error', $width, $height, $err );
00199                 } else {
00200                         $params = array(
00201                                 'width' => $width,
00202                                 'height' => $height,
00203                                 'page' => $page
00204                         );
00205                         return new ThumbnailImage( $image, $dstUrl, $dstPath, $params );
00206                 }
00207         }
00208 
00214         function getDjVuImage( $image, $path ) {
00215                 if ( !$image ) {
00216                         $deja = new DjVuImage( $path );
00217                 } elseif ( !isset( $image->dejaImage ) ) {
00218                         $deja = $image->dejaImage = new DjVuImage( $path );
00219                 } else {
00220                         $deja = $image->dejaImage;
00221                 }
00222                 return $deja;
00223         }
00224 
00231         function getMetaTree( $image , $gettext = false ) {
00232                 if ( isset( $image->dejaMetaTree ) ) {
00233                         return $image->dejaMetaTree;
00234                 }
00235 
00236                 $metadata = $image->getMetadata();
00237                 if ( !$this->isMetadataValid( $image, $metadata ) ) {
00238                         wfDebug( "DjVu XML metadata is invalid or missing, should have been fixed in upgradeRow\n" );
00239                         return false;
00240                 }
00241                 wfProfileIn( __METHOD__ );
00242 
00243                 wfSuppressWarnings();
00244                 try {
00245                         // Set to false rather than null to avoid further attempts
00246                         $image->dejaMetaTree = false;
00247                         $image->djvuTextTree = false;
00248                         $tree = new SimpleXMLElement( $metadata );
00249                         if( $tree->getName() == 'mw-djvu' ) {
00250                                 foreach($tree->children() as $b){
00251                                         if( $b->getName() == 'DjVuTxt' ) {
00252                                                 $image->djvuTextTree = $b;
00253                                         }
00254                                         elseif ( $b->getName() == 'DjVuXML' ) {
00255                                                 $image->dejaMetaTree = $b;
00256                                         }
00257                                 }
00258                         } else {
00259                                 $image->dejaMetaTree = $tree;
00260                         }
00261                 } catch( Exception $e ) {
00262                         wfDebug( "Bogus multipage XML metadata on '{$image->getName()}'\n" );
00263                 }
00264                 wfRestoreWarnings();
00265                 wfProfileOut( __METHOD__ );
00266                 if( $gettext ) {
00267                         return $image->djvuTextTree;
00268                 } else {
00269                         return $image->dejaMetaTree;
00270                 }
00271         }
00272 
00273         function getImageSize( $image, $path ) {
00274                 return $this->getDjVuImage( $image, $path )->getImageSize();
00275         }
00276 
00277         function getThumbType( $ext, $mime, $params = null ) {
00278                 global $wgDjvuOutputExtension;
00279                 static $mime;
00280                 if ( !isset( $mime ) ) {
00281                         $magic = MimeMagic::singleton();
00282                         $mime = $magic->guessTypesForExtension( $wgDjvuOutputExtension );
00283                 }
00284                 return array( $wgDjvuOutputExtension, $mime );
00285         }
00286 
00287         function getMetadata( $image, $path ) {
00288                 wfDebug( "Getting DjVu metadata for $path\n" );
00289                 return $this->getDjVuImage( $image, $path )->retrieveMetaData();
00290         }
00291 
00292         function getMetadataType( $image ) {
00293                 return 'djvuxml';
00294         }
00295 
00296         function isMetadataValid( $image, $metadata ) {
00297                 return !empty( $metadata ) && $metadata != serialize(array());
00298         }
00299 
00300         function pageCount( $image ) {
00301                 $tree = $this->getMetaTree( $image );
00302                 if ( !$tree ) {
00303                         return false;
00304                 }
00305                 return count( $tree->xpath( '//OBJECT' ) );
00306         }
00307 
00308         function getPageDimensions( $image, $page ) {
00309                 $tree = $this->getMetaTree( $image );
00310                 if ( !$tree ) {
00311                         return false;
00312                 }
00313 
00314                 $o = $tree->BODY[0]->OBJECT[$page-1];
00315                 if ( $o ) {
00316                         return array(
00317                                 'width' => intval( $o['width'] ),
00318                                 'height' => intval( $o['height'] )
00319                         );
00320                 } else {
00321                         return false;
00322                 }
00323         }
00324 
00325         function getPageText( $image, $page ){
00326                 $tree = $this->getMetaTree( $image, true );
00327                 if ( !$tree ) {
00328                         return false;
00329                 }
00330 
00331                 $o = $tree->BODY[0]->PAGE[$page-1];
00332                 if ( $o ) {
00333                         $txt = $o['value'];
00334                         return $txt;
00335                 } else {
00336                         return false;
00337                 }
00338 
00339         }
00340 
00341 }