summaryrefslogtreecommitdiff
path: root/www/wiki/extensions/ConfirmEdit/includes/CaptchaStore.php
blob: 5a78e466fb80d1cd5d5032ed895a9e09ed9dfa86 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
<?php

use MediaWiki\Session\SessionManager;

abstract class CaptchaStore {
	/**
	 * Store the correct answer for a given captcha
	 * @param  $index String
	 * @param  $info String the captcha result
	 */
	abstract public function store( $index, $info );

	/**
	 * Retrieve the answer for a given captcha
	 * @param  $index String
	 * @return String|false
	 */
	abstract public function retrieve( $index );

	/**
	 * Delete a result once the captcha has been used, so it cannot be reused
	 * @param  $index
	 */
	abstract public function clear( $index );

	/**
	 * Whether this type of CaptchaStore needs cookies
	 * @return Bool
	 */
	abstract public function cookiesNeeded();

	/**
	 * The singleton instance
	 * @var CaptchaStore
	 */
	private static $instance;

	/**
	 * Get somewhere to store captcha data that will persist between requests
	 *
	 * @throws Exception
	 * @return CaptchaStore
	 */
	final public static function get() {
		if ( !self::$instance instanceof self ) {
			global $wgCaptchaStorageClass;
			if ( in_array( 'CaptchaStore', class_parents( $wgCaptchaStorageClass ) ) ) {
				self::$instance = new $wgCaptchaStorageClass;
			} else {
				throw new Exception( "Invalid CaptchaStore class $wgCaptchaStorageClass" );
			}
		}
		return self::$instance;
	}

	final public static function unsetInstanceForTests() {
		if ( !defined( 'MW_PHPUNIT_TEST' ) ) {
			throw new MWException( 'Cannot unset ' . __CLASS__ . ' instance in operation.' );
		}
		self::$instance = null;
	}

	/**
	 * Protected constructor: no creating instances except through the factory method above
	 */
	protected function __construct() {
	}
}

class CaptchaSessionStore extends CaptchaStore {
	protected function __construct() {
		// Make sure the session is started
		SessionManager::getGlobalSession()->persist();
	}

	function store( $index, $info ) {
		SessionManager::getGlobalSession()->set( 'captcha' . $index, $info );
	}

	function retrieve( $index ) {
		return SessionManager::getGlobalSession()->get( 'captcha' . $index, false );
	}

	function clear( $index ) {
		SessionManager::getGlobalSession()->remove( 'captcha' . $index );
	}

	function cookiesNeeded() {
		return true;
	}
}

class CaptchaCacheStore extends CaptchaStore {
	function store( $index, $info ) {
		global $wgCaptchaSessionExpiration;

		ObjectCache::getMainStashInstance()->set(
			wfMemcKey( 'captcha', $index ),
			$info,
			$wgCaptchaSessionExpiration
		);
	}

	function retrieve( $index ) {
		$info = ObjectCache::getMainStashInstance()->get( wfMemcKey( 'captcha', $index ) );
		if ( $info ) {
			return $info;
		} else {
			return false;
		}
	}

	function clear( $index ) {
		ObjectCache::getMainStashInstance()->delete( wfMemcKey( 'captcha', $index ) );
	}

	function cookiesNeeded() {
		return false;
	}
}

class CaptchaHashStore extends CaptchaStore {
	protected $data = [];

	public function store( $index, $info ) {
		$this->data[$index] = $info;
	}

	public function retrieve( $index ) {
		if ( array_key_exists( $index, $this->data ) ) {
			return $this->data[$index];
		}
		return false;
	}

	public function clear( $index ) {
		unset( $this->data[$index] );
	}

	public function cookiesNeeded() {
		return false;
	}

	public function clearAll() {
		$this->data = [];
	}
}