diff --git a/admin/configuration.php b/admin/configuration.php
index d185a26c0..928ebcac0 100644
--- a/admin/configuration.php
+++ b/admin/configuration.php
@@ -50,6 +50,7 @@ $main_checkboxes = array(
'show_mobile_app_banner_in_gallery',
'show_mobile_app_banner_in_admin',
'upload_detect_duplicate',
+ 'use_standard_pages',
);
$sizes_checkboxes = array(
diff --git a/admin/themes/default/template/configuration_main.tpl b/admin/themes/default/template/configuration_main.tpl
index 03d3ef656..3ae6869a8 100644
--- a/admin/themes/default/template/configuration_main.tpl
+++ b/admin/themes/default/template/configuration_main.tpl
@@ -252,6 +252,17 @@ jQuery("input[name='email_admin_on_new_user_filter']").change(function() {
+
+
+
+
+
+
+
diff --git a/admin/themes_installed.php b/admin/themes_installed.php
index 2b4a6fa36..2a933e752 100644
--- a/admin/themes_installed.php
+++ b/admin/themes_installed.php
@@ -59,7 +59,7 @@ $tpl_themes = array();
foreach ($themes->fs_themes as $theme_id => $fs_theme)
{
- if ($theme_id == 'default')
+ if ($theme_id == 'default' or $theme_id == 'standard_pages')
{
continue;
}
diff --git a/identification.php b/identification.php
index 9059ef270..388243017 100644
--- a/identification.php
+++ b/identification.php
@@ -40,7 +40,7 @@ if ( !empty($_GET['redirect']) )
$redirect_to = urldecode($_GET['redirect']);
if ( $conf['guest_access'] and !isset($_GET['hide_redirect_error']))
{
- $page['errors'][] = l10n('You are not authorized to access the requested page');
+ $page['errors']['login_page_error'][] = l10n('You are not authorized to access the requested page');
}
}
@@ -48,7 +48,7 @@ if (isset($_POST['login']))
{
if (!isset($_COOKIE[session_name()]))
{
- $page['errors'][] = l10n('Cookies are blocked or not supported by your browser. You must enable cookies to connect.');
+ $page['errors']['login_page_error'][] = l10n('Cookies are blocked or not supported by your browser. You must enable cookies to connect.');
}
else
{
@@ -82,7 +82,7 @@ if (isset($_POST['login']))
}
else
{
- $page['errors'][] = l10n('Invalid username or password!');
+ $page['errors']['login_form_error'] = l10n('Invalid username or password!');
}
}
}
@@ -121,6 +121,41 @@ if (!$conf['gallery_locked'] && (!isset($themeconf['hide_menu_on']) OR !in_array
include( PHPWG_ROOT_PATH.'include/menubar.inc.php');
}
+//Load language if cookie is set from login/register/password pages
+if (isset($_COOKIE['lang']) and $user['language'] != $_COOKIE['lang'])
+{
+ if (!array_key_exists($_COOKIE['lang'], get_languages()))
+ {
+ fatal_error('[Hacking attempt] the input parameter "'.$_COOKIE['lang'].'" is not valid');
+ }
+
+ $user['language'] = $_COOKIE['lang'];
+ load_language('common.lang', '', array('language'=>$user['language']));
+}
+
+//Get list of languages
+foreach (get_languages() as $language_code => $language_name)
+{
+ $language_options[$language_code] = $language_name;
+}
+
+$template->assign(array(
+ 'language_options' => $language_options,
+ 'current_language' => $user['language']
+));
+
+//Get link to doc
+if ('fr' == substr($user['language'], 0, 2))
+{
+ $help_link = "https://doc-fr.piwigo.org/les-utilisateurs/se-connecter-a-piwigo";
+}
+else
+{
+ $help_link = "https://doc.piwigo.org/managing-users/log-in-to-piwigo";
+}
+
+$template->assign('HELP_LINK', $help_link);
+
//----------------------------------------------------------- html code display
include(PHPWG_ROOT_PATH.'include/page_header.php');
trigger_notify('loc_end_identification');
diff --git a/include/functions_user.inc.php b/include/functions_user.inc.php
index d3aaa37cf..5ffe9d757 100644
--- a/include/functions_user.inc.php
+++ b/include/functions_user.inc.php
@@ -1048,6 +1048,29 @@ function log_user($user_id, $remember_me)
{
global $conf, $user;
+ //New default login and register pages, if users changes languages and succesfully logs in
+ //we want to update the userpref language stored in a cookie
+
+ //TODO check value of cookie
+
+ if (isset($_COOKIE['lang']) and $user['language'] != $_COOKIE['lang'])
+ {
+ if (!array_key_exists($_COOKIE['lang'], get_languages()))
+ {
+ fatal_error('[Hacking attempt] the input parameter "'.$_COOKIE['lang'].'" is not valid');
+ }
+
+ single_update(
+ USER_INFOS_TABLE,
+ array('language' => $_COOKIE['lang']),
+ array('user_id' => $user_id)
+ );
+
+ // We unset the lang cookie, if user has changed their language using interface we don't want to keep setting it back
+ // to what was chosen using standard pages lang switch
+ setcookie("lang", "", time() - 3600);
+ }
+
if ($remember_me and $conf['authorize_remembering'])
{
$now = time();
diff --git a/include/template.class.php b/include/template.class.php
index b08a8c15e..47b50f8e4 100644
--- a/include/template.class.php
+++ b/include/template.class.php
@@ -181,10 +181,21 @@ class Template
*/
function set_theme($root, $theme, $path, $load_css=true, $load_local_head=true, $colorscheme='dark')
{
- $this->set_template_dir($root.'/'.$theme.'/'.$path);
-
$themeconf = $this->load_themeconf($root.'/'.$theme);
+ // We loop over the theme and the parent theme, so if we exclude default,
+ // standard pages can't get the header to load the html header
+ if (
+ 'default' != $theme
+ and in_array(script_basename(), array('identification', 'register', 'password'))
+ and (($themeconf['use_standard_pages'] ?? false) or conf_get_param('use_standard_pages', false))
+ )
+ {
+ $theme = 'standard_pages';
+ }
+
+ $this->set_template_dir($root.'/'.$theme.'/'.$path);
+
if (isset($themeconf['parent']) and $themeconf['parent'] != $theme)
{
$this->set_theme(
diff --git a/install/config.sql b/install/config.sql
index 86dd06b5c..1dc6915ea 100644
--- a/install/config.sql
+++ b/install/config.sql
@@ -79,3 +79,4 @@ INSERT INTO piwigo_config (param,value) VALUES ('index_search_in_set_button','fa
INSERT INTO piwigo_config (param,value) VALUES ('index_search_in_set_action','true');
INSERT INTO piwigo_config (param,value) VALUES ('upload_detect_duplicate','true');
INSERT INTO piwigo_config (param,value) VALUES ('webmaster_id','1');
+INSERT INTO piwigo_config (param,value) VALUES ('use_standard_pages','true');
diff --git a/install/db/175-database.php b/install/db/175-database.php
new file mode 100644
index 000000000..3cfb50ac6
--- /dev/null
+++ b/install/db/175-database.php
@@ -0,0 +1,22 @@
+
diff --git a/language/en_GB/common.lang.php b/language/en_GB/common.lang.php
index 564861ca8..52af7cfae 100644
--- a/language/en_GB/common.lang.php
+++ b/language/en_GB/common.lang.php
@@ -175,7 +175,7 @@ $lang['Photo title, A → Z'] = 'Photo title, A → Z';
$lang['Photo title, Z → A'] = 'Photo title, Z → A';
$lang['Link: %s'] = 'Link: %s';
$lang['Links'] = 'Links';
-$lang['Login'] = 'Login';
+$lang['Login'] = 'Sign in';
$lang['Logout'] = 'Logout';
$lang['Manage this user comment: %s'] = 'Manage this user comment: %s';
$lang['Manual sort order'] = 'Manual sort order';
diff --git a/language/en_UK/common.lang.php b/language/en_UK/common.lang.php
index 5d9c737a2..5812c4fc3 100644
--- a/language/en_UK/common.lang.php
+++ b/language/en_UK/common.lang.php
@@ -205,7 +205,7 @@ $lang['letters'] = "letters";
$lang['Links'] = "Links";
$lang['login mustn\'t end with a space character'] = "login must not end with a space character";
$lang['login mustn\'t start with a space character'] = "login must not start with a space character";
-$lang['Login'] = "Login";
+$lang['Login'] = "Sign in";
$lang['Logout'] = "Logout";
$lang['mail address must be like xxx@yyy.eee (example : jack@altern.org)'] = 'mail address must be like xxx@yyy.eee (example: jack@altern.org)';
$lang['Manage this user comment: %s'] = 'Manage this user comment: %s';
@@ -455,3 +455,20 @@ $lang['There are no tags available for the photos currently filtered'] = 'There
$lang['There are no creation dates available for the photos currently filtered'] = 'There are no creation dates available for the photos currently filtered';
$lang['There are no authors available for the photos currently filtered'] = 'There are no authors available for the photos currently filtered';
$lang['Set your password below.'] = 'Set your password below.';
+$lang['Use standard Piwigo template for common pages.'] = 'Use standard Piwigo template for common pages.';
+$lang['When enabled, a common template is used for the login and registration pages, regardless of the theme.'] = 'When enabled, a common template is used for the login and registration pages, regardless of the theme.';
+$lang['Don\'t have an account yet ?'] = 'Don\'t have an account yet ?';
+$lang['Create an account'] = 'Create an account';
+$lang['Return to the gallery'] = 'Return to the gallery';
+$lang['Already have an account ?'] = 'Already have an account ?';
+$lang['An email has been sent with a link to reset your password'] = 'An email has been sent with a link to reset your password';
+$lang['Check your inbox'] = 'Check your inbox';
+$lang['Your password was successfully set'] = 'Your password was successfully set';
+$lang['Your password was successfully reset'] = 'Your password was successfully reset';
+$lang['An error has occured please got back to Sign in or Register'] = 'An error has occured please got back to Sign in or Register';
+$lang['Return to Sign in'] = 'Return to Sign in';
+$lang['Hello %s, enter your new password below.'] = 'Hello %s, enter your new password below.';
+$lang['Confirm my new password'] = 'Confirm my new password';
+$lang['Confirm Password'] = 'Confirm Password';
+$lang['Confirm new password'] = 'Confirm new password';
+$lang['Set my password'] = 'Set my password';
diff --git a/language/fr_FR/common.lang.php b/language/fr_FR/common.lang.php
index 6fef01b41..ed2d7ade1 100644
--- a/language/fr_FR/common.lang.php
+++ b/language/fr_FR/common.lang.php
@@ -455,3 +455,20 @@ $lang['There are no tags available for the photos currently filtered'] = 'Aucun
$lang['There are no creation dates available for the photos currently filtered'] = 'Aucune date de création n\'est disponible pour les photos actuellement filtrées';
$lang['There are no authors available for the photos currently filtered'] = 'Aucun auteur n\'est disponible pour les photos actuellement filtrées';
$lang['Set your password below.'] = 'Définissez votre mot de passe ci-dessous.';
+$lang['Use standard Piwigo template for common pages.'] = 'Utiliser le modèle standard de Piwigo pour les pages courantes.';
+$lang['When enabled, a common template is used for the login and registration pages, regardless of the theme.'] = 'Lorsqu\'elle est activée, un modèle commun est utilisé pour les pages de connexion, d\'inscription et de mot de passe oublié, quel que soit le thème. Certains thèmes peuvent utiliser ces modèles même si vous décochez cette option.';
+$lang['Don\'t have an account yet ?'] = 'Vous n\'avez pas encore de compte?';
+$lang['Create an account'] = 'Créez un compte';
+$lang['Return to the gallery'] = 'Retour à la galerie';
+$lang['Already have an account ?'] = 'Vous avez déjà un compte ?';
+$lang['An error has occured please got back to Sign in or Register'] = 'Une erreur est survenue, veuillez retourner à la page Connexion ou Inscription.';
+$lang['Return to Sign in'] ='Retour à la page Connexion';
+$lang['An email has been sent with a link to reset your password'] = 'Un e-mail a été envoyé avec un lien pour réinitialiser votre mot de passe.';
+$lang['Check your inbox.'] = 'Vérifiez votre boîte de réception.';
+$lang['Hello %s, enter your new password below.'] = 'Bonjour %s, saisissez votre nouveau mot de passe ci-dessous.';
+$lang['Confirm my new password'] = 'Confirmer mon nouveau mot de passe';
+$lang['Confirm Password'] = 'Confirmer le mot de passe';
+$lang['Confirm new password'] = 'Confirmer le nouveau mot de passe';
+$lang['Set my password'] = 'Définir mon mot de passe';
+$lang['Your password was successfully set'] = 'Votre mot de passe a été défini avec succès';
+$lang['Your password was successfully reset'] = 'Votre mot de passe a été réinitialisé avec succès';
diff --git a/password.php b/password.php
index 209c0c019..26e3b3ab8 100644
--- a/password.php
+++ b/password.php
@@ -22,7 +22,7 @@ check_status(ACCESS_FREE);
trigger_notify('loc_begin_password');
-check_input_parameter('action', $_GET, false, '/^(lost|reset|none)$/');
+check_input_parameter('action', $_GET, false, '/^(lost|reset|lost_end|reset_end|none)$/');
// +-----------------------------------------------------------------------+
// | Functions |
@@ -40,7 +40,7 @@ function process_password_request()
if (empty($_POST['username_or_email']))
{
- $page['errors'][] = l10n('Invalid username or email');
+ $page['errors']['password_form_error'] = l10n('Invalid username or email');
return false;
}
@@ -53,7 +53,7 @@ function process_password_request()
if (!is_numeric($user_id))
{
- $page['errors'][] = l10n('Invalid username or email');
+ $page['errors']['password_form_error'] = l10n('Invalid username or email');
return false;
}
@@ -63,13 +63,13 @@ function process_password_request()
$status = $userdata['status'];
if (is_a_guest($status) or is_generic($status))
{
- $page['errors'][] = l10n('Password reset is not allowed for this user');
+ $page['errors']['password_form_error'] = l10n('Password reset is not allowed for this user');
return false;
}
if (empty($userdata['email']))
{
- $page['errors'][] = l10n(
+ $page['errors']['password_form_error'] = l10n(
'User "%s" has no email address, password reset is not possible',
$userdata['username']
);
@@ -92,7 +92,7 @@ function process_password_request()
}
else
{
- $page['errors'][] = l10n('Error sending email');
+ $page['errors']['password_page_error'] = l10n('Error sending email');
return false;
}
}
@@ -110,7 +110,7 @@ function check_password_reset_key($reset_key)
$key = $reset_key;
if (!preg_match('/^[a-z0-9]{20}$/i', $key))
{
- $page['errors'][] = l10n('Invalid key');
+ $page['errors']['password_page_error'] = l10n('Invalid key');
return false;
}
@@ -130,7 +130,7 @@ SELECT
{
if (is_a_guest($row['status']) or is_generic($row['status']))
{
- $page['errors'][] = l10n('Password reset is not allowed for this user');
+ $page['errors']['password_page_error'] = l10n('Password reset is not allowed for this user');
return false;
}
@@ -141,7 +141,7 @@ SELECT
if (empty($user_id))
{
- $page['errors'][] = l10n('Invalid key');
+ $page['errors']['password_page_error'] = l10n('Invalid key');
return false;
}
@@ -160,13 +160,13 @@ function reset_password()
if ($_POST['use_new_pwd'] != $_POST['passwordConf'])
{
- $page['errors'][] = l10n('The passwords do not match');
+ $page['errors']['password_form_error'] = l10n('The passwords do not match');
return false;
}
if (!isset($_GET['key']))
{
- $page['errors'][] = l10n('Invalid key');
+ $page['errors']['password_page_error'] = l10n('Invalid key');
}
$user_id = check_password_reset_key($_GET['key']);
@@ -202,7 +202,7 @@ if (isset($_POST['submit']))
{
if (process_password_request())
{
- $page['action'] = 'none';
+ $page['action'] = 'lost_end';
}
}
@@ -210,7 +210,7 @@ if (isset($_POST['submit']))
{
if (reset_password())
{
- $page['action'] = 'none';
+ $page['action'] = 'reset_end';
}
}
}
@@ -272,7 +272,6 @@ if ('lost' == $page['action'] and !is_a_guest())
// +-----------------------------------------------------------------------+
// | template initialization |
// +-----------------------------------------------------------------------+
-
$title = l10n('Password Reset');
if ('lost' == $page['action'])
{
@@ -291,7 +290,7 @@ else if ('reset' == $page['action'] and isset($first_login) and $first_login)
$page['body_id'] = 'thePasswordPage';
-$template->set_filenames(array('password'=>'password.tpl'));
+$template->set_filenames( array('password'=>'password.tpl') );
$template->assign(
array(
'title' => $title,
@@ -302,7 +301,6 @@ $template->assign(
)
);
-
// include menubar
$themeconf = $template->get_template_vars('themeconf');
if (!isset($themeconf['hide_menu_on']) OR !in_array('thePasswordPage', $themeconf['hide_menu_on']))
@@ -310,6 +308,42 @@ if (!isset($themeconf['hide_menu_on']) OR !in_array('thePasswordPage', $themecon
include( PHPWG_ROOT_PATH.'include/menubar.inc.php');
}
+//Load language if cookie is set from login/register/password pages
+if (isset($_COOKIE['lang']) and $user['language'] != $_COOKIE['lang'])
+{
+ if (!array_key_exists($_COOKIE['lang'], get_languages()))
+ {
+ fatal_error('[Hacking attempt] the input parameter "'.$_COOKIE['lang'].'" is not valid');
+ }
+
+ $user['language'] = $_COOKIE['lang'];
+ load_language('common.lang', '', array('language'=>$user['language']));
+}
+
+//Get list of languages
+foreach (get_languages() as $language_code => $language_name)
+{
+ $language_options[$language_code] = $language_name;
+}
+
+$template->assign(array(
+ 'language_options' => $language_options,
+ 'current_language' => $user['language']
+));
+
+//Get link to doc
+if ('fr' == substr($user['language'], 0, 2))
+{
+ $help_link = "https://doc-fr.piwigo.org/les-utilisateurs/se-connecter-a-piwigo";
+}
+else
+{
+ $help_link = "https://doc.piwigo.org/managing-users/log-in-to-piwigo";
+}
+
+$template->assign('HELP_LINK', $help_link);
+
+
// +-----------------------------------------------------------------------+
// | html code display |
// +-----------------------------------------------------------------------+
diff --git a/register.php b/register.php
index a5906786f..07fa7d047 100644
--- a/register.php
+++ b/register.php
@@ -29,20 +29,20 @@ if (isset($_POST['submit']))
if (!verify_ephemeral_key(@$_POST['key']))
{
set_status_header(403);
- $page['errors'][] = l10n('Invalid/expired form key');
+ $page['errors']['register_page_error'][] = l10n('Invalid/expired form key');
}
if(empty($_POST['password']))
{
- $page['errors'][] = l10n('Password is missing. Please enter the password.');
+ $page['errors']['register_form_error'] = l10n('Password is missing. Please enter the password.');
}
else if(empty($_POST['password_conf']))
{
- $page['errors'][] = l10n('Password confirmation is missing. Please confirm the chosen password.');
+ $page['errors']['register_form_error'] = l10n('Password confirmation is missing. Please confirm the chosen password.');
}
else if ($_POST['password'] != $_POST['password_conf'])
{
- $page['errors'][] = l10n('The passwords do not match');
+ $page['errors']['register_form_error'] = l10n('The passwords do not match');
}
register_user(
@@ -92,7 +92,7 @@ $template->assign(array(
'F_LOGIN' => $login,
'F_EMAIL' => $email,
'obligatory_user_mail_address' => $conf['obligatory_user_mail_address'],
- ));
+));
// include menubar
$themeconf = $template->get_template_vars('themeconf');
@@ -101,6 +101,41 @@ if (!isset($themeconf['hide_menu_on']) OR !in_array('theRegisterPage', $themecon
include( PHPWG_ROOT_PATH.'include/menubar.inc.php');
}
+//Load language if cookie is set from login/register/password pages
+if (isset($_COOKIE['lang']) and $user['language'] != $_COOKIE['lang'])
+{
+ if (!array_key_exists($_COOKIE['lang'], get_languages()))
+ {
+ fatal_error('[Hacking attempt] the input parameter "'.$_COOKIE['lang'].'" is not valid');
+ }
+
+ $user['language'] = $_COOKIE['lang'];
+ load_language('common.lang', '', array('language'=>$user['language']));
+}
+
+//Get list of languages
+foreach (get_languages() as $language_code => $language_name)
+{
+ $language_options[$language_code] = $language_name;
+}
+
+$template->assign(array(
+ 'language_options' => $language_options,
+ 'current_language' => $user['language'],
+));
+
+//Get link to doc
+if ('fr' == substr($user['language'], 0, 2))
+{
+ $help_link = "https://doc-fr.piwigo.org/les-utilisateurs/se-connecter-a-piwigo";
+}
+else
+{
+ $help_link = "https://doc.piwigo.org/managing-users/log-in-to-piwigo";
+}
+
+$template->assign('HELP_LINK', $help_link);
+
include(PHPWG_ROOT_PATH.'include/page_header.php');
trigger_notify('loc_end_register');
flush_page_messages();
diff --git a/themes/standard_pages/css/identification_register.css b/themes/standard_pages/css/identification_register.css
new file mode 100644
index 000000000..3975351bc
--- /dev/null
+++ b/themes/standard_pages/css/identification_register.css
@@ -0,0 +1,480 @@
+html{
+ min-height:100%;
+}
+
+#theHeader,
+#copyright{
+ display:none;
+}
+
+#theIdentificationPage,
+#theRegisterPage,
+#thePasswordPage{
+ width:100%;
+ height:100%;
+ min-height:100vh;
+ margin:0;
+ font-family:Arial, Helvetica, sans-serif;
+}
+
+#theIdentificationPage #the_page,
+#theRegisterPage #the_page,
+#thePasswordPage #the_page{
+ min-height:100vh;
+ height:100%;
+}
+
+#mode{
+ display:flex;
+ flex-direction:column;
+ height:100%;
+ min-height:100vh;
+ overflow-y:auto;
+}
+
+#login-form,
+#register-form,
+#password-form{
+ border-radius:15px;
+ width:400px;
+ margin:0 auto;
+ margin-top:50px;
+ box-shadow: 0px 4px 10px 0px rgba(0, 0, 0, 0.15);
+ padding:50px;
+}
+
+#logo-section{
+ max-width:300px;
+ margin:0 auto;
+ padding-top:50px;
+}
+
+#logo-section img{
+ width:100%;
+}
+
+h1{
+ font-size: 30px;
+ font-weight: 400;
+ margin:0;
+ margin-bottom:30px;
+ text-align:center;
+}
+
+h1 i{
+ margin:10px;
+}
+
+#login-form form,
+#register-form form,
+#password-form form{
+ display:flex;
+ justify-content:center;
+ flex-direction:column;
+}
+
+#password-form p{
+ text-align:center;
+ font-size:15px;
+ font-weight:500;
+ margin:0;
+}
+
+#password-form .error-message{
+ bottom:0;
+}
+
+.input-container{
+ border-radius:3px;
+ padding:5px 15px;
+ margin-bottom:25px;
+ flex-wrap:nowrap;
+}
+
+.input-container input{
+ background-color:transparent;
+ border:none;
+ width:100%;
+ line-height:25px;
+}
+
+.input-container input:focus{
+ border:none;
+ outline:none;
+}
+
+.input-container:focus-within{
+ border:1px solid #ff7700!important;
+}
+
+.input-container i {
+ font-size:15px;
+ margin-right:5px;
+}
+
+.column-flex{
+ display:flex;
+ flex-direction:column;
+ position:relative;
+}
+
+.row-flex{
+ display:flex;
+ flex-direction:row;
+ align-items:center;
+}
+
+
+.remember-me-container {
+ display: flex;
+ align-items: center;
+ cursor: pointer;
+ font-family: sans-serif;
+ font-size: 16px;
+ margin-bottom:5px;
+}
+
+.gallery-icon-checkmark {
+ width: 18px;
+ height: 18px;
+ border: 1px solid #777;
+ border-radius: 2px;
+ display: inline-block;
+ margin-right: 8px;
+ line-height: 18px;
+ font-size: 14px;
+}
+
+.remember-me-container:hover label{
+ cursor:pointer;
+}
+
+.gallery-icon-checkmark::before {
+ opacity: 0;
+}
+
+input[type="checkbox"]#remember_me {
+ display: none;
+}
+
+input[type="checkbox"]#remember_me:checked + label ~ .gallery-icon-checkmark::before,
+input[type="checkbox"]#remember_me:checked + .gallery-icon-checkmark::before {
+ opacity: 1;
+ font-size: 12px;
+ margin: 2px;
+ vertical-align: text-top;
+}
+
+label{
+margin-bottom:5px;
+font-size:15px;
+}
+
+p.form-instructions{
+ padding-bottom:25px;
+}
+
+.btn-main{
+ background-color:#ff7700!important;
+ color:white!important;
+ border:none;
+ padding:15px;
+ margin-top:15px;
+ cursor:pointer;
+ text-decoration:none!important;
+}
+
+a.btn-main{
+ display:block;
+ text-align:center;
+}
+
+#return-to-gallery{
+ margin: 30px auto;
+ display:block;
+ width:fit-content;
+}
+
+.secondary-links{
+ margin-top:40px;
+ text-align:center;
+}
+
+#theIdentificationPage a,
+#theRegisterPage a,
+#thePasswordPage a{
+ text-decoration:underline;
+}
+
+#theIdentificationPage a:hover,
+#theRegisterPage a:hover,
+#thePasswordPage a:hover{
+ border-bottom:none;
+}
+
+#separator{
+ width:300px;
+ border-bottom:1px solid #D8D8D8;
+ display:block;
+ margin: 15px auto;
+}
+
+#header-options{
+ position:fixed;
+ width:100%;
+ display:flex;
+ justify-content: space-between;
+ font-size:15px;
+}
+
+#header-options > *{
+ padding:15px;
+}
+
+#theIdentificationPage #header-options .toggle-mode{
+ cursor:pointer;
+}
+
+.gallery-icon-sun{
+ display:none;
+}
+
+.gallery-icon-eye{
+ cursor:pointer;
+}
+
+#language-switch{
+ display:flex;
+ justify-content: flex-end;
+ font-size:15px;
+ position: fixed;
+ right: 0;
+ bottom: 0;
+}
+
+#lang-select{
+ width:fit-content;
+ position:relative;
+}
+
+#selected-language-container{
+ padding:15px;
+}
+
+#lang-select #other-languages{
+ display:none;
+ border-radius: 5px;
+ padding: 15px;
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
+ margin-right:11px;
+ width:max-content;
+ position:absolute;
+ bottom:40px;
+ right:0;
+}
+
+#lang-select #other-languages span{
+ text-decoration:none;
+ display:block;
+ padding:5px 0;
+}
+
+#lang-select #other-languages span:hover{
+ color:#ff7700;
+ cursor:pointer;
+}
+
+#lang-select:hover #other-languages{
+ display:block;
+}
+
+#lang-select .gallery-icon-left-chevron:before{
+ rotate: 90deg;
+}
+
+#selected-language{
+ margin-left:5px;
+ text-decoration:underline;
+}
+
+.success-message{
+ width: calc(100% - 34px);
+ display: block;
+ padding: 15px;
+ margin-bottom:15px;
+}
+
+.error-message{
+ text-align: left;
+ position: absolute;
+ bottom: 10px;
+ left:0;
+ margin: 0;
+ display:none;
+}
+
+.error-message i,
+p.error-message{
+ color: #EB3223!important;
+}
+
+.error_block_container {
+ position: absolute;
+ right: 15px;
+ max-width: 300px;
+ top:40px;
+}
+
+.error_block {
+ display:flex;
+ background-color:#BE4949;
+ border-radius:5px;
+ color:#FFC8C8;
+ padding:15px;
+ position:relative;
+ align-items:center;
+}
+
+.error_block p{
+ margin:0;
+}
+
+.error_block .gallery-icon-cancel:before{
+ font-size:33px;
+ margin-left:0;
+ margin-right:15px;
+}
+
+#password-form p.intro-paragraph{
+ margin-bottom:15px;
+}
+
+
+/* Light */
+#theIdentificationPage .light,
+#theRegisterPage .light,
+#thePasswordPage .light{
+ background: linear-gradient(75.69deg, #FFEACF 7.64%, #FFFAF3 77.87%);
+}
+
+.light #login-form,
+.light #register-form,
+.light #password-form,
+.light #lang-select #other-languages {
+ background-color:#ffffff;
+}
+
+#theIdentificationPage .light a,
+#theRegisterPage .light a,
+#thePasswordPage .light a,
+.light h1,
+.light .input-container input,
+.light .secondary-links,
+.light .properties label,
+.light .properties i,
+.light #password-form p,
+.light #lang-select #other-languages span{
+ color:#3C3C3C;
+}
+
+#theIdentificationPage .light a:hover,
+#theRegisterPage .light a:hover,
+#thePasswordPage .light a:hover{
+ color:#ff7700;
+}
+
+.light #header-options a,
+.light #header-options .toggle-mode,
+.light #selected-language-container{
+ color:#ff7700;
+}
+
+.light .input-container{
+ background-color:#F0F0F0;
+ border:1px solid #F0F0F0;
+}
+
+.light #separator{
+ border-bottom:1px solid #D8D8D8;
+}
+
+.light .gallery-icon-eye{
+ color:#898989;
+}
+
+.light .success-message{
+ background-color: #DBF6D7;
+ color: #6DCE5E;
+ border-left: 4px solid #6DCE5E;
+}
+
+/* Dark */
+#theIdentificationPage .dark,
+#theRegisterPage .dark,
+#thePasswordPage .dark{
+ background: linear-gradient(75.69deg, #1B1B1D 7.64%, #2F2F2F 77.87%);
+}
+
+.dark #login-form,
+.dark #register-form,
+.dark #password-form{
+ background-color:#3C3C3C;
+}
+
+#theIdentificationPage .dark a,
+#theRegisterPage .dark a,
+#thePasswordPage .dark a,
+.dark h1,
+.dark .input-container input,
+.dark .secondary-links,
+.dark .properties label,
+.dark .properties i,
+.dark #password-form p,
+.dark #lang-select #other-languages span{
+ color:#D6D6D6;
+}
+
+#theIdentificationPage .dark a:hover,
+#theRegisterPage .dark a:hover,
+#thePasswordPage .dark a:hover,
+.dark #lang-select #other-languages span{
+ color:#ff7700;
+}
+
+.dark #header-options a,
+.dark #header-options .toggle-mode,
+.dark #selected-language-container{
+ color:#FFEBD0;
+}
+
+.dark .input-container{
+ background-color:#303030;
+ border:1px solid #303030;
+}
+
+.dark #separator{
+ border-bottom:1px solid #303030;
+}
+
+.dark .gallery-icon-eye{
+ color:#898989;
+}
+
+.dark #lang-select #other-languages {
+ background-color: #3C3C3C;
+}
+
+.dark .success-message{
+ background-color: #4EA590;
+ color: #AAF6E4;
+ border-left: 4px solid #AAF6E4;
+}
+
+/*Responsive display*/
+@media (max-width: 768px) {
+ #login-form,
+ #register-form,
+ #password-form{
+ max-width:300px;
+ }
+}
diff --git a/themes/standard_pages/images/piwigo_logo.svg b/themes/standard_pages/images/piwigo_logo.svg
new file mode 100644
index 000000000..582608ff7
--- /dev/null
+++ b/themes/standard_pages/images/piwigo_logo.svg
@@ -0,0 +1,26 @@
+
diff --git a/themes/standard_pages/images/piwigo_logo_dark.svg b/themes/standard_pages/images/piwigo_logo_dark.svg
new file mode 100644
index 000000000..58489e9ca
--- /dev/null
+++ b/themes/standard_pages/images/piwigo_logo_dark.svg
@@ -0,0 +1,16 @@
+
diff --git a/themes/standard_pages/js/identification_register.js b/themes/standard_pages/js/identification_register.js
new file mode 100644
index 000000000..52f4a7da1
--- /dev/null
+++ b/themes/standard_pages/js/identification_register.js
@@ -0,0 +1,115 @@
+let modeCookie = getCookie("mode");
+if("" != modeCookie)
+{
+ toggle_mode(modeCookie);
+}
+
+jQuery( document ).ready(function() {
+ jQuery("#selected-language").textContent = selected_language;
+
+ //Override empty input message
+ jQuery("form").on("submit", function (e) {
+ let isValid = true;
+
+ jQuery(".column-flex").each(function () {
+ let input = jQuery(this).find("input");
+ let errorMessage = jQuery(this).find(".error-message");
+ if (!input.val().trim()) {
+
+ e.preventDefault();
+ input[0].setCustomValidity(""); // Override browser tooltip (empty space hides it)
+ errorMessage.show();
+ isValid = false;
+ } else {
+ input[0].setCustomValidity("");
+ errorMessage.hide();
+ }
+ });
+
+ return isValid;
+ });
+
+ // Hide error message and reset validation on input
+ jQuery(".column-flex input").on("input", function () {
+ let errorMessage = jQuery(this).closest(".column-flex").find(".error-message");
+ jQuery(this)[0].setCustomValidity(""); // Reset browser tooltip
+ errorMessage.hide();
+ });
+
+
+ // Hide error message when user starts typing
+ jQuery(".column-flex input").on("input", function () {
+ jQuery(this).closest(".column-flex").find(".error-message").hide();
+ });
+
+});
+
+function toggle_mode(mode) {
+ setCookie("mode",mode,30);
+ if ("dark" == mode)
+ {
+ //Dark mode
+ jQuery( "#toggle_mode_light" ).hide();
+ jQuery( "#toggle_mode_dark" ).show();
+ jQuery( "#mode" ).addClass("dark");
+ jQuery( "#mode" ).removeClass("light");
+ jQuery( "#piwigo-logo" ).attr("src", url_logo_dark);
+ }
+ else
+ {
+ //Light mode
+ jQuery( "#toggle_mode_dark" ).hide();
+ jQuery( "#toggle_mode_light" ).show();
+ jQuery( "#mode" ).addClass("light");
+ jQuery( "#mode" ).removeClass("dark");
+ jQuery( "#piwigo-logo" ).attr("src", url_logo_light);
+ }
+}
+
+function setCookie(cname, cvalue, exdays) {
+ const d = new Date();
+ d.setTime(d.getTime() + (exdays*24*60*60*1000));
+ let expires = "expires="+ d.toUTCString();
+ document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
+ if (cname == "lang")
+ {
+ location.reload();
+ }
+}
+
+function getCookie(cname) {
+ let name = cname + "=";
+ let decodedCookie = decodeURIComponent(document.cookie);
+ let ca = decodedCookie.split(';');
+ for(let i = 0; i
+{get_combined_scripts load='footer'}
+
+
+