Smarty Forum Index Smarty
The discussions here are for Smarty, a template engine for the PHP programming language.

[Output Filter] Obfuscating email addresses

 
Post new topic   Reply to topic    Smarty Forum Index -> Plugins
View previous topic :: View next topic  
Author Message
andre
Smarty Pro


Joined: 23 Apr 2003
Posts: 164
Location: Karlsruhe, Germany

PostPosted: Tue Mar 16, 2004 8:30 am    Post subject: [Output Filter] Obfuscating email addresses Reply with quote

Hi,

for a very small CMS I wrote I needed an output filter which obfuscates all email addresses to prevent spam robots from harvesting them. To use the Smarty built-in {mailto} plugin wasn't possible here.

So here's the plugin code which works very well for me Wink :
[php:1:3890828dcf]
<?php
function smarty_outputfilter_obfuscate_email( $tpl_source, &$smarty ) {
preg_match_all('!<a\s([^>]*)href=["\']mailto:([^"\']+)["\']([^>]*)>(.*?)</a[^>]*>!is', $tpl_source, $matches);

// $matches[0] contains full matched string: <a href="...">...</a>
// $matches[1] contains additional parameters
// $matches[2] contains the email address which was specified as href
// $matches[3] contains additional parameters
// $matches[4] contains the text between the opening and closing <a> tag
$replace = $matches[0];
foreach ($matches[0] as $key => $match) {
$address = $matches[2][$key];
$obfuscated_address = str_replace(array(".","@"), array(" dot ", " at "), $address);
$extra = trim($matches[1][$key]." ".$matches[3][$key]);
$text = $matches[4][$key];
$obfuscated_text = str_replace(array(".","@"), array(" dot ", " at "), $text);

$string = "var e; if (e = document.getElementById('obfuscated_email_".$key."')) e.style.display = 'none';\n";
$string .= "document.write('<a href=\"mailto:".$address."\" ".$extra.">".$text."</a>');";
$js_encode = '';
for ($x=0; $x < strlen($string); $x++) {
$js_encode .= '%' . bin2hex($string[$x]);
}
$replace[$key] = '<a id="obfuscated_email_'.$key.'" href="mailto:'.$obfuscated_address.'">'.$obfuscated_text.'</a><script type="text/javascript" language="javascript">eval(unescape(\''.$js_encode.'\'))</script>';
}

$tpl_source = str_replace($matches[0], $replace, $tpl_source);

return $tpl_source;
}
?>
[/php:1:3890828dcf]

This filter plugin replaces all <a href=" ... "> ... </a> tags with a special JavaScript code which cannot be harvested. The code is based upon the original {mailto} plugin. I also included an additional text which is shown to users who disabled JavaScript. In this case the address is displayed this way: myname at example dot com

Feedback is welcome Smile
Back to top
View user's profile Send private message
sopel
Smarty n00b


Joined: 07 Jul 2004
Posts: 1

PostPosted: Tue Feb 01, 2005 8:55 pm    Post subject: Reply with quote

not everyone has javascript enabled. i would rather suggest much simpler modifier :

[php:1:2753b696a2]
function smarty_modifier_antispam($string)
{
$converted_str = '';
for ($i = 0,$count = strlen($string); $i<; $i++) {
$converted_str .= '&#'.ord(substr($string, $i, 1)).';';
}
return $converted_str;
}
[/php:1:2753b696a2]

probably it's not so (much) effective as javascript method, but works everywhere.
_________________
http://sopel.webd.pl
Back to top
View user's profile Send private message Visit poster's website
ingenious
Smarty Rookie


Joined: 17 Mar 2005
Posts: 15
Location: Sofia, Bulgaria

PostPosted: Thu Mar 17, 2005 5:39 pm    Post subject: Reply with quote

The above given function is already in the list of functions that come along with Smarty:

Code:
<a href="mailto:{$EmailAddress|escape:"hex"}">{$EmailAddress|escape:"hexentity"}</a>
Back to top
View user's profile Send private message Visit poster's website
mohrt
Administrator


Joined: 16 Apr 2003
Posts: 7368
Location: Lincoln Nebraska, USA

