Subversion Repositories ALCASAR

Rev

Rev 484 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log

Rev 484 Rev 2370
1
/**
1
/**
2
 *   ChilliLibrary.js
2
 *   ChilliLibrary.js
3
 *   V2.0
3
 *   V2.0
4
 *
4
 *
5
 *   This Javascript library can be used to create HTML/JS browser
5
 *   This Javascript library can be used to create HTML/JS browser
6
 *   based smart clients (BBSM) for the CoovaChilli access controller
6
 *   based smart clients (BBSM) for the CoovaChilli access controller
7
 *   Coova Chilli rev 81 or higher is required
7
 *   Coova Chilli rev 81 or higher is required
8
 *   
8
 *   
9
 *   This library creates four global objects :
9
 *   This library creates four global objects :
10
 *
10
 *
11
 *    - chilliController  Expose session/client state and 
11
 *    - chilliController  Expose session/client state and 
12
 *                        connect()/disconnect() methods the to BBSM.
12
 *                        connect()/disconnect() methods the to BBSM.
13
 *
13
 *
14
 *    - chilliJSON        INTERNAL (should not be called from the BBSM).
14
 *    - chilliJSON        INTERNAL (should not be called from the BBSM).
15
 *                        Issues a command to the chilli daemon by adding a new <SCRIPT>
15
 *                        Issues a command to the chilli daemon by adding a new <SCRIPT>
16
 *                        tag to the HTML DOM (this hack enables cross server requests). 
16
 *                        tag to the HTML DOM (this hack enables cross server requests). 
17
 *                        
17
 *                        
18
 *    - chilliClock       Can be used by BBSMs to display a count down.
18
 *    - chilliClock       Can be used by BBSMs to display a count down.
19
 *                        Will sync with chilliController for smooth UI display (not yet implemented)
19
 *                        Will sync with chilliController for smooth UI display (not yet implemented)
20
 *
20
 *
21
 *    - chilliLibrary     Expose API and library versions
21
 *    - chilliLibrary     Expose API and library versions
22
 *
22
 *
23
 *  For more information http://www.coova.org/CoovaChilli/JSON
23
 *  For more information http://www.coova.org/CoovaChilli/JSON
24
 *
24
 *
25
 *  TODO :
25
 *  TODO :
26
 *   - Fine tune level of debug messages
26
 *   - Fine tune level of debug messages
27
 *   - Define error code when invoking onError
27
 *   - Define error code when invoking onError
28
 *   - Retry mechanism after a JSON request fails
28
 *   - Retry mechanism after a JSON request fails
29
 *   - Delay clock tick when there is already an ongoing request
29
 *   - Delay clock tick when there is already an ongoing request
30
 *   - Use a true JSON parser to validate what we received
30
 *   - Use a true JSON parser to validate what we received
31
 *   - Use idleTime and idleTimeout to re-schedule autofresh after
31
 *   - Use idleTime and idleTimeout to re-schedule autofresh after
32
 *     a likely idle termination by chilli
32
 *     a likely idle termination by chilli
33
 *   - check that the library can be compiled as a Flash swf library
33
 *   - check that the library can be compiled as a Flash swf library
34
 *     and used from Flash BBSMs with the same API.
34
 *     and used from Flash BBSMs with the same API.
35
 *
35
 *
36
 *   Copyright (C) Y.Deltroo 2007
36
 *   Copyright (C) Y.Deltroo 2007
37
 *   Distributed under the BSD License
37
 *   Distributed under the BSD License
38
 *
38
 *
39
 *   This file also contains third party code :
39
 *   This file also contains third party code :
40
 *   - MD5, distributed under the BSD license
40
 *   - MD5, distributed under the BSD license
41
 *     http://pajhome.org.uk/crypt/md5
41
 *     http://pajhome.org.uk/crypt/md5
42
 *
42
 *
43
 */
43
 */
44
 
44
 
45
var chilliLibrary = { revision:'85' , apiVersion:'2.0' } ;
45
var chilliLibrary = { revision:'85' , apiVersion:'2.0' } ;
46
 
46
 
47
 
47
 
48
/**
48
/**
49
 *   Global chilliController object
49
 *   Global chilliController object
50
 *
50
 *
51
 *   CONFIGUARION PROPERTIES
51
 *   CONFIGUARION PROPERTIES
52
 *   -----------------------
52
 *   -----------------------
53
 *    ident (String) 
53
 *    ident (String) 
54
 *      Hex encoded string (used for client side CHAP-Password calculations) 
54
 *      Hex encoded string (used for client side CHAP-Password calculations) 
55
 *		  
55
 *		  
56
 *    interval (Number)
56
 *    interval (Number)
57
 *       Poll the gateway every interval, in seconds
57
 *       Poll the gateway every interval, in seconds
58
 *
58
 *
59
 *    host (String)
59
 *    host (String)
60
 *       IP address of the controller (String)
60
 *       IP address of the controller (String)
61
 *
61
 *
62
 *    port (Number)
62
 *    port (Number)
63
 *        UAM port to direct request to on the gateway
63
 *        UAM port to direct request to on the gateway
64
 *
64
 *
65
 *    ssl (Boolean)
65
 *    ssl (Boolean)
66
 *       Shall we use HTTP or HTTPS to communicate with the chilli controller 
66
 *       Shall we use HTTP or HTTPS to communicate with the chilli controller 
67
 *
67
 *
68
 *    uamService : String
68
 *    uamService : String
69
 *        !!! EXPERIMENTAL FEATURE !!!
69
 *        !!! EXPERIMENTAL FEATURE !!!
70
 *        URL to external uamService script (used for external MD5 calculation when portal/chilli trust is required)
70
 *        URL to external uamService script (used for external MD5 calculation when portal/chilli trust is required)
71
 *        This remote script runs on a SSL enable web server, and knows UAM SECRET.
71
 *        This remote script runs on a SSL enable web server, and knows UAM SECRET.
72
 *        The chilliController javascript object will send the password over SSL (and challenge for CHAP) 
72
 *        The chilliController javascript object will send the password over SSL (and challenge for CHAP) 
73
 *        UAM SERVICE should reply with a JSON response containing
73
 *        UAM SERVICE should reply with a JSON response containing
74
 *           - CHAP logon : CHAP-Password X0Red with UAM SECRET
74
 *           - CHAP logon : CHAP-Password X0Red with UAM SECRET
75
 *           - PAP  logon : Password XORed with UAM SECRET
75
 *           - PAP  logon : Password XORed with UAM SECRET
76
 *
76
 *
77
 *   For more information http://www.coova.org/CoovaChilli/JSON
77
 *   For more information http://www.coova.org/CoovaChilli/JSON
78
 *
78
 *
79
 */
79
 */
80
 
80
 
81
if (!chilliController || !chilliController.host)
81
if (!chilliController || !chilliController.host)
82
var chilliController = { interval:30 , host:"1.0.0.1" , port:false , ident:'00' , ssl:false , uamService: false };
82
var chilliController = { interval:30 , host:"1.0.0.1" , port:false , ident:'00' , ssl:false , uamService: false };
83
 
83
 
84
/* Define clientState numerical code constants  */
84
/* Define clientState numerical code constants  */
85
chilliController.stateCodes = { UNKNOWN:-1 , NOT_AUTH:0 , AUTH:1 , AUTH_PENDING:2 , AUTH_SPLASH:3 } ;
85
chilliController.stateCodes = { UNKNOWN:-1 , NOT_AUTH:0 , AUTH:1 , AUTH_PENDING:2 , AUTH_SPLASH:3 } ;
86
 
86
 
87
/* Initializing session and accounting members, objet properties */
87
/* Initializing session and accounting members, objet properties */
88
chilliController.session     = {} ;
88
chilliController.session     = {} ;
89
chilliController.accounting  = {} ;
89
chilliController.accounting  = {} ;
90
chilliController.redir       = {} ;
90
chilliController.redir       = {} ;
91
 
