var crypto= require('crypto'), sha1= require('./sha1'), http= require('http'), URL= require('url'), querystring= require('querystring'); exports.OAuth= function(requestUrl, accessUrl, consumerKey, consumerSecret, version, authorize_callback, signatureMethod, nonceSize, customHeaders) { this._requestUrl= requestUrl; this._accessUrl= accessUrl; this._consumerKey= consumerKey; this._consumerSecret= this._encodeData( consumerSecret ); this._version= version; if( authorize_callback === undefined ) { this._authorize_callback= "oob"; } else { this._authorize_callback= authorize_callback; } if( signatureMethod != "PLAINTEXT" && signatureMethod != "HMAC-SHA1") throw new Error("Un-supported signature method: " + signatureMethod ) this._signatureMethod= signatureMethod; this._nonceSize= nonceSize || 32; this._headers= customHeaders || {"Accept" : "*/*", "Connection" : "close", "User-Agent" : "Node authentication"} }; exports.OAuth.prototype._getTimestamp= function() { return Math.floor( (new Date()).getTime() / 1000 ); } exports.OAuth.prototype._encodeData= function(toEncode){ if( toEncode == null || toEncode == "" ) return "" else { var result= encodeURIComponent(toEncode); // Fix the mismatch between OAuth's RFC3986's and Javascript's beliefs in what is right and wrong ;) return result.replace(/\!/g, "%21") .replace(/\'/g, "%27") .replace(/\(/g, "%28") .replace(/\)/g, "%29") .replace(/\*/g, "%2A"); } } exports.OAuth.prototype._decodeData= function(toDecode) { if( toDecode != null ) { toDecode = toDecode.replace(/\+/g, " "); } return decodeURIComponent( toDecode); } exports.OAuth.prototype._getSignature= function(method, url, parameters, tokenSecret) { var signatureBase= this._createSignatureBase(method, url, parameters); return this._createSignature( signatureBase, tokenSecret ); } exports.OAuth.prototype._normalizeUrl= function(url) { var parsedUrl= URL.parse(url, true) var port =""; if( parsedUrl.port ) { if( (parsedUrl.protocol == "http:" && parsedUrl.port != "80" ) || (parsedUrl.protocol == "https:" && parsedUrl.port != "443") ) { port= ":" + parsedUrl.port; } } if( !parsedUrl.pathname || parsedUrl.pathname == "" ) parsedUrl.pathname ="/"; return parsedUrl.protocol + "//" + parsedUrl.hostname + port + parsedUrl.pathname; } // build the OAuth request authorization header exports.OAuth.prototype._buildAuthorizationHeaders= function(orderedParameters) { var authHeader="OAuth "; for( var i= 0 ; i < orderedParameters.length; i++) { // Whilst the all the parameters should be included within the signature, only the oauth_ arguments // should appear within the authorization header. var m = orderedParameters[i][0].match('^oauth_'); if( m && m[0] === "oauth_") { authHeader+= this._encodeData(orderedParameters[i][0])+"=\""+ this._encodeData(orderedParameters[i][1])+"\","; } } authHeader= authHeader.substring(0, authHeader.length-1); return authHeader; } // Takes a literal in, then returns a sorted array exports.OAuth.prototype._sortRequestParams= function(argumentsHash) { var argument_pairs= []; for(var key in argumentsHash ) { argument_pairs[argument_pairs.length]= [key, argumentsHash[key]]; } // Sort by name, then value. argument_pairs.sort(function(a,b) { if ( a[0]== b[0] ) { return a[1] < b[1] ? -1 : 1; } else return a[0] < b[0] ? -1 : 1; }); return argument_pairs; } exports.OAuth.prototype._normaliseRequestParams= function(arguments) { var argument_pairs= this._sortRequestParams( arguments ); var args= ""; for(var i=0;i