// ==UserScript==
// @name         RSS+Atom Feed Subscribe Button Generator
// @description  Finds RSS and/or Atom links on a page and inserts feed subscription links for use by aggregators
// @namespace    http://loonyone.livejournal.com
// @include      http://*
// @include      https://*
// @creator      Manpreet Singh |junkblocker<at>yahoo<dot>com|
// @source       http://userscripts.org/scripts/show/688
// @identifier   http://userscripts.org/scripts/source/688.user.js
// @version      1.0
// @date         2007-04-09
// ==/UserScript==

// Version 1.0 - Added auto update without requiring an external script
// Version 0.9 - Added a close button
// Version 0.8 - Checks some wiki feeds with ?action=rss_rc and feeds with /rss/$ or /atom/$
// Version 0.7 - Check for feedburner feeds
// Version 0.6 - Fixed a major issue with using snapshotLength when it was not available
// Version 0.5 - Updated contact info
// Version 0.4 - Added optional auto-update facility
// Version 0.3 - Added some speed optimizations
// Version 0.2 - Merged Iain Brodfoot's floating div behaviour and removed purl.org links
//             - Allow revert to old behaviour by hand editing this script
// Version 0.1 - First release

/*
 * Options contribution by Iain Broadfoot (ibroadfo@geeksoc.org)
 * - remove link to purl
 *   (Manually edit this script to restore old behaviour. See TWEAK NOTE 1 below)
 * - Float the buttons to enable better behaviour on blogger/blogspot.com
 *   (Manually edit this script to restore old behaviour. See TWEAK NOTE 2 below)
 *
 * Mostly lifted from
 *   Generate RSS and ATOM tags: http://highbyte.bounceme.net/greasemonkey/genrsslinkrel.user.js
 *   Amazon Atom Injector:       http://docs.g-blog.net/code/greasemonkey/amazon_xml_feeds.user.js
 *   Add RSS Index:              http://www.xs4all.nl/~jlpoutre/BoT/Javascript/RSSpanel/rsspanel.user.js
 */

