Page MenuHomePhabricator

SpecialExport.diff

Authored By
bzimport
Nov 21 2014, 8:45 PM
Size
17 KB
Referenced Files
None
Subscribers
None

SpecialExport.diff

--- mediawiki-1.5beta4/includes/SpecialExport.php 2005-07-13 03:59:12.000000000 +0200
+++ mwMM/applic/includes/SpecialExport.php 2005-08-20 17:45:52.867577320 +0200
@@ -1,4 +1,18 @@
<?php
+/*
+* ==== comments to be removed when patch is accepted :
+* this patch also assumes small patches in :
+* - Defines.php
+* - DefaultSettings.php
+** $wgSpecialExportDownload = MW_EXPORT_DISPO_SUGGESTED ;
+** $wgSpecialExportFilename = MW_EXPORT_FILENAME_DEFAULT ;
+** $wgSpecialExportPrefix = MW_EXPORT_DEFAULT_PREFIX ;
+* - Language.php (+ LanguageFr.php, De, etc)
+** exportpromptdisposition
+** exportpromptfilename
+** exportsubmit
+*/
+
# Copyright (C) 2003 Brion Vibber <brion@pobox.com>
# http://www.mediawiki.org/
#
@@ -22,64 +36,349 @@
* @subpackage SpecialPage
*/
+# This is not a valid entry point, perform no further processing unless MEDIAWIKI is defined
+if( !defined( 'MEDIAWIKI' ) ) {
+ die( "This file is part of MediaWiki and is not a valid entry point\n" );
+}
+
/** */
require_once( 'Revision.php' );
+/*
+* ==== comment to be removed after patch acceptance ====
+* why not just boolean's for the related parameters ?
+* do we expect other values ?
+*/
+define( 'MW_EXPORT_FULL', 0 );
+define( 'MW_EXPORT_CURRENT', 1 );
+
+define( 'MW_EXPORT_BUFFER', 0 );
+define( 'MW_EXPORT_STREAM', 1 );
+
+/*
+* ==== comment to be removed after patch acceptance ===
+* wfSpecialExport does 4 things :
+* 1 - process the request and/or the config parameters
+* 2 - send HTTP header(s)
+* 3 - send the XML output
+* 4 - build the form
+* Because this patch increases a little bit tasks 1, 2 and 4,
+* it seems more convenient to leave task 1 here,
+* but to move tasks 2, 3 and 4 in separate functions.
+* In order to avoid wfXxx name space pollution, these 3 functions
+* are created as static function of class WikiExporter
+* doHeaders() , doExport() , doForm
+*/
+
/**
- *
+ * Entry point
+ * @param $page string
*/
function wfSpecialExport( $page = '' ) {
- global $wgOut, $wgLang, $wgRequest;
+ global $wgRequest;
+
+ // config parameters :
+
+ $wgSpecialExportFilename = is_integer($wgSpecialExportFilename) ?
+ $wgSpecialExportFilename : MW_EXPORT_FILENAME_DEFAULT ;
+ $wgSpecialExportDownload = is_integer($wgSpecialExportDownload) ?
+ $wgSpecialExportDownload : MW_EXPORT_DISPO_DEFAULT ;
+ $wgSpecialExportPrefix = is_string($wgSpecialExportPrefix) ?
+ $wgSpecialExportPrefix : MW_EXPORT_DEFAULT_PREFIX ;
+
+ // proceed/prepare request :
if( $wgRequest->getVal( 'action' ) == 'submit') {
$page = $wgRequest->getText( 'pages' );
$curonly = $wgRequest->getCheck( 'curonly' );
+ $szRequesXmlFileName = $wgRequest->getText( 'szXmlFileName' );
+ $zRequestDispo = $wgRequest->getCheck( 'zDispo' );
} else {
# Pre-check the 'current version only' box in the UI
$curonly = true;
}
if( $page != '' ) {
+
+ // output HTTP header(s) :
+
+ WikiExporter::doHeaders(
+ // $zXmlDisposition = true // shall we use Content-Disposition ?
+ (( $wgSpecialExportDownload == MW_EXPORT_DISPO_ALLWAYS) || $zRequestDispo )
+ // , $szSuggestedPrefix = MW_EXPORT_DEFAULT_PREFIX
+ , $wgSpecialExportPrefix
+ // , $zDate = true
+ , (($wgSpecialExportFilename == MW_EXPORT_FILENAME_ASK_ELSE_TIMESTAMP)
+ || ($wgSpecialExportFilename == MW_EXPORT_FILENAME_TIMESTAMP))
+ , $szXmlFileName
+ // , $zRelyOnFileName = false
+ // , $uMaxLength = 250 // RARELY USED !
+ // , $zGerman = true // RARELY USED !
+ ) ;
+
+ // output XML :
+
+ WikiExporter::doExport(
+ $page
+ // , $history = MW_EXPORT_CURRENT
+ , ( $curonly ? MW_EXPORT_CURRENT : MW_EXPORT_FULL )
+ // , $buffer = MW_EXPORT_BUFFER
+ ) ;
+
+ } else {
+
+ // prepare the form :
+
+ WikiExporter::doForm(
+ // $zCurOnly = true // preset value of the 'current v. all' checkbox
+ $curonly
+ // , $zDisposition = true // preset value for the 'download' checkbox
+ , (($wgSpecialExportDownload == MW_EXPORT_DISPO_SUGGESTED) || $zRequestDispo)
+ // , $szXmlDispositionFileName = '' // preset value for the file name
+ , $szXmlFileName
+ // , $zAskFilename = true // shall we prompt the user for a filename?
+ , (($wgSpecialExportFilename == MW_EXPORT_FILENAME_ASK_ELSE_TIMESTAMP)
+ || ($wgSpecialExportFilename == MW_EXPORT_FILENAME_ASK_ELSE_RANDOM))
+ // , $zAskDisposition = true // shall we prompt the user for download?
+ , (($wgSpecialExportDownload == MW_EXPORT_DISPO_PERHAPS)
+ || ($wgSpecialExportDownload == MW_EXPORT_DISPO_SUGGESTED))
+ // , $szSuggestedPrefix = MW_EXPORT_DEFAULT_PREFIX
+ , $wgSpecialExportPrefix
+ // , $zDate = true
+ , (($wgSpecialExportFilename == MW_EXPORT_FILENAME_ASK_ELSE_TIMESTAMP)
+ || ($wgSpecialExportFilename == MW_EXPORT_FILENAME_TIMESTAMP))
+ // , $zRelyOnFileName = false
+ // , $uMaxLength = 250 // RARELY USED !
+ // , $zGerman = true // RARELY USED !
+ ) ;
+ }
+}
+
+/**
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+class WikiExporter {
+ /**#@+
+ * @access public
+ * @static
+ */
+
+ /**
+ * @param boolean $zXmlDisposition : shall we use Content-Disposition ?
+ * @param string $szSuggestedPrefix
+ * @param boolean $zDate : use a timestamp (otherwise use a random value)
+ * @param string $szXmlDispositionFileName
+ * @param boolean $zRelyOnFileName (turn on if you are sure file name is ok, probably beacause it was generated automatically)
+ * @param unsigned $uMaxLength (RARE) Maximum filename length. Default is 250 characters.
+ * @param boolean $zGerman (RARE) proceed also german characters
+ */
+ function doHeaders(
+ $zXmlDisposition = true // shall we use Content-Disposition ?
+ , $szSuggestedPrefix = MW_EXPORT_DEFAULT_PREFIX
+ , $zDate = true
+ , $szXmlDispositionFileName = ''
+ , $zRelyOnFileName = false
+ , $uMaxLength = 250 // RARELY USED !
+ , $zGerman = true // RARELY USED !
+ )
+ {
+ global $wgOut ;
$wgOut->disable();
header( "Content-type: application/xml; charset=utf-8" );
- $pages = explode( "\n", $page );
+ if($zXmlDisposition)
+ {
+ if( ! $zRelyOnFileName )
+ {
+ $szXmlDispositionFileName = wfUnixFileName(
+ $szXmlDispositionFileName,$uMaxLength,$zGerman) ;
+ }
+ if(! $szXmlDispositionFileName)
+ {
+ $szXmlDispositionFileName = wfSuggestFileName(
+ $szSuggestedPrefix,$zDate,$uMaxLength) ;
+ }
+ header("Content-Disposition: attachment; filename=\"{$szXmlDispositionFileName}\"'");
+ }
+ }
+ /**
+ * factorize and run...
+ *
+ * @param string $page
+ * @param unsigned $history one of MW_EXPORT_FULL or MW_EXPORT_CURRENT
+ * @param unsigned $buffer one of MW_EXPORT_BUFFER or MW_EXPORT_STREAM
+ */
+ function doExport(
+ $page
+ /*
+ * ==== comment to be removed after patch acceptance ====
+ * why not just boolean's for these 2 parameters ?
+ */
+ , $history = MW_EXPORT_CURRENT
+ , $buffer = MW_EXPORT_BUFFER
+ )
+ {
+ $pages = explode( "\n", $page );
$db =& wfGetDB( DB_SLAVE );
- $history = $curonly ? MW_EXPORT_CURRENT : MW_EXPORT_FULL;
- $exporter = new WikiExporter( $db, $history );
+ $exporter = new WikiExporter(
+ $db
+ , $history = MW_EXPORT_CURRENT
+ , $buffer = MW_EXPORT_BUFFER
+ );
+ /*
+ * ==== comment to be removed after patch acceptance ====
+ * Mind that openStream() and closeStream() are, in fact, static functions
+ */
$exporter->openStream();
+ // WikiExporter::openStream(); //...
$exporter->pagesByName( $pages );
$exporter->closeStream();
- return;
+ // WikiExporter::closeStream(); //...
}
+ /**
+ * write down the Export form on $wgOut
+ *
+ * @param boolean $curonly ($zCurOnly) preset value of the 'current v. all' checkbox
+ * @param boolean $zDisposition preset value for the 'download' checkbox
+ * @param string $szXmlDispositionFileName preset value for the file name
+ * @param boolean $zAskFilename shall we prompt the user for a filename?
+ * @param boolean $zAskDisposition shall we prompt the user for download?
+ * @param boolean $zDate use time stamp if we need to generate a file name
+ * @param boolean $zRelyOnFileName (turn on if you are sure file name is ok, probably beacause it was generated automatically)
+ * @param unsigned $uMaxLength (rarely used)
+ * @param boolean $zGerman (rarely used)
+ */
+ function doForm(
+ $zCurOnly = true // preset value of the 'current v. all' checkbox
+ , $zDisposition = true // preset value for the 'download' checkbox
+ , $szXmlDispositionFileName = '' // preset value for the file name
+ , $zAskFilename = true // shall we prompt the user for a filename?
+ , $zAskDisposition = true // shall we prompt the user for download?
+ , $szSuggestedPrefix = MW_EXPORT_DEFAULT_PREFIX
+ , $zDate = true
+ , $zRelyOnFileName = false
+ , $uMaxLength = 250 // RARELY USED !
+ , $zGerman = true // RARELY USED !
+ )
+ {
+ global $wgOut ;
+
$wgOut->addWikiText( wfMsg( "exporttext" ) );
$titleObj = Title::makeTitle( NS_SPECIAL, "Export" );
$action = $titleObj->escapeLocalURL( 'action=submit' );
+ /*
+ * === comment to be removed after patch acceptance :
+ * there was a minor bug here : $curonly was ignored
+ */
+ $szCurOnlyChecked = $zCurOnly ? " checked='checked' " : '' ;
+ $szPromptCurOnly = wfMsg( "exportcuronly" ) ;
$wgOut->addHTML( "
<form method='post' action=\"$action\">
<input type='hidden' name='action' value='submit' />
<textarea name='pages' cols='40' rows='10'></textarea><br />
-<label><input type='checkbox' name='curonly' value='true' checked='checked' />
-" . wfMsg( "exportcuronly" ) . "</label><br />
-<input type='submit' />
-</form>
+<label><input type='checkbox' name='curonly' value='true' {$szCurOnlyChecked} />
+{$szPromptCurOnly}</label><br />
+" ) ;
+
+ if($zAskDisposition)
+ {
+ /*
+ * === comment to be removed after patch acceptance :
+ * === Mind that 'exportpromptdisposition' is a NEW message.
+ */
+ $szPromptDisposition = wfMsg('exportpromptdisposition') ;
+ $szDispositionChecked = $zDisposition ? " checked='checked' " : '' ;
+ $wgOut->addHTML( "
+<label><input type='checkbox' name='zDispo' value='true' {$szDispositionChecked} />
+{$szPromptDisposition}</label><br />
" );
-}
+ }
-define( 'MW_EXPORT_FULL', 0 );
-define( 'MW_EXPORT_CURRENT', 1 );
+ if($zAskFilename)
+ {
+ /*
+ * === comment to be removed after patch acceptance :
+ * === Mind that 'exportpromptfilename' is a NEW message.
+ */
+ $szPromptFilename = wfMsg('exportpromptfilename') ;
+ if( ! $zRelyOnFileName )
+ {
+ /*
+ $szXmlDispositionFileName may perfectly be empty.
+ However, if it is provided, then it MUST be ok!
+ It is probably already builded automatically and correct.
+ Anyway, we still make an ultimate checking.
+ */
+ $szXmlDispositionFileName = trim($szXmlDispositionFileName) ;
+ if($szXmlDispositionFileName)
+ {
+ $szXmlDispositionFileName = wfUnixFileName($szXmlDispositionFileName,$uMaxLength,$zGerman) ;
+ }
+ }
+ if(! $szXmlDispositionFileName)
+ {
+ $szXmlDispositionFileName = wfSuggestFileName($szSuggestedPrefix,$zDate,$uMaxLength) ;
+ }
+ $wgOut->addHTML( "
+<label>{$szPromptFilename}</label>
+<input type='text' name='szXmlFileName' value='{$szXmlDispositionFileName}' size='40' />
+<br />
+" );
+ }
-define( 'MW_EXPORT_BUFFER', 0 );
-define( 'MW_EXPORT_STREAM', 1 );
+ /*
+ * === comment to be removed after patch acceptance :
+ * === Mind that 'exportsubmit' is a NEW message.
+ * The reason is that, at least in french, standard words often used on submit buttons
+ * such as 'submit', 'send', 'apply', 'transmit' are very ambiguous.
+ * 'Send' is generally translated by 'Envoyer'.
+ * But what means 'envoyer'? From where/who? To where/who?
+ * Why not 'receive' or 'recevoir' ? etc
+ * An *explicit* word such as 'Export', 'Import', 'Download', 'Upload'
+ * must absolutely be used (at least in some languages)...
+ */
+ $szSubmit = wfMsg('exportsubmit') ;
+ $wgOut->addHTML( "
+<input type='submit' value='{$szSubmit}' />
+</form>
+" );
+ /*
+ * ==== comments to be removed when patch is accepted :
+ * Mind the 3 new messages (see Language.php)
+ * - exportpromptdisposition
+ * - exportpromptfilename
+ * - exportsubmit
+ */
+ }
-/**
- * @package MediaWiki
- * @subpackage SpecialPage
+ /**#@-*/
+
+ /**#@+
+ * @access private
+ */
+ /**
+ * @var function
*/
-class WikiExporter {
var $pageCallback = null;
+ /**
+ * @var function
+ */
var $revCallback = null;
+ /**
+ * @var unsigned mode
+ */
+ var $history ;
+ /**
+ * @var unsigned mode
+ */
+ var $buffer ;
+ /**
+ * @var Database
+ */
+ var $db ;
+ /**#@-*/
/**
* If using MW_EXPORT_STREAM to stream a large amount of data,
@@ -89,11 +388,14 @@
* main query is still running.
*
* @param Database $db
- * @param int $history one of MW_EXPORT_FULL or MW_EXPORT_CURRENT
- * @param int $buffer one of MW_EXPORT_BUFFER or MW_EXPORT_STREAM
+ * @param unsigned $history one of MW_EXPORT_FULL or MW_EXPORT_CURRENT
+ * @param unsigned $buffer one of MW_EXPORT_BUFFER or MW_EXPORT_STREAM
*/
- function WikiExporter( &$db, $history = MW_EXPORT_CURRENT,
- $buffer = MW_EXPORT_BUFFER ) {
+ function WikiExporter(
+ &$db
+ , $history = MW_EXPORT_CURRENT
+ , $buffer = MW_EXPORT_BUFFER
+ ) {
$this->db =& $db;
$this->history = $history;
$this->buffer = $buffer;
@@ -251,6 +553,10 @@
// -------------------- private implementation below --------------------
+ /**#@+
+ * @access private
+ */
+
function dumpFrom( $cond = '' ) {
$fname = 'WikiExporter::dumpFrom';
wfProfileIn( $fname );
@@ -308,7 +614,6 @@
* blob storage types will make queries to pull source data.
*
* @param ResultWrapper $resultset
- * @access private
*/
function outputStream( $resultset ) {
$last = null;
@@ -335,7 +640,6 @@
* from the given database row.
*
* @param object $row
- * @access private
*/
function openPage( $row ) {
print "<page>\n";
@@ -354,7 +658,6 @@
* and passed the last database row used for this page.
*
* @param object $row
- * @access private
*/
function closePage( $row ) {
print "</page>\n";
@@ -368,7 +671,6 @@
* data filled in from the given database row.
*
* @param object $row
- * @access private
*/
function dumpRev( $row ) {
$fname = 'WikiExporter::dumpRev';
@@ -409,14 +711,111 @@
}
}
+ /**#@-*/
}
+/**
+* @param string $ts
+* @return string
+*/
function wfTimestamp2ISO8601( $ts ) {
#2003-08-05T18:30:02Z
return preg_replace( '/^(....)(..)(..)(..)(..)(..)$/', '$1-$2-$3T$4:$5:$6Z', $ts );
}
-function xmlsafe( $string ) {
+/*
+* ==== comment to be removed after patch acceptance ====
+* The next 3 global functions are, in my personal implementation,
+* located, for reusability, in includes/GlobalFunctions.php rather than here
+* because they can be usefull eveywhere there is a need to build a filename.
+* Mind that we voluntary divide into 3 functions as to improve reability.
+* I suggest to move these 3 functions into GlobalFunctions.php
+*/
+
+/**
+* Generates a unique file name e.g. for a downloaded file
+*
+* @param string $szSuggestedPrefix
+* @param boolean $zDate : use a timestamp (otherwise use a random value)
+* @param unsigned $uMaxLength Maximum filename length. Default is 250 characters.
+* @return string generated file name
+*/
+function wfSuggestFileName(
+$szPrefix = MW_EXPORT_DEFAULT_PREFIX
+, $zDate = true
+, $uMaxLength = 250
+)
+{
+ $szName = $szPrefix . '-' . ( $zDate ? date("Y-m-d-H-i-s") : mt_rand(1234567,9876543) ) ;
+ // still verify : illegal prefix ? length ?
+ return wfUnixFileName($szName,$uMaxLength) ;
+}
+
+/**
+* Generates an usefull Unix filename besides the original one.
+*
+* @param string $szName The filename to be processed.
+* @param unsigned $uMaxLength Maximum filename length. Default is 250 characters.
+* @param boolean $zGerman proceed also german characters
+* @return string
+*/
+function wfUnixFileName(
+$szName
+, $uMaxLength = 250
+, $zGerman= true
+)
+{
+ $uMaxLength = max(1,min(250,$uMaxLength)) ;
+ // remove accents :
+ $szName = wfRemoveAccents($szName,$zGerman) ;
+ // Replace any remaining special characters with an underscore.
+ $szName = preg_replace('/[^a-z0-9.-]+/i', '_', $szName);
+ // Remove any useless underscores, e.g. _a_a_._a_ becomes a_a.a
+ $szName = preg_replace('/_*\b_*/', '', $szName);
+ // Crop the filename if it's too long.
+ while (strlen($szName) > $uMaxLength)
+ $szName = preg_replace('/.\b/', '', $szName, 1);
+ return $szName;
+}
+
+/**
+* wfRemoveAccents replaces some special 'european' characters
+* so that a name may be used e.g. to build a file name.
+*
+* Mind that the returned string has the same length of the original
+* if $zGerman==false, but may have a different length otherwise.
+*
+* @param string $szName a name with accents
+* @param boolean $zGerman proceed also german characters
+* @return string the name with accents removed (replacing)
+*/
+function wfRemoveAccents($szName, $zGerman=true)
+{
+ if($zGerman)
+ {
+ // Replace German umlauts and other special characters.
+ $szName = str_replace("ß", "ss", $szName);
+ $szName = preg_replace('/[ÄÖÜäöü]/', '\0e', $szName);
+ }
+ // Proceed accents, etc
+ $szName = strtr($szName,
+ "ÀÁÂÃÄÅÆÈÉÊËÌÍÎÏÒÓÔÕÖØÙÚÛÜàáâãäåæèéêëìíîïòóôõöøùúûüçÇß",
+ "AAAAAAAEEEEIIIIOOOOOOUUUUaaaaaaaeeeeiiiioooooouuuucCs");
+ /*
+ * Mind that the process of "ß", "ü", etc is different if 'german' is on or off!
+ */
+ return $szName ;
+}
+
+/**
+* Function 'xmlsafe' UNUSED, renamed to wfXmlSafe to stick to mw conventions
+*
+* @param string $string
+* @return string $string
+* @todo move function into WikiExporter class or decide to rename as wfXmlSafe
+* @todo this function is currently unused...
+*/
+function wfXmlSafe( $string ) {
$fname = 'xmlsafe';
wfProfileIn( $fname );
@@ -432,4 +831,11 @@
return $string;
}
+/**
+* ==== comment to be removed after patch acceptance ====
+* I systematically destroy whitespaces after the final ? >
+* These caracters are generally harmless.
+* However, in some applications (cookies, headers) they are dangerous.
+* So, it's a matter of principle : just delete them eveywhere
+*/
?>

File Metadata

Mime Type
text/x-diff
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1794
Default Alt Text
SpecialExport.diff (17 KB)

Event Timeline