Files
wp-multi/includes/login-url.php
T
2026-08-14 07:59:43 +00:00

213 lines
8.3 KiB
PHP
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.
<?php
/**
* WP Multi Modul: Custom Login-URL
*
* Automatisch aus wp-multi.php ausgelagert. Wird über den Loader in
* wp-multi.php eingebunden (nur wenn das WP Multi Toolkit aktiv ist).
*/
if (!defined('ABSPATH')) { exit; }
/*
* Custom Login-URL — Admin-Panel-Adresse ändern (versteckt wp-admin / wp-login.php)
*
* Ersetzt die Standard-Login-Adresse durch einen eigenen Slug, z. B. /team/.
* Standardmäßig DEAKTIVIERT (leerer Slug), damit ohne bewusste Aktivierung
* nichts an der Erreichbarkeit des Backends geändert wird.
*/
// Liefert den konfigurierten Login-Slug (leer = Feature aus)
function wp_multi_login_slug() {
$slug = get_option('wp_multi_login_slug', '');
return is_string($slug) ? trim($slug, '/') : '';
}
// Feature ist nur aktiv, wenn ein Slug gesetzt ist UND Permalinks aktiv sind
function wp_multi_login_active() {
return wp_multi_login_slug() !== '' && get_option('permalink_structure') && !is_multisite();
}
// Vollständige neue Login-URL
function wp_multi_login_new_url($scheme = null) {
return user_trailingslashit(home_url('/', $scheme) . wp_multi_login_slug());
}
// Pfad-Anteil (ohne Domain) der Home-URL, z. B. "" oder "/blog"
function wp_multi_login_home_path() {
return untrailingslashit((string) parse_url(home_url(), PHP_URL_PATH));
}
// Sendet eine echte 404-Antwort und beendet die Ausführung (verstecktes Login)
function wp_multi_login_die_404() {
status_header(404);
nocache_headers();
if (function_exists('wp_die')) {
// Nutze die Theme-404 wenn möglich, sonst schlichte Meldung
wp_die(__('Seite nicht gefunden.', 'wp-multi'), '404', array('response' => 404));
}
exit;
}
// Ersetzt "wp-login.php" in generierten URLs durch den eigenen Slug
function wp_multi_login_filter_url($url, $scheme = null) {
if (strpos($url, 'wp-login.php') === false) {
return $url;
}
if (is_ssl()) {
$scheme = 'https';
}
$query = parse_url($url, PHP_URL_QUERY);
$args = array();
if ($query) {
parse_str($query, $args);
}
$new = wp_multi_login_new_url($scheme);
if (!empty($args)) {
// add_query_arg kodiert selbst; parse_str liefert bereits dekodierte Werte.
$new = add_query_arg($args, $new);
}
return $new;
}
function wp_multi_login_filter_site_url($url, $path, $scheme, $blog_id = null) {
return wp_multi_login_filter_url($url, $scheme);
}
function wp_multi_login_filter_wp_redirect($location) {
return wp_multi_login_filter_url($location);
}
// Registriert die Filter und den Request-Handler, sobald WordPress geladen ist
function wp_multi_login_init() {
if (!wp_multi_login_active()) {
return;
}
add_filter('site_url', 'wp_multi_login_filter_site_url', 10, 4);
add_filter('network_site_url', 'wp_multi_login_filter_site_url', 10, 4);
add_filter('wp_redirect', 'wp_multi_login_filter_wp_redirect', 10, 1);
add_filter('login_url', 'wp_multi_login_filter_wp_redirect', 10, 1);
add_filter('logout_url', 'wp_multi_login_filter_wp_redirect', 10, 1);
add_filter('lostpassword_url', 'wp_multi_login_filter_wp_redirect', 10, 1);
add_filter('register_url', 'wp_multi_login_filter_wp_redirect', 10, 1);
}
add_action('plugins_loaded', 'wp_multi_login_init', 1);
// Fängt die eingehende Anfrage ab: geheimer Slug lädt das Login, wp-login.php/wp-admin werden versteckt
function wp_multi_login_handle_request() {
if (!wp_multi_login_active()) {
return;
}
// Systemendpunkte niemals blockieren
if ((defined('DOING_AJAX') && DOING_AJAX) || (defined('DOING_CRON') && DOING_CRON) || (defined('REST_REQUEST') && REST_REQUEST)) {
return;
}
$uri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
$path = untrailingslashit((string) parse_url($uri, PHP_URL_PATH));
$home_path = wp_multi_login_home_path();
$login_path = $home_path . '/' . wp_multi_login_slug();
// 1) Aufruf des geheimen Slugs → echtes wp-login.php ausliefern
if ($path === $login_path) {
$GLOBALS['pagenow'] = 'wp-login.php';
require_once ABSPATH . 'wp-login.php';
exit;
}
// 2) Direkter Aufruf von wp-login.php (nicht über den Slug) → verstecken
if (strpos($uri, 'wp-login.php') !== false) {
wp_multi_login_die_404();
}
// 3) Der gesamte /wp-admin-Bereich für nicht eingeloggte Besucher → verstecken,
// statt zum versteckten Login weiterzuleiten. admin-ajax.php und admin-post.php
// bleiben ausdrücklich erreichbar (auch für Gäste / nopriv-Aktionen).
if (!is_user_logged_in()) {
$admin_path = $home_path . '/wp-admin';
$in_admin = ($path === $admin_path || strpos($path, $admin_path . '/') === 0);
$is_endpoint = (strpos($uri, 'admin-ajax.php') !== false || strpos($uri, 'admin-post.php') !== false);
if ($in_admin && !$is_endpoint) {
wp_multi_login_die_404();
}
}
}
add_action('wp_loaded', 'wp_multi_login_handle_request');
// Einstellung registrieren (mit Sanitisierung gegen reservierte Slugs)
function wp_multi_login_register_setting() {
register_setting('wp_multi_login_url_group', 'wp_multi_login_slug', array(
'type' => 'string',
'sanitize_callback' => 'wp_multi_login_sanitize_slug',
'default' => '',
));
}
add_action('admin_init', 'wp_multi_login_register_setting');
function wp_multi_login_sanitize_slug($value) {
$value = sanitize_title(trim((string) $value, '/'));
$reserved = array('wp-admin', 'wp-login', 'wp-content', 'wp-includes', 'admin-ajax', 'admin-post', 'wp-json', 'index');
if (in_array($value, $reserved, true)) {
add_settings_error('wp_multi_login_slug', 'reserved', __('Dieser Slug ist reserviert und kann nicht verwendet werden.', 'wp-multi'));
return '';
}
return $value;
}
// Admin-Seite "Login-URL"
function wp_multi_login_url_page() {
if (!current_user_can('manage_options')) {
wp_die(__('Zugriff verweigert.', 'wp-multi'));
}
$slug = wp_multi_login_slug();
$pretty = (bool) get_option('permalink_structure');
wpmt_admin_page_open(
__('Login-URL', 'wp-multi'),
__('Eigene Adresse für das Login / Admin-Panel festlegen', 'wp-multi')
);
if (is_multisite()) {
wpmt_admin_notice('error', __('Dieses Feature ist in einem Multisite-Netzwerk nicht verfügbar.', 'wp-multi'));
wpmt_admin_page_close();
return;
}
if (!$pretty) {
wpmt_admin_notice('warning', __('Für dieses Feature müssen „hübsche Permalinks" aktiviert sein (Einstellungen → Permalinks, nicht „Einfach"). Solange das nicht der Fall ist, bleibt die Login-URL unverändert.', 'wp-multi'));
}
wpmt_admin_notice('warning', __('Achtung: Merke dir die neue Adresse gut! Wenn du sie vergisst, kommst du nicht mehr ins Backend und musst das Feld per Datenbank oder FTP zurücksetzen. Leeres Feld = Standard-Login (/wp-login.php) bleibt aktiv.', 'wp-multi'));
if ($slug && $pretty) {
wpmt_admin_notice('success', sprintf(
__('Aktive Login-Adresse: %s', 'wp-multi'),
'<a href="' . esc_url(wp_multi_login_new_url()) . '"><strong>' . esc_html(wp_multi_login_new_url()) . '</strong></a>'
));
}
wpmt_admin_card_open(__('Einstellung', 'wp-multi'));
?>
<form method="post" action="options.php">
<?php settings_fields('wp_multi_login_url_group'); ?>
<div class="wpm-field">
<label class="wpm-field__label" for="wp_multi_login_slug"><?php esc_html_e('Login-Slug', 'wp-multi'); ?>
<small class="wpm-field__hint"><?php esc_html_e('Nur Kleinbuchstaben, Zahlen und Bindestriche. Leer lassen = deaktiviert.', 'wp-multi'); ?></small>
</label>
<div>
<span style="color:var(--wpm-text-muted);"><?php echo esc_html(trailingslashit(home_url('/'))); ?></span>
<input type="text" id="wp_multi_login_slug" name="wp_multi_login_slug" value="<?php echo esc_attr($slug); ?>" placeholder="team" style="max-width:220px; display:inline-block;">
</div>
</div>
<?php submit_button(__('Speichern', 'wp-multi')); ?>
</form>
<?php
wpmt_admin_card_close();
wpmt_admin_page_close();
}