From 9d25672b9b682c8122a3b5395d5e715014084f16 Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Mon, 23 Jun 2025 21:33:49 -0400 Subject: [PATCH 1/2] feat: Redesign login page * Redesign code related to $loginParms handling in login.inc template * Move mode selector and most other hardcoded parameters from the template to login.php * Add support for extra properties via optional 'extra' parameter * Add support for optional div wrapper via 'div' parameter * Add autocomplete=off for OTP (second factor) input --- login.php | 16 +++- src/Login.php | 1 - templates/login/login.inc | 175 ++++++++++++++++++++++++++++---------- 3 files changed, 146 insertions(+), 46 deletions(-) diff --git a/login.php b/login.php index 794a8816..67de1306 100644 --- a/login.php +++ b/login.php @@ -245,7 +245,21 @@ function _addAnchor($url, $type, $vars, $url_anchor = null) if (!empty($GLOBALS['conf']['user']['select_view'])) { $js_code['HordeLogin.pre_sel'] = $vars->get('horde_select_view', $_COOKIE['default_horde_view'] ?? 'auto'); $loginparams['horde_select_view'] = [ - 'type' => 'horde_select_view', + 'type' => 'select', + 'label' => _("Mode"), + 'value' => [ + 'auto' => [ 'name' => _("Automatic") ], + 'disabled' => null, + 'basic' => [ 'name' => _("Basic") ], + 'dynamic' => [ 'name' => _("Dynamic") ], + 'smartmobile' => [ 'name' => _("Mobile (Smartphone/Tablet)") ], + 'mobile' => [ 'name' => _("Mobile (Minimal)") ], + 'mobile_nojs' => [ 'name' => _("Mobile (No JavaScript)") ], + ], + 'div' => [ + 'id' => 'horde_select_view_div', + 'style' => 'display:none', + ], ]; } diff --git a/src/Login.php b/src/Login.php index 7df660fa..e5f97d56 100644 --- a/src/Login.php +++ b/src/Login.php @@ -40,7 +40,6 @@ public function buildLoginParams(): array $loginparams['horde_secondfactor'] = [ 'label' => _("Second Factor"), 'type' => 'password', - // 'value' => $this->vars->horde_secondfactor, 'extra' => [ 'autocomplete' => 'off' ], ]; } diff --git a/templates/login/login.inc b/templates/login/login.inc index 4fd282c2..1b46a7d2 100644 --- a/templates/login/login.inc +++ b/templates/login/login.inc @@ -12,50 +12,137 @@ - $val): ?> - - - - - -
-
- - - - - -
- - - + $val) { + $type = $val['type'] ?? ''; + $label = $val['label'] ?? ''; + $value = $val['value'] ?? ''; + $extra = $val['extra'] ?? ''; + + switch ($type) { + case 'text': + if (empty($extra)) { + // default + $extra = [ + 'autocapitalize' => 'off', + 'autocorrect' => 'off', + ]; + } + break; + case 'password': + $value = ''; + break; + } + + $div = $val['div'] ?? ''; + if (!empty($div)) { + $parms = [ 'div' ]; + if (!is_array($div)) { + $div = [ $div ]; + } + foreach ($div as $k => $v) { + $addParm($k, $v); + } + $div = $parms; + } + + $parms = []; + + if ($type == 'select') { + $addParm($type); + } else { + $addParm('input'); + $addParm('type' , $type); + } + + if (!empty($extra)) { + if (!is_array($extra)) { + $extra = [ $extra ]; + } + foreach ($extra as $k => $v) { + $addParm($k, $v); + } + } + + $addParm('id', $key); + $addParm('name', $key); + + if (is_string($value)) { + $addParm('value', htmlspecialchars($value));; + } + + if (!empty($div)) { + $addLine('<' . implode(' ', $div) . '>'); + ++$indent; + } + + if ($label != '') { + $addLine('
' . Horde::label($key, $label) . '
'); + } + + $addLine('
'); + ++$indent; + + if ($type == 'select') { + $addLine('<' . implode(' ', $parms) . '>'); + ++$indent; + foreach ($value as $k2 => $v2) { + $parms = []; + $addParm('option');; + if (is_null($v2)) { + $addParm('value', ''); + $addParm('disabled', 'disabled'); + $value = '- - - - - - - - - -'; + } else { + $addParm('value', $k2); + if (!empty($v2['selected'])) { + $addParm('selected', 'selected'); + } + if (!empty($v2['hidden'])) { + $addParm('style', 'display:none'); + } + $value = $v2['name']; + } + $addLine('<' . implode(' ', $parms) . '>' . htmlspecialchars($value) . ''); + } + --$indent; + $addLine(''); + } else { + if ($type != 'hidden') { + $addParm('style' , 'direction:ltr'); + } + $addLine('<' . implode(' ', $parms) . ' />'); + } + + --$indent; + $addLine('
'); + + if ($key == 'horde_pass') { + $addLine(''); + } + + if (!empty($div)) { + --$indent; + $addLine(''); + } + } + print implode("\n", $lines); +?> isLocked('language')): ?>
From 7e021e2257f9aca53f130ce62bb607de623585f4 Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Thu, 10 Jul 2025 18:27:46 -0400 Subject: [PATCH 2/2] fix: Make second factor input visible to user --- src/Login.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Login.php b/src/Login.php index e5f97d56..8ecd5cd7 100644 --- a/src/Login.php +++ b/src/Login.php @@ -39,8 +39,8 @@ public function buildLoginParams(): array if ($this->secondFactorSupported) { $loginparams['horde_secondfactor'] = [ 'label' => _("Second Factor"), - 'type' => 'password', - 'extra' => [ 'autocomplete' => 'off' ], + 'type' => 'text', + 'extra' => [ 'autocomplete' => 'one-time-code' ], ]; } return $loginparams;