home *** CD-ROM | disk | FTP | other *** search
/ Freelog 101 / FreelogNo101-JanvierFevrier2011.iso / Securite / Passter / Passter.exe / chrome_ex_oauthsimple.js < prev    next >
Text File  |  2010-10-26  |  20KB  |  459 lines

  1. /* OAuthSimple
  2.   * A simpler version of OAuth
  3.   *
  4.   * author:     jr conlin
  5.   * mail:       src@anticipatr.com
  6.   * copyright:  unitedHeroes.net
  7.   * version:    1.0
  8.   * url:        http://unitedHeroes.net/OAuthSimple
  9.   *
  10.   * Copyright (c) 2009, unitedHeroes.net
  11.   * All rights reserved.
  12.   *
  13.   * Redistribution and use in source and binary forms, with or without
  14.   * modification, are permitted provided that the following conditions are met:
  15.   *     * Redistributions of source code must retain the above copyright
  16.   *       notice, this list of conditions and the following disclaimer.
  17.   *     * Redistributions in binary form must reproduce the above copyright
  18.   *       notice, this list of conditions and the following disclaimer in the
  19.   *       documentation and/or other materials provided with the distribution.
  20.   *     * Neither the name of the unitedHeroes.net nor the
  21.   *       names of its contributors may be used to endorse or promote products
  22.   *       derived from this software without specific prior written permission.
  23.   *
  24.   * THIS SOFTWARE IS PROVIDED BY UNITEDHEROES.NET ''AS IS'' AND ANY
  25.   * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  26.   * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  27.   * DISCLAIMED. IN NO EVENT SHALL UNITEDHEROES.NET BE LIABLE FOR ANY
  28.   * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  29.   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  30.   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  31.   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  32.   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  33.   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  34.  */
  35. var OAuthSimple;
  36.  
  37. if (OAuthSimple === undefined)
  38. {
  39.     /* Simple OAuth
  40.      *
  41.      * This class only builds the OAuth elements, it does not do the actual
  42.      * transmission or reception of the tokens. It does not validate elements
  43.      * of the token. It is for client use only.
  44.      *
  45.      * api_key is the API key, also known as the OAuth consumer key
  46.      * shared_secret is the shared secret (duh).
  47.      *
  48.      * Both the api_key and shared_secret are generally provided by the site
  49.      * offering OAuth services. You need to specify them at object creation
  50.      * because nobody <explative>ing uses OAuth without that minimal set of
  51.      * signatures.
  52.      *
  53.      * If you want to use the higher order security that comes from the
  54.      * OAuth token (sorry, I don't provide the functions to fetch that because
  55.      * sites aren't horribly consistent about how they offer that), you need to
  56.      * pass those in either with .setTokensAndSecrets() or as an argument to the
  57.      * .sign() or .getHeaderString() functions.
  58.      *
  59.      * Example:
  60.        <code>
  61.         var oauthObject = OAuthSimple().sign({path:'http://example.com/rest/',
  62.                                               parameters: 'foo=bar&gorp=banana',
  63.                                               signatures:{
  64.                                                 api_key:'12345abcd',
  65.                                                 shared_secret:'xyz-5309'
  66.                                              }});
  67.         document.getElementById('someLink').href=oauthObject.signed_url;
  68.        </code>
  69.      *
  70.      * that will sign as a "GET" using "SHA1-MAC" the url. If you need more than
  71.      * that, read on, McDuff.
  72.      */
  73.  
  74.     /** OAuthSimple creator
  75.      *
  76.      * Create an instance of OAuthSimple
  77.      *
  78.      * @param api_key {string}       The API Key (sometimes referred to as the consumer key) This value is usually supplied by the site you wish to use.
  79.      * @param shared_secret (string) The shared secret. This value is also usually provided by the site you wish to use.
  80.      */
  81.     OAuthSimple = function (consumer_key,shared_secret)
  82.     {
  83. /*        if (api_key == undefined)
  84.             throw("Missing argument: api_key (oauth_consumer_key) for OAuthSimple. This is usually provided by the hosting site.");
  85.         if (shared_secret == undefined)
  86.             throw("Missing argument: shared_secret (shared secret) for OAuthSimple. This is usually provided by the hosting site.");
  87. */      this._secrets={};
  88.         this._parameters={};
  89.  
  90.         // General configuration options.
  91.         if (consumer_key !== undefined) {
  92.             this._secrets['consumer_key'] = consumer_key;
  93.             }
  94.         if (shared_secret !== undefined) {
  95.             this._secrets['shared_secret'] = shared_secret;
  96.             }
  97.         this._default_signature_method= "HMAC-SHA1";
  98.         this._action = "GET";
  99.         this._nonce_chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
  100.  
  101.  
  102.         this.reset = function() {
  103.             this._parameters={};
  104.             this._path=undefined;
  105.             return this;
  106.         };
  107.  
  108.         /** set the parameters either from a hash or a string
  109.          *
  110.          * @param {string,object} List of parameters for the call, this can either be a URI string (e.g. "foo=bar&gorp=banana" or an object/hash)
  111.          */
  112.         this.setParameters = function (parameters) {
  113.             if (parameters === undefined) {
  114.                 parameters = {};
  115.                 }
  116.             if (typeof(parameters) == 'string') {
  117.                 parameters=this._parseParameterString(parameters);
  118.                 }
  119.             this._parameters = parameters;
  120.             if (this._parameters['oauth_nonce'] === undefined) {
  121.                 this._getNonce();
  122.                 }
  123.             if (this._parameters['oauth_timestamp'] === undefined) {
  124.                 this._getTimestamp();
  125.                 }
  126.             if (this._parameters['oauth_method'] === undefined) {
  127.                 this.setSignatureMethod();
  128.                 }
  129.             if (this._parameters['oauth_consumer_key'] === undefined) {
  130.                 this._getApiKey();
  131.                 }
  132.             if(this._parameters['oauth_token'] === undefined) {
  133.                 this._getAccessToken();
  134.                 }
  135.  
  136.             return this;
  137.         };
  138.  
  139.         /** convienence method for setParameters
  140.          *
  141.          * @param parameters {string,object} See .setParameters
  142.          */
  143.         this.setQueryString = function (parameters) {
  144.             return this.setParameters(parameters);
  145.         };
  146.  
  147.         /** Set the target URL (does not include the parameters)
  148.          *
  149.          * @param path {string} the fully qualified URI (excluding query arguments) (e.g "http://example.org/foo")
  150.          */
  151.         this.setURL = function (path) {
  152.             if (path == '') {
  153.                 throw ('No path specified for OAuthSimple.setURL');
  154.                 }
  155.             this._path = path;
  156.             return this;
  157.         };
  158.  
  159.         /** convienence method for setURL
  160.          *
  161.          * @param path {string} see .setURL
  162.          */
  163.         this.setPath = function(path){
  164.             return this.setURL(path);
  165.         };
  166.  
  167.         /** set the "action" for the url, (e.g. GET,POST, DELETE, etc.)
  168.          *
  169.          * @param action {string} HTTP Action word.
  170.          */
  171.         this.setAction = function(action) {
  172.             if (action === undefined) {
  173.                 action="GET";
  174.                 }
  175.             action = action.toUpperCase();
  176.             if (action.match('[^A-Z]')) {
  177.                 throw ('Invalid action specified for OAuthSimple.setAction');
  178.                 }
  179.             this._action = action;
  180.             return this;
  181.         };
  182.  
  183.         /** set the signatures (as well as validate the ones you have)
  184.          *
  185.          * @param signatures {object} object/hash of the token/signature pairs {api_key:, shared_secret:, oauth_token: oauth_secret:}
  186.          */
  187.         this.setTokensAndSecrets = function(signatures) {
  188.             if (signatures)
  189.             {
  190.                 for (var i in signatures) {
  191.                     this._secrets[i] = signatures[i];
  192.                     }
  193.             }
  194.             // Aliases
  195.             if (this._secrets['api_key']) {
  196.                 this._secrets.consumer_key = this._secrets.api_key;
  197.                 }
  198.             if (this._secrets['access_token']) {
  199.                 this._secrets.oauth_token = this._secrets.access_token;
  200.                 }
  201.             if (this._secrets['access_secret']) {
  202.                 this._secrets.oauth_secret = this._secrets.access_secret;
  203.                 }
  204.             // Gauntlet
  205.             if (this._secrets.consumer_key === undefined) {
  206.                 throw('Missing required consumer_key in OAuthSimple.setTokensAndSecrets');
  207.                 }
  208.             if (this._secrets.shared_secret === undefined) {
  209.                 throw('Missing required shared_secret in OAuthSimple.setTokensAndSecrets');
  210.                 }
  211.             if ((this._secrets.oauth_token !== undefined) && (this._secrets.oauth_secret === undefined)) {
  212.                 throw('Missing oauth_secret for supplied oauth_token in OAuthSimple.setTokensAndSecrets');
  213.                 }
  214.             return this;
  215.         };
  216.  
  217.         /** set the signature method (currently only Plaintext or SHA-MAC1)
  218.          *
  219.          * @param method {string} Method of signing the transaction (only PLAINTEXT and SHA-MAC1 allowed for now)
  220.          */
  221.         this.setSignatureMethod = function(method) {
  222.             if (method === undefined) {
  223.                 method = this._default_signature_method;
  224.                 }
  225.             //TODO: accept things other than PlainText or SHA-MAC1
  226.             if (method.toUpperCase().match(/(PLAINTEXT|HMAC-SHA1)/) === undefined) {
  227.                 throw ('Unknown signing method specified for OAuthSimple.setSignatureMethod');
  228.                 }
  229.             this._parameters['oauth_signature_method']= method.toUpperCase();
  230.             return this;
  231.         };
  232.  
  233.         /** sign the request
  234.          *
  235.          * note: all arguments are optional, provided you've set them using the
  236.          * other helper functions.
  237.          *
  238.          * @param args {object} hash of arguments for the call
  239.          *                   {action:, path:, parameters:, method:, signatures:}
  240.          *                   all arguments are optional.
  241.          */
  242.         this.sign = function (args) {
  243.             if (args === undefined) {
  244.                 args = {};
  245.                 }
  246.             // Set any given parameters
  247.             if(args['action'] !== undefined) {
  248.                 this.setAction(args['action']);
  249.                 }
  250.             if (args['path'] !== undefined) {
  251.                 this.setPath(args['path']);
  252.                 }
  253.             if (args['method'] !== undefined) {
  254.                 this.setSignatureMethod(args['method']);
  255.                 }
  256.             this.setTokensAndSecrets(args['signatures']);
  257.             if (args['parameters'] !== undefined){
  258.             this.setParameters(args['parameters']);
  259.             }
  260.             // check the parameters
  261.             var normParams = this._normalizedParameters();
  262.             this._parameters['oauth_signature']=this._generateSignature(normParams);
  263.             return {
  264.                 parameters: this._parameters,
  265.                 signature: this._oauthEscape(this._parameters['oauth_signature']),
  266.                 signed_url: this._path + '?' + this._normalizedParameters(),
  267.                 header: this.getHeaderString()
  268.             };
  269.         };
  270.  
  271.         /** Return a formatted "header" string
  272.          *
  273.          * NOTE: This doesn't set the "Authorization: " prefix, which is required.
  274.          * I don't set it because various set header functions prefer different
  275.          * ways to do that.
  276.          *
  277.          * @param args {object} see .sign
  278.          */
  279.         this.getHeaderString = function(args) {
  280.             if (this._parameters['oauth_signature'] === undefined) {
  281.                 this.sign(args);
  282.                 }
  283.  
  284.             var result = 'OAuth ';
  285.             for (var pName in this._parameters)
  286.             {
  287.                 if (!pName.match(/^oauth/)) {
  288.                     continue;
  289.                     }
  290.                 if ((this._parameters[pName]) instanceof Array)
  291.                 {
  292.                     var pLength = this._parameters[pName].length;
  293.                     for (var j=0;j<pLength;j++)
  294.                     {
  295.                         result += pName +'="'+this._oauthEscape(this._parameters[pName][j])+'" ';
  296.                     }
  297.                 }
  298.                 else
  299.                 {
  300.                     result += pName + '="'+this._oauthEscape(this._parameters[pName])+'" ';
  301.                 }
  302.             }
  303.             return result;
  304.         };
  305.  
  306.         // Start Private Methods.
  307.  
  308.         /** convert the parameter string into a hash of objects.
  309.          *
  310.          */
  311.         this._parseParameterString = function(paramString){
  312.             var elements = paramString.split('&');
  313.             var result={};
  314.             for(var element=elements.shift();element;element=elements.shift())
  315.             {
  316.                 var keyToken=element.split('=');
  317.                 var value='';
  318.                 if (keyToken[1]) {
  319.                     value=decodeURIComponent(keyToken[1]);
  320.                     }
  321.                 if(result[keyToken[0]]){
  322.                     if (!(result[keyToken[0]] instanceof Array))
  323.                     {
  324.                         result[keyToken[0]] = Array(result[keyToken[0]],value);
  325.                     }
  326.                     else
  327.                     {
  328.                         result[keyToken[0]].push(value);
  329.                     }
  330.                 }
  331.                 else
  332.                 {
  333.                     result[keyToken[0]]=value;
  334.                 }
  335.             }
  336.             return result;
  337.         };
  338.  
  339.         this._oauthEscape = function(string) {
  340.             if (string === undefined) {
  341.                 return "";
  342.                 }
  343.             if (string instanceof Array)
  344.             {
  345.                 throw('Array passed to _oauthEscape');
  346.             }
  347.             return encodeURIComponent(string).replace(/\!/g, "%21").
  348.             replace(/\*/g, "%2A").
  349.             replace(/'/g, "%27").
  350.             replace(/\(/g, "%28").
  351.             replace(/\)/g, "%29");
  352.         };
  353.  
  354.         this._getNonce = function (length) {
  355.             if (length === undefined) {
  356.                 length=5;
  357.                 }
  358.             var result = "";
  359.             var cLength = this._nonce_chars.length;
  360.             for (var i = 0; i < length;i++) {
  361.                 var rnum = Math.floor(Math.random() *cLength);
  362.                 result += this._nonce_chars.substring(rnum,rnum+1);
  363.             }
  364.             this._parameters['oauth_nonce']=result;
  365.             return result;
  366.         };
  367.  
  368.         this._getApiKey = function() {
  369.             if (this._secrets.consumer_key === undefined) {
  370.                 throw('No consumer_key set for OAuthSimple.');
  371.                 }
  372.             this._parameters['oauth_consumer_key']=this._secrets.consumer_key;
  373.             return this._parameters.oauth_consumer_key;
  374.         };
  375.  
  376.         this._getAccessToken = function() {
  377.             if (this._secrets['oauth_secret'] === undefined) {
  378.                 return '';
  379.                 }
  380.             if (this._secrets['oauth_token'] === undefined) {
  381.                 throw('No oauth_token (access_token) set for OAuthSimple.');
  382.                 }
  383.             this._parameters['oauth_token'] = this._secrets.oauth_token;
  384.             return this._parameters.oauth_token;
  385.         };
  386.  
  387.         this._getTimestamp = function() {
  388.             var d = new Date();
  389.             var ts = Math.floor(d.getTime()/1000);
  390.             this._parameters['oauth_timestamp'] = ts;
  391.             return ts;
  392.         };
  393.  
  394.         this.b64_hmac_sha1 = function(k,d,_p,_z){
  395.         // heavily optimized and compressed version of http://pajhome.org.uk/crypt/md5/sha1.js
  396.         // _p = b64pad, _z = character size; not used here but I left them available just in case
  397.         if(!_p){_p='=';}if(!_z){_z=8;}function _f(t,b,c,d){if(t<20){return(b&c)|((~b)&d);}if(t<40){return b^c^d;}if(t<60){return(b&c)|(b&d)|(c&d);}return b^c^d;}function _k(t){return(t<20)?1518500249:(t<40)?1859775393:(t<60)?-1894007588:-899497514;}function _s(x,y){var l=(x&0xFFFF)+(y&0xFFFF),m=(x>>16)+(y>>16)+(l>>16);return(m<<16)|(l&0xFFFF);}function _r(n,c){return(n<<c)|(n>>>(32-c));}function _c(x,l){x[l>>5]|=0x80<<(24-l%32);x[((l+64>>9)<<4)+15]=l;var w=[80],a=1732584193,b=-271733879,c=-1732584194,d=271733878,e=-1009589776;for(var i=0;i<x.length;i+=16){var o=a,p=b,q=c,r=d,s=e;for(var j=0;j<80;j++){if(j<16){w[j]=x[i+j];}else{w[j]=_r(w[j-3]^w[j-8]^w[j-14]^w[j-16],1);}var t=_s(_s(_r(a,5),_f(j,b,c,d)),_s(_s(e,w[j]),_k(j)));e=d;d=c;c=_r(b,30);b=a;a=t;}a=_s(a,o);b=_s(b,p);c=_s(c,q);d=_s(d,r);e=_s(e,s);}return[a,b,c,d,e];}function _b(s){var b=[],m=(1<<_z)-1;for(var i=0;i<s.length*_z;i+=_z){b[i>>5]|=(s.charCodeAt(i/8)&m)<<(32-_z-i%32);}return b;}function _h(k,d){var b=_b(k);if(b.length>16){b=_c(b,k.length*_z);}var p=[16],o=[16];for(var i=0;i<16;i++){p[i]=b[i]^0x36363636;o[i]=b[i]^0x5C5C5C5C;}var h=_c(p.concat(_b(d)),512+d.length*_z);return _c(o.concat(h),512+160);}function _n(b){var t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",s='';for(var i=0;i<b.length*4;i+=3){var r=(((b[i>>2]>>8*(3-i%4))&0xFF)<<16)|(((b[i+1>>2]>>8*(3-(i+1)%4))&0xFF)<<8)|((b[i+2>>2]>>8*(3-(i+2)%4))&0xFF);for(var j=0;j<4;j++){if(i*8+j*6>b.length*32){s+=_p;}else{s+=t.charAt((r>>6*(3-j))&0x3F);}}}return s;}function _x(k,d){return _n(_h(k,d));}return _x(k,d);
  398.         }
  399.  
  400.  
  401.         this._normalizedParameters = function() {
  402.             var elements = new Array();
  403.             var paramNames = [];
  404.             var ra =0;
  405.             for (var paramName in this._parameters)
  406.             {
  407.                 if (ra++ > 1000) {
  408.                     throw('runaway 1');
  409.                     }
  410.                 paramNames.unshift(paramName);
  411.             }
  412.             paramNames = paramNames.sort();
  413.             pLen = paramNames.length;
  414.             for (var i=0;i<pLen; i++)
  415.             {
  416.                 paramName=paramNames[i];
  417.                 //skip secrets.
  418.                 if (paramName.match(/\w+_secret/)) {
  419.                     continue;
  420.                     }
  421.                 if (this._parameters[paramName] instanceof Array)
  422.                 {
  423.                     var sorted = this._parameters[paramName].sort();
  424.                     var spLen = sorted.length;
  425.                     for (var j = 0;j<spLen;j++){
  426.                         if (ra++ > 1000) {
  427.                             throw('runaway 1');
  428.                             }
  429.                         elements.push(this._oauthEscape(paramName) + '=' +
  430.                                   this._oauthEscape(sorted[j]));
  431.                     }
  432.                     continue;
  433.                 }
  434.                 elements.push(this._oauthEscape(paramName) + '=' +
  435.                               this._oauthEscape(this._parameters[paramName]));
  436.             }
  437.             return elements.join('&');
  438.         };
  439.  
  440.         this._generateSignature = function() {
  441.  
  442.             var secretKey = this._oauthEscape(this._secrets.shared_secret)+'&'+
  443.                 this._oauthEscape(this._secrets.oauth_secret);
  444.             if (this._parameters['oauth_signature_method'] == 'PLAINTEXT')
  445.             {
  446.                 return secretKey;
  447.             }
  448.             if (this._parameters['oauth_signature_method'] == 'HMAC-SHA1')
  449.             {
  450.                 var sigString = this._oauthEscape(this._action)+'&'+this._oauthEscape(this._path)+'&'+this._oauthEscape(this._normalizedParameters());
  451.                 return this.b64_hmac_sha1(secretKey,sigString);
  452.             }
  453.             return null;
  454.         };
  455.  
  456.     return this;
  457.     };
  458. }
  459.