91
 
92
chilliController.location   = { name: '' } ;
92
chilliController.location   = { name: '' } ;
93
chilliController.challenge       = '' ;
93
chilliController.challenge       = '' ;
94
chilliController.message         = '' ;
94
chilliController.message         = '' ;
95
chilliController.clientState     = chilliController.stateCodes.UNKNOWN ;
95
chilliController.clientState     = chilliController.stateCodes.UNKNOWN ;
96
chilliController.command         = '' ;
96
chilliController.command         = '' ;
97
chilliController.autorefreshTimer = 0  ;
97
chilliController.autorefreshTimer = 0  ;
98
 
98
 
99
/* This method returns the root URL for commands */
99
/* This method returns the root URL for commands */
100
chilliController.urlRoot = function () {
100
chilliController.urlRoot = function () {
101
	var protocol = ( chilliController.ssl ) ? "https" : "http" ;
101
	var protocol = ( chilliController.ssl ) ? "https" : "http" ;
102
	var urlRoot = protocol + "://" + chilliController.host + (chilliController.port ? ":" + chilliController.port.toString() : "") + "/json/" ;
102
	var urlRoot = protocol + "://" + chilliController.host + (chilliController.port ? ":" + chilliController.port.toString() : "") + "/json/" ;
103
	return urlRoot;
103
	return urlRoot;
104
};
104
};
105
 
105
 
106
/* Default event handlers */
106
/* Default event handlers */
107
chilliController.onUpdate = function ( cmd ) {
107
chilliController.onUpdate = function ( cmd ) {
108
	log('>> Default onUpdate handler. <<\n>> You should write your own. <<\n>> cmd = ' + cmd + ' <<' );
108
	log('>> Default onUpdate handler. <<\n>> You should write your own. <<\n>> cmd = ' + cmd + ' <<' );
109
};
109
};
110
 
110
 
111
chilliController.onError = function ( str ) {
111
chilliController.onError = function ( str ) {
112
	log ( '>> Default Error Handler<<\n>> You should write your own  <<\n>> ' + str + ' <<' );
112
	log ( '>> Default Error Handler<<\n>> You should write your own  <<\n>> ' + str + ' <<' );
113
};
113
};
114
 
114
 
115
 
115
 
116
chilliController.formatTime = function ( t , zeroReturn ) {
116
chilliController.formatTime = function ( t , zeroReturn ) {
117
 
117
 
118
    if ( typeof(t) == 'undefined' ) {
118
    if ( typeof(t) == 'undefined' ) {
119
	return "Not available";
119
	return "Not available";
120
    }
120
    }
121
 
121
 
122
    t = parseInt ( t , 10 ) ;
122
    t = parseInt ( t , 10 ) ;
123
    if ( (typeof (zeroReturn) !='undefined') && ( t === 0 ) ) {
123
    if ( (typeof (zeroReturn) !='undefined') && ( t === 0 ) ) {
124
	return zeroReturn;
124
	return zeroReturn;
125
    }
125
    }
126
 
126
 
127
    var h = Math.floor( t/3600 ) ;
127
    var h = Math.floor( t/3600 ) ;
128
    var m = Math.floor( (t - 3600*h)/60 ) ;
128
    var m = Math.floor( (t - 3600*h)/60 ) ;
129
    var s = t % 60  ;
129
    var s = t % 60  ;
130
 
130
 
131
    var s_str = s.toString();
131
    var s_str = s.toString();
132
    if (s < 10 ) { s_str = '0' + s_str;   }
132
    if (s < 10 ) { s_str = '0' + s_str;   }
133
 
133
 
134
    var m_str = m.toString();
134
    var m_str = m.toString();
135
    if (m < 10 ) { m_str= '0' + m_str;    }
135
    if (m < 10 ) { m_str= '0' + m_str;    }
136
 
136
 
137
    var h_str = h.toString();
137
    var h_str = h.toString();
138
    if (h < 10 ) { h_str= '0' + h_str;    }
138
    if (h < 10 ) { h_str= '0' + h_str;    }
139
 
139
 
140
 
140
 
141
    if      ( t < 60 )   { return s_str + 's' ; }
141
    if      ( t < 60 )   { return s_str + 's' ; }
142
    else if ( t < 3600 ) { return m_str + 'm' + s_str + 's' ; }
142
    else if ( t < 3600 ) { return m_str + 'm' + s_str + 's' ; }
143
    else                 { return h_str + 'h' + m_str + 'm' + s_str + 's'; }
143
    else                 { return h_str + 'h' + m_str + 'm' + s_str + 's'; }
144
 
144
 
145
};
145
};
146
 
146
 
147
chilliController.formatBytes = function ( b , zeroReturn ) {
147
chilliController.formatBytes = function ( b , zeroReturn ) {
148
 
148
 
149
    if ( typeof(b) == 'undefined' ) {
149
    if ( typeof(b) == 'undefined' ) {
150
        b = 0;
150
        b = 0;
151
    } else {
151
    } else {
152
        b = parseInt ( b , 10 ) ;
152
        b = parseInt ( b , 10 ) ;
153
    }
153
    }
154
 
154
 
155
    if ( (typeof (zeroReturn) !='undefined') && ( b === 0 ) ) {
155
    if ( (typeof (zeroReturn) !='undefined') && ( b === 0 ) ) {
156
	return zeroReturn;
156
	return zeroReturn;
157
    }
157
    }
158
 
158
 
159
    var kb = Math.round(b  / 10) / 100;
159
    var kb = Math.round(b  / 10) / 100;
160
    if (kb < 1) return b  + ' Bytes';
160
    if (kb < 1) return b  + ' Bytes';
161
 
161
 
162
    var mb = Math.round(kb / 10) / 100;
162
    var mb = Math.round(kb / 10) / 100;
163
    if (mb < 1)  return kb + ' Kilobytes';
163
    if (mb < 1)  return kb + ' Kilobytes';
164
 
164
 
165
    var gb = Math.round(mb / 10) / 100;
165
    var gb = Math.round(mb / 10) / 100;
166
    if (gb < 1)  return mb + ' Megabytes';
166
    if (gb < 1)  return mb + ' Megabytes';
167
 
167
 
168
    return gb + ' Gigabytes';
168
    return gb + ' Gigabytes';
169
};
169
};
170
 
170
 
171
 
171
 
172
/**
172
/**
173
 *   Global chilliController object
173
 *   Global chilliController object
174
 *
174
 *
175
 *   PUBLIC METHODS
175
 *   PUBLIC METHODS
176
 *   --------------
176
 *   --------------
177
 *     logon ( username, password ) :
177
 *     logon ( username, password ) :
178
 *           Attempt a CHAP logon with username/password
178
 *           Attempt a CHAP logon with username/password
179
 *           issues a /logon command to chilli daemon
179
 *           issues a /logon command to chilli daemon
180
 *
180
 *
181
 *     logon2 ( username, response ) :
181
 *     logon2 ( username, response ) :
182
 *           Attempt a CHAP logon with username/response
182
 *           Attempt a CHAP logon with username/response
183
 *           issues a /logon command to chilli daemon
183
 *           issues a /logon command to chilli daemon
184
 *
184
 *
185
 *     logoff () :
185
 *     logoff () :
186
 *           Disconnect the current user by issuing a
186
 *           Disconnect the current user by issuing a
187
 *           /logoff command to the chilli daemon
187
 *           /logoff command to the chilli daemon
188
 *
188
 *
189
 *     refresh () :
189
 *     refresh () :
190
 *           Issues a /status command to chilli daemon to refresh 
190
 *           Issues a /status command to chilli daemon to refresh 
191
 *           the local chilliController object state/session data
191
 *           the local chilliController object state/session data
192
 *
192
 *
193
 */
193
 */
194
 
194
 
