297 } |
297 } |
298 } |
298 } |
299 |
299 |
300 /* |
300 /* |
301 * AJAX login box (experimental) |
301 * AJAX login box (experimental) |
302 */ |
302 * Moved / rewritten in login.js |
303 |
303 */ |
304 var ajax_auth_prompt_cache = false; |
304 |
305 var ajax_auth_mb_cache = false; |
305 // Included only for API-compatibility |
306 var ajax_auth_level_cache = false; |
|
307 var ajax_auth_error_string = false; |
|
308 var ajax_auth_show_captcha = false; |
|
309 |
|
310 function ajaxAuthErrorToString($data) |
|
311 { |
|
312 var $errstring = $data.error; |
|
313 // this was literally copied straight from the PHP code. |
|
314 switch($data.error) |
|
315 { |
|
316 case 'key_not_found': |
|
317 $errstring = $lang.get('user_err_key_not_found'); |
|
318 break; |
|
319 case 'key_wrong_length': |
|
320 $errstring = $lang.get('user_err_key_wrong_length'); |
|
321 break; |
|
322 case 'too_big_for_britches': |
|
323 $errstring = $lang.get('user_err_too_big_for_britches'); |
|
324 break; |
|
325 case 'invalid_credentials': |
|
326 $errstring = $lang.get('user_err_invalid_credentials'); |
|
327 var subst = { |
|
328 fails: $data.lockout_fails, |
|
329 lockout_threshold: $data.lockout_threshold, |
|
330 lockout_duration: $data.lockout_duration |
|
331 } |
|
332 if ( $data.lockout_policy == 'lockout' ) |
|
333 { |
|
334 $errstring += $lang.get('user_err_invalid_credentials_lockout', subst); |
|
335 } |
|
336 else if ( $data.lockout_policy == 'captcha' ) |
|
337 { |
|
338 $errstring += $lang.get('user_err_invalid_credentials_lockout_captcha', subst); |
|
339 } |
|
340 break; |
|
341 case 'backend_fail': |
|
342 $errstring = $lang.get('user_err_backend_fail'); |
|
343 break; |
|
344 case 'locked_out': |
|
345 $attempts = parseInt($data['lockout_fails']); |
|
346 if ( $attempts > $data['lockout_threshold']) |
|
347 $attempts = $data['lockout_threshold']; |
|
348 $time_rem = $data.time_rem; |
|
349 $s = ( $time_rem == 1 ) ? '' : $lang.get('meta_plural'); |
|
350 |
|
351 var subst = { |
|
352 lockout_threshold: $data.lockout_threshold, |
|
353 time_rem: $time_rem, |
|
354 plural: $s, |
|
355 captcha_blurb: ( $data.lockout_policy == 'captcha' ? $lang.get('user_err_locked_out_captcha_blurb') : '' ) |
|
356 } |
|
357 |
|
358 $errstring = $lang.get('user_err_locked_out', subst); |
|
359 |
|
360 break; |
|
361 } |
|
362 return $errstring; |
|
363 } |
|
364 |
|
365 function ajaxPromptAdminAuth(call_on_ok, level) |
306 function ajaxPromptAdminAuth(call_on_ok, level) |
366 { |
307 { |
367 if ( typeof(call_on_ok) == 'function' ) |
308 ajaxLogonInit(call_on_ok, level); |
368 { |
|
369 ajax_auth_prompt_cache = call_on_ok; |
|
370 } |
|
371 if ( !level ) |
|
372 level = USER_LEVEL_MEMBER; |
|
373 ajax_auth_level_cache = level; |
|
374 var loading_win = '<div align="center" style="text-align: center;"> \ |
|
375 <p>' + $lang.get('user_login_ajax_fetching_key') + '</p> \ |
|
376 <p><small>' + $lang.get('user_login_ajax_link_fullform', { link_full_form: makeUrlNS('Special', 'Login/' + title) }) + '</p> \ |
|
377 <p><img alt="Please wait..." src="'+scriptPath+'/images/loading-big.gif" /></p> \ |
|
378 </div>'; |
|
379 var title = ( level > USER_LEVEL_MEMBER ) ? $lang.get('user_login_ajax_prompt_title_elev') : $lang.get('user_login_ajax_prompt_title'); |
|
380 ajax_auth_mb_cache = new messagebox(MB_OKCANCEL|MB_ICONLOCK, title, loading_win); |
|
381 ajax_auth_mb_cache.onbeforeclick['OK'] = ajaxValidateLogin; |
|
382 ajax_auth_mb_cache.onbeforeclick['Cancel'] = function() |
|
383 { |
|
384 if ( document.getElementById('autoCaptcha') ) |
|
385 { |
|
386 var to = fly_out_top(document.getElementById('autoCaptcha'), false, true); |
|
387 setTimeout(function() { |
|
388 var d = document.getElementById('autoCaptcha'); |
|
389 d.parentNode.removeChild(d); |
|
390 }, to); |
|
391 } |
|
392 } |
|
393 ajaxAuthLoginInnerSetup(); |
|
394 } |
|
395 |
|
396 function ajaxAuthLoginInnerSetup() |
|
397 { |
|
398 // let's hope this gets the image cached |
|
399 var _ = new Image(32, 32); |
|
400 _.src = scriptPath + "/images/check.png"; |
|
401 |
|
402 ajaxGet(makeUrlNS('Special', 'Login', 'act=getkey'), function() { |
|
403 if ( ajax.readyState == 4 && ajax.status == 200 ) |
|
404 { |
|
405 var response = String(ajax.responseText); |
|
406 if ( response.substr(0,1) != '{' ) |
|
407 { |
|
408 handle_invalid_json(response); |
|
409 ajax_auth_mb_cache.destroy(); |
|
410 return false; |
|
411 } |
|
412 response = parseJSON(response); |
|
413 var disable_controls = false; |
|
414 if ( response.locked_out && !ajax_auth_error_string ) |
|
415 { |
|
416 response.error = 'locked_out'; |
|
417 ajax_auth_error_string = ajaxAuthErrorToString(response); |
|
418 if ( response.lockout_policy == 'captcha' ) |
|
419 { |
|
420 ajax_auth_show_captcha = response.captcha; |
|
421 } |
|
422 else |
|
423 { |
|
424 disable_controls = true; |
|
425 } |
|
426 } |
|
427 var level = ajax_auth_level_cache; |
|
428 var form_html = ''; |
|
429 var shown_error = false; |
|
430 if ( ajax_auth_error_string ) |
|
431 { |
|
432 shown_error = true; |
|
433 form_html += '<div class="error-box-mini" id="ajax_auth_error">' + ajax_auth_error_string + '</div>'; |
|
434 ajax_auth_error_string = false; |
|
435 } |
|
436 else if ( level > USER_LEVEL_MEMBER ) |
|
437 { |
|
438 form_html += $lang.get('user_login_ajax_prompt_body_elev') + '<br /><br />'; |
|
439 } |
|
440 if ( ajax_auth_show_captcha ) |
|
441 { |
|
442 var captcha_html = ' \ |
|
443 <tr> \ |
|
444 <td>' + $lang.get('user_login_field_captcha') + ':</td> \ |
|
445 <td><input type="hidden" id="ajaxlogin_captcha_hash" value="' + ajax_auth_show_captcha + '" /><input type="text" tabindex="3" size="25" id="ajaxlogin_captcha_code" /> \ |
|
446 </tr>'; |
|
447 } |
|
448 else |
|
449 { |
|
450 var captcha_html = ''; |
|
451 } |
|
452 var disableme = ( disable_controls ) ? 'disabled="disabled" ' : ''; |
|
453 form_html += ' \ |
|
454 <form action="#" onsubmit="ajaxValidateLogin(); return false;" name="ajax_login_form"> \ |
|
455 <table border="0" align="center"> \ |
|
456 <tr> \ |
|
457 <td>' + $lang.get('user_login_field_username') + ':</td><td><input tabindex="1" id="ajaxlogin_user" type="text" ' + disableme + 'size="25" /> \ |
|
458 </tr> \ |
|
459 <tr> \ |
|
460 <td>' + $lang.get('user_login_field_password') + ':</td><td><input tabindex="2" id="ajaxlogin_pass" type="password" ' + disableme + 'size="25" /> \ |
|
461 </tr> \ |
|
462 ' + captcha_html + ' \ |
|
463 <tr> \ |
|
464 <td colspan="2" style="text-align: center;"> \ |
|
465 <small>' + $lang.get('user_login_ajax_link_fullform', { link_full_form: makeUrlNS('Special', 'Login/' + title, 'level=' + level) }) + '<br />'; |
|
466 if ( level <= USER_LEVEL_MEMBER ) |
|
467 { |
|
468 form_html += ' \ |
|
469 ' + $lang.get('user_login_ajax_link_forgotpass', { forgotpass_link: makeUrlNS('Special', 'PasswordReset') }) + '<br /> \ |
|
470 ' + $lang.get('user_login_createaccount_blurb', { reg_link: makeUrlNS('Special', 'Register') }); |
|
471 } |
|
472 form_html += '</small> \ |
|
473 </td> \ |
|
474 </tr> \ |
|
475 </table> \ |
|
476 <input type="hidden" id="ajaxlogin_crypt_key" value="' + response.key + '" /> \ |
|
477 <input type="hidden" id="ajaxlogin_crypt_challenge" value="' + response.challenge + '" /> \ |
|
478 </form>'; |
|
479 ajax_auth_mb_cache.updateContent(form_html); |
|
480 $dynano('messageBox').object.nextSibling.firstChild.tabindex = '3'; |
|
481 if ( typeof(response.username) == 'string' ) |
|
482 { |
|
483 $dynano('ajaxlogin_user').object.value = response.username; |
|
484 if ( IE ) |
|
485 { |
|
486 setTimeout("document.forms['ajax_login_form'].password.focus();", 200); |
|
487 } |
|
488 else |
|
489 { |
|
490 $dynano('ajaxlogin_pass').object.focus(); |
|
491 } |
|
492 } |
|
493 else |
|
494 { |
|
495 if ( IE ) |
|
496 { |
|
497 setTimeout("document.forms['ajax_login_form'].username.focus();", 200); |
|
498 } |
|
499 else |
|
500 { |
|
501 $dynano('ajaxlogin_user').object.focus(); |
|
502 } |
|
503 } |
|
504 var enter_obj = ( ajax_auth_show_captcha ) ? 'ajaxlogin_captcha_code' : 'ajaxlogin_pass'; |
|
505 $dynano(enter_obj).object.onblur = function(e) { if ( !shift ) $dynano('messageBox').object.nextSibling.firstChild.focus(); }; |
|
506 $dynano(enter_obj).object.onkeypress = function(e) |
|
507 { |
|
508 // Trigger a form submit when the password field is focused and the user presses enter |
|
509 |
|
510 // IE doesn't give us an event object when it should - check window.event. If that |
|
511 // still fails, give up. |
|
512 if ( !e ) |
|
513 { |
|
514 e = window.event; |
|
515 } |
|
516 if ( !e && IE ) |
|
517 { |
|
518 return true; |
|
519 } |
|
520 if ( e.keyCode == 13 ) |
|
521 { |
|
522 ajaxValidateLogin(); |
|
523 } |
|
524 }; |
|
525 /* |
|
526 ## This causes the background image to disappear under Fx 2 |
|
527 if ( shown_error ) |
|
528 { |
|
529 // fade to #FFF4F4 |
|
530 var fader = new Spry.Effect.Highlight('ajax_auth_error', {duration: 1000, from: '#FFF4F4', to: '#805600', restoreColor: '#805600', finish: function() |
|
531 { |
|
532 var fader = new Spry.Effect.Highlight('ajax_auth_error', {duration: 3000, from: '#805600', to: '#FFF4F4', restoreColor: '#FFF4F4'}); |
|
533 fader.start(); |
|
534 }}); |
|
535 fader.start(); |
|
536 } |
|
537 */ |
|
538 if ( ajax_auth_show_captcha ) |
|
539 { |
|
540 ajaxShowCaptcha(ajax_auth_show_captcha); |
|
541 ajax_auth_show_captcha = false; |
|
542 } |
|
543 } |
|
544 }); |
|
545 } |
|
546 |
|
547 function ajaxValidateLogin() |
|
548 { |
|
549 var username,password,auth_enabled,crypt_key,crypt_data,challenge_salt,challenge_data; |
|
550 username = document.getElementById('ajaxlogin_user'); |
|
551 if ( !username ) |
|
552 return false; |
|
553 username = document.getElementById('ajaxlogin_user').value; |
|
554 password = document.getElementById('ajaxlogin_pass').value; |
|
555 auth_enabled = false; |
|
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 |
|
566 disableJSONExts(); |
|
567 |
|
568 var auth_enabled = aes_self_test(); |
|
569 |
|
570 if ( !auth_enabled ) |
|
571 { |
|
572 alert('Login error: encryption sanity check failed\n'); |
|
573 return true; |
|
574 } |
|
575 |
|
576 crypt_key = document.getElementById('ajaxlogin_crypt_key').value; |
|
577 challenge_salt = document.getElementById('ajaxlogin_crypt_challenge').value; |
|
578 |
|
579 var crypt_key_md5 = hex_md5(crypt_key); |
|
580 |
|
581 challenge_data = hex_md5(password + challenge_salt) + challenge_salt; |
|
582 |
|
583 password = stringToByteArray(password); |
|
584 crypt_key = hexToByteArray(crypt_key); |
|
585 |
|
586 crypt_data = rijndaelEncrypt(password, crypt_key, 'ECB'); |
|
587 crypt_data = byteArrayToHex(crypt_data); |
|
588 |
|
589 var json_data = { |
|
590 'username' : username, |
|
591 'crypt_key' : crypt_key_md5, |
|
592 'challenge' : challenge_data, |
|
593 'crypt_data' : crypt_data, |
|
594 'level' : ajax_auth_level_cache |
|
595 }; |
|
596 |
|
597 if ( document.getElementById('ajaxlogin_captcha_hash') ) |
|
598 { |
|
599 json_data.captcha_hash = document.getElementById('ajaxlogin_captcha_hash').value; |
|
600 json_data.captcha_code = document.getElementById('ajaxlogin_captcha_code').value; |
|
601 } |
|
602 |
|
603 json_data = toJSONString(json_data); |
|
604 json_data = encodeURIComponent(json_data); |
|
605 |
|
606 var loading_win = '<div align="center" style="text-align: center;"> \ |
|
607 <p>' + $lang.get('user_login_ajax_loggingin') + '</p> \ |
|
608 <p><img alt="Please wait..." src="'+scriptPath+'/images/loading-big.gif" /></p> \ |
|
609 </div>'; |
|
610 |
|
611 ajax_auth_mb_cache.updateContent(loading_win); |
|
612 |
|
613 ajaxPost(makeUrlNS('Special', 'Login', 'act=ajaxlogin'), 'params=' + json_data, function() { |
|
614 if ( ajax.readyState == 4 && ajax.status == 200 ) |
|
615 { |
|
616 var response = ajax.responseText; |
|
617 if ( response.substr(0,1) != '{' ) |
|
618 { |
|
619 alert('Invalid JSON response from server: ' + response); |
|
620 ajaxAuthLoginInnerSetup(); |
|
621 return false; |
|
622 } |
|
623 response = parseJSON(response); |
|
624 switch(response.result) |
|
625 { |
|
626 case 'success': |
|
627 var success_win = '<div align="center" style="text-align: center;"> \ |
|
628 <p>' + $lang.get('user_login_success_short') + '</p> \ |
|
629 <p><img alt=" " src="'+scriptPath+'/images/check.png" /></p> \ |
|
630 </div>'; |
|
631 ajax_auth_mb_cache.updateContent(success_win); |
|
632 if ( typeof(ajax_auth_prompt_cache) == 'function' ) |
|
633 { |
|
634 ajax_auth_prompt_cache(response.key); |
|
635 } |
|
636 break; |
|
637 case 'success_reset': |
|
638 var conf = confirm($lang.get('user_login_ajax_msg_used_temp_pass')); |
|
639 if ( conf ) |
|
640 { |
|
641 var url = makeUrlNS('Special', 'PasswordReset/stage2/' + response.user_id + '/' + response.temppass); |
|
642 window.location = url; |
|
643 } |
|
644 else |
|
645 { |
|
646 ajaxAuthLoginInnerSetup(); |
|
647 } |
|
648 break; |
|
649 case 'error': |
|
650 if ( response.data.error == 'invalid_credentials' || response.data.error == 'locked_out' ) |
|
651 { |
|
652 ajax_auth_error_string = ajaxAuthErrorToString(response.data); |
|
653 mb_current_obj.updateContent(''); |
|
654 document.getElementById('messageBox').style.backgroundColor = '#C0C0C0'; |
|
655 var mb_parent = document.getElementById('messageBox').parentNode; |
|
656 new Spry.Effect.Shake(mb_parent, {duration: 1500}).start(); |
|
657 setTimeout("document.getElementById('messageBox').style.backgroundColor = '#FFF'; ajaxAuthLoginInnerSetup();", 2500); |
|
658 |
|
659 if ( response.data.lockout_policy == 'captcha' && response.data.error == 'locked_out' ) |
|
660 { |
|
661 ajax_auth_show_captcha = response.captcha; |
|
662 } |
|
663 } |
|
664 else |
|
665 { |
|
666 ajax_auth_error_string = ajaxAuthErrorToString(response.data); |
|
667 ajaxAuthLoginInnerSetup(); |
|
668 } |
|
669 break; |
|
670 default: |
|
671 alert(ajax.responseText); |
|
672 break; |
|
673 } |
|
674 } |
|
675 }); |
|
676 |
|
677 return true; |
|
678 |
|
679 } |
309 } |
680 |
310 |
681 // This code is in the public domain. Feel free to link back to http://jan.moesen.nu/ |
311 // This code is in the public domain. Feel free to link back to http://jan.moesen.nu/ |
682 function sprintf() |
312 function sprintf() |
683 { |
313 { |