PostPosted: Thu Mar 17, 2005 5:49 pm    Post subject: Reply with quote

There is also a {mailto} function that comes with Smarty that does much of the same. It is not an output filter though, it must be specified in the template.

http://smarty.php.net/mailto
Back to top
View user's profile Send private message Visit poster's website
php_pete
Smarty n00b


Joined: 25 Sep 2005
Posts: 2

PostPosted: Sun Sep 25, 2005 8:21 pm    Post subject: Reply with quote

This is a great piece of code and saved me a load of hassle when I wanted to obfuscate email addressed in database stored html, which meant that I couldn't use the email smarty tags.

I found a problem with the code though. If you have the same email address repeated on a single page then the str_replace function replaces all those email addresses with the first regex match. This means that all the ids of the obfuscated email addresses are the same (obfuscated_email_0) and wreaks havoc when the javascript tries to do its stuff.

Here is an alternative which uses a rather nasty global variable. Any body got any better ideas?

[php:1:c08f228f24]
<?php

function smarty_outputfilter_obfuscate_email( $tpl_source, &$smarty ) {
global $obfuscated_email_count;
$obfuscated_email_count = 0;
$tpl_source = preg_replace_callback(
'!<a\s([^>]*)href=["\']mailto:([^"\']+)["\']([^>]*)>(.*?)</a[^>]*>!is',
'do_it',
$tpl_source);
return $tpl_source;
}

function do_it($matches) {
global $obfuscated_email_count;

// $matches[0] contains full matched string: <a href="...">...</a>
// $matches[1] contains additional parameters
// $matches[2] contains the email address which was specified as href
// $matches[3] contains additional parameters
// $matches[4] contains the text between the opening and closing <a> tag

$address = $matches[2];
$obfuscated_address = str_replace(array(".","@"), array(" dot ", " at "), $address);
$extra = trim($matches[1]." ".$matches[3]);
$text = $matches[4];
$obfuscated_text = str_replace(array(".","@"), array(" dot ", " at "), $text);

$string = "var e; if (e = document.getElementById('obfuscated_email_".$obfuscated_email_count."')) e.style.display = 'none';\n";
$string .= "document.write('<a href=\"mailto:".$address."\" ".$extra.">".$text."</a>');";
$js_encode = '';
for ($x=0; $x < strlen($string); $x++) {
$js_encode .= '%' . bin2hex($string[$x]);
}
$replace = '<a id="obfuscated_email_'.$obfuscated_email_count.'" href="mailto:'.$obfuscated_address.'">'.$obfuscated_text.'</a><script type="text/javascript" language="javascript">eval(unescape(\''.$js_encode.'\'))</script>';

++$obfuscated_email_count;

return $replace;
}
?>
[/php:1:c08f228f24]

Pete
Back to top
View user's profile Send private message
boots
Administrator


Joined: 16 Apr 2003
Posts: 5611
Location: Toronto, Canada

PostPosted: Sun Sep 25, 2005 11:27 pm    Post subject: Reply with quote

Maybe make $obfuscated_email_count a member var on the $smarty object and then put do_it as a method on the object. In your callback you would use array($smarty, 'do_it') as the callback param. Just an idea.
Back to top
View user's profile Send private message
php_pete
Smarty n00b


Joined: 25 Sep 2005
Posts: 2

PostPosted: Mon Sep 26, 2005 7:28 am    Post subject: Reply with quote

That does the trick nicely thanks.

I was playing with the idea of enclosing the entire plugin in a class but still had to have a global object of that class kicking around.

It would have been good if we could have had plug classes as well as callbacks so then we could have more power over these kinds of things. And then we wouldn't need to stick these things into the smarty class and maintain a bit more encapsulation of the functionality.
Back to top
View user's profile Send private message
alarconcepts
Smarty Rookie


Joined: 28 May 2005
Posts: 18
Location: NY

PostPosted: Sun Aug 06, 2006 9:55 am    Post subject: Reply with quote

I needed an output filter that converts both html email-links and text-emails into ASCII equivalents. When all else fails, roll your own, right? So I did...

Wink

ASCII Email Encoder

Enjoy!

- John
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Smarty Forum Index -> Plugins All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group
Protected by Anti-Spam ACP