More maintenance for ConfirmEdit extension.
[toast/cookiecaptcha.git] / FancyCaptcha.class.php
index fa968202b3a4f4156924ae5cacfd70d410edade4..c6ee03c6ddf76b155bc8c1cd8c88a2162c7cf276 100644 (file)
@@ -15,7 +15,7 @@ class FancyCaptcha extends SimpleCaptcha {
                $digest = $wgCaptchaSecret . $info['salt'] . $answer . $wgCaptchaSecret . $info['salt'];
                $answerHash = substr( md5( $digest ), 0, 16 );
 
-               if( $answerHash == $info['hash'] ) {
+               if ( $answerHash == $info['hash'] ) {
                        wfDebug( "FancyCaptcha: answer hash matches expected {$info['hash']}\n" );
                        return true;
                } else {
@@ -24,13 +24,27 @@ class FancyCaptcha extends SimpleCaptcha {
                }
        }
 
+       function addCaptchaAPI( &$resultArr ) {
+               $info = $this->pickImage();
+               if ( !$info ) {
+                       $resultArr['captcha']['error'] = 'Out of images';
+                       return;
+               }
+               $index = $this->storeCaptcha( $info );
+               $title = SpecialPage::getTitleFor( 'Captcha', 'image' );
+               $resultArr['captcha']['type'] = 'image';
+               $resultArr['captcha']['mime'] = 'image/png';
+               $resultArr['captcha']['id'] = $index;
+               $resultArr['captcha']['url'] = $title->getLocalUrl( 'wpCaptchaId=' . urlencode( $index ) );
+       }
+
        /**
         * Insert the captcha prompt into the edit form.
         */
        function getForm() {
                $info = $this->pickImage();
-               if( !$info ) {
-                       die( "out of captcha images; this shouldn't happen" );
+               if ( !$info ) {
+                       throw new MWException( "Ran out of captcha images" );
                }
 
                // Generate a random key for use of this captcha image in this session.
@@ -40,24 +54,31 @@ class FancyCaptcha extends SimpleCaptcha {
 
                wfDebug( "Captcha id $index using hash ${info['hash']}, salt ${info['salt']}.\n" );
 
-               $title = Title::makeTitle( NS_SPECIAL, 'Captcha/image' );
+               $title = SpecialPage::getTitleFor( 'Captcha', 'image' );
 
                return "<p>" .
-                       wfElement( 'img', array(
+                       Html::element( 'img', array(
                                'src'    => $title->getLocalUrl( 'wpCaptchaId=' . urlencode( $index ) ),
                                'width'  => $info['width'],
                                'height' => $info['height'],
                                'alt'    => '' ) ) .
                        "</p>\n" .
-                       wfElement( 'input', array(
+                       Html::element( 'input', array(
                                'type'  => 'hidden',
                                'name'  => 'wpCaptchaId',
                                'id'    => 'wpCaptchaId',
                                'value' => $index ) ) .
-                       "<p>" .
-                       wfElement( 'input', array(
+                       '<p>' .
+                       Html::element( 'label', array(
+                               'for' => 'wpCaptchaWord',
+                       ), parent::getMessage( 'label' ) . wfMessage( 'colon-separator' )->text() ) .
+                       Html::element( 'input', array(
                                'name' => 'wpCaptchaWord',
                                'id'   => 'wpCaptchaWord',
+                               'type' => 'text',
+                               'autocorrect' => 'off',
+                               'autocapitalize' => 'off',
+                               'required' => 'required',
                                'tabindex' => 1 ) ) . // tab in before the edit textarea
                        "</p>\n";
        }
@@ -73,27 +94,30 @@ class FancyCaptcha extends SimpleCaptcha {
                        $wgCaptchaDirectory,
                        $wgCaptchaDirectoryLevels );
        }
-       
+
        function pickImageDir( $directory, $levels ) {
-               if( $levels ) {
+               if ( $levels ) {
                        $dirs = array();
-                       
+
                        // Check which subdirs are actually present...
                        $dir = opendir( $directory );
-                       while( false !== ($entry = readdir( $dir ) ) ) {
-                               if( ctype_xdigit( $entry ) && strlen( $entry ) == 1 ) {
+                       if ( !$dir ) {
+                               return false;
+                       }
+                       while ( false !== ( $entry = readdir( $dir ) ) ) {
+                               if ( ctype_xdigit( $entry ) && strlen( $entry ) == 1 ) {
                                        $dirs[] = $entry;
                                }
                        }
                        closedir( $dir );
-                       
+
                        $place = mt_rand( 0, count( $dirs ) - 1 );
                        // In case all dirs are not filled,
                        // cycle through next digits...
-                       for( $j = 0; $j < count( $dirs ); $j++ ) {
-                               $char = $dirs[($place + $j) % count( $dirs )];
+                       for ( $j = 0; $j < count( $dirs ); $j++ ) {
+                               $char = $dirs[( $place + $j ) % count( $dirs )];
                                $return = $this->pickImageDir( "$directory/$char", $levels - 1 );
-                               if( $return ) {
+                               if ( $return ) {
                                        return $return;
                                }
                        }
@@ -103,9 +127,9 @@ class FancyCaptcha extends SimpleCaptcha {
                        return $this->pickImageFromDir( $directory );
                }
        }
-       
+
        function pickImageFromDir( $directory ) {
-               if( !is_dir( $directory ) ) {
+               if ( !is_dir( $directory ) ) {
                        return false;
                }
                $n = mt_rand( 0, $this->countFiles( $directory ) - 1 );
@@ -115,9 +139,9 @@ class FancyCaptcha extends SimpleCaptcha {
 
                $entry = readdir( $dir );
                $pick = false;
-               while( false !== $entry ) {
+               while ( false !== $entry ) {
                        $entry = readdir( $dir );
-                       if( preg_match( '/^image_([0-9a-f]+)_([0-9a-f]+)\\.png$/', $entry, $matches ) ) {
+                       if ( preg_match( '/^image_([0-9a-f]+)_([0-9a-f]+)\\.png$/', $entry, $matches ) ) {
                                $size = getimagesize( "$directory/$entry" );
                                $pick = array(
                                        'salt' => $matches[1],
@@ -126,7 +150,7 @@ class FancyCaptcha extends SimpleCaptcha {
                                        'height' => $size[1],
                                        'viewed' => false,
                                );
-                               if( $count++ == $n ) {
+                               if ( $count++ == $n ) {
                                        break;
                                }
                        }
@@ -137,13 +161,14 @@ class FancyCaptcha extends SimpleCaptcha {
 
        /**
         * Count the number of files in a directory.
+        * @param $dirname
         * @return int
         */
        function countFiles( $dirname ) {
                $dir = opendir( $dirname );
                $count = 0;
-               while( false !== ($entry = readdir( $dir ) ) ) {
-                       if( $entry != '.' && $entry != '..' ) {
+               while ( false !== ( $entry = readdir( $dir ) ) ) {
+                       if ( $entry != '.' && $entry != '..' ) {
                                $count++;
                        }
                }
@@ -152,41 +177,38 @@ class FancyCaptcha extends SimpleCaptcha {
        }
 
        function showImage() {
-               global $wgOut, $wgRequest;
+               global $wgOut;
 
                $wgOut->disable();
 
                $info = $this->retrieveCaptcha();
-               if( $info ) {
-                       if( $info['viewed'] ) {
-                               wfHttpError( 403, 'Access Forbidden', "Can't view captcha image a second time." );
-                               return false;
-                       }
-
-                       $info['viewed'] = wfTimestamp();
+               if ( $info ) {
+                       $timestamp = new MWTimestamp();
+                       $info['viewed'] = $timestamp->getTimestamp();
                        $this->storeCaptcha( $info );
 
                        $salt = $info['salt'];
                        $hash = $info['hash'];
                        $file = $this->imagePath( $salt, $hash );
 
-                       if( file_exists( $file ) ) {
+                       if ( file_exists( $file ) ) {
                                global $IP;
                                require_once "$IP/includes/StreamFile.php";
-                               wfStreamFile( $file );
+                               header( "Cache-Control: private, s-maxage=0, max-age=3600" );
+                               StreamFile::stream( $file );
                                return true;
                        }
                }
                wfHttpError( 500, 'Internal Error', 'Requested bogus captcha image' );
                return false;
        }
-       
+
        function imagePath( $salt, $hash ) {
                global $wgCaptchaDirectory, $wgCaptchaDirectoryLevels;
                $file = $wgCaptchaDirectory;
                $file .= DIRECTORY_SEPARATOR;
-               for( $i = 0; $i < $wgCaptchaDirectoryLevels; $i++ ) {
-                       $file .= $hash{$i};
+               for ( $i = 0; $i < $wgCaptchaDirectoryLevels; $i++ ) {
+                       $file .= $hash { $i } ;
                        $file .= DIRECTORY_SEPARATOR;
                }
                $file .= "image_{$salt}_{$hash}.png";
@@ -197,15 +219,33 @@ class FancyCaptcha extends SimpleCaptcha {
         * Show a message asking the user to enter a captcha on edit
         * The result will be treated as wiki text
         *
-        * @param $action Action being performed
+        * @param $action string Action being performed
         * @return string
         */
        function getMessage( $action ) {
                $name = 'fancycaptcha-' . $action;
-               $text = wfMsg( $name );
+               $text = wfMessage( $name )->text();
                # Obtain a more tailored message, if possible, otherwise, fall back to
                # the default for edits
-               return wfEmptyMsg( $name, $text ) ? wfMsg( 'fancycaptcha-edit' ) : $text;
+               return wfMessage( $name, $text )->isDisabled() ? wfMessage( 'fancycaptcha-edit' )->text() : $text;
        }
 
+       /**
+        * Delete a solved captcha image, if $wgCaptchaDeleteOnSolve is true.
+        */
+       function passCaptcha() {
+               global $wgCaptchaDeleteOnSolve;
+
+               $info = $this->retrieveCaptcha(); // get the captcha info before it gets deleted
+               $pass = parent::passCaptcha();
+
+               if ( $pass && $wgCaptchaDeleteOnSolve ) {
+                       $filename = $this->imagePath( $info['salt'], $info['hash'] );
+                       if ( file_exists( $filename ) ) {
+                               unlink( $filename );
+                       }
+               }
+
+               return $pass;
+       }
 }