Index: config/index.php =================================================================== --- config/index.php (revision 48648) +++ config/index.php (working copy) @@ -81,6 +81,12 @@ $ourdb['mssql']['bgcolor'] = '#ffc0cb'; $ourdb['mssql']['rootuser'] = 'administrator'; +$ourdb['adodb']['fullname'] = 'Microsoft SQL Server'; +$ourdb['adodb']['havedriver'] = 1; +$ourdb['adodb']['compile'] = 'adodb.inc'; +$ourdb['adodb']['bgcolor'] = '#33ff33'; +$ourdb['adodb']['rootuser'] = 'sa'; + ?> @@ -537,6 +543,10 @@ print "
  • Found ImageMagick: $im; image thumbnailing will be enabled if you enable uploads.
  • \n"; $conf->ImageMagick = $im; break; + } else if ( file_exists( $im . '.exe' ) ) { + print "
  • Found ImageMagick: ${im}.exe; image thumbnailing will be enabled if you enable uploads.
  • \n"; + $conf->ImageMagick = $im . '.exe'; + break; } } Index: includes/AutoLoader.php =================================================================== --- includes/AutoLoader.php (revision 48648) +++ includes/AutoLoader.php (working copy) @@ -296,6 +296,7 @@ 'Blob' => 'includes/db/Database.php', 'ChronologyProtector' => 'includes/db/LBFactory.php', 'Database' => 'includes/db/Database.php', + 'DatabaseADODB' => 'includes/db/DatabaseADODB.php', 'DatabaseMssql' => 'includes/db/DatabaseMssql.php', 'DatabaseMysql' => 'includes/db/Database.php', 'DatabaseOracle' => 'includes/db/DatabaseOracle.php', Index: includes/BagOStuff.php =================================================================== --- includes/BagOStuff.php (revision 48648) +++ includes/BagOStuff.php (working copy) @@ -403,6 +403,7 @@ */ function _serialize( &$data ) { $serial = serialize( $data ); + return addslashes($serial); if( function_exists( 'gzdeflate' ) ) { return gzdeflate( $serial ); } else { @@ -416,6 +417,7 @@ * @return mixed */ function _unserialize( $serial ) { + return unserialize( stripslashes($serial) ); if( function_exists( 'gzinflate' ) ) { $decomp = @gzinflate( $serial ); if( false !== $decomp ) { @@ -490,6 +492,7 @@ return false; } function _strencode($s) { + return str_replace( "'", "''", $s ); return $this->_getDB()->strencode($s); } function _blobencode($s) { Index: includes/Credits.php =================================================================== --- includes/Credits.php (revision 48648) +++ includes/Credits.php (working copy) @@ -203,4 +203,4 @@ $skin = $wgUser->getSkin(); return $skin->link( $article->getTitle(), wfMsgHtml( 'others' ), array(), array( 'action' => 'credits' ), array( 'known' ) ); } -} \ No newline at end of file +} Index: includes/db/Database.php =================================================================== --- includes/db/Database.php (revision 48648) +++ includes/db/Database.php (working copy) @@ -2671,6 +2671,10 @@ function fetchObject() { return $this->db->fetchObject( $this->result ); } + + function fetchNextObject() { + return $this->db->fetchNextObject( $this->result ); + } /** * Fetch the next row from the given result object, in associative array Index: includes/Defines.php =================================================================== --- includes/Defines.php (revision 48648) +++ includes/Defines.php (working copy) @@ -72,6 +72,12 @@ */ define('NS_IMAGE', NS_FILE); define('NS_IMAGE_TALK', NS_FILE_TALK); +define('NS_PORTAL', 100); +define('NS_PORTAL_TALK', 101); +define('NS_MANUAL', 102); +define('NS_MANUAL_TALK', 103); +define('NS_EXTENSION', 104); +define('NS_EXTENSION_TALK', 105); /**#@-*/ /** Index: includes/filerepo/File.php =================================================================== --- includes/filerepo/File.php (revision 48648) +++ includes/filerepo/File.php (working copy) @@ -56,6 +56,35 @@ $this->repo = $repo; } + /** + * Convert a filename into a form required by the local filesystem. + * + * @param $utf8name Original filename (in UTF-8) + * @return Encoded filename + * @private + */ + static function nameToFSCharset( $utf8name ) { + global $wgLocalFilesystemCharsetOverride; + //global $wgLocalFilesystemCharsetFallback; + $s = $wgLocalFilesystemCharsetOverride ? @iconv( 'UTF-8', $wgLocalFilesystemCharsetOverride, $utf8name ) : $utf8name; + //if (!$s) { + // $s = $wgLocalFilesystemCharsetFallback ? iconv( 'UTF-8', $wgLocalFilesystemCharsetFallback, $utf8name ) : $utf8name; + //} + return $s; + } + + /** + * Convert a filename from an encoded form. + * + * @param $fsname Encoded filename + * @return Normal filename (in UTF-8) + * @private + */ + static function nameFromFSCharset( $fsname ) { + global $wgLocalFilesystemCharsetOverride; + return $wgLocalFilesystemCharsetOverride ? iconv( $wgLocalFilesystemCharsetOverride, 'UTF-8', $fsname ) : $fsname; + } + function __get( $name ) { $function = array( $this, 'get' . ucfirst( $name ) ); if ( !is_callable( $function ) ) { @@ -465,7 +494,7 @@ } $extension = $this->getExtension(); list( $thumbExt, $thumbMime ) = $this->handler->getThumbType( $extension, $this->getMimeType() ); - $thumbName = $this->handler->makeParamString( $params ) . '-' . $this->getName(); + $thumbName = $this->handler->makeParamString( $params ) . '-' . self::nameToFSCharset( $this->getName() ); if ( $thumbExt != $extension ) { $thumbName .= ".$thumbExt"; } @@ -725,7 +754,7 @@ * Get the path of the file relative to the public zone root */ function getRel() { - return $this->getHashPath() . $this->getName(); + return $this->getHashPath() . self::nameToFSCharset( $this->getName() ); } /** @@ -780,7 +809,7 @@ function getThumbUrl( $suffix = false ) { $path = $this->repo->getZoneUrl('public') . '/thumb/' . $this->getUrlRel(); if ( $suffix !== false ) { - $path .= '/' . rawurlencode( $suffix ); + $path .= '/' . rawurlencode( self::nameFromFSCharset( $suffix ) ); } return $path; } Index: includes/GlobalFunctions.php =================================================================== --- includes/GlobalFunctions.php (revision 48648) +++ includes/GlobalFunctions.php (working copy) @@ -831,7 +831,11 @@ $host = getenv( 'COMPUTERNAME' ); } else { # This may be a virtual server. - $host = $_SERVER['SERVER_NAME']; + if ( array_key_exists('SERVER_NAME', $_SERVER)) { + $host = $_SERVER['SERVER_NAME']; # This may be a virtual server. + } else if ( array_key_exists('COMPUTERNAME', $_SERVER) ) { + $host = $_SERVER['COMPUTERNAME']; + } } } return $host; @@ -2122,7 +2126,7 @@ } elseif ( php_uname( 's' ) == 'Windows NT' ) { # This is a hack to work around PHP's flawed invocation of cmd.exe # http://news.php.net/php.internals/21796 - $cmd = '"' . $cmd . '"'; + $cmd = 'cmd /C ' . '"' . str_replace( '/', '\\', $cmd) . '"'; } wfDebug( "wfShellExec: $cmd\n" ); Index: includes/ImagePage.php =================================================================== --- includes/ImagePage.php (revision 48648) +++ includes/ImagePage.php (working copy) @@ -657,6 +657,8 @@ $name = Title::makeTitle( $s->page_namespace, $s->page_title ); $link = $sk->makeKnownLinkObj( $name, "" ); $wgOut->addHTML( "
  • {$link}
  • \n" ); + } else { + break; } } $wgOut->addHTML( "\n" ); Index: includes/Import.php =================================================================== --- includes/Import.php (revision 48648) +++ includes/Import.php (working copy) @@ -841,6 +841,12 @@ if( $this->workRevision ) $this->workRevision->setSize( intval( $this->appenddata ) ); break; + // These were added for the classification section. + case "title_class": + case "page_class": + case "page_dis": + case "declass_date": + break; default: $this->debug( "Bad append: {$this->appendfield}" ); } @@ -869,6 +875,10 @@ $this->push( "contributor" ); xml_set_element_handler( $parser, "in_contributor", "out_contributor" ); break; + case "classification": + $this->push( "classification" ); + xml_set_element_handler( $parser, "in_classification", "out_classification"); + break; default: return $this->throwXMLerror( "Element <$name> not allowed in a ." ); } @@ -892,6 +902,33 @@ } } + // This was added to allow importing from Intellipedia + function in_classification( $parser, $name, $attribs ) { + $name = $this->stripXmlNamespace($name); + + switch( $name ) { + case "title_class": + case "page_class": + case "page_dis": + case "declass_date": + $this->appendfield = $name; + xml_set_element_handler( $parser, "in_nothing", "out_append"); + xml_set_character_data_handler( $parser, "char_append"); + break; + default: + return $this->throwXmlError( "Element <$name> not allowed in a "); + } + + } + + function out_classification( $parser, $name) { + $this->pop(); + if( $name != "classification" ) { + return $this->throwXmlError( "Expected , got " ); + } + xml_set_element_handler( $parser, "in_revision", "out_revision"); + } + function in_logitem( $parser, $name, $attribs ) { $name = $this->stripXmlNamespace($name); $this->debug( "in_logitem $name" ); Index: includes/LinkBatch.php =================================================================== --- includes/LinkBatch.php (revision 48648) +++ includes/LinkBatch.php (working copy) @@ -96,10 +96,12 @@ $ids = array(); $remaining = $this->data; while ( $row = $res->fetchObject() ) { + if (isset($row->page_namespace) && isset($row->page_title) && isset($row->page_id) && isset($row->page_len)) { $title = Title::makeTitle( $row->page_namespace, $row->page_title ); $cache->addGoodLinkObj( $row->page_id, $title, $row->page_len, $row->page_is_redirect ); $ids[$title->getPrefixedDBkey()] = $row->page_id; unset( $remaining[$row->page_namespace][$row->page_title] ); + } } // The remaining links in $data are bad links, register them as such Index: includes/Math.php =================================================================== --- includes/Math.php (revision 48648) +++ includes/Math.php (working copy) @@ -1,325 +1,445 @@ parsing - * @file - * @ingroup Parser + * LaTeX Rendering Class + * Copyright (C) 2003 Benjamin Zeiss + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * -------------------------------------------------------------------- + * @author Benjamin Zeiss + * @version v0.8 + * @package latexrender + * */ /** - * Takes LaTeX fragments, sends them to a helper program (texvc) for rendering - * to rasterized PNG and HTML and MathML approximations. An appropriate - * rendering form is picked and returned. - * - * @author Tomasz Wegrzanowski, with additions by Brion Vibber (2003, 2004) - * @ingroup Parser + * Error code: + * 1. Too long formulas + * 2. formula contains tags in the blacklist + * 3. formula incorrect, can't be render + * 4. can't exec tex command + * maybe directory unwritable,can't create temporary files + * 5. formula image too big + * 6. can't copy image file to cahed formula directory + * maybe ImageMagick fail */ -class MathRenderer { - var $mode = MW_MATH_MODERN; - var $tex = ''; - var $inputhash = ''; - var $hash = ''; - var $html = ''; - var $mathml = ''; - var $conservativeness = 0; - function __construct( $tex, $params=array() ) { - $this->tex = $tex; - $this->params = $params; - } - function setOutputMode( $mode ) { - $this->mode = $mode; - } +class LatexRender { - function render() { - global $wgTmpDirectory, $wgInputEncoding; - global $wgTexvc; - $fname = 'MathRenderer::render'; + // ==================================================================================== + // Variable Definitions + // ==================================================================================== + var $_picture_path = ""; + var $_picture_path_httpd = ""; + var $_tmp_dir = ""; + // i was too lazy to write mutator functions for every single program used + // just access it outside the class or change it here if nescessary + var $_latex_path = 'latex.exe'; + var $_dvips_path = 'dvips.exe'; + var $_convert_path = 'convert.exe'; + var $_identify_path = 'identify.exe'; - if( $this->mode == MW_MATH_SOURCE ) { - # No need to render or parse anything more! - return ('$ '.htmlspecialchars( $this->tex ).' $'); - } - if( $this->tex == '' ) { - return; # bug 8372 - } + var $_formula_density = 120; + var $_xsize_limit = 700; + var $_ysize_limit = 700; + var $_string_length_limit = 800; + var $_font_size = 10; + var $_latexclass = "article"; //install extarticle class if you wish to have smaller font sizes + var $_tmp_filename; + var $_image_format = "gif"; //change to png if you prefer + // this most certainly needs to be extended. in the long term it is planned to use + // a positive list for more security. this is hopefully enough for now. i'd be glad + // to receive more bad tags ! + var $_latex_tags_blacklist = array( + "include","def","command","loop","repeat","open","toks","output","input", + "catcode","name","^^", + "\\every","\\errhelp","\\errorstopmode","\\scrollmode","\\nonstopmode","\\batchmode", + "\\read","\\write","csname","\\newhelp","\\uppercase", "\\lowercase","\\relax","\\aftergroup", + "\\afterassignment","\\expandafter","\\noexpand","\\special" + ); + var $_errorcode = 0; + var $_errorextra = ""; - if( !$this->_recall() ) { - # Ensure that the temp and output directories are available before continuing... - if( !file_exists( $wgTmpDirectory ) ) { - if( !wfMkdirParents( $wgTmpDirectory ) ) { - return $this->_error( 'math_bad_tmpdir' ); - } - } elseif( !is_dir( $wgTmpDirectory ) || !is_writable( $wgTmpDirectory ) ) { - return $this->_error( 'math_bad_tmpdir' ); - } - if( function_exists( 'is_executable' ) && !is_executable( $wgTexvc ) ) { - return $this->_error( 'math_notexvc' ); - } - $cmd = $wgTexvc . ' ' . - escapeshellarg( $wgTmpDirectory ).' '. - escapeshellarg( $wgTmpDirectory ).' '. - escapeshellarg( $this->tex ).' '. - escapeshellarg( $wgInputEncoding ); + // ==================================================================================== + // constructor + // ==================================================================================== - if ( wfIsWindows() ) { - # Invoke it within cygwin sh, because texvc expects sh features in its default shell - $cmd = 'sh -c ' . wfEscapeShellArg( $cmd ); - } + /** + * Initializes the class + * + * @param string path where the rendered pictures should be stored + * @param string same path, but from the httpd chroot + */ + function LatexRender($picture_path,$picture_path_httpd,$tmp_dir) { + $this->_picture_path = $picture_path; + $this->_picture_path_httpd = $picture_path_httpd; + $this->_tmp_dir = $tmp_dir; + $this->_tmp_filename = md5(rand()); + } - wfDebug( "TeX: $cmd\n" ); - $contents = `$cmd`; - wfDebug( "TeX output:\n $contents\n---\n" ); + // ==================================================================================== + // public functions + // ==================================================================================== - if (strlen($contents) == 0) { - return $this->_error( 'math_unknown_error' ); - } + /** + * Picture path Mutator function + * + * @param string sets the current picture path to a new location + */ + function setPicturePath($name) { + $this->_picture_path = $name; + } - $retval = substr ($contents, 0, 1); - $errmsg = ''; - if (($retval == 'C') || ($retval == 'M') || ($retval == 'L')) { - if ($retval == 'C') { - $this->conservativeness = 2; - } else if ($retval == 'M') { - $this->conservativeness = 1; - } else { - $this->conservativeness = 0; - } - $outdata = substr ($contents, 33); + /** + * Picture path Mutator function + * + * @returns the current picture path + */ + function getPicturePath() { + return $this->_picture_path; + } - $i = strpos($outdata, "\000"); + /** + * Picture path HTTPD Mutator function + * + * @param string sets the current httpd picture path to a new location + */ + function setPicturePathHTTPD($name) { + $this->_picture_path_httpd = $name; + } - $this->html = substr($outdata, 0, $i); - $this->mathml = substr($outdata, $i+1); - } else if (($retval == 'c') || ($retval == 'm') || ($retval == 'l')) { - $this->html = substr ($contents, 33); - if ($retval == 'c') { - $this->conservativeness = 2; - } else if ($retval == 'm') { - $this->conservativeness = 1; - } else { - $this->conservativeness = 0; - } - $this->mathml = NULL; - } else if ($retval == 'X') { - $this->html = NULL; - $this->mathml = substr ($contents, 33); - $this->conservativeness = 0; - } else if ($retval == '+') { - $this->html = NULL; - $this->mathml = NULL; - $this->conservativeness = 0; - } else { - $errbit = htmlspecialchars( substr($contents, 1) ); - switch( $retval ) { - case 'E': - $errmsg = $this->_error( 'math_lexing_error', $errbit ); - break; - case 'S': - $errmsg = $this->_error( 'math_syntax_error', $errbit ); - break; - case 'F': - $errmsg = $this->_error( 'math_unknown_function', $errbit ); - break; - default: - $errmsg = $this->_error( 'math_unknown_error', $errbit ); - } - } + /** + * Picture path HTTPD Mutator function + * + * @returns the current picture path + */ + function getPicturePathHTTPD() { + return $this->_picture_path_httpd; + } - if ( !$errmsg ) { - $this->hash = substr ($contents, 1, 32); - } + /** + * Tries to match the LaTeX Formula given as argument against the + * formula cache. If the picture has not been rendered before, it'll + * try to render the formula and drop it in the picture cache directory. + * + * @param string formula in LaTeX format + * @returns the webserver based URL to a picture which contains the + * requested LaTeX formula. If anything fails, the resultvalue is false. + */ + function getFormulaURL($latex_formula) { + // circumvent certain security functions of web-software which + // is pretty pointless right here - wfRunHooks( 'MathAfterTexvc', array( &$this, &$errmsg ) ); + $latex_formula = preg_replace("/>/i", ">", $latex_formula); + $latex_formula = preg_replace("/hash)) { - return $this->_error( 'math_unknown_error' ); - } + $filename = 'math-' . $formula_hash.".".$this->_image_format; + $full_path_filename = $this->getPicturePath() . DIRECTORY_SEPARATOR . $filename; - if( !file_exists( "$wgTmpDirectory/{$this->hash}.png" ) ) { - return $this->_error( 'math_image_error' ); - } + if (is_file($full_path_filename)) { + return $this->getPicturePathHTTPD() . '/' . $filename; + } else { + // security filter: reject too long formulas + if (strlen($latex_formula) > $this->_string_length_limit) { + $this->_errorcode = 1; + return false; + } - if( filesize( "$wgTmpDirectory/{$this->hash}.png" ) == 0 ) { - return $this->_error( 'math_image_error' ); - } + // security filter: try to match against LaTeX-Tags Blacklist + for ($i=0; $i < sizeof($this->_latex_tags_blacklist); $i++) { + if (stristr($latex_formula,$this->_latex_tags_blacklist[$i])) { + $this->_errorcode = 2; + return false; + } + } - $hashpath = $this->_getHashPath(); - if( !file_exists( $hashpath ) ) { - if( !@wfMkdirParents( $hashpath, 0755 ) ) { - return $this->_error( 'math_bad_output' ); - } - } elseif( !is_dir( $hashpath ) || !is_writable( $hashpath ) ) { - return $this->_error( 'math_bad_output' ); - } + // security checks assume correct formula, let's render it + if ($this->renderLatex($latex_formula)) { + return $this->getPicturePathHTTPD()."/".$filename; + } else { + $this->_errorcode = 3; + return false; + } + } + } - if( !rename( "$wgTmpDirectory/{$this->hash}.png", "$hashpath/{$this->hash}.png" ) ) { - return $this->_error( 'math_output_error' ); - } + // ==================================================================================== + // private functions + // ==================================================================================== - # Now save it back to the DB: - if ( !wfReadOnly() ) { - $outmd5_sql = pack('H32', $this->hash); + /** + * wraps a minimalistic LaTeX document around the formula and returns a string + * containing the whole document as string. Customize if you want other fonts for + * example. + * + * @param string formula in LaTeX format + * @returns minimalistic LaTeX document containing the given formula + */ + function wrap_formula($latex_formula) { +# $string = "\documentclass[".$this->_font_size."pt]{".$this->_latexclass."}\n"; +# $string .= "\usepackage[latin1]{inputenc}\n"; + $string = "\documentclass{".$this->_latexclass."}\n"; + $string .= "\usepackage{amsmath}\n"; + $string .= "\usepackage{amsfonts}\n"; + $string .= "\usepackage{amssymb}\n"; + $string .= "\pagestyle{empty}\n"; + $string .= "\begin{document}\n"; + $string .= "$".$latex_formula."$\n"; + $string .= "\end{document}\n"; - $md5_sql = pack('H32', $this->md5); # Binary packed, not hex + return $string; + } - $dbw = wfGetDB( DB_MASTER ); - $dbw->replace( 'math', array( 'math_inputhash' ), - array( - 'math_inputhash' => $dbw->encodeBlob($md5_sql), - 'math_outputhash' => $dbw->encodeBlob($outmd5_sql), - 'math_html_conservativeness' => $this->conservativeness, - 'math_html' => $this->html, - 'math_mathml' => $this->mathml, - ), $fname - ); - } - - // If we're replacing an older version of the image, make sure it's current. - global $wgUseSquid; - if ( $wgUseSquid ) { - $urls = array( $this->_mathImageUrl() ); - $u = new SquidUpdate( $urls ); - $u->doUpdate(); - } + /** + * returns the dimensions of a picture file using 'identify' of the + * imagemagick tools. The resulting array can be adressed with either + * $dim[0] / $dim[1] or $dim["x"] / $dim["y"] + * + * @param string path to a picture + * @returns array containing the picture dimensions + */ + function getDimensions($filename) { + $output = array(); + $retValue = 1; + if ( php_uname( 's' ) == 'Windows NT' ) { + if ( strpos($this->_identify_path, ' ')) + $cmd = 'cmd /C ' . '"' . str_replace( '/', '\\', $this->_identify_path) . ' ' . $filename . '"'; + else + $cmd = 'cmd /C ' . str_replace('/', '\\', $this->_identify_path) . ' ' . $filename; + exec($cmd, $output); } + else + { + exec($this->_identify_path . " " . $filename, $output, $retValue); + } + //For some reason this didn't work for me, I used + //$commander = "identify ".$filename; + //$output=exec($commander); + //instead. This should work if Identify works on the commandline + if ($retValue == 1) + { + return array('x' => 0, 'y' => 0); + } + $result = explode(' ', $output[0]); + $dim = explode('x', $result[2]); + $dim['x'] = $dim[0]; + $dim['y'] = $dim[1]; - return $this->_doRender(); - } + return $dim; + } - function _error( $msg, $append = '' ) { - $mf = htmlspecialchars( wfMsg( 'math_failure' ) ); - $errmsg = htmlspecialchars( wfMsg( $msg ) ); - $source = htmlspecialchars( str_replace( "\n", ' ', $this->tex ) ); - return "$mf ($errmsg$append): $source\n"; - } + /** + * Renders a LaTeX formula by the using the following method: + * - write the formula into a wrapped tex-file in a temporary directory + * and change to it + * - Create a DVI file using latex (tetex) + * - Convert DVI file to Postscript (PS) using dvips (tetex) + * - convert, trim and add transparancy by using 'convert' from the + * imagemagick package. + * - Save the resulting image to the picture cache directory using an + * md5 hash as filename. Already rendered formulas can be found directly + * this way. + * + * @param string LaTeX formula + * @returns true if the picture has been successfully saved to the picture + * cache directory + */ + function renderLatex($latex_formula) { + $latex_document = $this->wrap_formula($latex_formula); - function _recall() { - global $wgMathDirectory; - $fname = 'MathRenderer::_recall'; + $current_dir = getcwd(); - $this->md5 = md5( $this->tex ); - $dbr = wfGetDB( DB_SLAVE ); - $rpage = $dbr->selectRow( 'math', - array( 'math_outputhash','math_html_conservativeness','math_html','math_mathml' ), - array( 'math_inputhash' => $dbr->encodeBlob(pack("H32", $this->md5))), # Binary packed, not hex - $fname - ); + chdir($this->_tmp_dir); - if( $rpage !== false ) { - # Tailing 0x20s can get dropped by the database, add it back on if necessary: - $xhash = unpack( 'H32md5', $dbr->decodeBlob($rpage->math_outputhash) . " " ); - $this->hash = $xhash ['md5']; + // create temporary latex file + $fp = fopen($this->_tmp_dir . DIRECTORY_SEPARATOR . $this->_tmp_filename . '.tex', 'w+'); + fputs($fp,$latex_document); + fclose($fp); - $this->conservativeness = $rpage->math_html_conservativeness; - $this->html = $rpage->math_html; - $this->mathml = $rpage->math_mathml; + // create temporary dvi file + // The \"'s are used in case the path has spaces in it (same as below for dvi) + $command = '"' . $this->_latex_path . '" --interaction=nonstopmode ' . $this->_tmp_filename . '.tex'; + //In my case this didn't output in the right directory (amongst other things) + //so I hardcoded everything in (If you use this, adjust it to your directories) + //$command = "\"C:\Program Files\MiKTeX\miktex\bin\latex\" --output-directory=D:\Wiki\www\images\\tmp\\ --interaction=nonstopmode D:\Wiki\www\images\\tmp\\".$this->_tmp_filename.".tex"; - $filename = $this->_getHashPath() . "/{$this->hash}.png"; - if( file_exists( $filename ) ) { - if( filesize( $filename ) == 0 ) { - // Some horrible error corrupted stuff :( - @unlink( $filename ); - } else { - return true; - } - } + if ( php_uname( 's' ) == 'Windows NT' ) { + $command = 'cmd /C ' . str_replace( '/', '\\', $command); + } + $retval = 1; + $output = array(); + $status_code = exec($command, $output, $retval); - if( file_exists( $wgMathDirectory . "/{$this->hash}.png" ) ) { - $hashpath = $this->_getHashPath(); + if (!$status_code) { + $this->cleanTemporaryDirectory(); + chdir($current_dir); + $this->_errorcode = 4; + return false; + } - if( !file_exists( $hashpath ) ) { - if( !@wfMkdirParents( $hashpath, 0755 ) ) { - return false; - } - } elseif( !is_dir( $hashpath ) || !is_writable( $hashpath ) ) { - return false; - } - if ( function_exists( "link" ) ) { - return link ( $wgMathDirectory . "/{$this->hash}.png", - $hashpath . "/{$this->hash}.png" ); - } else { - return rename ( $wgMathDirectory . "/{$this->hash}.png", - $hashpath . "/{$this->hash}.png" ); - } - } - + // convert dvi file to postscript using dvips + $command = '"' . $this->_dvips_path . '" -q -E ' . $this->_tmp_filename . '.dvi' . ' -o ' . $this->_tmp_filename . '.ps'; + if ( php_uname( 's' ) == 'Windows NT' ) { + $command = 'cmd /C ' . str_replace( '/', '\\', $command); } + $retval = 1; + $output = array(); + $status_code = exec($command, $output, $retval); - # Missing from the database and/or the render cache - return false; - } - - /** - * Select among PNG, HTML, or MathML output depending on - */ - function _doRender() { - if( $this->mode == MW_MATH_MATHML && $this->mathml != '' ) { - return Xml::tags( 'math', - $this->_attribs( 'math', - array( 'xmlns' => 'http://www.w3.org/1998/Math/MathML' ) ), - $this->mathml ); - } - if (($this->mode == MW_MATH_PNG) || ($this->html == '') || - (($this->mode == MW_MATH_SIMPLE) && ($this->conservativeness != 2)) || - (($this->mode == MW_MATH_MODERN || $this->mode == MW_MATH_MATHML) && ($this->conservativeness == 0))) { - return $this->_linkToMathImage(); + // imagemagick convert ps to image and trim picture + if (strpos($this->_convert_path, ' ')) { + $command = '"' . $this->_convert_path . '" -density ' . $this->_formula_density. + " -trim -transparent \"#FFFFFF\" ".$this->_tmp_filename.".ps ". + $this->_tmp_filename.".".$this->_image_format; } else { - return Xml::tags( 'span', - $this->_attribs( 'span', - array( 'class' => 'texhtml' ) ), - $this->html ); + $command = $this->_convert_path . ' -density ' . $this->_formula_density. + " -trim -transparent \"#FFFFFF\" ".$this->_tmp_filename.".ps ". + $this->_tmp_filename.".".$this->_image_format; } - } + if ( php_uname( 's' ) == 'Windows NT' ) { + $command = 'cmd /C ' . str_replace( '/', '\\', $command); + } + $retval = 1; + $output = array(); + $status_code = exec($command, $output, $retval); - function _attribs( $tag, $defaults=array(), $overrides=array() ) { - $attribs = Sanitizer::validateTagAttributes( $this->params, $tag ); - $attribs = Sanitizer::mergeAttributes( $defaults, $attribs ); - $attribs = Sanitizer::mergeAttributes( $attribs, $overrides ); - return $attribs; - } + // test picture for correct dimensions + $dim = $this->getDimensions($this->_tmp_filename . '.' . $this->_image_format); - function _linkToMathImage() { - $url = $this->_mathImageUrl(); + if ( ($dim["x"] > $this->_xsize_limit) or ($dim["y"] > $this->_ysize_limit)) { + $this->cleanTemporaryDirectory(); + chdir($current_dir); + $this->_errorcode = 5; + $this->_errorextra = ": " . $dim["x"] . "x" . number_format($dim["y"],0,"",""); + return false; + } - return Xml::element( 'img', - $this->_attribs( - 'img', - array( - 'class' => 'tex', - 'alt' => $this->tex ), - array( - 'src' => $url ) ) ); - } + // copy temporary formula file to cached formula directory + $latex_hash = md5($latex_formula); + $filename = $this->getPicturePath(). DIRECTORY_SEPARATOR . 'math-' . $latex_hash . '.' . $this->_image_format; + if (file_exists($this->_tmp_filename . '.' . $this->_image_format)) + $status_code = copy($this->_tmp_filename . '.' . $this->_image_format,$filename); - function _mathImageUrl() { - global $wgMathPath; - $dir = $this->_getHashSubPath(); - return "$wgMathPath/$dir/{$this->hash}.png"; - } - - function _getHashPath() { - global $wgMathDirectory; - $path = $wgMathDirectory .'/' . $this->_getHashSubPath(); - wfDebug( "TeX: getHashPath, hash is: $this->hash, path is: $path\n" ); - return $path; - } - - function _getHashSubPath() { - return substr($this->hash, 0, 1) - .'/'. substr($this->hash, 1, 1) - .'/'. substr($this->hash, 2, 1); - } + $this->cleanTemporaryDirectory(); - public static function renderMath( $tex, $params=array() ) { - global $wgUser; - $math = new MathRenderer( $tex, $params ); - $math->setOutputMode( $wgUser->getOption('math')); - return $math->render(); - } + if (!$status_code) { + chdir($current_dir); + $this->_errorcode = 6; + return false; + } + chdir($current_dir); + + return true; + } + + /** + * Cleans the temporary directory + */ + function cleanTemporaryDirectory() { + + $current_dir = getcwd(); + chdir($this->_tmp_dir); + @unlink($this->_tmp_dir . $DIRECTORY_SEPARATOR . $this->_tmp_filename.".tex"); + @unlink($this->_tmp_dir . $DIRECTORY_SEPARATOR . $this->_tmp_filename.".aux"); + @unlink($this->_tmp_dir . $DIRECTORY_SEPARATOR . $this->_tmp_filename.".log"); + @unlink($this->_tmp_dir . $DIRECTORY_SEPARATOR . $this->_tmp_filename.".dvi"); + @unlink($this->_tmp_dir . $DIRECTORY_SEPARATOR . $this->_tmp_filename.".ps"); + @unlink($this->_tmp_dir . $DIRECTORY_SEPARATOR . $this->_tmp_filename.".".$this->_image_format); + + chdir($current_dir); + } + } + + + +/** + * LaTeX Rendering Class - Calling function + * Copyright (C) 2003 Benjamin Zeiss + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * -------------------------------------------------------------------- + * @author Benjamin Zeiss + * @version v0.8 + * @package latexrender + * Revised by Steve Mayer + * This file can be included in many PHP programs by using something like (see example.php to see how it can be used) + * include_once('/full_path_here_to/latexrender/latex.php'); + * $text_to_be_converted=latex_content($text_to_be_converted); + * $text_to_be_converted will then contain the link to the appropriate image + * or an error code as follows (the 500 values can be altered in class.latexrender.php): + * 0 OK + * 1 Formula longer than 500 characters + * 2 Includes a blacklisted tag + * 3 (Not used) Latex rendering failed + * 4 Cannot create DVI file + * 5 Picture larger than 500 x 500 followed by x x y dimensions + * 6 Cannot copy image to pictures directory + */ +class MathRenderer { + function renderMath($latex_formula) { + + global $wgMathDirectory, $wgMathPath, $wgTmpDirectory, + $wgLaTexCommand, + $wgDvipsCommand, + $wgImageMagickConvertCommand, + $wgImageMagickIdentifyCommand; + + // $latex_formula = '\displaystyle ' . $latex_formula; + $latex = new LatexRender ($wgMathDirectory, $wgMathPath, $wgTmpDirectory); + + #check Math dir + if(!file_exists($wgMathDirectory)) @mkdir($wgMathDirectory); + if(!file_exists($wgTmpDirectory)) @mkdir($wgTmpDirectory); + + + $latex->_latex_path = $wgLaTexCommand; + $latex->_dvips_path = $wgDvipsCommand; + $latex->_convert_path = $wgImageMagickConvertCommand; + $latex->_identify_path = $wgImageMagickIdentifyCommand; + + $url = $latex->getFormulaURL($latex_formula); + + $alt_latex_formula = htmlentities($latex_formula, ENT_QUOTES); + $alt_latex_formula = str_replace("\r"," +",$alt_latex_formula); + $alt_latex_formula = str_replace("\n"," +",$alt_latex_formula); + $alt_latex_formula = str_replace('\displaystyle ','',$alt_latex_formula); + + if ($url != false) + $text = "$alt_latex_formula"; + else + $text = "[Unparseable or potentially dangerous latex formula. Error $latex->_errorcode $latex->_errorextra]"; + + return $text; +} +} Index: includes/Metadata.php =================================================================== --- includes/Metadata.php (revision 48648) +++ includes/Metadata.php (working copy) @@ -315,4 +315,4 @@ protected function epilogue() { echo "\n"; } -} \ No newline at end of file +} Index: includes/OutputPage.php =================================================================== --- includes/OutputPage.php (revision 48648) +++ includes/OutputPage.php (working copy) @@ -398,12 +398,21 @@ array_fill( 0, count( $categories ), 'normal' ) ); # Mark hidden categories - foreach ( $res as $row ) { - if ( isset( $row->pp_value ) ) { - $categories[$row->page_title] = 'hidden'; + try { + foreach ( $res as $row ) { + if (is_array($row)) { + if (isset( $row['pp_value'] )) { + $categories[$row['page_title']] = 'hidden'; + } + } else { + if ( isset( $row->pp_value ) ) { + $categories[$row->page_title] = 'hidden'; + } + } } + } catch (Exception $ex) { + wfDebug($ex->getMessage()); } - # Add the remaining categories to the skin if ( wfRunHooks( 'OutputPageMakeCategoryLinks', array( &$this, $categories, &$this->mCategoryLinks ) ) ) { $sk = $wgUser->getSkin(); @@ -891,6 +900,8 @@ $sk = $wgUser->getSkin(); + $this->addMeta( 'http:Page-Enter', 'progid:DXImageTransform.Microsoft.Fade(duration=.5)' ); + $this->addMeta( 'http:Page-Exit', 'progid:DXImageTransform.Microsoft.Fade(duration=.5)' ); if ( $wgUseAjax ) { $this->addScriptFile( 'ajax.js' ); Index: includes/Revision.php =================================================================== --- includes/Revision.php (revision 48648) +++ includes/Revision.php (working copy) @@ -795,7 +795,7 @@ $old_id = $dbw->nextSequenceValue( 'text_old_id_val' ); $dbw->insert( 'text', array( - 'old_id' => $old_id, + //'old_id' => $old_id, 'old_text' => $data, 'old_flags' => $flags, ), __METHOD__ Index: includes/specials/SpecialAncientpages.php =================================================================== --- includes/specials/SpecialAncientpages.php (revision 48648) +++ includes/specials/SpecialAncientpages.php (working copy) @@ -25,8 +25,13 @@ $db = wfGetDB( DB_SLAVE ); $page = $db->tableName( 'page' ); $revision = $db->tableName( 'revision' ); - $epoch = $wgDBtype == 'mysql' ? 'UNIX_TIMESTAMP(rev_timestamp)' : - 'EXTRACT(epoch FROM rev_timestamp)'; + if ( $wgDBtype == 'mysql' ) { + $epoch = 'UNIX_TIMESTAMP(rev_timestamp)'; + } else if ( $wgDBtype == 'adodb' ) { + $epoch = 'rev_timestamp'; + } else { + $epoch = 'EXTRACT(epoch FROM rev_timestamp)'; + } return "SELECT 'Ancientpages' as type, page_namespace as namespace, Index: includes/specials/SpecialListfiles.php =================================================================== --- includes/specials/SpecialListfiles.php (revision 48648) +++ includes/specials/SpecialListfiles.php (working copy) @@ -77,7 +77,7 @@ # Depends on $wgMiserMode if( isset($this->mFieldNames['COUNT(oi_archive_name)']) ) { $tables[] = 'oldimage'; - $options = array('GROUP BY' => 'img_name'); + $options = array('GROUP BY' => 'img_timestamp,img_name,img_user_text,img_size,img_description,img_user'); $join_conds = array('oldimage' => array('LEFT JOIN','oi_name = img_name') ); } return array( Index: includes/specials/SpecialNewpages.php =================================================================== --- includes/specials/SpecialNewpages.php (revision 48648) +++ includes/specials/SpecialNewpages.php (working copy) @@ -70,8 +70,6 @@ // PG offsets not just digits! if ( preg_match( '/^offset=([^=]+)$/', $bit, $m ) ) $this->opts->setValue( 'offset', intval($m[1]) ); - if ( preg_match( '/^username=(.*)$/', $bit, $m ) ) - $this->opts->setValue( 'username', $m[1] ); if ( preg_match( '/^namespace=(.*)$/', $bit, $m ) ) { $ns = $wgLang->getNsIndex( $m[1] ); if( $ns !== false ) { Index: includes/specials/SpecialRecentchangeslinked.php =================================================================== --- includes/specials/SpecialRecentchangeslinked.php (revision 48648) +++ includes/specials/SpecialRecentchangeslinked.php (working copy) @@ -134,7 +134,7 @@ } $subsql[] = $dbr->selectSQLText( array_merge( $tables, array( $link_table ) ), $select, $conds + $subconds, - __METHOD__, array( 'ORDER BY' => 'rc_timestamp DESC', 'LIMIT' => $limit ), + __METHOD__, array(), //array( 'ORDER BY' => 'rc_timestamp DESC', 'LIMIT' => $limit ), $join_conds + array( $link_table => array( 'INNER JOIN', $subjoin ) ) ); } @@ -144,7 +144,7 @@ $sql = $subsql[0]; else { // need to resort and relimit after union - $sql = "(" . implode( ") UNION (", $subsql ) . ") ORDER BY rc_timestamp DESC LIMIT {$limit}"; + $sql = implode( "UNION ", $subsql ) . " ORDER BY rc_timestamp DESC LIMIT {$limit}"; } $res = $dbr->query( $sql, __METHOD__ ); Index: includes/specials/SpecialShortpages.php =================================================================== --- includes/specials/SpecialShortpages.php (revision 48648) +++ includes/specials/SpecialShortpages.php (working copy) @@ -50,16 +50,16 @@ } function preprocessResults( $db, $res ) { - # There's no point doing a batch check if we aren't caching results; - # the page must exist for it to have been pulled out of the table - if( $this->isCached() ) { - $batch = new LinkBatch(); - while( $row = $db->fetchObject( $res ) ) - $batch->add( $row->namespace, $row->title ); - $batch->execute(); - if( $db->numRows( $res ) > 0 ) - $db->dataSeek( $res, 0 ); - } +// # There's no point doing a batch check if we aren't caching results; +// # the page must exist for it to have been pulled out of the table +// if( $this->isCached() ) { +// $batch = new LinkBatch(); +// while( $row = $db->fetchObject( $res ) ) +// $batch->add( $row->namespace, $row->title ); +// $batch->execute(); +// if( $db->numRows( $res ) > 0 ) +// $db->dataSeek( $res, 0 ); +// } } function sortDescending() { Index: includes/specials/SpecialStatistics.php =================================================================== --- includes/specials/SpecialStatistics.php (revision 48648) +++ includes/specials/SpecialStatistics.php (working copy) @@ -267,4 +267,4 @@ ";images=" . $this->images . ";jobs=" . $this->numJobs . "\n"; return; } -} \ No newline at end of file +} Index: includes/specials/SpecialUpload.php =================================================================== --- includes/specials/SpecialUpload.php (revision 48648) +++ includes/specials/SpecialUpload.php (working copy) @@ -1047,12 +1047,12 @@ } $val2 = $wgAllowCopyUploads ? min( $wgMaxUploadSize, $val2 ) : $val2; $maxUploadSize = '
    ' . - wfMsgExt( 'upload-maxfilesize', array( 'parseinline', 'escapenoentities' ), + wfMsgExt( 'upload-maxfilesize', array( 'parseinline' ), $wgLang->formatSize( $val2 ) ) . "
    \n"; - $sourcefilename = wfMsgExt( 'sourcefilename', array( 'parseinline', 'escapenoentities' ) ); - $destfilename = wfMsgExt( 'destfilename', array( 'parseinline', 'escapenoentities' ) ); + $sourcefilename = wfMsgExt( 'sourcefilename', 'parseinline' ); + $destfilename = wfMsgExt( 'destfilename', 'parseinline' ); $summary = wfMsgExt( 'fileuploadsummary', 'parseinline' ); Index: includes/specials/SpecialVersion.php =================================================================== --- includes/specials/SpecialVersion.php (revision 48648) +++ includes/specials/SpecialVersion.php (working copy) @@ -52,8 +52,7 @@ This wiki is powered by '''[http://www.mediawiki.org/ MediaWiki]''', copyright (C) 2001-2008 Magnus Manske, Brion Vibber, Lee Daniel Crocker, Tim Starling, Erik Möller, Gabriel Wicke, Ævar Arnfjörð Bjarmason, - Niklas Laxström, Domas Mituzas, Rob Church, Yuri Astrakhan, Aryeh Gregor, - Aaron Schulz and others. + Niklas Laxström, Domas Mituzas, Rob Church, DJ Bauch and others. MediaWiki is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by Index: includes/specials/SpecialWantedcategories.php =================================================================== --- includes/specials/SpecialWantedcategories.php (revision 48648) +++ includes/specials/SpecialWantedcategories.php (working copy) @@ -51,15 +51,15 @@ * Fetch user page links and cache their existence */ function preprocessResults( $db, $res ) { - $batch = new LinkBatch; - while ( $row = $db->fetchObject( $res ) ) - $batch->add( $row->namespace, $row->title ); - $batch->execute(); - - // Back to start for display - if ( $db->numRows( $res ) > 0 ) - // If there are no rows we get an error seeking. - $db->dataSeek( $res, 0 ); +// $batch = new LinkBatch; +// while ( $row = $db->fetchObject( $res ) ) +// $batch->add( $row->namespace, $row->title ); +// $batch->execute(); +// +// // Back to start for display +// if ( $db->numRows( $res ) > 0 ) +// // If there are no rows we get an error seeking. +// $db->dataSeek( $res, 0 ); } function formatResult( $skin, $result ) { Index: includes/specials/SpecialWantedpages.php =================================================================== --- includes/specials/SpecialWantedpages.php (revision 48648) +++ includes/specials/SpecialWantedpages.php (working copy) @@ -52,15 +52,15 @@ * Cache page existence for performance */ function preprocessResults( $db, $res ) { - $batch = new LinkBatch; - while ( $row = $db->fetchObject( $res ) ) - $batch->add( $row->namespace, $row->title ); - $batch->execute(); - - // Back to start for display - if ( $db->numRows( $res ) > 0 ) - // If there are no rows we get an error seeking. - $db->dataSeek( $res, 0 ); +// $batch = new LinkBatch; +// while ( $row = $db->fetchObject( $res ) ) +// $batch->add( $row->namespace, $row->title ); +// $batch->execute(); +// +// // Back to start for display +// if ( $db->numRows( $res ) > 0 ) +// // If there are no rows we get an error seeking. +// $db->dataSeek( $res, 0 ); } /** Index: includes/specials/SpecialWantedtemplates.php =================================================================== --- includes/specials/SpecialWantedtemplates.php (revision 48648) +++ includes/specials/SpecialWantedtemplates.php (working copy) @@ -35,14 +35,14 @@ $name = $dbr->addQuotes( $this->getName() ); return " - SELECT $name as type, + SELECT $name as type, tl_namespace as namespace, tl_title as title, COUNT(*) as value FROM $templatelinks LEFT JOIN $page ON tl_title = page_title AND tl_namespace = page_namespace WHERE page_title IS NULL AND tl_namespace = ". NS_TEMPLATE ." - GROUP BY tl_title + GROUP BY tl_namespace,tl_title "; } Index: includes/XmlTypeCheck.php =================================================================== --- includes/XmlTypeCheck.php (revision 48648) +++ includes/XmlTypeCheck.php (working copy) @@ -49,7 +49,7 @@ $file = fopen( $fname, "rb" ); do { - $chunk = fread( $file, 32768 ); + $chunk = fread( $file, 3276800 ); $ret = xml_parse( $parser, $chunk, feof( $file ) ); if( $ret == 0 ) { // XML isn't well-formed! Index: maintenance/updateArticleCount.inc.php =================================================================== --- maintenance/updateArticleCount.inc.php (revision 48648) +++ maintenance/updateArticleCount.inc.php (working copy) @@ -38,7 +38,7 @@ function makeSql() { list( $page, $pagelinks ) = $this->dbr->tableNamesN( 'page', 'pagelinks' ); $nsset = $this->makeNsSet(); - return "SELECT COUNT(DISTINCT page_namespace, page_title) AS pagecount " . + return "SELECT COUNT(DISTINCT CAST(page_namespace AS VARCHAR(5)) + page_title) AS pagecount " . "FROM $page, $pagelinks " . "WHERE pl_from=page_id and page_namespace IN ( $nsset ) " . "AND page_is_redirect = 0 AND page_len > 0";