phpBB
Statistics
| Revision:

root / trunk / phpBB / includes / captcha / plugins / captcha_abstract.php

History | View | Annotate | Download (8.5 kB)

1
<?php
2
/**
3
*
4
* @package VC
5
* @copyright (c) 2006, 2008 phpBB Group
6
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
7
*
8
*/
9
10
/**
11
* @ignore
12
*/
13
if (!defined('IN_PHPBB'))
14
{
15
        exit;
16
}
17
18
19
/**
20
* This class holds the code shared by the two default 3.0.x CAPTCHAs.
21
*
22
* @package VC
23
*/
24
class phpbb_captcha_plugins_captcha_abstract
25
{
26
        var $confirm_id;
27
        var $confirm_code;
28
        var $code;
29
        var $seed;
30
        var $attempts = 0;
31
        var $type;
32
        var $solved = 0;
33
        var $captcha_vars = false;
34
35
        function init($type)
36
        {
37
                global $config, $db, $user;
38
39
                // read input
40
                $this->confirm_id = request_var('confirm_id', '');
41
                $this->confirm_code = request_var('confirm_code', '');
42
                $refresh = request_var('refresh_vc', false) && $config['confirm_refresh'];
43
44
                $this->type = (int) $type;
45
46
                if (!strlen($this->confirm_id) || !$this->load_code())
47
                {
48
                        // we have no confirm ID, better get ready to display something
49
                        $this->generate_code();
50
                }
51
                else if ($refresh)
52
                {
53
                        $this->regenerate_code();
54
                }
55
        }
56
57
        function execute_demo()
58
        {
59
                global $user;
60
61
                $this->code = gen_rand_string_friendly(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS));
62
                $this->seed = hexdec(substr(unique_id(), 4, 10));
63
64
                // compute $seed % 0x7fffffff
65
                $this->seed -= 0x7fffffff * floor($this->seed / 0x7fffffff);
66
67
                $captcha = new captcha();
68
                define('IMAGE_OUTPUT', 1);
69
                $captcha->execute($this->code, $this->seed);
70
        }
71
72
        function execute()
73
        {
74
                if (empty($this->code))
75
                {
76
                        if (!$this->load_code())
77
                        {
78
                                // invalid request, bail out
79
                                return false;
80
                        }
81
                }
82
                $captcha = new captcha();
83
                define('IMAGE_OUTPUT', 1);
84
                $captcha->execute($this->code, $this->seed);
85
        }
86
87
        function get_template()
88
        {
89
                global $config, $user, $template, $phpEx, $phpbb_root_path;
90
91
                if ($this->is_solved())
92
                {
93
                        return false;
94
                }
95
                else
96
                {
97
                        $link = append_sid($phpbb_root_path . 'ucp.' . $phpEx,  'mode=confirm&amp;confirm_id=' . $this->confirm_id . '&amp;type=' . $this->type);
98
                        $explain = $user->lang(($this->type != CONFIRM_POST) ? 'CONFIRM_EXPLAIN' : 'POST_CONFIRM_EXPLAIN', '<a href="mailto:' . htmlspecialchars($config['board_contact']) . '">', '</a>');
99
100
                        $template->assign_vars(array(
101
                                'CONFIRM_IMAGE_LINK'                => $link,
102
                                'CONFIRM_IMAGE'                                => '<img src="' . $link . '" />',
103
                                'CONFIRM_IMG'                                => '<img src="' . $link . '" />',
104
                                'CONFIRM_ID'                                => $this->confirm_id,
105
                                'S_CONFIRM_CODE'                        => true,
106
                                'S_TYPE'                                        => $this->type,
107
                                'S_CONFIRM_REFRESH'                        => ($config['enable_confirm'] && $config['confirm_refresh'] && $this->type == CONFIRM_REG) ? true : false,
108
                                'L_CONFIRM_EXPLAIN'                        => $explain,
109
                        ));
110
111
                        return 'captcha_default.html';
112
                }
113
        }
114
115
        function get_demo_template($id)
