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

pictcode / app / Plugin / Recaptcha / View / Helper / RecaptchaHelper.php @ b3a58ce1

履歴 | 表示 | アノテート | ダウンロード (7.615 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
/**
13
 * CakePHP Recaptcha helper
14
 *
15
 * @package recaptcha
16
 * @subpackage recaptcha.views.helpers
17
 */
18
class RecaptchaHelper extends AppHelper {
19

    
20
/**
21
 * Secure API Url
22
 *
23
 * @var string
24
 */
25
        public $secureApiUrl = 'https://www.google.com/recaptcha/api';
26

    
27
/**
28
 * API Url
29
 *
30
 * @var string
31
 */
32
        public $apiUrl = 'http://www.google.com/recaptcha/api';
33

    
34
/**
35
 * View helpers
36
 *
37
 * @var array
38
 */
39
        public $helpers = array('Form', 'Html');
40

    
41
/**
42
 * Displays the Recaptcha input
43
 *
44
 * @param array $options An array of options
45
 *
46
 * ### Options:
47
 *
48
 * - `element` String, name of the view element that can be used instead of the hardcoded HTML structure from this helper
49
 * - `publicKey` String, default is read from Configure::read('Recaptcha.publicKey'), you can override it here
50
 * - `error` String, optional error message that is displayed using Form::error()
51
 * - `ssl` Boolean, use SSL or not, default is true
52
 * - `div` Array of options for the div tag the recaptcha is wrapped with, set to false if you want to disable it
53
 * - `recaptchaOptions` assoc array of options to pass into RecaptchaOptions var, like 'theme', 'lang'
54
 *    or 'custom_translations' to runtime configure the widget.
55
 *
56
 * @return string The resulting mark up
57
 * @access public
58
 */
59
        public function display($options = array()) {
60
                $defaults = array(
61
                        'element' => null,
62
                        'publicKey' => Configure::read('Recaptcha.publicKey'),
63
                        'error' => null,
64
                        'ssl' => true,
65
                        'error' => false,
66
                        'div' => array(
67
                                'class' => 'recaptcha'),
68
                                'recaptchaOptions' => array(
69
                                        'theme' => 'red',
70
                                        'lang' => 'en',
71
                                        'custom_translations' => array()
72
                                )
73
                );
74

    
75
                $options = Set::merge($defaults, $options);
76
                extract($options);
77

    
78
                if ($ssl) {
79
                        $server = $this->secureApiUrl;
80
                } else {
81
                        $server = $this->apiUrl;
82
                }
83

    
84
                $errorpart = "";
85
                if ($error) {
86
                        $errorpart = "&amp;error=" . $error;
87
                }
88

    
89
                if (!empty($element)) {
90
                        $elementOptions = array();
91
                        if (is_array($element)) {
92
                                $keys = array_keys($element);
93
                                $elementOptions = $element[$keys[0]];
94
                        }
95

    
96
                        return $this->View->element($element, $elementOptions);
97
                }
98

    
99
                $jsonOptions = preg_replace('/"callback":"([^"\r\n]*)"/', '"callback":$1', json_encode($recaptchaOptions));
100
                unset($recaptchaOptions);
101

    
102
                if (empty($this->params['isAjax'])) {
103
                        $configScript = sprintf('var RecaptchaOptions = %s', $jsonOptions);
104
                        echo $this->Html->scriptBlock($configScript);
105

    
106
                        $script = '';
107
                        $script .= '<script type="text/javascript" src="' . $server . '/challenge?k=' . $publicKey . '"></script>';
108
                        $script .= '<noscript>';
109
                        $script .= '        <iframe src="' . $server . '/noscript?k=' . $publicKey . '" height="300" width="500" frameborder="0"></iframe><br/>';
110
                        $script .= '        <textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>';
111
                        $script .= '  <input type="hidden" name="recaptcha_response_field" value="manual_challenge"/>';
112
                        $script .= '</noscript>';
113

    
114
                        if (!empty($error)) {
115
                                $script .= $this->Form->error($error);
116
                        }
117

    
118
                        if ($options['div'] != false) {
119
                                $script = $this->Html->tag('div', $script, $options['div']);
120
                        }
121

    
122
                        $this->Form->unlockField('recaptcha_challenge_field');
123
                        $this->Form->unlockField('recaptcha_response_field');
124

    
125
                        return $script;
126
                }
127

    
128
                $id = uniqid('recaptcha-');
129

    
130
                $script = '';
131
                $script .= '<div id="' . $id . '"></div>';
132
                $script .= '<script>';
133
                $script .= 'if (window.Recaptcha == undefined) {';
134
                $script .= '  (function() {';
135
                $script .= '          var headID = document.getElementsByTagName("head")[0];';
136
                $script .= '                var newScript = document.createElement("script");';
137
                $script .= '                newScript.type = "text/javascript";';
138
                $script .= '                newScript.onload = function() {';
139
                $script .= '                        Recaptcha.create("' . $publicKey . '", "' . $id . '", ' . $jsonOptions . ');';
140
                $script .= '                  Recaptcha.focus_response_field();';
141
                $script .= '                };';
142
                $script .= '                newScript.src = "' . $server . '/js/recaptcha_ajax.js"';
143
                $script .= '          headID.appendChild(newScript);';
144
                $script .= '  })();';
145
                $script .= '} else {';
146
                $script .= '  setTimeout(\'Recaptcha.create("' . $publicKey . '", "' . $id . '", ' . $jsonOptions . ')\', 1000);';
147
                $script .= '}';
148
                $script .= '</script>';
149

    
150
                return $script;
151
        }
152

    
153
/**
154
 * Recaptcha signup URL
155
 *
156
 * @param string $appName An application name
157
 * @return string A signup url
158
 */
159
        public function signupUrl($appName = null) {
160
                return "http://recaptcha.net/api/getkey?domain=" . WWW_ROOT . '&amp;app=' . urlencode($appName);
161
        }
162

    
163
/**
164
 * AES Pad
165
 *
166
 * @param string $val A value to pad
167
 * @return string
168
 */
169
        private function __aesPad($val) {
170
                $blockSize = 16;
171
                $numpad = $blockSize - (strlen($val) % $blockSize);
172
                return str_pad($val, strlen($val) + $numpad, chr($numpad));
173
        }
174

    
175
/**
176
 * AES Encryption
177
 *
178
 * @param string $value A value
179
 * @param string $key A key to use
180
 * @return string
181
 * @throws Exception
182
 */
183
        private function __aesEncrypt($value, $key) {
184
                if (!function_exists('mcrypt_encrypt')) {
185
                        throw new Exception(__d('recaptcha', 'To use reCAPTCHA Mailhide, you need to have the mcrypt php module installed.', true));
186
                }
187

    
188
                $mode = MCRYPT_MODE_CBC;
189
                $encryption = MCRYPT_RIJNDAEL_128;
190
                $value = $this->__aesPad($value);
191

    
192
                return mcrypt_encrypt($encryption, $key, $value, $mode, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
193
        }
194

    
195
/**
196
 * Mail-hide URL
197
 *
198
 * @param string $x An input string
199
 * @return string A base 64 encrypted string
200
 */
201
        private function __mailhideUrlbase64($x) {
202
                return strtr(base64_encode($x), '+/', '-_');
203
        }
204

    
205
/**
206
 * Gets the reCAPTCHA Mailhide url for a given email
207
 *
208
 * @param string $email An email address
209
 * @return string
210
 * @throws Exception
211
 */
212
        public function mailHideUrl($email = null) {
213
                $publicKey = Configure::read('Recaptcha.mailHide.publicKey');
214
                $privateKey = Configure::read('Recaptcha.mailHide.privateKey');
215

    
216
                if ($publicKey == '' || $publicKey == null || $privateKey == "" || $privateKey == null) {
217
                        throw new Exception(__d('recaptcha', "You need to set a private and public mail hide key. Please visit http://mailhide.recaptcha.net/apikey", true));
218
                }
219

    
220
                $key = pack('H*', $privateKey);
221
                $cryptmail = $this->__aesEncrypt($email, $key);
222

    
223
                return "http://mailhide.recaptcha.net/d?k=" . $publicKey . "&c=" . $this->__mailhideUrlbase64($cryptmail);
224
        }
225

    
226
/**
227
 * Get a part of the email to show
228
 *
229
 * Given johndoe@example,com return ["john", "example.com"].
230
 * the email is then displayed as john...@example.com
231
 *
232
 * @param string $email an email address
233
 * @return array
234
 */
235
        private function __hideEmailParts($email) {
236
                $array = preg_split("/@/", $email );
237

    
238
                if (strlen($array[0]) <= 4) {
239
                        $array[0] = substr($array[0], 0, 1);
240
                } elseif (strlen($array[0]) <= 6) {
241
                        $array[0] = substr($array[0], 0, 3);
242
                } else {
243
                        $array[0] = substr($array[0], 0, 4);
244
                }
245
                return $array;
246
        }
247

    
248
/**
249
 * Gets html to display an email address given a public an private key to get a key go to:
250
 * http://mailhide.recaptcha.net/apikey
251
 *
252
 * @param string $email An email address
253
 * @return string
254
 */
255
        public function mailHide($email) {
256
                $emailparts = $this->__hideEmailParts($email);
257
                $url = $this->mailHideUrl($email);
258

    
259
                return htmlentities($emailparts[0]) . "<a href='" . htmlentities($url) .
260
                        "' onclick=\"window.open('" . htmlentities($url) . "', '', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=300'); return false;\" title=\"Reveal this e-mail address\">...</a>@" . htmlentities($emailparts[1]);
261
        }
262

    
263
}