pictcode / app / Plugin / Recaptcha / View / Helper / RecaptchaHelper.php @ 9ddbf630
履歴 | 表示 | アノテート | ダウンロード (7.615 KB)
1 | b3a58ce1 | hasse | <?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 = "&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 . '&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 | } |