danielebarchiesi@2
|
1 <?php
|
danielebarchiesi@2
|
2
|
danielebarchiesi@2
|
3 /**
|
danielebarchiesi@2
|
4 * @file
|
danielebarchiesi@2
|
5 * Tests for CAPTCHA module.
|
danielebarchiesi@2
|
6 */
|
danielebarchiesi@2
|
7
|
danielebarchiesi@2
|
8 // TODO: write test for CAPTCHAs on admin pages
|
danielebarchiesi@2
|
9 // TODO: test for default challenge type
|
danielebarchiesi@2
|
10 // TODO: test about placement (comment form, node forms, log in form, etc)
|
danielebarchiesi@2
|
11 // TODO: test if captcha_cron does it work right
|
danielebarchiesi@2
|
12 // TODO: test custom CAPTCHA validation stuff
|
danielebarchiesi@2
|
13 // TODO: test if entry on status report (Already X blocked form submissions) works
|
danielebarchiesi@2
|
14 // TODO: test space ignoring validation of image CAPTCHA
|
danielebarchiesi@2
|
15
|
danielebarchiesi@2
|
16 // TODO: refactor the 'comment_body[' . LANGUAGE_NONE . '][0][value]' stuff
|
danielebarchiesi@2
|
17
|
danielebarchiesi@2
|
18 // Some constants for better reuse.
|
danielebarchiesi@2
|
19 define('CAPTCHA_WRONG_RESPONSE_ERROR_MESSAGE',
|
danielebarchiesi@2
|
20 'The answer you entered for the CAPTCHA was not correct.');
|
danielebarchiesi@2
|
21
|
danielebarchiesi@2
|
22 define('CAPTCHA_SESSION_REUSE_ATTACK_ERROR_MESSAGE',
|
danielebarchiesi@2
|
23 'CAPTCHA session reuse attack detected.');
|
danielebarchiesi@2
|
24
|
danielebarchiesi@2
|
25 define('CAPTCHA_UNKNOWN_CSID_ERROR_MESSAGE',
|
danielebarchiesi@2
|
26 'CAPTCHA validation error: unknown CAPTCHA session ID. Contact the site administrator if this problem persists.');
|
danielebarchiesi@2
|
27
|
danielebarchiesi@2
|
28
|
danielebarchiesi@2
|
29
|
danielebarchiesi@2
|
30 /**
|
danielebarchiesi@2
|
31 * Base class for CAPTCHA tests.
|
danielebarchiesi@2
|
32 *
|
danielebarchiesi@2
|
33 * Provides common setup stuff and various helper functions
|
danielebarchiesi@2
|
34 */
|
danielebarchiesi@2
|
35 abstract class CaptchaBaseWebTestCase extends DrupalWebTestCase {
|
danielebarchiesi@2
|
36
|
danielebarchiesi@2
|
37 /**
|
danielebarchiesi@2
|
38 * User with various administrative permissions.
|
danielebarchiesi@2
|
39 * @var Drupal user
|
danielebarchiesi@2
|
40 */
|
danielebarchiesi@2
|
41 protected $admin_user;
|
danielebarchiesi@2
|
42
|
danielebarchiesi@2
|
43 /**
|
danielebarchiesi@2
|
44 * Normal visitor with limited permissions
|
danielebarchiesi@2
|
45 * @var Drupal user;
|
danielebarchiesi@2
|
46 */
|
danielebarchiesi@2
|
47 protected $normal_user;
|
danielebarchiesi@2
|
48
|
danielebarchiesi@2
|
49 /**
|
danielebarchiesi@2
|
50 * Form ID of comment form on standard (page) node
|
danielebarchiesi@2
|
51 * @var string
|
danielebarchiesi@2
|
52 */
|
danielebarchiesi@2
|
53 const COMMENT_FORM_ID = 'comment_node_page_form';
|
danielebarchiesi@2
|
54
|
danielebarchiesi@2
|
55 /**
|
danielebarchiesi@2
|
56 * Drupal path of the (general) CAPTCHA admin page
|
danielebarchiesi@2
|
57 */
|
danielebarchiesi@2
|
58 const CAPTCHA_ADMIN_PATH = 'admin/config/people/captcha';
|
danielebarchiesi@2
|
59
|
danielebarchiesi@2
|
60
|
danielebarchiesi@2
|
61 function setUp() {
|
danielebarchiesi@2
|
62 // Load two modules: the captcha module itself and the comment module for testing anonymous comments.
|
danielebarchiesi@2
|
63 parent::setUp('captcha', 'comment');
|
danielebarchiesi@2
|
64 module_load_include('inc', 'captcha');
|
danielebarchiesi@2
|
65
|
danielebarchiesi@2
|
66 // Create a normal user.
|
danielebarchiesi@2
|
67 $permissions = array(
|
danielebarchiesi@2
|
68 'access comments', 'post comments', 'skip comment approval',
|
danielebarchiesi@2
|
69 'access content', 'create page content', 'edit own page content',
|
danielebarchiesi@2
|
70 );
|
danielebarchiesi@2
|
71 $this->normal_user = $this->drupalCreateUser($permissions);
|
danielebarchiesi@2
|
72
|
danielebarchiesi@2
|
73 // Create an admin user.
|
danielebarchiesi@2
|
74 $permissions[] = 'administer CAPTCHA settings';
|
danielebarchiesi@2
|
75 $permissions[] = 'skip CAPTCHA';
|
danielebarchiesi@2
|
76 $permissions[] = 'administer permissions';
|
danielebarchiesi@2
|
77 $permissions[] = 'administer content types';
|
danielebarchiesi@2
|
78 $this->admin_user = $this->drupalCreateUser($permissions);
|
danielebarchiesi@2
|
79
|
danielebarchiesi@2
|
80 // Put comments on page nodes on a separate page (default in D7: below post).
|
danielebarchiesi@2
|
81 variable_set('comment_form_location_page', COMMENT_FORM_SEPARATE_PAGE);
|
danielebarchiesi@2
|
82
|
danielebarchiesi@2
|
83 }
|
danielebarchiesi@2
|
84
|
danielebarchiesi@2
|
85 /**
|
danielebarchiesi@2
|
86 * Assert that the response is accepted:
|
danielebarchiesi@2
|
87 * no "unknown CSID" message, no "CSID reuse attack detection" message,
|
danielebarchiesi@2
|
88 * no "wrong answer" message.
|
danielebarchiesi@2
|
89 */
|
danielebarchiesi@2
|
90 protected function assertCaptchaResponseAccepted() {
|
danielebarchiesi@2
|
91 // There should be no error message about unknown CAPTCHA session ID.
|
danielebarchiesi@2
|
92 $this->assertNoText(t(CAPTCHA_UNKNOWN_CSID_ERROR_MESSAGE),
|
danielebarchiesi@2
|
93 'CAPTCHA response should be accepted (known CSID).',
|
danielebarchiesi@2
|
94 'CAPTCHA');
|
danielebarchiesi@2
|
95 // There should be no error message about CSID reuse attack.
|
danielebarchiesi@2
|
96 $this->assertNoText(t(CAPTCHA_SESSION_REUSE_ATTACK_ERROR_MESSAGE),
|
danielebarchiesi@2
|
97 'CAPTCHA response should be accepted (no CAPTCHA session reuse attack detection).',
|
danielebarchiesi@2
|
98 'CAPTCHA');
|
danielebarchiesi@2
|
99 // There should be no error message about wrong response.
|
danielebarchiesi@2
|
100 $this->assertNoText(t(CAPTCHA_WRONG_RESPONSE_ERROR_MESSAGE),
|
danielebarchiesi@2
|
101 'CAPTCHA response should be accepted (correct response).',
|
danielebarchiesi@2
|
102 'CAPTCHA');
|
danielebarchiesi@2
|
103 }
|
danielebarchiesi@2
|
104
|
danielebarchiesi@2
|
105 /**
|
danielebarchiesi@2
|
106 * Assert that there is a CAPTCHA on the form or not.
|
danielebarchiesi@2
|
107 * @param bool $presence whether there should be a CAPTCHA or not.
|
danielebarchiesi@2
|
108 */
|
danielebarchiesi@2
|
109 protected function assertCaptchaPresence($presence) {
|
danielebarchiesi@2
|
110 if ($presence) {
|
danielebarchiesi@2
|
111 $this->assertText(_captcha_get_description(),
|
danielebarchiesi@2
|
112 'There should be a CAPTCHA on the form.', 'CAPTCHA');
|
danielebarchiesi@2
|
113 }
|
danielebarchiesi@2
|
114 else {
|
danielebarchiesi@2
|
115 $this->assertNoText(_captcha_get_description(),
|
danielebarchiesi@2
|
116 'There should be no CAPTCHA on the form.', 'CAPTCHA');
|
danielebarchiesi@2
|
117 }
|
danielebarchiesi@2
|
118 }
|
danielebarchiesi@2
|
119
|
danielebarchiesi@2
|
120 /**
|
danielebarchiesi@2
|
121 * Helper function to create a node with comments enabled.
|
danielebarchiesi@2
|
122 *
|
danielebarchiesi@2
|
123 * @return
|
danielebarchiesi@2
|
124 * Created node object.
|
danielebarchiesi@2
|
125 */
|
danielebarchiesi@2
|
126 protected function createNodeWithCommentsEnabled($type='page') {
|
danielebarchiesi@2
|
127 $node_settings = array(
|
danielebarchiesi@2
|
128 'type' => $type,
|
danielebarchiesi@2
|
129 'comment' => COMMENT_NODE_OPEN,
|
danielebarchiesi@2
|
130 );
|
danielebarchiesi@2
|
131 $node = $this->drupalCreateNode($node_settings);
|
danielebarchiesi@2
|
132 return $node;
|
danielebarchiesi@2
|
133 }
|
danielebarchiesi@2
|
134
|
danielebarchiesi@2
|
135 /**
|
danielebarchiesi@2
|
136 * Helper function to generate a form values array for comment forms
|
danielebarchiesi@2
|
137 */
|
danielebarchiesi@2
|
138 protected function getCommentFormValues() {
|
danielebarchiesi@2
|
139 $edit = array(
|
danielebarchiesi@2
|
140 'subject' => 'comment_subject ' . $this->randomName(32),
|
danielebarchiesi@2
|
141 'comment_body[' . LANGUAGE_NONE . '][0][value]' => 'comment_body ' . $this->randomName(256),
|
danielebarchiesi@2
|
142 );
|
danielebarchiesi@2
|
143 return $edit;
|
danielebarchiesi@2
|
144 }
|
danielebarchiesi@2
|
145
|
danielebarchiesi@2
|
146 /**
|
danielebarchiesi@2
|
147 * Helper function to generate a form values array for node forms
|
danielebarchiesi@2
|
148 */
|
danielebarchiesi@2
|
149 protected function getNodeFormValues() {
|
danielebarchiesi@2
|
150 $edit = array(
|
danielebarchiesi@2
|
151 'title' => 'node_title ' . $this->randomName(32),
|
danielebarchiesi@2
|
152 'body[' . LANGUAGE_NONE . '][0][value]' => 'node_body ' . $this->randomName(256),
|
danielebarchiesi@2
|
153 );
|
danielebarchiesi@2
|
154 return $edit;
|
danielebarchiesi@2
|
155 }
|
danielebarchiesi@2
|
156
|
danielebarchiesi@2
|
157
|
danielebarchiesi@2
|
158 /**
|
danielebarchiesi@2
|
159 * Get the CAPTCHA session id from the current form in the browser.
|
danielebarchiesi@2
|
160 */
|
danielebarchiesi@2
|
161 protected function getCaptchaSidFromForm() {
|
danielebarchiesi@2
|
162 $elements = $this->xpath('//input[@name="captcha_sid"]');
|
danielebarchiesi@2
|
163 $captcha_sid = (int) $elements[0]['value'];
|
danielebarchiesi@2
|
164 return $captcha_sid;
|
danielebarchiesi@2
|
165 }
|
danielebarchiesi@2
|
166 /**
|
danielebarchiesi@2
|
167 * Get the CAPTCHA token from the current form in the browser.
|
danielebarchiesi@2
|
168 */
|
danielebarchiesi@2
|
169 protected function getCaptchaTokenFromForm() {
|
danielebarchiesi@2
|
170 $elements = $this->xpath('//input[@name="captcha_token"]');
|
danielebarchiesi@2
|
171 $captcha_token = (int) $elements[0]['value'];
|
danielebarchiesi@2
|
172 return $captcha_token;
|
danielebarchiesi@2
|
173 }
|
danielebarchiesi@2
|
174
|
danielebarchiesi@2
|
175 /**
|
danielebarchiesi@2
|
176 * Get the solution of the math CAPTCHA from the current form in the browser.
|
danielebarchiesi@2
|
177 */
|
danielebarchiesi@2
|
178 protected function getMathCaptchaSolutionFromForm() {
|
danielebarchiesi@2
|
179 // Get the math challenge.
|
danielebarchiesi@2
|
180 $elements = $this->xpath('//div[@class="form-item form-type-textfield form-item-captcha-response"]/span[@class="field-prefix"]');
|
danielebarchiesi@2
|
181 $challenge = (string) $elements[0];
|
danielebarchiesi@2
|
182 // Extract terms and operator from challenge.
|
danielebarchiesi@2
|
183 $matches = array();
|
danielebarchiesi@2
|
184 $ret = preg_match('/\\s*(\\d+)\\s*(-|\\+)\\s*(\\d+)\\s*=\\s*/', $challenge, $matches);
|
danielebarchiesi@2
|
185 // Solve the challenge
|
danielebarchiesi@2
|
186 $a = (int) $matches[1];
|
danielebarchiesi@2
|
187 $b = (int) $matches[3];
|
danielebarchiesi@2
|
188 $solution = $matches[2] == '-' ? $a - $b : $a + $b;
|
danielebarchiesi@2
|
189 return $solution;
|
danielebarchiesi@2
|
190 }
|
danielebarchiesi@2
|
191
|
danielebarchiesi@2
|
192 /**
|
danielebarchiesi@2
|
193 * Helper function to allow comment posting for anonymous users.
|
danielebarchiesi@2
|
194 */
|
danielebarchiesi@2
|
195 protected function allowCommentPostingForAnonymousVisitors() {
|
danielebarchiesi@2
|
196 // Log in as admin.
|
danielebarchiesi@2
|
197 $this->drupalLogin($this->admin_user);
|
danielebarchiesi@2
|
198 // Post user permissions form
|
danielebarchiesi@2
|
199 $edit = array(
|
danielebarchiesi@2
|
200 '1[access comments]' => true,
|
danielebarchiesi@2
|
201 '1[post comments]' => true,
|
danielebarchiesi@2
|
202 '1[skip comment approval]' => true,
|
danielebarchiesi@2
|
203 );
|
danielebarchiesi@2
|
204 $this->drupalPost('admin/people/permissions', $edit, 'Save permissions');
|
danielebarchiesi@2
|
205 $this->assertText('The changes have been saved.');
|
danielebarchiesi@2
|
206 // Log admin out
|
danielebarchiesi@2
|
207 $this->drupalLogout();
|
danielebarchiesi@2
|
208 }
|
danielebarchiesi@2
|
209
|
danielebarchiesi@2
|
210 }
|
danielebarchiesi@2
|
211
|
danielebarchiesi@2
|
212
|
danielebarchiesi@2
|
213
|
danielebarchiesi@2
|
214 class CaptchaTestCase extends CaptchaBaseWebTestCase {
|
danielebarchiesi@2
|
215
|
danielebarchiesi@2
|
216 public static function getInfo() {
|
danielebarchiesi@2
|
217 return array(
|
danielebarchiesi@2
|
218 'name' => t('General CAPTCHA functionality'),
|
danielebarchiesi@2
|
219 'description' => t('Testing of the basic CAPTCHA functionality.'),
|
danielebarchiesi@2
|
220 'group' => t('CAPTCHA'),
|
danielebarchiesi@2
|
221 );
|
danielebarchiesi@2
|
222 }
|
danielebarchiesi@2
|
223
|
danielebarchiesi@2
|
224 /**
|
danielebarchiesi@2
|
225 * Testing the protection of the user log in form.
|
danielebarchiesi@2
|
226 */
|
danielebarchiesi@2
|
227 function testCaptchaOnLoginForm() {
|
danielebarchiesi@2
|
228 // Create user and test log in without CAPTCHA.
|
danielebarchiesi@2
|
229 $user = $this->drupalCreateUser();
|
danielebarchiesi@2
|
230 $this->drupalLogin($user);
|
danielebarchiesi@2
|
231 // Log out again.
|
danielebarchiesi@2
|
232 $this->drupalLogout();
|
danielebarchiesi@2
|
233
|
danielebarchiesi@2
|
234 // Set a CAPTCHA on login form
|
danielebarchiesi@2
|
235 captcha_set_form_id_setting('user_login', 'captcha/Math');
|
danielebarchiesi@2
|
236
|
danielebarchiesi@2
|
237 // Check if there is a CAPTCHA on the login form (look for the title).
|
danielebarchiesi@2
|
238 $this->drupalGet('user');
|
danielebarchiesi@2
|
239 $this->assertCaptchaPresence(TRUE);
|
danielebarchiesi@2
|
240
|
danielebarchiesi@2
|
241 // Try to log in, which should fail.
|
danielebarchiesi@2
|
242 $edit = array(
|
danielebarchiesi@2
|
243 'name' => $user->name,
|
danielebarchiesi@2
|
244 'pass' => $user->pass_raw,
|
danielebarchiesi@2
|
245 'captcha_response' => '?',
|
danielebarchiesi@2
|
246 );
|
danielebarchiesi@2
|
247 $this->drupalPost('user', $edit, t('Log in'));
|
danielebarchiesi@2
|
248 // Check for error message.
|
danielebarchiesi@2
|
249 $this->assertText(t(CAPTCHA_WRONG_RESPONSE_ERROR_MESSAGE),
|
danielebarchiesi@2
|
250 'CAPTCHA should block user login form', 'CAPTCHA');
|
danielebarchiesi@2
|
251
|
danielebarchiesi@2
|
252 // And make sure that user is not logged in: check for name and password fields on ?q=user
|
danielebarchiesi@2
|
253 $this->drupalGet('user');
|
danielebarchiesi@2
|
254 $this->assertField('name', t('Username field found.'), 'CAPTCHA');
|
danielebarchiesi@2
|
255 $this->assertField('pass', t('Password field found.'), 'CAPTCHA');
|
danielebarchiesi@2
|
256
|
danielebarchiesi@2
|
257 }
|
danielebarchiesi@2
|
258
|
danielebarchiesi@2
|
259
|
danielebarchiesi@2
|
260 /**
|
danielebarchiesi@2
|
261 * Assert function for testing if comment posting works as it should.
|
danielebarchiesi@2
|
262 *
|
danielebarchiesi@2
|
263 * Creates node with comment writing enabled, tries to post comment
|
danielebarchiesi@2
|
264 * with given CAPTCHA response (caller should enable the desired
|
danielebarchiesi@2
|
265 * challenge on page node comment forms) and checks if the result is as expected.
|
danielebarchiesi@2
|
266 *
|
danielebarchiesi@2
|
267 * @param $captcha_response the response on the CAPTCHA
|
danielebarchiesi@2
|
268 * @param $should_pass boolean describing if the posting should pass or should be blocked
|
danielebarchiesi@2
|
269 * @param $message message to prefix to nested asserts
|
danielebarchiesi@2
|
270 */
|
danielebarchiesi@2
|
271 protected function assertCommentPosting($captcha_response, $should_pass, $message) {
|
danielebarchiesi@2
|
272 // Make sure comments on pages can be saved directely without preview.
|
danielebarchiesi@2
|
273 variable_set('comment_preview_page', DRUPAL_OPTIONAL);
|
danielebarchiesi@2
|
274
|
danielebarchiesi@2
|
275 // Create a node with comments enabled.
|
danielebarchiesi@2
|
276 $node = $this->createNodeWithCommentsEnabled();
|
danielebarchiesi@2
|
277
|
danielebarchiesi@2
|
278 // Post comment on node.
|
danielebarchiesi@2
|
279 $edit = $this->getCommentFormValues();
|
danielebarchiesi@2
|
280 $comment_subject = $edit['subject'];
|
danielebarchiesi@2
|
281 $comment_body = $edit['comment_body[' . LANGUAGE_NONE . '][0][value]'];
|
danielebarchiesi@2
|
282 $edit['captcha_response'] = $captcha_response;
|
danielebarchiesi@2
|
283 $this->drupalPost('comment/reply/' . $node->nid, $edit, t('Save'));
|
danielebarchiesi@2
|
284
|
danielebarchiesi@2
|
285 if ($should_pass) {
|
danielebarchiesi@2
|
286 // There should be no error message.
|
danielebarchiesi@2
|
287 $this->assertCaptchaResponseAccepted();
|
danielebarchiesi@2
|
288 // Get node page and check that comment shows up.
|
danielebarchiesi@2
|
289 $this->drupalGet('node/' . $node->nid);
|
danielebarchiesi@2
|
290 $this->assertText($comment_subject, $message .' Comment should show up on node page.', 'CAPTCHA');
|
danielebarchiesi@2
|
291 $this->assertText($comment_body, $message . ' Comment should show up on node page.', 'CAPTCHA');
|
danielebarchiesi@2
|
292 }
|
danielebarchiesi@2
|
293 else {
|
danielebarchiesi@2
|
294 // Check for error message.
|
danielebarchiesi@2
|
295 $this->assertText(t(CAPTCHA_WRONG_RESPONSE_ERROR_MESSAGE), $message .' Comment submission should be blocked.', 'CAPTCHA');
|
danielebarchiesi@2
|
296 // Get node page and check that comment is not present.
|
danielebarchiesi@2
|
297 $this->drupalGet('node/' . $node->nid);
|
danielebarchiesi@2
|
298 $this->assertNoText($comment_subject, $message .' Comment should not show up on node page.', 'CAPTCHA');
|
danielebarchiesi@2
|
299 $this->assertNoText($comment_body, $message . ' Comment should not show up on node page.', 'CAPTCHA');
|
danielebarchiesi@2
|
300 }
|
danielebarchiesi@2
|
301 }
|
danielebarchiesi@2
|
302
|
danielebarchiesi@2
|
303 /*
|
danielebarchiesi@2
|
304 * Testing the case sensistive/insensitive validation.
|
danielebarchiesi@2
|
305 */
|
danielebarchiesi@2
|
306 function testCaseInsensitiveValidation() {
|
danielebarchiesi@2
|
307 // Set Test CAPTCHA on comment form
|
danielebarchiesi@2
|
308 captcha_set_form_id_setting(self::COMMENT_FORM_ID, 'captcha/Test');
|
danielebarchiesi@2
|
309
|
danielebarchiesi@2
|
310 // Log in as normal user.
|
danielebarchiesi@2
|
311 $this->drupalLogin($this->normal_user);
|
danielebarchiesi@2
|
312
|
danielebarchiesi@2
|
313 // Test case sensitive posting.
|
danielebarchiesi@2
|
314 variable_set('captcha_default_validation', CAPTCHA_DEFAULT_VALIDATION_CASE_SENSITIVE);
|
danielebarchiesi@2
|
315 $this->assertCommentPosting('Test 123', TRUE, 'Case sensitive validation of right casing.');
|
danielebarchiesi@2
|
316 $this->assertCommentPosting('test 123', FALSE, 'Case sensitive validation of wrong casing.');
|
danielebarchiesi@2
|
317 $this->assertCommentPosting('TEST 123', FALSE, 'Case sensitive validation of wrong casing.');
|
danielebarchiesi@2
|
318
|
danielebarchiesi@2
|
319 // Test case insensitive posting (the default)
|
danielebarchiesi@2
|
320 variable_set('captcha_default_validation', CAPTCHA_DEFAULT_VALIDATION_CASE_INSENSITIVE);
|
danielebarchiesi@2
|
321 $this->assertCommentPosting('Test 123', TRUE, 'Case insensitive validation of right casing.');
|
danielebarchiesi@2
|
322 $this->assertCommentPosting('test 123', TRUE, 'Case insensitive validation of wrong casing.');
|
danielebarchiesi@2
|
323 $this->assertCommentPosting('TEST 123', TRUE, 'Case insensitive validation of wrong casing.');
|
danielebarchiesi@2
|
324
|
danielebarchiesi@2
|
325 }
|
danielebarchiesi@2
|
326
|
danielebarchiesi@2
|
327 /**
|
danielebarchiesi@2
|
328 * Test if the CAPTCHA description is only shown if there are challenge widgets to show.
|
danielebarchiesi@2
|
329 * For example, when a comment is previewed with correct CAPTCHA answer,
|
danielebarchiesi@2
|
330 * a challenge is generated and added to the form but removed in the pre_render phase.
|
danielebarchiesi@2
|
331 * The CAPTCHA description should not show up either.
|
danielebarchiesi@2
|
332 *
|
danielebarchiesi@2
|
333 * \see testCaptchaSessionReuseOnNodeForms()
|
danielebarchiesi@2
|
334 */
|
danielebarchiesi@2
|
335 function testCaptchaDescriptionAfterCommentPreview() {
|
danielebarchiesi@2
|
336 // Set Test CAPTCHA on comment form.
|
danielebarchiesi@2
|
337 captcha_set_form_id_setting(self::COMMENT_FORM_ID, 'captcha/Test');
|
danielebarchiesi@2
|
338
|
danielebarchiesi@2
|
339 // Log in as normal user.
|
danielebarchiesi@2
|
340 $this->drupalLogin($this->normal_user);
|
danielebarchiesi@2
|
341
|
danielebarchiesi@2
|
342 // Create a node with comments enabled.
|
danielebarchiesi@2
|
343 $node = $this->createNodeWithCommentsEnabled();
|
danielebarchiesi@2
|
344
|
danielebarchiesi@2
|
345 // Preview comment with correct CAPTCHA answer.
|
danielebarchiesi@2
|
346 $edit = $this->getCommentFormValues();
|
danielebarchiesi@2
|
347 $edit['captcha_response'] = 'Test 123';
|
danielebarchiesi@2
|
348 $this->drupalPost('comment/reply/' . $node->nid, $edit, t('Preview'));
|
danielebarchiesi@2
|
349
|
danielebarchiesi@2
|
350 // Check that there is no CAPTCHA after preview.
|
danielebarchiesi@2
|
351 $this->assertCaptchaPresence(FALSE);
|
danielebarchiesi@2
|
352 }
|
danielebarchiesi@2
|
353
|
danielebarchiesi@2
|
354 /**
|
danielebarchiesi@2
|
355 * Test if the CAPTCHA session ID is reused when previewing nodes:
|
danielebarchiesi@2
|
356 * node preview after correct response should not show CAPTCHA anymore.
|
danielebarchiesi@2
|
357 * The preview functionality of comments and nodes works slightly different under the hood.
|
danielebarchiesi@2
|
358 * CAPTCHA module should be able to handle both.
|
danielebarchiesi@2
|
359 *
|
danielebarchiesi@2
|
360 * \see testCaptchaDescriptionAfterCommentPreview()
|
danielebarchiesi@2
|
361 */
|
danielebarchiesi@2
|
362 function testCaptchaSessionReuseOnNodeForms() {
|
danielebarchiesi@2
|
363 // Set Test CAPTCHA on page form.
|
danielebarchiesi@2
|
364 captcha_set_form_id_setting('page_node_form', 'captcha/Test');
|
danielebarchiesi@2
|
365
|
danielebarchiesi@2
|
366 // Log in as normal user.
|
danielebarchiesi@2
|
367 $this->drupalLogin($this->normal_user);
|
danielebarchiesi@2
|
368
|
danielebarchiesi@2
|
369 // Page settings to post, with correct CAPTCHA answer.
|
danielebarchiesi@2
|
370 $edit = $this->getNodeFormValues();
|
danielebarchiesi@2
|
371 $edit['captcha_response'] = 'Test 123';
|
danielebarchiesi@2
|
372 // Preview the node
|
danielebarchiesi@2
|
373 $this->drupalPost('node/add/page', $edit, t('Preview'));
|
danielebarchiesi@2
|
374
|
danielebarchiesi@2
|
375 // Check that there is no CAPTCHA after preview.
|
danielebarchiesi@2
|
376 $this->assertCaptchaPresence(FALSE);
|
danielebarchiesi@2
|
377 }
|
danielebarchiesi@2
|
378
|
danielebarchiesi@2
|
379
|
danielebarchiesi@2
|
380 /**
|
danielebarchiesi@2
|
381 * CAPTCHA should also be put on admin pages even if visitor
|
danielebarchiesi@2
|
382 * has no access
|
danielebarchiesi@2
|
383 */
|
danielebarchiesi@2
|
384 function testCaptchaOnLoginBlockOnAdminPagesIssue893810() {
|
danielebarchiesi@2
|
385 // Set a CAPTCHA on login block form
|
danielebarchiesi@2
|
386 captcha_set_form_id_setting('user_login_block', 'captcha/Math');
|
danielebarchiesi@2
|
387
|
danielebarchiesi@2
|
388 // Check if there is a CAPTCHA on home page.
|
danielebarchiesi@2
|
389 $this->drupalGet('node');
|
danielebarchiesi@2
|
390 $this->assertCaptchaPresence(TRUE);
|
danielebarchiesi@2
|
391
|
danielebarchiesi@2
|
392 // Check there is a CAPTCHA on "forbidden" admin pages
|
danielebarchiesi@2
|
393 $this->drupalGet('admin');
|
danielebarchiesi@2
|
394 $this->assertCaptchaPresence(TRUE);
|
danielebarchiesi@2
|
395 }
|
danielebarchiesi@2
|
396
|
danielebarchiesi@2
|
397 }
|
danielebarchiesi@2
|
398
|
danielebarchiesi@2
|
399
|
danielebarchiesi@2
|
400 class CaptchaAdminTestCase extends CaptchaBaseWebTestCase {
|
danielebarchiesi@2
|
401
|
danielebarchiesi@2
|
402 public static function getInfo() {
|
danielebarchiesi@2
|
403 return array(
|
danielebarchiesi@2
|
404 'name' => t('CAPTCHA administration functionality'),
|
danielebarchiesi@2
|
405 'description' => t('Testing of the CAPTCHA administration interface and functionality.'),
|
danielebarchiesi@2
|
406 'group' => t('CAPTCHA'),
|
danielebarchiesi@2
|
407 );
|
danielebarchiesi@2
|
408 }
|
danielebarchiesi@2
|
409
|
danielebarchiesi@2
|
410 /**
|
danielebarchiesi@2
|
411 * Test access to the admin pages.
|
danielebarchiesi@2
|
412 */
|
danielebarchiesi@2
|
413 function testAdminAccess() {
|
danielebarchiesi@2
|
414 $this->drupalLogin($this->normal_user);
|
danielebarchiesi@2
|
415 $this->drupalGet(self::CAPTCHA_ADMIN_PATH);
|
danielebarchiesi@2
|
416 file_put_contents('tmp.simpletest.html', $this->drupalGetContent());
|
danielebarchiesi@2
|
417 $this->assertText(t('Access denied'), 'Normal users should not be able to access the CAPTCHA admin pages', 'CAPTCHA');
|
danielebarchiesi@2
|
418
|
danielebarchiesi@2
|
419 $this->drupalLogin($this->admin_user);
|
danielebarchiesi@2
|
420 $this->drupalGet(self::CAPTCHA_ADMIN_PATH);
|
danielebarchiesi@2
|
421 $this->assertNoText(t('Access denied'), 'Admin users should be able to access the CAPTCHA admin pages', 'CAPTCHA');
|
danielebarchiesi@2
|
422 }
|
danielebarchiesi@2
|
423
|
danielebarchiesi@2
|
424 /**
|
danielebarchiesi@2
|
425 * Test the CAPTCHA point setting getter/setter.
|
danielebarchiesi@2
|
426 */
|
danielebarchiesi@2
|
427 function testCaptchaPointSettingGetterAndSetter() {
|
danielebarchiesi@2
|
428 $comment_form_id = self::COMMENT_FORM_ID;
|
danielebarchiesi@2
|
429 // Set to 'none'.
|
danielebarchiesi@2
|
430 captcha_set_form_id_setting($comment_form_id, 'none');
|
danielebarchiesi@2
|
431 $result = captcha_get_form_id_setting($comment_form_id);
|
danielebarchiesi@2
|
432 $this->assertNotNull($result, 'Setting and getting CAPTCHA point: none', 'CAPTCHA');
|
danielebarchiesi@2
|
433 $this->assertNull($result->module, 'Setting and getting CAPTCHA point: none', 'CAPTCHA');
|
danielebarchiesi@2
|
434 $this->assertNull($result->captcha_type, 'Setting and getting CAPTCHA point: none', 'CAPTCHA');
|
danielebarchiesi@2
|
435 $result = captcha_get_form_id_setting($comment_form_id, TRUE);
|
danielebarchiesi@2
|
436 $this->assertEqual($result, 'none', 'Setting and symbolic getting CAPTCHA point: "none"', 'CAPTCHA');
|
danielebarchiesi@2
|
437 // Set to 'default'
|
danielebarchiesi@2
|
438 captcha_set_form_id_setting($comment_form_id, 'default');
|
danielebarchiesi@2
|
439 variable_set('captcha_default_challenge', 'foo/bar');
|
danielebarchiesi@2
|
440 $result = captcha_get_form_id_setting($comment_form_id);
|
danielebarchiesi@2
|
441 $this->assertNotNull($result, 'Setting and getting CAPTCHA point: default', 'CAPTCHA');
|
danielebarchiesi@2
|
442 $this->assertEqual($result->module, 'foo', 'Setting and getting CAPTCHA point: default', 'CAPTCHA');
|
danielebarchiesi@2
|
443 $this->assertEqual($result->captcha_type, 'bar', 'Setting and getting CAPTCHA point: default', 'CAPTCHA');
|
danielebarchiesi@2
|
444 $result = captcha_get_form_id_setting($comment_form_id, TRUE);
|
danielebarchiesi@2
|
445 $this->assertEqual($result, 'default', 'Setting and symbolic getting CAPTCHA point: "default"', 'CAPTCHA');
|
danielebarchiesi@2
|
446 // Set to 'baz/boo'.
|
danielebarchiesi@2
|
447 captcha_set_form_id_setting($comment_form_id, 'baz/boo');
|
danielebarchiesi@2
|
448 $result = captcha_get_form_id_setting($comment_form_id);
|
danielebarchiesi@2
|
449 $this->assertNotNull($result, 'Setting and getting CAPTCHA point: baz/boo', 'CAPTCHA');
|
danielebarchiesi@2
|
450 $this->assertEqual($result->module, 'baz', 'Setting and getting CAPTCHA point: baz/boo', 'CAPTCHA');
|
danielebarchiesi@2
|
451 $this->assertEqual($result->captcha_type, 'boo', 'Setting and getting CAPTCHA point: baz/boo', 'CAPTCHA');
|
danielebarchiesi@2
|
452 $result = captcha_get_form_id_setting($comment_form_id, TRUE);
|
danielebarchiesi@2
|
453 $this->assertEqual($result, 'baz/boo', 'Setting and symbolic getting CAPTCHA point: "baz/boo"', 'CAPTCHA');
|
danielebarchiesi@2
|
454 // Set to NULL (which should delete the CAPTCHA point setting entry).
|
danielebarchiesi@2
|
455 captcha_set_form_id_setting($comment_form_id, NULL);
|
danielebarchiesi@2
|
456 $result = captcha_get_form_id_setting($comment_form_id);
|
danielebarchiesi@2
|
457 $this->assertNull($result, 'Setting and getting CAPTCHA point: NULL', 'CAPTCHA');
|
danielebarchiesi@2
|
458 $result = captcha_get_form_id_setting($comment_form_id, TRUE);
|
danielebarchiesi@2
|
459 $this->assertNull($result, 'Setting and symbolic getting CAPTCHA point: NULL', 'CAPTCHA');
|
danielebarchiesi@2
|
460 // Set with object.
|
danielebarchiesi@2
|
461 $captcha_type = new stdClass;
|
danielebarchiesi@2
|
462 $captcha_type->module = 'baba';
|
danielebarchiesi@2
|
463 $captcha_type->captcha_type = 'fofo';
|
danielebarchiesi@2
|
464 captcha_set_form_id_setting($comment_form_id, $captcha_type);
|
danielebarchiesi@2
|
465 $result = captcha_get_form_id_setting($comment_form_id);
|
danielebarchiesi@2
|
466 $this->assertNotNull($result, 'Setting and getting CAPTCHA point: baba/fofo', 'CAPTCHA');
|
danielebarchiesi@2
|
467 $this->assertEqual($result->module, 'baba', 'Setting and getting CAPTCHA point: baba/fofo', 'CAPTCHA');
|
danielebarchiesi@2
|
468 $this->assertEqual($result->captcha_type, 'fofo', 'Setting and getting CAPTCHA point: baba/fofo', 'CAPTCHA');
|
danielebarchiesi@2
|
469 $result = captcha_get_form_id_setting($comment_form_id, TRUE);
|
danielebarchiesi@2
|
470 $this->assertEqual($result, 'baba/fofo', 'Setting and symbolic getting CAPTCHA point: "baba/fofo"', 'CAPTCHA');
|
danielebarchiesi@2
|
471
|
danielebarchiesi@2
|
472 }
|
danielebarchiesi@2
|
473
|
danielebarchiesi@2
|
474
|
danielebarchiesi@2
|
475 /**
|
danielebarchiesi@2
|
476 * Helper function for checking CAPTCHA setting of a form.
|
danielebarchiesi@2
|
477 *
|
danielebarchiesi@2
|
478 * @param $form_id the form_id of the form to investigate.
|
danielebarchiesi@2
|
479 * @param $challenge_type what the challenge type should be:
|
danielebarchiesi@2
|
480 * NULL, 'none', 'default' or something like 'captcha/Math'
|
danielebarchiesi@2
|
481 */
|
danielebarchiesi@2
|
482 protected function assertCaptchaSetting($form_id, $challenge_type) {
|
danielebarchiesi@2
|
483 $result = captcha_get_form_id_setting(self::COMMENT_FORM_ID, TRUE);
|
danielebarchiesi@2
|
484 $this->assertEqual($result, $challenge_type,
|
danielebarchiesi@2
|
485 t('Check CAPTCHA setting for form: expected: @expected, received: @received.',
|
danielebarchiesi@2
|
486 array('@expected' => var_export($challenge_type, TRUE), '@received' => var_export($result, TRUE))),
|
danielebarchiesi@2
|
487 'CAPTCHA');
|
danielebarchiesi@2
|
488 }
|
danielebarchiesi@2
|
489
|
danielebarchiesi@2
|
490 /**
|
danielebarchiesi@2
|
491 * Testing of the CAPTCHA administration links.
|
danielebarchiesi@2
|
492 */
|
danielebarchiesi@2
|
493 function testCaptchAdminLinks() {
|
danielebarchiesi@2
|
494 // Log in as admin
|
danielebarchiesi@2
|
495 $this->drupalLogin($this->admin_user);
|
danielebarchiesi@2
|
496
|
danielebarchiesi@2
|
497 // Enable CAPTCHA administration links.
|
danielebarchiesi@2
|
498 $edit = array(
|
danielebarchiesi@2
|
499 'captcha_administration_mode' => TRUE,
|
danielebarchiesi@2
|
500 );
|
danielebarchiesi@2
|
501 $this->drupalPost(self::CAPTCHA_ADMIN_PATH, $edit, 'Save configuration');
|
danielebarchiesi@2
|
502
|
danielebarchiesi@2
|
503 // Create a node with comments enabled.
|
danielebarchiesi@2
|
504 $node = $this->createNodeWithCommentsEnabled();
|
danielebarchiesi@2
|
505
|
danielebarchiesi@2
|
506 // Go to node page
|
danielebarchiesi@2
|
507 $this->drupalGet('node/' . $node->nid);
|
danielebarchiesi@2
|
508
|
danielebarchiesi@2
|
509 // Click the add new comment link
|
danielebarchiesi@2
|
510 $this->clickLink(t('Add new comment'));
|
danielebarchiesi@2
|
511 $add_comment_url = $this->getUrl();
|
danielebarchiesi@2
|
512 // Remove fragment part from comment URL to avoid problems with later asserts
|
danielebarchiesi@2
|
513 $add_comment_url = strtok($add_comment_url, "#");
|
danielebarchiesi@2
|
514
|
danielebarchiesi@2
|
515 ////////////////////////////////////////////////////////////
|
danielebarchiesi@2
|
516 // Click the CAPTCHA admin link to enable a challenge.
|
danielebarchiesi@2
|
517 $this->clickLink(t('Place a CAPTCHA here for untrusted users.'));
|
danielebarchiesi@2
|
518 // Enable Math CAPTCHA.
|
danielebarchiesi@2
|
519 $edit = array('captcha_type' => 'captcha/Math');
|
danielebarchiesi@2
|
520 $this->drupalPost($this->getUrl(), $edit, t('Save'));
|
danielebarchiesi@2
|
521
|
danielebarchiesi@2
|
522 // Check if returned to original comment form.
|
danielebarchiesi@2
|
523 $this->assertUrl($add_comment_url, array(),
|
danielebarchiesi@2
|
524 'After setting CAPTCHA with CAPTCHA admin links: should return to original form.', 'CAPTCHA');
|
danielebarchiesi@2
|
525 // Check if CAPTCHA was successfully enabled (on CAPTCHA admin links fieldset).
|
danielebarchiesi@2
|
526 $this->assertText(t('CAPTCHA: challenge "@type" enabled', array('@type' => 'Math')),
|
danielebarchiesi@2
|
527 'Enable a challenge through the CAPTCHA admin links', 'CAPTCHA');
|
danielebarchiesi@2
|
528 // Check if CAPTCHA was successfully enabled (through API).
|
danielebarchiesi@2
|
529 $this->assertCaptchaSetting(self::COMMENT_FORM_ID, 'captcha/Math');
|
danielebarchiesi@2
|
530
|
danielebarchiesi@2
|
531 //////////////////////////////////////////////////////
|
danielebarchiesi@2
|
532 // Edit challenge type through CAPTCHA admin links.
|
danielebarchiesi@2
|
533 $this->clickLink(t('change'));
|
danielebarchiesi@2
|
534 // Enable Math CAPTCHA.
|
danielebarchiesi@2
|
535 $edit = array('captcha_type' => 'default');
|
danielebarchiesi@2
|
536 $this->drupalPost($this->getUrl(), $edit, t('Save'));
|
danielebarchiesi@2
|
537
|
danielebarchiesi@2
|
538 // Check if returned to original comment form.
|
danielebarchiesi@2
|
539 $this->assertEqual($add_comment_url, $this->getUrl(),
|
danielebarchiesi@2
|
540 'After editing challenge type CAPTCHA admin links: should return to original form.', 'CAPTCHA');
|
danielebarchiesi@2
|
541 // Check if CAPTCHA was successfully changed (on CAPTCHA admin links fieldset).
|
danielebarchiesi@2
|
542 // This is actually the same as the previous setting because the captcha/Math is the
|
danielebarchiesi@2
|
543 // default for the default challenge. TODO Make sure the edit is a real change.
|
danielebarchiesi@2
|
544 $this->assertText(t('CAPTCHA: challenge "@type" enabled', array('@type' => 'Math')),
|
danielebarchiesi@2
|
545 'Enable a challenge through the CAPTCHA admin links', 'CAPTCHA');
|
danielebarchiesi@2
|
546 // Check if CAPTCHA was successfully edited (through API).
|
danielebarchiesi@2
|
547 $this->assertCaptchaSetting(self::COMMENT_FORM_ID, 'default');
|
danielebarchiesi@2
|
548
|
danielebarchiesi@2
|
549
|
danielebarchiesi@2
|
550
|
danielebarchiesi@2
|
551 //////////////////////////////////////////////////////
|
danielebarchiesi@2
|
552 // Disable challenge through CAPTCHA admin links.
|
danielebarchiesi@2
|
553 $this->clickLink(t('disable'));
|
danielebarchiesi@2
|
554 // And confirm.
|
danielebarchiesi@2
|
555 $this->drupalPost($this->getUrl(), array(), 'Disable');
|
danielebarchiesi@2
|
556
|
danielebarchiesi@2
|
557 // Check if returned to original comment form.
|
danielebarchiesi@2
|
558 $this->assertEqual($add_comment_url, $this->getUrl(),
|
danielebarchiesi@2
|
559 'After disablin challenge with CAPTCHA admin links: should return to original form.', 'CAPTCHA');
|
danielebarchiesi@2
|
560 // Check if CAPTCHA was successfully disabled (on CAPTCHA admin links fieldset).
|
danielebarchiesi@2
|
561 $this->assertText(t('CAPTCHA: no challenge enabled'),
|
danielebarchiesi@2
|
562 'Disable challenge through the CAPTCHA admin links', 'CAPTCHA');
|
danielebarchiesi@2
|
563 // Check if CAPTCHA was successfully disabled (through API).
|
danielebarchiesi@2
|
564 $this->assertCaptchaSetting(self::COMMENT_FORM_ID, 'none');
|
danielebarchiesi@2
|
565
|
danielebarchiesi@2
|
566 }
|
danielebarchiesi@2
|
567
|
danielebarchiesi@2
|
568
|
danielebarchiesi@2
|
569 function testUntrustedUserPosting() {
|
danielebarchiesi@2
|
570 // Set CAPTCHA on comment form.
|
danielebarchiesi@2
|
571 captcha_set_form_id_setting(self::COMMENT_FORM_ID, 'captcha/Math');
|
danielebarchiesi@2
|
572
|
danielebarchiesi@2
|
573 // Create a node with comments enabled.
|
danielebarchiesi@2
|
574 $node = $this->createNodeWithCommentsEnabled();
|
danielebarchiesi@2
|
575
|
danielebarchiesi@2
|
576 // Log in as normal (untrusted) user.
|
danielebarchiesi@2
|
577 $this->drupalLogin($this->normal_user);
|
danielebarchiesi@2
|
578
|
danielebarchiesi@2
|
579 // Go to node page and click the "add comment" link.
|
danielebarchiesi@2
|
580 $this->drupalGet('node/' . $node->nid);
|
danielebarchiesi@2
|
581 $this->clickLink(t('Add new comment'));
|
danielebarchiesi@2
|
582 $add_comment_url = $this->getUrl();
|
danielebarchiesi@2
|
583
|
danielebarchiesi@2
|
584 // Check if CAPTCHA is visible on form.
|
danielebarchiesi@2
|
585 $this->assertCaptchaPresence(TRUE);
|
danielebarchiesi@2
|
586 // Try to post a comment with wrong answer.
|
danielebarchiesi@2
|
587 $edit = $this->getCommentFormValues();
|
danielebarchiesi@2
|
588 $edit['captcha_response'] = 'xx';
|
danielebarchiesi@2
|
589 $this->drupalPost($add_comment_url, $edit, t('Preview'));
|
danielebarchiesi@2
|
590 $this->assertText(t(CAPTCHA_WRONG_RESPONSE_ERROR_MESSAGE),
|
danielebarchiesi@2
|
591 'wrong CAPTCHA should block form submission.', 'CAPTCHA');
|
danielebarchiesi@2
|
592
|
danielebarchiesi@2
|
593 //TODO: more testing for untrusted posts.
|
danielebarchiesi@2
|
594 }
|
danielebarchiesi@2
|
595
|
danielebarchiesi@2
|
596
|
danielebarchiesi@2
|
597
|
danielebarchiesi@2
|
598 /**
|
danielebarchiesi@2
|
599 * Test XSS vulnerability on CAPTCHA description.
|
danielebarchiesi@2
|
600 */
|
danielebarchiesi@2
|
601 function testXssOnCaptchaDescription() {
|
danielebarchiesi@2
|
602 // Set CAPTCHA on user register form.
|
danielebarchiesi@2
|
603 captcha_set_form_id_setting('user_register', 'captcha/Math');
|
danielebarchiesi@2
|
604
|
danielebarchiesi@2
|
605 // Put Javascript snippet in CAPTCHA description.
|
danielebarchiesi@2
|
606 $this->drupalLogin($this->admin_user);
|
danielebarchiesi@2
|
607 $xss = '<script type="text/javascript">alert("xss")</script>';
|
danielebarchiesi@2
|
608 $edit = array('captcha_description' => $xss);
|
danielebarchiesi@2
|
609 $this->drupalPost(self::CAPTCHA_ADMIN_PATH, $edit, 'Save configuration');
|
danielebarchiesi@2
|
610
|
danielebarchiesi@2
|
611 // Visit user register form and check if Javascript snippet is there.
|
danielebarchiesi@2
|
612 $this->drupalLogout();
|
danielebarchiesi@2
|
613 $this->drupalGet('user/register');
|
danielebarchiesi@2
|
614 $this->assertNoRaw($xss, 'Javascript should not be allowed in CAPTCHA description.', 'CAPTCHA');
|
danielebarchiesi@2
|
615
|
danielebarchiesi@2
|
616 }
|
danielebarchiesi@2
|
617
|
danielebarchiesi@2
|
618 /**
|
danielebarchiesi@2
|
619 * Test the CAPTCHA placement clearing.
|
danielebarchiesi@2
|
620 */
|
danielebarchiesi@2
|
621 function testCaptchaPlacementCacheClearing() {
|
danielebarchiesi@2
|
622 // Set CAPTCHA on user register form.
|
danielebarchiesi@2
|
623 captcha_set_form_id_setting('user_register_form', 'captcha/Math');
|
danielebarchiesi@2
|
624 // Visit user register form to fill the CAPTCHA placement cache.
|
danielebarchiesi@2
|
625 $this->drupalGet('user/register');
|
danielebarchiesi@2
|
626 // Check if there is CAPTCHA placement cache.
|
danielebarchiesi@2
|
627 $placement_map = variable_get('captcha_placement_map_cache', NULL);
|
danielebarchiesi@2
|
628 $this->assertNotNull($placement_map, 'CAPTCHA placement cache should be set.');
|
danielebarchiesi@2
|
629 // Clear the cache
|
danielebarchiesi@2
|
630 $this->drupalLogin($this->admin_user);
|
danielebarchiesi@2
|
631 $this->drupalPost(self::CAPTCHA_ADMIN_PATH, array(), t('Clear the CAPTCHA placement cache'));
|
danielebarchiesi@2
|
632 // Check that the placement cache is unset
|
danielebarchiesi@2
|
633 $placement_map = variable_get('captcha_placement_map_cache', NULL);
|
danielebarchiesi@2
|
634 $this->assertNull($placement_map, 'CAPTCHA placement cache should be unset after cache clear.');
|
danielebarchiesi@2
|
635 }
|
danielebarchiesi@2
|
636
|
danielebarchiesi@2
|
637 /**
|
danielebarchiesi@2
|
638 * Helper function to get the CAPTCHA point setting straight from the database.
|
danielebarchiesi@2
|
639 * @param string $form_id
|
danielebarchiesi@2
|
640 * @return stdClass object
|
danielebarchiesi@2
|
641 */
|
danielebarchiesi@2
|
642 private function getCaptchaPointSettingFromDatabase($form_id) {
|
danielebarchiesi@2
|
643 $result = db_query(
|
danielebarchiesi@2
|
644 "SELECT * FROM {captcha_points} WHERE form_id = :form_id",
|
danielebarchiesi@2
|
645 array(':form_id' => $form_id)
|
danielebarchiesi@2
|
646 )->fetchObject();
|
danielebarchiesi@2
|
647 return $result;
|
danielebarchiesi@2
|
648 }
|
danielebarchiesi@2
|
649
|
danielebarchiesi@2
|
650 /**
|
danielebarchiesi@2
|
651 * Method for testing the CAPTCHA point administration
|
danielebarchiesi@2
|
652 */
|
danielebarchiesi@2
|
653 function testCaptchaPointAdministration() {
|
danielebarchiesi@2
|
654 // Generate CAPTCHA point data:
|
danielebarchiesi@2
|
655 // Drupal form ID should consist of lowercase alphanumerics and underscore)
|
danielebarchiesi@2
|
656 $captcha_point_form_id = 'form_' . strtolower($this->randomName(32));
|
danielebarchiesi@2
|
657 // the Math CAPTCHA by the CAPTCHA module is always available, so let's use it
|
danielebarchiesi@2
|
658 $captcha_point_module = 'captcha';
|
danielebarchiesi@2
|
659 $captcha_point_type = 'Math';
|
danielebarchiesi@2
|
660
|
danielebarchiesi@2
|
661 // Log in as admin
|
danielebarchiesi@2
|
662 $this->drupalLogin($this->admin_user);
|
danielebarchiesi@2
|
663
|
danielebarchiesi@2
|
664 // Set CAPTCHA point through admin/user/captcha/captcha/captcha_point
|
danielebarchiesi@2
|
665 $form_values = array(
|
danielebarchiesi@2
|
666 'captcha_point_form_id' => $captcha_point_form_id,
|
danielebarchiesi@2
|
667 'captcha_type' => $captcha_point_module .'/'. $captcha_point_type,
|
danielebarchiesi@2
|
668 );
|
danielebarchiesi@2
|
669 $this->drupalPost(self::CAPTCHA_ADMIN_PATH . '/captcha/captcha_point', $form_values, t('Save'));
|
danielebarchiesi@2
|
670 $this->assertText(t('Saved CAPTCHA point settings.'),
|
danielebarchiesi@2
|
671 'Saving of CAPTCHA point settings');
|
danielebarchiesi@2
|
672
|
danielebarchiesi@2
|
673 // Check in database
|
danielebarchiesi@2
|
674 $result = $this->getCaptchaPointSettingFromDatabase($captcha_point_form_id);
|
danielebarchiesi@2
|
675 $this->assertEqual($result->module, $captcha_point_module,
|
danielebarchiesi@2
|
676 'Enabled CAPTCHA point should have module set');
|
danielebarchiesi@2
|
677 $this->assertEqual($result->captcha_type, $captcha_point_type,
|
danielebarchiesi@2
|
678 'Enabled CAPTCHA point should have type set');
|
danielebarchiesi@2
|
679
|
danielebarchiesi@2
|
680 // Disable CAPTCHA point again
|
danielebarchiesi@2
|
681 $this->drupalPost(self::CAPTCHA_ADMIN_PATH . '/captcha/captcha_point/'. $captcha_point_form_id .'/disable', array(), t('Disable'));
|
danielebarchiesi@2
|
682 $this->assertRaw(t('Disabled CAPTCHA for form %form_id.', array('%form_id' => $captcha_point_form_id)), 'Disabling of CAPTCHA point');
|
danielebarchiesi@2
|
683
|
danielebarchiesi@2
|
684 // Check in database
|
danielebarchiesi@2
|
685 $result = $this->getCaptchaPointSettingFromDatabase($captcha_point_form_id);
|
danielebarchiesi@2
|
686 $this->assertNull($result->module,
|
danielebarchiesi@2
|
687 'Disabled CAPTCHA point should have NULL as module');
|
danielebarchiesi@2
|
688 $this->assertNull($result->captcha_type,
|
danielebarchiesi@2
|
689 'Disabled CAPTCHA point should have NULL as type');
|
danielebarchiesi@2
|
690
|
danielebarchiesi@2
|
691 // Set CAPTCHA point through admin/user/captcha/captcha/captcha_point/$form_id
|
danielebarchiesi@2
|
692 $form_values = array(
|
danielebarchiesi@2
|
693 'captcha_type' => $captcha_point_module .'/'. $captcha_point_type,
|
danielebarchiesi@2
|
694 );
|
danielebarchiesi@2
|
695 $this->drupalPost(self::CAPTCHA_ADMIN_PATH . '/captcha/captcha_point/'. $captcha_point_form_id, $form_values, t('Save'));
|
danielebarchiesi@2
|
696 $this->assertText(t('Saved CAPTCHA point settings.'),
|
danielebarchiesi@2
|
697 'Saving of CAPTCHA point settings');
|
danielebarchiesi@2
|
698
|
danielebarchiesi@2
|
699 // Check in database
|
danielebarchiesi@2
|
700 $result = $this->getCaptchaPointSettingFromDatabase($captcha_point_form_id);
|
danielebarchiesi@2
|
701 $this->assertEqual($result->module, $captcha_point_module,
|
danielebarchiesi@2
|
702 'Enabled CAPTCHA point should have module set');
|
danielebarchiesi@2
|
703 $this->assertEqual($result->captcha_type, $captcha_point_type,
|
danielebarchiesi@2
|
704 'Enabled CAPTCHA point should have type set');
|
danielebarchiesi@2
|
705
|
danielebarchiesi@2
|
706 // Delete CAPTCHA point
|
danielebarchiesi@2
|
707 $this->drupalPost(self::CAPTCHA_ADMIN_PATH . '/captcha/captcha_point/'. $captcha_point_form_id .'/delete', array(), t('Delete'));
|
danielebarchiesi@2
|
708 $this->assertRaw(t('Deleted CAPTCHA for form %form_id.', array('%form_id' => $captcha_point_form_id)),
|
danielebarchiesi@2
|
709 'Deleting of CAPTCHA point');
|
danielebarchiesi@2
|
710
|
danielebarchiesi@2
|
711 // Check in database
|
danielebarchiesi@2
|
712 $result = $this->getCaptchaPointSettingFromDatabase($captcha_point_form_id);
|
danielebarchiesi@2
|
713 $this->assertFalse($result, 'Deleted CAPTCHA point should be in database');
|
danielebarchiesi@2
|
714 }
|
danielebarchiesi@2
|
715
|
danielebarchiesi@2
|
716 /**
|
danielebarchiesi@2
|
717 * Method for testing the CAPTCHA point administration
|
danielebarchiesi@2
|
718 */
|
danielebarchiesi@2
|
719 function testCaptchaPointAdministrationByNonAdmin() {
|
danielebarchiesi@2
|
720 // First add a CAPTCHA point (as admin)
|
danielebarchiesi@2
|
721 $this->drupalLogin($this->admin_user);
|
danielebarchiesi@2
|
722 $captcha_point_form_id = 'form_' . strtolower($this->randomName(32));
|
danielebarchiesi@2
|
723 $captcha_point_module = 'captcha';
|
danielebarchiesi@2
|
724 $captcha_point_type = 'Math';
|
danielebarchiesi@2
|
725 $form_values = array(
|
danielebarchiesi@2
|
726 'captcha_point_form_id' => $captcha_point_form_id,
|
danielebarchiesi@2
|
727 'captcha_type' => $captcha_point_module .'/'. $captcha_point_type,
|
danielebarchiesi@2
|
728 );
|
danielebarchiesi@2
|
729 $this->drupalPost(self::CAPTCHA_ADMIN_PATH . '/captcha/captcha_point/', $form_values, t('Save'));
|
danielebarchiesi@2
|
730 $this->assertText(t('Saved CAPTCHA point settings.'),
|
danielebarchiesi@2
|
731 'Saving of CAPTCHA point settings');
|
danielebarchiesi@2
|
732
|
danielebarchiesi@2
|
733 // Switch from admin to nonadmin
|
danielebarchiesi@2
|
734 $this->drupalGet(url('logout', array('absolute' => TRUE)));
|
danielebarchiesi@2
|
735 $this->drupalLogin($this->normal_user);
|
danielebarchiesi@2
|
736
|
danielebarchiesi@2
|
737
|
danielebarchiesi@2
|
738 // Try to set CAPTCHA point through admin/user/captcha/captcha/captcha_point
|
danielebarchiesi@2
|
739 $this->drupalGet(self::CAPTCHA_ADMIN_PATH . '/captcha/captcha_point');
|
danielebarchiesi@2
|
740 $this->assertText(t('You are not authorized to access this page.'),
|
danielebarchiesi@2
|
741 'Non admin should not be able to set a CAPTCHA point');
|
danielebarchiesi@2
|
742
|
danielebarchiesi@2
|
743 // Try to set CAPTCHA point through admin/user/captcha/captcha/captcha_point/$form_id
|
danielebarchiesi@2
|
744 $this->drupalGet(self::CAPTCHA_ADMIN_PATH . '/captcha/captcha_point/' . 'form_' . strtolower($this->randomName(32)));
|
danielebarchiesi@2
|
745 $this->assertText(t('You are not authorized to access this page.'),
|
danielebarchiesi@2
|
746 'Non admin should not be able to set a CAPTCHA point');
|
danielebarchiesi@2
|
747
|
danielebarchiesi@2
|
748 // Try to disable the CAPTCHA point
|
danielebarchiesi@2
|
749 $this->drupalGet(self::CAPTCHA_ADMIN_PATH . '/captcha/captcha_point/'. $captcha_point_form_id .'/disable');
|
danielebarchiesi@2
|
750 $this->assertText(t('You are not authorized to access this page.'),
|
danielebarchiesi@2
|
751 'Non admin should not be able to disable a CAPTCHA point');
|
danielebarchiesi@2
|
752
|
danielebarchiesi@2
|
753 // Try to delete the CAPTCHA point
|
danielebarchiesi@2
|
754 $this->drupalGet(self::CAPTCHA_ADMIN_PATH . '/captcha/captcha_point/'. $captcha_point_form_id .'/delete');
|
danielebarchiesi@2
|
755 $this->assertText(t('You are not authorized to access this page.'),
|
danielebarchiesi@2
|
756 'Non admin should not be able to delete a CAPTCHA point');
|
danielebarchiesi@2
|
757
|
danielebarchiesi@2
|
758 // Switch from nonadmin to admin again
|
danielebarchiesi@2
|
759 $this->drupalGet(url('logout', array('absolute' => TRUE)));
|
danielebarchiesi@2
|
760 $this->drupalLogin($this->admin_user);
|
danielebarchiesi@2
|
761
|
danielebarchiesi@2
|
762 // Check if original CAPTCHA point still exists in database
|
danielebarchiesi@2
|
763 $result = $this->getCaptchaPointSettingFromDatabase($captcha_point_form_id);
|
danielebarchiesi@2
|
764 $this->assertEqual($result->module, $captcha_point_module,
|
danielebarchiesi@2
|
765 'Enabled CAPTCHA point should still have module set');
|
danielebarchiesi@2
|
766 $this->assertEqual($result->captcha_type, $captcha_point_type,
|
danielebarchiesi@2
|
767 'Enabled CAPTCHA point should still have type set');
|
danielebarchiesi@2
|
768
|
danielebarchiesi@2
|
769 // Delete CAPTCHA point
|
danielebarchiesi@2
|
770 $this->drupalPost(self::CAPTCHA_ADMIN_PATH . '/captcha/captcha_point/'. $captcha_point_form_id .'/delete', array(), t('Delete'));
|
danielebarchiesi@2
|
771 $this->assertRaw(t('Deleted CAPTCHA for form %form_id.', array('%form_id' => $captcha_point_form_id)),
|
danielebarchiesi@2
|
772 'Deleting of CAPTCHA point');
|
danielebarchiesi@2
|
773 }
|
danielebarchiesi@2
|
774
|
danielebarchiesi@2
|
775
|
danielebarchiesi@2
|
776
|
danielebarchiesi@2
|
777 }
|
danielebarchiesi@2
|
778
|
danielebarchiesi@2
|
779
|
danielebarchiesi@2
|
780
|
danielebarchiesi@2
|
781 class CaptchaPersistenceTestCase extends CaptchaBaseWebTestCase {
|
danielebarchiesi@2
|
782
|
danielebarchiesi@2
|
783 public static function getInfo() {
|
danielebarchiesi@2
|
784 return array(
|
danielebarchiesi@2
|
785 'name' => t('CAPTCHA persistence functionality'),
|
danielebarchiesi@2
|
786 'description' => t('Testing of the CAPTCHA persistence functionality.'),
|
danielebarchiesi@2
|
787 'group' => t('CAPTCHA'),
|
danielebarchiesi@2
|
788 );
|
danielebarchiesi@2
|
789 }
|
danielebarchiesi@2
|
790
|
danielebarchiesi@2
|
791 /**
|
danielebarchiesi@2
|
792 * Set up the persistence and CAPTCHA settings.
|
danielebarchiesi@2
|
793 * @param int $persistence the persistence value.
|
danielebarchiesi@2
|
794 */
|
danielebarchiesi@2
|
795 private function setUpPersistence($persistence) {
|
danielebarchiesi@2
|
796 // Log in as admin
|
danielebarchiesi@2
|
797 $this->drupalLogin($this->admin_user);
|
danielebarchiesi@2
|
798 // Set persistence.
|
danielebarchiesi@2
|
799 $edit = array('captcha_persistence' => $persistence);
|
danielebarchiesi@2
|
800 $this->drupalPost(self::CAPTCHA_ADMIN_PATH, $edit, 'Save configuration');
|
danielebarchiesi@2
|
801 // Log admin out.
|
danielebarchiesi@2
|
802 $this->drupalLogout();
|
danielebarchiesi@2
|
803
|
danielebarchiesi@2
|
804 // Set the Test123 CAPTCHA on user register and comment form.
|
danielebarchiesi@2
|
805 // We have to do this with the function captcha_set_form_id_setting()
|
danielebarchiesi@2
|
806 // (because the CATCHA admin form does not show the Test123 option).
|
danielebarchiesi@2
|
807 // We also have to do this after all usage of the CAPTCHA admin form
|
danielebarchiesi@2
|
808 // (because posting the CAPTCHA admin form would set the CAPTCHA to 'none').
|
danielebarchiesi@2
|
809 captcha_set_form_id_setting('user_login', 'captcha/Test');
|
danielebarchiesi@2
|
810 $this->drupalGet('user');
|
danielebarchiesi@2
|
811 $this->assertCaptchaPresence(TRUE);
|
danielebarchiesi@2
|
812 captcha_set_form_id_setting('user_register_form', 'captcha/Test');
|
danielebarchiesi@2
|
813 $this->drupalGet('user/register');
|
danielebarchiesi@2
|
814 $this->assertCaptchaPresence(TRUE);
|
danielebarchiesi@2
|
815 }
|
danielebarchiesi@2
|
816
|
danielebarchiesi@2
|
817 protected function assertPreservedCsid($captcha_sid_initial) {
|
danielebarchiesi@2
|
818 $captcha_sid = $this->getCaptchaSidFromForm();
|
danielebarchiesi@2
|
819 $this->assertEqual($captcha_sid_initial, $captcha_sid,
|
danielebarchiesi@2
|
820 "CAPTCHA session ID should be preserved (expected: $captcha_sid_initial, found: $captcha_sid).");
|
danielebarchiesi@2
|
821 }
|
danielebarchiesi@2
|
822
|
danielebarchiesi@2
|
823 protected function assertDifferentCsid($captcha_sid_initial) {
|
danielebarchiesi@2
|
824 $captcha_sid = $this->getCaptchaSidFromForm();
|
danielebarchiesi@2
|
825 $this->assertNotEqual($captcha_sid_initial, $captcha_sid,
|
danielebarchiesi@2
|
826 "CAPTCHA session ID should be different.");
|
danielebarchiesi@2
|
827 }
|
danielebarchiesi@2
|
828
|
danielebarchiesi@2
|
829 function testPersistenceAlways(){
|
danielebarchiesi@2
|
830 // Set up of persistence and CAPTCHAs.
|
danielebarchiesi@2
|
831 $this->setUpPersistence(CAPTCHA_PERSISTENCE_SHOW_ALWAYS);
|
danielebarchiesi@2
|
832
|
danielebarchiesi@2
|
833 // Go to login form and check if there is a CAPTCHA on the login form (look for the title).
|
danielebarchiesi@2
|
834 $this->drupalGet('user');
|
danielebarchiesi@2
|
835 $this->assertCaptchaPresence(TRUE);
|
danielebarchiesi@2
|
836 $captcha_sid_initial = $this->getCaptchaSidFromForm();
|
danielebarchiesi@2
|
837
|
danielebarchiesi@2
|
838 // Try to with wrong user name and password, but correct CAPTCHA.
|
danielebarchiesi@2
|
839 $edit = array(
|
danielebarchiesi@2
|
840 'name' => 'foobar',
|
danielebarchiesi@2
|
841 'pass' => 'bazlaz',
|
danielebarchiesi@2
|
842 'captcha_response' => 'Test 123',
|
danielebarchiesi@2
|
843 );
|
danielebarchiesi@2
|
844 $this->drupalPost(NULL, $edit, t('Log in'));
|
danielebarchiesi@2
|
845 // Check that there was no error message for the CAPTCHA.
|
danielebarchiesi@2
|
846 $this->assertCaptchaResponseAccepted();
|
danielebarchiesi@2
|
847
|
danielebarchiesi@2
|
848 // Name and password were wrong, we should get an updated form with a fresh CAPTCHA.
|
danielebarchiesi@2
|
849 $this->assertCaptchaPresence(TRUE);
|
danielebarchiesi@2
|
850 $this->assertPreservedCsid($captcha_sid_initial);
|
danielebarchiesi@2
|
851
|
danielebarchiesi@2
|
852 // Post from again.
|
danielebarchiesi@2
|
853 $this->drupalPost(NULL, $edit, t('Log in'));
|
danielebarchiesi@2
|
854 // Check that there was no error message for the CAPTCHA.
|
danielebarchiesi@2
|
855 $this->assertCaptchaResponseAccepted();
|
danielebarchiesi@2
|
856 $this->assertPreservedCsid($captcha_sid_initial);
|
danielebarchiesi@2
|
857
|
danielebarchiesi@2
|
858 }
|
danielebarchiesi@2
|
859
|
danielebarchiesi@2
|
860 function testPersistencePerFormInstance(){
|
danielebarchiesi@2
|
861 // Set up of persistence and CAPTCHAs.
|
danielebarchiesi@2
|
862 $this->setUpPersistence(CAPTCHA_PERSISTENCE_SKIP_ONCE_SUCCESSFUL_PER_FORM_INSTANCE);
|
danielebarchiesi@2
|
863
|
danielebarchiesi@2
|
864 // Go to login form and check if there is a CAPTCHA on the login form.
|
danielebarchiesi@2
|
865 $this->drupalGet('user');
|
danielebarchiesi@2
|
866 $this->assertCaptchaPresence(TRUE);
|
danielebarchiesi@2
|
867 $captcha_sid_initial = $this->getCaptchaSidFromForm();
|
danielebarchiesi@2
|
868
|
danielebarchiesi@2
|
869 // Try to with wrong user name and password, but correct CAPTCHA.
|
danielebarchiesi@2
|
870 $edit = array(
|
danielebarchiesi@2
|
871 'name' => 'foobar',
|
danielebarchiesi@2
|
872 'pass' => 'bazlaz',
|
danielebarchiesi@2
|
873 'captcha_response' => 'Test 123',
|
danielebarchiesi@2
|
874 );
|
danielebarchiesi@2
|
875 $this->drupalPost(NULL, $edit, t('Log in'));
|
danielebarchiesi@2
|
876 // Check that there was no error message for the CAPTCHA.
|
danielebarchiesi@2
|
877 $this->assertCaptchaResponseAccepted();
|
danielebarchiesi@2
|
878 // There shouldn't be a CAPTCHA on the new form.
|
danielebarchiesi@2
|
879 $this->assertCaptchaPresence(FALSE);
|
danielebarchiesi@2
|
880 $this->assertPreservedCsid($captcha_sid_initial);
|
danielebarchiesi@2
|
881
|
danielebarchiesi@2
|
882 // Start a new form instance/session
|
danielebarchiesi@2
|
883 $this->drupalGet('node');
|
danielebarchiesi@2
|
884 $this->drupalGet('user');
|
danielebarchiesi@2
|
885 $this->assertCaptchaPresence(TRUE);
|
danielebarchiesi@2
|
886 $this->assertDifferentCsid($captcha_sid_initial);
|
danielebarchiesi@2
|
887
|
danielebarchiesi@2
|
888 // Check another form
|
danielebarchiesi@2
|
889 $this->drupalGet('user/register');
|
danielebarchiesi@2
|
890 $this->assertCaptchaPresence(TRUE);
|
danielebarchiesi@2
|
891 $this->assertDifferentCsid($captcha_sid_initial);
|
danielebarchiesi@2
|
892
|
danielebarchiesi@2
|
893 }
|
danielebarchiesi@2
|
894
|
danielebarchiesi@2
|
895 function testPersistencePerFormType(){
|
danielebarchiesi@2
|
896 // Set up of persistence and CAPTCHAs.
|
danielebarchiesi@2
|
897 $this->setUpPersistence(CAPTCHA_PERSISTENCE_SKIP_ONCE_SUCCESSFUL_PER_FORM_TYPE);
|
danielebarchiesi@2
|
898
|
danielebarchiesi@2
|
899 // Go to login form and check if there is a CAPTCHA on the login form.
|
danielebarchiesi@2
|
900 $this->drupalGet('user');
|
danielebarchiesi@2
|
901 $this->assertCaptchaPresence(TRUE);
|
danielebarchiesi@2
|
902 $captcha_sid_initial = $this->getCaptchaSidFromForm();
|
danielebarchiesi@2
|
903
|
danielebarchiesi@2
|
904 // Try to with wrong user name and password, but correct CAPTCHA.
|
danielebarchiesi@2
|
905 $edit = array(
|
danielebarchiesi@2
|
906 'name' => 'foobar',
|
danielebarchiesi@2
|
907 'pass' => 'bazlaz',
|
danielebarchiesi@2
|
908 'captcha_response' => 'Test 123',
|
danielebarchiesi@2
|
909 );
|
danielebarchiesi@2
|
910 $this->drupalPost(NULL, $edit, t('Log in'));
|
danielebarchiesi@2
|
911 // Check that there was no error message for the CAPTCHA.
|
danielebarchiesi@2
|
912 $this->assertCaptchaResponseAccepted();
|
danielebarchiesi@2
|
913 // There shouldn't be a CAPTCHA on the new form.
|
danielebarchiesi@2
|
914 $this->assertCaptchaPresence(FALSE);
|
danielebarchiesi@2
|
915 $this->assertPreservedCsid($captcha_sid_initial);
|
danielebarchiesi@2
|
916
|
danielebarchiesi@2
|
917 // Start a new form instance/session
|
danielebarchiesi@2
|
918 $this->drupalGet('node');
|
danielebarchiesi@2
|
919 $this->drupalGet('user');
|
danielebarchiesi@2
|
920 $this->assertCaptchaPresence(FALSE);
|
danielebarchiesi@2
|
921 $this->assertDifferentCsid($captcha_sid_initial);
|
danielebarchiesi@2
|
922
|
danielebarchiesi@2
|
923 // Check another form
|
danielebarchiesi@2
|
924 $this->drupalGet('user/register');
|
danielebarchiesi@2
|
925 $this->assertCaptchaPresence(TRUE);
|
danielebarchiesi@2
|
926 $this->assertDifferentCsid($captcha_sid_initial);
|
danielebarchiesi@2
|
927 }
|
danielebarchiesi@2
|
928
|
danielebarchiesi@2
|
929 function testPersistenceOnlyOnce(){
|
danielebarchiesi@2
|
930 // Set up of persistence and CAPTCHAs.
|
danielebarchiesi@2
|
931 $this->setUpPersistence(CAPTCHA_PERSISTENCE_SKIP_ONCE_SUCCESSFUL);
|
danielebarchiesi@2
|
932
|
danielebarchiesi@2
|
933 // Go to login form and check if there is a CAPTCHA on the login form.
|
danielebarchiesi@2
|
934 $this->drupalGet('user');
|
danielebarchiesi@2
|
935 $this->assertCaptchaPresence(TRUE);
|
danielebarchiesi@2
|
936 $captcha_sid_initial = $this->getCaptchaSidFromForm();
|
danielebarchiesi@2
|
937
|
danielebarchiesi@2
|
938 // Try to with wrong user name and password, but correct CAPTCHA.
|
danielebarchiesi@2
|
939 $edit = array(
|
danielebarchiesi@2
|
940 'name' => 'foobar',
|
danielebarchiesi@2
|
941 'pass' => 'bazlaz',
|
danielebarchiesi@2
|
942 'captcha_response' => 'Test 123',
|
danielebarchiesi@2
|
943 );
|
danielebarchiesi@2
|
944 $this->drupalPost(NULL, $edit, t('Log in'));
|
danielebarchiesi@2
|
945 // Check that there was no error message for the CAPTCHA.
|
danielebarchiesi@2
|
946 $this->assertCaptchaResponseAccepted();
|
danielebarchiesi@2
|
947 // There shouldn't be a CAPTCHA on the new form.
|
danielebarchiesi@2
|
948 $this->assertCaptchaPresence(FALSE);
|
danielebarchiesi@2
|
949 $this->assertPreservedCsid($captcha_sid_initial);
|
danielebarchiesi@2
|
950
|
danielebarchiesi@2
|
951 // Start a new form instance/session
|
danielebarchiesi@2
|
952 $this->drupalGet('node');
|
danielebarchiesi@2
|
953 $this->drupalGet('user');
|
danielebarchiesi@2
|
954 $this->assertCaptchaPresence(FALSE);
|
danielebarchiesi@2
|
955 $this->assertDifferentCsid($captcha_sid_initial);
|
danielebarchiesi@2
|
956
|
danielebarchiesi@2
|
957 // Check another form
|
danielebarchiesi@2
|
958 $this->drupalGet('user/register');
|
danielebarchiesi@2
|
959 $this->assertCaptchaPresence(FALSE);
|
danielebarchiesi@2
|
960 $this->assertDifferentCsid($captcha_sid_initial);
|
danielebarchiesi@2
|
961 }
|
danielebarchiesi@2
|
962
|
danielebarchiesi@2
|
963 }
|
danielebarchiesi@2
|
964
|
danielebarchiesi@2
|
965
|
danielebarchiesi@2
|
966 class CaptchaSessionReuseAttackTestCase extends CaptchaBaseWebTestCase {
|
danielebarchiesi@2
|
967
|
danielebarchiesi@2
|
968 public static function getInfo() {
|
danielebarchiesi@2
|
969 return array(
|
danielebarchiesi@2
|
970 'name' => t('CAPTCHA session reuse attack tests'),
|
danielebarchiesi@2
|
971 'description' => t('Testing of the protection against CAPTCHA session reuse attacks.'),
|
danielebarchiesi@2
|
972 'group' => t('CAPTCHA'),
|
danielebarchiesi@2
|
973 );
|
danielebarchiesi@2
|
974 }
|
danielebarchiesi@2
|
975
|
danielebarchiesi@2
|
976 /**
|
danielebarchiesi@2
|
977 * Assert that the CAPTCHA session ID reuse attack was detected.
|
danielebarchiesi@2
|
978 */
|
danielebarchiesi@2
|
979 protected function assertCaptchaSessionIdReuseAttackDetection() {
|
danielebarchiesi@2
|
980 $this->assertText(t(CAPTCHA_SESSION_REUSE_ATTACK_ERROR_MESSAGE),
|
danielebarchiesi@2
|
981 'CAPTCHA session ID reuse attack should be detected.',
|
danielebarchiesi@2
|
982 'CAPTCHA');
|
danielebarchiesi@2
|
983 // There should be an error message about wrong response.
|
danielebarchiesi@2
|
984 $this->assertText(t(CAPTCHA_WRONG_RESPONSE_ERROR_MESSAGE),
|
danielebarchiesi@2
|
985 'CAPTCHA response should flagged as wrong.',
|
danielebarchiesi@2
|
986 'CAPTCHA');
|
danielebarchiesi@2
|
987 }
|
danielebarchiesi@2
|
988
|
danielebarchiesi@2
|
989 function testCaptchaSessionReuseAttackDetectionOnCommentPreview() {
|
danielebarchiesi@2
|
990 // Create commentable node
|
danielebarchiesi@2
|
991 $node = $this->createNodeWithCommentsEnabled();
|
danielebarchiesi@2
|
992 // Set Test CAPTCHA on comment form.
|
danielebarchiesi@2
|
993 captcha_set_form_id_setting(self::COMMENT_FORM_ID, 'captcha/Math');
|
danielebarchiesi@2
|
994 variable_set('captcha_persistence', CAPTCHA_PERSISTENCE_SKIP_ONCE_SUCCESSFUL_PER_FORM_INSTANCE);
|
danielebarchiesi@2
|
995
|
danielebarchiesi@2
|
996 // Log in as normal user.
|
danielebarchiesi@2
|
997 $this->drupalLogin($this->normal_user);
|
danielebarchiesi@2
|
998
|
danielebarchiesi@2
|
999 // Go to comment form of commentable node.
|
danielebarchiesi@2
|
1000 $this->drupalGet('comment/reply/' . $node->nid);
|
danielebarchiesi@2
|
1001 $this->assertCaptchaPresence(TRUE);
|
danielebarchiesi@2
|
1002
|
danielebarchiesi@2
|
1003 // Get CAPTCHA session ID and solution of the challenge.
|
danielebarchiesi@2
|
1004 $captcha_sid = $this->getCaptchaSidFromForm();
|
danielebarchiesi@2
|
1005 $captcha_token = $this->getCaptchaTokenFromForm();
|
danielebarchiesi@2
|
1006 $solution = $this->getMathCaptchaSolutionFromForm();
|
danielebarchiesi@2
|
1007
|
danielebarchiesi@2
|
1008 // Post the form with the solution.
|
danielebarchiesi@2
|
1009 $edit = $this->getCommentFormValues();
|
danielebarchiesi@2
|
1010 $edit['captcha_response'] = $solution;
|
danielebarchiesi@2
|
1011 $this->drupalPost(NULL, $edit, t('Preview'));
|
danielebarchiesi@2
|
1012 // Answer should be accepted and further CAPTCHA ommitted.
|
danielebarchiesi@2
|
1013 $this->assertCaptchaResponseAccepted();
|
danielebarchiesi@2
|
1014 $this->assertCaptchaPresence(FALSE);
|
danielebarchiesi@2
|
1015
|
danielebarchiesi@2
|
1016 // Post a new comment, reusing the previous CAPTCHA session.
|
danielebarchiesi@2
|
1017 $edit = $this->getCommentFormValues();
|
danielebarchiesi@2
|
1018 $edit['captcha_sid'] = $captcha_sid;
|
danielebarchiesi@2
|
1019 $edit['captcha_token'] = $captcha_token;
|
danielebarchiesi@2
|
1020 $edit['captcha_response'] = $solution;
|
danielebarchiesi@2
|
1021 $this->drupalPost('comment/reply/' . $node->nid, $edit, t('Preview'));
|
danielebarchiesi@2
|
1022 // CAPTCHA session reuse attack should be detected.
|
danielebarchiesi@2
|
1023 $this->assertCaptchaSessionIdReuseAttackDetection();
|
danielebarchiesi@2
|
1024 // There should be a CAPTCHA.
|
danielebarchiesi@2
|
1025 $this->assertCaptchaPresence(TRUE);
|
danielebarchiesi@2
|
1026
|
danielebarchiesi@2
|
1027 }
|
danielebarchiesi@2
|
1028
|
danielebarchiesi@2
|
1029 function testCaptchaSessionReuseAttackDetectionOnNodeForm() {
|
danielebarchiesi@2
|
1030 // Set CAPTCHA on page form.
|
danielebarchiesi@2
|
1031 captcha_set_form_id_setting('page_node_form', 'captcha/Math');
|
danielebarchiesi@2
|
1032 variable_set('captcha_persistence', CAPTCHA_PERSISTENCE_SKIP_ONCE_SUCCESSFUL_PER_FORM_INSTANCE);
|
danielebarchiesi@2
|
1033
|
danielebarchiesi@2
|
1034 // Log in as normal user.
|
danielebarchiesi@2
|
1035 $this->drupalLogin($this->normal_user);
|
danielebarchiesi@2
|
1036
|
danielebarchiesi@2
|
1037 // Go to node add form.
|
danielebarchiesi@2
|
1038 $this->drupalGet('node/add/page');
|
danielebarchiesi@2
|
1039 $this->assertCaptchaPresence(TRUE);
|
danielebarchiesi@2
|
1040
|
danielebarchiesi@2
|
1041 // Get CAPTCHA session ID and solution of the challenge.
|
danielebarchiesi@2
|
1042 $captcha_sid = $this->getCaptchaSidFromForm();
|
danielebarchiesi@2
|
1043 $captcha_token = $this->getCaptchaTokenFromForm();
|
danielebarchiesi@2
|
1044 $solution = $this->getMathCaptchaSolutionFromForm();
|
danielebarchiesi@2
|
1045
|
danielebarchiesi@2
|
1046 // Page settings to post, with correct CAPTCHA answer.
|
danielebarchiesi@2
|
1047 $edit = $this->getNodeFormValues();
|
danielebarchiesi@2
|
1048 $edit['captcha_response'] = $solution;
|
danielebarchiesi@2
|
1049 // Preview the node
|
danielebarchiesi@2
|
1050 $this->drupalPost(NULL, $edit, t('Preview'));
|
danielebarchiesi@2
|
1051 // Answer should be accepted.
|
danielebarchiesi@2
|
1052 $this->assertCaptchaResponseAccepted();
|
danielebarchiesi@2
|
1053 // Check that there is no CAPTCHA after preview.
|
danielebarchiesi@2
|
1054 $this->assertCaptchaPresence(FALSE);
|
danielebarchiesi@2
|
1055
|
danielebarchiesi@2
|
1056 // Post a new comment, reusing the previous CAPTCHA session.
|
danielebarchiesi@2
|
1057 $edit = $this->getNodeFormValues();
|
danielebarchiesi@2
|
1058 $edit['captcha_sid'] = $captcha_sid;
|
danielebarchiesi@2
|
1059 $edit['captcha_token'] = $captcha_token;
|
danielebarchiesi@2
|
1060 $edit['captcha_response'] = $solution;
|
danielebarchiesi@2
|
1061 $this->drupalPost('node/add/page', $edit, t('Preview'));
|
danielebarchiesi@2
|
1062 // CAPTCHA session reuse attack should be detected.
|
danielebarchiesi@2
|
1063 $this->assertCaptchaSessionIdReuseAttackDetection();
|
danielebarchiesi@2
|
1064 // There should be a CAPTCHA.
|
danielebarchiesi@2
|
1065 $this->assertCaptchaPresence(TRUE);
|
danielebarchiesi@2
|
1066
|
danielebarchiesi@2
|
1067 }
|
danielebarchiesi@2
|
1068
|
danielebarchiesi@2
|
1069 function testCaptchaSessionReuseAttackDetectionOnLoginForm() {
|
danielebarchiesi@2
|
1070 // Set CAPTCHA on login form.
|
danielebarchiesi@2
|
1071 captcha_set_form_id_setting('user_login', 'captcha/Math');
|
danielebarchiesi@2
|
1072 variable_set('captcha_persistence', CAPTCHA_PERSISTENCE_SKIP_ONCE_SUCCESSFUL_PER_FORM_INSTANCE);
|
danielebarchiesi@2
|
1073
|
danielebarchiesi@2
|
1074 // Go to log in form.
|
danielebarchiesi@2
|
1075 $this->drupalGet('user');
|
danielebarchiesi@2
|
1076 $this->assertCaptchaPresence(TRUE);
|
danielebarchiesi@2
|
1077
|
danielebarchiesi@2
|
1078 // Get CAPTCHA session ID and solution of the challenge.
|
danielebarchiesi@2
|
1079 $captcha_sid = $this->getCaptchaSidFromForm();
|
danielebarchiesi@2
|
1080 $captcha_token = $this->getCaptchaTokenFromForm();
|
danielebarchiesi@2
|
1081 $solution = $this->getMathCaptchaSolutionFromForm();
|
danielebarchiesi@2
|
1082
|
danielebarchiesi@2
|
1083 // Log in through form.
|
danielebarchiesi@2
|
1084 $edit = array(
|
danielebarchiesi@2
|
1085 'name' => $this->normal_user->name,
|
danielebarchiesi@2
|
1086 'pass' => $this->normal_user->pass_raw,
|
danielebarchiesi@2
|
1087 'captcha_response' => $solution,
|
danielebarchiesi@2
|
1088 );
|
danielebarchiesi@2
|
1089 $this->drupalPost(NULL, $edit, t('Log in'));
|
danielebarchiesi@2
|
1090 $this->assertCaptchaResponseAccepted();
|
danielebarchiesi@2
|
1091 $this->assertCaptchaPresence(FALSE);
|
danielebarchiesi@2
|
1092 // If a "log out" link appears on the page, it is almost certainly because
|
danielebarchiesi@2
|
1093 // the login was successful.
|
danielebarchiesi@2
|
1094 $pass = $this->assertLink(t('Log out'), 0, t('User %name successfully logged in.', array('%name' => $this->normal_user->name)), t('User login'));
|
danielebarchiesi@2
|
1095
|
danielebarchiesi@2
|
1096 // Log out again.
|
danielebarchiesi@2
|
1097 $this->drupalLogout();
|
danielebarchiesi@2
|
1098
|
danielebarchiesi@2
|
1099 // Try to log in again, reusing the previous CAPTCHA session.
|
danielebarchiesi@2
|
1100 $edit += array(
|
danielebarchiesi@2
|
1101 'captcha_sid' => $captcha_sid,
|
danielebarchiesi@2
|
1102 'captcha_token' => $captcha_token,
|
danielebarchiesi@2
|
1103 );
|
danielebarchiesi@2
|
1104 $this->drupalPost('user', $edit, t('Log in'));
|
danielebarchiesi@2
|
1105 // CAPTCHA session reuse attack should be detected.
|
danielebarchiesi@2
|
1106 $this->assertCaptchaSessionIdReuseAttackDetection();
|
danielebarchiesi@2
|
1107 // There should be a CAPTCHA.
|
danielebarchiesi@2
|
1108 $this->assertCaptchaPresence(TRUE);
|
danielebarchiesi@2
|
1109 }
|
danielebarchiesi@2
|
1110
|
danielebarchiesi@2
|
1111
|
danielebarchiesi@2
|
1112 public function testMultipleCaptchaProtectedFormsOnOnePage()
|
danielebarchiesi@2
|
1113 {
|
danielebarchiesi@2
|
1114 // Set Test CAPTCHA on comment form and login block
|
danielebarchiesi@2
|
1115 captcha_set_form_id_setting(self::COMMENT_FORM_ID, 'captcha/Test');
|
danielebarchiesi@2
|
1116 captcha_set_form_id_setting('user_login_block', 'captcha/Math');
|
danielebarchiesi@2
|
1117 $this->allowCommentPostingForAnonymousVisitors();
|
danielebarchiesi@2
|
1118
|
danielebarchiesi@2
|
1119 // Create a node with comments enabled.
|
danielebarchiesi@2
|
1120 $node = $this->createNodeWithCommentsEnabled();
|
danielebarchiesi@2
|
1121
|
danielebarchiesi@2
|
1122 // Preview comment with correct CAPTCHA answer.
|
danielebarchiesi@2
|
1123 $edit = $this->getCommentFormValues();
|
danielebarchiesi@2
|
1124 $comment_subject = $edit['subject'];
|
danielebarchiesi@2
|
1125 $edit['captcha_response'] = 'Test 123';
|
danielebarchiesi@2
|
1126 $this->drupalPost('comment/reply/' . $node->nid, $edit, t('Preview'));
|
danielebarchiesi@2
|
1127 // Post should be accepted: no warnings,
|
danielebarchiesi@2
|
1128 // no CAPTCHA reuse detection (which could be used by user log in block).
|
danielebarchiesi@2
|
1129 $this->assertCaptchaResponseAccepted();
|
danielebarchiesi@2
|
1130 $this->assertText($comment_subject);
|
danielebarchiesi@2
|
1131
|
danielebarchiesi@2
|
1132 }
|
danielebarchiesi@2
|
1133
|
danielebarchiesi@2
|
1134 }
|
danielebarchiesi@2
|
1135
|
danielebarchiesi@2
|
1136
|
danielebarchiesi@2
|
1137 // Some tricks to debug:
|
danielebarchiesi@2
|
1138 // drupal_debug($data) // from devel module
|
danielebarchiesi@2
|
1139 // file_put_contents('tmp.simpletest.html', $this->drupalGetContent());
|