Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
1.23% covered (danger)
1.23%
1 / 81
6.25% covered (danger)
6.25%
1 / 16
CRAP
0.00% covered (danger)
0.00%
0 / 1
recaptcha
1.23% covered (danger)
1.23%
1 / 81
6.25% covered (danger)
6.25%
1 / 16
1147.71
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 init
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 is_available
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 has_config
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 get_name
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 get_generator_class
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 acp_page
0.00% covered (danger)
0.00%
0 / 33
0.00% covered (danger)
0.00%
0 / 1
110
 execute_demo
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 execute
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 get_template
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
20
 get_demo_template
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 get_hidden_fields
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
6
 uninstall
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 install
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 validate
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 recaptcha_check_answer
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
20
1<?php
2/**
3*
4* This file is part of the phpBB Forum Software package.
5*
6* @copyright (c) phpBB Limited <https://www.phpbb.com>
7* @license GNU General Public License, version 2 (GPL-2.0)
8*
9* For full copyright and license information, please see
10* the docs/CREDITS.txt file.
11*
12*/
13
14namespace phpbb\captcha\plugins;
15
16use phpbb\exception\runtime_exception;
17
18class recaptcha extends captcha_abstract
19{
20    private $response;
21
22    /**
23    * Constructor
24    */
25    public function __construct()
26    {
27    }
28
29    function init($type)
30    {
31        global $user, $request;
32
33        $user->add_lang('captcha_recaptcha');
34        parent::init($type);
35        $this->response = $request->variable('g-recaptcha-response', '');
36    }
37
38    public function is_available()
39    {
40        global $config, $user;
41        $user->add_lang('captcha_recaptcha');
42        return (isset($config['recaptcha_pubkey']) && !empty($config['recaptcha_pubkey']));
43    }
44
45    /**
46    *  API function
47    */
48    function has_config()
49    {
50        return true;
51    }
52
53    public static function get_name()
54    {
55        return 'CAPTCHA_RECAPTCHA';
56    }
57
58    /**
59    * This function is implemented because required by the upper class, but is never used for reCaptcha.
60    * @throws runtime_exception
61    */
62    function get_generator_class()
63    {
64        throw new runtime_exception('NO_GENERATOR_CLASS');
65    }
66
67    function acp_page($id, $module)
68    {
69        global $config, $template, $user, $phpbb_log, $request;
70
71        $captcha_vars = array(
72            'recaptcha_pubkey'                => 'RECAPTCHA_PUBKEY',
73            'recaptcha_privkey'                => 'RECAPTCHA_PRIVKEY',
74        );
75
76        $module->tpl_name = 'captcha_recaptcha_acp';
77        $module->page_title = 'ACP_VC_SETTINGS';
78        $form_key = 'acp_captcha';
79        add_form_key($form_key);
80
81        $submit = $request->variable('submit', '');
82
83        if ($submit && check_form_key($form_key))
84        {
85            $captcha_vars = array_keys($captcha_vars);
86            foreach ($captcha_vars as $captcha_var)
87            {
88                $value = $request->variable($captcha_var, '');
89                if ($value)
90                {
91                    $config->set($captcha_var, $value);
92                }
93            }
94
95            $recaptcha_domain = $request->variable('recaptcha_v2_domain', '', true);
96            if (in_array($recaptcha_domain, recaptcha_v3::$supported_domains))
97            {
98                $config->set('recaptcha_v2_domain', $recaptcha_domain);
99            }
100
101            $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_CONFIG_VISUAL');
102            trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($module->u_action));
103        }
104        else if ($submit)
105        {
106            trigger_error($user->lang['FORM_INVALID'] . adm_back_link($module->u_action));
107        }
108        else
109        {
110            foreach ($captcha_vars as $captcha_var => $template_var)
111            {
112                $var = (isset($_REQUEST[$captcha_var])) ? $request->variable($captcha_var, '') : ((isset($config[$captcha_var])) ? $config[$captcha_var] : '');
113                $template->assign_var($template_var, $var);
114            }
115
116            $template->assign_vars(array(
117                'CAPTCHA_PREVIEW'        => $this->get_demo_template($id),
118                'CAPTCHA_NAME'            => $this->get_service_name(),
119                'RECAPTCHA_V2_DOMAIN'    => $config['recaptcha_v2_domain'] ?? recaptcha_v3::GOOGLE,
120                'RECAPTCHA_V2_DOMAINS'    => recaptcha_v3::$supported_domains,
121                'U_ACTION'                => $module->u_action,
122            ));
123
124        }
125    }
126
127    // not needed
128    function execute_demo()
129    {
130    }
131
132    // not needed
133    function execute()
134    {
135    }
136
137    function get_template()
138    {
139        global $config, $user, $template, $phpbb_root_path, $phpEx;
140
141        if ($this->is_solved())
142        {
143            return false;
144        }
145        else
146        {
147            $contact_link = phpbb_get_board_contact_link($config, $phpbb_root_path, $phpEx);
148            $explain = $user->lang(($this->type != CONFIRM_POST) ? 'CONFIRM_EXPLAIN' : 'POST_CONFIRM_EXPLAIN', '<a href="' . $contact_link . '">', '</a>');
149            $domain = $config['recaptcha_v2_domain'] ?? recaptcha_v3::GOOGLE;
150
151            $template->assign_vars(array(
152                'RECAPTCHA_SERVER'            => sprintf('//%1$s/recaptcha/api', $domain),
153                'RECAPTCHA_PUBKEY'            => isset($config['recaptcha_pubkey']) ? $config['recaptcha_pubkey'] : '',
154                'S_RECAPTCHA_AVAILABLE'        => self::is_available(),
155                'S_CONFIRM_CODE'            => true,
156                'S_TYPE'                    => $this->type,
157                'L_CONFIRM_EXPLAIN'            => $explain,
158            ));
159
160            return 'captcha_recaptcha.html';
161        }
162    }
163
164    function get_demo_template($id)
165    {
166        return $this->get_template();
167    }
168
169    function get_hidden_fields()
170    {
171        $hidden_fields = array();
172
173        // this is required for posting.php - otherwise we would forget about the captcha being already solved
174        if ($this->solved)
175        {
176            $hidden_fields['confirm_code'] = $this->code;
177        }
178        $hidden_fields['confirm_id'] = $this->confirm_id;
179        return $hidden_fields;
180    }
181
182    function uninstall()
183    {
184        $this->garbage_collect(0);
185    }
186
187    function install()
188    {
189        return;
190    }
191
192    function validate()
193    {
194        if (!parent::validate())
195        {
196            return false;
197        }
198        else
199        {
200            return $this->recaptcha_check_answer();
201        }
202    }
203
204    /**
205    * Calls an HTTP POST function to verify if the user's guess was correct
206    *
207    * @return bool|string Returns false on success or error string on failure.
208    */
209    function recaptcha_check_answer()
210    {
211        global $config, $user;
212
213        //discard spam submissions
214        if ($this->response == null || strlen($this->response) == 0)
215        {
216            return $user->lang['RECAPTCHA_INCORRECT'];
217        }
218
219        $recaptcha = new \ReCaptcha\ReCaptcha($config['recaptcha_privkey']);
220        $result = $recaptcha->verify($this->response, $user->ip);
221
222        if ($result->isSuccess())
223        {
224            $this->solved = true;
225            return false;
226        }
227        else
228        {
229            return $user->lang['RECAPTCHA_INCORRECT'];
230        }
231    }
232}