Coded something up in Couch in an interesting way? Have a snippet or shortcode to share? Post it here for the community to benefit.
18 posts Page 1 of 2
Email Guardian Tag
Automatically Obfuscate All Email Addresses
email-guardian.zip
(4 KiB) Downloaded 2282 times

Simply wrap any code with the email_guardian tag to find and obfuscate email addresses.
Code: Select all
<cms:email_guardian>
  <cms:show my_blog_post />
</cms:email_guardian>

The email_guardian tag will find all plain text email addresses and mailto links, obfuscating them by using a cipher with a random key and reversing the order of characters to hide them from spambots. A JavaScript routine then decodes them for displaying normally on the page. You can wrap an entire page with the tag or use multiple tags to wrap specific content.

Parameters:
no_script_message - If Javascript is disabled, this message will be displayed instead of the expected content. The default is 'JavaScript required to see this email address.'

create_links - For free floating plaintext email addresses, the Email Guardian helpfully converts the address to a clickable mailto link. To turn off this feature and simply obfuscate text email addresses without converting them, set the parameter create_links="0".

Installing the Add-On
To use this tag, unzip and add the folder to your 'couch/addons' directory. Initiate the tag in 'couch/addons/k_functions.php'.
Code: Select all
require_once( K_COUCH_DIR.'addons/email-guardian/email-guardian.php' );

https://github.com/fallingsprings/couch ... l-guardian



*The zip file above is a new, more capable and more robust update to the Email Guardian tag. The original post below remains purely for historical purposes.*

I created a website for someone with very low confidence on a computer. Explaining about mailto links and email obfuscation was not an option. She needed to be able to just type email addresses anywhere without having to think about it.

So I made the email_guardian tag to scan for email addresses and automatically obfuscate them using Couch's cloak_email tag.

I know a lot of people don't think twice about posting an email address on the web, so this tag could be a useful tool for designers who want to make it easy for people but still keep them protected.

Simply wrap any portion of code in the <cms:email_guardian> tag to scan for and encrypt all email addresses.
Code: Select all
<cms:email_guardian>
    <cms:show my_blog_post />
</cms:email_guardian>

To enable the tag, add the following code to your couch/addons/kfunctions.php file.
Code: Select all
//This tag is deprecated. Please download the zip file instead.
class CustomTags {
    static function email_guardian( $params, $node ){
        global $FUNCS;
        foreach( $node->children as $child ){
            $html .= $child->get_HTML();
        }
        preg_match_all('/\b[^\s]+@[^\s]+/', strip_tags(htmlspecialchars_decode($html, ENT_QUOTES)), $emails);
        foreach($emails[0] as $email){
            $email = trim(strtolower($email), ".,;:?!\"\'‘’‚“”„‹›-+&#*%$@~`^()|<>[]{}/\\");
            $code = $FUNCS->embed( "<cms:cloak_email email='{$email}' />", $is_code=1 );
            $pos = strpos($html, $email);
            if ($pos !== false) {
                $html = substr_replace($html, $code, $pos, strlen($email));
            }
        }
        return $html;
    }
}
$FUNCS->register_tag( 'email_guardian', array('CustomTags', 'email_guardian') );
This is great Tim - my congratulations :D :D :D
+1 for this from me too?

I guess most "normal users" (picture a busy small business owner) will have difficulties keeping the shorthand mailto tag in their mind...
tim wrote: I created a website for someone with very low confidence on a computer. Explaining about mailto links and email obfuscation was not an option. She needed to be able to just type email addresses anywhere without having to think about it.

So I made the email_guardian tag to scan for email addresses and automatically obfuscate them using Couch's cloak_email tag.

I know a lot of people don't think twice about posting an email address on the web, so this tag could be a useful tool for designers who want to make it easy for people but still keep them protected.

Simply wrap any portion of code in the <cms:email_guardian> tag to scan for and encrypt all email addresses.
Code: Select all
<cms:email_guardian>
    <cms:show my_blog_post />
</cms:email_guardian>