195
chilliController.logon = function ( username , password )  {
195
chilliController.logon = function ( username , password )  {
196
 
196
 
197
	if ( typeof(username) !== 'string') {
197
	if ( typeof(username) !== 'string') {
198
		chilliController.onError( 1 , "username missing (or incorrect type)" ) ;
198
		chilliController.onError( 1 , "username missing (or incorrect type)" ) ;
199
	}
199
	}
200
	
200
	
201
	if ( typeof(password) !== 'string') {
201
	if ( typeof(password) !== 'string') {
202
		chilliController.onError( 2 , "password missing (or incorrect type)" ) ;
202
		chilliController.onError( 2 , "password missing (or incorrect type)" ) ;
203
	}
203
	}
204
 
204
 
205
	log ( 'chilliController.logon( "' + username + '" , "' + password + ' " )' );
205
	log ( 'chilliController.logon( "' + username + '" , "' + password + ' " )' );
206
 
206
 
207
	chilliController.temp = { 'username': username , 'password': password };
207
	chilliController.temp = { 'username': username , 'password': password };
208
	chilliController.command = 'logon';
208
	chilliController.command = 'logon';
209
 
209
 
210
	log ('chilliController.logon: asking for a new challenge ' );
210
	log ('chilliController.logon: asking for a new challenge ' );
211
	chilliJSON.onError        = chilliController.onError    ;
211
	chilliJSON.onError        = chilliController.onError    ;
212
	chilliJSON.onJSONReady    = chilliController.logonStep2 ;
212
	chilliJSON.onJSONReady    = chilliController.logonStep2 ;
213
	chilliController.clientState = chilliController.AUTH_PENDING ; 
213
	chilliController.clientState = chilliController.AUTH_PENDING ; 
214
	chilliJSON.get( chilliController.urlRoot() + 'status'  ) ;
214
	chilliJSON.get( chilliController.urlRoot() + 'status'  ) ;
215
};
215
};
216
 
216
 
217
chilliController.logon2 = function ( username , response )  {
217
chilliController.logon2 = function ( username , response )  {
218
 
218
 
219
	if ( typeof(username) !== 'string') {
219
	if ( typeof(username) !== 'string') {
220
		chilliController.onError( 1 , "username missing (or incorrect type)" ) ;
220
		chilliController.onError( 1 , "username missing (or incorrect type)" ) ;
221
	}
221
	}
222
	
222
	
223
	if ( typeof(response) !== 'string') {
223
	if ( typeof(response) !== 'string') {
224
		chilliController.onError( 2 , "response missing (or incorrect type)" ) ;
224
		chilliController.onError( 2 , "response missing (or incorrect type)" ) ;
225
	}
225
	}
226
 
226
 
227
	log ( 'chilliController.logon2( "' + username + '" , "' + response + ' " )' );
227
	log ( 'chilliController.logon2( "' + username + '" , "' + response + ' " )' );
228
 
228
 
229
	chilliController.temp = { 'username': username , 'response': response };
229
	chilliController.temp = { 'username': username , 'response': response };
230
	chilliController.command = 'logon2';
230
	chilliController.command = 'logon2';
231
 
231
 
232
	log ('chilliController.logon2: asking for a new challenge ' );
232
	log ('chilliController.logon2: asking for a new challenge ' );
233
	chilliJSON.onError        = chilliController.onError    ;
233
	chilliJSON.onError        = chilliController.onError    ;
234
	chilliJSON.onJSONReady    = chilliController.logonStep2 ;
234
	chilliJSON.onJSONReady    = chilliController.logonStep2 ;
235
	chilliController.clientState = chilliController.AUTH_PENDING ; 
235
	chilliController.clientState = chilliController.AUTH_PENDING ; 
236
	chilliJSON.get( chilliController.urlRoot() + 'status'  ) ;
236
	chilliJSON.get( chilliController.urlRoot() + 'status'  ) ;
237
};
237
};
238
 
238
 
239
 
239
 
240
/**
240
/**
241
 *   Second part of the logon process invoked after
241
 *   Second part of the logon process invoked after
242
 *   the just requested challenge has been received
242
 *   the just requested challenge has been received
243
 */
243
 */
244
chilliController.logonStep2 = function ( resp ) {
244
chilliController.logonStep2 = function ( resp ) {
245
 
245
 
246
	log('Entering logonStep 2');
246
	log('Entering logonStep 2');
247
 
247
 
248
	if ( typeof (resp.challenge) != 'string' ) {
248
	if ( typeof (resp.challenge) != 'string' ) {
249
		log('logonStep2: cannot find a challenge. Aborting.');
249
		log('logonStep2: cannot find a challenge. Aborting.');
250
		return chilliController.onError('Cannot get challenge');
250
		return chilliController.onError('Cannot get challenge');
251
	}
251
	}
252
 
252
 
253
	if ( resp.clientSate === chilliController.stateCodes.AUTH ) {
253
	if ( resp.clientState === chilliController.stateCodes.AUTH ) {
254
		log('logonStep2: Already connected. Aborting.');
254
		log('logonStep2: Already connected. Aborting.');
255
		return chilliController.onError('Already connected.');
255
		return chilliController.onError('Already connected.');
256
	}
256
	}
257
 
257
 
258
	var challenge = resp.challenge;
258
	var challenge = resp.challenge;
259
 
259
 
260
	var username = chilliController.temp.username ; 
260
	var username = chilliController.temp.username ; 
261
	var password = chilliController.temp.password ;
261
	var password = chilliController.temp.password ;
262
	var response = chilliController.temp.response ;
262
	var response = chilliController.temp.response ;
263
 
263
 
264
	log ('chilliController.logonStep2: Got challenge = ' + challenge );
264
	log ('chilliController.logonStep2: Got challenge = ' + challenge );
265
 
265
 
266
	if ( chilliController.uamService ) { /* MD5 CHAP will be calculated by uamService */
266
	if ( chilliController.uamService ) { /* MD5 CHAP will be calculated by uamService */
267
 
267
 
268
		log ('chilliController.logonStep2: Logon using uamService (external MD5 CHAP)');
268
		log ('chilliController.logonStep2: Logon using uamService (external MD5 CHAP)');
269
 
269
 
270
		var c ;
270
		var c ;
271
		if ( chilliController.uamService.indexOf('?') === -1 ) { 
271
		if ( chilliController.uamService.indexOf('?') === -1 ) { 
272
			c = '?' ;
272
			c = '?' ;
273
		}
273
		}
274
		else {
274
		else {
275
			c = '&' ;
275
			c = '&' ;
276
		}
276
		}
277
 
277
 
278
		// Build command URL
278
		// Build command URL
279
		var url = chilliController.uamService + c + 'username=' + escape(username) +'&password=' + escape(password) +'&challenge=' + challenge ;
279
		var url = chilliController.uamService + c + 'username=' + escape(username) +'&password=' + escape(password) +'&challenge=' + challenge ;
280
 
280
 
281
		if (chilliController.queryObj && chilliController.queryObj['userurl'] ) {
281
		if (chilliController.queryObj && chilliController.queryObj['userurl'] ) {
282
		    url += '&userurl='+chilliController.queryObj['userurl'] ;
282
		    url += '&userurl='+chilliController.queryObj['userurl'] ;
283
		}
283
		}
284
 
284
 
285
		// Make uamService request
285
		// Make uamService request
286
		chilliJSON.onError     = chilliController.onError     ;
286
		chilliJSON.onError     = chilliController.onError     ;
287
		chilliJSON.onJSONReady = chilliController.logonStep3 ;
287
		chilliJSON.onJSONReady = chilliController.logonStep3 ;
288
 
288
 
289
		chilliController.clientState = chilliController.AUTH_PENDING ; 
289
		chilliController.clientState = chilliController.AUTH_PENDING ; 
290
		chilliJSON.get( url ) ;
290
		chilliJSON.get( url ) ;
291
	}
291
	}
292
	else {
292
	else {
293
		/* TODO: Should check if challenge has expired and possibly get a new one */
293
		/* TODO: Should check if challenge has expired and possibly get a new one */
294
        	/*       OR always call status first to get a fresh challenge             */
294
        	/*       OR always call status first to get a fresh challenge             */
295
 
295
 
296
	    if (!response || response == '') {
296
	    if (!response || response == '') {
297
		/* Calculate MD5 CHAP at the client side */
297
		/* Calculate MD5 CHAP at the client side */
298
		var myMD5 = new ChilliMD5();
298
		var myMD5 = new ChilliMD5();
299
		response = myMD5.chap ( chilliController.ident , password , challenge );
299
		response = myMD5.chap ( chilliController.ident , password , challenge );
300
		log ( 'chilliController.logonStep2: Calculating CHAP-Password = ' + response );
300
		log ( 'chilliController.logonStep2: Calculating CHAP-Password = ' + response );
301
	    }
301
	    }
302
 
302
 
303
		/* Prepare chilliJSON for logon request */
303
		/* Prepare chilliJSON for logon request */
304
		chilliJSON.onError     = chilliController.onError     ;
304
		chilliJSON.onError     = chilliController.onError     ;
305
		chilliJSON.onJSONReady = chilliController.processReply ;
305
		chilliJSON.onJSONReady = chilliController.processReply ;
306
		chilliController.clientState = chilliController.stateCodes.AUTH_PENDING ; 
306
		chilliController.clientState = chilliController.stateCodes.AUTH_PENDING ; 
307
	
307
	
308
		/* Build /logon command URL */
308
		/* Build /logon command URL */
309
		var logonUrl = chilliController.urlRoot() + 'logon?username=' + escape(username) + '&response='  + response;
309
		var logonUrl = chilliController.urlRoot() + 'logon?username=' + escape(username) + '&response='  + response;
310
		if (chilliController.queryObj && chilliController.queryObj['userurl'] ) {
310
		if (chilliController.queryObj && chilliController.queryObj['userurl'] ) {
311
		    logonUrl += '&userurl='+chilliController.queryObj['userurl'] ;
311
		    logonUrl += '&userurl='+chilliController.queryObj['userurl'] ;
312
		}
312
		}
313
		chilliJSON.get ( logonUrl ) ;
313
		chilliJSON.get ( logonUrl ) ;
314
	}
314
	}
315
 
315
 
316
}; 
316
}; 
317
 
