summaryrefslogtreecommitdiff
path: root/includes/specials
diff options
context:
space:
mode:
Diffstat (limited to 'includes/specials')
-rw-r--r--includes/specials/SpecialImport.php30
-rw-r--r--includes/specials/SpecialUndelete.php35
-rw-r--r--includes/specials/SpecialUpload.php65
3 files changed, 110 insertions, 20 deletions
diff --git a/includes/specials/SpecialImport.php b/includes/specials/SpecialImport.php
index 4c37f1f9..1623245d 100644
--- a/includes/specials/SpecialImport.php
+++ b/includes/specials/SpecialImport.php
@@ -43,26 +43,30 @@ function wfSpecialImport( $page = '' ) {
if( $wgRequest->wasPosted() && $wgRequest->getVal( 'action' ) == 'submit') {
$isUpload = false;
$namespace = $wgRequest->getIntOrNull( 'namespace' );
+ $sourceName = $wgRequest->getVal( "source" );
- switch( $wgRequest->getVal( "source" ) ) {
- case "upload":
+ if ( !$wgUser->matchEditToken( $wgRequest->getVal( 'editToken' ) ) ) {
+ $source = new WikiErrorMsg( 'import-token-mismatch' );
+ } elseif ( $sourceName == 'upload' ) {
$isUpload = true;
if( $wgUser->isAllowed( 'importupload' ) ) {
$source = ImportStreamSource::newFromUpload( "xmlimport" );
} else {
return $wgOut->permissionRequired( 'importupload' );
}
- break;
- case "interwiki":
+ } elseif ( $sourceName == "interwiki" ) {
$interwiki = $wgRequest->getVal( 'interwiki' );
- $history = $wgRequest->getCheck( 'interwikiHistory' );
- $frompage = $wgRequest->getText( "frompage" );
- $source = ImportStreamSource::newFromInterwiki(
- $interwiki,
- $frompage,
- $history );
- break;
- default:
+ if ( !in_array( $interwiki, $wgImportSources ) ) {
+ $source = new WikiErrorMsg( "import-invalid-interwiki" );
+ } else {
+ $history = $wgRequest->getCheck( 'interwikiHistory' );
+ $frompage = $wgRequest->getText( "frompage" );
+ $source = ImportStreamSource::newFromInterwiki(
+ $interwiki,
+ $frompage,
+ $history );
+ }
+ } else {
$source = new WikiErrorMsg( "importunknownsource" );
}
@@ -106,6 +110,7 @@ function wfSpecialImport( $page = '' ) {
Xml::hidden( 'action', 'submit' ) .
Xml::hidden( 'source', 'upload' ) .
Xml::input( 'xmlimport', 50, '', array( 'type' => 'file' ) ) . ' ' .
+ Xml::hidden( 'editToken', $wgUser->editToken() ) .
Xml::submitButton( wfMsg( 'uploadbtn' ) ) .
Xml::closeElement( 'form' ) .
Xml::closeElement( 'fieldset' )
@@ -124,6 +129,7 @@ function wfSpecialImport( $page = '' ) {
wfMsgExt( 'import-interwiki-text', array( 'parse' ) ) .
Xml::hidden( 'action', 'submit' ) .
Xml::hidden( 'source', 'interwiki' ) .
+ Xml::hidden( 'editToken', $wgUser->editToken() ) .
Xml::openElement( 'table', array( 'id' => 'mw-import-table' ) ) .
"<tr>
<td>" .
diff --git a/includes/specials/SpecialUndelete.php b/includes/specials/SpecialUndelete.php
index fbbf89d6..d862ebb3 100644
--- a/includes/specials/SpecialUndelete.php
+++ b/includes/specials/SpecialUndelete.php
@@ -571,7 +571,7 @@ class PageArchive {
*/
class UndeleteForm {
var $mAction, $mTarget, $mTimestamp, $mRestore, $mTargetObj;
- var $mTargetTimestamp, $mAllowed, $mComment;
+ var $mTargetTimestamp, $mAllowed, $mComment, $mToken;
function UndeleteForm( $request, $par = "" ) {
global $wgUser;
@@ -589,6 +589,7 @@ class UndeleteForm {
$this->mDiff = $request->getCheck( 'diff' );
$this->mComment = $request->getText( 'wpComment' );
$this->mUnsuppress = $request->getVal( 'wpUnsuppress' ) && $wgUser->isAllowed( 'suppressrevision' );
+ $this->mToken = $request->getVal( 'token' );
if( $par != "" ) {
$this->mTarget = $par;
@@ -655,6 +656,9 @@ class UndeleteForm {
if( !$file->userCan( File::DELETED_FILE ) ) {
$wgOut->permissionRequired( 'suppressrevision' );
return false;
+ } elseif ( !$wgUser->matchEditToken( $this->mToken, $this->mFile ) ) {
+ $this->showFileConfirmationForm( $this->mFile );
+ return false;
} else {
return $this->showFile( $this->mFile );
}
@@ -880,6 +884,29 @@ class UndeleteForm {
}
/**
+ * Show a form confirming whether a tokenless user really wants to see a file
+ */
+ private function showFileConfirmationForm( $key ) {
+ global $wgOut, $wgUser, $wgLang;
+ $file = new ArchivedFile( $this->mTargetObj, '', $this->mFile );
+ $wgOut->addWikiMsg( 'undelete-show-file-confirm',
+ $this->mTargetObj->getText(),
+ $wgLang->timeanddate( $file->getTimestamp() ) );
+ $wgOut->addHTML(
+ Xml::openElement( 'form', array(
+ 'method' => 'POST',
+ 'action' => SpecialPage::getTitleFor( 'Undelete' )->getLocalUrl(
+ 'target=' . urlencode( $this->mTarget ) .
+ '&file=' . urlencode( $key ) .
+ '&token=' . urlencode( $wgUser->editToken( $key ) ) )
+ )
+ ) .
+ Xml::submitButton( wfMsg( 'undelete-show-file-submit' ) ) .
+ '</form>'
+ );
+ }
+
+ /**
* Show a deleted file version requested by the visitor.
*/
private function showFile( $key ) {
@@ -1191,13 +1218,15 @@ class UndeleteForm {
* @return string
*/
function getFileLink( $file, $titleObj, $ts, $key, $sk ) {
- global $wgLang;
+ global $wgLang, $wgUser;
if( !$file->userCan(File::DELETED_FILE) ) {
return '<span class="history-deleted">' . $wgLang->timeanddate( $ts, true ) . '</span>';
} else {
$link = $sk->makeKnownLinkObj( $titleObj, $wgLang->timeanddate( $ts, true ),
- "target=".$this->mTargetObj->getPrefixedUrl()."&file=$key" );
+ "target=".$this->mTargetObj->getPrefixedUrl().
+ "&file=$key" .
+ "&token=" . urlencode( $wgUser->editToken( $key ) ) );
if( $file->isDeleted(File::DELETED_FILE) )
$link = '<span class="history-deleted">' . $link . '</span>';
return $link;
diff --git a/includes/specials/SpecialUpload.php b/includes/specials/SpecialUpload.php
index 8fe2f52f..3a79e052 100644
--- a/includes/specials/SpecialUpload.php
+++ b/includes/specials/SpecialUpload.php
@@ -1326,11 +1326,11 @@ wgUploadAutoFill = {$autofill};
$magic = MimeMagic::singleton();
$mime = $magic->guessMimeType($tmpfile,false);
+
#check mime type, if desired
global $wgVerifyMimeType;
if ($wgVerifyMimeType) {
-
- wfDebug ( "\n\nmime: <$mime> extension: <$extension>\n\n");
+ wfDebug ( "\n\nmime: <$mime> extension: <$extension>\n\n");
#check mime type against file extension
if( !self::verifyExtension( $mime, $extension ) ) {
return new WikiErrorMsg( 'uploadcorrupt' );
@@ -1338,9 +1338,22 @@ wgUploadAutoFill = {$autofill};
#check mime type blacklist
global $wgMimeTypeBlacklist;
- if( isset($wgMimeTypeBlacklist) && !is_null($wgMimeTypeBlacklist)
- && $this->checkFileExtension( $mime, $wgMimeTypeBlacklist ) ) {
- return new WikiErrorMsg( 'filetype-badmime', htmlspecialchars( $mime ) );
+ if( isset($wgMimeTypeBlacklist) && !is_null($wgMimeTypeBlacklist) ) {
+ if ( $this->checkFileExtension( $mime, $wgMimeTypeBlacklist ) ) {
+ return new WikiErrorMsg( 'filetype-badmime', htmlspecialchars( $mime ) );
+ }
+
+ # Check IE type
+ $fp = fopen( $tmpfile, 'rb' );
+ $chunk = fread( $fp, 256 );
+ fclose( $fp );
+ $extMime = $magic->guessTypesForExtension( $extension );
+ $ieTypes = $magic->getIEMimeTypes( $tmpfile, $chunk, $extMime );
+ foreach ( $ieTypes as $ieType ) {
+ if ( $this->checkFileExtension( $ieType, $wgMimeTypeBlacklist ) ) {
+ return new WikiErrorMsg( 'filetype-bad-ie-mime', $ieType );
+ }
+ }
}
}
@@ -1348,6 +1361,11 @@ wgUploadAutoFill = {$autofill};
if( $this->detectScript ( $tmpfile, $mime, $extension ) ) {
return new WikiErrorMsg( 'uploadscripted' );
}
+ if( $extension == 'svg' || $mime == 'image/svg+xml' ) {
+ if( $this->detectScriptInSvg( $tmpfile ) ) {
+ return new WikiErrorMsg( 'uploadscripted' );
+ }
+ }
/**
* Scan the uploaded file for viruses
@@ -1399,6 +1417,7 @@ wgUploadAutoFill = {$autofill};
}
}
+
/**
* Heuristic for detecting files that *could* contain JavaScript instructions or
* things that may look like HTML to a browser and are thus
@@ -1459,6 +1478,7 @@ wgUploadAutoFill = {$autofill};
*/
$tags = array(
+ '<a href',
'<body',
'<head',
'<html', #also in safari
@@ -1497,6 +1517,41 @@ wgUploadAutoFill = {$autofill};
return false;
}
+ function detectScriptInSvg( $filename ) {
+ $check = new XmlTypeCheck( $filename, array( $this, 'checkSvgScriptCallback' ) );
+ return $check->filterMatch;
+ }
+
+ /**
+ * @todo Replace this with a whitelist filter!
+ */
+ function checkSvgScriptCallback( $element, $attribs ) {
+ $stripped = $this->stripXmlNamespace( $element );
+
+ if( $stripped == 'script' ) {
+ wfDebug( __METHOD__ . ": Found script element '$element' in uploaded file.\n" );
+ return true;
+ }
+
+ foreach( $attribs as $attrib => $value ) {
+ $stripped = $this->stripXmlNamespace( $attrib );
+ if( substr( $stripped, 0, 2 ) == 'on' ) {
+ wfDebug( __METHOD__ . ": Found script attribute '$attrib'='value' in uploaded file.\n" );
+ return true;
+ }
+ if( $stripped == 'href' && strpos( strtolower( $value ), 'javascript:' ) !== false ) {
+ wfDebug( __METHOD__ . ": Found script href attribute '$attrib'='$value' in uploaded file.\n" );
+ return true;
+ }
+ }
+ }
+
+ private function stripXmlNamespace( $name ) {
+ // 'http://www.w3.org/2000/svg:script' -> 'script'
+ $parts = explode( ':', strtolower( $name ) );
+ return array_pop( $parts );
+ }
+
/**
* Generic wrapper function for a virus scanner program.
* This relies on the $wgAntivirus and $wgAntivirusSetup variables.