To enable the tag, add the following code to your couch/addons/kfunctions.php file.
Code: Select all
class CustomTags {
    static function email_guardian( $params, $node ){
        global $FUNCS;
        foreach( $node->children as $child ){
            $html .= $child->get_HTML();
        }
        preg_match_all('/\b[^\s]+@[^\s]+/', strip_tags(htmlspecialchars_decode($html, ENT_QUOTES)), $emails);
        foreach($emails[0] as $email){
            $email = trim(strtolower($email), ".,;:?!\"\'‘’‚“”„‹›-+&#*%$@~`^()|<>[]{}/\\");
            $code = $FUNCS->embed( "<cms:cloak_email email='{$email}' />", $is_code=1 );
            $pos = strpos($html, $email);
            if ($pos !== false) {
                $html = substr_replace($html, $code, $pos, strlen($email));
            }
        }
        return $html;
    }
}
$FUNCS->register_tag( 'email_guardian', array('CustomTags', 'email_guardian') );


Hi Tim

I have needed something like on a clients site so it protects the email links from spam so done the following

kfunctions.php file in the root
Code: Select all
class CustomTags {
    static function email_guardian( $params, $node ){
        global $FUNCS;
        foreach( $node->children as $child ){
            $html .= $child->get_HTML();
        }
        preg_match_all('/\b[^\s]+@[^\s]+/', strip_tags(htmlspecialchars_decode($html, ENT_QUOTES)), $emails);
        foreach($emails[0] as $email){
            $email = trim(strtolower($email), ".,;:?!\"\'‘’‚“”„‹›-+&#*%$@~`^()|<>[]{}/\\");
            $code = $FUNCS->embed( "<cms:cloak_email email='{$email}' />", $is_code=1 );
            $pos = strpos($html, $email);
            if ($pos !== false) {
                $html = substr_replace($html, $code, $pos, strlen($email));
            }
        }
        return $html;
    }
}
$FUNCS->register_tag( 'email_guardian', array('CustomTags', 'email_guardian') );


includes/header.php
Code: Select all
<a href="mailto:<cms:email_guardian><cms:get_custom_field 'header_email_link' masterpage='globalstwo.php'/>"></cms:email_guardian>
<i class="bx bx-envelope"></i>
Email: <cms:email_guardian><cms:get_custom_field 'header_email_link' masterpage='globalstwo.php'/></cms:email_guardian>
</a>


Just unsure if it's worked or not, the email address is showing and the mailto link looks correct but unsure if it's scanning for email addresses and automatically obfuscate them using Couch's cloak_email tag. The source code looks like the following

Code: Select all
<a href="mailto:email@domain.co.uk">
<i class="bx bx-envelope"></i>
Email: email@domain.co.uk
</a>


Is there a way it should look if it's worked or is the above correct?
Hi Ian.

When this tag or the cms:cloak_email tag is working properly, it returns pure javascript that builds a mailto: link on the page, thus hiding the email from scrapers. The source will end up looking like this, but the page will show an email link.
Code: Select all
<span id="vXmtb9ElYQHct70S">(Please enable JavaScript to view this email address)</span><script>
(function() {
var v0Lyk8lq6EQc5IRU = ["109","97","105","x6c","x74","111","58","109","121","x65","109","97","105","x6c","x40","103","109","x61","x69","x6c","x2e","x63","x6f","109"];
var vdyBb3wYH8jSSA2e = ["109","x79","101","109","x61","105","108","64","103","109","97","x69","x6c","x2e","99","x6f","x6d"];
var vtKBwtp1SfpPPPEW = "<a hr" + "ef=\"";
for (var i = 0; i < v0Lyk8lq6EQc5IRU.length; i++) vtKBwtp1SfpPPPEW += '&#' + v0Lyk8lq6EQc5IRU[i] + ';';
vtKBwtp1SfpPPPEW += '">';
for (var i = 0; i < vdyBb3wYH8jSSA2e.length; i++) vtKBwtp1SfpPPPEW += '&#' + vdyBb3wYH8jSSA2e[i] + ';';
vtKBwtp1SfpPPPEW += '</a>';
document.getElementById('vXmtb9ElYQHct70S').innerHTML = vtKBwtp1SfpPPPEW;
})();
</script>

The script creates the mailto: link, so you don't have to hard code the <a> tag at all, just put the plain email address inside the couch tag.

Unfortunately, because the tag builds the whole <a> tag from javascript, I don't know any way that you can put the fancy envelope icon *<i class="bx bx-envelope"></i>* into it without modifying the cloak_email tag. These tags only produce a text link.

When I tried your code, the source didn't look normal at all. It was garbled.

This tag works more like this, but I don't know how to get the envelope icon inside of the <a> tag without changing the Couch source code:
Code: Select all
<cms:email_guardian>
<i class="bx bx-envelope"></i>
Email: <cms:get_custom_field 'header_email_link' masterpage='globalstwo.php'/>
</cms:email_guardian>
Thank you Tim, it's working now as the source code now looks like the following