116
        {
117
                global $config, $user, $template, $phpbb_admin_path, $phpEx;
118
119
                $variables = '';
120
121
                if (is_array($this->captcha_vars))
122
                {
123
                        foreach ($this->captcha_vars as $captcha_var => $template_var)
124
                        {
125
                                $variables .= '&amp;' . rawurlencode($captcha_var) . '=' . request_var($captcha_var, (int) $config[$captcha_var]);
126
                        }
127
                }
128
129
                // acp_captcha has a delivery function; let's use it
130
                $template->assign_vars(array(
131
                        'CONFIRM_IMAGE'                => append_sid($phpbb_admin_path . 'index.' . $phpEx, 'captcha_demo=1&amp;mode=visual&amp;i=' . $id . '&amp;select_captcha=' . $this->get_class_name()) . $variables,
132
                        'CONFIRM_ID'                => $this->confirm_id,
133
                ));
134
135
                return 'captcha_default_acp_demo.html';
136
        }
137
138
        function get_hidden_fields()
139
        {
140
                $hidden_fields = array();
141
142
                // this is required for posting.php - otherwise we would forget about the captcha being already solved
143
                if ($this->solved)
144
                {
145
                        $hidden_fields['confirm_code'] = $this->confirm_code;
146
                }
147
                $hidden_fields['confirm_id'] = $this->confirm_id;
148
                return $hidden_fields;
149
        }
150
151
        function garbage_collect($type)
152
        {
153
                global $db, $config;
154
155
                $sql = 'SELECT DISTINCT c.session_id
156
                        FROM ' . CONFIRM_TABLE . ' c
157
                        LEFT JOIN ' . SESSIONS_TABLE . ' s ON (c.session_id = s.session_id)
158
                        WHERE s.session_id IS NULL' .
159
                                ((empty($type)) ? '' : ' AND c.confirm_type = ' . (int) $type);
160
                $result = $db->sql_query($sql);
161
162
                if ($row = $db->sql_fetchrow($result))
163
                {
164
                        $sql_in = array();
165
                        do
166
                        {
167
                                $sql_in[] = (string) $row['session_id'];
168
                        }
169
                        while ($row = $db->sql_fetchrow($result));
170
171
                        if (sizeof($sql_in))
172
                        {
173
                                $sql = 'DELETE FROM ' . CONFIRM_TABLE . '
174
                                        WHERE ' . $db->sql_in_set('session_id', $sql_in);
175
                                $db->sql_query($sql);
176
                        }
177
                }
178
                $db->sql_freeresult($result);
179
        }
180
181
        function uninstall()
182
        {
183
                $this->garbage_collect(0);
184
        }
185
186
        function install()
187
        {
188
                return;
189
        }
190
191
        function validate()
192
        {
193
                global $config, $db, $user;
194
195
                if (empty($user->lang))
196
                {
197
                        $user->setup();
198
                }
199
200
                $error = '';
201
                if (!$this->confirm_id)
202
                {
203
                        $error = $user->lang['CONFIRM_CODE_WRONG'];
204
                }
205
                else
206
                {
207
                        if ($this->check_code())
208
                        {
209
                                $this->solved = true;
210
                        }
211
                        else
212
                        {
213
                                $error = $user->lang['CONFIRM_CODE_WRONG'];
214
                        }
215
                }
216
217
                if (strlen($error))
218
                {
219
                        // okay, incorrect answer. Let's ask a new question.
220
                        $this->new_attempt();
221
                        return $error;
222
                }
223
                else
224
                {
225
                        return false;
226
                }
227
        }
228
229
        /**
230
        * The old way to generate code, suitable for GD and non-GD. Resets the internal state.
231
        */
232
        function generate_code()
233
        {
234
                global $db, $user;
235
236
                $this->code = gen_rand_string_friendly(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS));
237
                $this->confirm_id = md5(unique_id($user->ip));
238
                $this->seed = hexdec(substr(unique_id(), 4, 10));
239
                $this->solved = 0;
240
                // compute $seed % 0x7fffffff
241
                $this->seed -= 0x7fffffff * floor($this->seed / 0x7fffffff);
242
243
                $sql = 'INSERT INTO ' . CONFIRM_TABLE . ' ' . $db->sql_build_array('INSERT', array(
244
                                'confirm_id'        => (string) $this->confirm_id,
245
                                'session_id'        => (string) $user->session_id,
246
                                'confirm_type'        => (int) $this->type,
247
                                'code'                        => (string) $this->code,
248
                                'seed'                        => (int) $this->seed)
249
                );
