addOption( "wordlist", 'A list of words', true, true ); $this->addOption( "font", "The font to use", true, true ); $this->addOption( "font-size", "The font size ", false, true ); $this->addOption( "blacklist", "A blacklist of words that should not be used", false, true ); $this->addOption( "fill", "Fill the captcha container to N files", true, true ); $this->addOption( "verbose", "Show debugging information" ); $this->mDescription = "Generate new captchas and move them into storage"; } public function execute() { global $wgCaptchaSecret, $wgCaptchaDirectoryLevels; $instance = ConfirmEditHooks::getInstance(); if ( !( $instance instanceof FancyCaptcha ) ) { $this->error( "\$wgCaptchaClass is not FancyCaptcha.\n", 1 ); } $backend = $instance->getBackend(); $countAct = $instance->estimateCaptchaCount(); $this->output( "Estimated number of captchas is $countAct.\n" ); $countGen = (int)$this->getOption( 'fill' ) - $countAct; if ( $countGen <= 0 ) { $this->output( "No need to generate anymore captchas.\n" ); return; } $tmpDir = wfTempDir() . '/mw-fancycaptcha-' . time() . '-' . wfRandomString( 6 ); if ( !wfMkdirParents( $tmpDir ) ) { $this->error( "Could not create temp directory.\n", 1 ); } $e = null; // exception try { $cmd = sprintf( "python %s --key %s --output %s --count %s --dirs %s", wfEscapeShellArg( __DIR__ . '/../captcha.py' ), wfEscapeShellArg( $wgCaptchaSecret ), wfEscapeShellArg( $tmpDir ), wfEscapeShellArg( $countGen ), wfEscapeShellArg( $wgCaptchaDirectoryLevels ) ); foreach ( [ 'wordlist', 'font', 'font-size', 'blacklist', 'verbose' ] as $par ) { if ( $this->hasOption( $par ) ) { $cmd .= " --$par " . wfEscapeShellArg( $this->getOption( $par ) ); } } $this->output( "Generating $countGen new captchas...\n" ); $retVal = 1; wfShellExec( $cmd, $retVal, [], [ 'time' => 0 ] ); if ( $retVal != 0 ) { wfRecursiveRemoveDir( $tmpDir ); $this->error( "Could not run generation script.\n", 1 ); } $flags = FilesystemIterator::SKIP_DOTS; $iter = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $tmpDir, $flags ), RecursiveIteratorIterator::CHILD_FIRST // include dirs ); $this->output( "Copying the new captchas to storage...\n" ); foreach ( $iter as $fileInfo ) { if ( !$fileInfo->isFile() ) { continue; } list( $salt, $hash ) = $instance->hashFromImageName( $fileInfo->getBasename() ); $dest = $instance->imagePath( $salt, $hash ); $backend->prepare( [ 'dir' => dirname( $dest ) ] ); $status = $backend->quickStore( [ 'src' => $fileInfo->getPathname(), 'dst' => $dest ] ); if ( !$status->isOK() ) { $this->error( "Could not save file '{$fileInfo->getPathname()}'.\n" ); } } } catch ( Exception $e ) { wfRecursiveRemoveDir( $tmpDir ); throw $e; } $this->output( "Removing temporary files...\n" ); wfRecursiveRemoveDir( $tmpDir ); $this->output( "Done.\n" ); } } $maintClass = "GenerateFancyCaptchas"; require_once ( RUN_MAINTENANCE_IF_MAIN );