Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions ReleaseNotes.wiki
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
; Version 2.1.6 (Dec 19, 2025)
* Change logic to how an image gets uploaded
; Version 2.1.5 (Nov 24, 2025)
* Changed dutch i18n strings
* Fixed where if an error occured the i18n key instead of msg gets shown
Expand Down
2 changes: 1 addition & 1 deletion extension.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"Robin van der Wiel",
"Yvar Nanlohij"
],
"version": "2.1.5",
"version": "2.1.6",
"url": "https://www.archixl.nl",
"descriptionmsg": "sc-desc",
"license-name": "GPL-2.0+",
Expand Down
7 changes: 7 additions & 0 deletions src/Hooks.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace MediaWiki\Extension\SmartComments;

use MediaWiki\Extension\SmartComments\Settings\Handler;
use MediaWiki\Extension\SmartComments\Store\ImageSaver;
use MediaWiki\Extension\SmartComments\Updater\Page;
use OutputPage;
use SMW\SemanticData;
Expand All @@ -29,6 +30,12 @@ public static function onMediaWikiServices( \MediaWiki\MediaWikiServices $servic
if ( !mkdir( self::$imageSaveDirectory ) ) {
throw new \Exception( "Could not create directory for images (" . self::$imageSaveDirectory . ")." );
}
} else {
if ( !is_dir( self::$imageSaveDirectory . ImageSaver::tmpPath ) ) {
if ( !mkdir( self::$imageSaveDirectory . ImageSaver::tmpPath ) ) {
throw new \Exception( "Could not create directory for images (" . self::$imageSaveDirectory . ImageSaver::tmpPath . ")." );
}
}
}
}

Expand Down
45 changes: 45 additions & 0 deletions src/Store/ImageSaver.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
namespace MediaWiki\Extension\SmartComments\Store;

use MediaWiki\Extension\SmartComments\Hooks;
use MediaWiki\Logger\LoggerFactory;
use UploadBase;

class ImageSaver {

Expand All @@ -15,6 +17,8 @@ class ImageSaver {
/** @var string */
private $imageName;

public const tmpPath = 'tmp';

/**
* @param \Title $title
*/
Expand Down Expand Up @@ -60,11 +64,52 @@ public function save( $data ): ?string {
return null;
}

if ( !$this->scanFile( $data ) ) {
return null;
}


if ( ! file_put_contents( Hooks::$imageSaveDirectory . "/{$this->imageName}.{$this->imageType}", $data) ) {
return null;
}

return "{$this->imageName}.{$this->imageType}";
}

private function scanFile( string $data ): bool {
$logger = LoggerFactory::getInstance( 'upload' );

// Generate a safe random filename
$filename = bin2hex( openssl_random_pseudo_bytes( 16 ) ) . ".{$this->imageType}";
$path = Hooks::$imageSaveDirectory . self::tmpPath . "/{$filename}";

// Write temp file
if ( file_put_contents( $path, $data ) === false ) {
$logger->error( 'Failed to write temp upload file', [
'path' => $path,
] );
return false;
}

// Virus scan
$virus = UploadBase::detectVirus( $path );
if ( $virus !== false ) {
// Remove infected file
if ( !@unlink( $path ) ) {
$logger->warning( 'Failed to delete infected upload file', [
'path' => $path,
'virus' => $virus,
] );
}

$logger->warning( 'Virus detected in upload', [
'path' => $path,
'virus' => $virus,
] );

return false;
}

return true;
}
}
Loading