Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge branch 'master' of github.com:yql/yql-tables

  • Loading branch information...
commit dc73449d0665466ec0db514296898f9ff71b231d 2 parents 03ecafd + dbaa458
Sam Pullara authored
Showing with 1,694 additions and 882 deletions.
  1. +22 −1 amazon/amazon.ecs.xml
  2. +17 −0 brazil/correios/brazil.correios.encomendas.xml
  3. +0 −67 data/bonsai/bonsai.admin.xml
  4. +0 −208 data/bonsai/bonsai.branch.xml
  5. +0 −226 data/bonsai/bonsai.root.xml
  6. +19 −0 flickr/flickr.people.getInfo.xml
  7. +36 −0 foursquare/foursquare.addvenue.xml
  8. +15 −0 foursquare/foursquare.categories.xml
  9. +39 −0 foursquare/foursquare.checkin.xml
  10. +26 −0 foursquare/foursquare.checkins.xml
  11. +27 −0 foursquare/foursquare.flagclosed.xml
  12. +25 −0 foursquare/foursquare.friends.xml
  13. +26 −0 foursquare/foursquare.history.xml
  14. +36 −0 foursquare/foursquare.proposeedit.xml
  15. +27 −0 foursquare/foursquare.user.xml
  16. +32 −0 foursquare/foursquare.venue.xml
  17. +21 −0 foursquare/foursquare.venues.xml
  18. +89 −0 noaa/noaa.spc.day1otlk.xml
  19. +482 −0 oauth/json2.js
  20. +61 −0 oauth/oauth.xml
  21. +60 −47 openid/openid.assoc.xml
  22. +0 −56 openid/openid.ax.xml
  23. +55 −55 openid/openid.normalize.xml
  24. +168 −0 openid/openid.verify.xml
  25. +150 −136 openid/openid.xml
  26. +4 −5 openid/openid.yadis.xml
  27. +0 −31 openid/test.assoc.html
  28. +0 −49 openid/test.html
  29. +1 −1  simplegeo/simplegeo.checkins.xml
  30. +57 −0 simplegeo/simplegeo.density.xml
  31. +19 −0 slideshare/slideshare.slideshows.xml
  32. +37 −0 text/text.text.xml
  33. +33 −0 twitter/twitter.translate.xml
  34. +110 −0 uknutritionals/nutritionals.xml
