|
1 <?php |
|
2 /** |
|
3 * Zend Framework |
|
4 * |
|
5 * LICENSE |
|
6 * |
|
7 * This source file is subject to the new BSD license that is bundled |
|
8 * with this package in the file LICENSE.txt. |
|
9 * It is also available through the world-wide-web at this URL: |
|
10 * http://framework.zend.com/license/new-bsd |
|
11 * If you did not receive a copy of the license and are unable to |
|
12 * obtain it through the world-wide-web, please send an email |
|
13 * to license@zend.com so we can send you a copy immediately. |
|
14 * |
|
15 * @category Zend |
|
16 * @package Zend_Service |
|
17 * @subpackage ReCaptcha |
|
18 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) |
|
19 * @license http://framework.zend.com/license/new-bsd New BSD License |
|
20 */ |
|
21 |
|
22 /** @see Zend_Service_ReCaptcha */ |
|
23 require_once 'Zend/Service/ReCaptcha.php'; |
|
24 |
|
25 /** |
|
26 * Zend_Service_ReCaptcha_MailHide |
|
27 * |
|
28 * @category Zend |
|
29 * @package Zend_Service |
|
30 * @subpackage ReCaptcha |
|
31 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) |
|
32 * @license http://framework.zend.com/license/new-bsd New BSD License |
|
33 * @version $Id: MailHide.php 20108 2010-01-06 22:05:31Z matthew $ |
|
34 */ |
|
35 class Zend_Service_ReCaptcha_MailHide extends Zend_Service_ReCaptcha |
|
36 { |
|
37 /**#@+ |
|
38 * Encryption constants |
|
39 */ |
|
40 const ENCRYPTION_MODE = MCRYPT_MODE_CBC; |
|
41 const ENCRYPTION_CIPHER = MCRYPT_RIJNDAEL_128; |
|
42 const ENCRYPTION_BLOCK_SIZE = 16; |
|
43 const ENCRYPTION_IV = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; |
|
44 /**#@-*/ |
|
45 |
|
46 /** |
|
47 * Url to the mailhide server |
|
48 * |
|
49 * @var string |
|
50 */ |
|
51 const MAILHIDE_SERVER = 'http://mailhide.recaptcha.net/d'; |
|
52 |
|
53 /** |
|
54 * The email address to protect |
|
55 * |
|
56 * @var string |
|
57 */ |
|
58 protected $_email = null; |
|
59 |
|
60 /** |
|
61 * @var Zend_Validate_Interface |
|
62 */ |
|
63 protected $_emailValidator; |
|
64 |
|
65 /** |
|
66 * Binary representation of the private key |
|
67 * |
|
68 * @var string |
|
69 */ |
|
70 protected $_privateKeyPacked = null; |
|
71 |
|
72 /** |
|
73 * The local part of the email |
|
74 * |
|
75 * @var string |
|
76 */ |
|
77 protected $_emailLocalPart = null; |
|
78 |
|
79 /** |
|
80 * The domain part of the email |
|
81 * |
|
82 * @var string |
|
83 */ |
|
84 protected $_emailDomainPart = null; |
|
85 |
|
86 /** |
|
87 * Local constructor |
|
88 * |
|
89 * @param string $publicKey |
|
90 * @param string $privateKey |
|
91 * @param string $email |
|
92 * @param array|Zend_Config $options |
|
93 */ |
|
94 public function __construct($publicKey = null, $privateKey = null, $email = null, $options = null) |
|
95 { |
|
96 /* Require the mcrypt extension to be loaded */ |
|
97 $this->_requireMcrypt(); |
|
98 |
|
99 /* If options is a Zend_Config object we want to convert it to an array so we can merge it with the default options */ |
|
100 if ($options instanceof Zend_Config) { |
|
101 $options = $options->toArray(); |
|
102 } |
|
103 |
|
104 /* Merge if needed */ |
|
105 if (is_array($options)) { |
|
106 $options = array_merge($this->getDefaultOptions(), $options); |
|
107 } else { |
|
108 $options = $this->getDefaultOptions(); |
|
109 } |
|
110 |
|
111 parent::__construct($publicKey, $privateKey, null, $options); |
|
112 |
|
113 if ($email !== null) { |
|
114 $this->setEmail($email); |
|
115 } |
|
116 } |
|
117 |
|
118 |
|
119 /** |
|
120 * Get emailValidator |
|
121 * |
|
122 * @return Zend_Validate_Interface |
|
123 */ |
|
124 public function getEmailValidator() |
|
125 { |
|
126 if (null === $this->_emailValidator) { |
|
127 require_once 'Zend/Validate/EmailAddress.php'; |
|
128 $this->setEmailValidator(new Zend_Validate_EmailAddress()); |
|
129 } |
|
130 return $this->_emailValidator; |
|
131 } |
|
132 |
|
133 /** |
|
134 * Set email validator |
|
135 * |
|
136 * @param Zend_Validate_Interface $validator |
|
137 * @return Zend_Service_ReCaptcha_MailHide |
|
138 */ |
|
139 public function setEmailValidator(Zend_Validate_Interface $validator) |
|
140 { |
|
141 $this->_emailValidator = $validator; |
|
142 return $this; |
|
143 } |
|
144 |
|
145 |
|
146 /** |
|
147 * See if the mcrypt extension is available |
|
148 * |
|
149 * @throws Zend_Service_ReCaptcha_MailHide_Exception |
|
150 */ |
|
151 protected function _requireMcrypt() |
|
152 { |
|
153 if (!extension_loaded('mcrypt')) { |
|
154 /** @see Zend_Service_ReCaptcha_MailHide_Exception */ |
|
155 require_once 'Zend/Service/ReCaptcha/MailHide/Exception.php'; |
|
156 |
|
157 throw new Zend_Service_ReCaptcha_MailHide_Exception('Use of the Zend_Service_ReCaptcha_MailHide component requires the mcrypt extension to be enabled in PHP'); |
|
158 } |
|
159 } |
|
160 |
|
161 /** |
|
162 * Serialize as string |
|
163 * |
|
164 * When the instance is used as a string it will display the email address. Since we can't |
|
165 * throw exceptions within this method we will trigger a user warning instead. |
|
166 * |
|
167 * @return string |
|
168 */ |
|
169 public function __toString() |
|
170 { |
|
171 try { |
|
172 $return = $this->getHtml(); |
|
173 } catch (Exception $e) { |
|
174 $return = ''; |
|
175 trigger_error($e->getMessage(), E_USER_WARNING); |
|
176 } |
|
177 |
|
178 return $return; |
|
179 } |
|
180 |
|
181 /** |
|
182 * Get the default set of parameters |
|
183 * |
|
184 * @return array |
|
185 */ |
|
186 public function getDefaultOptions() |
|
187 { |
|
188 return array( |
|
189 'encoding' => 'UTF-8', |
|
190 'linkTitle' => 'Reveal this e-mail address', |
|
191 'linkHiddenText' => '...', |
|
192 'popupWidth' => 500, |
|
193 'popupHeight' => 300, |
|
194 ); |
|
195 } |
|
196 |
|
197 /** |
|
198 * Override the setPrivateKey method |
|
199 * |
|
200 * Override the parent method to store a binary representation of the private key as well. |
|
201 * |
|
202 * @param string $privateKey |
|
203 * @return Zend_Service_ReCaptcha_MailHide |
|
204 */ |
|
205 public function setPrivateKey($privateKey) |
|
206 { |
|
207 parent::setPrivateKey($privateKey); |
|
208 |
|
209 /* Pack the private key into a binary string */ |
|
210 $this->_privateKeyPacked = pack('H*', $this->_privateKey); |
|
211 |
|
212 return $this; |
|
213 } |
|
214 |
|
215 /** |
|
216 * Set the email property |
|
217 * |
|
218 * This method will set the email property along with the local and domain parts |
|
219 * |
|
220 * @param string $email |
|
221 * @return Zend_Service_ReCaptcha_MailHide |
|
222 */ |
|
223 public function setEmail($email) |
|
224 { |
|
225 $this->_email = $email; |
|
226 |
|
227 $validator = $this->getEmailValidator(); |
|
228 if (!$validator->isValid($email)) { |
|
229 require_once 'Zend/Service/ReCaptcha/MailHide/Exception.php'; |
|
230 throw new Zend_Service_ReCaptcha_MailHide_Exception('Invalid email address provided'); |
|
231 } |
|
232 |
|
233 $emailParts = explode('@', $email, 2); |
|
234 |
|
235 /* Decide on how much of the local part we want to reveal */ |
|
236 if (strlen($emailParts[0]) <= 4) { |
|
237 $emailParts[0] = substr($emailParts[0], 0, 1); |
|
238 } else if (strlen($emailParts[0]) <= 6) { |
|
239 $emailParts[0] = substr($emailParts[0], 0, 3); |
|
240 } else { |
|
241 $emailParts[0] = substr($emailParts[0], 0, 4); |
|
242 } |
|
243 |
|
244 $this->_emailLocalPart = $emailParts[0]; |
|
245 $this->_emailDomainPart = $emailParts[1]; |
|
246 |
|
247 return $this; |
|
248 } |
|
249 |
|
250 /** |
|
251 * Get the email property |
|
252 * |
|
253 * @return string |
|
254 */ |
|
255 public function getEmail() |
|
256 { |
|
257 return $this->_email; |
|
258 } |
|
259 |
|
260 /** |
|
261 * Get the local part of the email address |
|
262 * |
|
263 * @return string |
|
264 */ |
|
265 public function getEmailLocalPart() |
|
266 { |
|
267 return $this->_emailLocalPart; |
|
268 } |
|
269 |
|
270 /** |
|
271 * Get the domain part of the email address |
|
272 * |
|
273 * @return string |
|
274 */ |
|
275 public function getEmailDomainPart() |
|
276 { |
|
277 return $this->_emailDomainPart; |
|
278 } |
|
279 |
|
280 /** |
|
281 * Get the HTML code needed for the mail hide |
|
282 * |
|
283 * @param string $email |
|
284 * @return string |
|
285 * @throws Zend_Service_ReCaptcha_MailHide_Exception |
|
286 */ |
|
287 public function getHtml($email = null) |
|
288 { |
|
289 if ($email !== null) { |
|
290 $this->setEmail($email); |
|
291 } elseif (null === ($email = $this->getEmail())) { |
|
292 /** @see Zend_Service_ReCaptcha_MailHide_Exception */ |
|
293 require_once 'Zend/Service/ReCaptcha/MailHide/Exception.php'; |
|
294 throw new Zend_Service_ReCaptcha_MailHide_Exception('Missing email address'); |
|
295 } |
|
296 |
|
297 if ($this->_publicKey === null) { |
|
298 /** @see Zend_Service_ReCaptcha_MailHide_Exception */ |
|
299 require_once 'Zend/Service/ReCaptcha/MailHide/Exception.php'; |
|
300 throw new Zend_Service_ReCaptcha_MailHide_Exception('Missing public key'); |
|
301 } |
|
302 |
|
303 if ($this->_privateKey === null) { |
|
304 /** @see Zend_Service_ReCaptcha_MailHide_Exception */ |
|
305 require_once 'Zend/Service/ReCaptcha/MailHide/Exception.php'; |
|
306 throw new Zend_Service_ReCaptcha_MailHide_Exception('Missing private key'); |
|
307 } |
|
308 |
|
309 /* Generate the url */ |
|
310 $url = $this->_getUrl(); |
|
311 |
|
312 $enc = $this->getOption('encoding'); |
|
313 |
|
314 /* Genrate the HTML used to represent the email address */ |
|
315 $html = htmlentities($this->getEmailLocalPart(), ENT_COMPAT, $enc) |
|
316 . '<a href="' |
|
317 . htmlentities($url, ENT_COMPAT, $enc) |
|
318 . '" onclick="window.open(\'' |
|
319 . htmlentities($url, ENT_COMPAT, $enc) |
|
320 . '\', \'\', \'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=' |
|
321 . $this->_options['popupWidth'] |
|
322 . ',height=' |
|
323 . $this->_options['popupHeight'] |
|
324 . '\'); return false;" title="' |
|
325 . $this->_options['linkTitle'] |
|
326 . '">' . $this->_options['linkHiddenText'] . '</a>@' |
|
327 . htmlentities($this->getEmailDomainPart(), ENT_COMPAT, $enc); |
|
328 |
|
329 return $html; |
|
330 } |
|
331 |
|
332 /** |
|
333 * Get the url used on the "hidden" part of the email address |
|
334 * |
|
335 * @return string |
|
336 */ |
|
337 protected function _getUrl() |
|
338 { |
|
339 /* Figure out how much we need to pad the email */ |
|
340 $numPad = self::ENCRYPTION_BLOCK_SIZE - (strlen($this->_email) % self::ENCRYPTION_BLOCK_SIZE); |
|
341 |
|
342 /* Pad the email */ |
|
343 $emailPadded = str_pad($this->_email, strlen($this->_email) + $numPad, chr($numPad)); |
|
344 |
|
345 /* Encrypt the email */ |
|
346 $emailEncrypted = mcrypt_encrypt(self::ENCRYPTION_CIPHER, $this->_privateKeyPacked, $emailPadded, self::ENCRYPTION_MODE, self::ENCRYPTION_IV); |
|
347 |
|
348 /* Return the url */ |
|
349 return self::MAILHIDE_SERVER . '?k=' . $this->_publicKey . '&c=' . strtr(base64_encode($emailEncrypted), '+/', '-_'); |
|
350 } |
|
351 } |