MeshCentral/views/translations/login-mobile_ja.handlebars

647 lines
44 KiB
Handlebars
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html><html dir="ltr" xmlns="http://www.w3.org/1999/xhtml"><head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta name="viewport" content="user-scalable=1.0,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="format-detection" content="telephone=no">
<link rel="shortcut icon" type="image/x-icon" href="{{{domainurl}}}favicon.ico">
<script type="text/javascript" src="scripts/common-0.0.1.js"></script>
<script type="text/javascript" src="scripts/u2f-api.js"></script>
<title>{{{title}}} - Login</title>
<style>
a {
color: #036;
text-decoration: underline;
}
#footer a {
color: #fff;
text-decoration: underline;
}
#footer a:hover {
color: #fff;
text-decoration: none;
}
</style>
</head>
<body onload="if (typeof(startup) !== 'undefined') startup();" style="overflow-y:hidden;margin:0;padding:0;border:0;color:black;font-size:13px;font-family:\'Trebuchet MS\', Arial, Helvetica, sans-serif">
<div id="container">
<div id="mastheadx"></div>
<div id="masthead" style="background:url(logo.png) 0px 0px;background-size:341px 50px;background-color:#036;background-repeat:no-repeat;height:50px;width:100%;overflow:hidden">
<div style="float:left;height:66px;color:#c8c8c8;padding-left:10px;padding-top:6px">
<strong><font style="font-size:36px;font-family:Arial,Helvetica,sans-serif">{{{title}}}</font></strong>
</div>
<div style="float:left;height:66px;color:#c8c8c8;padding-left:5px;padding-top:10px">
<strong><font style="font-size:12px;font-family:Arial,Helvetica,sans-serif">{{{title2}}}</font></strong>
</div>
</div>
<div id="page_content" style="overflow-y:scroll;position:absolute;bottom:32px;top:50px;width:100%;display:flex;align-items:center">
<div id="column_l" style="padding:10px;width:100%">
<table style="width:100%">
<tbody><tr>
<td align="center">
<div id="loginpanel" style="background-color:#979797;border-radius:16px;width:260px;padding:16px;text-align:center;clear:both;display:none">
<form method="post">
<input type="hidden" name="action" value="login">
<div id="message1"></div>
<div>
<b>ログイン</b>
</div>
<table>
<tbody><tr>
<td id="loginusername" align="right" width="100">ユーザー名:</td>
<td><input id="username" type="text" maxlength="64" name="username" onchange="validateLogin(1)" onkeyup="validateLogin(1,event)"></td>
</tr>
<tr>
<td align="right">パスワード:</td>
<td><input id="password" type="password" maxlength="256" name="password" autocomplete="off" onchange="validateLogin(2)" onkeyup="validateLogin(2,event)"></td>
</tr>
<tr>
<td><div id="showPassHintLink" style="display:none"><a onclick="showPassHint()" style="cursor:pointer">ヒントを見せて</a></div></td>
<td align="right"><input id="loginButton" type="submit" value="ログイン" disabled="disabled"></td>
</tr>
</tbody></table>
<div id="hrAccountDiv" style="display:none"><hr></div>
<div id="resetAccountDiv" style="display:none;padding:2px">
<span id="resetAccountSpan">ユーザー/パスワードを忘れましたか?</span> <a onclick="xgo(3)" style="cursor:pointer">アカウントをリセット</a>。
</div>
<div id="newAccountDiv" style="display:none;padding:2px">
アカウントを持っていないのですか? <a onclick="xgo(2)" style="cursor:pointer">一つ作る</a>。
</div>
<input id="loginformargs" name="urlargs" type="hidden" value="">
</form>
</div>
<div id="createpanel" style="display:none">
<div style="background-color:#979797;border-radius:16px;width:260px;padding:16px;text-align:center;clear:both;position:relative">
<form method="post">
<input type="hidden" name="action" value="createaccount">
<div id="message2"></div>
<div>
<b>アカウント作成</b>
</div>
<div id="passwordPolicyCallout" style="left:-5px;top:10px;width:100px;position:absolute;background-color:#FFC;border-radius:5px;padding:5px;box-shadow:0px 0px 15px #666;font-size:10px"></div>
<table>
<tbody><tr id="nuUserRow">
<td align="right" width="100">ユーザー名:</td>
<td><input id="ausername" type="text" name="username" onchange="validateCreate(1)" maxlength="64" onkeydown="haltReturn(event)" onkeyup="validateCreate(1,event)"></td>
</tr>
<tr>
<td align="right" width="100">Eメール</td>
<td><input id="aemail" type="text" name="email" onchange="validateCreate(2)" maxlength="256" onkeydown="haltReturn(event)" onkeyup="validateCreate(2,event)"></td>
</tr>
<tr>
<td align="right">パスワード:</td>
<td><input id="apassword1" type="password" name="password1" autocomplete="off" maxlength="256" onkeydown="haltReturn(event)" onchange="validateCreate(3)" onkeyup="validateCreate(3,event)"></td>
</tr>
<tr>
<td align="right">パスワード:</td>
<td><input id="apassword2" type="password" name="password2" autocomplete="off" maxlength="256" onkeydown="haltReturn(event)" onchange="validateCreate(4)" onkeyup="validateCreate(4,event)"></td>
</tr>
<tr id="createPanelHint" style="display:none">
<td align="right">ヒントを渡す:</td>
<td><input id="apasswordhint" type="text" name="apasswordhint" autocomplete="off" maxlength="256" onkeydown="haltReturn(event)" onchange="validateCreate(5)" onkeyup="validateCreate(5,event)"></td>
</tr>
<tr id="newAccountPass" title="アカウント作成トークンを入力してください">
<td align="right">作成トークン:</td>
<td><input id="anewaccountpass" type="password" name="anewaccountpass" autocomplete="off" maxlength="256" onkeydown="haltReturn(event)" onchange="validateCreate(6)" onkeyup="validateCreate(6,event)"></td>
</tr>
<tr>
<td colspan="2">
<div style="float:right"><input id="createButton" type="submit" value="アカウントを作成する" disabled="disabled"></div>
<div id="passWarning" style="padding-top:6px"></div>
</td>
</tr>
</tbody></table>
<hr><a onclick="xgo(1)" style="cursor:pointer">ログインに戻る</a>
<input id="createformargs" name="urlargs" type="hidden" value="">
</form>
</div>
</div>
<div id="resetpanel" style="background-color:#979797;border-radius:16px;width:260px;padding:16px;text-align:center;display:none;clear:both">
<form method="post">
<input type="hidden" name="action" value="resetaccount">
<div id="message3"></div>
<div>
<b>アカウントのリセット</b>
</div>
<table>
<tbody><tr>
<td align="right" width="100">Eメール</td>
<td><input id="remail" type="text" name="email" maxlength="256" onchange="validateReset()" onkeyup="validateReset(event)"></td>
</tr>
<tr>
<td colspan="2">
<div style="float:right"><input id="eresetButton" type="submit" value="アカウントをリセット" disabled="disabled"></div>
<div id="passWarning" style="padding-top:6px"></div>
</td>
</tr>
</tbody></table>
<hr><a onclick="xgo(1)" style="cursor:pointer">ログインに戻る</a>
<input id="resetformargs" name="urlargs" type="hidden" value="">
</form>
</div>
<div id="tokenpanel" style="background-color:#979797;border-radius:16px;width:260px;padding:16px;text-align:center;display:none;clear:both">
<form method="post" autocomplete="off">
<input type="hidden" name="action" value="tokenlogin">
<input type="hidden" name="hwstate" value="{{{hwstate}}}">
<div id="message4"></div>
<table>
<tbody><tr>
<td align="right" width="100">ログイントークン:</td>
<td>
<input id="tokenInput" type="text" name="token" maxlength="50" onchange="checkToken(event)" onkeyup="checkToken(event)" onkeydown="checkToken(event)" onfocus="checkTokenTimer(1)" onblur="checkTokenTimer(0)">
<input id="hwtokenInput" type="text" name="hwtoken" style="display:none">
</td>
</tr>
<tr>
<td colspan="2" style="align-content:center">
<label><input id="tokenInputRemember" name="remembertoken" type="checkbox">このデバイスを30日間記憶します。</label>
</td>
</tr>
<tr>
<td colspan="2">
<div style="float:right"><input id="tokenOkButton" type="submit" value="ログイン" disabled="disabled"></div>
<div style="float:right"><input style="display:none;float:right" id="securityKeyButton" type="button" value="セキュリティキーを使用" onclick="useSecurityKey()"></div>
</td>
</tr>
</tbody></table>
<hr><a onclick="xgo(1)" style="cursor:pointer">ログインに戻る</a>
<input id="tokenformargs" name="urlargs" type="hidden" value="">
</form>
</div>
<div id="resettokenpanel" style="background-color:#979797;border-radius:16px;width:260px;padding:16px;text-align:center;display:none;clear:both">
<form method="post" autocomplete="off">
<input type="hidden" name="action" value="resetaccount">
<div id="message5"></div>
<table>
<tbody><tr>
<td align="right" width="100">ログイントークン:</td>
<td>
<input id="resetTokenInput" type="text" name="token" maxlength="50" onchange="resetCheckToken(event)" onpaste="resetCheckToken(event)" onkeyup="resetCheckToken(event)" onkeydown="resetCheckToken(event)">
<input id="resetHwtokenInput" type="text" name="hwtoken" style="display:none">
</td>
</tr>
<tr>
<td colspan="2">
<div style="float:right"><input id="resetTokenOkButton" type="submit" value="ログイン" disabled="disabled"></div>
</td>
</tr>
</tbody></table>
<hr><a onclick="xgo(1)" style="cursor:pointer">ログインに戻る</a>
<input id="resettokenformargs" name="urlargs" type="hidden" value="">
</form>
</div>
<div id="resetpasswordpanel" style="position:relative;background-color:#979797;border-radius:16px;width:300px;padding:16px;text-align:center;display:none">
<form method="post">
<input type="hidden" name="action" value="resetpassword">
<div id="message6"></div>
<div id="rpasswordPolicyCallout" style="left:-10px;width:100px;display:none;position:absolute;background-color:#FFC;border-radius:5px;padding:5px;box-shadow:0px 0px 15px #666;font-size:10px"></div>
<table>
<tbody><tr>
<td id="rnuPass1" width="100" align="right">パスワード:</td>
<td><input id="rapassword1" type="password" name="rpassword1" autocomplete="off" maxlength="256" onkeydown="haltReturn(event)" onchange="validatePassReset(3,event)" onkeyup="validatePassReset(3,event)"></td>
</tr>
<tr>
<td id="rnuPass2" align="right">パスワード:</td>
<td><input id="rapassword2" type="password" name="rpassword2" autocomplete="off" maxlength="256" onkeydown="haltReturn(event)" onchange="validatePassReset(4,event)" onkeyup="validatePassReset(4,event)"></td>
</tr>
<tr id="resetpasswordpanelHint" style="display:none">
<td id="rnuHint" align="right">パスワードのヒント:</td>
<td><input id="rapasswordhint" type="text" name="rpasswordhint" autocomplete="off" maxlength="256" onkeydown="haltReturn(event)" onchange="validatePassReset(5,event)" onkeyup="validatePassReset(5,event)"></td>
</tr>
<tr>
<td colspan="2">
<div style="float:right"><input id="resetPassButton" type="submit" value="パスワードを再設定する" disabled="disabled"></div>
<div id="rpassWarning" style="padding-top:6px"></div>
</td>
</tr>
</tbody></table>
<hr><a onclick="xgo(1)" style="cursor:pointer">ログインに戻る</a>
<input id="resetpasswordformargs" name="urlargs" type="hidden" value="">
</form>
</div>
</td>
</tr>
</tbody></table>
</div>
</div>
<div id="footer" style="height:32px;width:100%;text-align:center;background-color:#113962;position:absolute;bottom:0px">
<table cellpadding="0" cellspacing="6" style="width:100%">
<tbody><tr>
<td style="text-align:left;color:white">{{{footer}}}</td>
<td style="text-align:right">{{{rootCertLink}}}&nbsp;<a href="terms">利用規約とプライバシー</a></td>
</tr>
</tbody></table>
</div>
</div>
<div id="dialog" style="z-index:1000;background-color:#EEE;box-shadow:0px 0px 15px #666;font-family:Arial,Helvetica,sans-serif;border-radius:5px;position:fixed;top:180px;width:400px;display:none">
<div style="width:100%;background-color:#003366;color:#FFF;border-radius:5px 5px 0 0">
<div id="id_dialogclose" style="float:right;padding:5px;cursor:pointer" onclick="setDialogMode()"><b>バツ</b></div>
<div id="id_dialogtitle" style="padding:5px"></div>
<div style="width:100%;margin:6px"></div>
</div>
<div style="margin-right:16px;margin-left:8px">
<div id="dialog1" style="margin:auto;text-align:center;margin:3px">
<div id="id_dialogMessage" style="padding:10px"></div>
</div>
<div id="dialog2" style="margin:auto;margin:3px">
<div id="id_dialogOptions"></div>
</div>
</div>
<div id="idx_dlgButtonBar" style="padding:10px;margin-bottom:20px">
<input id="idx_dlgCancelButton" type="button" value="キャンセル" style="float:right;width:80px;margin-left:5px" onclick="dialogclose(0)">
<input id="idx_dlgOkButton" type="button" value="OK" style="float:right;width:80px" onclick="dialogclose(1)">
</div>
</div>
<script>
'use strict';
var loginMode = '{{{loginmode}}}';
var newAccount = '{{{newAccount}}}';
var passhint = '{{{passhint}}}';
var newAccountPass = parseInt('{{{newAccountPass}}}');
var emailCheck = ('{{{emailcheck}}}' == 'true');
var features = parseInt('{{{features}}}');
var passRequirements = '{{{passRequirements}}}';
if (passRequirements != '') { passRequirements = JSON.parse(decodeURIComponent(passRequirements)); } else { passRequirements = {}; }
var passRequirementsEx = ((passRequirements.min != null) || (passRequirements.max != null) || (passRequirements.upper != null) || (passRequirements.lower != null) || (passRequirements.numeric != null) || (passRequirements.nonalpha != null));
var hardwareKeyChallenge = decodeURIComponent('{{{hkey}}}');
var publicKeyCredentialRequestOptions = null;
var currentpanel = 0;
// Display the right server message
var messageid = parseInt('{{{messageid}}}');
var okmessages = ['', "お待ちください、送信されたメールをリセットします。"];
var failmessages = ["アカウントを作成できません。", "アカウントの上限に達しました。", "このメールアドレスを持つ既存のアカウント。", "アカウント作成トークンが無効です。", "ユーザー名は既に存在します。", "パスワードが拒否されました。別のパスワードを使用してください。", "無効なメール。", "アカウントが見つかりませんでした。", "トークンが無効です。もう一度お試しください。", "メールを送信できません。", "アカウントがロックされました。", "アクセスが拒否されました。", "ログインに失敗しました。ユーザー名とパスワードを確認してください。", "パスワードの変更が要求されました。", "IPアドレスがブロックされています。しばらくしてからもう一度お試しください。"];
if (messageid > 0) {
var msg = '';
if ((messageid < 100) && (messageid < okmessages.length)) { msg = okmessages[messageid]; }
else if ((messageid >= 100) && ((messageid - 100) < failmessages.length)) { msg = failmessages[messageid - 100]; }
if (msg != '') {
if (messageid >= 100) { msg = ('<span class="msg error"><b style=color:#8C001A>' + msg + '<b></span><br /><br />'); } else { msg = ('<span class="msg success"><b>' + msg + '</b></span><br /><br />'); }
for (var i = 1; i < 7; i++) { QH('message' + i, msg); }
}
}
// If URL arguments are provided, add them to form posts
if (window.location.href.indexOf('?') > 0) {
var urlargs = window.location.href.substring(window.location.href.indexOf('?'));
Q('loginformargs').value = urlargs;
Q('createformargs').value = urlargs;
Q('resetformargs').value = urlargs;
Q('tokenformargs').value = urlargs;
Q('resettokenformargs').value = urlargs;
Q('resetpasswordformargs').value = urlargs;
}
function startup() {
if ((features & 32) == 0) {
// Guard against other site's top frames (web bugs).
var loc = null;
try { loc = top.location.toString().toLowerCase(); } catch (e) { }
if (top != self && (loc == null || top.active == false)) { top.location = self.location; return; }
}
if (features & 0x200000) { // Email is username
QH('loginusername', "Eメール");
QH('resetAccountSpan', "パスワードをお忘れですか?");
QV('nuUserRow', false);
}
QV('createPanelHint', passRequirements.hint === true);
QV('resetpasswordpanelHint', passRequirements.hint === true);
window.onresize = center;
center();
validateLogin();
validateCreate();
if (loginMode.length != 0) { go(parseInt(loginMode)); } else { go(1); }
QV('newAccountDiv', (newAccount === '1') || (newAccount === 'true')); // If new accounts are not allowed, don't display the new account link.
if ((passRequirements.hint === true) && (passhint != null) && (passhint.length > 0)) { QV('showPassHintLink', true); }
QV('newAccountPass', (newAccountPass == 1));
QV('resetAccountDiv', (emailCheck == true));
QV('hrAccountDiv', (emailCheck == true) || (newAccountPass == 1));
if (loginMode == '4') {
try { if (hardwareKeyChallenge.length > 0) { hardwareKeyChallenge = JSON.parse(hardwareKeyChallenge); } else { hardwareKeyChallenge = null; } } catch (ex) { hardwareKeyChallenge = null }
QV('securityKeyButton', (hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn'));
}
if (loginMode == '5') {
try { if (hardwareKeyChallenge.length > 0) { hardwareKeyChallenge = JSON.parse(hardwareKeyChallenge); } else { hardwareKeyChallenge = null; } } catch (ex) { hardwareKeyChallenge = null }
if ((hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn')) {
if (typeof hardwareKeyChallenge.challenge == 'string') { hardwareKeyChallenge.challenge = Uint8Array.from(atob(hardwareKeyChallenge.challenge), function (c) { return c.charCodeAt(0) }).buffer; }
publicKeyCredentialRequestOptions = { challenge: hardwareKeyChallenge.challenge, allowCredentials: [], timeout: hardwareKeyChallenge.timeout }
for (var i = 0; i < hardwareKeyChallenge.keyIds.length; i++) {
publicKeyCredentialRequestOptions.allowCredentials.push(
{ id: Uint8Array.from(atob(hardwareKeyChallenge.keyIds[i]), function (c) { return c.charCodeAt(0) }), type: 'public-key', transports: ['usb', 'ble', 'nfc'], }
);
}
// New WebAuthn hardware keys
navigator.credentials.get({ publicKey: publicKeyCredentialRequestOptions }).then(
function (rawAssertion) {
var assertion = {
id: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.rawId))),
clientDataJSON: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.clientDataJSON))),
userHandle: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.userHandle))),
signature: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.signature))),
authenticatorData: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.authenticatorData))),
};
Q('resetHwtokenInput').value = JSON.stringify(assertion);
QE('resetTokenOkButton', true);
Q('resetTokenOkButton').click();
},
function (error) { console.log('credentials-get error', error); }
);
}
}
}
// Use a hardware security key
function useSecurityKey() {
if ((hardwareKeyChallenge != null) && (hardwareKeyChallenge.type == 'webAuthn')) {
if (typeof hardwareKeyChallenge.challenge == 'string') { hardwareKeyChallenge.challenge = Uint8Array.from(atob(hardwareKeyChallenge.challenge), function (c) { return c.charCodeAt(0) }).buffer; }
publicKeyCredentialRequestOptions = { challenge: hardwareKeyChallenge.challenge, allowCredentials: [], timeout: hardwareKeyChallenge.timeout }
for (var i = 0; i < hardwareKeyChallenge.keyIds.length; i++) {
publicKeyCredentialRequestOptions.allowCredentials.push(
{ id: Uint8Array.from(atob(hardwareKeyChallenge.keyIds[i]), function (c) { return c.charCodeAt(0) }), type: 'public-key', transports: ['usb', 'ble', 'nfc'], }
);
}
// New WebAuthn hardware keys
navigator.credentials.get({ publicKey: publicKeyCredentialRequestOptions }).then(
function (rawAssertion) {
var assertion = {
id: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.rawId))),
clientDataJSON: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.clientDataJSON))),
userHandle: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.userHandle))),
signature: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.signature))),
authenticatorData: btoa(String.fromCharCode.apply(null, new Uint8Array(rawAssertion.response.authenticatorData))),
};
Q('hwtokenInput').value = JSON.stringify(assertion);
QE('tokenOkButton', true);
Q('tokenOkButton').click();
},
function (error) { console.log('credentials-get error', error); }
);
}
}
function showPassHint() {
if (passRequirements.hint === true) { messagebox("パスワードのヒント", passhint); }
}
function xgo(x) {
QV('message1', false);
QV('message2', false);
QV('message3', false);
QV('message4', false);
QV('message5', false);
QV('message6', false);
go(x);
}
function go(x) {
currentpanel = x;
setDialogMode(0);
QV('showPassHintLink', false);
QV('loginpanel', x == 1);
QV('createpanel', x == 2);
QV('resetpanel', x == 3);
QV('tokenpanel', x == 4);
QV('resettokenpanel', x == 5);
QV('resetpasswordpanel', x == 6);
if (x == 1) { Q('username').focus(); }
if (x == 2) { if (features & 0x200000) { Q('aemail').focus(); } else { Q('ausername').focus(); } } // Email is username
if (x == 3) { Q('remail').focus(); }
if (x == 4) { Q('tokenInput').focus(); }
if (x == 5) { Q('resetTokenInput').focus(); }
if (x == 6) { Q('rapassword1').focus(); }
}
function validateLogin(box, e) {
var ok = ((Q('username').value.length > 0) && (Q('username').value.indexOf(' ') == -1) && (Q('password').value.length > 0));
QE('loginButton', ok);
setDialogMode(0);
if ((e != null) && (e.keyCode == 13)) { if (box == 1) { Q('password').focus(); } else if (box == 2) { Q('loginButton').click(); } }
if (e != null) { haltEvent(e); }
}
function validateCreate(box,e) {
setDialogMode(0);
var ok = false;
if (features & 0x200000) { ok = true; } else { ok = (Q('ausername').value.length > 0) && (Q('ausername').value.indexOf(' ') == -1) && (Q('ausername').value.indexOf('"') == -1) && (Q('ausername').value.indexOf(',') == -1); }
ok &= ((validateEmail(Q('aemail').value) == true) && (Q('apassword1').value.length > 0) && (Q('apassword2').value == Q('apassword1').value));
if ((newAccountPass == 1) && (Q('anewaccountpass').value.length == 0)) { ok = false; }
if (Q('apassword1').value == '') {
QH('passWarning', '');
QV('passwordPolicyCallout', false);
} else {
if (!passRequirementsEx) {
// No password requirements, display password strength
var passStrength = checkPasswordStrength(Q('apassword1').value);
if (passStrength >= 80) { QH('passWarning', '<span style=color:green><b>' + "強力なパスワード" + '</b><span>'); }
else if (passStrength >= 60) { QH('passWarning', '<span style=color:blue><b>' + "良いパスワード" + '</b><span>'); }
else { QH('passWarning', '<span style=color:red><b>' + "弱いパスワード" + '</b><span>'); }
} else {
// Password requirements provided, use that
var passReq = checkPasswordRequirements(Q('apassword1').value, passRequirements);
if (passReq == false) {
ok = false;
//QS('nuPass1').color = '#7b241c';
//QS('nuPass2').color = '#7b241c';
QH('passWarning', '<span style=color:red><b>' + "パスワードポリシー" + '</b><span>'); // TODO: Display problem hint
QV('passwordPolicyCallout', true);
QH('passwordPolicyCallout', passwordPolicyText(Q('apassword1').value));
} else {
QH('passWarning', '');
QV('passwordPolicyCallout', false);
}
}
}
QE('createButton', ok);
if ((e != null) && (e.keyCode == 13)) {
if (box == 1) { Q('aemail').focus(); }
if (box == 2) { Q('apassword1').focus(); }
if (box == 3) { Q('apassword2').focus(); }
if (box == 4) { Q('apasswordhint').focus(); }
if (box == 5) { if (newAccountPass == 1) { Q('anewaccountpass').focus(); } else { Q('createButton').click(); } }
if (box == 6) { Q('createButton').click(); }
}
if (e != null) { haltEvent(e); }
}
function validatePassReset(box, e) {
setDialogMode(0);
var pass1ok = (Q('rapassword1').value.length > 0);
var pass2ok = (Q('rapassword2').value.length > 0) && (Q('rapassword2').value == Q('rapassword1').value);
var ok = (pass1ok && pass2ok);
// Color the fields
QS('rnuPass1').color = pass1ok ? 'black' : '#7b241c';
QS('rnuPass2').color = pass2ok ? 'black' : '#7b241c';
if (Q('rapassword1').value == '') {
QH('rpassWarning', '');
QV('rpasswordPolicyCallout', false);
} else {
if (!passRequirementsEx) {
// No password requirements, display password strength
var passStrength = checkPasswordStrength(Q('rapassword1').value);
if (passStrength >= 80) { QH('rpassWarning', '<span style=color:green><b>' + "強力なパスワード" + '</b><span>'); }
else if (passStrength >= 60) { QH('rpassWarning', '<span style=color:blue><b>' + "良いパスワード" + '</b><span>'); }
else { QH('rpassWarning', '<span style=color:red><b>' + "弱いパスワード" + '</b><span>'); }
} else {
// Password requirements provided, use that
var passReq = checkPasswordRequirements(Q('rapassword1').value, passRequirements);
if (passReq == false) {
ok = false;
QS('rnuPass1').color = '#7b241c';
QS('rnuPass2').color = '#7b241c';
QH('rpassWarning', '<div style=color:red;cursor:pointer onclick=showPasswordPolicy()><b>' + "パスワードポリシー" + '</b><div>'); // This is also a link to the password policy
QV('rpasswordPolicyCallout', true);
QH('rpasswordPolicyCallout', passwordPolicyText(Q('rapassword1').value));
} else {
QH('rpassWarning', '');
QV('rpasswordPolicyCallout', false);
}
}
}
if ((e != null) && (e.keyCode == 13)) {
if (box == 2) { Q('rapassword1').focus(); }
if (box == 3) { Q('rapassword2').focus(); }
if (box == 4) { Q('rapasswordhint').focus(); }
if (box == 6) { Q('resetPassButton').click(); }
}
if (e != null) { haltEvent(e); }
QE('resetPassButton', ok);
}
function validateReset(e) {
setDialogMode(0);
var x = validateEmail(Q('remail').value);
QE('eresetButton', x);
if ((e != null) && (e.keyCode == 13) && (x == true)) { Q('eresetButton').click(); }
if (e != null) { haltEvent(e); }
}
function passwordPolicyText(pass) {
var policy = '<div style=text-align:left>';
var counts = strCount(pass);
if (passRequirements.min && ((pass == null) || (pass.length < passRequirements.min))) { policy += format("最小長{0}", passRequirements.min) + '<br />'; }
if (passRequirements.max && ((pass == null) || (pass.length > passRequirements.max))) { policy += format("{0}の最大長", passRequirements.max) + '<br />'; }
if (passRequirements.upper && ((pass == null) || (counts.upper < passRequirements.upper))) { policy += format("{0}大文字", passRequirements.upper) + '<br />'; }
if (passRequirements.lower && ((pass == null) || (counts.lower < passRequirements.lower))) { policy += format("{0}小文字", passRequirements.lower) + '<br />'; }
if (passRequirements.numeric && ((pass == null) || (counts.numeric < passRequirements.numeric))) { policy += format("{0}数値", passRequirements.numeric) + '<br />'; }
if (passRequirements.nonalpha && ((pass == null) || (counts.nonalpha < passRequirements.nonalpha))) { policy += format("{0}英数字以外", passRequirements.nonalpha) + '<br />'; }
policy += '</div>';
return policy;
}
// Return a password strength score
function checkPasswordStrength(password) {
var r = 0, letters = {}, varCount = 0, variations = { digits: /\d/.test(password), lower: /[a-z]/.test(password), upper: /[A-Z]/.test(password), nonWords: /\W/.test(password) }
if (!password) return 0;
for (var i = 0; i< password.length; i++) { letters[password[i]] = (letters[password[i]] || 0) + 1; r += 5.0 / letters[password[i]]; }
for (var c in variations) { varCount += (variations[c] == true) ? 1 : 0; }
return parseInt(r + (varCount - 1) * 10);
}
// Check password requirements
function checkPasswordRequirements(password, requirements) {
if ((requirements == null) || (requirements == '') || (typeof requirements != 'object')) return true;
if (requirements.min) { if (password.length < requirements.min) return false; }
if (requirements.max) { if (password.length > requirements.max) return false; }
var counts = strCount(password);
if (requirements.numeric && (counts.numeric < requirements.numeric)) return false;
if (requirements.lower && (counts.lower < requirements.lower)) return false;
if (requirements.upper && (counts.upper < requirements.upper)) return false;
if (requirements.nonalpha && (counts.nonalpha < requirements.nonalpha)) return false;
return true;
}
function strCount(password) {
var counts = { numeric: 0, lower: 0, upper: 0, nonalpha: 0 };
if (typeof password != 'string') return counts;
for (var i = 0; i < password.length; i++) {
if (/\d/.test(password[i])) { counts.numeric++; }
if (/[a-z]/.test(password[i])) { counts.lower++; }
if (/[A-Z]/.test(password[i])) { counts.upper++; }
if (/\W/.test(password[i])) { counts.nonalpha++; }
}
return counts;
}
var xcheckTokenTimer = null;
function checkTokenTimer(enter) {
if ((enter == 0) && (xcheckTokenTimer != null)) { clearInterval(xcheckTokenTimer); xcheckTokenTimer = null; }
if ((enter == 1) && (xcheckTokenTimer == null)) { xcheckTokenTimer = setInterval(checkToken, 200); }
}
function checkToken() {
var t1 = Q('tokenInput').value, t2 = t1.split(' ').join('');
if (t1 != t2) { Q('tokenInput').value = t2; }
QE('tokenOkButton', (Q('tokenInput').value.length == 6) || (Q('tokenInput').value.length == 8) || (Q('tokenInput').value.length == 44));
}
function resetCheckToken() {
var t1 = Q('resetTokenInput').value, t2 = t1.split(' ').join('');
if (t1 != t2) { Q('resetTokenInput').value = t2; }
QE('resetTokenOkButton', (Q('resetTokenInput').value.length == 6) || (Q('resetTokenInput').value.length == 8) || (Q('resetTokenInput').value.length == 44));
}
//
// POPUP DIALOG
//
// undefined = Hidden, 1 = Generic Message
var xxdialogMode;
var xxdialogFunc;
var xxdialogButtons;
var xxdialogTag;
var xxcurrentView = 0;
// Display a dialog box
// Parameters: Dialog Mode (0 = none), Dialog Title, Buttons (1 = OK, 2 = Cancel, 3 = OK & Cancel), Call back function(0 = Cancel, 1 = OK), Dialog Content (Mode 2 only)
function setDialogMode(x, y, b, f, c, tag) {
xxdialogMode = x;
xxdialogFunc = f;
xxdialogButtons = b;
xxdialogTag = tag;
QE('idx_dlgOkButton', true);
QV('idx_dlgOkButton', b & 1);
QV('idx_dlgCancelButton', b & 2);
QV('id_dialogclose', (b & 2) || (b & 8));
QV('idx_dlgButtonBar', b & 7);
if (y) QH('id_dialogtitle', y);
for (var i = 1; i < 24; i++) { QV('dialog' + i, i == x); } // Edit this line when more dialogs are added
QV('dialog', x);
if (c) { if (x == 2) { QH('id_dialogOptions', c); } else { QH('id_dialogMessage', c); } }
}
function dialogclose(x) {
var f = xxdialogFunc;
var b = xxdialogButtons;
var t = xxdialogTag;
setDialogMode();
if (((b & 8) || x) && f) f(x, t);
}
function center() { QS('dialog').left = ((((getDocWidth() - 400) / 2)) + 'px'); }
function messagebox(t, m) { QH('id_dialogMessage', m); setDialogMode(1, t, 1); }
function statusbox(t, m) { QH('id_dialogMessage', m); setDialogMode(1, t); }
function getDocWidth() { if (window.innerWidth) return window.innerWidth; if (document.documentElement && document.documentElement.clientWidth && document.documentElement.clientWidth != 0) return document.documentElement.clientWidth; return document.getElementsByTagName('body')[0].clientWidth; }
function haltEvent(e) { if (e.preventDefault) e.preventDefault(); if (e.stopPropagation) e.stopPropagation(); return false; }
function haltReturn(e) { if (e.keyCode == 13) { haltEvent(e); } }
function validateEmail(v) { var emailReg = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; return emailReg.test(v); } // New version
function format(format) { var args = Array.prototype.slice.call(arguments, 1); return format.replace(/{(\d+)}/g, function (match, number) { return typeof args[number] != 'undefined' ? args[number] : match; }); };
</script>
</body></html>