統計
| ブランチ: | リビジョン:

pictcode / app / Plugin / Recaptcha / Controller / Component / RecaptchaComponent.php @ b3a58ce1

履歴 | 表示 | アノテート | ダウンロード (4.564 KB)

1
<?php
2
/**
3
 * Copyright 2009-2014, Cake Development Corporation (http://cakedc.com)
4
 *
5
 * Licensed under The MIT License
6
 * Redistributions of files must retain the above copyright notice.
7
 *
8
 * @copyright Copyright 2009-2014, Cake Development Corporation (http://cakedc.com)
9
 * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
10
 */
11

    
12
App::uses('HttpSocket', 'Network/Http');
13

    
14
/**
15
 * CakePHP Recaptcha component
16
 *
17
 * @package recaptcha
18
 * @subpackage recaptcha.controllers.components
19
 */
20

    
21
class RecaptchaComponent extends Component {
22

    
23
/**
24
 * Name
25
 *
26
 * @var string
27
 */
28
        public $Controller = null;
29

    
30
/**
31
 * Recaptcha API Url
32
 *
33
 * @var string
34
 */
35
        public $apiUrl = 'http://www.google.com/recaptcha/api/verify';
36

    
37
/**
38
 * Private API Key
39
 *
40
 * @var string
41
 */
42
        public $privateKey = '';
43

    
44
/**
45
 * Error coming back from Recaptcha
46
 *
47
 * @var string
48
 */
49
        public $error = null;
50

    
51
/**
52
 * Actions that should automatically checked for a recaptcha input
53
 *
54
 * @var array
55
 */
56
        public $actions = array();
57

    
58
/**
59
 * Settings
60
 *
61
 * @var array
62
 */
63
        public $settings = array();
64

    
65
/**
66
 * Default Options
67
 *
68
 * @var array
69
 */
70
        protected $_defaults = array(
71
                'errorField' => 'recaptcha',
72
                'actions' => array()
73
        );
74

    
75
 /**
76
 * Constructor
77
 *
78
 * @param ComponentCollection $collection A ComponentCollection this component can use to lazy load its components
79
 * @param array $settings Array of configuration settings
80
 * @return RecaptchaComponent
81
 */
82
        public function __construct(ComponentCollection $collection, $settings = array()) {
83
                parent::__construct($collection, $settings);
84
                $this->Controller = $collection->getController();
85
                $this->_defaults['modelClass'] = $this->Controller->modelClass;
86
                $this->settings = array_merge($this->_defaults, $settings);
87
                $this->actions = array_merge($this->actions, $this->settings['actions']);
88
                unset($this->settings['actions']);
89
        }
90

    
91
/**
92
 * Callback
93
 *
94
 * @param Controller $controller Controller with components to initialize
95
 * @param array $settings Array of configuration settings
96
 * @throws Exception Throws an exception if Recaptchas config is not present
97
 * @return void
98
 */
99
        public function initialize(Controller $controller, $settings = array()) {
100
                if ($controller->name === 'CakeError') {
101
                        return;
102
                }
103
                $this->privateKey = Configure::read('Recaptcha.privateKey');
104
                $this->Controller = $controller;
105

    
106
                if (!isset($this->Controller->helpers['Recaptcha.Recaptcha'])) {
107
                        $this->Controller->helpers[] = 'Recaptcha.Recaptcha';
108
                }
109

    
110
                if (empty($this->privateKey)) {
111
                        throw new Exception(__d('recaptcha', "You must set your private Recaptcha key using Configure::write('Recaptcha.privateKey', 'your-key');!", true));
112
                }
113
        }
114

    
115
/**
116
 * Callback
117
 *
118
 * @param Controller $controller Controller with components to initialize
119
 * @return void
120
 */
121
        public function startup(Controller $controller) {
122
                extract($this->settings);
123
                $this->Controller->helpers[] = 'Recaptcha.Recaptcha';
124
                $this->Controller->{$modelClass}->Behaviors->load('Recaptcha.Recaptcha', array(
125
                        'field' => $errorField
126
                ));
127

    
128
                $this->Controller->{$modelClass}->recaptcha = true;
129
                if (in_array($this->Controller->action, $this->actions)) {
130
                        if (!$this->verify()) {
131
                                $this->Controller->{$modelClass}->recaptcha = false;
132
                                $this->Controller->{$modelClass}->recaptchaError = $this->error;
133
                        }
134
                }
135
        }
136

    
137
/**
138
 * Verifies the recaptcha input
139
 *
140
 * Please note that you still have to pass the result to the model and do
141
 * the validation there to make sure the data is not saved!
142
 *
143
 * @return boolean True if the response was correct
144
 */
145
        public function verify() {
146
                if (isset($this->Controller->request->data['recaptcha_challenge_field']) &&
147
                        isset($this->Controller->request->data['recaptcha_response_field'])) {
148

    
149
                        $response = $this->_getApiResponse();
150
                        $response = explode("\n", $response->body());
151

    
152
                        if (empty($response[0])) {
153
                                $this->error = __d('recaptcha', 'Invalid API response, please contact the site admin.', true);
154
                                return false;
155
                        }
156

    
157
                        if ($response[0] === 'true') {
158
                                return true;
159
                        }
160

    
161
                        if ($response[1] === 'incorrect-captcha-sol') {
162
                                $this->error = __d('recaptcha', 'Incorrect captcha', true);
163
                        } else {
164
                                $this->error = $response[1];
165
                        }
166
                }
167
                return false;
168
        }
169

    
170
/**
171
 * Queries the Recaptcha API and and returns the raw response
172
 *
173
 * @return string
174
 */
175
        protected function _getApiResponse() {
176
                $Socket = new HttpSocket();
177
                return $Socket->post($this->apiUrl, array(
178
                        'privatekey' => $this->privateKey,
179
                        'remoteip' => env('REMOTE_ADDR'),
180
                        'challenge' => $this->Controller->request->data['recaptcha_challenge_field'],
181
                        'response' => $this->Controller->request->data['recaptcha_response_field']
182
                ));
183
        }
184

    
185
}