RegExp.escape=function(str)
{var specials=new RegExp("[.*+?|()\\[\\]{}\\\\\\/]","g");return str.replace(specials,"\\$&");}
if(typeof JSON=="undefined"){JSON={};}
JSON.stringify=JSON.stringify||function(obj){var t=typeof(obj);if(t!="object"||obj===null){if(t=="string")obj='"'+obj+'"';return String(obj);}
else{var n,v,json=[],arr=(obj&&obj.constructor==Array);for(n in obj){v=obj[n];t=typeof(v);if(t=="string")v='"'+v+'"';else if(t=="object"&&v!==null)v=JSON.stringify(v);json.push((arr?"":'"'+ n+'":')+ String(v));}
return(arr?"[":"{")+ String(json)+(arr?"]":"}");}};JSON.parse=JSON.parse||function(str){if(str==="")str='""';eval("var p="+ str+";");return p;};xdRequest_callback_array=new Array();function xdRequest(inputURL){var remote_table_definition="http://xdrequest.googlecode.com/svn/trunk/xdRequest.xml";var baseYQLURL="https://query.yahooapis.com/v1/public/yql?format=json&debug=true&q=";var baseYQLStatement="USE '"+ remote_table_definition+"' AS remote;";this.post_body;this.post_hidden_fields=true;var self=this;var properties={"headers":[]};var cookiejar=new Array();var url=false;var html;this.setURL=function(inputURL){if(inputURL.match(/^https?:\/\/([\w]*\.)*[\w]{2,}$/)||inputURL.match(/^https?:\/\/([\w]*\.)*[\w]{2,}\/.*$/)){url=inputURL;}
else{throw"Invalid URL specified.";}
return self;}
this.getURL=function(){return url;}
this.header=function(name,value){properties.headers.push(new Array(name,value));return self;}
this.headers=function(){return properties.headers;}
this.get=function(param1,param2){if(!param1){throw"get method requires at least a callback function";}
if(!param2){if(!typeof param1=="function"){throw"If get is called with a single parameter, it must be a callback function.";}
callback=param1;}
else{if(!typeof param2=="function"){throw"Second parameter in get method must be a callback function.";}
try{this.setURL(param1);}
catch(err){throw"Malformed URL was specified in get method.";}
callback=param2;}
if(!typeof callback=="function"){throw"Callback needs to be a function.";}
properties.method="GET";var cookies=this.cookies();if(cookies){var cookieString="";for(var cookie in cookies){if(cookies[cookie].match(url,this.secure())){cookieString+=cookies[cookie].name+"="+ cookies[cookie].value+"; ";}}
cookieString=cookieString.replace(/; $/,"");this.header("Cookie",cookieString);}
var yqlStatement=baseYQLStatement+"SELECT * FROM remote WHERE url='"+ url+"' AND parameters='"+ JSON.stringify(properties)+"'";var yqlURL=baseYQLURL+ encodeURIComponent(yqlStatement).replace(/%255C'/g,"%5C'")+"&callback="+ encodeURIComponent(newCallback(callback,url));var script=document.createElement("script");script.id=url;script.src=yqlURL;document.body.appendChild(script);properties={"headers":[]};return self;}
this.post=function(param1,param2){if(!param1){throw"get method requires at least a callback function";}
if(!param2){if(!typeof param1=="function"){throw"If get is called with a single parameter, it must be a callback function.";}
callback=param1;}
else{if(!typeof param2=="function"){throw"Second parameter in get method must be a callback function.";}
try{this.setURL(param1);}
catch(err){throw"Malformed URL was specified in get method.";}
callback=param2;}
if(!typeof callback=="function"){throw"Callback needs to be a function.";}
if(!self.post_body){throw"Postbody required for post method";}
properties.method="POST";properties.postbody=self.post_body;if(self.post_hidden_fields){var hidden_fields=self.getHiddenFields();var field;if(hidden_fields){for(field in hidden_fields){properties.postbody+="&"+ hidden_fields[field].name+"="+ hidden_fields[field].value;}}}
var cookies=this.cookies();if(cookies){var cookieString="";for(var cookie in cookies){if(cookies[cookie].match(url,this.secure())){cookieString+=cookies[cookie].name+"="+ cookies[cookie].value+"; ";}}
cookieString=cookieString.replace(/; $/,"");this.header("Cookie",cookieString);}
var yqlStatement=baseYQLStatement+"SELECT * FROM remote WHERE url='"+ url+"' AND parameters='"+ JSON.stringify(properties)+"'";var yqlURL=baseYQLURL+ encodeURIComponent(yqlStatement).replace(/%255C'/g,"%5C'")+"&callback="+ encodeURIComponent(newCallback(callback,url));var script=document.createElement("script");script.id=url;script.src=yqlURL;document.body.appendChild(script);properties={"headers":[]};return self;}
function newCallback(callback,scriptID){xdRequest_callback_array.push(function(response){if(response.query){if(response.query.results.error){callback(response.query.results.error);}
else if(response.query.results.result.html.match(/org.mozilla.javascript.Undefined/)){var error={"error":"Invalid URL was specified."};callback(error);}
else{if(response.query.results.result.response_headers["set-cookie"]){addCookies(response.query.results.result.response_headers["set-cookie"]);}
if(response.query.results.result.status.match(/^3[\d]{2}/)){for(var header in response.query.results.result.response_headers){if(header=="location"){var redirect=response.query.results.result.response_headers[header];break;}}
self.get(redirect,callback);}
else if(response.query.results.result!=200){newresult=response.query.results.result;newresult.error=response.query.diagnostics.url[1]["http-status-message"];self.html=response.query.results.result.html;callback(response.query.results.result);}
else{self.html=response.query.results.result.html;callback(response.query.results.result);}}}
else{if(response.error){if(response.error.description.match(/mismatched character/)){error={"error":"Invalid parameters transmitted.  Please ensure that single quotes are properly escaped."}}
else{error={"error":response.error.description}}
callback(error);}
else{var error={"error":"Unknown error."};callback(error);}}
var script=document.getElementById(scriptID);try{script.parentNode.removeChild(script);}
catch(err){}});return"xdRequest_callback_array["+(xdRequest_callback_array.length-1).toString()+"]";}
this.addCookie=function(newCookieString){var newCookie;var cookieIndex;newCookie=new xdRequest_cookie(newCookieString);if(!newCookie.domain){newCookie.domain=this.domain();}
if(cookieIndex=getCookie(newCookie.name,newCookie.value,true)){cookiejar[cookieIndex].expiration=newCookie.expiration;}
else{cookiejar.push(newCookie);}
return self;}
function addCookies(newCookieArray){if(typeof newCookieArray=="string"){newCookieArray=[newCookieArray];}
for(var newCookie in newCookieArray){self.addCookie(newCookieArray[newCookie]);}
for(var index in cookiejar){if(cookiejar[index].isExpired()){deleteCookie(index);}}}
this.cookies=function(){var outputCookies=new Array();for(cookie in cookiejar){if(cookiejar[cookie].match(url,this.secure())){outputCookies.push(cookiejar[cookie]);}}
if(outputCookies.length>0){return outputCookies;}
else{return false;}}
this.secure=function(){if(url.match(/^https/)){return true;}
else{return false;}}
this.domain=function(){if(!url){return false;}
if(url.match(/^https?:\/\/([^\/]*).*/)){return url.match(/^https?:\/\/([^\/]*).*/)[1];}
return false;}
function getCookie(name,value,returnIndex){for(var index in cookiejar){if(name==cookiejar[index].name&&value==cookiejar[index].value){if(returnIndex){return index;}
else{return cookiejar[index];}}}
return false;}
function deleteCookie(cookie){if(typeof cookie=="number"){return cookiejar.splice(cookie,1);}
else if(typeof cookie=="xdRequest_cookie"){return cookiejar.splice(getCookie(cookie.name,cookie.value,true),1);}
else{return false;}}
this.getHiddenFields=function(){if(!this.html){return false;}
var inputs;if(inputs=this.html.match(/<\s*input[^>]*>/ig)){var hidden;var newInput;if(hidden=inputs.join("").match(/<\s*input(?:(?:(?!type\s*=\s*['"]hidden['"])[^>])*)type\s*=\s*['"]hidden['"][^>]*>/ig)){for(var x in hidden){newInput={};if(hidden[x].match(/.*name\s*=\s*['"]([^'"]*)['"].*/)){newInput.name=hidden[x].match(/.*name\s*=\s*['"]([^'"]*)['"].*/)[1];}
if(hidden[x].match(/.*value\s*=\s*['"]([^'"]*)['"].*/)){newInput.value=hidden[x].match(/.*value\s*=\s*['"]([^'"]*)['"].*/)[1];}
hidden[x]=newInput;}
return hidden;}
else{return false;}}
else{return false;}}
this.getInputs=function(){if(!this.html){return false;}
var inputs;var newInput;if(inputs=this.html.match(/<\s*input[^>]*>/ig)){for(var x in inputs){newInput={};if(inputs[x].match(/.*name\s*=\s*['"]([^'"]*)['"].*/)){newInput.name=inputs[x].match(/.*name\s*=\s*['"]([^'"]*)['"].*/)[1];}
if(inputs[x].match(/.*value\s*=\s*['"]([^'"]*)['"].*/)){newInput.value=inputs[x].match(/.*value\s*=\s*['"]([^'"]*)['"].*/)[1]}
inputs[x]=newInput;}
return inputs;}
else{return false;}}
this.getInput=function(name){var inputs=this.getInputs();if(inputs){for(var input in inputs){if(inputs[input].name==name){return inputs[input].value;}}}
return false;}
if(inputURL){this.setURL(inputURL);}}
function xdRequest_cookie(cookieString){this.name;this.value;this.domain;this.path;this.expiration;this.secure=false;this.isExpired=function(){if(this.expiration=="session"){return false;}
if(Date.parse(Date())>this.expiration){return true;}
else{return false;}}
this.match=function(url,compareSecure){if(this.isExpired()){return false;}
var compareDomain=url.match(/^https?:\/\/([^\/]*).*/);if(!compareDomain){throw"Invalid URL specified on cookie match.";}
compareDomain=compareDomain[1];if(!compareDomain.match(RegExp.escape(this.domain))){return false;}
if(!url.match(/^https?:\/\/[^\/]*\/.*/)){var comparePath="/";}
else{var comparePath=url.match(/^https?:\/\/[^\/]*(\/.*)/)[1];}
if(!comparePath.match(RegExp.escape("^"+ this.path))){return false;}
if(url.match(/^http:/)&&this.secure){return false;}
return true;}
if(cookieString){var propertyName;var propertyValue;var self=this;this.name=cookieString.split(/;\s*/)[0].match(/^([^=]*)=/)[1];this.value=cookieString.split(/;\s*/)[0].match(/^[^=]*=(.*)$/)[1];var properties=cookieString.split(/;\s*/);for(var property in properties){if(properties[property].match(/^([^=]*)=/)){propertyName=properties[property].match(/^([^=]*)=/)[1];propertyValue=properties[property].match(/^[^=]*=(.*)$/)[1];switch(propertyName){case"domain":case"Domain":this.domain=propertyValue.replace(/"|'/g,"");break;case"path":case"Path":this.path=propertyValue.replace(/"|'/g,"");break;case"expires":case"Expires":this.expiration=Date.parse(propertyValue.replace(/"|'/g,""));break;default:break;}}
else{switch(properties[property]){case"secure":this.secure=true;break;default:break;}}}
if(!this.expiration){this.expiration="session";}
return self;}}