View
23 amazon/amazon.ecs.xml
@@ -201,6 +201,27 @@
response.object = y.rest(signeduri).get().response;
]]></execute>
</select>
+ <select itemPath="ItemLookupResponse.Items.Item" produces="XML">
+ <urls>
+ <url>http://ecs.amazonaws.com/onca/xml?Service=AWSECommerceService</url>
+ </urls>
+ <inputs>
+ <key id="Operation" type="xs:string" paramType="query" required="false"
+ default="ItemLookup"/>
+ <key id="ItemId" type="xs:string" paramType="query" required="true"/>
+ <key id="MerchantId" type="xs:string" paramType="query" required="false"/>
+ <key id="AWSAccessKeyId" type="xs:string" paramType="query" required="true"/>
+ <key id="secret" type="xs:string" paramType="variable" required="true"/>
+ <key id="ResponseGroup" type="xs:string" paramType="query" required="false"/>
+ <key id="AssociateTag" type="xs:string" paramType="query" required="false"/>
+ <key id="Sort" type="xs:string" paramType="query" required="false"/>
+ <key id="Version" type="xs:string" paramType="query" required="false"
+ default="2009-03-31"/>
+ </inputs>
+ <execute><![CDATA[
+ var signeduri = getSignedURL(request.url, AWSAccessKeyId, secret);
+ response.object = y.rest(signeduri).get().response;
+ ]]></execute>
+ </select>
</bindings>
</table>
-
View
17 brazil/correios/brazil.correios.encomendas.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<table xmlns="http://query.yahooapis.com/v1/schema/table.xsd">
+ <meta>
+ <author>Guilherme Chapiewski</author>
+ <sampleQuery>select * from {table} where numero='EC884014459BR'</sampleQuery>
+ </meta>
+ <bindings>
+ <select itemPath="results.status" produces="XML">
+ <urls>
+ <url>http://correios-api.appspot.com/yql</url>
+ </urls>
+ <inputs>
+ <key id="numero" type="xs:string" paramType="query" required="true" />
+ </inputs>
+ </select>
+ </bindings>
+</table>
View
67 data/bonsai/bonsai.admin.xml
@@ -1,67 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<table xmlns="http://query.yahooapis.com/v1/schema/table.xsd">
- <meta>
- <author>Erik Eldridge</author>
- <description>
- </description>
- <sampleQuery>use 'http://test.erikeldridge.com/yql/tc.admin.xml' as tc.admin; insert into tc.admin (root) values("store://Is4R1AolbcX6Jdz7prCxi9")</sampleQuery>
- </meta>
- <bindings>
- <insert>
- <inputs>
- <key id="root" type="xs:string" paramType="variable" required="true"/>
- </inputs>
- <execute><![CDATA[
-
- y.include('http://test.erikeldridge.com/yql/json2.js');
-
- response.object = function(url) {
-
- var queries = [],
- results = [];
-
- //create leaf
- queries[0] = "insert into yql.storage.admin (value) values ('{json}')"
- .replace('{json}', JSON.stringify({'1st':'leaf'}));
- results[0] = y.xmlToJson(y.query(queries[0]).results);
-
- //create branch
- queries[1] = "insert into yql.storage.admin (value) values ('{json}')"
- .replace('{json}', JSON.stringify(results[0].results.inserted));
- results[1] = y.xmlToJson(y.query(queries[0]).results);
-
- //save branch to root
- queries[2] = "update yql.storage set value='{value}' where name='{name}'"
- .replace('{value}', JSON.stringify(results[1].results.inserted))
- .replace('{name}', root);
- results[2] = y.xmlToJson(y.query(queries[2]).results);
-
- return results[2];
- }();
- ]]></execute>
- </insert>
- <select>
- <inputs>
- <key id="root" type="xs:string" paramType="variable" required="true"/>
- </inputs>
- <execute><![CDATA[
-
- y.include('http://test.erikeldridge.com/yql/json2.js');
-
- response.object = function(url) {
-
- var queries = [],
- results = [];
-
- //create leaf
- queries[0] = "use 'http://test.erikeldridge.com/yql/bonsai.root.xml' as bonsai.root;"
- +"select * from bonsai.root where admin='true' and root='{root}'"
- .replace('{root}', root);
- results[0] = y.xmlToJson(y.query(queries[0]).results);
-
- return results[0].results;
- }();
- ]]></execute>
- </select>
- </bindings>
-</table>
View
208 data/bonsai/bonsai.branch.xml
@@ -1,208 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<table xmlns="http://query.yahooapis.com/v1/schema/table.xsd">
- <meta>
- <author>Erik Eldridge</author>
- <description>
- </description>
- <sampleQuery>use 'http://test.erikeldridge.com/yql/tc.admin.xml' as tc.admin; insert into tc.admin (root) values("store://Is4R1AolbcX6Jdz7prCxi9")</sampleQuery>
- </meta>
- <bindings>
- <select>
- <inputs>
- <key id="key" type="xs:string" paramType="variable" />
- <key id="select" type="xs:string" paramType="variable"/>
- <key id="update" type="xs:string" paramType="variable"/>
- <key id="admin" type="xs:string" paramType="variable" default="false" />
- </inputs>
- <execute><![CDATA[
-
- y.include('http://test.erikeldridge.com/yql/json2.js');
-
- response.object = function(url) {
-
- var queries = [],
- results = [];
-
- //get leaves
- queries[0] = 'select * from yql.storage where name="{select}"'
- .replace('{select}', select);
- results[0] = y.xmlToJson(y.query(queries[0]).results);
-
- //if admin mode, just dump sherpa keys
- if ('true' === admin) {
- return results[0].results.result.value
- }
-
- //count # leaves to determine if branch is full
- var count = 0;
- for each (var leaf in results[0].results.result.value) {
- count ++;
- }
-
- //key is not in branch
- if (!results[0].results.result.value[key]) {
- return {
- "meta" : {
- "count" : count,
- "select" : select,
- "update" : update,
- },
- "results" : false
- };
- }
-
- //key is in branch, so fetch & return value
- queries[1] = "select * from yql.storage where name='{name}'"
- .replace('{name}', results[0].results.result.value[key].select);
- results[1] = y.xmlToJson(y.query(queries[1]).results);
-
- return {
- "meta" : {
- "count" : count,
- "select" : select,
- "update" : update
- },
- "results" : results[1].results.result.value
- };
-
- }();
- ]]></execute>
- </select>
- <update>
- <inputs>
- <key id="key" type="xs:string" paramType="variable" required="true"/>
- <key id="select" type="xs:string" paramType="variable" required="true"/>
- <value id="val" type="xs:string" paramType="variable" required="true"/>
- </inputs>
- <execute><![CDATA[
-
- y.include('http://test.erikeldridge.com/yql/json2.js');
-
- response.object = function(url) {
-
- var queries = [],
- results = [];
-
- //get leaves
- queries[0] = 'select * from yql.storage where name="{select}"'
- .replace('{select}', select);
- results[0] = y.xmlToJson(y.query(queries[0]).results);
-
- //key is not in branch
- if (!results[0].results.result.value[key]) {
- return {"error":"key could not be found"};
- }
-
- //key is in branch, so update value
- queries[1] = "update yql.storage set value='{val}' where name='{update}'"
- .replace('{val}', val)
- .replace('{update}', results[0].results.result.value[key].update);
- results[1] = y.xmlToJson(y.query(queries[1]).results);
-
- return results[1];
- }();
- ]]></execute>
- </update>
- <insert>
- <inputs>
- <value id="key" type="xs:string" paramType="variable" required="true"/>
- <value id="val" type="xs:string" paramType="variable" required="true"/>
- <value id="select" type="xs:string" paramType="variable" required="true"/>
- <value id="update" type="xs:string" paramType="variable" required="true"/>
- </inputs>
- <execute><![CDATA[
-
- y.include('http://test.erikeldridge.com/yql/json2.js');
-
- response.object = function(url) {
-
- var queries = [],
- results = [];
-
- //get leaves
- queries[0] = 'select * from yql.storage where name="{select}"'
- .replace('{select}', select);
- results[0] = y.xmlToJson(y.query(queries[0]).results);
-
- //key is already in branch
- if (results[0].results.result.value[key]) {
- return {"error":"key already defined"};
- }
-
- //if this branch has a pool, extract leaf from it
- if (results[0].results.result.value['pool']) {
- for (var i in results[0].results.result.value['pool']) {
- var leaf = results[0].results.result.value['pool'][i];
- delete results[0].results.result.value['pool'][i];
- break;
- };
-
- //otherwise, create leaf
- } else {
- queries[1] = "insert into yql.storage.admin (value) values ('{val}')"
- .replace('{val}', val);
- results[1] = y.xmlToJson(y.query(queries[1]).results);
- var leaf = results[1].results.inserted;
- }
-
- //add leaf to leaves collection
- results[0].results.result.value[key] = leaf;
-
- //save leaves back to branch
- queries[2] = "update yql.storage set value='{val}' where name='{update}'"
- .replace('{val}', JSON.stringify(results[0].results.result.value))
- .replace('{update}', update);
-
- results[2] = y.xmlToJson(y.query(queries[2]).results);
-
- return results[2];
- }();
- ]]></execute>
- </insert>
- <delete>
- <inputs>
- <key id="key" type="xs:string" paramType="variable" required="true"/>
- <key id="select" type="xs:string" paramType="variable" required="true"/>
- <key id="update" type="xs:string" paramType="variable" required="true"/>
- </inputs>
- <execute><![CDATA[
-
- y.include('http://test.erikeldridge.com/yql/json2.js');
-
- response.object = function(url) {
-
- var queries = [],
- results = [];
-
- //get leaves
- queries[0] = 'select * from yql.storage where name="{select}"'
- .replace('{select}', select);
- results[0] = y.xmlToJson(y.query(queries[0]).results);
-
- //key is not in branch
- if (!results[0].results.result.value[key]) {
- return {"error":"key is not in branch"};
- }
-
- //add leaf to branch pool
- //note: i'd love to use an array for the pool, but it seems we're limited to objects
- if (!results[0].results.result.value['pool']) {
- results[0].results.result.value['pool'] = {};
- }
- results[0].results.result.value['pool'][key] = results[0].results.result.value[key];
-
- //remove leaf from branch
- delete results[0].results.result.value[key];
-
- //save updated branch
- queries[2] = "update yql.storage set value='{val}' where name='{update}'"
- .replace('{val}', JSON.stringify(results[0].results.result.value))
- .replace('{update}', update);
- results[2] = y.xmlToJson(y.query(queries[2]).results);
-
- return results[2];
- }();
- ]]></execute>
- </delete>
- </bindings>
-</table>
View
226 data/bonsai/bonsai.root.xml
@@ -1,226 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<table xmlns="http://query.yahooapis.com/v1/schema/table.xsd">
- <meta>
- <author>Erik Eldridge</author>
- <description>
- </description>
- <sampleQuery>use 'http://test.erikeldridge.com/yql/bonsai.root.xml' as table; select * from table where key="foo" and root="store://asd123"</sampleQuery>
- </meta>
- <bindings>
- <select>
- <inputs>
- <key id="key" type="xs:string" paramType="variable"/>
- <key id="root" type="xs:string" paramType="variable" required="true"/>
- <key id="admin" type="xs:string" paramType="variable" default="false"/>
- </inputs>
- <execute><![CDATA[
-
- var select = root;
-
- response.object = function(url) {
-
- var queries = [],
- results = [];
-
- //fetch branches
- queries[0] = 'select * from yql.storage where name="{select}"'
- .replace('{select}', select);
- results[0] = y.xmlToJson(y.query(queries[0]).results);
-
- //search in parallel for key in each branch
- queries[1] = [];
- for each (var branch in results[0].results.result.value) {
- if ('true' === admin) {
- queries[1].push(
- "use 'http://test.erikeldridge.com/yql/bonsai.branch.xml' as bonsai.branch;"
- +"select * from bonsai.branch where admin='true' and select='{select}'"
- .replace('{select}', branch.select)
- );
- } else {
- queries[1].push(
- "use 'http://test.erikeldridge.com/yql/bonsai.branch.xml' as bonsai.branch;"
- +"select * from bonsai.branch where key='{key}' and select='{select}'"
- .replace('{key}', key)
- .replace('{select}', branch.select)
- );
- }
- }
-
- queries[2] = 'use "http://test.erikeldridge.com/yql/query.multi.xml" as multi;'
- +'select * from multi where queries="{queries}"'
- .replace('{queries}', queries[1].join('-')//note this for query multi
- );
- results[1] = y.xmlToJson(y.query(queries[2]).results);
-
- //note: this only handles a single branch
- if ('true' === admin) {
- return {
- "branch":{
- "meta":results[0].results.result.value.branch,
- "leaves":results[1].results.results.result
- }
- }
- }
-
- if (results[1].results) {
- return results[1].results.results.result;
- }
-
- return {"error" : "key doesn't exists"};
- }();
- ]]></execute>
- </select>
- <update>
- <inputs>
- <key id="key" type="xs:string" paramType="variable" required="true"/>
- <key id="root" type="xs:string" paramType="variable" required="true"/>
- <value id="val" type="xs:string" paramType="variable" required="true"/>
- </inputs>
- <execute><![CDATA[
-
- var select = root;
-
- response.object = function(url) {
-
- var queries = [],
- results = [];
-
- //fetch branches
- queries[0] = 'select * from yql.storage where name="{select}"'
- .replace('{select}', select);
- results[0] = y.xmlToJson(y.query(queries[0]).results);
-
- //construct update queries for branch
- queries[1] = [];
- for each (var branch in results[0].results.result.value) {
- queries[1].push(
- "use 'http://test.erikeldridge.com/yql/bonsai.branch.xml' as bonsai.branch;"
- +"update bonsai.branch set val='{val}' where key='{key}' and select='{select}'"
- .replace('{val}', val)
- .replace('{key}', key)
- .replace('{select}', branch.select)
- );
- }
-
- queries[2] = 'use "http://test.erikeldridge.com/yql/query.multi.xml" as multi;'
- +'select * from multi where queries="{queries}"'
- .replace('{queries}', queries[1].join('-')//note this for query multi
- );
- results[1] = y.xmlToJson(y.query(queries[2]).results);
-
- if (results[1].results) {
- return results[1].results;
- }
-
- return {"error" : "key doesn't exists"};
- }();
- ]]></execute>
- </update>
- <insert>
- <inputs>
- <value id="key" type="xs:string" paramType="variable" required="true"/>
- <value id="root" type="xs:string" paramType="variable" required="true"/>
- <value id="val" type="xs:string" paramType="variable" required="true"/>
- </inputs>
- <execute><![CDATA[
-
- var select = root;
-
- response.object = function(url) {
-
- var queries = [],
- results = [];
-
- //fetch branches
- queries[0] = 'select * from yql.storage where name="{select}"'
- .replace('{select}', select);
- results[0] = y.xmlToJson(y.query(queries[0]).results);
-
- //construct select queries to find branch w/ space for new record
- queries[1] = [];
- for each (var branch in results[0].results.result.value) {
- queries[1].push(
- "use 'http://test.erikeldridge.com/yql/bonsai.branch.xml' as bonsai.branch;"
- +"select * from bonsai.branch where key='{key}' and select='{select}' and update='{update}'"
- .replace('{key}', key)
- .replace('{select}', branch.select)
- .replace('{update}', branch.update)
- );
- }
-
- queries[2] = 'use "http://test.erikeldridge.com/yql/query.multi.xml" as multi;'
- +'select * from multi where queries="{queries}"'
- .replace('{queries}', queries[1].join('-')//note this for query multi
- );
- results[1] = y.xmlToJson(y.query(queries[2]).results);
-
- for each (var result in results[1].results.results) {
- if (result.meta.count < 10) {
- queries[3] = "use 'http://test.erikeldridge.com/yql/bonsai.branch.xml' as bonsai.branch;"
- +"insert into bonsai.branch (key, val, select, update) values ('{key}', '{val}', '{select}', '{update}')"
- .replace('{key}', key)
- .replace('{val}', val)
- .replace('{select}', result.meta.select)
- .replace('{update}', result.meta.update);
- break;
- }
- }
-
- if (queries[3]) {
- results[2] = y.xmlToJson(y.query(queries[3]).results);
- return results[2];
- } else {
- return {"error" : "branch full"};
- }
-
- return {"error" : "key doesn't exists"};
- }();
- ]]></execute>
- </insert>
- <delete>
- <inputs>
- <key id="key" type="xs:string" paramType="variable" required="true"/>
- <key id="root" type="xs:string" paramType="variable" required="true"/>
- </inputs>
- <execute><![CDATA[
-
- var select = root;
-
- response.object = function(url) {
-
- var queries = [],
- results = [];
-
- //fetch branches
- queries[0] = 'select * from yql.storage where name="{select}"'
- .replace('{select}', select);
- results[0] = y.xmlToJson(y.query(queries[0]).results);
-
- //construct delete queries for branches
- queries[1] = [];
- for each (var branch in results[0].results.result.value) {
- queries[1].push(
- "use 'http://test.erikeldridge.com/yql/bonsai.branch.xml' as bonsai.branch;"
- +"delete from bonsai.branch where key='{key}' and select='{select}' and update='{update}'"
- .replace('{key}', key)
- .replace('{select}', branch.select)
- .replace('{update}', branch.update)
- );
- }
-
- queries[2] = 'use "http://test.erikeldridge.com/yql/query.multi.xml" as multi;'
- +'select * from multi where queries="{queries}"'
- .replace('{queries}', queries[1].join('-')//note this for query multi
- );
- results[1] = y.xmlToJson(y.query(queries[2]).results);
-
- if (results[1].results) {
- return results[1].results;
- }
-
- return {"error" : "key doesn't exists"};
- }();
- ]]></execute>
- </delete>
- </bindings>
-</table>
View
19 flickr/flickr.people.getInfo.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<table xmlns="http://query.yahooapis.com/v1/schema/table.xsd">
+ <meta>
+ <author>Fabio Kung &lt;fabio.kung@gmail.com&gt;</author>
+ <documentationURL>http://www.flickr.com/services/api/flickr.people.getInfo.html</documentationURL>
+ <sampleQuery>select * from {table} where user_id="26545327@N00"</sampleQuery>
+ </meta>
+ <bindings>
+ <select itemPath="rsp.person" produces="XML">
+ <urls>
+ <url env="all">http://api.flickr.com/services/rest/?method=flickr.people.getInfo</url>
+ </urls>
+ <inputs>
+ <key id="user_id" type="xs:string" paramType="query" />
+ <key id="api_key" type="xs:string" const="true" private="true" paramType="query" default="d98a5516040113c777323bea72473fc7"/>
+ </inputs>
+ </select>
+ </bindings>
+</table>
View
36 foursquare/foursquare.addvenue.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<table xmlns="http://query.yahooapis.com/v1/schema/table.xsd">
+ <meta>
+ <author>Andrew Guyton</author>
+ <documentationURL>http://groups.google.com/group/foursquare-api/web/api-documentation</documentationURL>
+ <sampleQuery>select * from {table}</sampleQuery>
+ </meta>
+ <bindings>
+ <select itemPath="" produces="XML">
+ <urls>
+ <url>http://api.foursquare.com/v1/addvenue</url>
+ </urls>
+ <inputs>
+ <key id="name" type="xs:string" paramType="query" required="true" />
+ <key id="address" type="xs:string" paramType="query" required="false" />
+ <key id="crossstreet" type="xs:string" paramType="query" required="false" />
+ <key id="city" type="xs:string" paramType="query" required="false" />
+ <key id="state" type="xs:string" paramType="query" required="false" />
+ <key id="zip" type="xs:string" paramType="query" required="false" />
+ <key id="phone" type="xs:string" paramType="query" required="false" />
+ <key id="geolat" type="xs:string" paramType="query" required="false" />
+ <key id="geolong" type="xs:string" paramType="query" required="false" />
+ <key id="primarycategoryid" type="xs:string" paramType="query" required="false" />
+ <key id="username" type="xs:string" paramType="variable" required="true" />
+ <key id="password" type="xs:string" paramType="variable" required="true" />
+ </inputs>
+ <execute>
+ <![CDATA[
+ y.include("http://yqlblog.net/samples/base64.js");
+ var authheader = "Basic "+Base64.encode(username+":"+password);
+ response.object = request.header("Authorization",authheader).post(y.queryParams).response;
+ ]]>
+ </execute>
+ </select>
+ </bindings>
+</table>
View
15 foursquare/foursquare.categories.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<table xmlns="http://query.yahooapis.com/v1/schema/table.xsd">
+ <meta>
+ <author>Andrew Guyton</author>
+ <documentationURL>http://groups.google.com/group/foursquare-api/web/api-documentation</documentationURL>
+ <sampleQuery>select * from {table}</sampleQuery>
+ </meta>
+ <bindings>
+ <select itemPath="" produces="XML">
+ <urls>
+ <url>http://api.foursquare.com/v1/categories</url>
+ </urls>
+ </select>
+ </bindings>
+</table>
View
39 foursquare/foursquare.checkin.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<table xmlns="http://query.yahooapis.com/v1/schema/table.xsd">
+ <meta>
+ <author>Andrew Guyton</author>
+ <documentationURL>http://groups.google.com/group/foursquare-api/web/api-documentation</documentationURL>
+ <sampleQuery>select * from {table}</sampleQuery>
+ </meta>
+ <bindings>
+ <select itemPath="" produces="XML">
+ <urls>
+ <url>http://api.foursquare.com/v1/checkin</url>
+ </urls>
+ <inputs>
+ <key id="vid" type="xs:string" paramType="query" required="false" />
+ <key id="venue" type="xs:string" paramType="query" required="false" />
+ <key id="shout" type="xs:string" paramType="query" required="false" />
+ <key id="private" type="xs:string" paramType="query" required="false" />
+ <key id="twitter" type="xs:string" paramType="query" required="false" />
+ <key id="facebook" type="xs:string" paramType="query" required="false" />
+ <key id="geolat" type="xs:string" paramType="query" required="false" />
+ <key id="geolong" type="xs:string" paramType="query" required="false" />
+ <key id="username" type="xs:string" paramType="variable" required="true" />
+ <key id="password" type="xs:string" paramType="variable" required="true" />
+ </inputs>
+ <execute>
+ <![CDATA[
+ if(!vid && !venue && !shout){
+ out = <error>I need a vid, venue or shout</error>
+ response.object = out;
+ } else {
+ y.include("http://yqlblog.net/samples/base64.js");
+ var authheader = "Basic "+Base64.encode(username+":"+password);
+ response.object = request.header("Authorization",authheader).post(y.queryParams).response;
+ }
+ ]]>
+ </execute>
+ </select>
+ </bindings>
+</table>
View
26 foursquare/foursquare.checkins.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<table xmlns="http://query.yahooapis.com/v1/schema/table.xsd">
+ <meta>
+ <author>Andrew Guyton</author>
+ <documentationURL>http://groups.google.com/group/foursquare-api/web/api-documentation</documentationURL>
+ <sampleQuery>select * from {table}</sampleQuery>
+ </meta>
+ <bindings>
+ <select itemPath="" produces="XML">
+ <urls>
+ <url>http://api.foursquare.com/v1/checkins</url>
+ </urls>
+ <inputs>
+ <key id="geolat" type="xs:string" paramType="query" required="false" />
+ <key id="geolong" type="xs:string" paramType="query" required="false" />
+ <key id="username" type="xs:string" paramType="variable" required="true" />
+ <key id="password" type="xs:string" paramType="variable" required="true" />
+ </inputs>
+ <execute><![CDATA[
+ y.include("http://yqlblog.net/samples/base64.js");
+ var authheader = "Basic "+Base64.encode(username+":"+password);
+ response.object = request.header("Authorization",authheader).get().response;
+ ]]></execute>
+ </select>
+ </bindings>
+</table>
View
27 foursquare/foursquare.flagclosed.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<table xmlns="http://query.yahooapis.com/v1/schema/table.xsd">
+ <meta>
+ <author>Andrew Guyton</author>
+ <documentationURL>http://groups.google.com/group/foursquare-api/web/api-documentation</documentationURL>
+ <sampleQuery>select * from {table} where vid="1"</sampleQuery>
+ </meta>
+ <bindings>
+ <select itemPath="" produces="XML">
+ <urls>
+ <url>http://api.foursquare.com/v1/flagclosed</url>
+ </urls>
+ <inputs>
+ <key id="vid" type="xs:string" paramType="query" required="true" />
+ <key id="username" type="xs:string" paramType="variable" required="true" />
+ <key id="password" type="xs:string" paramType="variable" required="true" />
+ </inputs>
+ <execute>
+ <![CDATA[
+ y.include("http://yqlblog.net/samples/base64.js");
+ var authheader = "Basic "+Base64.encode(username+":"+password);
+ response.object = request.header("Authorization",authheader).post(y.queryParams).response;
+ ]]>
+ </execute>
+ </select>
+ </bindings>
+</table>
View
25 foursquare/foursquare.friends.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<table xmlns="http://query.yahooapis.com/v1/schema/table.xsd">
+ <meta>
+ <author>Andrew Guyton</author>
+ <documentationURL>http://groups.google.com/group/foursquare-api/web/api-documentation</documentationURL>
+ <sampleQuery>select * from {table}</sampleQuery>
+ </meta>
+ <bindings>
+ <select itemPath="" produces="XML">
+ <urls>
+ <url>http://api.foursquare.com/v1/friends</url>
+ </urls>
+ <inputs>
+ <key id="uid" type="xs:string" paramType="query" required="false" />
+ <key id="username" type="xs:string" paramType="variable" required="true" />
+ <key id="password" type="xs:string" paramType="variable" required="true" />
+ </inputs>
+ <execute><![CDATA[
+ y.include("http://yqlblog.net/samples/base64.js");
+ var authheader = "Basic "+Base64.encode(username+":"+password);
+ response.object = request.header("Authorization",authheader).get().response;
+ ]]></execute>
+ </select>
+ </bindings>
+</table>
View
26 foursquare/foursquare.history.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<table xmlns="http://query.yahooapis.com/v1/schema/table.xsd">
+ <meta>
+ <author>Andrew Guyton</author>
+ <documentationURL>http://groups.google.com/group/foursquare-api/web/api-documentation</documentationURL>
+ <sampleQuery>select * from {table}</sampleQuery>
+ </meta>
+ <bindings>
+ <select itemPath="" produces="XML">
+ <urls>
+ <url>http://api.foursquare.com/v1/history</url>
+ </urls>
+ <inputs>
+ <key id="l" type="xs:string" paramType="query" required="false" />
+ <key id="sinceid" type="xs:string" paramType="query" required="false" />
+ <key id="username" type="xs:string" paramType="variable" required="true" />
+ <key id="password" type="xs:string" paramType="variable" required="true" />
+ </inputs>
+ <execute><![CDATA[
+ y.include("http://yqlblog.net/samples/base64.js");
+ var authheader = "Basic "+Base64.encode(username+":"+password);
+ response.object = request.header("Authorization",authheader).get().response;
+ ]]></execute>
+ </select>
+ </bindings>
+</table>
View
36 foursquare/foursquare.proposeedit.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<table xmlns="http://query.yahooapis.com/v1/schema/table.xsd">
+ <meta>
+ <author>Andrew Guyton</author>
+ <documentationURL>http://groups.google.com/group/foursquare-api/web/api-documentation</documentationURL>
+ <sampleQuery>select * from {table}</sampleQuery>
+ </meta>
+ <bindings>
+ <select itemPath="" produces="XML">
+ <urls>
+ <url>http://api.foursquare.com/v1/proposeedit</url>
+ </urls>
+ <inputs>
+ <key id="vid" type="xs:string" paramType="query" required="true" />
+ <key id="name" type="xs:string" paramType="query" required="true" />
+ <key id="address" type="xs:string" paramType="query" required="true" />
+ <key id="crossstreet" type="xs:string" paramType="query" required="false" />
+ <key id="city" type="xs:string" paramType="query" required="true" />
+ <key id="state" type="xs:string" paramType="query" required="true" />
+ <key id="zip" type="xs:string" paramType="query" required="false" />
+ <key id="phone" type="xs:string" paramType="query" required="false" />
+ <key id="geolat" type="xs:string" paramType="query" required="false" />
+ <key id="geolong" type="xs:string" paramType="query" required="false" />
+ <key id="username" type="xs:string" paramType="variable" required="true" />
+ <key id="password" type="xs:string" paramType="variable" required="true" />
+ </inputs>
+ <execute>
+ <![CDATA[
+ y.include("http://yqlblog.net/samples/base64.js");
+ var authheader = "Basic "+Base64.encode(username+":"+password);
+ response.object = request.header("Authorization",authheader).post(y.queryParams).response;
+ ]]>
+ </execute>
+ </select>
+ </bindings>
+</table>
View
27 foursquare/foursquare.user.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<table xmlns="http://query.yahooapis.com/v1/schema/table.xsd">
+ <meta>
+ <author>Andrew Guyton</author>
+ <documentationURL>http://groups.google.com/group/foursquare-api/web/api-documentation</documentationURL>
+ <sampleQuery>select * from {table}</sampleQuery>
+ </meta>
+ <bindings>
+ <select itemPath="" produces="XML">
+ <urls>
+ <url>http://api.foursquare.com/v1/user</url>
+ </urls>
+ <inputs>
+ <key id="uid" type="xs:string" paramType="query" required="false" />
+ <key id="badges" type="xs:string" paramType="query" required="false" />
+ <key id="mayor" type="xs:string" paramType="query" required="false" />
+ <key id="username" type="xs:string" paramType="variable" required="true" />
+ <key id="password" type="xs:string" paramType="variable" required="true" />
+ </inputs>
+ <execute><![CDATA[
+ y.include("http://yqlblog.net/samples/base64.js");
+ var authheader = "Basic "+Base64.encode(username+":"+password);
+ response.object = request.header("Authorization",authheader).get().response;
+ ]]></execute>
+ </select>
+ </bindings>
+</table>
View
32 foursquare/foursquare.venue.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<table xmlns="http://query.yahooapis.com/v1/schema/table.xsd">
+ <meta>
+ <author>Andrew Guyton</author>
+ <documentationURL>http://groups.google.com/group/foursquare-api/web/api-documentation</documentationURL>
+ <sampleQuery>select * from {table} where vid="125694"</sampleQuery>
+ </meta>
+ <bindings>
+ <select itemPath="" produces="XML">
+ <urls>
+ <url>http://api.foursquare.com/v1/venue</url>
+ </urls>
+ <inputs>
+ <key id="vid" type="xs:string" paramType="query" required="true" />
+ <key id="username" type="xs:string" paramType="variable" required="false" />
+ <key id="password" type="xs:string" paramType="variable" required="false" />
+ </inputs>
+ <execute><![CDATA[
+ if(username && password)
+ {
+ y.include("http://yqlblog.net/samples/base64.js");
+ var authheader = "Basic "+Base64.encode(username+":"+password);
+ response.object = request.header("Authorization",authheader).get().response;
+ }
+ else
+ {
+ response.object = request.get().response;
+ }
+ ]]></execute>
+ </select>
+ </bindings>
+</table>
View
21 foursquare/foursquare.venues.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<table xmlns="http://query.yahooapis.com/v1/schema/table.xsd">
+ <meta>
+ <author>Andrew Guyton</author>
+ <documentationURL>http://groups.google.com/group/foursquare-api/web/api-documentation</documentationURL>
+ <sampleQuery>select * from {table} where geolat="33.7772869" and geolong="-84.3976068"</sampleQuery>
+ </meta>
+ <bindings>
+ <select itemPath="" produces="XML">
+ <urls>
+ <url>http://api.foursquare.com/v1/venues</url>
+ </urls>
+ <inputs>
+ <key id="geolat" type="xs:string" paramType="query" required="true" />
+ <key id="geolong" type="xs:string" paramType="query" required="true" />
+ <key id="l" type="xs:string" paramType="query" required="false" />
+ <key id="q" type="xs:string" paramType="query" required="false" />
+ </inputs>
+ </select>
+ </bindings>
+</table>
View
89 noaa/noaa.spc.day1otlk.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<table xmlns="http://query.yahooapis.com/v1/schema/table.xsd">
+ <meta>
+ <author>Hank Marquardt</author>
+ <description>NOAA Storm Prediction Center Day 1 Outlook Data</description>
+ <sampleQuery>select * from {table} where areatype="TORNADO"</sampleQuery>
+ </meta>
+ <bindings>
+ <select itemPath="" produces="XML">
+ <urls>
+ <url env="all">http://www.spc.noaa.gov/products/outlook/day1otlk.html</url>
+ </urls>
+ <inputs>
+ <key id="areatype" type="xs:string" paramType="variable" required="false" />
+ <key id="debug" type="xs:string" paramType="variable" required="false" />
+ </inputs>
+ <execute><![CDATA[
+ var spcurl = "http://www.spc.noaa.gov/products/outlook/day1otlk.html";
+ var spcbase = "http://www.spc.noaa.gov";
+ var spcxpath = "//pre/a";
+ var q = y.query('select * from html where url = @url and xpath = @xpath',{'url': spcurl, 'xpath': spcxpath});
+
+ /*
+ This about killed me ... apparently response.object, does an internal call to xmlToJson on assignment
+ and that wasn't apparent to me, so I was flummoxed as to why my code wasn't working, the next line here solved
+ all that ... facepalm. Oh and thank you to y.log which helped me figure that out.
+ */
+
+ var myresults = y.xmlToJson(q.results);
+ var dataurl = spcbase+myresults.results.a.href;
+ var dataReq = y.rest(dataurl);
+ var rawData = dataReq.get().response;
+
+ /*
+ At this point, we have the raw SPC data for the current 1 day outlook, what follows is regex magic
+ and not for the faint of heart.
+ */
+
+ // Isolate the percentage fields then strip the new lines
+ rawData=rawData.replace(/([0-9]\.[0-9]{2}|SLGT|TSTM)/mg,'|$1|');
+ rawData=rawData.replace(/\n/mg,'');
+
+ // This gives us an array with each type isolated (ie TORNADO, HAIL, WIND)
+ var weatherArr = rawData.match(/\.\.\. (.+?) \.\.\.(.)+?&&/mg);
+
+ // Setup the output and log variables
+ var resultSet = [];
+ var resultIndex = 0;
+ var oLog = [];
+ var oLogIdx = 0;
+
+ for(var weatherType in weatherArr) {
+ wrkStr = weatherArr[weatherType];
+ wrkStr = wrkStr.replace(/^\.\.\. /,'');
+ wType = wrkStr.split(/ \.\.\./);
+ oType = wType[0]; // Output for 'type' eg. TORNADO, WIND
+ oData = wType[1]; // Data associated with type
+ wPcts = oData.match(/(\|[^\|]+\|)/g); // Gets values of Percents
+ wPctsData = oData.split(/\|[^\|]+\|/g); // Split data by Percents
+ wPctsData.shift(); // Throw out first value of split
+ oLog[oLogIdx++] = {'wPctsData': wPctsData};
+ for(var i in wPcts) {
+ oPct = wPcts[i].replace(/\|/g,''); // Percent value to be output
+ wPctData = wPctsData[i].match(/[0-9]{8}/g); // Grab all the lat/lon pairs
+ oLog[oLogIdx++] = {'wPctData': wPctData};
+ latlonSet = [];
+ latlonIndex = 0;
+ for(var j in wPctData) {
+ wLatLon = wPctData[j].match(/[0-9]{4}/g);
+ oLat = wLatLon[0]/100;
+ oLon = wLatLon[1]/100*-1; // Lon values are negative for US
+ latlonSet[latlonIndex++] = {'lat': oLat, 'lon': oLon};
+ }
+ if(areatype == oType || !areatype) {
+ resultSet[resultIndex++] = {'type': oType, 'probablity': oPct, 'areadata': latlonSet};
+ }
+ }
+ }
+
+ if(!debug) {
+ response.object={'data': resultSet, 'records': resultIndex};
+ } else {
+ response.object={'data': resultSet, 'records': resultIndex, 'oLogs': oLog};
+ }
+
+ ]]></execute>
+ </select>
+ </bindings>
+</table>
View
482 oauth/json2.js
@@ -0,0 +1,482 @@
+/*
+ http://www.JSON.org/json2.js
+ 2010-03-20
+
+ Public Domain.
+
+ NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+
+ See http://www.JSON.org/js.html
+
+
+ This code should be minified before deployment.
+ See http://javascript.crockford.com/jsmin.html
+
+ USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
+ NOT CONTROL.
+
+
+ This file creates a global JSON object containing two methods: stringify
+ and parse.
+
+ JSON.stringify(value, replacer, space)
+ value any JavaScript value, usually an object or array.
+
+ replacer an optional parameter that determines how object
+ values are stringified for objects. It can be a
+ function or an array of strings.
+
+ space an optional parameter that specifies the indentation
+ of nested structures. If it is omitted, the text will
+ be packed without extra whitespace. If it is a number,
+ it will specify the number of spaces to indent at each
+ level. If it is a string (such as '\t' or '&nbsp;'),
+ it contains the characters used to indent at each level.
+
+ This method produces a JSON text from a JavaScript value.
+
+ When an object value is found, if the object contains a toJSON
+ method, its toJSON method will be called and the result will be
+ stringified. A toJSON method does not serialize: it returns the
+ value represented by the name/value pair that should be serialized,
+ or undefined if nothing should be serialized. The toJSON method
+ will be passed the key associated with the value, and this will be
+ bound to the value
+
+ For example, this would serialize Dates as ISO strings.
+
+ Date.prototype.toJSON = function (key) {
+ function f(n) {
+ // Format integers to have at least two digits.
+ return n < 10 ? '0' + n : n;
+ }
+
+ return this.getUTCFullYear() + '-' +
+ f(this.getUTCMonth() + 1) + '-' +
+ f(this.getUTCDate()) + 'T' +
+ f(this.getUTCHours()) + ':' +
+ f(this.getUTCMinutes()) + ':' +
+ f(this.getUTCSeconds()) + 'Z';
+ };
+
+ You can provide an optional replacer method. It will be passed the
+ key and value of each member, with this bound to the containing
+ object. The value that is returned from your method will be
+ serialized. If your method returns undefined, then the member will
+ be excluded from the serialization.
+
+ If the replacer parameter is an array of strings, then it will be
+ used to select the members to be serialized. It filters the results
+ such that only members with keys listed in the replacer array are
+ stringified.
+
+ Values that do not have JSON representations, such as undefined or
+ functions, will not be serialized. Such values in objects will be
+ dropped; in arrays they will be replaced with null. You can use
+ a replacer function to replace those with JSON values.
+ JSON.stringify(undefined) returns undefined.
+
+ The optional space parameter produces a stringification of the
+ value that is filled with line breaks and indentation to make it
+ easier to read.
+
+ If the space parameter is a non-empty string, then that string will
+ be used for indentation. If the space parameter is a number, then
+ the indentation will be that many spaces.
+
+ Example:
+
+ text = JSON.stringify(['e', {pluribus: 'unum'}]);
+ // text is '["e",{"pluribus":"unum"}]'
+
+
+ text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
+ // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
+
+ text = JSON.stringify([new Date()], function (key, value) {
+ return this[key] instanceof Date ?
+ 'Date(' + this[key] + ')' : value;
+ });
+ // text is '["Date(---current time---)"]'
+
+
+ JSON.parse(text, reviver)
+ This method parses a JSON text to produce an object or array.
+ It can throw a SyntaxError exception.
+
+ The optional reviver parameter is a function that can filter and
+ transform the results. It receives each of the keys and values,
+ and its return value is used instead of the original value.
+ If it returns what it received, then the structure is not modified.
+ If it returns undefined then the member is deleted.
+
+ Example:
+
+ // Parse the text. Values that look like ISO date strings will
+ // be converted to Date objects.
+
+ myData = JSON.parse(text, function (key, value) {
+ var a;
+ if (typeof value === 'string') {
+ a =
+/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
+ if (a) {
+ return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
+ +a[5], +a[6]));
+ }
+ }
+ return value;
+ });
+
+ myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
+ var d;
+ if (typeof value === 'string' &&
+ value.slice(0, 5) === 'Date(' &&
+ value.slice(-1) === ')') {
+ d = new Date(value.slice(5, -1));
+ if (d) {
+ return d;
+ }
+ }
+ return value;
+ });
+
+
+ This is a reference implementation. You are free to copy, modify, or
+ redistribute.
+*/
+
+/*jslint evil: true, strict: false */
+
+/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
+ call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
+ getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
+ lastIndex, length, parse, prototype, push, replace, slice, stringify,
+ test, toJSON, toString, valueOf
+*/
+
+
+// Create a JSON object only if one does not already exist. We create the
+// methods in a closure to avoid creating global variables.
+
+if (!this.JSON) {
+ this.JSON = {};
+}
+
+(function () {
+
+ function f(n) {
+ // Format integers to have at least two digits.
+ return n < 10 ? '0' + n : n;
+ }
+
+ if (typeof Date.prototype.toJSON !== 'function') {
+
+ Date.prototype.toJSON = function (key) {
+
+ return isFinite(this.valueOf()) ?
+ this.getUTCFullYear() + '-' +
+ f(this.getUTCMonth() + 1) + '-' +
+ f(this.getUTCDate()) + 'T' +
+ f(this.getUTCHours()) + ':' +
+ f(this.getUTCMinutes()) + ':' +
+ f(this.getUTCSeconds()) + 'Z' : null;
+ };
+
+ String.prototype.toJSON =
+ Number.prototype.toJSON =
+ Boolean.prototype.toJSON = function (key) {
+ return this.valueOf();
+ };
+ }
+
+ var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
+ escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
+ gap,
+ indent,
+ meta = { // table of character substitutions
+ '\b': '\\b',
+ '\t': '\\t',
+ '\n': '\\n',
+ '\f': '\\f',
+ '\r': '\\r',
+ '"' : '\\"',
+ '\\': '\\\\'
+ },
+ rep;
+
+
+ function quote(string) {
+
+// If the string contains no control characters, no quote characters, and no
+// backslash characters, then we can safely slap some quotes around it.
+// Otherwise we must also replace the offending characters with safe escape
+// sequences.
+
+ escapable.lastIndex = 0;
+ return escapable.test(string) ?
+ '"' + string.replace(escapable, function (a) {
+ var c = meta[a];
+ return typeof c === 'string' ? c :
+ '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
+ }) + '"' :
+ '"' + string + '"';
+ }
+
+
+ function str(key, holder) {
+
+// Produce a string from holder[key].
+
+ var i, // The loop counter.
+ k, // The member key.
+ v, // The member value.
+ length,
+ mind = gap,
+ partial,
+ value = holder[key];
+
+// If the value has a toJSON method, call it to obtain a replacement value.
+
+ if (value && typeof value === 'object' &&
+ typeof value.toJSON === 'function') {
+ value = value.toJSON(key);
+ }
+
+// If we were called with a replacer function, then call the replacer to
+// obtain a replacement value.
+
+ if (typeof rep === 'function') {
+ value = rep.call(holder, key, value);
+ }
+
+// What happens next depends on the value's type.
+
+ switch (typeof value) {
+ case 'string':
+ return quote(value);
+
+ case 'number':
+
+// JSON numbers must be finite. Encode non-finite numbers as null.
+
+ return isFinite(value) ? String(value) : 'null';
+
+ case 'boolean':
+ case 'null':
+
+// If the value is a boolean or null, convert it to a string. Note:
+// typeof null does not produce 'null'. The case is included here in
+// the remote chance that this gets fixed someday.
+
+ return String(value);
+
+// If the type is 'object', we might be dealing with an object or an array or
+// null.
+
+ case 'object':
+
+// Due to a specification blunder in ECMAScript, typeof null is 'object',
+// so watch out for that case.
+
+ if (!value) {
+ return 'null';
+ }
+
+// Make an array to hold the partial results of stringifying this object value.
+
+ gap += indent;
+ partial = [];
+
+// Is the value an array?
+
+ if (Object.prototype.toString.apply(value) === '[object Array]') {
+
+// The value is an array. Stringify every element. Use null as a placeholder
+// for non-JSON values.
+
+ length = value.length;
+ for (i = 0; i < length; i += 1) {
+ partial[i] = str(i, value) || 'null';
+ }
+
+// Join all of the elements together, separated with commas, and wrap them in
+// brackets.
+
+ v = partial.length === 0 ? '[]' :
+ gap ? '[\n' + gap +
+ partial.join(',\n' + gap) + '\n' +
+ mind + ']' :
+ '[' + partial.join(',') + ']';
+ gap = mind;
+ return v;
+ }
+
+// If the replacer is an array, use it to select the members to be stringified.
+
+ if (rep && typeof rep === 'object') {
+ length = rep.length;
+ for (i = 0; i < length; i += 1) {
+ k = rep[i];
+ if (typeof k === 'string') {
+ v = str(k, value);
+ if (v) {
+ partial.push(quote(k) + (gap ? ': ' : ':') + v);
+ }
+ }
+ }
+ } else {
+
+// Otherwise, iterate through all of the keys in the object.
+
+ for (k in value) {
+ if (Object.hasOwnProperty.call(value, k)) {
+ v = str(k, value);
+ if (v) {
+ partial.push(quote(k) + (gap ? ': ' : ':') + v);
+ }
+ }
+ }
+ }
+
+// Join all of the member texts together, separated with commas,
+// and wrap them in braces.
+
+ v = partial.length === 0 ? '{}' :
+ gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
+ mind + '}' : '{' + partial.join(',') + '}';
+ gap = mind;
+ return v;
+ }
+ }
+
+// If the JSON object does not yet have a stringify method, give it one.
+
+ if (typeof JSON.stringify !== 'function') {
+ JSON.stringify = function (value, replacer, space) {
+
+// The stringify method takes a value and an optional replacer, and an optional
+// space parameter, and returns a JSON text. The replacer can be a function
+// that can replace values, or an array of strings that will select the keys.
+// A default replacer method can be provided. Use of the space parameter can
+// produce text that is more easily readable.
+
+ var i;
+ gap = '';
+ indent = '';
+
+// If the space parameter is a number, make an indent string containing that
+// many spaces.
+
+ if (typeof space === 'number') {
+ for (i = 0; i < space; i += 1) {
+ indent += ' ';
+ }
+
+// If the space parameter is a string, it will be used as the indent string.
+
+ } else if (typeof space === 'string') {
+ indent = space;
+ }
+
+// If there is a replacer, it must be a function or an array.
+// Otherwise, throw an error.
+
+ rep = replacer;
+ if (replacer && typeof replacer !== 'function' &&
+ (typeof replacer !== 'object' ||
+ typeof replacer.length !== 'number')) {
+ throw new Error('JSON.stringify');
+ }
+
+// Make a fake root object containing our value under the key of ''.
+// Return the result of stringifying the value.
+
+ return str('', {'': value});
+ };
+ }
+
+
+// If the JSON object does not yet have a parse method, give it one.
+
+ if (typeof JSON.parse !== 'function') {
+ JSON.parse = function (text, reviver) {
+
+// The parse method takes a text and an optional reviver function, and returns
+// a JavaScript value if the text is a valid JSON text.
+
+ var j;
+
+ function walk(holder, key) {
+
+// The walk method is used to recursively walk the resulting structure so
+// that modifications can be made.
+
+ var k, v, value = holder[key];
+ if (value && typeof value === 'object') {
+ for (k in value) {
+ if (Object.hasOwnProperty.call(value, k)) {
+ v = walk(value, k);
+ if (v !== undefined) {
+ value[k] = v;
+ } else {
+ delete value[k];
+ }
+ }
+ }
+ }
+ return reviver.call(holder, key, value);
+ }
+
+
+// Parsing happens in four stages. In the first stage, we replace certain
+// Unicode characters with escape sequences. JavaScript handles many characters
+// incorrectly, either silently deleting them, or treating them as line endings.
+
+ text = String(text);
+ cx.lastIndex = 0;
+ if (cx.test(text)) {
+ text = text.replace(cx, function (a) {
+ return '\\u' +
+ ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
+ });
+ }
+
+// In the second stage, we run the text against regular expressions that look
+// for non-JSON patterns. We are especially concerned with '()' and 'new'
+// because they can cause invocation, and '=' because it can cause mutation.
+// But just to be safe, we want to reject all unexpected forms.
+
+// We split the second stage into 4 regexp operations in order to work around
+// crippling inefficiencies in IE's and Safari's regexp engines. First we
+// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
+// replace all simple value tokens with ']' characters. Third, we delete all
+// open brackets that follow a colon or comma or that begin the text. Finally,
+// we look to see that the remaining characters are only whitespace or ']' or
+// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
+
+ if (/^[\],:{}\s]*$/.
+test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
+replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
+replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
+
+// In the third stage we use the eval function to compile the text into a
+// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
+// in JavaScript: it can begin a block or an object literal. We wrap the text
+// in parens to eliminate the ambiguity.
+
+ j = eval('(' + text + ')');
+
+// In the optional fourth stage, we recursively walk the new structure, passing
+// each name/value pair to a reviver function for possible transformation.
+
+ return typeof reviver === 'function' ?
+ walk({'': j}, '') : j;
+ }
+
+// If the text is not JSON parseable, then a SyntaxError is thrown.
+
+ throw new SyntaxError('JSON.parse');
+ };
+ }
+}());
View
61 oauth/oauth.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<table xmlns="http://query.yahooapis.com/v1/schema/table.xsd">
+ <meta>
+ <author>Erik Eldridge</author>
+ <sampleQuery>select * from oauth where uri='http://example.com' and consumerKey='asd123' and consumerSecret='zxc456' and callbackUri='http://example.com';</sampleQuery>
+ <documentationURL>http://wiki.github.com/erikeldridge/yql-oauth-support/</documentationURL>
+ </meta>
+ <bindings>
+ <select itemPath="" produces="XML">
+ <inputs>
+ <key id="method" type="xs:string" paramType="variable" default="GET"/>
+ <key id="uri" type="xs:string" paramType="variable" required="true"/>
+ <key id="consumerKey" type="xs:string" paramType="variable" required="true"/>
+ <key id="consumerSecret" type="xs:string" paramType="variable" required="true"/>
+ <key id="callbackUri" type="xs:string" paramType="variable"/>
+ <key id="token" type="xs:string" paramType="variable"/>
+ <key id="tokenSecret" type="xs:string" paramType="variable"/>
+ <key id="verifier" type="xs:string" paramType="variable"/>
+ </inputs>
+ <execute><![CDATA[
+
+ y.include( "http://github.com/yql/yql-tables/raw/master/oauth/oauth.utils.js" );
+
+ //http://github.com/kvz/phpjs/raw/master/functions/url/parse_url.js
+ y.include( 'store://G5vGxDjeP712fgg9vHVi5b' );
+
+ var parsed = parse_url( uri );
+ var accessor = {
+ consumerKey: consumerKey,
+ consumerSecret: consumerSecret,
+ token: "",
+ tokenSecret: "",
+ realm: parsed['scheme'] + '://' + parsed['host']
+ };
+
+ if ( token ) {
+ accessor.token = token;
+ }
+ if ( tokenSecret ) {
+ accessor.tokenSecret = tokenSecret;
+ }
+
+ var args = {
+ method: method,
+ accessor: accessor,
+ parameters:[]
+ };
+
+ if ( callbackUri ) {
+ args.parameters.push( [ "oauth_callback", callbackUri ] );
+ }
+ if ( verifier ) {
+ args.parameters.push( [ "oauth_verifier", verifier ] );
+ }
+
+ var request = y.rest( uri );
+ response.object = sendRequest( args );
+ ]]></execute>
+ </select>
+ </bindings>
+</table>
View
107 openid/openid.assoc.xml
@@ -1,64 +1,77 @@
<?xml version="1.0" encoding="UTF-8"?>
-<table xmlns="http://query.yahooapis.com/v1/schema/table.xsd">
+<table xmlns="http://query.yahooapis.com/v1/schema/table.xsd" https="true">
<meta>
<author>Erik Eldridge</author>
<description>
- - generate an openid association for caller to store
- - For more info see http://openid.net/specs/openid-authentication-2_0.html#associations
+ Generate an openid association for caller to store
</description>
+ <!-- yahoo -->
<sampleQuery>select * from {table} where uri="https://open.login.yahooapis.com/openid/op/auth"</sampleQuery>
+ <documentationURL>http://wiki.github.com/erikeldridge/yql-openid-support/</documentationURL>
</meta>
<bindings>
<select produces="JSON">
<inputs>
-
- <!-- uri must be a valid auth uri -->
+
+ <!-- uri must be a valid auth uri. get auth endpoint by running openid.xml w/o assoc -->
<key id="uri" type="xs:string" paramType="variable" required="true"/>
-
+
</inputs>
<execute><![CDATA[
-
- //use a wrapper fn so we can exit early, ie as a workaround for lack of exit(), die(), etc
- var wrapper = function () {
-
- var params = {
- 'openid.ns' : 'http://specs.openid.net/auth/2.0',
- 'openid.mode' : 'associate',
- 'openid.assoc_type' : 'HMAC-SHA1',
- 'openid.session_type' : 'no-encryption'
- },
- pairs = [];
- for (var key in params) {
- pairs.push(key + '=' + encodeURIComponent(params[key]));
- }
-
- y.include('http://github.com/kvz/phpjs/raw/master/functions/strings/trim.js');
-
- var assocUri = uri + '?' + pairs.join('&'),
- resp = y.rest(assocUri).get().response,
- assoc = trim(resp, '\n').split('\n');
-
- return {
- "status" : "success",
- "assoc" : assoc
- };
-
- }();
-
- //output
- if ('success' === wrapper.status) {
- response.object = {
- "status" : "success",
- "assoc" : wrapper.assoc
- };
- } else {
- response.object = {
- "status" : "error",
- "details" : wrapper.details
- };
- }
-
+ //credit: http://javascript.crockford.com/remedial.html
+ if(!String.prototype.supplant){String.prototype.supplant=function(o){return this.replace(/{([^{}]*)}/g,function(a,b){var r=o[b];return typeof r==='string'||typeof r==='number'?r:a;});};}if(!String.prototype.trim){String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g,"");};}
+
+ //json
+ y.include( 'store://pitrYOXYb8vQfiui4rUYPX' );
+
+ response.object = function() {
+
+ var params = {
+ 'openid.ns': 'http://specs.openid.net/auth/2.0',
+ 'openid.mode': 'associate',
+ 'openid.assoc_type': 'HMAC-SHA1',
+ 'openid.session_type': 'no-encryption'
+ };
+ var pairs = [];
+
+ for (var key in params) {
+ pairs.push(key + '=' + encodeURIComponent(params[key]));
+ }
+
+ var assocUri = uri + '?' + pairs.join('&');
+ var req = y.rest(assocUri).get();
+
+ if ( 200 !== req.status ) {
+ return {
+ "error": 'non-200 response status: ' + req.status
+ };
+ }
+
+ var arr = req.response.trim().split('\n');
+ var params = {};
+
+ for (var i in arr) {
+ var pair = arr[i].split(':');
+ params[pair[0]] = pair[1];
+ }
+
+ if ( params.assoc_handle ) {
+ return {
+ "success": params
+ };
+ } else if ( params.error ) {
+ return {
+ "error": 'unsuccessful response: ' + req.response
+ };
+ } else {
+ return {
+ "error": 'invalid response returned: ' + req.response
+ };
+ }
+
+ } ();
+
]]></execute>
</select>
</bindings>
View
56 openid/openid.ax.xml
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<table xmlns="http://query.yahooapis.com/v1/schema/table.xsd">
- <meta>
- <author>Erik Eldridge</author>
- <description>
- format attribute exchange params and append them to an openid auth url.
- For more info see:
- http://openid.net/specs/openid-attribute-exchange-1_0.html
- </description>
- <sampleQuery>select * from {table} where uri=@uri and fields=@fields</sampleQuery>
- </meta>
- <bindings>
- <select itemPath="" produces="JSON">
- <inputs>
- <key id="params" type="xs:string" paramType="variable" required="false"/>
- </inputs>
- <execute><![CDATA[
-
- var params = {
- 'uri': 'https://open.login.yahooapis.com/openid/op/auth?openid.return_to=http%3A%2F%2Ftest.erikeldridge.com&openid.mode=checkid_setup&openid.identity=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select&openid.ns=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0&openid.realm=http%3A%2F%2Ftest.erikeldridge.com&openid.claimed_id=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select',
- 'fields':[
- {'schema':'http://axschema.org/contact/email', 'alias':'email', 'req':true},
- {'schema':'http://axschema.org/namePerson', 'alias':'fullname', 'req':true}
- ]
- };
- var uri = null,
- pair = null,
- alias = null,
- pairs = [],
- required = [];
- //params = JSON.parse(params)
-
- pairs.push('openid.ax.mode=fetch_request');
-
- for (var i in params['fields']) {
-
- var alias = params['fields'][i]['alias'];
-
- if (true === params['fields'][i]['req']) {
- required.push(alias);
- }
-
- pair = 'openid.ax.type.' + alias + '=' + encodeURIComponent(params['fields'][i]['schema']);
- pairs.push(pair);
- }
-
- pairs.push('openid.ax.required=' + required.join(','));
-
- uri = params['uri'] + '&' + pairs.join('&');
-
- response.object = uri;
-
- ]]></execute>
- </select>
- </bindings>
-</table>
View
110 openid/openid.normalize.xml
@@ -1,64 +1,64 @@
<?xml version="1.0" encoding="UTF-8"?>
-<table xmlns="http://query.yahooapis.com/v1/schema/table.xsd">
- <meta>
- <author>Erik Eldridge</author>
- <description>
- Normalize url for openid usage as per
- http://openid.net/specs/openid-authentication-2_0.html#discovery
- </description>
- <sampleQuery>select * from {table} where id='yahoo.com'</sampleQuery>
- </meta>
- <bindings>
- <select produces="JSON">
- <inputs>
- <key id="id" type="xs:string" paramType="variable" required="true"/>
- </inputs>
- <execute><![CDATA[
-
- //ref: http://openid.net/specs/openid-authentication-2_0.html#normalization_example
-
- function normalizeIdentifier (identifier) {
+<table xmlns="http://query.yahooapis.com/v1/schema/table.xsd" https="true">
+ <meta>
+ <author>Erik Eldridge</author>
+ <description>
+ Normalize url for openid usage
+ </description>
+ <sampleQuery>select * from {table} where id='yahoo.com'</sampleQuery>
+ <documentationURL>http://wiki.github.com/erikeldridge/yql-openid-support/</documentationURL>
+ </meta>
+ <bindings>
+ <select produces="JSON">
+ <inputs>
+ <key id="id" type="xs:string" paramType="variable" required="true"/>
+ </inputs>
+ <execute><![CDATA[
+
+ //ref: http://openid.net/specs/openid-authentication-2_0.html#normalization_example
+
+ function normalizeIdentifier (identifier) {
- var pattern = '^(http[s]*)?'//scheme
- + '(:\/\/)?'//separator
- +'([^:?#/]+)'//domain
- +'([^:?#]+)?',//path
- match = identifier.match(new RegExp(pattern)),
- normalized = '';
+ var pattern = '^(http[s]*)?'//scheme
+ + '(:\/\/)?'//separator
+ +'([^:?#/]+)'//domain
+ +'([^:?#]+)?',//path
+ match = identifier.match(new RegExp(pattern)),
+ normalized = '';
- if (undefined === match[1]) {
- normalized += 'http';
- } else {
- normalized += match[1];
- }
+ if (undefined === match[1]) {
+ normalized += 'http';
+ } else {
+ normalized += match[1];
+ }
- normalized += '://';
+ normalized += '://';
- if (undefined === match[3]) {
- return false;
- }
+ if (undefined === match[3]) {
+ return false;
+ }
- normalized += match[3];
+ normalized += match[3];
- // if there's a path
- if (match[4]) {
- normalized += match[4];
- } else {
- normalized += '/';
- }
+ // if there's a path
+ if (match[4]) {
+ normalized += match[4];
+ } else {
+ normalized += '/';
+ }
- return normalized;
- }
-
- var normalized = normalizeIdentifier(id);
-
- if (!normalized) {
- response.object = { state : "error", details : "domain required, eg example.com" };
- } else {
- response.object = { "state" : "success", "id" : normalized };
- }
-
- ]]></execute>
- </select>
- </bindings>
+ return normalized;
+ }
+
+ var normalized = normalizeIdentifier(id);
+
+ if (!normalized) {
+ response.object = { state : "error", details : "domain required, eg example.com" };
+ } else {
+ response.object = { "state" : "success", "id" : normalized };
+ }
+
+ ]]></execute>
+ </select>
+ </bindings>
</table>
View
168 openid/openid.verify.xml
@@ -0,0 +1,168 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<table xmlns="http://query.yahooapis.com/v1/schema/table.xsd" https="true">
+ <meta>
+ <author>Erik Eldridge w/ help from Yu Wang</author>
+ <description>
+ Verify positive assertion
+ </description>
+ <sampleQuery>select * from {table} where localUrl='http://example.com' and assertJson='{...}' and assocJson='{...}'</sampleQuery>
+ <documentationURL>http://wiki.github.com/ydn/yql-openid-support/</documentationURL>
+ </meta>
+ <bindings>
+ <select produces="JSON">
+ <inputs>
+ <key id="localUrl" type="xs:string" paramType="variable" required="true"/>
+ <key id="assertJson" type="xs:string" paramType="variable" required="true"/>
+ <key id="assocJson" type="xs:string" paramType="variable" required="true"/>
+ <key id="nonceStoreUri" type="xs:string" paramType="variable"/>
+ </inputs>
+ <execute><![CDATA[
+
+ //credit: http://javascript.crockford.com/remedial.html
+ if(!String.prototype.supplant){String.prototype.supplant=function(o){return this.replace(/{([^{}]*)}/g,function(a,b){var r=o[b];return typeof r==='string'||typeof r==='number'?r:a;});};}if(!String.prototype.trim){String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g,"");};}
+
+ y.include( 'store://pitrYOXYb8vQfiui4rUYPX' );
+ y.include('http://test.erikeldridge.com/yql/2.0.0-crypto-sha1.js');
+ y.include('http://crypto-js.googlecode.com/files/2.0.0-hmac-min.js');
+
+ response.object = function() {
+
+ try {
+ var assertion = JSON.parse(decodeURIComponent(assertJson));
+ } catch ( e ) {
+ return {
+ "error": "invalid assertJson: "+e
+ };
+ }
+
+ //note: this doesn't validate query parameters in return_to
+ if (assertion['openid.return_to'].trim() !== localUrl) {
+ return {
+ "error": "return_to url (" + assertion['openid.return_to'] + ") doesn't match local url (" + localUrl + ")"
+ };
+ }
+
+ //2) Verifying Discovered Information
+ //perform disco on the Claimed Id
+ //try yadis
+ var claimedId = assertion['openid.claimed_id'].split('#')[0],
+ githubAcct = 'erikeldridge',
+ yadisYql = 'use "{yadisTableUri}" as yadis; select * from yadis where uri = "{claimedId}"'.supplant({
+ yadisTableUri: 'http://github.com/' + githubAcct + '/yql-tables/raw/master/openid/openid.yadis.xml',
+ claimedId: claimedId
+ }),
+ yadisResults = y.xmlToJson(y.query(yadisYql).results);
+
+ if (yadisResults.results.result && 'success' === yadisResults.results.result.status) {
+
+ //if xrds, the protocol version, OP Endpoint URL &
+ //the OP-Local Identifier (if different than the Claimed Identifier)
+ //MUST be present in one <xrd:Service> element.
+ var xrdsQuery = 'select * from xml where url="{url}"'.supplant({
+ url: yadisResults.results.result.uri,
+ }),
+ xrdsResults = y.xmlToJson(y.query(xrdsQuery).results),
+ protocolVerified = false;
+
+ //check protocol
+ assertion['openid.ns'] = assertion['openid.ns'].trim();
+ for each(var type in xrdsResults.results.XRDS.XRD.Service.Type) {
+ if (-1 !== type.indexOf(assertion['openid.ns'])) {
+ protocolVerified = true;
+ break;
+ }
+ }
+
+ if (!protocolVerified) {
+ return {
+ "error": "Discovered protocol version doesn't match one in assertion"
+ };
+ }
+
+ //check if protocol and op endpoint are in the same service element
+ if (!xrdsResults.results.XRDS.XRD.Service.URI) {
+ return {
+ "error": "OP Endpoint URL MUST be present in one <xrd:Service>"
+ };
+ }
+
+ var opEndpointUri = xrdsResults.results.XRDS.XRD.Service.URI;
+ } else {
+
+ //try html
+ var htmlYql = 'select * from html where url="{claimedId}" and xpath=\'//link[@rel="openid2.provider"]\''.supplant({
+ claimedId: claimedId
+ }),
+ htmlResults = y.xmlToJson(y.query(htmlYql).results);
+ if (htmlResults.results) {
+ var opEndpointUri = htmlResults.results.link.href;
+ }
+ }
+
+ if (!opEndpointUri) {
+ return {
+ "error": "discovery failed; no op endpoint uri found"
+ };
+ } else if (opEndpointUri !== assertion['openid.op_endpoint']) {
+ return {
+ "error": "passed op endpoint != discovered op endpoint"
+ };
+ }
+
+ // 3) verify nonce (http://openid.net/specs/openid-authentication-2_0.html#verify_nonce)
+ // note: this expects a service w/ api: GET {uri}/{key}; POST {uri}/{key}, value='true'
+ if (nonceStoreUri) {
+ var key = y.crypto.encodeMd5(assertion.response_nonce);
+ var resp = y.rest(nonceStoreUri+'get/'+key).get().response;
+ if (resp) {
+ return {
+ "error": "invalid nonce"
+ };
+ } else {
+ resp = y.rest(nonceStoreUri+'put/'+key).contentType('application/x-www-form-urlencoded').query({
+ 'value': 'true'
+ }).post().response
+ }
+ }
+
+ // 4) verify signatures (http://openid.net/specs/openid-authentication-2_0.html#verifying_signatures)
+ var message = '';
+ for each(var key in assertion['openid.signed'].split(',')) {
+ message += key + ':' + assertion['openid.' + key] + '\n';
+ }
+
+ var assoc = JSON.parse(decodeURIComponent(assocJson));
+
+ if ('no-encryption' === assoc['session_type'] && 'HMAC-SHA1' === assoc['assoc_type']) {
+ raw_signature = Crypto.HMAC(
+ Crypto.SHA1, message, Crypto.util.base64ToBytes(assoc['mac_key']), {
+ asBytes: true
+ });
+ } else if ('no-encryption' === assoc['session_type'] && 'HMAC-SHA256' === assoc['assoc_type']) {
+ raw_signature = Crypto.HMAC(
+ Crypto.SHA256, message, Crypto.util.base64ToBytes(assoc['mac_key']), {
+ asBytes: true
+ });
+ } else {
+ return {
+ "error": "only no-encryption w/ sha1 or sha256 is supported at this time"
+ };
+ }
+
+ var sig = Crypto.util.bytesToBase64(raw_signature);
+
+ if (sig !== assertion['openid.sig']) {
+ return {
+ "error": "signatures do not match"
+ };
+ }
+
+ return {
+ "success": ":)"
+ };
+
+ }();
+ ]]></execute>
+ </select>
+ </bindings>
+</table>
View
286 openid/openid.xml
@@ -1,153 +1,167 @@
<?xml version="1.0" encoding="UTF-8"?>
-<table xmlns="http://query.yahooapis.com/v1/schema/table.xsd">
+<table xmlns="http://query.yahooapis.com/v1/schema/table.xsd" https="true">
<meta>
<author>Erik Eldridge</author>
<description>
- - generate an openid auth url from an identifier.
- - supports openid 2.0 only, ie is not 1.1 compat
- - For more info see http://openid.net/specs/openid-authentication-2_0.html
+ Generate an openid auth url from an identifier (openid 2.0 only, ie is not 1.1 compat)
</description>
- <sampleQuery>select * from {table} where identifier="yahoo.com" and return_to="http://example.com"</sampleQuery>
+ <sampleQuery>select * from {table} where id="yahoo.com" and return_to="http://example.com"</sampleQuery>
+ <documentationURL>http://wiki.github.com/erikeldridge/yql-openid-support/</documentationURL>
</meta>
<bindings>
<select produces="XML">
<inputs>
+
+ <!-- the openid to use, eg 'yahoo.com' -->
<key id="id" type="xs:string" paramType="variable" required="true"/>
+
+ <!-- a url to return to after auth, eg http://example.com -->
<key id="return_to" type="xs:string" paramType="variable" required="true"/>
+
+ <!--
+ json array of attr exchange (http://axschema.org, http://openid.net/specs/openid-attribute-exchange-1_0.html) fields, eg
+ [{'schema':'http://axschema.org/contact/email','alias':'email','required':true},
+ {'schema':'http://axschema.org/namePerson','alias':'fullname','required':true}]
+ -->
+ <key id="axJson" type="xs:string" paramType="variable" />
+
+ <!-- oauth consumer key for hybrid auth (http://developer.yahoo.net/blog/archives/2009/09/yahoo_openid_hybrid.html) -->
+ <key id="oauthKey" type="xs:string" paramType="variable" />
+
+ <!-- if you have an openid association, pass the handle here -->
<key id="assoc_handle" type="xs:string" paramType="variable" />
+
</inputs>
<execute><![CDATA[
-
- //set this domain to your base uri for testing
- var domain = 'http://github.com/erikeldridge/yql-tables/raw/master/openid',
-
- normalize = function (id) {
- var tableUri = domain+'/openid.normalize.xml',
- query = 'use "'+tableUri+'" as norm; '
- + 'select * from norm where id="'+id+'"',
- results = y.xmlToJson(y.query(query).results);
-
- if ('success' == results.results.result.state) {
- return results.results.result.id;
- } else {
- return false;
- }
- },
- discover = function (normId) {
-
- //try yadis
- var yadisTableUri = domain+'/openid.yadis.xml?r=5',
- yadisQuery = 'use "'+yadisTableUri+'" as yadis; '
- + 'select * from yadis where uri = "'+normId+'"',
- yadisResults = y.xmlToJson(y.query(yadisQuery).results);y.log(yadisResults);
-
- //results.result only shows up for success responses. not sure why
- if (yadisResults.results.result
- && 'success' === yadisResults.results.result.status) {
- var xrdsQuery = 'select * from xml where url="'+yadisResults.results.result.uri+'"',
- xrdsResult = y.xmlToJson(y.query(xrdsQuery).results);
- return xrdsResult.results.XRDS.XRD.Service.URI;
- }
-
- //try html
- var htmlQuery = 'select * from html where url="'+normId+'" '
- + 'and xpath=\'//link[@rel="openid2.provider"]\'',
- htmlResults = y.xmlToJson(y.query(htmlQuery).results);
- if (htmlResults.results) {
- return htmlResults.results.link.href;
- }
-
- //ok, yadis and html fail, so give up
- return false;
- },
-
- asociate (authUri) {
-
- },
-
- //use a wrapper fn so we can exit early, ie as a workaround for lack of exit(), die(), etc
- wrapper = function (id) {
-
- //normalize id
- var normId = normalize(id);
-
- if (!normId) {
- return {
- 'status' : 'error',
- 'details' : 'invalid id'
- };
- }
-
- //get auth base url
- var baseUri = discover(normId);
-
- if (!baseUri) {
- return {
- 'status' : 'error',
- 'details' : 'id could not be resolved to an openid provider'
- };
- }
-
- //create association
- var assoc = associate();
-
- //validate return_to and extract realm url
- var pattern = '^([^:?#/]+' //scheme
- + ':\/\/' //separator
- +'[^:?#/]+)', //domain
-
- match = return_to.match(new RegExp(pattern));
-
- if (match) {
- var realm = match[0];
- } else {
- return {
- 'status' : 'error',
- 'details' : 'invalid return_to uri'
- };
- }
-
- //construct auth uri
- var params = {
- 'openid.ns' : 'http://specs.openid.net/auth/2.0',
- 'openid.realm' : realm,
- 'openid.mode' : 'checkid_setup',
- 'openid.return_to' : return_to,
- 'openid.identity' : 'http://specs.openid.net/auth/2.0/identifier_select',
- 'openid.claimed_id' : 'http://specs.openid.net/auth/2.0/identifier_select'
- },
-
- pairs = [];
-
-
- if (assoc_handle) {
- params['openid.assoc_handle'] = assoc_handle;
- }
-
- for (var key in params) {
- pairs.push(key + '=' + encodeURIComponent(params[key]));
- }
-
- return {
- "status" : "success",
- "uri" : baseUri + '?' + pairs.join('&')
- };
-
- }(id);
-
- //output
- if ('success' === wrapper.status) {
- response.object = {
- "status" : "success",
- "uri" : wrapper.uri
</