Index: trunk/extensions/TrustedMath/TrustedMath_body.php |
— | — | @@ -0,0 +1,95 @@ |
| 2 | +<?php |
| 3 | +class TrustedMath { |
| 4 | + |
| 5 | + |
| 6 | + public static function newFromText( $text ) { |
| 7 | + return new self( $text ); |
| 8 | + } |
| 9 | + public static function newFromTitle( $title ) { |
| 10 | + $text = Article::newFromId( $title->getArticleId() )->getRawText(); |
| 11 | + return new self( $text ); |
| 12 | + } |
| 13 | + |
| 14 | + |
| 15 | + protected $text = null; |
| 16 | + protected $hash = null; |
| 17 | + protected $error = array(); |
| 18 | + |
| 19 | + public function __construct( $text ) { |
| 20 | + $this->text = $text; |
| 21 | + } |
| 22 | + |
| 23 | + public function getHash() { |
| 24 | + if ( is_null( $this->hash ) ) { |
| 25 | + $this->hash = md5( $this->getText() ); |
| 26 | + } |
| 27 | + return $this->hash; |
| 28 | + } |
| 29 | + protected function getHashPath() { |
| 30 | + $hash = $this->getHash(); |
| 31 | + return $hash{0} . '/' . $hash{0} . $hash{1}; |
| 32 | + } |
| 33 | + |
| 34 | + public function getText() { |
| 35 | + return $this->text; |
| 36 | + } |
| 37 | + |
| 38 | + public function render( $force = false ) { |
| 39 | + global $wgTrustedMathLatexPath, $wgTrustedMathDviPngPath, |
| 40 | + $wgTrustedMathDirectory; |
| 41 | + |
| 42 | + $hash = $this->getHash(); |
| 43 | + $hashPath = $this->getHashPath(); |
| 44 | + $filePath = "$wgTrustedMathDirectory/$hashPath/$hash.png"; |
| 45 | + |
| 46 | + if ( !$force && file_exists( $filePath ) && |
| 47 | + filesize( $filePath ) > 0 ) { |
| 48 | + return Status::newGood( "$hashPath/$hash.png" ); |
| 49 | + } |
| 50 | + |
| 51 | + wfSuppressWarnings(); |
| 52 | + if ( !wfMkDirParents( "$wgTrustedMathDirectory/$hashPath" ) ) { |
| 53 | + wfRestoreWarnings(); |
| 54 | + return Status::newFatal( 'trustedmath-path-error', $hashPath ); |
| 55 | + } |
| 56 | + wfRestoreWarnings(); |
| 57 | + |
| 58 | + #$dir = wfTempDir(); |
| 59 | + $dir = $wgTrustedMathDirectory; |
| 60 | + $file = tempnam( $dir, 'trustedmath_' ); |
| 61 | + file_put_contents( "$file.tex", self::wrapEquation( $this->getText() ) ); |
| 62 | + |
| 63 | + // FIXME: dangerous |
| 64 | + $environ = array( 'USERPROFILE' => $wgTrustedMathDirectory ); |
| 65 | + |
| 66 | + $retval = null; |
| 67 | + wfShellExec( wfEscapeShellArg( $wgTrustedMathLatexPath, |
| 68 | + '-halt-on-error', '-output-directory', |
| 69 | + $dir, "$file.tex" ) . ' 2>&1', $retval, $environ ); |
| 70 | + if ( !file_exists( "$file.dvi" ) ) { |
| 71 | + return Status::newFatal( 'trustedmath-convert-error', |
| 72 | + $wgTrustedMathLatexPath ); |
| 73 | + } |
| 74 | + |
| 75 | + wfShellExec( wfEscapeShellArg( $wgTrustedMathDviPngPath ) . |
| 76 | + ' -D 150 -T tight -v -o ' . |
| 77 | + wfEscapeShellArg( $filePath, "$file.dvi" ), $retval, $environ ); |
| 78 | + if ( !file_exists( $filePath ) ) { |
| 79 | + return Status::newFatal( 'trustedmath-convert-error', |
| 80 | + $wgTrustedMathDviPngPath ); |
| 81 | + } |
| 82 | + |
| 83 | + return Status::newGood( "$hashPath/$hash.png" ); |
| 84 | + } |
| 85 | + |
| 86 | + protected static function wrapEquation( $equation ) { |
| 87 | + return implode( "\n", array( |
| 88 | + '\documentclass{article}', |
| 89 | + '\pagestyle{empty}', |
| 90 | + '\begin{document}', |
| 91 | + '$' . $equation . '$', |
| 92 | + '\end{document}', |
| 93 | + ) ); |
| 94 | + } |
| 95 | + |
| 96 | +} |
Property changes on: trunk/extensions/TrustedMath/TrustedMath_body.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 97 | + native |
Index: trunk/extensions/TrustedMath/TrustedMath.i18n.php |
— | — | @@ -0,0 +1,12 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +$messages = array(); |
| 5 | + |
| 6 | +$messages['en'] = array( |
| 7 | + 'trustedmath-namespace' => 'Math', |
| 8 | + 'trustedmath-talk-namespace' => 'Math_talk', |
| 9 | + 'trustedmath-permission-error' => 'Untrusted math is disabled on this wiki', |
| 10 | + 'trustedmath-path-error' => 'Error creating the math directory', |
| 11 | + 'trustedmath-convert-error' => 'Error creating math image in $1', |
| 12 | + |
| 13 | +); |
\ No newline at end of file |
Property changes on: trunk/extensions/TrustedMath/TrustedMath.i18n.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 14 | + native |
Index: trunk/extensions/TrustedMath/TrustedMath.php |
— | — | @@ -0,0 +1,20 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +$dir = dirname( __FILE__ ); |
| 5 | +$wgAutoloadClasses['TrustedMath'] = "$dir/TrustedMath_body.php"; |
| 6 | +$wgAutoloadClasses['TrustedMathHooks'] = "$dir/TrustedMathHooks.php"; |
| 7 | + |
| 8 | +$wgExtensionMessagesFiles['TrustedMath'] = "$dir/TrustedMath.i18n.php"; |
| 9 | + |
| 10 | +$wgExtensionFunctions[] = 'TrustedMathHooks::initGlobals'; |
| 11 | +$wgHooks['ParserFirstCallInit'][] = 'TrustedMathHooks::onParserFirstCallInit'; |
| 12 | +#Broken |
| 13 | +#$wgHooks['ParserAfterStrip'][] = 'TrustedMathHooks::onParserAfterStrip'; |
| 14 | + |
| 15 | + |
| 16 | +$wgTrustedMathLatexPath = null; |
| 17 | +$wgTrustedMathDviPngPath = null; |
| 18 | +$wgTrustedMathDirectory = null; |
| 19 | +$wgTrustedMathPath = null; |
| 20 | +$wgTrustedMathUnsafeMode = false; |
| 21 | +$wgTrustedMathNamespace = 262; |
\ No newline at end of file |
Property changes on: trunk/extensions/TrustedMath/TrustedMath.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 22 | + native |
Index: trunk/extensions/TrustedMath/TrustedMathHooks.php |
— | — | @@ -0,0 +1,106 @@ |
| 2 | +<?php |
| 3 | +class TrustedMathHooks { |
| 4 | + |
| 5 | + public static function onParserAfterStrip( $parser, &$text, &$stripState ) { |
| 6 | + global $wgTrustedMathNamespace; |
| 7 | + |
| 8 | + if ( $parser->getTitle()->getNamespace() == $wgTrustedMathNamespace ) { |
| 9 | + if ( strpos( $text, '<math>' ) === false ) { |
| 10 | + $text = "<math>$text</math>"; |
| 11 | + return false; |
| 12 | + } |
| 13 | + } |
| 14 | + return true; |
| 15 | + } |
| 16 | + |
| 17 | + |
| 18 | + public static function initGlobals() { |
| 19 | + global $wgTrustedMathDirectory, $wgTrustedMathPath; |
| 20 | + global $wgUploadDirectory, $wgUploadPath; |
| 21 | + |
| 22 | + if ( is_null( $wgTrustedMathDirectory ) ) { |
| 23 | + $wgTrustedMathDirectory = "$wgUploadDirectory/math"; |
| 24 | + } |
| 25 | + if ( is_null( $wgTrustedMathPath ) ) { |
| 26 | + $wgTrustedMathPath = "$wgUploadPath/math"; |
| 27 | + } |
| 28 | + |
| 29 | + self::initNamespace(); |
| 30 | + } |
| 31 | + |
| 32 | + public static function initNamespace() { |
| 33 | + global $wgExtraNamespaces, $wgNamespaceProtection; |
| 34 | + global $wgTrustedMathNamespace; |
| 35 | + |
| 36 | + if ( !isset( $wgExtraNamespaces[$wgTrustedMathNamespace] ) ) { |
| 37 | + $wgExtraNamespaces[$wgTrustedMathNamespace] = |
| 38 | + wfMsgForContent( 'trustedmath-namespace' ); |
| 39 | + } |
| 40 | + if ( !isset( $wgExtraNamespaces[$wgTrustedMathNamespace+1] ) ) { |
| 41 | + $wgExtraNamespaces[$wgTrustedMathNamespace+1] = |
| 42 | + wfMsgForContent( 'trustedmath-talk-namespace' ); |
| 43 | + } |
| 44 | + |
| 45 | + if ( !isset( $wgNamespaceProtection[$wgTrustedMathNamespace] ) ) { |
| 46 | + $wgNamespaceProtection[$wgTrustedMathNamespace] = array( 'editmath' ); |
| 47 | + } |
| 48 | + } |
| 49 | + |
| 50 | + public static function onParserFirstCallInit( $parser ) { |
| 51 | + $parser->setHook( 'math', __CLASS__ . '::mathTag' ); |
| 52 | + return true; |
| 53 | + } |
| 54 | + |
| 55 | + public static function mathTag( $input, $args, $parser, $frame ) { |
| 56 | + global $wgTrustedMathNamespace; |
| 57 | + |
| 58 | + if ( isset( $args['name'] ) ) { |
| 59 | + $title = Title::newFromText( $args['name'], $wgTrustedMathNamespace ); |
| 60 | + if ( !self::validateSafeMode( $title ) ) { |
| 61 | + return self::getPermissionError( $parser ); |
| 62 | + } |
| 63 | + |
| 64 | + $math = TrustedMath::newFromTitle( $title ); |
| 65 | + } else { |
| 66 | + global $wgTitle; // eeeeeewh |
| 67 | + |
| 68 | + if ( !self::validateSafeMode( $wgTitle ) ) { |
| 69 | + return self::getPermissionError( $parser ); |
| 70 | + } |
| 71 | + |
| 72 | + $math = TrustedMath::newFromText( $input ); |
| 73 | + } |
| 74 | + |
| 75 | + $status = $math->render(); |
| 76 | + |
| 77 | + if ( $status->isOk() ) { |
| 78 | + global $wgTrustedMathPath; |
| 79 | + |
| 80 | + return Html::element( 'img', array( |
| 81 | + 'src' => "{$wgTrustedMathPath}/{$status->value}", |
| 82 | + 'class' => 'tex', |
| 83 | + 'alt' => $math->getText(), |
| 84 | + ) ); |
| 85 | + } else { |
| 86 | + return $parser->recursiveTagParse( '<span class="error">' . |
| 87 | + $status->getWikiText() . '</span>', $frame ); |
| 88 | + } |
| 89 | + |
| 90 | + } |
| 91 | + |
| 92 | + protected static function validateSafeMode( $title ) { |
| 93 | + global $wgTrustedMathNamespace; |
| 94 | + return !( self::safeMode() && |
| 95 | + $title->getNamespace() != $wgTrustedMathNamespace ); |
| 96 | + } |
| 97 | + |
| 98 | + protected static function safeMode() { |
| 99 | + global $wgTrustedMathUnsafeMode; |
| 100 | + return !$wgTrustedMathUnsafeMode; |
| 101 | + } |
| 102 | + |
| 103 | + protected static function getPermissionError( $parser ) { |
| 104 | + return $parser->recursiveTagParse( '<span class="error">' . |
| 105 | + wfMsg( 'trustedmath-permission-error' ) . '</span>' ); |
| 106 | + } |
| 107 | +} |
\ No newline at end of file |
Property changes on: trunk/extensions/TrustedMath/TrustedMathHooks.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 108 | + native |