(function () {
/*
  var SCRIPT_METADATA = {
    name: 'RSS+Atom Feed Subscribe Button Generator',
    url: 'http://userscripts.org/scripts/source/688.user.js',
    version: "1.0",
  };
  function autoUpdate(SCRIPT) {
    try {
      if (!GM_getValue) return;
      // avoid a flood of dialogs e.g. when opening a browser with multiple tabs set to homepage and a script with * includes
      var DoS_PREVENTION_TIME = 2 * 60 * 1000;
      var isSomeoneChecking = GM_getValue('CHECKING', null);
      var now = new Date().getTime();
      GM_setValue('CHECKING', now.toString());
      if (isSomeoneChecking && (now - isSomeoneChecking) < DoS_PREVENTION_TIME) return;
      var lastChecked = GM_getValue('LAST_CHECKED', null);

      var ONE_DAY = 24 * 60 * 60 * 1000;
      if (lastChecked && (now - lastChecked) < ONE_DAY) return;
      GM_xmlhttpRequest({
        method: 'GET',
        url: SCRIPT.url,
        onload: function(result) {
          if (!result.responseText.match(/@version\s+([\d.]+)/)) return;
          var theOtherVersion = RegExp.$1;
          if (theOtherVersion == SCRIPT.version) return;
          if (window.confirm('A new version ' + theOtherVersion + ' of greasemonkey script "' + SCRIPT.name + '" is available.\nYour installed version is ' + SCRIPT.version + ' .\n\nUpdate now?\n')) {
            GM_openInTab(aScriptURL);
          }
        }
      });
      GM_setValue('LAST_CHECKED', now.toString());
    } catch (ex) {
    }
  }
  autoUpdate(SCRIPT_METADATA);
*/

  var ATOM_ICON  = '<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAAAPCAMAAAEzEIgrAAAAwFBMVEUiIiKZmZlmZmaIiIi7u7vMzMwzMzP5+fkRERHu7u6Wlpb9/f3KyspVVVXGxsb7+/t3d3fPz8/S0tLDw8P8/Py9vb2xsbG+vr6rq6u/v79ERETl5eXKq6vFxcXb29txcXGpqamysrLOzs6zu+J+fn4eHh56enoDHH7W1tb01NS3t7dSUlKrtN7ExMSzs7OapdXHx8e6urrLy8vAwMDHpaXMlZWstd/Jycm1veSurq6YmJibptXIyMgAAACIjXj///+BJyE6AAABVklEQVQ4y52T6VLbMBRGryRvIWSBhL0t0FL2rWXt8um8/1vxQ44xwemEfuOxRpqjoyvZMjUxBT1LMRKtNYqdI4gxmhACrKiIdUwA03WA1mBHjGDV4BdZ4RsSQ3LAMThiJEYiBgBf207SQoCA9TXO6m6zaBt0qBgr+wHfOFKmIMdMXz8JlKxCAthyQiRw3rhklgfr2oMHNkruu/cSZYDJZxJsAt+DcoVuMB8H9bTLNpegQrrQHEgCd4WQ/wk3DOXNVhaAmUwU+gLk/U5wVmPKDqOtptMBLn+OzGW1bkerG5O/nx74WOaFTvIAXG+XSb/3dkL8d2bCIFUmjV39TQ836/m/W5vpNcLUvn+/CnuDKqmc5BkdlPB48gf6+5LHZKyk+7JQmP7tRmhS8JKRSxqclnV9+cR1CxdoX4WQ9WaSbG8IwPTqc//9oS95hm+ztvN0ezcs+Z/oBckmBmW7bigcAAAAAElFTkSuQmCC" style="border:none;" />';
  var RSS_ICON   = '<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAAAPCAIAAAD8q9/YAAAA5ElEQVR4nOVWMQ7DIAw8V/krc5YMfUCGLp15LR1IHAvb0EopDNwEhzE+bAuAyUAAUkqjw+gEIlqOYaAb/MX0ej9v8PMfbOsO4DE6jN6YTvBSEvHsZ1nkmjTNBHL9AMhFvq27HkgDcxczxbRgPIfmEUowa4ipHEj91Z7nIOrw7kL7kUuesbmkbSzBOXssKVCbUQcXmTHBGWju0lVgei4cmsZWD2sZgS6RHqNCZAF1m292SaZyiZ5DyVgZxplDLmkmM35sYDjZa/anl/PMa+XNI3B9POZ4h4loumdpOsHT/aVHh9AdH916sSoQOJxpAAAAAElFTkSuQmCC" style="border:none;" />';
  var RDF_ICON   = '<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAAAPCAIAAAD8q9/YAAAA40lEQVR4nOVWoRbDIAy87PVf0TUVfEAFBs3XMsFGGUkA0RXBqfYIIUcSAFgMBCDGODuMh0BE2+fT0A3+QnTe3uDnPzj2E8BrdhhPYznBW02Ebz/nIh9hGFL9AEhFfuwn/ygNxFmZqX4rRnMoLsEEZxkhXno0Rlc70szaXnA/5ZBmLA5xG0lwSmD7GGvaOG+rzIjIGejO4lUgeq4cisZSD4+c2IbaZs7bLKBtMzKrZBqbqDksGSnDAAz9FPBIzqX4ytLim93tTy3niefKu0vgeniscQ8T0XLX0nKCl3tLzw7hcbwB232nKlQYcjEAAAAASUVORK5CYII=" style="border:none;" />';
  var XML_ICON   = '<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAAAPCAIAAAD8q9/YAAAA3klEQVR4nOVWuxKEIAzc3Piv1jYWfoCFjbVfyxU4EfMAbsaTgq1wCSGbBAHoDAQghNA6jJdARMM5HOkBf0fY9uUBP//BPK0APq3DeBvdCR4kcYSrvXlcJBVi/wCITT5Pqx6kBuYqZsSnYDyH5hZK8EinEqGHyQpwEHl4udB+0inP2JzSNkowYKjFPREVSkRlTHAFiqt0F5iehUPT2DrDnrBf/uTbvrCAvE3NqpTJJNFzmDL+GTbrrI1hJEIfHrN6xfPp1TzyWnlxC1wPjz7uYSLq7lrqTnB3b+nWIbyOLwOWtSLcWFU8AAAAAElFTkSuQmCC" style="border:none;" />';
  var CLOSE_ICON = '<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAScwAAEnMBjCK5BwAAABh0RVh0U29mdHdhcmUAUGFpbnQuTkVUIHYzLjA1G8PgXAAAAFRJREFUOE9jZGBg+A/EZIP/5ACYpRC9aQzEY6ByGmjG5Qpkcbw2oxuAhY/f2TAN2FxClJ/xeIFGNpPtZ4pDm1CCISrAcBmCoZnEBA4PbSgDll6JpgF1Tx8yB8tBWgAAAABJRU5ErkJggg==" style="border:none;" />';

  // array to keep track of 'seen' feed links.
  var seen = [];

  var fsbdiv = document.createElement("div");
  fsbdiv.setAttribute("id", "XmlButtons");
  fsbdiv.style.textAlign = "left";
  fsbdiv.style.margin = "0px";
  // top right bottom left
  fsbdiv.style.padding = "0px 3px 0px 3px";
  // TWEAK NOTE 1 START: Comment out the next three lines to disable the buttons from floating
  fsbdiv.style.position = "fixed";
  fsbdiv.style.top = "0px";
  fsbdiv.style.zIndex = "99999";
  // TWEAK NOTE 1 END

  // Get links already declared properly in <link> elements in <head>
  function getProperlyDeclaredTag() {
    var linkRelElems = document.getElementsByTagName("link");
    var tlink;
    var i = 0;

    while (tlink = linkRelElems[i++]) {
      var thref = tlink.href;
      var type = tlink.type;

      if (type && type.match(/.*\/rs[sd](\+xml)?$/)) {
        addRssLinkTag(thref, RSS_ICON);
      } else if (type && type.match(/.*\/atom\+xml$/)) {
        addRssLinkTag(thref, ATOM_ICON);
      } else if (type && type.match(/^text\/xml$/)) {
        addRssLinkTag(thref, RSS_ICON);
      }
    }
  }

  function getTagsFromAllLinkElements() {
    if( !document.links ) {
      document.links = document.getElementsByTagName("a");
    }
    var links = document.links;
    for (var a = 0, len = links.length; a < len ; a++) {
      var link = links[a];
      linkhref = link.href;

      if (linkhref.match(/(^(feed|rss):|[\.\/]rss([\.\/]xml|\.aspx|\.jsp|\/)?$|\/node\/feed$|\/rss\/[a-z0-9]+$|\?(rss|xml|rdf)=|\?action=rss_rc$|feeds\.feedburner\.com\/[a-z0-9]+$)/i)) {
        addRssLinkTag(linkhref, RSS_ICON);
      } else if (linkhref.match(/.*\/atom(\.xml|\.aspx|\.jsp|\/)?$/)) {
        addRssLinkTag(linkhref, ATOM_ICON);
      } else if (linkhref.match(/\/feeds?\/[^.\/]*\.xml$|.*\/index\.xml$|feed\/msgs\.xml(\?num=\d+)?$/)) {
        addRssLinkTag(linkhref, XML_ICON);
      } else if (linkhref.match(/.*\.rdf$/)) {
        addRssLinkTag(linkhref, RDF_ICON);
      }
    }
  }

  function beenThere(linkhref) {
    if (seen.length <= 0) return false;

    var href = linkhref.toLowerCase();
    for (var i = seen.length-1; i >=0; --i) {
      if (seen[i].toLowerCase() == href) return true;
    }

    return false;
  }

  function addRssLinkTag(linkhref, icon) {
    if (beenThere(linkhref)) {
      return;
    } else {
      seen.push(linkhref);
    }

    var flink = document.createElement("a");
    flink.innerHTML = icon;
    // this service creates link for all known aggregators which support RSS subscription service via
    // a URL
    // TWEAK NOTE 2 START : Uncomment the second line (and optionally comment the first line) below to retore linking to purl.org pages for easy subscription in feed readers
    flink.href = linkhref;
    // flink.href = "http://purl.org/net/syndication/subscribe/?rss=" + linkhref;
    // TWEAK NOTE 2 END
    flink.alt = linkhref;
    flink.title = linkhref;
    fsbdiv.appendChild(flink);
    fsbdiv.appendChild(document.createTextNode(" "));
  }

  getProperlyDeclaredTag();
  getTagsFromAllLinkElements();

  var body = document.getElementsByTagName("body")[0];
  // insert the div only if something was found
  if (seen.length > 0) {
    var head = document.getElementsByTagName('head');
    if (head && head[0]) {
      var closeButton = document.createElement('a');
      closeButton.innerHTML = CLOSE_ICON;
      closeButton.href = 'javascript: closeFSB();';
      closeButton.style.display = 'inline';
      closeButton.style.cursor = 'pointer';
      var s = document.createElement('script');
      s.language='javascript';
      s.type = 'text/javascript';
      s.text = 'function closeFSB(){try{document.getElementById("XmlButtons").style.display="none"}catch(e){}}';
      head[0].appendChild(s);
    }
    fsbdiv.insertBefore(closeButton, fsbdiv.firstChild);
    setTimeout(function() {
      body.insertBefore(fsbdiv, body.firstChild);
    }, 333); // hack to workaround the duplicated content problem
  }
})();

