diff --git a/doc/LUCIDE-LICENSE.md b/doc/LUCIDE-LICENSE.md
new file mode 100644
index 0000000..135377a
--- /dev/null
+++ b/doc/LUCIDE-LICENSE.md
@@ -0,0 +1,51 @@
+The application icon in themes/default/graphics/ is derived from Lucide Icons,
+converted to PNG format.
+
+Source: https://github.com/lucide-icons/lucide
+License: ISC (with some icons under MIT via Feather Icons)
+
+The full license text follows below.
+
+========================================================================
+
+ISC License
+
+Copyright (c) 2020 Lucide Icons and Contributors
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+========================================================================
+
+Some Lucide icons are derived from Feather Icons by Cole Bemis:
+
+The MIT License (MIT)
+
+Copyright (c) 2013-present Cole Bemis
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/src/ResponsivePasswordController.php b/src/ResponsivePasswordController.php
index 7cc2024..882ef8d 100644
--- a/src/ResponsivePasswordController.php
+++ b/src/ResponsivePasswordController.php
@@ -4,8 +4,8 @@
namespace Horde\Passwd;
-use Horde\Core\Assets\ResponsiveAssets;
-use Horde\Core\Config\RegistryState;
+use Horde\Core\PageOutput\PageContent;
+use Horde\Core\PageOutput\ResponsiveChromeRenderer;
use Horde\Core\View\ResponsiveTemplateView;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
@@ -28,31 +28,15 @@
*/
class ResponsivePasswordController implements RequestHandlerInterface
{
- /**
- * Handle password change request
- *
- * @param ServerRequestInterface $request The request object
- *
- * @return ResponseInterface The response
- */
public function handle(ServerRequestInterface $request): ResponseInterface
{
global $registry, $session, $injector, $conf;
- // Get form variables
$vars = $injector->getInstance('Horde_Variables');
- // Use existing Passwd_Basic for business logic
- $basic = new \Passwd_Basic($vars);
-
- // Build responsive assets
- $responsiveAssets = new ResponsiveAssets(new RegistryState($registry->applications));
-
- // Get backend info
$backends = $injector->getInstance('Passwd_Factory_Driver')->backends;
$backend_key = $vars->backend;
if (!isset($backends[$backend_key])) {
- // Choose first available backend
foreach ($backends as $k => $v) {
if (substr($k, 0, 1) != '_') {
$backend_key = $k;
@@ -61,10 +45,8 @@ public function handle(ServerRequestInterface $request): ResponseInterface
}
}
- // Determine if we should show backend selector
$showlist = ($conf['backend']['backend_list'] == 'shown');
- // Build header text
if ($showlist) {
$header = _("Change your password");
} else {
@@ -74,24 +56,7 @@ public function handle(ServerRequestInterface $request): ResponseInterface
);
}
- // Prepare view data
$viewData = [
- // Topbar data
- 'topbar' => [
- 'appName' => _("Change Password"),
- 'portalUrl' => (string) $registry->getServiceLink('portal')->setRaw(true),
- 'logoutUrl' => (string) $registry->getServiceLink('logout')->setRaw(true),
- 'userName' => $registry->getAuth(),
- ],
-
- // Asset URIs
- 'hordeThemesUri' => $registry->get('themesuri', 'horde'),
- 'hordeJsUri' => $registry->get('jsuri', 'horde'),
- 'passwdThemesUri' => $registry->get('themesuri', 'passwd'),
- 'passwdJsUri' => $registry->get('jsuri', 'passwd'),
- 'registry' => $registry,
-
- // Form data
'formInput' => \Horde_Util::formInput(),
'url' => $vars->return_to ?: '',
'userid' => $registry->getAuth() ?: '',
@@ -101,26 +66,31 @@ public function handle(ServerRequestInterface $request): ResponseInterface
'backend' => $backend_key,
'token' => $session->getToken(),
'header' => $header,
-
- // Status messages (use responsive listener for proper CSS classes)
'status' => $this->getStatusMessages(),
];
- // Render responsive template
- $templatePath = PASSWD_TEMPLATES . '/responsive.html.php';
+ $templatePath = PASSWD_TEMPLATES . '/responsive-body.html.php';
$view = new ResponsiveTemplateView($templatePath, $viewData);
+ $bodyHtml = $view->render();
+
+ $chromeRenderer = $injector->get(ResponsiveChromeRenderer::class);
+ $pageContent = new PageContent(
+ title: _("Change Password") . ' - Horde',
+ bodyHtml: $bodyHtml,
+ app: 'passwd',
+ jsFiles: ['passwd-responsive.js'],
+ );
+
+ $pageHtml = $chromeRenderer->renderPage($pageContent, $request);
$streamFactory = $injector->getInstance('Psr\Http\Message\StreamFactoryInterface');
$responseFactory = $injector->getInstance('Psr\Http\Message\ResponseFactoryInterface');
+
return $responseFactory->createResponse(200)
- ->withBody($streamFactory->createStream($view->render()));
+ ->withHeader('Content-Type', 'text/html; charset=UTF-8')
+ ->withBody($streamFactory->createStream($pageHtml));
}
- /**
- * Get status messages using responsive listener
- *
- * @return string HTML status messages
- */
private function getStatusMessages(): string
{
$notification = $GLOBALS['notification'] ?? null;
@@ -128,7 +98,6 @@ private function getStatusMessages(): string
return '';
}
- // Register our responsive listener if not already registered
if (!$notification->getListener('responsive_status')) {
$notification->attach(
'responsive_status',
diff --git a/templates/responsive-body.html.php b/templates/responsive-body.html.php
new file mode 100644
index 0000000..9a2f40a
--- /dev/null
+++ b/templates/responsive-body.html.php
@@ -0,0 +1,113 @@
+= htmlspecialchars($header) ?>
+