317
 
318
/**
318
/**
319
 *   Third part of the logon process invoked after
319
 *   Third part of the logon process invoked after
320
 *   getting a uamService response
320
 *   getting a uamService response
321
 */
321
 */
322
chilliController.logonStep3 = function ( resp ) {
322
chilliController.logonStep3 = function ( resp ) {
323
	log('Entering logonStep 3');
323
	log('Entering logonStep 3');
324
 
324
 
325
	var username = chilliController.temp.username ; 
325
	var username = chilliController.temp.username ; 
326
 
326
 
327
	if ( typeof (resp.response) == 'string' ) {
327
	if ( typeof (resp.response) == 'string' ) {
328
		chilliJSON.onError     = chilliController.onError     ;
328
		chilliJSON.onError     = chilliController.onError     ;
329
		chilliJSON.onJSONReady = chilliController.processReply ;
329
		chilliJSON.onJSONReady = chilliController.processReply ;
330
		chilliController.clientState = chilliController.stateCodes.AUTH_PENDING ; 
330
		chilliController.clientState = chilliController.stateCodes.AUTH_PENDING ; 
331
	
331
	
332
		/* Build /logon command URL */
332
		/* Build /logon command URL */
333
		var logonUrl = chilliController.urlRoot() + 'logon?username=' + escape(username) + '&response='  + resp.response;
333
		var logonUrl = chilliController.urlRoot() + 'logon?username=' + escape(username) + '&response='  + resp.response;
334
		if (chilliController.queryObj && chilliController.queryObj['userurl'] ) {
334
		if (chilliController.queryObj && chilliController.queryObj['userurl'] ) {
335
		    logonUrl += '&userurl='+chilliController.queryObj['userurl'] ;
335
		    logonUrl += '&userurl='+chilliController.queryObj['userurl'] ;
336
		}
336
		}
337
		chilliJSON.get ( logonUrl ) ;
337
		chilliJSON.get ( logonUrl ) ;
338
	}
338
	}
339
}
339
}
340
 
340
 
341
chilliController.refresh = function ( ) {
341
chilliController.refresh = function ( ) {
342
 
342
 
343
	if ( chilliController.autorefreshTimer ) {
343
	if ( chilliController.autorefreshTimer ) {
344
		chilliController.command = 'autorefresh' ;
344
		chilliController.command = 'autorefresh' ;
345
	}
345
	}
346
	else {
346
	else {
347
		chilliController.command = 'refresh' ;
347
		chilliController.command = 'refresh' ;
348
	}
348
	}
349
 
349
 
350
	chilliJSON.onError     = chilliController.onError        ;
350
	chilliJSON.onError     = chilliController.onError        ;
351
	chilliJSON.onJSONReady = chilliController.processReply   ;
351
	chilliJSON.onJSONReady = chilliController.processReply   ;
352
	chilliJSON.get( chilliController.urlRoot() + 'status'  ) ;
352
	chilliJSON.get( chilliController.urlRoot() + 'status'  ) ;
353
};
353
};
354
 
354
 
355
chilliController.logoff = function () {
355
chilliController.logoff = function () {
356
 
356
 
357
	chilliController.command  = 'logoff'                      ;
357
	chilliController.command  = 'logoff'                      ;
358
	chilliJSON.onError        = chilliController.onError      ;
358
	chilliJSON.onError        = chilliController.onError      ;
359
	chilliJSON.onJSONReady    = chilliController.processReply ;
359
	chilliJSON.onJSONReady    = chilliController.processReply ;
360
	chilliJSON.get( chilliController.urlRoot() + 'logoff' );
360
	chilliJSON.get( chilliController.urlRoot() + 'logoff' );
361
};
361
};
362
 
362
 
363
/* *
363
/* *
364
 *
364
 *
365
 * This functions does some check/type processing on the JSON resp
365
 * This functions does some check/type processing on the JSON resp
366
 * and updates the corresponding chilliController members
366
 * and updates the corresponding chilliController members
367
 *
367
 *
368
 */
368
 */
