@@ -48,7 +48,7 @@ function build_url( url_components, url_params ) {
4848 if ( ! url_params ) return url ;
4949
5050 each ( url_params , function ( key , value ) {
51- params . push ( key + "=" + encode ( value ) ) ;
51+ params . push ( key + "=" + encode_param ( value ) ) ;
5252 } ) ;
5353
5454 url += "?" + params . join ( PARAMSBIT ) ;
@@ -158,13 +158,21 @@ function map( list, fun ) {
158158 * ======
159159 * var encoded_path = encode('path');
160160 */
161- function encode ( path ) {
161+ function encode_base ( path , chars ) {
162162 return map ( ( encodeURIComponent ( path ) ) . split ( '' ) , function ( chr ) {
163- return "-_.!~*'()" . indexOf ( chr ) < 0 ? chr :
163+ return chars . indexOf ( chr ) < 0 ? chr :
164164 "%" + chr . charCodeAt ( 0 ) . toString ( 16 ) . toUpperCase ( )
165165 } ) . join ( '' ) ;
166166}
167167
168+ function encode ( path ) {
169+ return encode_base ( path , "-_.!~*'()" ) ;
170+ }
171+
172+ function encode_param ( value ) {
173+ return encode_base ( value , ".!~*'()" ) ;
174+ }
175+
168176/**
169177 * Generate Subscription Channel List
170178 * ==================================
@@ -192,6 +200,9 @@ function PN_API(setup) {
192200 , PUBLISH_KEY = setup [ 'publish_key' ] || ''
193201 , SUBSCRIBE_KEY = setup [ 'subscribe_key' ] || ''
194202 , AUTH_KEY = setup [ 'auth_key' ] || ''
203+ , SECRET_KEY = setup [ 'secret_key' ] || ''
204+ , PNSDK = setup [ 'PNSDK' ] || ''
205+ , hmac_SHA256 = setup [ 'hmac_SHA256' ]
195206 , SSL = setup [ 'ssl' ] ? 's' : ''
196207 , ORIGIN = 'http' + SSL + '://' + ( setup [ 'origin' ] || 'pubsub.pubnub.com' )
197208 , STD_ORIGIN = nextorigin ( ORIGIN )
@@ -571,7 +582,7 @@ function PN_API(setup) {
571582 SUB_RECEIVER = xdr ( {
572583 timeout : sub_timeout ,
573584 callback : jsonp ,
574- fail : function ( ) {
585+ fail : function ( ) {
575586 SUB_RECEIVER = null ;
576587 SELF [ 'time' ] ( _test_connection ) ;
577588 } ,
@@ -684,6 +695,121 @@ function PN_API(setup) {
684695 ]
685696 } ) ;
686697 } ,
698+ 'grant' : function ( args , callback ) {
699+ var callback = args [ 'callback' ] || callback
700+ , err = args [ 'error' ] || function ( ) { }
701+ , channel = args [ 'channel' ]
702+ , jsonp = jsonp_cb ( )
703+ , ttl = args [ 'ttl' ] || - 1
704+ , r = ( args [ 'read' ] ) ?"1" :"0"
705+ , w = ( args [ 'write' ] ) ?"1" :"0"
706+ , auth_key = args [ 'auth_key' ] ;
707+
708+ function replaceAll ( find , replace , str ) {
709+ return str . replace ( new RegExp ( find , 'g' ) , replace ) ;
710+ }
711+
712+ // Make sure we have a Channel
713+ if ( ! channel ) return error ( 'Missing Channel' ) ;
714+ if ( ! callback ) return error ( 'Missing Callback' ) ;
715+ if ( ! SUBSCRIBE_KEY ) return error ( 'Missing Subscribe Key' ) ;
716+ if ( ! PUBLISH_KEY ) return error ( 'Missing Publish Key' ) ;
717+ if ( ! SECRET_KEY ) return error ( 'Missing Secret Key' ) ;
718+ if ( ! auth_key ) return error ( 'Missing Auth Key' ) ;
719+
720+ if ( jsonp != '0' ) { data [ 'callback' ] = jsonp ; }
721+
722+ var timestamp = Math . floor ( new Date ( ) . getTime ( ) / 1000 ) ;
723+
724+ var sign_input = SUBSCRIBE_KEY + "\n" + PUBLISH_KEY + "\n"
725+ + "grant" + "\n" + "auth=" + auth_key + "&" + "channel="
726+ + channel + "&" + "pnsdk=" + PNSDK + "&" + "r=" + r + "&" + "timestamp=" + timestamp
727+ + ( ( ttl > - 1 ) ?"&" + "ttl=" + ttl :"" )
728+ + "&" + "w=" + w ;
729+ var signature = hmac_SHA256 ( sign_input , SECRET_KEY ) ;
730+
731+ signature = replaceAll ( "\\+" , "-" , signature ) ;
732+ signature = replaceAll ( "\\/" , "_" , signature ) ;
733+
734+ var data = {
735+ 'w' : w ,
736+ 'r' : r ,
737+ 'signature' : signature ,
738+ 'channel' : channel ,
739+ 'auth' : auth_key ,
740+ 'timestamp' : timestamp
741+ } ;
742+ if ( ttl > - 1 ) data [ 'ttl' ] = ttl
743+
744+ xdr ( {
745+ callback : jsonp ,
746+ data : data ,
747+ success : function ( response ) { callback ( response ) } ,
748+ fail : err ,
749+ url : [
750+ STD_ORIGIN , 'v1' , 'auth' , 'grant' ,
751+ 'sub-key' , SUBSCRIBE_KEY
752+ ]
753+ } ) ;
754+ } ,
755+ 'audit' : function ( args , callback ) {
756+ var callback = args [ 'callback' ] || callback
757+ , err = args [ 'error' ] || function ( ) { }
758+ , channel = args [ 'channel' ]
759+ , jsonp = jsonp_cb ( )
760+ , ttl = args [ 'ttl' ] || - 1
761+ , auth_key = args [ 'auth_key' ] ;
762+
763+ function replaceAll ( find , replace , str ) {
764+ return str . replace ( new RegExp ( find , 'g' ) , replace ) ;
765+ }
766+
767+ // Make sure we have a Channel
768+ if ( ! callback ) return error ( 'Missing Callback' ) ;
769+ if ( ! SUBSCRIBE_KEY ) return error ( 'Missing Subscribe Key' ) ;
770+ if ( ! PUBLISH_KEY ) return error ( 'Missing Publish Key' ) ;
771+ if ( ! SECRET_KEY ) return error ( 'Missing Secret Key' ) ;
772+
773+ if ( jsonp != '0' ) { data [ 'callback' ] = jsonp ; }
774+
775+ var timestamp = Math . floor ( new Date ( ) . getTime ( ) / 1000 ) ;
776+
777+ var sign_input = SUBSCRIBE_KEY + "\n" + PUBLISH_KEY + "\n" + "audit" + "\n" ;
778+
779+ if ( auth_key ) sign_input += ( "auth=" + auth_key + "&" ) ;
780+ if ( channel ) sign_input += ( "channel=" + channel + "&" ) ;
781+
782+ sign_input += "pnsdk=" + PNSDK + "&" + "timestamp=" + timestamp ;
783+
784+ var signature = hmac_SHA256 ( sign_input , SECRET_KEY ) ;
785+
786+ signature = replaceAll ( "\\+" , "-" , signature ) ;
787+ signature = replaceAll ( "\\/" , "_" , signature ) ;
788+
789+ var data = {
790+ 'signature' : signature ,
791+ 'timestamp' : timestamp
792+ } ;
793+ if ( channel ) data [ 'channel' ] = channel
794+ if ( auth_key ) data [ 'auth' ] = auth_key
795+
796+ xdr ( {
797+ callback : jsonp ,
798+ data : data ,
799+ success : function ( response ) { callback ( response ) } ,
800+ fail : err ,
801+ url : [
802+ STD_ORIGIN , 'v1' , 'auth' , 'audit' ,
803+ 'sub-key' , SUBSCRIBE_KEY
804+ ]
805+ } ) ;
806+ } ,
807+ 'revoke' : function ( args , callback ) {
808+ args [ 'read' ] = false ;
809+ args [ 'write' ] = false ;
810+ SELF [ 'grant' ] ( args , callback ) ;
811+ } ,
812+
687813
688814 // Expose PUBNUB Functions
689815 'xdr' : xdr ,
0 commit comments