Code: Select all
<i class="bx bx-envelope"></i>
                                            Email: <span id="vcGrbviiQ1c8HK4d">(Please enable JavaScript to view this email address)</span><script>
(function() {
var viOoRmEAJbdRHzWv = ["109","x61","x69","108","x74","111","x3a","x69","x6e","x66","x6f","x40","x73","109","97","114","x74","114","x65","x70","x61","x69","114","45","x69","x74","46","99","111","46","117","107"];
var vKEUR8GnbZgXuHoU = ["x69","110","102","111","x40","x73","x6d","97","x72","116","114","x65","x70","97","x69","114","45","x69","116","46","x63","x6f","46","x75","107"];
var v07p1enQZy1Ndvx9 = "<a hr" + "ef=\"";
for (var i = 0; i < viOoRmEAJbdRHzWv.length; i++) v07p1enQZy1Ndvx9 += '&#' + viOoRmEAJbdRHzWv[i] + ';';
v07p1enQZy1Ndvx9 += '">';
for (var i = 0; i < vKEUR8GnbZgXuHoU.length; i++) v07p1enQZy1Ndvx9 += '&#' + vKEUR8GnbZgXuHoU[i] + ';';
v07p1enQZy1Ndvx9 += '</a>';
document.getElementById('vcGrbviiQ1c8HK4d').innerHTML = v07p1enQZy1Ndvx9;
})();
</script>


Just need to find a way to get the envelope icon inside the a tag somehow, wonder if css:before or after would work?
I altered the css so the icon looks the same as it was inside the a tag before the spam protection code was added and looks good
It is good you made it work. I might have an important comment though (admins can move it to a separate topic, i do not mind) -

Tag cms:cloak_email appears in tags.php, anyone can see that it does one thing - takes a string, converts it to HTML Unicode entities and puts those back inside the <a> tag. All the bells and whistles about randomly generated names of the variables in that code is pure smoke.

Long story short, I spent some time with it and found a native javascript function String.fromCharCode();. With this function a stream of charcodes can be combined to a string and that string is the HTML we look for.

The salt here is that the existing algorithm can actually encrypt any HTML - from a small text to huge blocks.
If effort is applied, then a new tag may appear - cms:cloak_string. Such tag could be used inside Tim's shortcode or in any other new shortcode. Any passed parameter to such shortcode would be cloaked and it means that we can write the HTML ourselves as in
Code: Select all
<a href="<cms:cloak_string 'mailto:email@domain.co.uk' />" ><i class="bx bx-envelope"></i>Email:</a>

Native tag cms:cloak_email also takes care of the link generation because of one reason - it must inject the script after tag ended. In above code, the tag would not know where to inject the script, other than to the end of the whole page. Couch can not do that at the moment, but can be made to, of course (it is nice to have all js scripts before the closing 'body' tag). That said, the best scenario is to make a tag that knows where the text is ended and therefore knows where to inject the script afterwards. Example below is a tag that does not yet exist and my intention is to display the approach -
Code: Select all
<cms:cloak text='mailto:email@domain.co.uk'>
    <a href="<cms:show cloaked_text />">
        <i class="bx bx-envelope"></i>
        Email:
    </a>
</cms:cloak>

The above variant seems to have arbitrary complexity (extra param) - in the beginning of my post I showed cloaking of entire link. It says to me that a better approach could be as simple as this -
Code: Select all
<cms:cloak>
   // any html here
</cms:cloak>


Hope it clears some smoke around the functionality of cms:cloak_email and opens new perspectives.
That's good to know and very useful info Trendoman thank you
Ian,
Glad you sorted this out and high five for thinking of the CSS trick to inject the envelope.

Now that it's working, I wanted to say that using the <cms:cloak_email> tag directly might be better for your use case.

The email_guardian tag was meant to protect users from themselves. You wrap it around content that the client is entering in case they might put in an email address without understanding the dangers. In your case you know it's an email, so there's no need to add the extra layer of the email_guardian.
Code: Select all
<i class="bx bx-envelope"></i>
<cms:cloak_email email="<cms:get_custom_field 'header_email_link' masterpage='globalstwo.php'/>" title="Email: <cms:get_custom_field 'header_email_link' masterpage='globalstwo.php'/>" />
18 posts Page 1 of 2