369
chilliController.processReply = function ( resp ) {
369
chilliController.processReply = function ( resp ) {
370
 
370
 
371
	if ( typeof (resp.message)  == 'string' ) {
371
	if ( typeof (resp.message)  == 'string' ) {
372
 
372
 
373
		/* The following trick will replace HTML entities with the corresponding
373
		/* The following trick will replace HTML entities with the corresponding
374
                 * character. This will not work in Flash (no innerHTML) 
374
                 * character. This will not work in Flash (no innerHTML) 
375
                 */
375
                 */
376
 
376
 
377
		var fakediv = document.createElement('div');
377
		var fakediv = document.createElement('div');
378
		fakediv.innerHTML = resp.message ;
378
		fakediv.innerHTML = resp.message ;
379
		chilliController.message = fakediv.innerHTML  ;
379
		chilliController.message = fakediv.innerHTML  ;
380
	}
380
	}
381
 
381
 
382
	if ( typeof (resp.challenge) == 'string' ) {
382
	if ( typeof (resp.challenge) == 'string' ) {
383
		chilliController.challenge = resp.challenge ;
383
		chilliController.challenge = resp.challenge ;
384
	}
384
	}
385
 
385
 
386
	if ( typeof ( resp.location ) == 'object' ) {
386
	if ( typeof ( resp.location ) == 'object' ) {
387
		chilliController.location =  resp.location ;
387
		chilliController.location =  resp.location ;
388
	}
388
	}
389
 
389
 
390
	if ( typeof ( resp.accounting ) == 'object' ) {
390
	if ( typeof ( resp.accounting ) == 'object' ) {
391
		chilliController.accounting = resp.accounting ;
391
		chilliController.accounting = resp.accounting ;
392
	}
392
	}
393
 
393
 
394
	if (  (typeof ( resp.redir ) == 'object') ) {
394
	if (  (typeof ( resp.redir ) == 'object') ) {
395
		chilliController.redir = resp.redir ;
395
		chilliController.redir = resp.redir ;
396
	}		
396
	}		
397
	
397
	
398
	/* Update the session member only the first time after AUTH */
398
	/* Update the session member only the first time after AUTH */
399
	if (  (typeof ( resp.session ) == 'object') &&
399
	if (  (typeof ( resp.session ) == 'object') &&
400
	      ( chilliController.session==null || (
400
	      ( chilliController.session==null || (
401
	         ( chilliController.clientState !== chilliController.stateCodes.AUTH  )  &&
401
	         ( chilliController.clientState !== chilliController.stateCodes.AUTH  )  &&
402
	         ( resp.clientState === chilliController.stateCodes.AUTH  )))) {
402
	         ( resp.clientState === chilliController.stateCodes.AUTH  )))) {
403
 
403
 
404
		chilliController.session = resp.session ;
404
		chilliController.session = resp.session ;
405
 
405
 
406
		if ( resp.session.startTime ) {
406
		if ( resp.session.startTime ) {
407
			chilliController.session.startTime = new Date();
407
			chilliController.session.startTime = new Date();
408
			chilliController.session.startTime.setTime(resp.session.startTime);
408
			chilliController.session.startTime.setTime(resp.session.startTime);
409
		}
409
		}
410
	}
410
	}
411
 
411
 
412
	/* Update clientState */
412
	/* Update clientState */
413
	if (  ( resp.clientState === chilliController.stateCodes.NOT_AUTH     ) ||
413
	if (  ( resp.clientState === chilliController.stateCodes.NOT_AUTH     ) ||
414
              ( resp.clientState === chilliController.stateCodes.AUTH         ) ||
414
              ( resp.clientState === chilliController.stateCodes.AUTH         ) ||
415
              ( resp.clientState === chilliController.stateCodes.AUTH_SPLASH  ) ||
415
              ( resp.clientState === chilliController.stateCodes.AUTH_SPLASH  ) ||
416
	      ( resp.clientState === chilliController.stateCodes.AUTH_PENDING ) ) {
416
	      ( resp.clientState === chilliController.stateCodes.AUTH_PENDING ) ) {
417
 
417
 
418
		chilliController.clientState = resp.clientState ;
418
		chilliController.clientState = resp.clientState ;
419
	}
419
	}
420
	else {
420
	else {
421
		chilliController.onError("Unknown clientState found in JSON reply");
421
		chilliController.onError("Unknown clientState found in JSON reply");
422
	}
422
	}
423
 
423
 
424
 
424
 
425
	/* Launch or stop the autorefresh timer if required */
425
	/* Launch or stop the autorefresh timer if required */
426
	if ( chilliController.clientState === chilliController.stateCodes.AUTH  ) {
426
	if ( chilliController.clientState === chilliController.stateCodes.AUTH  ) {
427
 
427
 
428
             if ( !chilliController.autorefreshTimer ) {
428
             if ( !chilliController.autorefreshTimer ) {
429
			chilliController.autorefreshTimer = setInterval ('chilliController.refresh()' , 1000*chilliController.interval);
429
			chilliController.autorefreshTimer = setInterval ('chilliController.refresh()' , 1000*chilliController.interval);
430
	     }
430
	     }
431
	} 
431
	} 
432
	else if ( chilliController.clientState  === chilliController.stateCodes.NOT_AUTH ) {
432
	else if ( chilliController.clientState  === chilliController.stateCodes.NOT_AUTH ) {
433
		clearInterval ( chilliController.autorefreshTimer ) ;
433
		clearInterval ( chilliController.autorefreshTimer ) ;
434
		 chilliController.autorefreshTimer = 0 ;
434
		 chilliController.autorefreshTimer = 0 ;
435
	}
435
	}
436
 
436
 
437
	/* Lastly... call the event handler  */
437
	/* Lastly... call the event handler  */
438
	log ('chilliController.processReply: Calling onUpdate. clienState = ' + chilliController.clientState);
438
	log ('chilliController.processReply: Calling onUpdate. clienState = ' + chilliController.clientState);
439
	chilliController.onUpdate( chilliController.command );
439
	chilliController.onUpdate( chilliController.command );
440
};
440
};
441
 
441
 
442
 
442
 
443
 
443
 
444
/** 
444
/** 
445
 *  chilliJSON object  
445
 *  chilliJSON object  
446
 *
446
 *
447
 *  This private objet implements the cross domain hack
447
 *  This private objet implements the cross domain hack
448
 *  If no answer is received before timeout, then an error is raised.
448
 *  If no answer is received before timeout, then an error is raised.
449
 *
449
 *
450
 */
450
 */
451
 
451
 
452
var chilliJSON = { timeout:25000 , timer:0 , node:0 , timestamp:0 };
452
var chilliJSON = { timeout:25000 , timer:0 , node:0 , timestamp:0 };
453
 
453
 
454
chilliJSON.expired   = function () {
454
chilliJSON.expired   = function () {
455
 
455
 
456
		if ( chilliJSON.node.text ) {
456
		if ( chilliJSON.node.text ) {
457
			log ('chilliJSON: reply content \n' + chilliJSON.node.text );
457
			log ('chilliJSON: reply content \n' + chilliJSON.node.text );
458
		}
458
		}
459
		else {
459
		else {
460
			log ('chilliJSON: request timed out (or reply is not valid JS)');
460
			log ('chilliJSON: request timed out (or reply is not valid JS)');
461
		}
461
		}
462
 
462
 
463
		clearInterval ( chilliJSON.timer ) ;
463
		clearInterval ( chilliJSON.timer ) ;
464
		chilliJSON.timer = 0 ;
464
		chilliJSON.timer = 0 ;
465
 
465
 
466
		/* remove the <SCRIPT> tag node that we have created */
466
		/* remove the <SCRIPT> tag node that we have created */
467
		if ( typeof (chilliJSON.node) !== 'number' ) {
467
		if ( typeof (chilliJSON.node) !== 'number' ) {
468
			document.getElementsByTagName('head')[0].removeChild ( chilliJSON.node );
468
			document.getElementsByTagName('head')[0].removeChild ( chilliJSON.node );
469
		}
469
		}
470
		chilliJSON.node = 0;
470
		chilliJSON.node = 0;
471
 
471
 
472
		/* TODO: Implement some kind of retry mechanism here ... */
472
		/* TODO: Implement some kind of retry mechanism here ... */
473
 
473
 
474
		chilliJSON.onError('JSON request timed out (or reply is not valid)');
474
		chilliJSON.onError('JSON request timed out (or reply is not valid)');
475
};
475
};
476
 
476
 
477
chilliJSON.reply = function  ( raw ) {
477
chilliJSON.reply = function  ( raw ) {
478
 
478
 
479
		clearInterval ( chilliJSON.timer ) ;
479
		clearInterval ( chilliJSON.timer ) ;
480
		chilliJSON.timer = 0 ;
480
		chilliJSON.timer = 0 ;
481
 
481
 
482
		var now = new Date()    ;
482
		var now = new Date()    ;
483
		var end = now.getTime() ;
483
		var end = now.getTime() ;
484
		 
484
		 
485
		if ( chilliJSON.timestamp ) {
485
		if ( chilliJSON.timestamp ) {
486
			log ( 'chilliJSON: JSON reply received in ' + ( end - chilliJSON.timestamp ) + ' ms\n' + dumpObject(raw) );
486
			log ( 'chilliJSON: JSON reply received in ' + ( end - chilliJSON.timestamp ) + ' ms\n' + dumpObject(raw) );
487
		}
487
		}
488
 
488
 
489
		if ( typeof (chilliJSON.node) !== 'number' ) {
489
		if ( typeof (chilliJSON.node) !== 'number' ) {
490
			document.getElementsByTagName('head')[0].removeChild ( chilliJSON.node );
490
			document.getElementsByTagName('head')[0].removeChild ( chilliJSON.node );
491
		}
491
		}
492
		chilliJSON.node = 0;
492
		chilliJSON.node = 0;
493
 
493
 
494
         	/* TODO: We should parse raw JSON as an extra security measure */
494
         	/* TODO: We should parse raw JSON as an extra security measure */
495
				
495
				
496
		chilliJSON.onJSONReady( raw ) ;
496
		chilliJSON.onJSONReady( raw ) ;
497
} ;
497
} ;
498
 
