Paladox has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/243936

Change subject: Rename extension files to EasyTimeline
......................................................................

Rename extension files to EasyTimeline

Matches extension name as it is called internal.

Replaced the uppercased Timeline.php file with the Lowecase timeline.php
file which requires the new EasyTimeline.php file so that jenkins test run
on it.

In the future we will add extension.json.

Remove i18n shim.

Converted spaces to tabs in en.json.

Moved funtions and class into own files.

Renamed the emssages inside the i18n files to prefix the extension name.

Change-Id: I8ebf3d0e4d381e632a19c340aaabef863fc1b726
---
A EasyTimeline.class.php
A EasyTimeline.hooks.php
A EasyTimeline.php
D Timeline.i18n.php
D Timeline.php
M i18n/en.json
M i18n/qqq.json
A timeline.php
8 files changed, 317 insertions(+), 345 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/timeline 
refs/changes/36/243936/1

diff --git a/EasyTimeline.class.php b/EasyTimeline.class.php
new file mode 100644
index 0000000..f17752f
--- /dev/null
+++ b/EasyTimeline.class.php
@@ -0,0 +1,29 @@
+<?php
+
+class TimelineSettings {
+       public $ploticusCommand, $perlCommand;
+
+       // Update this timestamp to force older rendered timelines
+       // to be generated when the page next gets rendered.
+       // Can help to resolve old image-generation bugs.
+       public $epochTimestamp = '20120101000000';
+
+       // Path to the EasyTimeline.pl perl file, which is used to actually 
generate the timelines.
+       public $timelineFile;
+
+       // Font name.
+       // Documentation on how Ploticus handles fonts is available at
+       // http://ploticus.sourceforge.net/doc/fonts.html section "What fonts 
are available?"
+       // and below. If using a TrueType font, the file with .ttf extension
+       // must be available in path specified by environment variable 
$GDFONTPATH;
+       // some other font types are available (see the docs linked above).
+       //
+       // Use the fontname 'ascii' to use the internal Ploticus font that does 
not require
+       // an external font file. Defaults to FreeSans for backwards 
compatibility.
+       //
+       // Note: according to Ploticus docs, font names with a space may be 
problematic.
+       public $fontFile = 'FreeSans';
+
+       // The name of the FileBackend to use for timeline (see $wgFileBackends)
+       public $fileBackend = '';
+}
diff --git a/EasyTimeline.hooks.php b/EasyTimeline.hooks.php
new file mode 100644
index 0000000..6f31ee2
--- /dev/null
+++ b/EasyTimeline.hooks.php
@@ -0,0 +1,249 @@
+<?php
+
+class EasyTimelineHooks {
+       /**
+        * @param $parser Parser
+        * @return bool
+        */
+       public static function onEasyTimelineExtension( &$parser ) {
+               $parser->setHook( 'timeline', 'onRenderTimeline' );
+               return true;
+       }
+
+       /**
+        * @param $timelinesrc string
+        * @param $args array
+        * @throws Exception
+        * @return string HTML
+        */
+       function onRenderTimeline( $timelinesrc, array $args ) {
+               global $wgUploadDirectory, $wgUploadPath, $wgArticlePath, 
$wgTmpDirectory, $wgRenderHashAppend;
+               global $wgTimelineSettings;
+
+               $method = isset( $args['method'] ) ? $args['method'] : 
'ploticusOnly';
+               $svg2png = ( $method == 'svg2png' );
+
+               // Get the backend to store plot data and pngs
+               if ( $wgTimelineSettings->fileBackend != '' ) {
+                       $backend = FileBackendGroup::singleton()->get( 
$wgTimelineSettings->fileBackend );
+               } else {
+                       $backend = new FSFileBackend( array(
+                               'name'           => 'timeline-backend',
+                               'wikiId'         => wfWikiId(),
+                               'lockManager'    => new NullLockManager( 
array() ),
+                               'containerPaths' => array( 'timeline-render' => 
"{$wgUploadDirectory}/timeline" ),
+                               'fileMode'       => 0777
+                       ) );
+               }
+
+               // Get a hash of the plot data.
+               // $args must be checked, because the same source text may be 
used with
+               // with different args.
+               $hash = md5( $timelinesrc . implode( '', $args ) );
+               if ( $wgRenderHashAppend != '' ) {
+                       $hash = md5( $hash . $wgRenderHashAppend );
+               }
+
+               // Storage destination path (excluding file extension)
+               $fname = 'mwstore://' . $backend->getName() . 
"/timeline-render/$hash";
+
+               $previouslyFailed = $backend->fileExists( array( 'src' => 
"{$fname}.err" ) );
+               $previouslyRendered = $backend->fileExists( array( 'src' => 
"{$fname}.png" ) );
+               if ( $previouslyRendered ) {
+                       $timestamp = $backend->getFileTimestamp( array( 'src' 
=> "{$fname}.png" ) );
+                       $expired = ( $timestamp < 
$wgTimelineSettings->epochTimestamp );
+               } else {
+                       $expired = false;
+               }
+
+               // Create a new .map, .png (or .gif), and .err file as needed...
+               if ( $expired || ( !$previouslyRendered && !$previouslyFailed ) 
) {
+                       if ( !is_dir( $wgTmpDirectory ) ) {
+                               mkdir( $wgTmpDirectory, 0777 );
+                       }
+                       $tmpFile = TempFSFile::factory( 'timeline_' );
+                       if ( $tmpFile ) {
+                               $tmpPath = $tmpFile->getPath();
+                               file_put_contents( $tmpPath, $timelinesrc ); // 
store plot data to file
+
+                               $filesCollect = array(); // temp files to clean 
up
+                               foreach ( array( 'map', 'png', 'svg', 'err' ) 
as $ext ) {
+                                       $fileCollect = new TempFSFile( 
"{$tmpPath}.{$ext}" );
+                                       $fileCollect->autocollect(); // clean 
this up
+                                       $filesCollect[] = $fileCollect;
+                               }
+
+                               // Get command for ploticus to read the user 
input and output an error,
+                               // map, and rendering (png or gif) file under 
the same dir as the temp file.
+                               $cmdline = wfEscapeShellArg( 
$wgTimelineSettings->perlCommand, $wgTimelineSettings->timelineFile ) .
+                               ($svg2png ? " -s " : "") .
+                               " -i " . wfEscapeShellArg( $tmpPath ) .
+                               " -m -P " . wfEscapeShellArg( 
$wgTimelineSettings->ploticusCommand ) .
+                               " -T " . wfEscapeShellArg( $wgTmpDirectory ) .
+                               " -A " . wfEscapeShellArg( $wgArticlePath ) .
+                               " -f " . wfEscapeShellArg( 
$wgTimelineSettings->fontFile );
+
+                               // Actually run the command...
+                               wfDebug( "Timeline cmd: $cmdline\n" );
+                               $retVal = null;
+                               $ret = wfShellExec( $cmdline, $retVal );
+
+                               // If running in svg2png mode, create the PNG 
file from the SVG
+                               if ( $svg2png ) {
+                                       // Read the default timeline image size 
from the DVG file
+                                       $svgFilename = "{$tmpPath}.svg";
+                                       wfSuppressWarnings();
+                                       $svgHandle = fopen( $svgFilename, "r" );
+                                       wfRestoreWarnings();
+                                       if ( !$svgHandle ) {
+                                               throw new Exception( "Unable to 
open file $svgFilename for reading the timeline size" );
+                                       }
+                                       while ( !feof( $svgHandle ) ) {
+                                               $line = fgets( $svgHandle );
+                                               if ( preg_match( 
'/width="([0-9.]+)" height="([0-9.]+)"/', $line, $matches ) ) {
+                                                       $svgWidth = $matches[1];
+                                                       $svgHeight = 
$matches[2];
+                                                       break;
+                                               }
+                                       }
+                                       fclose( $svgHandle );
+
+                                       $svgHandler = new SvgHandler();
+                                       wfDebug( "Rasterizing PNG timeline from 
SVG $svgFilename, size $svgWidth x $svgHeight\n" );
+                                       $rasterizeResult = 
$svgHandler->rasterize( $svgFilename, "{$tmpPath}.png", $svgWidth, $svgHeight );
+                                       if ( $rasterizeResult !== true ) {
+                                               return "<div class=\"error\" 
dir=\"ltr\">FAIL: " . $rasterizeResult->toText() . "</div>";
+                                       }
+                               }
+
+                               // Copy the output files into storage...
+                               // @TODO: store error files in another 
container or not at all?
+                               $ops = array();
+                               $backend->prepare( array( 'dir' => dirname( 
$fname ) ) );
+                               foreach ( array( 'map', 'png', 'err' ) as $ext 
) {
+                                       if ( file_exists( "{$tmpPath}.{$ext}" ) 
) {
+                                               $ops[] = array( 'op' => 'store',
+                                                       'src' => 
"{$tmpPath}.{$ext}", 'dst' => "{$fname}.{$ext}" );
+                                       }
+                               }
+                               if ( !$backend->doQuickOperations( $ops 
)->isOK() ) {
+                                       return "<div class=\"error\" 
dir=\"ltr\"><tt>Timeline error. " .
+                                               "Could not store output 
files</tt></div>"; // ugh
+                               }
+                       } else {
+                               return "<div class=\"error\" 
dir=\"ltr\"><tt>Timeline error. " .
+                                       "Could not create temp 
file</tt></div>"; // ugh
+                       }
+
+                       if ( $ret == "" || $retVal > 0 ) {
+                               // Message not localized, only relevant during 
install
+                               return "<div class=\"error\" 
dir=\"ltr\"><tt>Timeline error. " .
+                                       "Command line was: " . 
htmlspecialchars( $cmdline ) . "</tt></div>";
+                       }
+               }
+
+               $err = $backend->getFileContents( array( 'src' => 
"{$fname}.err" ) );
+
+               if ( $err != "" ) {
+                       // Convert the error from poorly-sanitized HTML to 
plain text
+                       $err = strtr( $err, array(
+                               '</p><p>' => "\n\n",
+                               '<p>' => '',
+                               '</p>' => '',
+                               '<b>' => '',
+                               '</b>' => '',
+                               '<br>' => "\n" ) );
+                       $err = Sanitizer::decodeCharReferences( $err );
+
+                       // Now convert back to HTML again
+                       $encErr = nl2br( htmlspecialchars( $err ) );
+                       $txt = "<div class=\"error\" 
dir=\"ltr\"><tt>$encErr</tt></div>";
+               } else {
+                       $map = $backend->getFileContents( array( 'src' => 
"{$fname}.map" ) );
+
+                       $map = str_replace( ' >', ' />', $map );
+                       $map = "<map name=\"timeline_" . htmlspecialchars( 
$hash ) . "\">{$map}</map>";
+                       $map = easyTimelineFixMap( $map );
+
+                       $url = "{$wgUploadPath}/timeline/{$hash}.png";
+                       $txt = $map .
+                               "<img usemap=\"#timeline_" . htmlspecialchars( 
$hash ) . "\" " .
+                               "src=\"" . htmlspecialchars( $url ) . "\">";
+
+                       if( $expired ) {
+                               // Replacing an older file, we may need to 
purge the old one.
+                               global $wgUseSquid;
+                               if( $wgUseSquid ) {
+                                       $u = new SquidUpdate( array( $url ) );
+                                       $u->doUpdate();
+                               }
+                       }
+               }
+
+               return $txt;
+       }
+
+       /**
+        * Do a security check on the image map HTML
+        * @param $html string
+        * @return string HTML
+        */
+       function easyTimelineFixMap( $html ) {
+               global $wgUrlProtocols;
+               $doc = new DOMDocument( '1.0', 'UTF-8' );
+               wfSuppressWarnings();
+               $status = $doc->loadXML( $html );
+               wfRestoreWarnings();
+               if ( !$status ) {
+                        // Load messages only if error occurs
+                       return '<div class="error">' . wfMessage( 
'easytimeline-invalidmap' )->text() . '</div>';
+               }
+
+               $map = $doc->firstChild;
+               if ( strtolower( $map->nodeName ) !== 'map' ) {
+                        // Load messages only if error occurs
+                       return '<div class="error">' . wfMessage( 
'easytimeline-invalidmap' )->text() . '</div>';
+               }
+               $name = $map->attributes->getNamedItem( 'name' )->value;
+               $html = Xml::openElement( 'map', array( 'name' => $name ) );
+
+               $allowedAttribs = array( 'shape', 'coords', 'href', 'nohref', 
'alt',
+                       'tabindex', 'title' );
+               foreach ( $map->childNodes as $node ) {
+                       if ( strtolower( $node->nodeName ) !== 'area' ) {
+                               continue;
+                       }
+                       $ok = true;
+                       $attributes = array();
+                       foreach ( $node->attributes as $name => $value ) {
+                               $value = $value->value;
+                               $lcName = strtolower( $name );
+                               if ( !in_array( $lcName, $allowedAttribs ) ) {
+                                       $ok = false;
+                                       break;
+                               }
+                               if ( $lcName == 'href' && substr( $value, 0, 1 
) !== '/' ) {
+                                       $ok = false;
+                                       foreach ( $wgUrlProtocols as $protocol 
) {
+                                               if ( substr( $value, 0, strlen( 
$protocol ) ) == $protocol ) {
+                                                       $ok = true;
+                                                       break;
+                                               }
+                                       }
+                                       if ( !$ok ) {
+                                               break;
+                                       }
+                               }
+                               $attributes[$name] = $value;
+                       }
+                       if ( !$ok ) {
+                               $html .= "<!-- illegal element removed -->\n";
+                               continue;
+                       }
+
+                       $html .= Xml::element( 'area', $attributes );
+               }
+               $html .= '</map>';
+               return $html;
+       }
+}
diff --git a/EasyTimeline.php b/EasyTimeline.php
new file mode 100644
index 0000000..c57dcbd
--- /dev/null
+++ b/EasyTimeline.php
@@ -0,0 +1,28 @@
+<?php
+/**
+ * EasyTimeline
+ * To use, include this file from your LocalSettings.php
+ * To configure, set members of $wgTimelineSettings after the inclusion
+ *
+ * @file
+ * @ingroup Extensions
+ * @author Erik Zachte <x...@chello.nl (nospam: xxx=epzachte)>
+ * @license GNU General Public License version 2
+ * @link http://www.mediawiki.org/wiki/Extension:EasyTimeline Documentation
+ */
+
+$wgExtensionCredits['parserhook'][] = array(
+       'path' => __FILE__,
+       'name' => 'EasyTimeline',
+       'author' => 'Erik Zachte',
+       'url' => 'https://www.mediawiki.org/wiki/Extension:EasyTimeline',
+       'descriptionmsg' => 'easytimeline-desc',
+);
+
+$wgTimelineSettings = new TimelineSettings;
+$wgTimelineSettings->ploticusCommand = "/usr/bin/ploticus";
+$wgTimelineSettings->perlCommand = "/usr/bin/perl";
+$wgTimelineSettings->timelineFile = __DIR__ . "/EasyTimeline.pl";
+
+$wgHooks['ParserFirstCallInit'][] = 
'EasyTimelineHooks::onEasyTimelineExtension';
+$wgMessagesDirs['EasyTimeline'] = __DIR__ . '/i18n';
diff --git a/Timeline.i18n.php b/Timeline.i18n.php
deleted file mode 100644
index a0f596f..0000000
--- a/Timeline.i18n.php
+++ /dev/null
@@ -1,35 +0,0 @@
-<?php
-/**
- * This is a backwards-compatibility shim, generated by:
- * 
https://git.wikimedia.org/blob/mediawiki%2Fcore.git/HEAD/maintenance%2FgenerateJsonI18n.php
- *
- * Beginning with MediaWiki 1.23, translation strings are stored in json files,
- * and the EXTENSION.i18n.php file only exists to provide compatibility with
- * older releases of MediaWiki. For more information about this migration, see:
- * https://www.mediawiki.org/wiki/Requests_for_comment/Localisation_format
- *
- * This shim maintains compatibility back to MediaWiki 1.17.
- */
-$messages = array();
-if ( !function_exists( 'wfJsonI18nShim96c961c7746fddd4' ) ) {
-       function wfJsonI18nShim96c961c7746fddd4( $cache, $code, &$cachedData ) {
-               $codeSequence = array_merge( array( $code ), 
$cachedData['fallbackSequence'] );
-               foreach ( $codeSequence as $csCode ) {
-                       $fileName = dirname( __FILE__ ) . "/i18n/$csCode.json";
-                       if ( is_readable( $fileName ) ) {
-                               $data = FormatJson::decode( file_get_contents( 
$fileName ), true );
-                               foreach ( array_keys( $data ) as $key ) {
-                                       if ( $key === '' || $key[0] === '@' ) {
-                                               unset( $data[$key] );
-                                       }
-                               }
-                               $cachedData['messages'] = array_merge( $data, 
$cachedData['messages'] );
-                       }
-
-                       $cachedData['deps'][] = new FileDependency( $fileName );
-               }
-               return true;
-       }
-
-       $GLOBALS['wgHooks']['LocalisationCacheRecache'][] = 
'wfJsonI18nShim96c961c7746fddd4';
-}
diff --git a/Timeline.php b/Timeline.php
deleted file mode 100644
index 07f1ecf..0000000
--- a/Timeline.php
+++ /dev/null
@@ -1,302 +0,0 @@
-<?php
-/**
- * EasyTimeline - Timeline extension
- * To use, include this file from your LocalSettings.php
- * To configure, set members of $wgTimelineSettings after the inclusion
- *
- * @file
- * @ingroup Extensions
- * @author Erik Zachte <x...@chello.nl (nospam: xxx=epzachte)>
- * @license GNU General Public License version 2
- * @link http://www.mediawiki.org/wiki/Extension:EasyTimeline Documentation
- */
-
-$wgExtensionCredits['parserhook'][] = array(
-       'path' => __FILE__,
-       'name' => 'EasyTimeline',
-       'author' => 'Erik Zachte',
-       'url' => 'https://www.mediawiki.org/wiki/Extension:EasyTimeline',
-       'descriptionmsg' => 'timeline-desc',
-);
-
-class TimelineSettings {
-       public $ploticusCommand, $perlCommand;
-
-       // Update this timestamp to force older rendered timelines
-       // to be generated when the page next gets rendered.
-       // Can help to resolve old image-generation bugs.
-       public $epochTimestamp = '20120101000000';
-
-       // Path to the EasyTimeline.pl perl file, which is used to actually 
generate the timelines.
-       public $timelineFile;
-
-       // Font name.
-       // Documentation on how Ploticus handles fonts is available at
-       // http://ploticus.sourceforge.net/doc/fonts.html section "What fonts 
are available?"
-       // and below. If using a TrueType font, the file with .ttf extension
-       // must be available in path specified by environment variable 
$GDFONTPATH;
-       // some other font types are available (see the docs linked above).
-       //
-       // Use the fontname 'ascii' to use the internal Ploticus font that does 
not require
-       // an external font file. Defaults to FreeSans for backwards 
compatibility.
-       //
-       // Note: according to Ploticus docs, font names with a space may be 
problematic.
-       public $fontFile = 'FreeSans';
-
-       // The name of the FileBackend to use for timeline (see $wgFileBackends)
-       public $fileBackend = '';
-}
-$wgTimelineSettings = new TimelineSettings;
-$wgTimelineSettings->ploticusCommand = "/usr/bin/ploticus";
-$wgTimelineSettings->perlCommand = "/usr/bin/perl";
-$wgTimelineSettings->timelineFile = __DIR__ . "/EasyTimeline.pl";
-
-$wgHooks['ParserFirstCallInit'][] = 'wfTimelineExtension';
-$wgMessagesDirs['Timeline'] = __DIR__ . '/i18n';
-$wgExtensionMessagesFiles['Timeline'] = __DIR__ . '/Timeline.i18n.php';
-
-/**
- * @param $parser Parser
- * @return bool
- */
-function wfTimelineExtension( &$parser ) {
-       $parser->setHook( 'timeline', 'wfRenderTimeline' );
-       return true;
-}
-
-/**
- * @param $timelinesrc string
- * @param $args array
- * @throws Exception
- * @return string HTML
- */
-function wfRenderTimeline( $timelinesrc, array $args ) {
-       global $wgUploadDirectory, $wgUploadPath, $wgArticlePath, 
$wgTmpDirectory, $wgRenderHashAppend;
-       global $wgTimelineSettings;
-
-       $method = isset( $args['method'] ) ? $args['method'] : 'ploticusOnly';
-       $svg2png = ( $method == 'svg2png' );
-
-       // Get the backend to store plot data and pngs
-       if ( $wgTimelineSettings->fileBackend != '' ) {
-               $backend = FileBackendGroup::singleton()->get( 
$wgTimelineSettings->fileBackend );
-       } else {
-               $backend = new FSFileBackend( array(
-                       'name'           => 'timeline-backend',
-                       'wikiId'         => wfWikiId(),
-                       'lockManager'    => new NullLockManager( array() ),
-                       'containerPaths' => array( 'timeline-render' => 
"{$wgUploadDirectory}/timeline" ),
-                       'fileMode'       => 0777
-               ) );
-       }
-
-       // Get a hash of the plot data.
-       // $args must be checked, because the same source text may be used with
-       // with different args.
-       $hash = md5( $timelinesrc . implode( '', $args ) );
-       if ( $wgRenderHashAppend != '' ) {
-               $hash = md5( $hash . $wgRenderHashAppend );
-       }
-
-       // Storage destination path (excluding file extension)
-       $fname = 'mwstore://' . $backend->getName() . "/timeline-render/$hash";
-
-       $previouslyFailed = $backend->fileExists( array( 'src' => 
"{$fname}.err" ) );
-       $previouslyRendered = $backend->fileExists( array( 'src' => 
"{$fname}.png" ) );
-       if ( $previouslyRendered ) {
-               $timestamp = $backend->getFileTimestamp( array( 'src' => 
"{$fname}.png" ) );
-               $expired = ( $timestamp < $wgTimelineSettings->epochTimestamp );
-       } else {
-               $expired = false;
-       }
-
-       // Create a new .map, .png (or .gif), and .err file as needed...
-       if ( $expired || ( !$previouslyRendered && !$previouslyFailed ) ) {
-               if ( !is_dir( $wgTmpDirectory ) ) {
-                       mkdir( $wgTmpDirectory, 0777 );
-               }
-               $tmpFile = TempFSFile::factory( 'timeline_' );
-               if ( $tmpFile ) {
-                       $tmpPath = $tmpFile->getPath();
-                       file_put_contents( $tmpPath, $timelinesrc ); // store 
plot data to file
-
-                       $filesCollect = array(); // temp files to clean up
-                       foreach ( array( 'map', 'png', 'svg', 'err' ) as $ext ) 
{
-                               $fileCollect = new TempFSFile( 
"{$tmpPath}.{$ext}" );
-                               $fileCollect->autocollect(); // clean this up
-                               $filesCollect[] = $fileCollect;
-                       }
-
-                       // Get command for ploticus to read the user input and 
output an error,
-                       // map, and rendering (png or gif) file under the same 
dir as the temp file.
-                       $cmdline = wfEscapeShellArg( 
$wgTimelineSettings->perlCommand, $wgTimelineSettings->timelineFile ) .
-                       ($svg2png ? " -s " : "") .
-                       " -i " . wfEscapeShellArg( $tmpPath ) .
-                       " -m -P " . wfEscapeShellArg( 
$wgTimelineSettings->ploticusCommand ) .
-                       " -T " . wfEscapeShellArg( $wgTmpDirectory ) .
-                       " -A " . wfEscapeShellArg( $wgArticlePath ) .
-                       " -f " . wfEscapeShellArg( 
$wgTimelineSettings->fontFile );
-
-                       // Actually run the command...
-                       wfDebug( "Timeline cmd: $cmdline\n" );
-                       $retVal = null;
-                       $ret = wfShellExec( $cmdline, $retVal );
-
-                       // If running in svg2png mode, create the PNG file from 
the SVG
-                       if ( $svg2png ) {
-                               // Read the default timeline image size from 
the DVG file
-                               $svgFilename = "{$tmpPath}.svg";
-                               wfSuppressWarnings();
-                               $svgHandle = fopen( $svgFilename, "r" );
-                               wfRestoreWarnings();
-                               if ( !$svgHandle ) {
-                                       throw new Exception( "Unable to open 
file $svgFilename for reading the timeline size" );
-                               }
-                               while ( !feof( $svgHandle ) ) {
-                                       $line = fgets( $svgHandle );
-                                       if ( preg_match( '/width="([0-9.]+)" 
height="([0-9.]+)"/', $line, $matches ) ) {
-                                               $svgWidth = $matches[1];
-                                               $svgHeight = $matches[2];
-                                               break;
-                                       }
-                               }
-                               fclose( $svgHandle );
-
-                               $svgHandler = new SvgHandler();
-                               wfDebug( "Rasterizing PNG timeline from SVG 
$svgFilename, size $svgWidth x $svgHeight\n" );
-                               $rasterizeResult = $svgHandler->rasterize( 
$svgFilename, "{$tmpPath}.png", $svgWidth, $svgHeight );
-                               if ( $rasterizeResult !== true ) {
-                                       return "<div class=\"error\" 
dir=\"ltr\">FAIL: " . $rasterizeResult->toText() . "</div>";
-                               }
-                       }
-
-                       // Copy the output files into storage...
-                       // @TODO: store error files in another container or not 
at all?
-                       $ops = array();
-                       $backend->prepare( array( 'dir' => dirname( $fname ) ) 
);
-                       foreach ( array( 'map', 'png', 'err' ) as $ext ) {
-                               if ( file_exists( "{$tmpPath}.{$ext}" ) ) {
-                                       $ops[] = array( 'op' => 'store',
-                                               'src' => "{$tmpPath}.{$ext}", 
'dst' => "{$fname}.{$ext}" );
-                               }
-                       }
-                       if ( !$backend->doQuickOperations( $ops )->isOK() ) {
-                               return "<div class=\"error\" 
dir=\"ltr\"><tt>Timeline error. " .
-                                       "Could not store output 
files</tt></div>"; // ugh
-                       }
-               } else {
-                       return "<div class=\"error\" dir=\"ltr\"><tt>Timeline 
error. " .
-                               "Could not create temp file</tt></div>"; // ugh
-               }
-
-               if ( $ret == "" || $retVal > 0 ) {
-                       // Message not localized, only relevant during install
-                       return "<div class=\"error\" dir=\"ltr\"><tt>Timeline 
error. " .
-                               "Command line was: " . htmlspecialchars( 
$cmdline ) . "</tt></div>";
-               }
-       }
-
-       $err = $backend->getFileContents( array( 'src' => "{$fname}.err" ) );
-
-       if ( $err != "" ) {
-               // Convert the error from poorly-sanitized HTML to plain text
-               $err = strtr( $err, array(
-                       '</p><p>' => "\n\n",
-                       '<p>' => '',
-                       '</p>' => '',
-                       '<b>' => '',
-                       '</b>' => '',
-                       '<br>' => "\n" ) );
-               $err = Sanitizer::decodeCharReferences( $err );
-
-               // Now convert back to HTML again
-               $encErr = nl2br( htmlspecialchars( $err ) );
-               $txt = "<div class=\"error\" 
dir=\"ltr\"><tt>$encErr</tt></div>";
-       } else {
-               $map = $backend->getFileContents( array( 'src' => 
"{$fname}.map" ) );
-
-               $map = str_replace( ' >', ' />', $map );
-               $map = "<map name=\"timeline_" . htmlspecialchars( $hash ) . 
"\">{$map}</map>";
-               $map = easyTimelineFixMap( $map );
-
-               $url = "{$wgUploadPath}/timeline/{$hash}.png";
-               $txt = $map .
-                       "<img usemap=\"#timeline_" . htmlspecialchars( $hash ) 
. "\" " .
-                       "src=\"" . htmlspecialchars( $url ) . "\">";
-
-               if( $expired ) {
-                       // Replacing an older file, we may need to purge the 
old one.
-                       global $wgUseSquid;
-                       if( $wgUseSquid ) {
-                               $u = new SquidUpdate( array( $url ) );
-                               $u->doUpdate();
-                       }
-               }
-       }
-
-       return $txt;
-}
-
-/**
- * Do a security check on the image map HTML
- * @param $html string
- * @return string HTML
- */
-function easyTimelineFixMap( $html ) {
-       global $wgUrlProtocols;
-       $doc = new DOMDocument( '1.0', 'UTF-8' );
-       wfSuppressWarnings();
-       $status = $doc->loadXML( $html );
-       wfRestoreWarnings();
-       if ( !$status ) {
-                // Load messages only if error occurs
-               return '<div class="error">' . wfMessage( 'timeline-invalidmap' 
)->text() . '</div>';
-       }
-
-       $map = $doc->firstChild;
-       if ( strtolower( $map->nodeName ) !== 'map' ) {
-                // Load messages only if error occurs
-               return '<div class="error">' . wfMessage( 'timeline-invalidmap' 
)->text() . '</div>';
-       }
-       $name = $map->attributes->getNamedItem( 'name' )->value;
-       $html = Xml::openElement( 'map', array( 'name' => $name ) );
-
-       $allowedAttribs = array( 'shape', 'coords', 'href', 'nohref', 'alt',
-               'tabindex', 'title' );
-       foreach ( $map->childNodes as $node ) {
-               if ( strtolower( $node->nodeName ) !== 'area' ) {
-                       continue;
-               }
-               $ok = true;
-               $attributes = array();
-               foreach ( $node->attributes as $name => $value ) {
-                       $value = $value->value;
-                       $lcName = strtolower( $name );
-                       if ( !in_array( $lcName, $allowedAttribs ) ) {
-                               $ok = false;
-                               break;
-                       }
-                       if ( $lcName == 'href' && substr( $value, 0, 1 ) !== 
'/' ) {
-                               $ok = false;
-                               foreach ( $wgUrlProtocols as $protocol ) {
-                                       if ( substr( $value, 0, strlen( 
$protocol ) ) == $protocol ) {
-                                               $ok = true;
-                                               break;
-                                       }
-                               }
-                               if ( !$ok ) {
-                                       break;
-                               }
-                       }
-                       $attributes[$name] = $value;
-               }
-               if ( !$ok ) {
-                       $html .= "<!-- illegal element removed -->\n";
-                       continue;
-               }
-
-               $html .= Xml::element( 'area', $attributes );
-       }
-       $html .= '</map>';
-       return $html;
-}
diff --git a/i18n/en.json b/i18n/en.json
index 624227b..b107cc9 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -1,7 +1,7 @@
 {
-    "@metadata": {
-        "authors": []
-    },
-    "timeline-desc": "Adds <code>&lt;timeline&gt;</code> tag to create 
timelines",
-    "timeline-invalidmap": "Invalid image map generated by EasyTimeline"
-}
\ No newline at end of file
+       "@metadata": {
+               "authors": []
+       },
+       "easytimeline-desc": "Adds <code>&lt;timeline&gt;</code> tag to create 
timelines",
+       "easytimeline-invalidmap": "Invalid image map generated by EasyTimeline"
+}
diff --git a/i18n/qqq.json b/i18n/qqq.json
index a8d4602..2644d01 100644
--- a/i18n/qqq.json
+++ b/i18n/qqq.json
@@ -6,6 +6,6 @@
                        "Shirayuki"
                ]
        },
-       "timeline-desc": "Extension description displayed on 
[[Special:Version]]",
-       "timeline-invalidmap": "Used as error message if failed to load XML or 
the first node in XML is not \"map\"."
+       "easytimeline-desc": 
"{{desc|what=extension|name=EasyTimeline|url=https://www.mediawiki.org/wiki/Extension:EasyTimeline}}";,
+       "easytimeline-invalidmap": "Used as error message if failed to load XML 
or the first node in XML is not \"map\"."
 }
diff --git a/timeline.php b/timeline.php
new file mode 100644
index 0000000..a9c54a3
--- /dev/null
+++ b/timeline.php
@@ -0,0 +1,3 @@
+<?php
+
+require_once __DIR__ . '/EasyTimeline.php';

-- 
To view, visit https://gerrit.wikimedia.org/r/243936
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I8ebf3d0e4d381e632a19c340aaabef863fc1b726
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/timeline
Gerrit-Branch: master
Gerrit-Owner: Paladox <thomasmulhall...@yahoo.com>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to