Tuesday, May 27, 2008

Intranet Feed Reader - Firefox Add On

I just ported Michal Bali's iGoogle gadget: Intranet Feed Reader. The add on can be found here. Again, log in is required for download since it is still in sandbox.

The add on adds capabilities to read intranet feeds into your Firefox's sidebar:


More details can be found at this Michal's blog post:
http://blog.decaresystems.ie/index.php/2008/05/20/google-gadget-intranet-feed-reader/

I will just shortly quote the conclusion of the article:

The intranet feed reader gadget can be used as part of a developer’s dashboard. It can display any intranet feed. Most useful might be information necessary for day-to-day work (e.g. current assigned issues in the bug tracking system, changed resources in company’s wiki or version control system).
Here is in short how to setup and use it:
After installation there will be new menu item added to the Firefox's Tools menu - Internet Feed Reader. It has sub menu items Properties and Show Panel, intuitively Properties are setting up the extension and Show Panel is showing sidebar panel with the feed contents.
Parameters of the Properties dialog are:
  • XML Url: required, url of the rss feed you want to follow
  • XML2JSONP Proxy Url: required, url of the XML to JSONP proxy. The extension uses JSONP to display the feed contents so proxy is required to convert XML feed to JSONP. How to setup the proxy for testing the extension is following up shortly
  • cookiesJson: optional, authentication cookie if required by the feed provider
Test the extension
In order to test extension you will need XML2JSONP Proxy. Basic implementation of the proxy by Michal Bali can be found here:
http://michalbali.googlepages.com/xml2jsonp
I did install the Apach Tomcat 6.0 and setup the xml2json.war from the proxy's site. After installation XML2JSONP Proxy Url parameter would look like something like this:
http://localhost:8080/xml2json/Xml2JsonpProxyServlet
Just put any feed url into XML Url, maybe:
http://blog.decaresystems.ie/index.php/author/mbali/feed/
And after setting up the stuff just click on Tools > Intranet Feed Reader > Show Panel.

IMPORTANT!!!
Use only trusted XML 2 JSONP proxy, ideally from your own machine or from your intranet. JSONP works by injecting Javascript into the page thus using untrusted server might cause injection of malicious code and by doing that in the priviledged mode that the extension is working in can cause serious damage to your computer!

Related articles:
http://digitalmihailo.blogspot.com/2008/05/make-jsonp-work-in-firefox-chrome.html

Sunday, May 25, 2008

Make JSONP work in Firefox Chrome

I have been doing some Firefox extension and I needed to do some JSONP Ajax call in the sidebar and then show the result. jQuery makes it easy, you do something like:




$.ajax({
type: "GET",
dataType: "jsonp",
url: "http://someurl.com",
data: aRequestData,
cache: false,
error: function (XMLHttpRequest, textStatus, errorThrown) {
// typically only one of textStatus or errorThrown
// will have info
alert("Error occured textStatus=" + textStatus + " errorThrown=" + errorThrown);
},
success: function(data) {
alert('success');
}
});




Plain and simple and it works in browser window, however, to my big surprise it did not work in Chrome, never got to the success alert. After turning on Firebug I got an error from jQuery: head is null. OK, What is JSONP?
How it works is that script is injected into the head element of the HTML document. Source of the script is a link to the external server that is providing customized javascript function call with the retrieved data. Upon receiving data jQuery is deleting that script element.
So head is null indeed since document.getElementsByTag("head") is not returning enything since I don't have head element in my XUL file:



<?xml version="1.0"?>
<?xml-stylesheet href="chrome://browser/skin/browser.css" type="text/css" ?>
<?xml-stylesheet href="chrome://intranetfeedreader/skin/sidebar.css" type="text/css"?>
<!DOCTYPE prefwindow SYSTEM "chrome://intranetfeedreader/locale/intranetfeedreader.dtd">

<page id="sbIntranetFeedReaderSidebar" title="&sidebar.title;"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
>
<script src="jquery-1.2.3.js"/>
<script src="sidebar.js"/>
<vbox flex="1">
<label id="atest" value="&sidebar.title;" />
</vbox>
</page>



So nothing fancy but no head tag. Well lets add head tag and see if we can trick the jQuery:



<?xml version="1.0"?>
<?xml-stylesheet href="chrome://browser/skin/browser.css" type="text/css" ?>
<?xml-stylesheet href="chrome://intranetfeedreader/skin/sidebar.css" type="text/css"?>
<!DOCTYPE prefwindow SYSTEM "chrome://intranetfeedreader/locale/intranetfeedreader.dtd">

<page id="sbIntranetFeedReaderSidebar" title="&sidebar.title;"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
>
<head>
<script src="jquery-1.2.3.js"/>
<script src="sidebar.js"/>
</head>
<vbox flex="1">
<label id="atest" value="&sidebar.title;" />
</vbox>
</page>



And it worked :) I got rid of the error, but still no success alert. To make the long story short: injection of scripts this way is not working in Chrome. It will allow only urls starting with chrome://. Well it should work that way, working from browser window is pretty harmless (well it depends ...) compared to working in chrome where the code has much more privileges and can do some serious damage. I am not really convinced that getting the data this way is really smart thing to do, simply injecting javascript code from another server is scary - I can imagine that it is not too hard to inject whatever harmful code this way.
So I guess one big warning is due for the reminder of the post:

WARNING!!!! The following code should be used only with trusted servers. Ideally only in intranet. Never, never, never use this code with server that you do not trust 100%. Of course you are using this code on your own risk.

Since the injection of the script by purely adding script element to the document does not work in chrome then we have to do the script loading manually. Idea is to download the script ourselves and then execute it ourselves. That is not hard at all, and here is (almost) all the code:



var scriptCollection = document.getElementsByTagName("script");
var reader = new httpReader(scriptCollection[scriptCollection.length - 1].src);

function evaluateJs(aReader){
if(aReader && aReader.mData)
eval(aReader.mData);
}

reader.AsyncLoad(bind(evaluateJs, this, reader));


The code is really simple, firstly we get all the script elements from the document, then we initialize httpReader object with the source of the last script (jQuery is appending it to the head, well keep all your scripts enclosed in the head tag or modify the code to get the correct script). evaluateJs is simply helper function that is calling eval function on the script we get from the server. And at the end we asyncronuosly load the url with the script.

This code executes javascript code as browser would in the normal html document - get the script and then execute it. Some further testing should probably be involved here to check the code we are going to evaluate but anyhow if you plan on using this approach you should really take security seriously into consideration.

The last bit is httpReader, it is simple implementation from the article: Creating Sandboxed HTTP Connections from the developer.mozilla.org. bind functions are based on Firebug code. And the file is here.

Monday, May 12, 2008

Baby boy Luka

I just got a baby boy Luka:


He was born on 7th May 2008 in Cork University Maternity Hospital. That was the happiest day of my life, and probably the scariest at the same time :)

Just wanted to say one big Thank You! to everyone in CUMH - they were all absolutely brilliant, I have never seen so many nice people in the same place in my life. Everyone was so nice and caring, we've seen like 50 people in three days we've been there and I have no words to describe how nice they all were. Guys we love you all!