498
 
499
chilliJSON.get = function ( gUrl ) {
499
chilliJSON.get = function ( gUrl ) {
500
 
500
 
501
		if ( typeof(gUrl) == "string" ) {
501
		if ( typeof(gUrl) == "string" ) {
502
			chilliJSON.url = gUrl ;
502
			chilliJSON.url = gUrl ;
503
		}
503
		}
504
		else {
504
		else {
505
			log ( "chilliJSON:error:Incorrect url passed to chilliJSON.get():" + gUrl );
505
			log ( "chilliJSON:error:Incorrect url passed to chilliJSON.get():" + gUrl );
506
			chilliJSON.onError ( "Incorrect url passed to chilliJSON.get() " );
506
			chilliJSON.onError ( "Incorrect url passed to chilliJSON.get() " );
507
			return ;
507
			return ;
508
		}
508
		}
509
 
509
 
510
		if ( chilliJSON.timer ) {
510
		if ( chilliJSON.timer ) {
511
			log('logon:   There is already a request running. Return without launching a new request.');
511
			log('logon:   There is already a request running. Return without launching a new request.');
512
			return ;
512
			return ;
513
		}
513
		}
514
 
514
 
515
	
515
	
516
		var scriptElement  = document.createElement('script');
516
		var scriptElement  = document.createElement('script');
517
		scriptElement.type = 'text/javascript';
517
		scriptElement.type = 'text/javascript';
518
 
518
 
519
		var c ;
519
		var c ;
520
		if ( this.url.indexOf('?') === -1 ) { 
520
		if ( this.url.indexOf('?') === -1 ) { 
521
			c = '?' ;
521
			c = '?' ;
522
		}
522
		}
523
		else {
523
		else {
524
			c = '&' ;
524
			c = '&' ;
525
		}
525
		}
526
 
526
 
527
		scriptElement.src = chilliJSON.url + c + 'callback=chilliJSON.reply' ;
527
		scriptElement.src = chilliJSON.url + c + 'callback=chilliJSON.reply' ;
528
		scriptElement.src += '&'+Math.random(); // prevent caching in Safari
528
		scriptElement.src += '&'+Math.random(); // prevent caching in Safari
529
		
529
		
530
		/* Adding the node that will trigger the HTTP request to the DOM tree */
530
		/* Adding the node that will trigger the HTTP request to the DOM tree */
531
		chilliJSON.node = document.getElementsByTagName('head')[0].appendChild(scriptElement);
531
		chilliJSON.node = document.getElementsByTagName('head')[0].appendChild(scriptElement);
532
 
532
 
533
		/* Using interval instead of timeout to support Flash 5,6,7 */
533
		/* Using interval instead of timeout to support Flash 5,6,7 */
534
		chilliJSON.timer     = setInterval ( 'chilliJSON.expired()' , chilliJSON.timeout ) ; 
534
		chilliJSON.timer     = setInterval ( 'chilliJSON.expired()' , chilliJSON.timeout ) ; 
535
		var now              = new Date();
535
		var now              = new Date();
536
		chilliJSON.timestamp = now.getTime() ;
536
		chilliJSON.timestamp = now.getTime() ;
537
 
537
 
538
		log ('chilliJSON: getting ' + chilliJSON.url + ' . Waiting for reply ...');
538
		log ('chilliJSON: getting ' + chilliJSON.url + ' . Waiting for reply ...');
539
 
539
 
540
}; // end chilliJSON.get = function ( url )
540
}; // end chilliJSON.get = function ( url )
541
 
541
 
542
 
542
 
543
/** 
543
/** 
544
 *  chilliClock object  
544
 *  chilliClock object  
545
 *
545
 *
546
 *  Can be used by BBSMs to display a count down.
546
 *  Can be used by BBSMs to display a count down.
547
 *
547
 *
548
 *  Will sync with chilliController and modulate the delay to call onTick
548
 *  Will sync with chilliController and modulate the delay to call onTick
549
 *  This will avoid ugly sequence of short updates in the IO
549
 *  This will avoid ugly sequence of short updates in the IO
550
 *  (not yet implemented)
550
 *  (not yet implemented)
551
 *
551
 *
552
 */
552
 */
553
 
553
 
554
var chilliClock = { isStarted : 0 };
554
var chilliClock = { isStarted : 0 };
555
 
555
 
556
chilliClock.onTick = function () {
556
chilliClock.onTick = function () {
557
	log ("You should define your own onTick() handler on this clock object. Clock value = " + this.value );
557
	log ("You should define your own onTick() handler on this clock object. Clock value = " + this.value );
558
};
558
};
559
 
559
 
560
chilliClock.increment = function () {
560
chilliClock.increment = function () {
561
 
561
 
562
	chilliClock.value  =  chilliClock.value + 1 ;
562
	chilliClock.value  =  chilliClock.value + 1 ;
563
	chilliClock.onTick( chilliClock.value ) ;
563
	chilliClock.onTick( chilliClock.value ) ;
564
};
564
};
565
 
565
 
566
chilliClock.resync = function ( newval ) {
566
chilliClock.resync = function ( newval ) {
567
	clearInterval ( chilliClock.isStarted )    ;
567
	clearInterval ( chilliClock.isStarted )    ;
568
	chilliClock.value     = parseInt( newval , 10 ) ;
568
	chilliClock.value     = parseInt( newval , 10 ) ;
569
	chilliClock.isStarted = setInterval ( 'chilliClock.increment()' , 1000 );
569
	chilliClock.isStarted = setInterval ( 'chilliClock.increment()' , 1000 );
570
};
570
};
571
 
571
 
572
chilliClock.start = function ( newval ) {
572
chilliClock.start = function ( newval ) {
573
 
573
 
574
	if ( typeof (newval) !== 'Number' ) {
574
	if ( typeof (newval) !== 'Number' ) {
575
		chilliClock.resync ( 0 ) ;
575
		chilliClock.resync ( 0 ) ;
576
	}
576
	}
577
	else {
577
	else {
578
		chilliClock.resync ( newval ) ;
578
		chilliClock.resync ( newval ) ;
579
	}
579
	}
580
};
580
};
581
 
581
 
582
chilliClock.stop = function () {
582
chilliClock.stop = function () {
583
	clearInterval ( chilliClock.isStarted )  ;
583
	clearInterval ( chilliClock.isStarted )  ;
584
	chilliClock.isStarted = 0 ;
584
	chilliClock.isStarted = 0 ;
585
};
585
};
586
 
586
 
587
 
587
 
588
function getel(e) {
588
function getel(e) {
589
	if (document.getElementById) {
589
	if (document.getElementById) {
590
		return document.getElementById(e);
590
		return document.getElementById(e);
591
	} else if (document.all){
591
	} else if (document.all){
592
		return document.all[e];
592
		return document.all[e];
593
	}
593
	}
594
}
594
}
595
 
595
 
