1

How can i rewrite all external links with a single onmousedown event?

Kinda like what facebooks does with it's link shim

Please check the original Facebook Article about the link shim: http://on.fb.me/zYAq0N

Requirements:

  • Should work for all subdomains on mainsite.com.

  • Should redirect example.com to mainsite.com/link.cgi?u=http://example.com

  • Should only redirect links not belonging to mainsite.com.

Uses:

This is for security of the users of a private web app, and to protect referrers.

Best to do it on the fly for good UI as pointed out in the FB article.

That's so when users hovers over some link it shows the correct link but when he clicks it, js redirects it to my.site.com/link.cgi=http://link.com

Thanks in advance

SOLVED: https://gist.github.com/2342509

Carlos Barbosa
  • 1,422
  • 2
  • 23
  • 42
  • no evil, it's to protect my users, on my web app, from external sites. – Carlos Barbosa Apr 08 '12 at 14:25
  • 2
    Then, just rewrite the links entirely so the user can see where they are going to be taken when they hover. Why show them X, but take them to Y. That's deception. – jfriend00 Apr 08 '12 at 14:26
  • as you can see in the FB article i linked, for good UI, on the fly my redirect will only stop my users if site is considered with malware, we are going to use the safebrowsing api from google for the endpoint: – Carlos Barbosa Apr 08 '12 at 14:27
  • I've tested and written code to spoof the referrer, see [this answer](http://stackoverflow.com/a/8957778/938089?what-is-the-most-reliable-way-to-hide-spoof-the-referrer-in-javascript). It was done by rewriting the URL to a `data:`-URI on click. Replace the `data:`-URI with any URI, and there you are. The user will not see the updated link, but it redirects correctly. – Rob W Apr 08 '12 at 14:29
  • From FB article: Good UX In order to make for a simpler user experience, we don't want to write these link shim links directly into the site. If we did, then when anyone hovered over them, their browser would show the Facebook url and not the actual destination. In order to work around this, we install an onmousedown handler that modifies the link on the fly after the person has clicked it, so their browser hits the link shim first, but they don't see gobbledygook when they mouseover it. In browsers that don't support javascript, we fall back to simply rewriting these URLs directly. – Carlos Barbosa Apr 08 '12 at 14:31
  • No need to rewrite, if you hook into the `click` event in which you do your thing (which should include stopping propagation and returning false to prevent the normal `href` target to be used) you'll get that sort of functionality. That said, bear in mind that you should not use such things to annoy the user, so if you use it to track links clicked or whatever fine, but don't send the user somewhere else. – Lucero Apr 08 '12 at 14:32

2 Answers2

5

For an individual link:

function $(id){ return document.getElementById(id); }
$(link).onclick = function(){ this.href = "http://otherlink.com"; }

<a href="http://example.com" id="link">My Sheisty Link</a>

So to get all external links:

window.onload = function(){
var links = document.getElementsByTagName("a");
for(a in links){
  var thisLink = links[a].href.split("/")[2];
  if(thisLink !=== window.location.hostname){
    links[a].href = "http://mainsite.com/link.cgi?u=" + links[a]; }
  // Or you could set onclick like the example above
  // May need to accommodate "www"
}}

Edit:
Found this answer and got a better idea.

document.onclick = function (e) {
 e = e ||  window.event;
 var element = e.target || e.srcElement;

if (element.tagName == 'A') {
 var link = element.href.split("/")[2];
  if(link !=== window.location.hostname){
    links[a].href = "http://mainsite.com/link.cgi?u=" + links[a]; }
    return false; // prevent default action and stop event propagation
  }else{ return true; }
}};
Community
  • 1
  • 1
Gary
  • 13,303
  • 18
  • 49
  • 71
1

If you use jQuery then the following will work

$('a:link').mousedown(function() { 
  this.href = 'http://my.site.com/link.cgi=' + this.href; 
});

Otherwise

var anchors = document.getElementsByTagName('a');
for(var i = 0; i < anchors.length; i++) {
  var a = anchors[i];
  if(a.href) {
    a.addEventListener('mousedown', function(e) {
      this.href = 'http://my.site.com/link.cgi=' + this.href;
    }, false);
  }
}
Vincent McNabb
  • 33,327
  • 7
  • 31
  • 53