web/enmi/Zend/Service/ReCaptcha/MailHide.php
changeset 19 1c2f13fd785c
parent 0 4eba9c11703f
equal deleted inserted replaced
18:bd595ad770fc 19:1c2f13fd785c
       
     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 }