596
function log( msg , messageLevel ) {
596
function log( msg , messageLevel ) {
597
	if (!chilliController.debug) return;
597
	if (!chilliController.debug) return;
598
	if ( typeof(trace)=="function") {
598
	if ( typeof(trace)=="function") {
599
		// ActionScript trace
599
		// ActionScript trace
600
		trace ( msg );
600
		trace ( msg );
601
	}
601
	}
602
	else if ( typeof(console)=="object") {
602
	else if ( typeof(console)=="object") {
603
		// FireBug console
603
		// FireBug console
604
		console.debug ( msg );
604
		console.debug ( msg );
605
	}
605
	}
606
 
606
 
607
	if ( getel('debugarea') ) {
607
	if ( getel('debugarea') ) {
608
		var e = getel('debugarea') ;
608
		var e = getel('debugarea') ;
609
		e.value = e.value + '\n' + msg;
609
		e.value = e.value + '\n' + msg;
610
		e.scrollTop = e.scrollHeight - e.clientHeight;
610
		e.scrollTop = e.scrollHeight - e.clientHeight;
611
	}
611
	}
612
}
612
}
613
 
613
 
614
/* Transform an object to a text representation */
614
/* Transform an object to a text representation */
615
function dumpObject ( obj ) {
615
function dumpObject ( obj ) {
616
 
616
 
617
	var str = '' ;
617
	var str = '' ;
618
 
618
 
619
	for (var key in obj ) {
619
	for (var key in obj ) {
620
		str = str + "    " + key + " = " + obj[key] + "\n" ;
620
		str = str + "    " + key + " = " + obj[key] + "\n" ;
621
		if ( typeof ( obj[key] ) == "object" ) {
621
		if ( typeof ( obj[key] ) == "object" ) {
622
			for ( var key2 in obj[key] ) {
622
			for ( var key2 in obj[key] ) {
623
				str = str + "      " + key2 + " = "  + obj[key][key2] + "\n" ;
623
				str = str + "      " + key2 + " = "  + obj[key][key2] + "\n" ;
624
			}
624
			}
625
		}
625
		}
626
	}
626
	}
627
 
627
 
628
	return str;
628
	return str;
629
}
629
}
630
 
630
 
631
/*
631
/*
632
 * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
632
 * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
633
 * Digest Algorithm, as defined in RFC 1321.
633
 * Digest Algorithm, as defined in RFC 1321.
634
 * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
634
 * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
635
 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
635
 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
636
 * Distributed under the BSD License
636
 * Distributed under the BSD License
637
 * See http://pajhome.org.uk/crypt/md5 for more info.
637
 * See http://pajhome.org.uk/crypt/md5 for more info.
638
 *
638
 *
639
 * added by Y.DELTROO
639
 * added by Y.DELTROO
640
 *   - new functions: chap(), hex2binl() and str2hex() 
640
 *   - new functions: chap(), hex2binl() and str2hex() 
641
 *   - modifications to comply with the jslint test, http://www.jslint.com/
641
 *   - modifications to comply with the jslint test, http://www.jslint.com/
642
 *
642
 *
643
 * Copyright (c) 2007
643
 * Copyright (c) 2007
644
 * Distributed under the BSD License
644
 * Distributed under the BSD License
645
 *
645
 *
646
 */
646
 */
647
 
647
 
648
 
648
 
