436
+ − 1
/*
+ − 2
* AJAX-based intelligent login interface
+ − 3
*/
+ − 4
+ − 5
/*
+ − 6
* FRONTEND
+ − 7
*/
+ − 8
+ − 9
/**
+ − 10
* Performs a logon as a regular member.
+ − 11
*/
+ − 12
+ − 13
function ajaxLogonToMember()
+ − 14
{
+ − 15
// IE <6 pseudo-compatibility
+ − 16
if ( KILL_SWITCH )
+ − 17
return true;
+ − 18
if ( auth_level >= USER_LEVEL_MEMBER )
+ − 19
return true;
+ − 20
ajaxLoginInit(function(k)
+ − 21
{
+ − 22
window.location.reload();
+ − 23
}, USER_LEVEL_MEMBER);
+ − 24
}
+ − 25
+ − 26
/**
+ − 27
* Authenticates to the highest level the current user is allowed to go to.
+ − 28
*/
+ − 29
+ − 30
function ajaxLogonToElev()
+ − 31
{
+ − 32
if ( auth_level == user_level )
+ − 33
return true;
+ − 34
+ − 35
ajaxLoginInit(function(k)
+ − 36
{
+ − 37
ENANO_SID = k;
+ − 38
var url = String(' ' + window.location).substr(1);
+ − 39
url = append_sid(url);
+ − 40
window.location = url;
+ − 41
}, user_level);
+ − 42
}
+ − 43
+ − 44
/*
+ − 45
* BACKEND
+ − 46
*/
+ − 47
+ − 48
/**
+ − 49
* Holding object for various AJAX authentication information.
+ − 50
* @var object
+ − 51
*/
+ − 52
+ − 53
var logindata = {};
+ − 54
+ − 55
/**
+ − 56
* Path to the image used to indicate loading progress
+ − 57
* @var string
+ − 58
*/
+ − 59
+ − 60
if ( !ajax_login_loadimg_path )
+ − 61
var ajax_login_loadimg_path = false;
+ − 62
+ − 63
if ( !ajax_login_successimg_path )
+ − 64
var ajax_login_successimg_path = false;
+ − 65
+ − 66
/**
+ − 67
* Status variables
+ − 68
* @var int
+ − 69
*/
+ − 70
+ − 71
var AJAX_STATUS_LOADING_KEY = 1;
+ − 72
var AJAX_STATUS_GENERATING_KEY = 2;
+ − 73
var AJAX_STATUS_LOGGING_IN = 3;
+ − 74
var AJAX_STATUS_SUCCESS = 4;
+ − 75
var AJAX_STATUS_DESTROY = 65535;
+ − 76
+ − 77
/**
+ − 78
* State constants
+ − 79
* @var int
+ − 80
*/
+ − 81
+ − 82
var AJAX_STATE_EARLY_INIT = 1;
+ − 83
var AJAX_STATE_LOADING_KEY = 2;
+ − 84
+ − 85
/**
+ − 86
* Performs the AJAX request to get an encryption key and from there spawns the login form.
+ − 87
* @param function The function that will be called once authentication completes successfully.
+ − 88
* @param int The security level to authenticate at - see http://docs.enanocms.org/Help:Appendix_B
+ − 89
*/
+ − 90
+ − 91
function ajaxLoginInit(call_on_finish, user_level)
+ − 92
{
+ − 93
logindata = {};
+ − 94
+ − 95
var title = ( user_level > USER_LEVEL_MEMBER ) ? $lang.get('user_login_ajax_prompt_title_elev') : $lang.get('user_login_ajax_prompt_title');
+ − 96
logindata.mb_object = new messagebox(MB_OKCANCEL | MB_ICONLOCK, title, '');
+ − 97
+ − 98
logindata.mb_object.onclick['Cancel'] = function()
+ − 99
{
+ − 100
// Hide the error message and captcha
+ − 101
if ( document.getElementById('ajax_login_error_box') )
+ − 102
{
+ − 103
document.getElementById('ajax_login_error_box').parentNode.removeChild(document.getElementById('ajax_login_error_box'));
+ − 104
}
+ − 105
if ( document.getElementById('autoCaptcha') )
+ − 106
{
+ − 107
var to = fly_out_top(document.getElementById('autoCaptcha'), false, true);
+ − 108
setTimeout(function() {
+ − 109
var d = document.getElementById('autoCaptcha');
+ − 110
d.parentNode.removeChild(d);
+ − 111
}, to);
+ − 112
}
+ − 113
};
+ − 114
+ − 115
logindata.mb_object.onbeforeclick['OK'] = function()
+ − 116
{
+ − 117
ajaxLoginSubmitForm();
+ − 118
return true;
+ − 119
}
+ − 120
+ − 121
// Fetch the inner content area
+ − 122
logindata.mb_inner = document.getElementById('messageBox').getElementsByTagName('div')[0];
+ − 123
+ − 124
// Initialize state
+ − 125
logindata.showing_status = false;
+ − 126
logindata.user_level = user_level;
+ − 127
logindata.successfunc = call_on_finish;
+ − 128
+ − 129
// Build the "loading" window
+ − 130
ajaxLoginSetStatus(AJAX_STATUS_LOADING_KEY);
+ − 131
+ − 132
// Request the key
+ − 133
ajaxLoginPerformRequest({ mode: 'getkey' });
+ − 134
}
+ − 135
+ − 136
/**
+ − 137
* Sets the contents of the AJAX login window to the appropriate status message.
+ − 138
* @param int One of AJAX_STATUS_*
+ − 139
*/
+ − 140
+ − 141
function ajaxLoginSetStatus(status)
+ − 142
{
+ − 143
if ( !logindata.mb_inner )
+ − 144
return false;
+ − 145
if ( logindata.showing_status )
+ − 146
{
+ − 147
var div = document.getElementById('ajax_login_status');
+ − 148
if ( div )
+ − 149
logindata.mb_inner.removeChild(div);
+ − 150
}
+ − 151
switch(status)
+ − 152
{
+ − 153
case AJAX_STATUS_LOADING_KEY:
+ − 154
+ − 155
// Create the status div
+ − 156
var div = document.createElement('div');
+ − 157
div.id = 'ajax_login_status';
+ − 158
div.style.marginTop = '10px';
+ − 159
div.style.textAlign = 'center';
+ − 160
+ − 161
// The circly ball ajaxy image + status message
+ − 162
var status_msg = $lang.get('user_login_ajax_fetching_key');
+ − 163
+ − 164
// Insert the status message
+ − 165
div.appendChild(document.createTextNode(status_msg));
+ − 166
+ − 167
// Append a br or two to space things properly
+ − 168
div.appendChild(document.createElement('br'));
+ − 169
div.appendChild(document.createElement('br'));
+ − 170
+ − 171
var img = document.createElement('img');
+ − 172
img.src = ( ajax_login_loadimg_path ) ? ajax_login_loadimg_path : scriptPath + '/images/loading-big.gif';
+ − 173
div.appendChild(img);
+ − 174
+ − 175
// Another coupla brs
+ − 176
div.appendChild(document.createElement('br'));
+ − 177
div.appendChild(document.createElement('br'));
+ − 178
+ − 179
// The link to the full login form
+ − 180
var small = document.createElement('small');
+ − 181
small.innerHTML = $lang.get('user_login_ajax_link_fullform', { link_full_form: makeUrlNS('Special', 'Login/' + title) });
+ − 182
div.appendChild(small);
+ − 183
+ − 184
// Insert the entire message into the login window
+ − 185
logindata.mb_inner.innerHTML = '';
+ − 186
logindata.mb_inner.appendChild(div);
+ − 187
+ − 188
break;
+ − 189
case AJAX_STATUS_GENERATING_KEY:
+ − 190
+ − 191
// Create the status div
+ − 192
var div = document.createElement('div');
+ − 193
div.id = 'ajax_login_status';
+ − 194
div.style.marginTop = '10px';
+ − 195
div.style.textAlign = 'center';
+ − 196
+ − 197
// The circly ball ajaxy image + status message
+ − 198
var status_msg = $lang.get('user_login_ajax_generating_key');
+ − 199
+ − 200
// Insert the status message
+ − 201
div.appendChild(document.createTextNode(status_msg));
+ − 202
+ − 203
// Append a br or two to space things properly
+ − 204
div.appendChild(document.createElement('br'));
+ − 205
div.appendChild(document.createElement('br'));
+ − 206
+ − 207
var img = document.createElement('img');
+ − 208
img.src = ( ajax_login_loadimg_path ) ? ajax_login_loadimg_path : scriptPath + '/images/loading-big.gif';
+ − 209
div.appendChild(img);
+ − 210
+ − 211
// Another coupla brs
+ − 212
div.appendChild(document.createElement('br'));
+ − 213
div.appendChild(document.createElement('br'));
+ − 214
+ − 215
// The link to the full login form
+ − 216
var small = document.createElement('small');
+ − 217
small.innerHTML = $lang.get('user_login_ajax_link_fullform_dh', { link_full_form: makeUrlNS('Special', 'Login/' + title) });
+ − 218
div.appendChild(small);
+ − 219
+ − 220
// Insert the entire message into the login window
+ − 221
logindata.mb_inner.innerHTML = '';
+ − 222
logindata.mb_inner.appendChild(div);
+ − 223
+ − 224
break;
+ − 225
case AJAX_STATUS_LOGGING_IN:
+ − 226
+ − 227
// Create the status div
+ − 228
var div = document.createElement('div');
+ − 229
div.id = 'ajax_login_status';
+ − 230
div.style.marginTop = '10px';
+ − 231
div.style.textAlign = 'center';
+ − 232
+ − 233
// The circly ball ajaxy image + status message
+ − 234
var status_msg = $lang.get('user_login_ajax_loggingin');
+ − 235
+ − 236
// Insert the status message
+ − 237
div.appendChild(document.createTextNode(status_msg));
+ − 238
+ − 239
// Append a br or two to space things properly
+ − 240
div.appendChild(document.createElement('br'));
+ − 241
div.appendChild(document.createElement('br'));
+ − 242
+ − 243
var img = document.createElement('img');
+ − 244
img.src = ( ajax_login_loadimg_path ) ? ajax_login_loadimg_path : scriptPath + '/images/loading-big.gif';
+ − 245
div.appendChild(img);
+ − 246
+ − 247
// Insert the entire message into the login window
+ − 248
logindata.mb_inner.innerHTML = '';
+ − 249
logindata.mb_inner.appendChild(div);
+ − 250
+ − 251
break;
+ − 252
case AJAX_STATUS_SUCCESS:
+ − 253
+ − 254
// Create the status div
+ − 255
var div = document.createElement('div');
+ − 256
div.id = 'ajax_login_status';
+ − 257
div.style.marginTop = '10px';
+ − 258
div.style.textAlign = 'center';
+ − 259
+ − 260
// The circly ball ajaxy image + status message
+ − 261
var status_msg = $lang.get('user_login_success_short');
+ − 262
+ − 263
// Insert the status message
+ − 264
div.appendChild(document.createTextNode(status_msg));
+ − 265
+ − 266
// Append a br or two to space things properly
+ − 267
div.appendChild(document.createElement('br'));
+ − 268
div.appendChild(document.createElement('br'));
+ − 269
+ − 270
var img = document.createElement('img');
+ − 271
img.src = ( ajax_login_successimg_path ) ? ajax_login_successimg_path : scriptPath + '/images/check.png';
+ − 272
div.appendChild(img);
+ − 273
+ − 274
// Insert the entire message into the login window
+ − 275
logindata.mb_inner.innerHTML = '';
+ − 276
logindata.mb_inner.appendChild(div);
+ − 277
+ − 278
case AJAX_STATUS_DESTROY:
+ − 279
case null:
+ − 280
case undefined:
+ − 281
logindata.showing_status = false;
+ − 282
return null;
+ − 283
break;
+ − 284
}
+ − 285
logindata.showing_status = true;
+ − 286
}
+ − 287
+ − 288
/**
+ − 289
* Performs an AJAX logon request to the server and calls ajaxLoginProcessResponse() on the result.
+ − 290
* @param object JSON packet to send
+ − 291
*/
+ − 292
+ − 293
function ajaxLoginPerformRequest(json)
+ − 294
{
+ − 295
json = toJSONString(json);
+ − 296
json = ajaxEscape(json);
+ − 297
ajaxPost(makeUrlNS('Special', 'Login/action.json'), 'r=' + json, function()
+ − 298
{
+ − 299
if ( ajax.readyState == 4 && ajax.status == 200 )
+ − 300
{
+ − 301
// parse response
+ − 302
var response = String(ajax.responseText + '');
+ − 303
if ( response.substr(0, 1) != '{' )
+ − 304
{
+ − 305
handle_invalid_json(response);
+ − 306
return false;
+ − 307
}
+ − 308
response = parseJSON(response);
+ − 309
ajaxLoginProcessResponse(response);
+ − 310
}
+ − 311
}, true);
+ − 312
}
+ − 313
+ − 314
/**
+ − 315
* Processes a response from the login server
+ − 316
* @param object JSON response
+ − 317
*/
+ − 318
+ − 319
function ajaxLoginProcessResponse(response)
+ − 320
{
+ − 321
// Did the server send a plaintext error?
+ − 322
if ( response.mode == 'error' )
+ − 323
{
+ − 324
logindata.mb_object.destroy();
+ − 325
new messagebox(MB_ICONSTOP | MB_OK, 'FIXME L10N: There was an error in the login process', 'The following error code came from the server:<br />' + response.error);
+ − 326
return false;
+ − 327
}
+ − 328
// Rid ourselves of any loading windows
+ − 329
ajaxLoginSetStatus(AJAX_STATUS_DESTROY);
+ − 330
// Main mode switch
+ − 331
switch ( response.mode )
+ − 332
{
+ − 333
case 'build_box':
+ − 334
// The server wants us to build the login form, all the information is there
+ − 335
ajaxLoginBuildForm(response);
+ − 336
break;
+ − 337
case 'login_success':
+ − 338
ajaxLoginSetStatus(AJAX_STATUS_SUCCESS);
+ − 339
logindata.successfunc(response.key);
+ − 340
break;
+ − 341
case 'login_failure':
+ − 342
document.getElementById('messageBox').style.backgroundColor = '#C0C0C0';
+ − 343
var mb_parent = document.getElementById('messageBox').parentNode;
+ − 344
new Spry.Effect.Shake(mb_parent, {duration: 1500}).start();
+ − 345
setTimeout(function()
+ − 346
{
+ − 347
document.getElementById('messageBox').style.backgroundColor = '#FFF';
+ − 348
ajaxLoginBuildForm(response.respawn_info);
+ − 349
ajaxLoginShowFriendlyError(response);
+ − 350
}, 2500);
+ − 351
break;
+ − 352
}
+ − 353
}
+ − 354
+ − 355
/*
+ − 356
* RESPONSE HANDLERS
+ − 357
*/
+ − 358
+ − 359
/**
+ − 360
* Builds the login form.
+ − 361
* @param object Metadata to build off of
+ − 362
*/
+ − 363
+ − 364
function ajaxLoginBuildForm(data)
+ − 365
{
+ − 366
// let's hope this effectively preloads the image...
+ − 367
var _ = document.createElement('img');
+ − 368
_.src = ( ajax_login_successimg_path ) ? ajax_login_successimg_path : scriptPath + '/images/check.png';
+ − 369
+ − 370
var div = document.createElement('div');
+ − 371
div.id = 'ajax_login_form';
+ − 372
+ − 373
var show_captcha = ( data.locked_out && data.lockout_info.lockout_policy == 'captcha' ) ? data.lockout_info.captcha : false;
+ − 374
+ − 375
// text displayed on re-auth
+ − 376
if ( logindata.user_level > USER_LEVEL_MEMBER )
+ − 377
{
+ − 378
div.innerHTML += $lang.get('user_login_ajax_prompt_body_elev') + '<br /><br />';
+ − 379
}
+ − 380
+ − 381
// Create the form
+ − 382
var form = document.createElement('form');
+ − 383
form.action = 'javascript:void(ajaxLoginSubmitForm());';
+ − 384
form.onsubmit = function()
+ − 385
{
+ − 386
ajaxLoginSubmitForm();
+ − 387
return false;
+ − 388
}
+ − 389
+ − 390
// Using tables to wrap form elements because it results in a
+ − 391
// more visually appealing form. Yes, tables suck. I don't really
+ − 392
// care - they make forms look good.
+ − 393
+ − 394
var table = document.createElement('table');
+ − 395
table.style.margin = '0 auto';
+ − 396
+ − 397
// Field - username
+ − 398
var tr1 = document.createElement('tr');
+ − 399
var td1_1 = document.createElement('td');
+ − 400
td1_1.appendChild(document.createTextNode($lang.get('user_login_field_username') + ':'));
+ − 401
tr1.appendChild(td1_1);
+ − 402
var td1_2 = document.createElement('td');
+ − 403
var f_username = document.createElement('input');
+ − 404
f_username.id = 'ajax_login_field_username';
+ − 405
f_username.name = 'ajax_login_field_username';
+ − 406
f_username.type = 'text';
+ − 407
f_username.size = '25';
+ − 408
if ( data.username )
+ − 409
f_username.value = data.username;
+ − 410
td1_2.appendChild(f_username);
+ − 411
tr1.appendChild(td1_2);
+ − 412
table.appendChild(tr1);
+ − 413
+ − 414
// Field - password
+ − 415
var tr2 = document.createElement('tr');
+ − 416
var td2_1 = document.createElement('td');
+ − 417
td2_1.appendChild(document.createTextNode($lang.get('user_login_field_password') + ':'));
+ − 418
tr2.appendChild(td2_1);
+ − 419
var td2_2 = document.createElement('td');
+ − 420
var f_password = document.createElement('input');
+ − 421
f_password.id = 'ajax_login_field_password';
+ − 422
f_password.name = 'ajax_login_field_username';
+ − 423
f_password.type = 'password';
+ − 424
f_password.size = '25';
+ − 425
if ( !show_captcha )
+ − 426
{
+ − 427
f_password.onkeyup = function(e)
+ − 428
{
+ − 429
if ( !e.keyCode )
+ − 430
e = window.event;
+ − 431
if ( !e.keyCode )
+ − 432
return true;
+ − 433
if ( e.keyCode == 13 )
+ − 434
{
+ − 435
ajaxLoginSubmitForm();
+ − 436
}
+ − 437
}
+ − 438
}
+ − 439
td2_2.appendChild(f_password);
+ − 440
tr2.appendChild(td2_2);
+ − 441
table.appendChild(tr2);
+ − 442
+ − 443
// Field - captcha
+ − 444
if ( show_captcha )
+ − 445
{
+ − 446
var tr3 = document.createElement('tr');
+ − 447
var td3_1 = document.createElement('td');
+ − 448
td3_1.appendChild(document.createTextNode($lang.get('user_login_field_captcha') + ':'));
+ − 449
tr3.appendChild(td3_1);
+ − 450
var td3_2 = document.createElement('td');
+ − 451
var f_captcha = document.createElement('input');
+ − 452
f_captcha.id = 'ajax_login_field_captcha';
+ − 453
f_captcha.name = 'ajax_login_field_username';
+ − 454
f_captcha.type = 'text';
+ − 455
f_captcha.size = '25';
+ − 456
f_captcha.onkeyup = function(e)
+ − 457
{
+ − 458
if ( !e )
+ − 459
e = window.event;
+ − 460
if ( !e.keyCode )
+ − 461
return true;
+ − 462
if ( e.keyCode == 13 )
+ − 463
{
+ − 464
ajaxLoginSubmitForm();
+ − 465
}
+ − 466
}
+ − 467
td3_2.appendChild(f_captcha);
+ − 468
tr3.appendChild(td3_2);
+ − 469
table.appendChild(tr3);
+ − 470
}
+ − 471
+ − 472
// Done building the main part of the form
+ − 473
form.appendChild(table);
+ − 474
+ − 475
// Field: enable Diffie Hellman
+ − 476
var lbl_dh = document.createElement('label');
+ − 477
lbl_dh.style.fontSize = 'smaller';
+ − 478
lbl_dh.style.display = 'block';
+ − 479
lbl_dh.style.textAlign = 'center';
+ − 480
var check_dh = document.createElement('input');
+ − 481
check_dh.type = 'checkbox';
+ − 482
// this onclick attribute changes the cookie whenever the checkbox or label is clicked
+ − 483
check_dh.setAttribute('onclick', 'var ck = ( this.checked ) ? "enable" : "disable"; createCookie("diffiehellman_login", ck, 3650);');
+ − 484
if ( readCookie('diffiehellman_login') != 'disable' )
+ − 485
check_dh.setAttribute('checked', 'checked');
+ − 486
check_dh.id = 'ajax_login_field_dh';
+ − 487
lbl_dh.appendChild(check_dh);
+ − 488
lbl_dh.innerHTML += $lang.get('user_login_ajax_check_dh');
+ − 489
form.appendChild(lbl_dh);
+ − 490
+ − 491
div.appendChild(form);
+ − 492
+ − 493
// Diagnostic / help links
+ − 494
// (only displayed in login, not in re-auth)
+ − 495
if ( logindata.user_level == USER_LEVEL_MEMBER )
+ − 496
{
+ − 497
form.style.marginBottom = '10px';
+ − 498
var links = document.createElement('small');
+ − 499
links.style.display = 'block';
+ − 500
links.style.textAlign = 'center';
+ − 501
links.innerHTML = '';
+ − 502
if ( !show_captcha )
+ − 503
links.innerHTML += $lang.get('user_login_ajax_link_fullform', { link_full_form: makeUrlNS('Special', 'Login/' + title) }) + '<br />';
+ − 504
// Always shown
+ − 505
links.innerHTML += $lang.get('user_login_ajax_link_forgotpass', { forgotpass_link: makeUrlNS('Special', 'PasswordReset') }) + '<br />';
+ − 506
if ( !show_captcha )
+ − 507
links.innerHTML += $lang.get('user_login_createaccount_blurb', { reg_link: makeUrlNS('Special', 'Register') });
+ − 508
div.appendChild(links);
+ − 509
}
+ − 510
+ − 511
// Insert the entire form into the login window
+ − 512
logindata.mb_inner.innerHTML = '';
+ − 513
logindata.mb_inner.appendChild(div);
+ − 514
+ − 515
// Post operations: field focus
+ − 516
if ( data.username )
+ − 517
f_password.focus();
+ − 518
else
+ − 519
f_username.focus();
+ − 520
+ − 521
// Post operations: show captcha window
+ − 522
if ( show_captcha )
+ − 523
ajaxShowCaptcha(show_captcha);
+ − 524
+ − 525
// Post operations: stash encryption keys and All That Jazz(TM)
+ − 526
logindata.key_aes = data.aes_key;
+ − 527
logindata.key_dh = data.dh_public_key;
+ − 528
logindata.captcha_hash = show_captcha;
+ − 529
+ − 530
// Are we locked out? If so simulate an error and disable the controls
+ − 531
if ( data.lockout_info.lockout_policy == 'lockout' && data.locked_out )
+ − 532
{
+ − 533
f_username.setAttribute('disabled', 'disabled');
+ − 534
f_password.setAttribute('disabled', 'disabled');
+ − 535
var fake_packet = {
+ − 536
error_code: 'locked_out',
+ − 537
respawn_info: data
+ − 538
};
+ − 539
ajaxLoginShowFriendlyError(fake_packet);
+ − 540
}
+ − 541
}
+ − 542
+ − 543
function ajaxLoginSubmitForm(real, username, password, captcha)
+ − 544
{
+ − 545
// Perform AES test to make sure it's all working
+ − 546
if ( !aes_self_test() )
+ − 547
{
+ − 548
alert('BUG: AES self-test failed');
+ − 549
login_cache.mb_object.destroy();
+ − 550
return false;
+ − 551
}
+ − 552
// Hide the error message and captcha
+ − 553
if ( document.getElementById('ajax_login_error_box') )
+ − 554
{
+ − 555
document.getElementById('ajax_login_error_box').parentNode.removeChild(document.getElementById('ajax_login_error_box'));
+ − 556
}
+ − 557
if ( document.getElementById('autoCaptcha') )
+ − 558
{
+ − 559
var to = fly_out_top(document.getElementById('autoCaptcha'), false, true);
+ − 560
setTimeout(function() {
+ − 561
var d = document.getElementById('autoCaptcha');
+ − 562
d.parentNode.removeChild(d);
+ − 563
}, to);
+ − 564
}
+ − 565
// Encryption: preprocessor
+ − 566
if ( real )
+ − 567
{
+ − 568
var do_dh = true;
+ − 569
}
+ − 570
else if ( document.getElementById('ajax_login_field_dh') )
+ − 571
{
+ − 572
var do_dh = document.getElementById('ajax_login_field_dh').checked;
+ − 573
}
+ − 574
else
+ − 575
{
+ − 576
// The user probably clicked ok when the form wasn't in there.
+ − 577
return false;
+ − 578
}
+ − 579
if ( !username )
+ − 580
{
+ − 581
var username = document.getElementById('ajax_login_field_username').value;
+ − 582
}
+ − 583
if ( !password )
+ − 584
{
+ − 585
var password = document.getElementById('ajax_login_field_password').value;
+ − 586
}
+ − 587
if ( !captcha && document.getElementById('ajax_login_field_captcha') )
+ − 588
{
+ − 589
var captcha = document.getElementById('ajax_login_field_captcha').value;
+ − 590
}
+ − 591
+ − 592
if ( do_dh )
+ − 593
{
+ − 594
ajaxLoginSetStatus(AJAX_STATUS_GENERATING_KEY);
+ − 595
if ( !real )
+ − 596
{
+ − 597
// Wait while the browser updates the login window
+ − 598
setTimeout(function()
+ − 599
{
+ − 600
ajaxLoginSubmitForm(true, username, password, captcha);
+ − 601
}, 200);
+ − 602
return true;
+ − 603
}
+ − 604
// Perform Diffie Hellman stuff
+ − 605
var dh_priv = dh_gen_private();
+ − 606
var dh_pub = dh_gen_public(dh_priv);
+ − 607
var secret = dh_gen_shared_secret(dh_priv, logindata.key_dh);
+ − 608
// secret_hash is used to verify that the server guesses the correct secret
+ − 609
var secret_hash = hex_sha1(secret);
+ − 610
// crypt_key is the actual AES key
+ − 611
var crypt_key = (hex_sha256(secret)).substr(0, (keySizeInBits / 4));
+ − 612
}
+ − 613
else
+ − 614
{
+ − 615
var crypt_key = logindata.key_aes;
+ − 616
}
+ − 617
+ − 618
ajaxLoginSetStatus(AJAX_STATUS_LOGGING_IN);
+ − 619
+ − 620
// Encrypt the password and username
+ − 621
var userinfo = toJSONString({
+ − 622
username: username,
+ − 623
password: password
+ − 624
});
+ − 625
var crypt_key_ba = hexToByteArray(crypt_key);
+ − 626
userinfo = stringToByteArray(userinfo);
+ − 627
+ − 628
userinfo = rijndaelEncrypt(userinfo, crypt_key_ba, 'ECB');
+ − 629
userinfo = byteArrayToHex(userinfo);
+ − 630
// Encrypted username and password (serialized with JSON) are now in the userinfo string
+ − 631
+ − 632
// Collect other needed information
+ − 633
if ( logindata.captcha_hash )
+ − 634
{
+ − 635
var captcha_hash = logindata.captcha_hash;
+ − 636
var captcha_code = captcha;
+ − 637
}
+ − 638
else
+ − 639
{
+ − 640
var captcha_hash = false;
+ − 641
var captcha_code = false;
+ − 642
}
+ − 643
+ − 644
// Ship it across the 'net
+ − 645
if ( do_dh )
+ − 646
{
+ − 647
var json_packet = {
+ − 648
mode: 'login_dh',
+ − 649
userinfo: userinfo,
+ − 650
captcha_code: captcha_code,
+ − 651
captcha_hash: captcha_hash,
+ − 652
dh_public_key: logindata.key_dh,
+ − 653
dh_client_key: dh_pub,
+ − 654
dh_secret_hash: secret_hash,
+ − 655
level: logindata.user_level
+ − 656
}
+ − 657
}
+ − 658
else
+ − 659
{
+ − 660
var json_packet = {
+ − 661
mode: 'login_aes',
+ − 662
userinfo: userinfo,
+ − 663
captcha_code: captcha_code,
+ − 664
captcha_hash: captcha_hash,
+ − 665
key_aes: hex_md5(crypt_key),
+ − 666
level: logindata.user_level
+ − 667
}
+ − 668
}
+ − 669
ajaxLoginPerformRequest(json_packet);
+ − 670
}
+ − 671
+ − 672
function ajaxLoginShowFriendlyError(response)
+ − 673
{
+ − 674
if ( !response.respawn_info )
+ − 675
return false;
+ − 676
if ( !response.error_code )
+ − 677
return false;
+ − 678
var text = ajaxLoginGetErrorText(response);
+ − 679
if ( document.getElementById('ajax_login_error_box') )
+ − 680
{
+ − 681
// console.info('Reusing existing error-box');
+ − 682
document.getElementById('ajax_login_error_box').innerHTML = text;
+ − 683
return true;
+ − 684
}
+ − 685
+ − 686
// console.info('Drawing new error-box');
+ − 687
+ − 688
// calculate position for the top of the box
+ − 689
var mb_bottom = $('messageBoxButtons').Top() + $('messageBoxButtons').Height();
+ − 690
// if the box isn't done flying in yet, just estimate
+ − 691
if ( mb_bottom < ( getHeight() / 2 ) )
+ − 692
{
+ − 693
mb_bottom = ( getHeight() / 2 ) + 120;
+ − 694
}
+ − 695
var win_bottom = getHeight() + getScrollOffset();
+ − 696
var top = mb_bottom + ( ( win_bottom - mb_bottom ) / 2 ) - 32;
+ − 697
// left position = 0.2 * window_width, seeing as the box is 60% width this works hackishly but nice and quick
+ − 698
var left = getWidth() * 0.2;
+ − 699
+ − 700
// create the div
+ − 701
var errbox = document.createElement('div');
+ − 702
errbox.className = 'error-box-mini';
+ − 703
errbox.style.position = 'absolute';
+ − 704
errbox.style.width = '60%';
+ − 705
errbox.style.top = top + 'px';
+ − 706
errbox.style.left = left + 'px';
+ − 707
errbox.innerHTML = text;
+ − 708
errbox.id = 'ajax_login_error_box';
+ − 709
+ − 710
var body = document.getElementsByTagName('body')[0];
+ − 711
body.appendChild(errbox);
+ − 712
}
+ − 713
+ − 714
function ajaxLoginGetErrorText(response)
+ − 715
{
+ − 716
switch ( response.error_code )
+ − 717
{
+ − 718
default:
+ − 719
return $lang.get('user_err_' + response.error_code);
+ − 720
break;
+ − 721
case 'locked_out':
+ − 722
if ( response.respawn_info.lockout_info.lockout_policy == 'lockout' )
+ − 723
{
+ − 724
return $lang.get('user_err_locked_out', {
+ − 725
lockout_threshold: response.respawn_info.lockout_info.lockout_threshold,
+ − 726
lockout_duration: response.respawn_info.lockout_info.lockout_duration,
+ − 727
time_rem: response.respawn_info.lockout_info.time_rem,
+ − 728
plural: ( response.respawn_info.lockout_info.time_rem == 1 ) ? '' : $lang.get('meta_plural'),
+ − 729
captcha_blurb: ''
+ − 730
});
+ − 731
break;
+ − 732
}
+ − 733
case 'invalid_credentials':
+ − 734
var base = $lang.get('user_err_invalid_credentials');
+ − 735
if ( response.respawn_info.locked_out )
+ − 736
{
+ − 737
base += ' ';
+ − 738
var captcha_blurb = '';
+ − 739
switch(response.respawn_info.lockout_info.lockout_policy)
+ − 740
{
+ − 741
case 'captcha':
+ − 742
captcha_blurb = $lang.get('user_err_locked_out_captcha_blurb');
+ − 743
break;
+ − 744
case 'lockout':
+ − 745
break;
+ − 746
default:
+ − 747
base += 'WTF? Shouldn\'t be locked out with lockout policy set to disable.';
+ − 748
break;
+ − 749
}
+ − 750
base += $lang.get('user_err_locked_out', {
+ − 751
captcha_blurb: captcha_blurb,
+ − 752
lockout_threshold: response.respawn_info.lockout_info.lockout_threshold,
+ − 753
lockout_duration: response.respawn_info.lockout_info.lockout_duration,
+ − 754
time_rem: response.respawn_info.lockout_info.time_rem,
+ − 755
plural: ( response.respawn_info.lockout_info.time_rem == 1 ) ? '' : $lang.get('meta_plural')
+ − 756
});
+ − 757
}
+ − 758
else if ( response.respawn_info.lockout_info.lockout_policy == 'lockout' || response.respawn_info.lockout_info.lockout_policy == 'captcha' )
+ − 759
{
+ − 760
// if we have a lockout policy of captcha or lockout, then warn the user
+ − 761
switch ( response.respawn_info.lockout_info.lockout_policy )
+ − 762
{
+ − 763
case 'captcha':
+ − 764
base += $lang.get('user_err_invalid_credentials_lockout', {
+ − 765
fails: response.respawn_info.lockout_info.lockout_fails,
+ − 766
lockout_threshold: response.respawn_info.lockout_info.lockout_threshold,
+ − 767
lockout_duration: response.respawn_info.lockout_info.lockout_duration
+ − 768
});
+ − 769
break;
+ − 770
case 'lockout':
+ − 771
break;
+ − 772
}
+ − 773
}
+ − 774
return base;
+ − 775
break;
+ − 776
}
+ − 777
}
+ − 778