Last updated August 26, 2009. Created by adixon on May 10, 2006.
Edited by ronald_istos, Senpai, add1sun, Dublin Drupaller. Log in to edit this page.
Here's a way to obfuscate emails from spam harvesters using just your theme.
Setting aside the question of whether it really works and how long it might work, on this particular site we wanted the site-wide but weak protection that this provides. Most of the existing obfuscation techniques are parts of modules, but here the more reliable (and potentially efficient?) mechanism is to do all your obfuscation at once at the theme level. In this case, the emails were being exposed by the civicrm module in the profiles.
The actual obfuscation is done by encoding the address in javascript so that most users won't actually notice, with the usual obfuscation as a fallback if the user has no javascript.
So here it is in two parts:
1. In your template.php file, add these two functions:
function _phptemplate_encode_mailto($mail) {
$link = 'document.write(\'<a href="mailto:' . $mail . '">' . $mail . '</a>\');';
$js_encode = ''; for ($x = 0; $x < strlen($link); $x++) {
$js_encode .= '%' . bin2hex($link{$x});
}
$link = '<script type="text/javascript" language="javascript">eval(unescape(\''.$js_encode.'\'))</script>';
$link .= '<noscript>'.str_replace(array('@','.'),array(' at ',' dot '),$mail). '</noscript>';
return $link;
}
function phptemplate_safemail($text) {
if (strpos($text, '@') === FALSE)
return $text;
// Split at <a> and </a> so that we can avoid encoding addresses in link text.
$t = preg_replace(":(</?a):i", "\001\\1", strtr($text, "\r\n", "\002\003"));
$a = explode("\001", $t);
$n = count($a);
for ($i = 0; $i < $n; ++$i) {
if (preg_match('/^(<a[^>]*)mailto:([^@]+@[-.a-z0-9]+)(.*)/i', $a[$i], $m)) {
$a[$i] = _phptemplate_encode_mailto($m[2]);
$a[1+$i] = substr($a[1+$i],4);
}
else if (!preg_match('/^(.*)(<input[^>]+)[-.a-z0-9]+@[-.a-z0-9]+.*\/>/i',$a[$i])) {
while (preg_match('/(.*)[^-.a-z0-9]([-.a-z0-9]+)(@[-.a-z0-9]+)(.*)$/i', $a[$i], $m)) {
$a[$i] = $m[1] . _phptemplate_encode_mailto($m[2].$m[3]) . $m[4];
}
}
}
return strtr(implode('', $a), "\002\003", "\r\n");
}...and then add this fragment inside php tags in your page.tpl.php page (before the $content gets printed of course..).
It won't obfuscate emails in the /admin section or on edit forms. There may be some other pages that you don't want obfuscated as well.
<?php
if (function_exists('phptemplate_safemail') && ('admin' != arg(0))) :
$larg = arg(-1 + count(explode('/', $_GET['q'])));
if ('edit' != $larg) {
$content = phptemplate_safemail($content);
}
endif;
?>With thanks to:
- walkah for the javascript trick (i.e. most of the first function)
- whoever's responsible for http://www.settingtheworldtorights.com/node/417 for the regular expressions (i.e., most of the second function)
- jason of cooptools.ca for asking me to assemble the pieces and document it here
and apologies if this looks like a repeat of a forum article I posted, it is (someone suggested this is a better spot for it).
Comments
Just a note of caution
If the email address is immediately adjacent to an HTML tag (such as
Eish!
Fix for adjacent HTML tag
Just change the while loop to match this one. Seems to fix the problem here.
<?phpwhile (preg_match('/(.*)([^-.a-z0-9])([-.a-z0-9]+)(@[-.a-z0-9]+)(.*)$/i', $a[$i], $m)) {
$a[$i] = $m[1] . $m[2] . _phptemplate_encode_mailto($m[3].$m[4]) . $m[5];
}
?>
Test
Is there any way to know whether this code is working aside from not getting errors once making these additions to the template and page.tpl? Is there a way to test it out?
Thanks