250
                $db->sql_query($sql);
251
        }
252
253
        /**
254
        * New Question, if desired.
255
        */
256
        function regenerate_code()
257
        {
258
                global $db, $user;
259
260
                $this->code = gen_rand_string_friendly(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS));
261
                $this->seed = hexdec(substr(unique_id(), 4, 10));
262
                $this->solved = 0;
263
                // compute $seed % 0x7fffffff
264
                $this->seed -= 0x7fffffff * floor($this->seed / 0x7fffffff);
265
266
                $sql = 'UPDATE ' . CONFIRM_TABLE . ' SET ' . $db->sql_build_array('UPDATE', array(
267
                                'code'                        => (string) $this->code,
268
                                'seed'                        => (int) $this->seed)) . '
269
                                WHERE
270
                                confirm_id = \'' . $db->sql_escape($this->confirm_id) . '\'
271
                                        AND session_id = \'' . $db->sql_escape($user->session_id) . '\'';
272
                $db->sql_query($sql);
273
        }
274
275
        /**
276
        * New Question, if desired.
277
        */
278
        function new_attempt()
279
        {
280
                global $db, $user;
281
282
                $this->code = gen_rand_string_friendly(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS));
283
                $this->seed = hexdec(substr(unique_id(), 4, 10));
284
                $this->solved = 0;
285
                // compute $seed % 0x7fffffff
286
                $this->seed -= 0x7fffffff * floor($this->seed / 0x7fffffff);
287
288
                $sql = 'UPDATE ' . CONFIRM_TABLE . ' SET ' . $db->sql_build_array('UPDATE', array(
289
                                'code'                        => (string) $this->code,
290
                                'seed'                        => (int) $this->seed)) . '
291
                                , attempts = attempts + 1
292
                                WHERE
293
                                confirm_id = \'' . $db->sql_escape($this->confirm_id) . '\'
294
                                        AND session_id = \'' . $db->sql_escape($user->session_id) . '\'';
295
                $db->sql_query($sql);
296
        }
297
298
        /**
299
        * Look up everything we need for painting&checking.
300
        */
301
        function load_code()
302
        {
303
                global $db, $user;
304
305
                $sql = 'SELECT code, seed, attempts
306
                        FROM ' . CONFIRM_TABLE . "
307
                        WHERE confirm_id = '" . $db->sql_escape($this->confirm_id) . "'
308
                                AND session_id = '" . $db->sql_escape($user->session_id) . "'
309
                                AND confirm_type = " . $this->type;
310
                $result = $db->sql_query($sql);
311
                $row = $db->sql_fetchrow($result);
312
                $db->sql_freeresult($result);
313
314
                if ($row)
315
                {
316
                        $this->code = $row['code'];
317
                        $this->seed = $row['seed'];
318
                        $this->attempts = $row['attempts'];
319
                        return true;
320
                }
321
322
                return false;
323
        }
324
325
        function check_code()
326
        {
327
                return (strcasecmp($this->code, $this->confirm_code) === 0);
328
        }
329
330
        function get_attempt_count()
331
        {
332
                return $this->attempts;
333
        }
334
335
        function reset()
336
        {
337
                global $db, $user;
338
339
                $sql = 'DELETE FROM ' . CONFIRM_TABLE . "
340
                        WHERE session_id = '" . $db->sql_escape($user->session_id) . "'
341
                                AND confirm_type = " . (int) $this->type;
342
                $db->sql_query($sql);
343
344
                // we leave the class usable by generating a new question
345
                $this->generate_code();
346
        }
347
348
        function is_solved()
349
        {
350
                if (request_var('confirm_code', false) && $this->solved === 0)
351
                {
352
                        $this->validate();
353
                }
354
                return (bool) $this->solved;
355
        }
356
357
        /**
358
        *  API function
359
        */
360
        function has_config()
361
        {
362
                return false;
363
        }
364
365
}
366
367
/**
368
* Old class name for legacy use. The new class name is auto loadable.
369
*/
370
class phpbb_default_captcha extends phpbb_captcha_plugins_captcha_abstract
371
{
372
}