649
function ChilliMD5() {
649
function ChilliMD5() {
650
 
650
 
651
	var hexcase = 0;  /* hex output format. 0 - lowercase; 1 - uppercase        */
651
	var hexcase = 0;  /* hex output format. 0 - lowercase; 1 - uppercase        */
652
	var b64pad  = ""; /* base-64 pad character. "=" for strict RFC compliance   */
652
	var b64pad  = ""; /* base-64 pad character. "=" for strict RFC compliance   */
653
	var chrsz   = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode      */
653
	var chrsz   = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode      */
654
 
654
 
655
	this.hex_md5 = function (s){
655
	this.hex_md5 = function (s){
656
		return binl2hex(core_md5(str2binl(s), s.length * chrsz));
656
		return binl2hex(core_md5(str2binl(s), s.length * chrsz));
657
	};
657
	};
658
 
658
 
659
	this.chap = function ( hex_ident , str_password , hex_chal ) {
659
	this.chap = function ( hex_ident , str_password , hex_chal ) {
660
 
660
 
661
		//  Convert everything to hex encoded strings
661
		//  Convert everything to hex encoded strings
662
		var hex_password =  str2hex ( str_password );
662
		var hex_password =  str2hex ( str_password );
663
 
663
 
664
		// concatenate hex encoded strings
664
		// concatenate hex encoded strings
665
		var hex   = hex_ident + hex_password + hex_chal;
665
		var hex   = hex_ident + hex_password + hex_chal;
666
 
666
 
667
		// Convert concatenated hex encoded string to its binary representation
667
		// Convert concatenated hex encoded string to its binary representation
668
		var bin   = hex2binl ( hex ) ;
668
		var bin   = hex2binl ( hex ) ;
669
 
669
 
670
		// Calculate MD5 on binary representation
670
		// Calculate MD5 on binary representation
671
		var md5 = core_md5( bin , hex.length * 4 ) ; 
671
		var md5 = core_md5( bin , hex.length * 4 ) ; 
672
 
672
 
673
		return binl2hex( md5 );
673
		return binl2hex( md5 );
674
	};
674
	};
675
 
675
 
676
	function core_md5(x, len) {
676
	function core_md5(x, len) {
677
	  x[len >> 5] |= 0x80 << ((len) % 32);
677
	  x[len >> 5] |= 0x80 << ((len) % 32);
678
	  x[(((len + 64) >>> 9) << 4) + 14] = len;
678
	  x[(((len + 64) >>> 9) << 4) + 14] = len;
679
 
679
 
680
	  var a =  1732584193;
680
	  var a =  1732584193;
681
	  var b = -271733879;
681
	  var b = -271733879;
682
	  var c = -1732584194;
682
	  var c = -1732584194;
683
	  var d =  271733878;
683
	  var d =  271733878;
684
 
684
 
685
	  for(var i = 0; i < x.length; i += 16) {
685
	  for(var i = 0; i < x.length; i += 16) {
686
		var olda = a;
686
		var olda = a;
687
		var oldb = b;
687
		var oldb = b;
688
		var oldc = c;
688
		var oldc = c;
689
		var oldd = d;
689
		var oldd = d;
690
 
690
 
691
		a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
691
		a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
692
		d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
692
		d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
693
		c = md5_ff(c, d, a, b, x[i+ 2], 17,  606105819);
693
		c = md5_ff(c, d, a, b, x[i+ 2], 17,  606105819);
694
		b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
694
		b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
695
		a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
695
		a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
696
		d = md5_ff(d, a, b, c, x[i+ 5], 12,  1200080426);
696
		d = md5_ff(d, a, b, c, x[i+ 5], 12,  1200080426);
697
		c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
697
		c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
698
		b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
698
		b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
699
		a = md5_ff(a, b, c, d, x[i+ 8], 7 ,  1770035416);
699
		a = md5_ff(a, b, c, d, x[i+ 8], 7 ,  1770035416);
700
		d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
700
		d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
701
		c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
701
		c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
702
		b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
702
		b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
703
		a = md5_ff(a, b, c, d, x[i+12], 7 ,  1804603682);
703
		a = md5_ff(a, b, c, d, x[i+12], 7 ,  1804603682);
704
		d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
704
		d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
705
		c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
705
		c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
706
		b = md5_ff(b, c, d, a, x[i+15], 22,  1236535329);
706
		b = md5_ff(b, c, d, a, x[i+15], 22,  1236535329);
707
 
707
 
708
		a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
708
		a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
709
		d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
709
		d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
710
		c = md5_gg(c, d, a, b, x[i+11], 14,  643717713);
710
		c = md5_gg(c, d, a, b, x[i+11], 14,  643717713);
711
		b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
711
		b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
712
		a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
712
		a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
713
		d = md5_gg(d, a, b, c, x[i+10], 9 ,  38016083);
713
		d = md5_gg(d, a, b, c, x[i+10], 9 ,  38016083);
714
		c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
714
		c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
715
		b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
715
		b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
716
		a = md5_gg(a, b, c, d, x[i+ 9], 5 ,  568446438);
716
		a = md5_gg(a, b, c, d, x[i+ 9], 5 ,  568446438);
717
		d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
717
		d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
718
		c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
718
		c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
719
		b = md5_gg(b, c, d, a, x[i+ 8], 20,  1163531501);
719
		b = md5_gg(b, c, d, a, x[i+ 8], 20,  1163531501);
720
		a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
720
		a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
721
		d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
721
		d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
722
		c = md5_gg(c, d, a, b, x[i+ 7], 14,  1735328473);
722
		c = md5_gg(c, d, a, b, x[i+ 7], 14,  1735328473);
723
		b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
723
		b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
724
 
724
 
725
		a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
725
		a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
726
		d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
726
		d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
727
		c = md5_hh(c, d, a, b, x[i+11], 16,  1839030562);
727
		c = md5_hh(c, d, a, b, x[i+11], 16,  1839030562);
728
		b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
728
		b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
729
		a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
729
		a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
730
		d = md5_hh(d, a, b, c, x[i+ 4], 11,  1272893353);
730
		d = md5_hh(d, a, b, c, x[i+ 4], 11,  1272893353);
731
		c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
731
		c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
732
		b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
732
		b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
733
		a = md5_hh(a, b, c, d, x[i+13], 4 ,  681279174);
733
		a = md5_hh(a, b, c, d, x[i+13], 4 ,  681279174);
734
		d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
734
		d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
735
		c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
735
		c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
736
		b = md5_hh(b, c, d, a, x[i+ 6], 23,  76029189);
736
		b = md5_hh(b, c, d, a, x[i+ 6], 23,  76029189);
737
		a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
737
		a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
738
		d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
738
		d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
739
		c = md5_hh(c, d, a, b, x[i+15], 16,  530742520);
739
		c = md5_hh(c, d, a, b, x[i+15], 16,  530742520);
740
		b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
740
		b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
741
 
741
 
742
		a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
742
		a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
743
		d = md5_ii(d, a, b, c, x[i+ 7], 10,  1126891415);
743
		d = md5_ii(d, a, b, c, x[i+ 7], 10,  1126891415);
744
		c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
744
		c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
745
		b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
745
		b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
746
		a = md5_ii(a, b, c, d, x[i+12], 6 ,  1700485571);
746
		a = md5_ii(a, b, c, d, x[i+12], 6 ,  1700485571);
747
		d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
747
		d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
748
		c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
748
		c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
749
		b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
749
		b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
750
		a = md5_ii(a, b, c, d, x[i+ 8], 6 ,  1873313359);
750
		a = md5_ii(a, b, c, d, x[i+ 8], 6 ,  1873313359);
751
		d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
751
		d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
752
		c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
752
		c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
753
		b = md5_ii(b, c, d, a, x[i+13], 21,  1309151649);
753
		b = md5_ii(b, c, d, a, x[i+13], 21,  1309151649);
754
		a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
754
		a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
755
		d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
755
		d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
756
		c = md5_ii(c, d, a, b, x[i+ 2], 15,  718787259);
756
		c = md5_ii(c, d, a, b, x[i+ 2], 15,  718787259);
757
		b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
757
		b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
758
 
758
 
759
		a = safe_add(a, olda);
759
		a = safe_add(a, olda);
760
		b = safe_add(b, oldb);
760
		b = safe_add(b, oldb);
761
		c = safe_add(c, oldc);
761
		c = safe_add(c, oldc);
762
		d = safe_add(d, oldd);
762
		d = safe_add(d, oldd);
763
	  }
763
	  }
764
	  return [ a, b, c, d ];
764
	  return [ a, b, c, d ];
765
 
765
 
766
	}
766
	}
767
 
767
 
768
	function md5_cmn(q, a, b, x, s, t) {
768
	function md5_cmn(q, a, b, x, s, t) {
769
	  return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
769
	  return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
770
	}
770
	}
771
 
771
 
772
	function md5_ff(a, b, c, d, x, s, t) {
772
	function md5_ff(a, b, c, d, x, s, t) {
773
	  return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
773
	  return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
774
	}
774
	}
775
 
775
 
776
	function md5_gg(a, b, c, d, x, s, t) {
776
	function md5_gg(a, b, c, d, x, s, t) {
777
	  return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
777
	  return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
778
	}
778
	}
779
 
779
 
780
	function md5_hh(a, b, c, d, x, s, t) {
780
	function md5_hh(a, b, c, d, x, s, t) {
781
	  return md5_cmn(b ^ c ^ d, a, b, x, s, t);
781
	  return md5_cmn(b ^ c ^ d, a, b, x, s, t);
782
	}
782
	}
783
 
783
 
784
	function md5_ii(a, b, c, d, x, s, t) {
784
	function md5_ii(a, b, c, d, x, s, t) {
785
	  return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
785
	  return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
786
	}
786
	}
787
 
787
 
788
	function safe_add(x, y) {
788
	function safe_add(x, y) {
789
	  var lsw = (x & 0xFFFF) + (y & 0xFFFF);
789
	  var lsw = (x & 0xFFFF) + (y & 0xFFFF);
790
	  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
790
	  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
791
	  return (msw << 16) | (lsw & 0xFFFF);
791
	  return (msw << 16) | (lsw & 0xFFFF);
792
	}
792
	}
793
	function bit_rol(num, cnt) {
793
	function bit_rol(num, cnt) {
794
	  return (num << cnt) | (num >>> (32 - cnt));
794
	  return (num << cnt) | (num >>> (32 - cnt));
795
	}
795
	}
796
 
796
 
797
	function str2binl(str) {
797
	function str2binl(str) {
798
	  var bin = [] ;
798
	  var bin = [] ;
799
	  var mask = (1 << chrsz) - 1;
799
	  var mask = (1 << chrsz) - 1;
800
	  for (var i = 0; i < str.length * chrsz; i += chrsz) {
800
	  for (var i = 0; i < str.length * chrsz; i += chrsz) {
801
		bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
801
		bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
802
 
802
 
803
 
803
 
804
 
804
 
805
 
805
 
806
 
806
 
807
 
807
 
808
 
808
 
809
 
809
 
810
<< (i%32);< (i%32);< binarray.length * 4; i++) {		str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
810
<< (i%32);< (i%32);< binarray.length * 4; i++) {		str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
811
<< (i%32);< (i%32);< binarray.length * 4; i++) {			   hex_tab.charAt((binarray[i>>2] >> ((i%4)*8  )) & 0xF);
811
<< (i%32);< (i%32);< binarray.length * 4; i++) {			   hex_tab.charAt((binarray[i>>2] >> ((i%4)*8  )) & 0xF);
812
 
812
 
813
 
813
 
814
 
814
 
815
 
815
 
816
 
816
 
817
 
817
 
818
 
818
 
819
 
819
 
820
 
820
 
821
 
821
 
822
 
822
 
823
 
823
 
824
 
824
 
825
 
825
 
826
 
826
 
827
 
827
 
828
 
828
 
829
 
829
 
830
 
830
 
831
 
831
 
832
 
832
 
833
 
833
 
834
 
834
 
835
 
835
 
836
 
836
 
837
 
837
 
838
 
838
 
839
<< (i%32);< (i%32);< binarray.length * 4; i++) {			bin[i>>5] |= ( octet & 255 ) << (i%32);
839
<< (i%32);< (i%32);< binarray.length * 4; i++) {			bin[i>>5] |= ( octet & 255 ) << (i%32);
840
 
840
 
841
 
841
 
842
 
842
 
843
 
843
 
844
 
844
 
845
 
845
 
846
 
846
 
847
 
847
 
848
 
848
 
849
 
849
 
850
 
850