A project I’m working on needs to output text that may have e-mail addresses in it to the Web. Because we don’t want people’s e-mail addresses exposed to spammers, I had to write an obfuscation class to make sure those e-mail addresses are hidden somehow. I haven’t decided what method to hide those addresses with yet (I’m leaning towards Mailhide), but I thought I’d post the base code now. The class is written so that you can extend it to hide the addresses however you like. Here’s the class (PHP 5 only, but would be easy to convert to PHP 4).
/**
* Simple Obfuscation Class
*
* The beginning of an obfuscation class, made primarily to obfuscate
* email addresses within a block of text or HTML. Used in conjunction
* with reCAPTCHA's Mailhide service or
* a database-driven e-mail address hider.
*
* LICENSE
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details .
*
* @author Chris Morrell
* @copyright Copyright 2008 Chris Morrell
* @version 0.1
* @license GPL
*
*/
class Galahad_Obfuscator
{
const EMAIL_ANCHOR = 101;
const EMAIL_URL = 102;
const EMAIL_DISPLAY = 103;
protected $mailtoRegexp = '/((.*?)<\/a>/is';
protected $emailRegexp = '/\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b/i';
/**
* Public method to obfuscate all e-mail addresses in a string
*
* @param string $string
* @return string
*/
public function emailAddresses($string)
{
$string = $this->replaceMailto($string);
$string = $this->replaceEmail($string);
return $string;
}
/**
* Private function to replace all e-mail addresses with
* obfuscated string (most often links)
*
* @param string $string
* @return string
*/
private function replaceEmail($string)
{
$string = preg_replace_callback($this->emailRegexp, array($this, 'processEmail'), $string);
return $string;
}
/**
* Private function to handle all found e-mail addresses in string
*
* @param array $matches
* @return string
*/
private function processEmail($matches)
{
return $this->obfuscateEmail($matches[0], self::EMAIL_ANCHOR);
}
/**
* Private function to replace all mailto: anchors with
* obfuscated anchors
*
* @param string $string
* @return string
*/
private function replaceMailto($string)
{
$string = preg_replace_callback($this->mailtoRegexp, array($this, 'processMailto'), $string);
return $string;
}
/**
* Private function to handle all found mailto: anchors
*
* @param array $matches
* @return string
*/
private function processMailto($matches)
{
$newUrl = $this->obfuscateEmail($matches[2], self::EMAIL_URL);
$inner = $matches[4];
if (preg_match($this->emailRegexp, $inner)) {
$inner = $this->obfuscateEmail($inner, self::EMAIL_DISPLAY);
}
return "{$matches[1]}{$newUrl}{$matches[3]}>{$inner}";
}
/**
* Subclass this method to obfuscate the address however you see
* fit (whether with Mailhide or some other system). Right now
* this function isn't very helpful, as it obfuscates all e-mail
* addresses and links them to #
*
* @param string $email
* @param int $type
* @return string
*/
protected function obfuscateEmail($email, $type = self::EMAIL_ANCHOR)
{
$email = substr($email, 0, strpos($email, '@') + 1) . '...';
if ($type == self::EMAIL_ANCHOR) {
return "<a href="\">{$email}</a>";
} else if ($type == self::EMAIL_URL) {
return "#";
}
return $email;
}
}
Here’s some sample usage:
class My_Obfuscator extends Galahad_Obfuscator
{
protected function obfuscateEmail($email, $type = self::EMAIL_ANCHOR)
{
$id = $this->emailToId($email);
$email = substr($email, 0, strpos($email, '@') + 1) . '...';
if ($type == self::EMAIL_ANCHOR) {
return "<a href="\">{$email}</a>";
} else if ($type == self::EMAIL_URL) {
return "http://yoursite.com/get-email.php?id={$id}";
}
return $email;
}
private function emailToId($email)
{
// Implement this by adding the email to a database
// and returning the row's ID, for example
return rand(1,500);
}
}
$html = 'some string with e-mail addresses in it.';
$obfuscator = new My_Obfuscator();
echo $obfuscator->emailAddresses($html);
So far the class has worked well with limited testing. Obviously it handles both e-mail addresses in plain text and mailto: links. Please let me know if you find any bugs in it, or have a suggestion about how to make it better.
Related posts:
- Crazy idea… I’ve been toying with the idea of using my cache...
- Zend Framework: Using separate layouts per module Someone was recently asking on ZFTalk about how to use...
- PHP Modeling (in Zend Framework) I’ve been thinking a lot about Modeling in a MVC...
- Simple PHP Pavatar Method Microsoft Passport was a good idea. OpenID is a better...
- More PHP Modeling (w/ video demo) [Updated with follow-up video] About a month ago I posted...