feat(apk): choisir d'ouvrir avec le verrouillage d'ecran, un code ou le mot de passe du coffre
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+62
-40
@@ -395,6 +395,9 @@
|
||||
|
||||
<div class="stack">
|
||||
<button class="btn wide main" id="btnOpen">➜ Open vault</button>
|
||||
<!-- LA SORTIE DE SECOURS DU VERROUILLAGE D'ECRAN : empreinte refusee,
|
||||
schema oublie - le mot de passe du coffre ouvre toujours. -->
|
||||
<button class="btn wide" id="btnUsePwd" hidden>Use the vault password</button>
|
||||
<button class="btn wide" id="btnSync">↻ Sync</button>
|
||||
<!-- UN SEUL BOUTON, ET IL NE MENT PAS SUR SA DESTINATION.
|
||||
Il y en avait deux, "Settings" et "Log", et le second a fini par
|
||||
@@ -582,22 +585,21 @@
|
||||
clair en main : les deux ne pourraient que refuser, et proposer une
|
||||
action qui refuse toujours vaut moins que ne rien proposer. -->
|
||||
<div id="secCode" hidden>
|
||||
<h2>Unlock code</h2>
|
||||
<h2>Unlock with</h2>
|
||||
<!-- TROIS FACONS D'OUVRIR, UNE SEULE COPIE LOCALE. Le coffre lui-meme n'est
|
||||
jamais touche : seul le scellement de la copie rapide change. Le champ
|
||||
sert a tout - nouveau code, mot de passe du coffre, ou code courant
|
||||
pour revenir au verrouillage d'ecran (retirer une protection demande
|
||||
de la connaitre). -->
|
||||
<div class="in-wrap">
|
||||
<input class="field-in" id="sPinNew" placeholder="new unlock code or password"
|
||||
<input class="field-in" id="sPinNew" placeholder="code or password"
|
||||
type="password" autocomplete="off">
|
||||
<div class="in-x" data-clear="sPinNew">×</div>
|
||||
</div>
|
||||
<button class="btn wide" id="sPinSet">Set this code</button>
|
||||
<!-- Le champ ci-dessus sert aux deux : le NOUVEAU code pour "Set", le code
|
||||
COURANT pour "Remove". Retirer une protection demande de la connaitre,
|
||||
sinon quiconque trouve le telephone ouvert la leve en deux appuis. -->
|
||||
<button class="btn wide danger" id="sPinClear">Remove the unlock code</button>
|
||||
<div class="note">To remove the code, type the current one above first.
|
||||
The code seals the copy kept on this device. It can be
|
||||
digits or a full password - a longer one is harder to guess, and it is
|
||||
asked for only when the vault opens. Removing it leaves the vault
|
||||
readable by anyone holding the phone unlocked.</div>
|
||||
<button class="btn wide" id="sModeDevice">Screen lock (fingerprint, pattern...)</button>
|
||||
<button class="btn wide" id="sModeCode">App code (type it above)</button>
|
||||
<button class="btn wide" id="sModePwd">Vault password (type it above)</button>
|
||||
<div class="note" id="sModeNote"></div>
|
||||
</div>
|
||||
|
||||
<h2>Diagnostics</h2>
|
||||
@@ -1648,14 +1650,49 @@ document.getElementById('histBody').addEventListener('click', function (ev) {
|
||||
document.getElementById('sLog').addEventListener('click', function () {
|
||||
showLog(document.getElementById('log').hidden);
|
||||
});
|
||||
document.getElementById('sPinSet').addEventListener('click', function () {
|
||||
var v = document.getElementById('sPinNew').value;
|
||||
if (!v) { toast('Type a code first'); return; }
|
||||
// DEMANDE EXPLICITE, EFFET IMMEDIAT. Le code ne se depose plus dans un champ
|
||||
// que l'ouverture suivante appliquerait : Delphi refuse si le coffre n'est
|
||||
// pas ouvert, ce qui prouve que le code courant est connu.
|
||||
// FACON D'OUVRIR. Delphi dit laquelle est en place (PM.setUnlockMode) ; chaque
|
||||
// bouton envoie la commande qui existe deja pour la poser. Revenir au
|
||||
// verrouillage d'ecran, c'est retirer le code : il faut donc le code courant.
|
||||
var unlockMode = 'none', canDeviceLock = false, hasContainer = false;
|
||||
function syncUnlockUi() {
|
||||
['device', 'code', 'password'].forEach(function (m) {
|
||||
var id = { device: 'sModeDevice', code: 'sModeCode', password: 'sModePwd' }[m];
|
||||
document.getElementById(id).classList.toggle('main', unlockMode === m);
|
||||
});
|
||||
document.getElementById('sModeDevice').disabled = !canDeviceLock;
|
||||
document.getElementById('sModeNote').textContent =
|
||||
{ device: 'Now: screen lock. Changing the screen lock or adding a fingerprint never deletes the vault.',
|
||||
code: 'Now: app code. To go back to the screen lock, type the current code above.',
|
||||
password: 'Now: vault password. To go back to the screen lock, type it above.',
|
||||
none: 'Now: no protection - anyone holding the phone unlocked can open the vault.' }[unlockMode]
|
||||
+ (canDeviceLock ? '' : ' This phone has no screen lock.');
|
||||
document.getElementById('btnUsePwd').hidden =
|
||||
!(authMode === 'open' && unlockMode === 'device' && hasContainer);
|
||||
}
|
||||
function modeField() {
|
||||
var el = document.getElementById('sPinNew'), v = el.value;
|
||||
el.value = '';
|
||||
return v;
|
||||
}
|
||||
document.getElementById('sModeCode').addEventListener('click', function () {
|
||||
var v = modeField();
|
||||
if (!v) { toast('Type the new code above first'); return; }
|
||||
send('pinset?c=' + encodeURIComponent(v));
|
||||
document.getElementById('sPinNew').value = '';
|
||||
});
|
||||
document.getElementById('sModePwd').addEventListener('click', function () {
|
||||
var v = modeField();
|
||||
if (!v) { toast('Type the vault password above first'); return; }
|
||||
send('pinset?pw=1&c=' + encodeURIComponent(v));
|
||||
});
|
||||
document.getElementById('sModeDevice').addEventListener('click', function () {
|
||||
if (unlockMode === 'device') { toast('Already using the screen lock'); return; }
|
||||
var v = modeField();
|
||||
if (!v && unlockMode !== 'none') { toast('Type the current code or password above first'); return; }
|
||||
send('pinclear?c=' + encodeURIComponent(v));
|
||||
});
|
||||
document.getElementById('btnUsePwd').addEventListener('click', function () {
|
||||
PM.setAuthMode('login');
|
||||
document.getElementById('pass').focus();
|
||||
});
|
||||
document.getElementById('sWipe').addEventListener('click', function (ev) {
|
||||
// DEUX APPUIS, comme pour retirer le code : un effacement sans retour ne se
|
||||
@@ -1675,27 +1712,6 @@ document.getElementById('sWipe').addEventListener('click', function (ev) {
|
||||
send('wipelocal');
|
||||
closeSettings();
|
||||
});
|
||||
document.getElementById('sPinClear').addEventListener('click', function (ev) {
|
||||
var b = ev.currentTarget;
|
||||
if (b.getAttribute('data-armed') === null) {
|
||||
b.setAttribute('data-armed', '1');
|
||||
b.textContent = 'Really remove - tap again';
|
||||
setTimeout(function () {
|
||||
b.removeAttribute('data-armed');
|
||||
b.textContent = 'Remove the unlock code';
|
||||
}, 4000);
|
||||
return;
|
||||
}
|
||||
b.removeAttribute('data-armed');
|
||||
b.textContent = 'Remove the unlock code';
|
||||
// LE CODE COURANT VOYAGE AVEC LA DEMANDE. Le coffre ouvert ne prouve rien :
|
||||
// il peut l'etre depuis une heure et rester a l'ecran. Delphi compare a ce
|
||||
// sous quoi le cache est reellement scelle, et refuse sinon.
|
||||
send('pinclear?c=' + encodeURIComponent(
|
||||
document.getElementById('sPinNew').value));
|
||||
document.getElementById('sPinNew').value = '';
|
||||
});
|
||||
|
||||
function goList() {
|
||||
closeMenu();
|
||||
document.body.classList.remove('on-detail');
|
||||
@@ -1826,6 +1842,12 @@ var PM = {
|
||||
syncPinbox();
|
||||
document.getElementById('btnAuth').textContent =
|
||||
(mode === 'register') ? 'Create vault' : 'Sign in';
|
||||
syncUnlockUi();
|
||||
},
|
||||
|
||||
setUnlockMode: function (mode, canDevice, container) {
|
||||
unlockMode = mode; canDeviceLock = canDevice; hasContainer = container;
|
||||
syncUnlockUi();
|
||||
},
|
||||
|
||||
setPinNeeded: function (on) {
|
||||
|
||||
+44
-3
@@ -337,6 +337,7 @@ type
|
||||
/// le code courant deja connu - c'est ce qui empeche un tiers d'en poser un
|
||||
/// que le proprietaire ne connaitrait pas.
|
||||
procedure SetUnlockCode(const ANew: string);
|
||||
procedure PushUnlockMode;
|
||||
/// Va chercher l'icone du site de l'entree ouverte, ou l'efface.
|
||||
procedure SetEntryIcon(AFetch: Boolean);
|
||||
/// Le depot a bouge, ou ne l'a plus : LE DRAPEAU ET SON TEMOIN ENSEMBLE.
|
||||
@@ -534,6 +535,7 @@ begin
|
||||
WebCall('PM.setAuthMode("login")')
|
||||
else
|
||||
WebCall('PM.setAuthMode("register")');
|
||||
PushUnlockMode;
|
||||
|
||||
LCanOpen := HasVault and not FVaultUnreadable;
|
||||
if LCanOpen then
|
||||
@@ -1701,7 +1703,10 @@ begin
|
||||
Exit // Touch a deja eu lieu plus haut
|
||||
|
||||
else if LAction = 'state' then
|
||||
FWebView := Param('view')
|
||||
begin
|
||||
FWebView := Param('view');
|
||||
if FWebView = 'settings' then PushUnlockMode;
|
||||
end
|
||||
|
||||
else if LAction = 'open' then
|
||||
OpenEntry(StrToIntDef(Param('i'), -1))
|
||||
@@ -1789,7 +1794,16 @@ begin
|
||||
{$ENDIF}
|
||||
|
||||
else if LAction = 'pinset' then
|
||||
SetUnlockCode(TNetEncoding.URL.Decode(Param('c')))
|
||||
begin
|
||||
// MODE MOT DE PASSE = le code EST le mot de passe du coffre. On le
|
||||
// verifie : sinon une faute de frappe scellerait sous un "mot de passe"
|
||||
// que l'utilisateur ne retapera jamais a l'identique.
|
||||
if (Param('pw') = '1') and
|
||||
((FPlain = '') or (TNetEncoding.URL.Decode(Param('c')) <> CachePwd)) then
|
||||
WebCall('PM.toast("Wrong vault password")')
|
||||
else
|
||||
SetUnlockCode(TNetEncoding.URL.Decode(Param('c')));
|
||||
end
|
||||
|
||||
else if LAction = 'pinclear' then
|
||||
ClearUnlockCode(TNetEncoding.URL.Decode(Param('c')))
|
||||
@@ -3070,6 +3084,7 @@ begin
|
||||
Log('Unlock code set');
|
||||
WebCall('PM.toast("Unlock code set")');
|
||||
WebCall('PM.pinChanged()');
|
||||
PushUnlockMode;
|
||||
except
|
||||
on E: Exception do
|
||||
begin
|
||||
@@ -3079,6 +3094,28 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
/// Dit a la page comment le cache est scelle. 'password' = scelle sous un code
|
||||
/// egal au mot de passe du coffre - connu seulement une fois ouvert (FPinSealed).
|
||||
procedure TForm8.PushUnlockMode;
|
||||
var
|
||||
LMode: string;
|
||||
begin
|
||||
if VaultNeedsPin then
|
||||
begin
|
||||
if (FPinSealed <> '') and (FPinSealed = CachePwd) then
|
||||
LMode := 'password'
|
||||
else
|
||||
LMode := 'code';
|
||||
end
|
||||
else if VaultNeedsAuth then
|
||||
LMode := 'device'
|
||||
else
|
||||
LMode := 'none';
|
||||
WebCall(Format('PM.setUnlockMode("%s", %s, %s)',
|
||||
[LMode, LowerCase(BoolToStr(BiometricAvailable, True)),
|
||||
LowerCase(BoolToStr(HasLocalContainer, True))]));
|
||||
end;
|
||||
|
||||
function TForm8.CachePwd: string;
|
||||
begin
|
||||
if HasLocalContainer then Result := FVaultPwd else Result := FSyncPwd;
|
||||
@@ -3117,7 +3154,10 @@ begin
|
||||
Exit;
|
||||
end;
|
||||
try
|
||||
SaveVault(FPlain, FETag, CachePwd, BiometricAvailable, False, '',
|
||||
// Cle NEUVE : le verrouillage d'ecran a pu changer pendant que le code
|
||||
// protegeait, et une ancienne paire invalidee scellerait un fichier
|
||||
// impossible a rouvrir.
|
||||
SaveVault(FPlain, FETag, CachePwd, BiometricAvailable, True, '',
|
||||
FKey, FKeySalt, FKeyIters, True);
|
||||
if VaultNeedsPin then
|
||||
begin
|
||||
@@ -3130,6 +3170,7 @@ begin
|
||||
Log('Unlock code removed');
|
||||
WebCall('PM.toast("Unlock code removed")');
|
||||
WebCall('PM.pinChanged()');
|
||||
PushUnlockMode;
|
||||
ShowUnlock;
|
||||
except
|
||||
on E: Exception do
|
||||
|
||||
Reference in New Issue
Block a user