5|Q*{x+=&6yyU!q1z@;uK;MC
z31PS+Cj|0%Y)3BPjq;ar?*3>j)~wuRnzzRH+o2!=F0y4?1&B~@w0i`lt~2?|4JfdN
z$y8QXF3)OW>EL&XhSol{qvp_$hw|~4T
ziF>zGt@GRNP!a}?V@xA__w=*eVJO$LD%&*NV^fKcj$E(@t;*_)i90dE>!IgSB6(e!
z!T}a@w19`{CERWm_(0aFJOL@N$V337`5fAp@)XgKytx=m*oF8=Me!j7)+6)l8cz0?
zjQ&bLo3YPq!kYO$yAas&
z7XQE|H=dKWJfN`6c4Ew%?IthNdHrVpWJtO3qh7e}eC;Bd58)x?giTub+_De(Z@ob|
z@!u~Nsu#$n+mysRq@#_mENT&nM>#&^%o#MI1kvL&LWGqL0zr8_q+AXlX3A9NCo{{S
z2g)Msu;!#L>YJ!VyPgKa-hKG+j66@er~?s)Y9|enqP0*lDrH2i=g{~NAT1>ju5qX?
z)vQT978oe4#%W?e?*+lNS&_9GLhD1YzQt-(AGy$g?QPv!y(X)4#X-EgwMu6=tcGpG
zhG2O@t~uvHpMtZsV)TJij4fG5xeBJH;qggw`dBP8f>;P4aHu2=Iq$Z_5yLjtS?ix1
z+yjI=Qly4zuum=Ifaj7UaSA^5?J^nyBf1fP
zf+dKr%QP$MMz4qnBFloJkC)~^6za)%k3?n}tqvtPL1>l{8g;iSb7Nu!g|b;djU(1n
z1@Y;@3(im9bBFH*p+hCGsjuqBuVc!>7xb74
zz_bD~Bq^rfb08(nGHbN)_M*7f1JNOEp!>g3P;=K1*>UEz@xUsriIFmhHBVo7ji
zhiyloNpgmnpoO}HJS%9`@M3CQ9>qX_yOu>29Ib~ttIAb2wLZfduvj#15g9Xek63X@
zemEQ;?Ha#?9lG0dYt49Xol(u8MDHuNJ-s4U_HQ(+6!y#^-fZlf-FsH2#a$=AGNt(c
z)!!;xGj{0mEXwvz2SNz{kSXR}UYjHj{E}LSEF85vSDzK4cbzEGg?bq?(h%|b5V@MG
zjd;MWv0%h|ttPW_m8zYh0)oJ`Q8^QLBM^*h^NIVaD&~gjT%L8{-Y!d(`)OX6gb^zJ
zITk}0lR{24qL1xsJ+i0=gVPf;vPEPyw%~}y
zw@(U8Q9OE-Oc(4Cs%+6U)W#TgY@Sg~sM<DHOq3KtDNzzf#+a<;rZFD}hDd`kj<%9_WN2Gg@D7dd48#6S7!6D#u
z?J($pNOUx%F^e8x)X#4q#i-R8YHwQSpm*}f6Y4KdZA4$LnOch7fEYgkZBlKUDx9Wn}WyC+l>Rgu^}1-J9vGxo}Xz3{E>oN9K|
zIOtHPYdgZ7lauH4IfuhOBGDc`abv^rcF`Y&*_HGLJldlC
ziw+x&wFKkM!4}cd@VjeMEXpvmwjGL2fG_Q2rK7^wO{c?Q$2QD*OT(W?&0@T8wg?
zRW8YSHvVE7VgBaVuJeCs00S&~Od*w~ZX8j#BO_h2dm>pl3^jMpjMC$=SefT=cA#j}
z3yjb8!Q|dB6=SpAGj)K%B@8C;1%?%b14)U8?Vc`4&?JGuMQW(b;1aW$r}XSR9II&6
zY=9NWf8AVxZaP6TKm=+0EISbA|J@R#_^q3uG$F)qrB
z-}e;)%~l0fD3|IFwbnjS%@k*vm^JlgwR=LAir5dXzVzGOla(AvCsJk^wEdK&8>MyO
zD`M=c&cYT8YIp1{R^o`tZ~nGuFWvnz7N2u5baW2j-u0
z2J+^0w#cAyOm5JA=>ve#?CX|qV%$mZO)ucDV#*lVNM89}N9Znl%8=(58nvm$#5HqH
zREoh=NHxm5c<_ks^3w}?zqB%|^IbDqVsoGFqNDPiSgW}Q
z=_%CgeQFC)%JJF*18u)dWR$H-`KP7S~2b|lcG2G9}h#m{cG~#Jrm2{pOY0~h9G#PFMeCM1jR18
za7Ys20T0}78Px#(sHOC
zOzN65hjdVF5mb#GVV7<0r*lPHg*vPxal}?-atnle5Q;OyK;cEEu?%Xg9(m$A-F;A`
zE4mhfyxd@o)a)>z|H2e>?B{d^0i?YIihV2hUNu+IcMD0ZiYfFp62*E@+Bgs^HCkd`
zRIEXg5e?jm0(j|ja3S2q2t=p>tK&@b$piPk%@PgUkn`O;bY={qLb1>AacC|=HmPys
zJoD7fv;qujv-Mh|6Khz6s^B68BGZ|^D(>@fj1-1uPbz}ofUFdd{6p4usy{+ywO@T$
z6om_r1B2HV9Fd3ayj9IU)Er>~sVmAP4-m-4kcA|uQhm3nt;C*aw8OJu^o{nR#A%2z
zRZKTE4^QhxWYw!D{V4KI7*nd&8`7Dn3yo8%ZEu|!^GLEj9laSuf?Uu*gu-#Ld#WK{
z=dYcM@+OnXIGFUI59+(42T^DFS?G1TDP^=u$SsTvuknnz;<8nyW+wR)f?1QJNhRQE
z5C&AzEjWHRoz-*_md9joL6DB~RD9%>JxkI{uHF6EkWiE(N$7>l5sy8oq@Wc7g)Wfo
zh1C(Uo~u~QC1tOHH=`JJ3x#CDC#E*<#KcP$CD$x{%!Yl1iUaXPV`2d384D|v@S)~HeQ`nVCwfffDYIF+}ssQP+Ll^Sm*=7v9K|Dgt)Mw%^
z!i==3+?_D#3?+`@UKR@?SVu2{pZXS2l=~SCXzb*^W;*eW3t!^!&8(t{%xc1^krhkL
zmD%FDWlR8f`^kXZTfu8iRYha>YSN?Ofgac}&T=9&u)AQ0h&FYrX&
zpp9zX=J~gWd$Fdm0C|&;`!d8sh)<}(
zwfSq35mZv82P%{%Vl9@f$tU>
literal 0
HcmV?d00001
diff --git a/lang/bdp-kompass_de_DE.po b/lang/bdp-kompass_de_DE.po
new file mode 100644
index 0000000..0ad6ab1
--- /dev/null
+++ b/lang/bdp-kompass_de_DE.po
@@ -0,0 +1,111 @@
+msgid "Extended Security"
+msgstr "Erweiterte Sicherheit"
+
+msgid "Save changes"
+msgstr "Änderungen speichern"
+
+msgid "All settings are saved."
+msgstr "Die Einstellungen wurden gespeichert."
+
+msgid "Disable xmlrpc"
+msgstr "xmlrpc deaktivieren"
+
+msgid "By introducing the REST API in WordPress, xmlrpc. However, php is no longer needed to communicate outside of WordPress, which is why there is no longer any reason to leave it active or use it. Therefore, for the security of your site, it is better to deactivate or delete it."
+msgstr "Durch die Einführung der REST API in WordPress wird xmlrpc. php jedoch nicht mehr benötigt, um außerhalb von WordPress zu kommunizieren, weshalb es hier keinen Grund mehr gibt, diese aktiv zu lassen oder zu nutzen. Deshalb ist es für die Sicherheit deiner Seite besser, diese zu deaktivieren oder zu löschen."
+
+msgid "Disable Authorscan"
+msgstr "Autorenscan deaktivieren"
+
+
+msgid "The author page in WordPress typically displays a list of all posts by a specific author on your website. Unfortunately, Google also records the page and to prevent this, we can deactivate the author page. When a visitor clicks on an name of an author, they are redirected to the author page. This page contains a list of posts written by this author, as well as possibly a brief description of the author and a photo. It is also possible to record which user names have been created."
+msgstr "Die Autorenseite in WordPress zeigt normalerweise eine Liste aller Beiträge eines bestimmten Autors auf deiner Website an. Google erfasst die Seite auch leider und um das zu verhindern, können wir die Autorenseite deaktivieren. Wenn ein Besucher auf den Namen eines Autors klickt, wird er auf die Autorenseite weitergeleitet. Diese Seite enthält eine Liste der Beiträge, die von diesem Autor verfasst wurden, sowie möglicherweise eine kurze Beschreibung des Autors und ein Foto. Auch ist es darüber möglich zu erfassen, welche Nutzernamen angelegt sind."
+
+msgid "Disable scripting in /wp-content/uploads/"
+msgstr "Scripting in /wp-content/uploads/ deaktivieren"
+
+msgid "Disabling scripting in /wp-content/uploads/ can be a security measure to protect your WordPress website from potential threats. The /wp-content/uploads folder is usually the default folder where WordPress stores uploaded files, such as images, videos, and other media files."
+msgstr "Das Deaktivieren von Scripting in /wp-content/uploads/ kann eine Sicherheitsmaßnahme sein, um dein WordPress-Website vor potenziellen Bedrohungen zu schützen. Der Ordner /wp-content/uploads ist normalerweise der Standardordner, in dem WordPress hochgeladene Dateien, wie Bilder, Videos und andere Mediendateien, speichert."
+
+msgid "Block access to potentially sensitive files"
+msgstr "Zugriff auf potenziell sensible Dateien blockieren"
+
+msgid "This setting prohibits access to configuration files and log files"
+msgstr "Diese Einstellung verbietet den Zugriff auf Konfigurationsdateien sowie Log-Dateien"
+
+msgid "Disable file editor in WP Dashboard"
+msgstr "Dateieditor im WP Dashboard deaktivieren"
+
+msgid "This is a security feature that allows you to prevent users from editing theme and plugin files directly from the WordPress dashboard. This can be useful for a variety of reasons, including preventing accidental code changes and protecting your website from malicious attacks."
+msgstr "Hierbei handelt es sich um eine Sicherheitsfunktion, mit der Sie verhindern können, dass Benutzer Theme- und Plugin-Dateien direkt über das WordPress-Dashboard bearbeiten können. Dies kann aus verschiedenen Gründen nützlich sein, unter anderem um versehentliche Änderungen am Code zu verhindern und Ihre Website vor böswilligen Angriffen zu schützen."
+
+msgid "Disable script concatenation"
+msgstr "Skriptverkettung deaktivieren"
+
+msgid "Disabling script concatenation in the WordPress admin panel is a simple and effective way to enhance performance. However, it is crucial to carefully consider the impact of this change, as it may increase the number of HTTP requests, potentially affecting loading times"
+msgstr "Das Deaktivieren der Skriptverkettung im WordPress-Admin-Panel ist eine einfache und effektive Möglichkeit, die Leistung zu verbessern. Es ist jedoch wichtig, die Auswirkungen dieser Änderung sorgfältig abzuwägen, da sie die Anzahl der HTTP-Anfragen erhöhen und sich möglicherweise auf die Ladezeiten auswirken kann."
+
+msgid "Disable script execution in include dir"
+msgstr "Skriptausführung im Include-Verzeichnis deaktivieren"
+
+msgid "Limiting script execution in specific directories can improve security by preventing potentially malicious scripts from running in critical parts of the WordPress system. This is particularly important to prevent attacks such as Cross-Site Scripting (XSS), which inject malicious code into website content."
+msgstr "Das Begrenzen der Skriptausführung in bestimmten Verzeichnissen kann die Sicherheit verbessern, indem potenziell schädliche Skripte daran gehindert werden, in kritischen Teilen des WordPress-Systems ausgeführt zu werden. Dies ist besonders wichtig, um Angriffe wie Cross-Site Scripting (XSS) zu verhindern, bei denen schädlicher Code in Webseiteninhalte eingeschleust wird."
+
+msgid "Change site keys"
+msgstr "Seitenschlüssel erneuern"
+
+msgid "An error occured connecting api.wordpress.org"
+msgstr "Beim Kontaktieren von api.wordpress.org trat ein Fehler auf"
+
+msgid "The site keys were updated successfully."
+msgstr "Die Seitenschlüssel wurden erneuert."
+
+msgid "Protect WP detected missing security settings"
+msgstr "Protect WP hat fehlende Sicherheitseinstellungen festgestellt"
+
+msgid "Protect WP has detected that advanced security settings are missing. You can update the settings directly in the dashboard."
+msgstr "Protect WP hat festgestellt, dass erweiterte Sicherheitseinstellungen fehlen. Du kannst die Einstellungen direkt im Dashboard aktualisieren."
+
+msgid "Protect WP - security settings"
+msgstr "Protect WP - Sicherheitseinstellungen"
+
+msgid "Prohibit access from unwanted bots"
+msgstr "Zugriff von ungewollten Bots verbieten"
+
+msgid "Excluding specific bots from a WordPress website provides improved security by reducing potentially malicious activity and security risks, optimizes resource consumption and site performance, protects against content theft and duplicate content, enables more precise control of traffic, and promotes more effective SEO -Optimization by reducing irrelevant bots, ultimately leading to a safer, more efficient and better performing website."
+msgstr "Das Ausschließen bestimmter Bots von einer WordPress-Website bietet eine verbesserte Sicherheit, indem potenziell bösartige Aktivitäten und Sicherheitsrisiken reduziert werden, optimiert den Ressourcenverbrauch und die Website-Performance, schützt vor Inhaltsdiebstahl und Duplicate Content, ermöglicht eine genauere Kontrolle des Datenverkehrs und fördert eine effektivere SEO-Optimierung durch die Reduzierung nicht relevanter Bots, was letztendlich zu einer sichereren, effizienteren und besser performenden Website führt."
+
+msgid "Bot Detection Database"
+msgstr "Datenbank zur Bot-Erkennung"
+
+msgid "Registered bots"
+msgstr "Vorhandene Bots"
+
+msgid "Add more bots"
+msgstr "Weitere Bots hinzufügen"
+
+msgid "Leave blank in order to delete"
+msgstr "Zum Löschen leer lassen"
+
+msgid "Please use line breaks to enter multiple bots"
+msgstr "Bitte Zeilenumbruch verwenden, um mehrere Bots einzutragen"#
+
+msgid "Bot Detection Database updated successfully."
+msgstr "Die Datenbank zur Bot-Erkennung wurde erfolgreich aktualisiert."
+
+msgid "Disable directory listing"
+msgstr "Auflistung von Verzeichnissen deaktivieren"
+
+msgid "Directory listing should be disabled to ensure the security and privacy of a website. When Directory Listing is enabled, this allows users to directly access the contents of directories on a web server without having to specify a specific file. This can expose sensitive information such as directory structures, internal files and scripts, posing a potential security risk. Disabling Directory Listing prevents users from accessing this sensitive information, thereby providing an additional layer of security for the website."
+msgstr "Das Auflisten von Verzeichnissen sollte deaktiviert werden, um die Sicherheit und Privatsphäre einer Website zu gewährleisten. Wenn Directory Listing aktiviert ist, ermöglicht dies Benutzern den direkten Zugriff auf die Inhalte von Verzeichnissen auf einem Webserver, ohne dass eine spezifische Datei angegeben werden muss. Dies kann sensible Informationen wie Verzeichnisstrukturen, interne Dateien und Skripte offenlegen, was ein potenzielles Sicherheitsrisiko darstellt. Durch das Deaktivieren von Directory Listing wird verhindert, dass Benutzer auf diese sensiblen Informationen zugreifen können, und bietet somit eine zusätzliche Sicherheitsschicht für die Website."
+
+msgid "Disable debug output"
+msgstr "Debug-Ausgaben deaktivieren"
+
+msgid "Debugging should be disabled to protect sensitive information about the internal structure and potential security vulnerabilities of a a WordPress website from potential attackers. When debugging is enabled, error messages and warnings are displayed directly on the website, which can provide attackers with valuable information about the configuration of the website and possible vulnerabilities."
+msgstr "Debugging sollte deaktiviert werden, um sensible Informationen über die interne Struktur und mögliche Sicherheitslücken einer WordPress-Website vor potenziellen Angreifern zu schützen. Wenn Debuggin aktiviert ist, werden Fehlermeldungen und Warnungen direkt auf der Webseite angezeigt, was Angreifern wertvolle Informationen über die Konfiguration und mögliche Schwachstellen der Website geben kann. "
+
+msgid "Change Login URL"
+msgstr "Login-URL ändern"
+
+msgid "Changing the default login URL of WordPress is advisable to enhance the security of your website. By default, WordPress login URLs is /wp-admin or /wp-login.php, which are easily guessed by hackers and facilitate attacks such as brute-force attacks. Changing the login URL to something unique and difficult to guess increases security since potential attackers will struggle to find the correct URL. This can help protect your website from unauthorized access and other malicious activities."
+msgstr "Es ist ratsam, die Standard-Login-URL von WordPress zu ändern, um die Sicherheit deiner Website zu erhöhen. Standardmäßig lautet die Login-URL von WordPress /wp-admin oder /wp-login.php, was für Hacker leicht zu erraten ist und Angriffe wie Brute-Force-Attacken erleichtern kann. Durch Ändern der Login-URL auf etwas Einzigartiges und schwer zu erraten, erhöhst du die Sicherheit, da potenzielle Angreifer Schwierigkeiten haben werden, die richtige URL zu finden. Dies kann helfen, deine Website vor unautorisiertem Zugriff und anderen böswilligen Aktivitäten zu schützen."
\ No newline at end of file
diff --git a/modules/security/classes/Security.class.php b/modules/security/classes/Security.class.php
index 8c252e6..60d38e6 100644
--- a/modules/security/classes/Security.class.php
+++ b/modules/security/classes/Security.class.php
@@ -4,18 +4,15 @@ namespace Bdp\Modules\Security;
use ZipArchive;
-
-
class Security
{
- public const required_security_plugins = [
- 'wps_hide_login' => ['downloadUrl' => 'https://downloads.wordpress.org/plugin/wps-hide-login.1.9.10.zip'],
- 'limit-login-attempts-reloaded' => ['downloadUrl' => 'https://downloads.wordpress.org/plugin/limit-login-attempts-reloaded.2.25.27.zip']];
-
+ public const required_security_plugins = [];
public const delete_plugins = [
'akismet/akismet.php',
- 'hello.php'
+ 'hello.php',
+ 'wps_hide_login',
+ 'limit-login-attempts-reloaded'
];
public static function setup()
@@ -27,9 +24,17 @@ class Security
}
}
- $loginUrl = get_option('whl_page', 'bdp_login');
- update_option('whl_page', $loginUrl);
-
+ $loginUrl = get_option('whl_page', null) ?? 'bdp-login';
+ enable_option_rewrite_url($loginUrl);
+ enable_option_disable_xmlrpc();
+ enable_option_block_authorscan();
+ enable_option_block_execution_in_uploads();
+ enable_option_prohibit_special_files();
+ enable_option_file_editor();
+ enable_option_disable_conatenation();
+ enable_option_secure_include_dir();
+ enable_option_prohibit_bot_access();
+ enable_option_block_directory_listing();
}
public static function deletePlugins() {
@@ -37,6 +42,67 @@ class Security
delete_plugins(self::delete_plugins);
}
+ public static function ProhibitBots() {
+ $botList = get_prohibitedbot_list();
+
+ if (!is_bot_access_prohibited() || count($botList) == 0) {
+ return;
+ }
+
+ foreach ($botList as $botListEntry) {
+ if (stripos($_SERVER['HTTP_USER_AGENT'], $botListEntry) !== false) {
+ status_header(403);
+ die();
+ }
+ }
+ }
+
+
+ public static function protectAuthorScan()
+ {
+ global $wp;
+
+ if (str_starts_with($wp->request, 'author/') && is_authorscan_blocked()) {
+ status_header(403);
+ die();
+ }
+ }
+
+ public static function SetPageFilters() {
+ global $wp;
+
+ if (str_contains($_SERVER['REQUEST_URI'], 'wp-login.php?action=logout')) {
+ return;
+ }
+
+ add_action('template_redirect', [Security::class, 'protectAuthorScan']);
+ Security::protectLoginSecurity();
+ }
+
+ public static function protectLoginSecurity() {
+ $hideLogin = is_login_rewritten();
+
+ if (null === $hideLogin) {
+ return;
+ }
+
+ if ( str_contains( $_SERVER['REQUEST_URI'], 'wp-login.php' ) && ! isset( $_POST['redirect_to'] ) && $_POST['redirect_to'] !== 'interner-bereich' ) {
+ wp_redirect( home_url() );
+ die();
+ }
+
+ if ( str_contains( $_SERVER['REQUEST_URI'], $hideLogin ) !== false ) {
+ $user_login = '';
+ $_REQUEST['redirect_to'] = 'interner-bereich';
+ require_once 'wp-login.php';
+ die();
+ }
+
+ if ( str_contains( $_SERVER['REQUEST_URI'], 'interner-bereich' ) !== false ) {
+ wp_redirect( '/wp-admin' );
+ die();
+ }
+ }
public static function installSecurityPlugin(string $pluginSlug, string $downloadUrl) : bool
{
diff --git a/modules/security/includes/settings_reader.php b/modules/security/includes/settings_reader.php
new file mode 100644
index 0000000..d11b85d
--- /dev/null
+++ b/modules/security/includes/settings_reader.php
@@ -0,0 +1,79 @@
+
+
+
+ = __('All settings are saved.', BDP_LV_PLUGIN_SLUG); ?>
+
+
+
+
+
+ = __('An error occured connecting api.wordpress.org', BDP_LV_PLUGIN_SLUG); ?>
+
+
+
+
+
+ = __('The site keys were updated successfully.', BDP_LV_PLUGIN_SLUG); ?>
+
+
+ = __('Bot Detection Database', BDP_LV_PLUGIN_SLUG); ?>
+
+
= __('Registered bots', BDP_LV_PLUGIN_SLUG); ?>
+
+
+
+ = __('Leave blank in order to delete', BDP_LV_PLUGIN_SLUG); ?>
+
+
+
+
+
= __('Add more bots', BDP_LV_PLUGIN_SLUG); ?>
+
+
+
+
+
+
diff --git a/modules/security/internal/index.php b/modules/security/internal/index.php
index aeb4f8c..1712cae 100644
--- a/modules/security/internal/index.php
+++ b/modules/security/internal/index.php
@@ -1,6 +1,6 @@
';
-echo 'Erweiterte Sicherheitseinstellungen ';
+echo 'Erweiterte Sicherheitseinstellungen ';
if (isset($_POST['submit'])) {
echo 'Die Einstellungen wurden gespeichert.
';
update_option('whl_page', $_POST['login_url']);
@@ -9,13 +9,12 @@ if (isset($_POST['submit'])) {
diff --git a/modules/security/internal/site-health-tab.php b/modules/security/internal/site-health-tab.php
new file mode 100644
index 0000000..b7b3014
--- /dev/null
+++ b/modules/security/internal/site-health-tab.php
@@ -0,0 +1,118 @@
+= __('Extended Security', BDP_LV_PLUGIN_SLUG); ?>
+
+
+ type="checkbox" id="sec_mod_1" name="security_settings[]" value="option_disable_xmlrpc" />
+
+ = __('Disable xmlrpc', BDP_LV_PLUGIN_SLUG); ?>
+
+ = __('By introducing the REST API in WordPress, xmlrpc. However, php is no longer needed to communicate outside of WordPress, which is why there is no longer any reason to leave it active or use it. Therefore, for the security of your site, it is better to deactivate or delete it.', BDP_LV_PLUGIN_SLUG); ?>
+
+
+
+
+ type="checkbox" id="sec_mod_2" name="security_settings[]" value="option_block_authorscan" />
+
+ = __('Disable Authorscan', BDP_LV_PLUGIN_SLUG); ?>
+
+ = __('The author page in WordPress typically displays a list of all posts by a specific author on your website. Unfortunately, Google also records the page and to prevent this, we can deactivate the author page. When a visitor clicks on an name of an author, they are redirected to the author page. This page contains a list of posts written by this author, as well as possibly a brief description of the author and a photo. It is also possible to record which user names have been created.', BDP_LV_PLUGIN_SLUG); ?>
+
+
+
+
+ type="checkbox" id="sec_mod_3" name="security_settings[]" value="option_block_execution_in_uploads" />
+
+ = __('Disable scripting in /wp-content/uploads/', BDP_LV_PLUGIN_SLUG); ?>
+
+ = __('Disabling scripting in /wp-content/uploads/ can be a security measure to protect your WordPress website from potential threats. The /wp-content/uploads folder is usually the default folder where WordPress stores uploaded files, such as images, videos, and other media files.', BDP_LV_PLUGIN_SLUG); ?>
+
+
+
+
+ type="checkbox" id="sec_mod_4" name="security_settings[]" value="option_prohibit_special_files" />
+
+ = __('Block access to potentially sensitive files', BDP_LV_PLUGIN_SLUG); ?>
+
+ = __('This setting prohibits access to configuration files and log files', BDP_LV_PLUGIN_SLUG); ?>
+
+
+
+
+
+ type="checkbox" id="sec_mod_5" name="security_settings[]" value="option_file_editor" />
+
+ = __('Disable file editor in WP Dashboard', BDP_LV_PLUGIN_SLUG); ?>
+
+ = __('This is a security feature that allows you to prevent users from editing theme and plugin files directly from the WordPress dashboard. This can be useful for a variety of reasons, including preventing accidental code changes and protecting your website from malicious attacks.', BDP_LV_PLUGIN_SLUG); ?>
+
+
+
+
+
+ type="checkbox" id="sec_mod_6" name="security_settings[]" value="option_disable_conatenation" />
+
+ = __('Disable script concatenation', BDP_LV_PLUGIN_SLUG); ?>
+
+ = __('Disabling script concatenation in the WordPress admin panel is a simple and effective way to enhance performance. However, it is crucial to carefully consider the impact of this change, as it may increase the number of HTTP requests, potentially affecting loading times', BDP_LV_PLUGIN_SLUG); ?>
+
+
+
+
+
+ type="checkbox" id="sec_mod_7" name="security_settings[]" value="option_secure_include_dir" />
+
+ = __('Disable script execution in include dir', BDP_LV_PLUGIN_SLUG); ?>
+
+ = __('Limiting script execution in specific directories can improve security by preventing potentially malicious scripts from running in critical parts of the WordPress system. This is particularly important to prevent attacks such as Cross-Site Scripting (XSS), which inject malicious code into website content.', BDP_LV_PLUGIN_SLUG); ?>
+
+
+
+
+
+
type="checkbox" id="sec_mod_8" name="security_settings[]" value="option_prohibit_bot_access" />
+
+ = __('Prohibit access from unwanted bots', BDP_LV_PLUGIN_SLUG); ?>
+
+ = __('Excluding specific bots from a WordPress website provides improved security by reducing potentially malicious activity and security risks, optimizes resource consumption and site performance, protects against content theft and duplicate content, enables more precise control of traffic, and promotes more effective SEO -Optimization by reducing irrelevant bots, ultimately leading to a safer, more efficient and better performing website.', BDP_LV_PLUGIN_SLUG); ?>
+ = __('Bot Detection Database', BDP_LV_PLUGIN_SLUG); ?>
+
+
+
+
+
+
+ type="checkbox" id="sec_mod_9" name="security_settings[]" value="option_block_directory_listing" />
+
+ = __('Disable directory listing', BDP_LV_PLUGIN_SLUG); ?>
+
+ = __('Directory listing should be disabled to ensure the security and privacy of a website. When Directory Listing is enabled, this allows users to directly access the contents of directories on a web server without having to specify a specific file. This can expose sensitive information such as directory structures, internal files and scripts, posing a potential security risk. Disabling Directory Listing prevents users from accessing this sensitive information, thereby providing an additional layer of security for the website.', BDP_LV_PLUGIN_SLUG); ?>
+
+
+
+
+
+ type="checkbox" id="sec_mod_10" name="security_settings[]" value="option_disable_wp_debug" />
+
+ = __('Disable debug output', BDP_LV_PLUGIN_SLUG); ?>
+
+ = __('Debugging should be disabled to protect sensitive information about the internal structure and potential security vulnerabilities of a a WordPress website from potential attackers. When debugging is enabled, error messages and warnings are displayed directly on the website, which can provide attackers with valuable information about the configuration of the website and possible vulnerabilities.', BDP_LV_PLUGIN_SLUG); ?>
+
+
+
+
+ type="checkbox" id="sec_mod_11" name="security_settings[]" value="option_rewrite_url" />
+
+ = __('Change Login URL', BDP_LV_PLUGIN_SLUG); ?>
+
+ = __('Changing the default login URL of WordPress is advisable to enhance the security of your website. By default, WordPress login URLs is /wp-admin or /wp-login.php, which are easily guessed by hackers and facilitate attacks such as brute-force attacks. Changing the login URL to something unique and difficult to guess increases security since potential attackers will struggle to find the correct URL. This can help protect your website from unauthorized access and other malicious activities.', BDP_LV_PLUGIN_SLUG); ?>
+
+ = __('Login-URL', BDP_LV_PLUGIN_SLUG) ?>: = get_site_url(); ?>/
+
+
+
+
+
+
+
+
+
+= __('Change site keys', BDP_LV_PLUGIN_SLUG); ?>
\ No newline at end of file
diff --git a/modules/security/security.php b/modules/security/security.php
index acfd2fe..e911026 100644
--- a/modules/security/security.php
+++ b/modules/security/security.php
@@ -1,21 +1,53 @@
';
+ echo '';
+ echo '';
+ return;
+ }
+
+ update_option('protect_wp_needs_attention', false);
+ if (isset($_POST['save_settings'])) {
+ $securitySettings = [];
+ if (isset($_POST['security_settings'])) {
+ $securitySettings = $_POST['security_settings'];
+ }
+ kompass_sec_save_settings($securitySettings);
+ }
+ if (isset($_GET['action']) && $_GET['action'] == 'updatesitekeys') {
+ kompass_sec_site_keys();
+ }
+
+ echo '';
+ echo '';
+ echo '
';
+ return;
+ }
}
add_action('site_health_tab_content', 'wp_example_site_health_tab_content');
From bb741539f6b99734c8a247dbc23cd0b1520ae529 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thomas=20G=C3=BCnther?=
Date: Wed, 21 Feb 2024 21:41:11 +0100
Subject: [PATCH 3/8] Update in code structure
---
includes/filters.php | 2 +-
modules/firstusage/classes/Security.class.php | 32 ++++++++++++-------
modules/security/classes/Security.class.php | 2 +-
3 files changed, 22 insertions(+), 14 deletions(-)
diff --git a/includes/filters.php b/includes/filters.php
index dce19a7..42b1702 100644
--- a/includes/filters.php
+++ b/includes/filters.php
@@ -2,7 +2,7 @@
add_action( 'plugins_loaded', 'bdp_kompass_load_plugin_textdomain' );
-register_activation_hook(__FILE__, 'bdp_plugin_install');
+register_activation_hook(BDP_LV_STARTUP_FILE, 'bdp_plugin_install');
add_action('init', 'bdp_plugin_init');
diff --git a/modules/firstusage/classes/Security.class.php b/modules/firstusage/classes/Security.class.php
index 9735d4b..da7af89 100644
--- a/modules/firstusage/classes/Security.class.php
+++ b/modules/firstusage/classes/Security.class.php
@@ -8,28 +8,36 @@ use ZipArchive;
class Security
{
- public const required_security_plugins = [
- 'wps_hide_login' => ['downloadUrl' => 'https://downloads.wordpress.org/plugin/wps-hide-login.1.9.10.zip'],
- ];
+ public const required_security_plugins = [];
public const delete_plugins = [
'akismet/akismet.php',
'hello.php',
- 'limit-login-attempts-reloaded'
+ 'limit-login-attempts-reloaded',
+ 'wps-hide-login/wps-hide-login.php'
];
public static function setup()
{
- self::deletePlugins();
- foreach (self::required_security_plugins as $pluginSlug => $pluginData) {
- if (!is_dir(WP_PLUGIN_DIR . '/' . $pluginSlug)) {
- self::installSecurityPlugin($pluginSlug, $pluginData['downloadUrl']);
- }
- }
+ self::deletePlugins();
+ foreach (self::required_security_plugins as $pluginSlug => $pluginData) {
+ if (!is_dir(WP_PLUGIN_DIR . '/' . $pluginSlug)) {
+ self::installSecurityPlugin($pluginSlug, $pluginData['downloadUrl']);
+ }
+ }
- $loginUrl = get_option('whl_page', 'bdp_login');
- update_option('whl_page', $loginUrl);
+ $loginUrl = get_option('whl_page', null) ?? 'bdp-login';
+ enable_option_rewrite_url($loginUrl);
+ enable_option_disable_xmlrpc();
+ enable_option_block_authorscan();
+ enable_option_block_execution_in_uploads();
+ enable_option_prohibit_special_files();
+ enable_option_file_editor();
+ enable_option_disable_conatenation();
+ enable_option_secure_include_dir();
+ enable_option_prohibit_bot_access();
+ enable_option_block_directory_listing();
}
diff --git a/modules/security/classes/Security.class.php b/modules/security/classes/Security.class.php
index 60d38e6..a16acfb 100644
--- a/modules/security/classes/Security.class.php
+++ b/modules/security/classes/Security.class.php
@@ -11,7 +11,7 @@ class Security
public const delete_plugins = [
'akismet/akismet.php',
'hello.php',
- 'wps_hide_login',
+ 'wps-hide-login/wps-hide-login.php',
'limit-login-attempts-reloaded'
];
From 18820c71911b9ef71ce1b25e94da9d395bceacd2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thomas=20G=C3=BCnther?=
Date: Mon, 26 Feb 2024 14:47:51 +0100
Subject: [PATCH 4/8] Protection of WordPress logins
---
assets/password.js | 43 +++
assets/security.css | 12 +
bdp-kompass.php | 12 +
includes/action_caller.php | 23 ++
includes/frontend-functions.php | 34 ++-
includes/pre_requires.php | 1 +
includes/setup.php | 12 +-
includes/spl.php | 32 ++
.../Controllers/LoginHandler.php | 282 ++++++++++++++++++
.../Controllers/OptionsPage.php | 130 ++++++++
.../Views/checkbox-option.php | 29 ++
.../LimitLoginAttempts/Views/radio-option.php | 35 +++
.../LimitLoginAttempts/Views/tab-control.php | 18 ++
.../LimitLoginAttempts/Views/text-element.php | 7 +
.../includes/block-and-allow-list-form.php | 56 ++++
.../includes/gui_elements.php | 116 +++++++
.../includes/validators.php | 64 ++++
.../includes/password_strength_rules.php | 10 +
18 files changed, 903 insertions(+), 13 deletions(-)
create mode 100644 assets/password.js
create mode 100644 includes/action_caller.php
create mode 100644 includes/spl.php
create mode 100644 modules/LimitLoginAttempts/Controllers/LoginHandler.php
create mode 100644 modules/LimitLoginAttempts/Controllers/OptionsPage.php
create mode 100644 modules/LimitLoginAttempts/Views/checkbox-option.php
create mode 100644 modules/LimitLoginAttempts/Views/radio-option.php
create mode 100644 modules/LimitLoginAttempts/Views/tab-control.php
create mode 100644 modules/LimitLoginAttempts/Views/text-element.php
create mode 100644 modules/LimitLoginAttempts/includes/block-and-allow-list-form.php
create mode 100644 modules/LimitLoginAttempts/includes/gui_elements.php
create mode 100644 modules/LimitLoginAttempts/includes/validators.php
create mode 100644 modules/PasswordStrength/includes/password_strength_rules.php
diff --git a/assets/password.js b/assets/password.js
new file mode 100644
index 0000000..8796982
--- /dev/null
+++ b/assets/password.js
@@ -0,0 +1,43 @@
+jQuery(document).ready(function($) {
+ $( "" +
+ php_vars.password_too_short_text + " " ).insertBefore( ".submit" );
+
+ $("#password_too_short").css('display', 'none');
+
+ $(document).on('DOMSubtreeModified', '#pass-strength-result', function() {
+ var strengthMeter = $(this).attr('class');
+ var allowedStrengths = php_vars.allowed_strengths;
+
+ $( "[name='pw_weak']" ).css('visibility', 'hidden');
+ $( '.pw-weak' ).css('visibility', 'hidden');
+ $( '#pw-weak-text-label' ).css('visibility', 'hidden');
+
+ if (strengthMeter !== '') {
+ if (allowedStrengths.includes(strengthMeter)) {
+ $("[name='pw_weak']").prop("checked", true);
+ $("[name='submit']").css('display', 'inline');
+ $('#createusersub').css('display', 'inline');
+ $('submit').onclick = function() {
+ $('your-profile').submit();
+ };
+ $("#createusersub").onclick = function() {
+ $('createuser').submit();
+ };
+
+ $("#password_too_short").css('display', 'none');
+ } else {
+ $("#createusersub").css('display', 'none');
+ $("[name='submit']").prop("disabled", true);
+ $("[name='pw_weak']").prop("checked", false);
+ $("[name='submit']").css('display', 'none');
+ $('submit').onclick = function() {
+ return false;
+ };
+ $("#createusersub").onclick = function() {
+ return false;
+ };
+ $("#password_too_short").css('display', 'inline');
+ }
+ }
+ });
+});
\ No newline at end of file
diff --git a/assets/security.css b/assets/security.css
index 5e213a9..46884dd 100644
--- a/assets/security.css
+++ b/assets/security.css
@@ -50,4 +50,16 @@
.long_text {
width: 80%;
+}
+
+.protect-login-no-blocked-ips
+{
+ padding: 5px 10px;
+ width: 90%;
+ background-color: #ffffff;
+ border-style: solid;
+ border-color: #00a32a;
+ border-width: 1px;
+ font-weight: bold;
+ font-size: 12pt;
}
\ No newline at end of file
diff --git a/bdp-kompass.php b/bdp-kompass.php
index 1089ef6..fd253ce 100644
--- a/bdp-kompass.php
+++ b/bdp-kompass.php
@@ -12,6 +12,7 @@
* Text Domain: bdp-kompass
*/
+use Bdp\Modules\LimitLoginAttempts\Controllers\OptionsPage as OptionsPageAlias;
use Bdp\Modules\Security\Security;
use Bdp\Modules\Seo\Seo;
@@ -36,6 +37,9 @@ function bdp_plugin_init() {
}
}
+add_action('admin_menu', function () {
+ new OptionsPageAlias();
+});
function register_custom_theme_directory() {
@@ -47,4 +51,12 @@ function register_custom_theme_directory() {
switch_theme('buena');
}
+function enqueue_custom_password_js() {
+ wp_enqueue_script( 'custom-password-js', BDP_LV_PLUGIN_URL . 'assets/password.js');
+ wp_localize_script( 'custom-password-js', 'php_vars', [
+ 'allowed_strengths' => kompass_get_minimal_password_strength(),
+ 'password_too_short_text' => 'Dass Passwort entspricht nicht den Anforderungen.'
+ ]);
+}
+
#add_action( 'after_setup_theme', 'register_custom_theme_directory' );
diff --git a/includes/action_caller.php b/includes/action_caller.php
new file mode 100644
index 0000000..9913ef1
--- /dev/null
+++ b/includes/action_caller.php
@@ -0,0 +1,23 @@
+handleCookies();
+ add_action('auth_cookie_bad_username', [$loginHandler, 'checkFailedCookies']);
+ add_action('auth_cookie_valid', [$loginHandler, 'onValidCookie'], 10, 2);
+}
+
+if (isset($_POST['save_kompass_balist_list_type'])) {
+ updateBlockOrAllowList($_POST);
+}
+
+
diff --git a/includes/frontend-functions.php b/includes/frontend-functions.php
index a3b79df..e44b540 100644
--- a/includes/frontend-functions.php
+++ b/includes/frontend-functions.php
@@ -16,17 +16,13 @@ function bdp_update_dashboard_style() {
function bdp_add_menu_security() {
+
$moduleLoad = get_admin_url() . 'admin.php?page=' . BDP_LV_PLUGIN_SLUG . '/modules/index.php&loadmodule=';
- add_menu_page(
- 'Sicherheit',
- 'Webseiten-Sicherheit',
- 'manage_options',
- 'site-health.php',
- '',
- 'dashicons-admin-network',
- 5
- );
+
+
+
+
}
function bdp_add_menu_contents() {
@@ -69,7 +65,7 @@ function bdp_add_menu_mein_lv() {
$moduleLoad = get_admin_url() . 'admin.php?page=' . BDP_LV_PLUGIN_SLUG . '/modules/index.php&loadmodule=';
add_menu_page(
- 'Mein BDP',
+ 'Mein BdP',
'BdP',
'manage_options',
$mainSlug,
@@ -113,7 +109,7 @@ function bdp_add_menu_setup() {
add_submenu_page('users.php',
'Design-Einstellungen',
- 'Design',
+ 'Template bearbeiten',
'manage_options',
'customize.php?return=/wp-admin/'
);
@@ -132,6 +128,22 @@ function bdp_add_menu_setup() {
'manage_options',
'themes.php'
);
+
+ add_submenu_page('users.php',
+ 'Sicherheit',
+ 'Webseiten-Sicherheit',
+ 'manage_options',
+ 'site-health.php'
+ );
+
+ $loginOption = new \Bdp\Modules\LimitLoginAttempts\Controllers\OptionsPage();
+ add_submenu_page('users.php',
+ 'Login-Sicherheit',
+ 'Login-Sicherheit',
+ 'manage_options',
+ BDP_LV_PLUGIN_SLUG . '-limit-login-attempts',
+ [$loginOption, 'limit_login_option_page']
+ );
}
function bdp_cleanup_menu()
diff --git a/includes/pre_requires.php b/includes/pre_requires.php
index 1436eff..12dc003 100644
--- a/includes/pre_requires.php
+++ b/includes/pre_requires.php
@@ -3,3 +3,4 @@ require_once (ABSPATH . '/wp-admin/includes/plugin.php');
require_once (ABSPATH . '/wp-admin/includes/class-wp-filesystem-base.php');
require_once (ABSPATH . '/wp-admin/includes/class-wp-filesystem-direct.php');
require_once (ABSPATH . '/wp-includes/pluggable.php');
+require_once (ABSPATH . '/wp-admin/includes/template.php');
\ No newline at end of file
diff --git a/includes/setup.php b/includes/setup.php
index f8b5e8d..ca1e6a2 100644
--- a/includes/setup.php
+++ b/includes/setup.php
@@ -3,9 +3,12 @@ if ( ! defined( 'WP_PLUGIN_DIR' ) ) { // Abspath to wp-content/plu
define( 'WP_PLUGIN_DIR', WP_CONTENT_DIR . '/plugins' ); // Full path, no trailing slash.
}
+use Bdp\Modules\LimitLoginAttempts\Controllers\LoginHandler;
+
+
require_once dirname(__FILE__) . '/pre_requires.php';
require_once dirname(__FILE__) . '/environment.php';
-
+require_once dirname(__FILE__) . '/spl.php';
require_once dirname(__FILE__) . '/update.class.php';
require_once BDP_LV_PLUGIN_DIR . 'includes/FileAccess.class.php';
@@ -20,6 +23,10 @@ require_once (BDP_LV_PLUGIN_DIR . '/includes/frontend-functions.php');
require_once (BDP_LV_PLUGIN_DIR . '/modules/security/security.php');
+function admin_init()
+{
+ kompass_settings_validators();
+}
bdp_create_menu_structure();
@@ -31,6 +38,7 @@ function bdp_kompass_load_plugin_textdomain() {
-#$class =
+$loginHandler = new LoginHandler();
new BdpVersionChecker();
#add_filter( 'plugins_api', array( $class, 'info' ), 20, 3 );
+require_once dirname(__FILE__) . '/action_caller.php';
diff --git a/includes/spl.php b/includes/spl.php
new file mode 100644
index 0000000..5f3b398
--- /dev/null
+++ b/includes/spl.php
@@ -0,0 +1,32 @@
+isLoginAllowedFromIp() ) {
+ return $user;
+ }
+
+ global $limit_login_my_error_shown;
+ $limit_login_my_error_shown = true;
+
+ $error = new \WP_Error();
+ // This error should be the same as in "shake it" filter below
+ $error->add('too_many_retries', $this->composeErrorMessage());
+ return $error;
+ }
+
+ public function onFailedLogin(string $username) {
+ $ip = $this->getAddress();
+
+ /* if currently locked-out, do not add to retries */
+ $lockouts = get_option('protect_login_limit_login_lockouts', []);
+
+ if(isset($lockouts[$ip]) && time() < $lockouts[$ip]) {
+ return;
+ }
+
+ /* Get the arrays with retries and retries-valid information */
+ $retries = get_option('kompass_limit_login_retries', []);
+ $valid = get_option('kompass_limit_login_retries_valid', []);
+
+ /* Check validity and add one to retries */
+ if (isset($retries[$ip])) { //} && isset($valid[$ip]) && time() < $valid[$ip]) {
+ $retries[$ip] ++;
+ } else {
+ $retries[$ip] = 1;
+ }
+
+ update_option('kompass_limit_login_retries', $retries);
+
+ /* lockout? */
+ if($retries[$ip] % get_option('kompass_limit_login_allowed_retries', 0) != 0) {
+ return;
+ }
+
+
+ $retries_long = get_option('kompass_limit_login_allowed_retries', 1)
+ * get_option('kompass_limit_login_allowed_lockouts', 1);
+
+ if ($retries[$ip] >= $retries_long) {
+ $lockouts[$ip] = time() + get_option('kompass_limit_login_long_duration', 86400);
+
+ } else {
+ $lockouts[$ip] = time() + get_option('kompass_limit_login_lockout_duration', 900);
+ }
+
+ update_option('kompass_limit_login_lockouts', $lockouts);
+
+
+ /* do any notification */
+ $this->notify($username);
+
+ }
+
+ private function notifyByEmail($user)
+ {
+ $ip = $this->getAddress();
+
+ $lockouts = get_option('kompass_limit_login_lockouts', []);
+ if (!isset($lockouts[$ip])) {
+ return;
+ }
+
+ $blocked_until = $lockouts[$ip];
+
+ $retries = get_option('kompass_limit_login_retries', []);
+ $currentRetries = $retries[$ip];
+
+ $notify_after = get_option('kompass_limit_login_notify_email_after', 1);
+ if ($currentRetries % $notify_after !== 0) {
+ return;
+ }
+
+ $blogname = get_option('blogname', 'none');
+
+ $subject = sprintf(__("[%s] Too many failed login attempts"
+ , 'limit-login-attempts')
+ , $blogname);
+
+ $message = 'Neue Sperrung auf deiner Webseite: ' . PHP_EOL .
+ 'IP-Adresse: ' . $ip . PHP_EOL .
+ 'Gesperrt bis: ' . date('d.m.Y H:i', $blocked_until);
+
+ $admin_email = get_option('admin_email');
+ wp_mail($admin_email, $subject, $message);
+ }
+
+
+ /* Handle notification in event of lockout */
+ private function notify($user) {
+ $args = get_option('kompass_limit_login_lockout_notify', []);
+ if (!is_array($args)) {
+ $args = [$args];
+ }
+ foreach ($args as $mode) {
+ switch (trim($mode)) {
+ case 'email':
+ $this->notifyByEmail($user);
+ break;
+ }
+ }
+ }
+
+ private function composeErrorMessage() {
+ $ip = $this->getAddress();
+ $lockouts = get_option('kompass_limit_login_lockouts');
+
+ $msg = __('ERROR : Too many failed login attempts.', 'limit-login-attempts') . ' ';
+
+ if (!is_array($lockouts) || !isset($lockouts[$ip]) || time() >= $lockouts[$ip]) {
+ /* Huh? No timeout active? */
+ $msg .= __('Please try again later.', 'limit-login-attempts');
+ return $msg;
+ }
+
+ $when = ceil(($lockouts[$ip] - time()) / 60);
+ if ($when > 60) {
+ $when = ceil($when / 60);
+ $msg .= sprintf(_n('Please try again in %d hour.', 'Please try again in %d hours.', $when, 'limit-login-attempts'), $when);
+ } else {
+ $msg .= sprintf(_n('Please try again in %d minute.', 'Please try again in %d minutes.', $when, 'limit-login-attempts'), $when);
+ }
+
+ return $msg;
+ }
+
+ private static function getAddress($typeName = '') {
+ global $limitLoginAttemptsSettings;
+
+ $typeOriginal = $typeName;
+ if (empty($typeName)) {
+ $typeName = get_option('kompass_limit_loginclient_type', self::DIRECT_ADDR);
+ }
+
+ if (isset($_SERVER[$typeName]) && filter_var($_SERVER[$typeName], FILTER_VALIDATE_IP)) {
+ return $_SERVER[$typeName];
+ }
+
+ /*
+ * Not found. Did we get proxy type from option?
+ * If so, try to fall back to direct address.
+ */
+ if ( empty($typeName) && $typeOriginal == self::PROXY_ADDR
+ && isset($_SERVER[self::DIRECT_ADDR])
+ && filter_var($_SERVER[self::DIRECT_ADDR], FILTER_VALIDATE_IP)) {
+
+ /*
+ * NOTE: Even though we fall back to direct address -- meaning you
+ * can get a mostly working plugin when set to PROXY mode while in
+ * fact directly connected to Internet it is not safe!
+ *
+ * Client can itself send HTTP_X_FORWARDED_FOR header fooling us
+ * regarding which IP should be banned.
+ */
+
+ return $_SERVER[self::DIRECT_ADDR];
+ }
+
+ return '';
+
+ }
+
+ public function isLoginAllowedFromIp() {
+ $ip = $this->getAddress();
+
+ if (in_array($ip, get_option('kompass_limit_login_blocklist', []))) {
+ return false;
+ }
+
+ if (in_array($ip, get_option('kompass_limit_login_allowlist', []))) {
+ return true;
+ }
+
+ /* lockout active? */
+ $lockouts = get_option('kompass_limit_login_lockouts', []);
+ return (!is_array($lockouts) || !isset($lockouts[$ip]) || time() >= $lockouts[$ip]);
+ }
+
+ public function checkFailedCookies($cookie_elements) {
+ $this->clearAuthCookie();
+
+ /*
+ * Invalid username gets counted every time.
+ */
+
+ $this->onFailedLogin($cookie_elements['username']);
+ }
+
+ private function clearAuthCookie() {
+ wp_clear_auth_cookie();
+
+ if (!empty($_COOKIE[AUTH_COOKIE])) {
+ $_COOKIE[AUTH_COOKIE] = '';
+ }
+ if (!empty($_COOKIE[SECURE_AUTH_COOKIE])) {
+ $_COOKIE[SECURE_AUTH_COOKIE] = '';
+ }
+ if (!empty($_COOKIE[LOGGED_IN_COOKIE])) {
+ $_COOKIE[LOGGED_IN_COOKIE] = '';
+ }
+ }
+
+ public function onValidCookie($cookie_elements, $user) {
+ /*
+ * As all meta values get cached on user load this should not require
+ * any extra work for the common case of no stored value.
+ */
+
+ if (get_user_meta($user->ID, 'kompass_limit_login_previous_cookie')) {
+ delete_user_meta($user->ID, 'kompass_limit_login_previous_cookie');
+ }
+ }
+
+ function clearLoginCookie($cookie_elements) {
+ $this->clearAuthCookie();
+
+ /*
+ * Under some conditions an invalid auth cookie will be used multiple
+ * times, which results in multiple failed attempts from that one
+ * cookie.
+ *
+ * Unfortunately I've not been able to replicate this consistently and
+ * thus have not been able to make sure what the exact cause is.
+ *
+ * Probably it is because a reload of for example the admin dashboard
+ * might result in multiple requests from the browser before the invalid
+ * cookie can be cleard.
+ *
+ * Handle this by only counting the first attempt when the exact same
+ * cookie is attempted for a user.
+ */
+
+ extract($cookie_elements, EXTR_OVERWRITE);
+
+ // Check if cookie is for a valid user
+ $user = get_user_by('login', $username);
+ if (!$user) {
+ // "shouldn't happen" for this action
+ $this->onFailedLogin($username);
+ return;
+ }
+
+ $previous_cookie = get_user_meta($user->ID, 'kompass_limit_login_previous_cookie', true);
+ if ($previous_cookie && $previous_cookie == $cookie_elements) {
+ // Identical cookies, ignore this attempt
+ return;
+ }
+
+ // Store cookie
+ if ($previous_cookie)
+ update_user_meta($user->ID, 'kompass_limit_login_previous_cookie', $cookie_elements);
+ else
+ add_user_meta($user->ID, 'kompass_limit_login_previous_cookie', $cookie_elements, true);
+
+ $this->onFailedLogin($username);
+ }
+
+ public function handleCookies() {
+ if ($this->isLoginAllowedFromIp()) {
+ return;
+ }
+
+ $this->clearAuthCookie();
+ }
+}
\ No newline at end of file
diff --git a/modules/LimitLoginAttempts/Controllers/OptionsPage.php b/modules/LimitLoginAttempts/Controllers/OptionsPage.php
new file mode 100644
index 0000000..8e4f4f3
--- /dev/null
+++ b/modules/LimitLoginAttempts/Controllers/OptionsPage.php
@@ -0,0 +1,130 @@
+ $blockedUntil) {
+ $ips .= '' .
+ '' . $ip . ' ' .
+ '' . date('d.m.Y H:i', $blockedUntil) . ' Uhr ' .
+ '
+ Freigeben ' .
+ ' ';
+ };
+
+ return $ips;
+ }
+
+ public function limit_login_option_page() {
+ global $errors;
+
+ $showMessage = null;
+
+ if (isset($_POST['update_options'])) {
+ update_settings($_POST);
+ $showMessage = 'Die Einstellungen wurden gespeichert';
+ }
+ if (isset($_GET['action']) && $_GET['action'] == 'release') {
+ $showMessage = 'Die IP-Adresse wurde freigegeben.';
+ }
+
+ if(isset($_POST['save_kompass_balist_list_type'])) {
+ $showMessage = 'Die Liste wurde gespeichert.';
+ }
+
+ if (null !== $showMessage && $errors === false) {
+ echo '';
+ echo $showMessage;
+ echo '
';
+ }
+
+ if ($errors) {
+ echo '';
+ echo 'Beim Durchführen der Aktion ist ein Fehler aufgetreten.';
+ echo '
';
+ }
+
+ $tab = isset($_GET['tab']) ? $_GET['tab'] : 'tab1';
+ ?>
+
+
+
Protect Login - Einstellungen
+
+ = kompass_print_tab_header($tab); ?>
+
+
+ ';
+ do_settings_sections(BDP_LV_PLUGIN_SLUG . '-limit-login-attempts');
+ submit_button();
+ echo '';
+ break;
+ case 'tab2':
+ echo '
Blocklist ';
+ echo '';
+ break;
+ case 'tab3':
+ echo 'Allowlist ';
+ echo '';
+ break;
+ case 'tab4':
+ if (isset($_GET['action']) && $_GET['action'] == 'release') {
+ $this->releaseIp(base64_decode($_GET['ip']));
+ }
+ $blockedIps = $this->getBlockedIps();
+ ?>
+ Gesperrte IPs
+ ';
+ echo 'Derzeit sind keine Adressen gesperrt.';
+ echo '';
+ } else { ?>
+
+
+ IP
+ Gesperrt bis
+ Aktion
+
+ = $blockedIps ?>
+
+
+
+
+ [
+ 'email' => 'E-Mail an Administrator'
+ ],
+ ];
+
+ if(!isset($options[$settingName])) {
+ return;
+ }
+
+ $setting = $options[$settingName];
+ foreach ($setting as $radioOption => $optionText) {
+ $isChecked = in_array($radioOption, $currentSetting) ? 'checked ' : '' ;
+
+ echo ' ' .
+ '' . $optionText . ' ';
+ }
+}
diff --git a/modules/LimitLoginAttempts/Views/radio-option.php b/modules/LimitLoginAttempts/Views/radio-option.php
new file mode 100644
index 0000000..a317dfd
--- /dev/null
+++ b/modules/LimitLoginAttempts/Views/radio-option.php
@@ -0,0 +1,35 @@
+ [
+ 'REMOTE_ADDR' => 'Direkte Verbrindung',
+ 'HTTP_X_FORWARDED_FOR' => 'Hinter einem Proxy'
+ ],
+ 'kompass_limit_login_cookies' => [
+ true => 'Ja',
+ false => 'Nein'
+ ],
+ 'kompass_password_minimal_strength' => [
+ '1' => 'Alle Passwörter erlauben',
+ '2' => 'Mittelstarke Passwörter',
+ '3' => 'Nur Starke Passwörter'
+ ]
+ ];
+
+ if(!isset($options[$settingName])) {
+ return;
+ }
+
+ $setting = $options[$settingName];
+ foreach ($setting as $radioOption => $optionText) {
+ $isChecked = $currentSetting == $radioOption ? 'checked ' : '' ;
+ echo ' ' .
+ '' . $optionText . ' ';
+ }
+}
diff --git a/modules/LimitLoginAttempts/Views/tab-control.php b/modules/LimitLoginAttempts/Views/tab-control.php
new file mode 100644
index 0000000..c94a830
--- /dev/null
+++ b/modules/LimitLoginAttempts/Views/tab-control.php
@@ -0,0 +1,18 @@
+'.
+ '
+ Optionen
+ '.
+ '
+ Blocklist
+ '.
+ '
+ Allowlist
+ '.
+ '
+ Gesperrte IPs
+ ';
+ }
\ No newline at end of file
diff --git a/modules/LimitLoginAttempts/Views/text-element.php b/modules/LimitLoginAttempts/Views/text-element.php
new file mode 100644
index 0000000..2702e0c
--- /dev/null
+++ b/modules/LimitLoginAttempts/Views/text-element.php
@@ -0,0 +1,7 @@
+';
+ if (defined('WP_DEBUG') && WP_DEBUG == true) {
+ echo ' ' . $settingName;
+ }
+}
diff --git a/modules/LimitLoginAttempts/includes/block-and-allow-list-form.php b/modules/LimitLoginAttempts/includes/block-and-allow-list-form.php
new file mode 100644
index 0000000..265584d
--- /dev/null
+++ b/modules/LimitLoginAttempts/includes/block-and-allow-list-form.php
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+ = __('Zum Löschen frei lassen', BDP_LV_PLUGIN_SLUG); ?>
+
+
+
+
+
= __('IP-Adresse hinzufügen', BDP_LV_PLUGIN_SLUG); ?>
+
+
+
+
+';
+}
+
+function _kompass_limit_logins_settings_callback($args) {
+ $setting = get_option($args['setting'], null);
+ if (null === $setting) {
+ $setting = '';
+ }
+
+ $value = esc_attr($setting);
+ if (isset($args['unit_division'])) {
+ $value = (int)$value / (int)$args['unit_division'];
+ }
+
+ kompass_print_textbox($args['setting'], $value);
+}
+
+function _kompass_limit_logins_settings_radio_callback($args)
+{
+ kompass_print_radio($args['setting']);
+}
+function _kompass_limit_logins_settings_checkbox_callback($args) {
+ kompass_print_checkbox($args['setting']);
+}
+
+
+
+
+
+
+add_settings_section(
+ 'custom_settings_section',
+ 'Optionen',
+ 'custom_settings_section_callback',
+ BDP_LV_PLUGIN_SLUG . '-limit-login-attempts'
+);
+
+$settings_page = BDP_LV_PLUGIN_SLUG . '-limit-login-attempts';
+
+
+
+add_settings_field(
+ 'kompass_lla_1',
+ 'Maximale Wiederholungen',
+ '_kompass_limit_logins_settings_callback',
+ $settings_page,
+ 'custom_settings_section',
+ ['setting' => 'kompass_limit_login_allowed_retries']);
+
+add_settings_field(
+ 'kompass_lla_2',
+ 'Dauer der Sperre (in Minuten)',
+ '_kompass_limit_logins_settings_callback',
+ $settings_page,
+ 'custom_settings_section',
+ ['setting' => 'kompass_limit_login_lockout_duration', 'unit_division' => 60 ]);
+
+add_settings_field(
+ 'kompass_lla_3',
+ 'Maximale Anzahl an Sperrungen',
+ '_kompass_limit_logins_settings_callback',
+ $settings_page,
+ 'custom_settings_section',
+ ['setting' => 'kompass_limit_login_allowed_lockouts']);
+
+add_settings_field(
+ 'kompass_lla_4',
+ 'Langzeitsperre in Stunden',
+ '_kompass_limit_logins_settings_callback',
+ $settings_page,
+ 'custom_settings_section',
+ ['setting' => 'kompass_limit_login_long_duration', 'unit_division' => 3600]);
+
+add_settings_field(
+ 'kompass_lla_5',
+ 'Mininmale Passwort-Stärke:',
+ '_kompass_limit_logins_settings_radio_callback',
+ $settings_page,
+ 'custom_settings_section',
+ ['setting' => 'kompass_password_minimal_strength']);
+
+add_settings_field(
+ 'kompass_lla_6',
+ 'Seite erreichbar über:',
+ '_kompass_limit_logins_settings_radio_callback',
+ $settings_page,
+ 'custom_settings_section',
+ ['setting' => 'kompass_limit_login_client_type']);
+
+add_settings_field(
+ 'kompass_lla_7',
+ 'Cookies verarbeiten',
+ '_kompass_limit_logins_settings_radio_callback',
+ $settings_page,
+ 'custom_settings_section',
+ ['setting' => 'kompass_limit_login_cookies']);
+
+add_settings_field(
+ 'kompass_lla_8',
+ 'Bei Sperrung benachrichtigen',
+ '_kompass_limit_logins_settings_checkbox_callback',
+ $settings_page,
+ 'custom_settings_section',
+ ['setting' => 'kompass_limit_login_lockout_notify']);
+
+add_settings_field(
+ 'kompass_lla_9',
+ 'Fehlversuche bis zur Benachrichtigung',
+ '_kompass_limit_logins_settings_callback',
+ $settings_page,
+ 'custom_settings_section',
+ ['setting' => 'kompass_limit_login_notify_email_after']);
diff --git a/modules/LimitLoginAttempts/includes/validators.php b/modules/LimitLoginAttempts/includes/validators.php
new file mode 100644
index 0000000..e2fb154
--- /dev/null
+++ b/modules/LimitLoginAttempts/includes/validators.php
@@ -0,0 +1,64 @@
+ 'short, bad, good, strong',
+ '2' => 'good, strong',
+ '3' => 'strong'];
+
+ return ' ' . $possibleStrengths[$minPasswordStrength];
+}
\ No newline at end of file
From 40a3b93d4be1bb6ed27b8790a1ddf8da9a1161e2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thomas=20G=C3=BCnther?=
Date: Tue, 27 Feb 2024 11:33:24 +0100
Subject: [PATCH 5/8] Created setup environment
---
bdp-kompass.php | 14 ++--
modules/firstusage/classes/Security.class.php | 84 -------------------
modules/firstusage/internal/index.php | 22 -----
modules/firstusage/security.php | 3 -
modules/security/classes/Security.class.php | 18 +++-
modules/security/includes/settings_writer.php | 6 +-
6 files changed, 25 insertions(+), 122 deletions(-)
delete mode 100644 modules/firstusage/classes/Security.class.php
delete mode 100644 modules/firstusage/internal/index.php
delete mode 100644 modules/firstusage/security.php
diff --git a/bdp-kompass.php b/bdp-kompass.php
index fd253ce..e29e533 100644
--- a/bdp-kompass.php
+++ b/bdp-kompass.php
@@ -19,10 +19,7 @@ use Bdp\Modules\Seo\Seo;
require_once dirname(__FILE__) . '/includes/setup.php';
function bdp_plugin_install() {
- Seo::setup();
- Calendar::setup();
- Security::setup();
- update_option('kompass_installation', true);
+
}
@@ -30,11 +27,14 @@ function bdp_plugin_init() {
Security::ProhibitBots();
Security::SetPageFilters();
- remove_menu_page( 'admin.php?page=limit-login-attempts&tab=dashboard' );
- if ( get_option( 'kompass_installation' ) == true ) {
- delete_option( 'kompass_installation' );
+ if (null == get_option('kompass_already_installed', null)) {
+ Seo::setup();
+ Calendar::setup();
+ Security::setup();
+ update_option('kompass_already_installed', true);
wp_redirect( 'site-health.php?tab=bdp_enhanced_security');
}
+
}
add_action('admin_menu', function () {
diff --git a/modules/firstusage/classes/Security.class.php b/modules/firstusage/classes/Security.class.php
deleted file mode 100644
index da7af89..0000000
--- a/modules/firstusage/classes/Security.class.php
+++ /dev/null
@@ -1,84 +0,0 @@
- $pluginData) {
- if (!is_dir(WP_PLUGIN_DIR . '/' . $pluginSlug)) {
- self::installSecurityPlugin($pluginSlug, $pluginData['downloadUrl']);
- }
- }
-
- $loginUrl = get_option('whl_page', null) ?? 'bdp-login';
- enable_option_rewrite_url($loginUrl);
- enable_option_disable_xmlrpc();
- enable_option_block_authorscan();
- enable_option_block_execution_in_uploads();
- enable_option_prohibit_special_files();
- enable_option_file_editor();
- enable_option_disable_conatenation();
- enable_option_secure_include_dir();
- enable_option_prohibit_bot_access();
- enable_option_block_directory_listing();
-
- }
-
- public static function deletePlugins() {
- deactivate_plugins(self::delete_plugins);
- delete_plugins(self::delete_plugins);
- }
-
-
- public static function installSecurityPlugin(string $pluginSlug, string $downloadUrl) : bool
- {
- $ch = curl_init();
- $source = $downloadUrl;
- curl_setopt($ch, CURLOPT_URL, $source);
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
- $data = curl_exec ($ch);
- curl_close ($ch);
-
- $destination = WP_PLUGIN_DIR . '/' . $pluginSlug . '.zip';
- $file = fopen($destination, "w+");
- fputs($file, $data);
- fclose($file);
-
- $zip = new ZipArchive();
- $zip->open($destination);
- $zip->extractTo(WP_PLUGIN_DIR);
- $zip->close();
- unlink($destination);
-
- $pluginInfos = get_plugins( '/'.$pluginSlug );
- $installfile = $pluginSlug . '/';
- if( ! empty( $pluginInfos ) ) {
- foreach ($pluginInfos as $file => $info) :
- $installfile .= $file;
- endforeach;
- }
-
-
-
- $result = activate_plugin($installfile);
-
- return $result === null;
- }
-}
\ No newline at end of file
diff --git a/modules/firstusage/internal/index.php b/modules/firstusage/internal/index.php
deleted file mode 100644
index 731ff16..0000000
--- a/modules/firstusage/internal/index.php
+++ /dev/null
@@ -1,22 +0,0 @@
-';
-echo 'Installation erfolgreich! ';
-
-?>
-
-
-
diff --git a/modules/firstusage/security.php b/modules/firstusage/security.php
deleted file mode 100644
index 455ff9a..0000000
--- a/modules/firstusage/security.php
+++ /dev/null
@@ -1,3 +0,0 @@
-
Date: Tue, 27 Feb 2024 11:34:52 +0100
Subject: [PATCH 6/8] Created setup environment
---
bdp-kompass.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/bdp-kompass.php b/bdp-kompass.php
index e29e533..c8e6daf 100644
--- a/bdp-kompass.php
+++ b/bdp-kompass.php
@@ -2,7 +2,7 @@
/**
* Plugin Name: BdP Kompass
* Description: Wordpress-Plugin zur Unterstützung von Stämmen im Bund der Pfadfinderinnen und Pfadfinder e.V. zur optimalen Verwaltung eurer Webseite
- * Version: 4.1.1
+ * Version: 4.2.1
* Tags: bdp, utility, helper
* Requires at least: 6.0
* Requires PHP: 8.2
From 9d6c90e9cd65fb24ea6f8c03a3d387400e01274e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thomas=20G=C3=BCnther?=
Date: Tue, 27 Feb 2024 11:57:38 +0100
Subject: [PATCH 7/8] Updated Limit Login setup
---
modules/security/classes/Security.class.php | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/modules/security/classes/Security.class.php b/modules/security/classes/Security.class.php
index 13359e7..c4973dc 100644
--- a/modules/security/classes/Security.class.php
+++ b/modules/security/classes/Security.class.php
@@ -38,7 +38,7 @@ class Security
enable_option_secure_include_dir();
enable_option_prohibit_bot_access();
enable_option_block_directory_listing();
-
+ self::resetLimitLoginAttempts();
delete_option('whl_page');
}
@@ -150,4 +150,16 @@ class Security
return $result === null;
}
+
+ public static function resetLimitLoginAttempts() {
+ update_option('kompass_limit_login_lockout_duration', 900);
+ update_option('kompass_limit_login_allowed_retries', 3);
+ update_option('kompass_limit_login_allowed_lockouts', 3);
+ update_option('kompass_password_minimal_strength', 3);
+ update_option('kompass_limit_login_client_type', 'REMOTE_ADDR');
+ update_option('kompass_limit_login_long_duration', 86400);
+ update_option('kompass_limit_login_lockout_notify', ['email']);
+ update_option('kompass_limit_login_notify_email_after', 3);
+ update_option('kompass_limit_login_cookies',0);
+ }
}
\ No newline at end of file
From d1eece58758fc5d1ba58b84df06cacbb2ba9bb48 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thomas=20G=C3=BCnther?=
Date: Tue, 27 Feb 2024 11:58:24 +0100
Subject: [PATCH 8/8] celanup
---
buena/404.php | 96 -----
buena/comments.php | 27 --
buena/content.php | 17 -
buena/functions.php | 89 ----
buena/index.php | 106 -----
buena/searchform.php | 11 -
buena/src/autoloader.php | 19 -
.../src/Shy/WordPress/CompositeOption.php | 98 -----
.../src/Shy/WordPress/HookableTrait.php | 35 --
.../src/Shy/WordPress/Plugin.php | 13 -
.../src/Shy/WordPress/SettingsPage.php | 383 ------------------
.../shy-wordpress/src/Shy/WordPress/Theme.php | 18 -
buena/use/shy-wordpress/src/autoloader.php | 20 -
.../Shy/WordPress/Tests/HookableTraitTest.php | 40 --
.../Shy/WordPress/Tests/SettingsPageTest.php | 181 ---------
buena/use/shy-wordpress/tests/autoloader.php | 20 -
buena/use/shy-wordpress/tests/bootstrap.php | 14 -
17 files changed, 1187 deletions(-)
delete mode 100644 buena/404.php
delete mode 100644 buena/comments.php
delete mode 100644 buena/content.php
delete mode 100644 buena/functions.php
delete mode 100644 buena/index.php
delete mode 100644 buena/searchform.php
delete mode 100644 buena/src/autoloader.php
delete mode 100644 buena/use/shy-wordpress/src/Shy/WordPress/CompositeOption.php
delete mode 100644 buena/use/shy-wordpress/src/Shy/WordPress/HookableTrait.php
delete mode 100644 buena/use/shy-wordpress/src/Shy/WordPress/Plugin.php
delete mode 100644 buena/use/shy-wordpress/src/Shy/WordPress/SettingsPage.php
delete mode 100644 buena/use/shy-wordpress/src/Shy/WordPress/Theme.php
delete mode 100644 buena/use/shy-wordpress/src/autoloader.php
delete mode 100644 buena/use/shy-wordpress/tests/Shy/WordPress/Tests/HookableTraitTest.php
delete mode 100644 buena/use/shy-wordpress/tests/Shy/WordPress/Tests/SettingsPageTest.php
delete mode 100644 buena/use/shy-wordpress/tests/autoloader.php
delete mode 100644 buena/use/shy-wordpress/tests/bootstrap.php
diff --git a/buena/404.php b/buena/404.php
deleted file mode 100644
index 543055f..0000000
--- a/buena/404.php
+++ /dev/null
@@ -1,96 +0,0 @@
-
-
-
-
->
-
-
-
-
-
-
-
-
-
-
-
->
-
-
-
- 'primary', 'depth' => 2, 'container' => 'nav', 'container_class' => 'nav-menu' ] ); ?>
-
-
-
-
-
-
-
- '' ] ); ?>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/buena/comments.php b/buena/comments.php
deleted file mode 100644
index 3669590..0000000
--- a/buena/comments.php
+++ /dev/null
@@ -1,27 +0,0 @@
-%s
', __( 'Kommentare werden erst angezeigt, wenn das Kennwort eingegeben wurde.', 'buena-theme' ) );
- return;
-}
-
-// FIXME: Hier sollten die Social-Media-Knöpfe auftauchen…
-
-?>
-
diff --git a/buena/content.php b/buena/content.php
deleted file mode 100644
index 54689ca..0000000
--- a/buena/content.php
+++ /dev/null
@@ -1,17 +0,0 @@
->
-
-
-
- 'Seiten:', 'after' => ' ' ) ); ?>
-
-
- '' ] ); ?>
-
-
-
-
-
-
-
diff --git a/buena/functions.php b/buena/functions.php
deleted file mode 100644
index ac7df51..0000000
--- a/buena/functions.php
+++ /dev/null
@@ -1,89 +0,0 @@
-= 50400 ) {
- // Register autoloader if updater plugin missing
- if ( ! class_exists( 'plugins\buena\use\shy-wordpress\src\Shy\WordPress\Theme' ) ) {
- if ( ! include_once __DIR__ . '/use/shy-wordpress/src/autoloader.php' ) {
- trigger_pfadfinden_plugin_error(
- __( 'Das Theme ist unvollständig und konnte nicht geladen werden. Neuinstallation müsste helfen.', 'buena-theme' ),
- E_USER_ERROR
- );
- return;
- }
- }
-
- // Register our autoloader
- if ( ! include_once __DIR__ . '/src/autoloader.php' ) {
- trigger_pfadfinden_plugin_error(
- __( 'Das Theme ist unvollständig und konnte nicht geladen werden. Neuinstallation müsste helfen.', 'buena-theme' ),
- E_USER_ERROR
- );
- return;
- }
-
- /**
- * @return \plugins\buena\src\Pfadfinden\WordPress\BuenaTheme
- */
- function buena_get_theme()
- {
- static $theme = null;
- if (!$theme) {
- $theme = new ReflectionClass( 'plugins\buena\src\Pfadfinden\WordPress\BuenaTheme' );
- $theme = $theme->newInstance();
- }
-
- return $theme;
- }
-
- /**
- * @param string $method
- * @return callable
- */
- function buena_get_callback( $method )
- {
- return array( buena_get_theme(), (string) $method );
- }
-
- return buena_get_theme();
-}
-
-
-// Display error message
-trigger_pfadfinden_plugin_error(
- sprintf(
- __( 'You need at least PHP 5.4 to use the Buena theme. Your are using %s.', 'buena-theme' ),
- PHP_VERSION
- ),
- E_USER_ERROR
-);
diff --git a/buena/index.php b/buena/index.php
deleted file mode 100644
index c823787..0000000
--- a/buena/index.php
+++ /dev/null
@@ -1,106 +0,0 @@
-
-
-
-
->
-
-
-
-
-
-
-
-
-
-
-
-
-
->
-
-
-
- 'primary', 'depth' => 2, 'container' => 'nav', 'container_class' => 'nav-menu nav-menu-primary' ] ); ?>
-
-
-
-
- getTeaserImage() ): ?>
-
-
-
- printTitle(); ?>
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/buena/searchform.php b/buena/searchform.php
deleted file mode 100644
index 16ba18d..0000000
--- a/buena/searchform.php
+++ /dev/null
@@ -1,11 +0,0 @@
-
diff --git a/buena/src/autoloader.php b/buena/src/autoloader.php
deleted file mode 100644
index d09cc39..0000000
--- a/buena/src/autoloader.php
+++ /dev/null
@@ -1,19 +0,0 @@
-slug;
- }
-
-
- protected function __construct( $slug )
- {
- $this->slug = (string) $slug;
-
- $this->addHookMethod( 'default_option_' . $this->slug, 'getDefaults' );
- }
-
-
- /**
- * Return default values for all suboptions.
- * Hooked into get_option() defaults.
- *
- * @return array
- */
- abstract public function getDefaults();
-
- /**
- * @param string $offset
- * @return mixed
- */
- public function getDefault( $offset )
- {
- return $this->getDefaults()[ $offset ];
- }
-
-
- public function offsetExists( $offset )
- {
- $settings = get_option( $this->slug );
- return isset( $settings[ $offset ] );
- }
-
- public function offsetGet( $offset )
- {
- $settings = get_option( $this->slug );
- if ( ! isset( $settings[ $offset ] ) ) {
- throw new \OutOfBoundsException( "There is no setting '$offset'." );
- }
-
- return $settings[ $offset ];
- }
-
- public function offsetSet( $offset, $value )
- {
- $settings = get_option( $this->slug );
- if ( ! isset( $settings[ $offset ] ) ) {
- throw new \OutOfBoundsException( "There is no setting '$offset'." );
- }
-
- $settings[ $offset ] = $value;
- update_option( $this->slug, $settings );
- }
-
- public function offsetUnset( $offset )
- {
- throw new \BadMethodCallException( 'You cannot unset settings.' );
- }
-
-
- public function count()
- {
- return count( $this->getDefaults() );
- }
-
-
- public function getIterator()
- {
- return new \ArrayIterator( get_option( $this->slug ) );
- }
-}
diff --git a/buena/use/shy-wordpress/src/Shy/WordPress/HookableTrait.php b/buena/use/shy-wordpress/src/Shy/WordPress/HookableTrait.php
deleted file mode 100644
index e6adc43..0000000
--- a/buena/use/shy-wordpress/src/Shy/WordPress/HookableTrait.php
+++ /dev/null
@@ -1,35 +0,0 @@
-getPageTitle();
- }
-
-
- /**
- * @param string $slug Page slug
- * @param string $capability Required capability to view
- */
- protected function __construct( $slug, $capability = 'manage_options' )
- {
- parent::__construct( $slug );
-
- $this->capability = (string) $capability;
-
- $this->addHookMethod( 'admin_menu', 'registerPage' );
- $this->addHookMethod( 'admin_init', 'registerSettings' );
- }
-
- public function __toString()
- {
- return $this->slug;
- }
-
- /**
- * Register our options page.
- *
- * @return void
- */
- public function registerPage()
- {
- add_submenu_page(
- $this->getParentSlug(),
- $this->getPageTitle(),
- $this->getMenuTitle(),
- $this->capability,
- $this->slug,
- array( $this, 'renderPage' )
- );
- }
-
- /**
- * Register the actual settings.
- * Override and use addSection() and add*Field() methods.
- *
- * @return void
- */
- public function registerSettings()
- {
- register_setting(
- $this->slug,
- $this->slug,
- array( $this, 'sanitizeOptions' )
- );
- }
-
- /**
- * Sanitize option values after form submission.
- *
- * @param array $options
- * @return array
- */
- abstract public function sanitizeOptions( array $options );
-
-
- /**
- * Section to add fields to.
- *
- * Parameter default from add_settings_field().
- *
- * @var string
- */
- protected $currentSection = 'default';
-
- /**
- * Add a new section and return its generated name.
- *
- * @param string $title optional, can be empty
- * @param string $name optional, will be generated if empty
- * @return string
- */
- protected function addSection( $title = '', $name = '' )
- {
- $name = (string) $name;
- if ( ! strlen( $name ) ) {
- $name = $this->slug . '-section' . ( count( $this->getSections() ) + 1 );
- }
-
- add_settings_section(
- $name,
- esc_html( $title ),
- array( $this, 'renderSectionTeaser' ),
- $this->slug
- );
-
- return $this->currentSection = $name;
- }
-
- /**
- * Callback before output of section fields.
- *
- * Teasers must escape their output themselves.
- *
- * @param array $section {
- * @type string $id
- * @type string $title
- * @type callable $callback
- * }
- */
- public function renderSectionTeaser( array $section )
- {
- }
-
- /**
- * Get all known section names on this page.
- *
- * @global $wp_settings_fields
- * @return array
- */
- public function getSections()
- {
- global $wp_settings_fields;
-
- if ( ! isset( $wp_settings_fields[ $this->slug ] ) ) {
- return array();
- }
-
- return array_keys( $wp_settings_fields[ $this->slug ] );
- }
-
- /**
- * @global $wp_settings_fields
- * @param string $section
- * @return array
- */
- public function getFieldsForSection( $section )
- {
- global $wp_settings_fields;
-
- return $wp_settings_fields[ $this->slug ][ $section ];
- }
-
- /**
- * Add a custom field to this setting page.
- *
- * @param string $name
- * @param string $label
- * @param callable $callback
- * @param array $args
- */
- protected function addField( $name, $label, $callback, $args = array() )
- {
- if ( ! is_callable( $callback ) ) {
- throw new \InvalidArgumentException( 'Parameter $callback must be callable.' );
- }
-
- add_settings_field(
- $name,
- esc_html( $label ),
- $callback,
- $this->slug,
- $this->currentSection,
- $args
- );
- }
-
- /**
- * Add a text field to this settings page.
- *
- * @param string $name
- * @param string $label
- * @param array $args
- * @param string $callback
- */
- protected function addTextField( $name, $label, $args = array(), $callback = '' )
- {
- if ( ! $callback || ! is_callable( $callback ) ) {
- $callback = array( $this, 'renderTextField' );
- }
-
- $this->addField(
- $name,
- $label,
- $callback,
- $args + array(
- 'label_for' => $this->slug . '-' . $name,
- 'name' => $name,
- 'attr' => array(),
- )
- );
- }
-
- /**
- * @param string $name
- * @param string $label
- * @param string $caption
- * @param array $args
- * @param callable $callback
- */
- protected function addCheckboxField( $name, $label, $caption, $args = array(), $callback = '' )
- {
- if ( ! $callback || ! is_callable( $callback ) ) {
- $callback = array( $this, 'renderCheckboxField' );
- }
-
- $this->addField(
- $name,
- $label,
- $callback,
- $args + array(
- 'label_for' => $this->slug . '-' . $name,
- 'name' => $name,
- 'caption' => $caption,
- 'attr' => array(),
- )
- );
- }
-
- /**
- * Add an error.
- *
- * @param string $code
- * @param string $message
- */
- protected function addError( $code, $message )
- {
- add_settings_error( $this->slug, $code, $message );
- }
-
- /**
- * Errors for this setting.
- *
- * @return array {
- * @type string $setting
- * @type string $code
- * @type string $message
- * @type string $type 'error'
- * }
- */
- public function getErrors()
- {
- return get_settings_errors( $this->slug );
- }
-
-
- /**
- * Render a setting as text field.
- *
- * @param array $args {
- * @type string $name
- * @type string $label_for
- * @type array $attr
- * }
- */
- public function renderTextField( array $args )
- {
- $name = $args['name'];
-
- $this->renderInputTag( array(
- 'type' => 'text',
- 'id' => $args['label_for'],
- 'class' => 'regular-text',
- 'name' => $this->slug . '[' . $name . ']',
- 'value' => $this[ $name ],
- ) + $args['attr'] );
- }
-
- /**
- * Render a setting as checkbox.
- *
- * @param array $args {
- * @type string $caption
- * @type string $name
- * @type string $label_for
- * @type array $attr
- * }
- */
- public function renderCheckboxField( array $args )
- {
- $name = $args['name'];
-
- echo '';
- $this->renderInputTag( array(
- 'type' => 'checkbox',
- 'id' => isset( $args['label_for'] ) ? $args['label_for'] : null,
- 'name' => $this->slug . '[' . $name . ']',
- 'value' => '1',
- 'checked' => $this[ $name ] ? 'checked' : null,
- ) + $args['attr'] );
- echo ' ' . esc_html( $args['caption'] ) . ' ';
- }
-
- /**
- * Output an input tag with given HTML attributes.
- *
- * @param array $attr
- */
- protected function renderInputTag( array $attr )
- {
- echo ' $v ) {
- if ( null !== $v ) {
- printf( ' %s="%s"', $k, esc_attr( $v ) );
- }
- }
- echo ' />';
- }
-
- /**
- * Output settings page.
- */
- public function renderPage()
- {
- if ( ! current_user_can( $this->capability ) ) {
- wp_die( __( 'You do not have sufficient permissions to access this page.' ) );
- }
-
- ?>
-
-
getPageTitle() ); ?>
-
-
- getContentWidth();
- }
-
- /**
- * @return integer
- */
- abstract public function getContentWidth();
-}
diff --git a/buena/use/shy-wordpress/src/autoloader.php b/buena/use/shy-wordpress/src/autoloader.php
deleted file mode 100644
index 00744fb..0000000
--- a/buena/use/shy-wordpress/src/autoloader.php
+++ /dev/null
@@ -1,20 +0,0 @@
-
- */
-class HookableTraitTest extends \WP_UnitTestCase
-{
- use HookableTrait;
-
-
- public function actionMethod()
- {
- }
-
- public function testWorksAsAction()
- {
- $this->addHookMethod( 'shywp_test_action', 'actionMethod' );
- $this->assertTrue( has_action( 'shywp_test_action' ), 'Registering an action via addHookMethod() worked.' );
- }
-
-
- public function filterMethod( $value )
- {
- return $value;
- }
-
- public function testWorksAsFilter()
- {
- $this->addHookMethod( 'shywp_test_filter', 'filterMethod' );
- $this->assertTrue( has_filter( 'shywp_test_filter' ), 'Registering a filter via addHookMethod() worked.' );
- }
-}
diff --git a/buena/use/shy-wordpress/tests/Shy/WordPress/Tests/SettingsPageTest.php b/buena/use/shy-wordpress/tests/Shy/WordPress/Tests/SettingsPageTest.php
deleted file mode 100644
index 12459f6..0000000
--- a/buena/use/shy-wordpress/tests/Shy/WordPress/Tests/SettingsPageTest.php
+++ /dev/null
@@ -1,181 +0,0 @@
-getMockBuilder( 'plugins\buena\use\shy-wordpress\src\Shy\WordPress\SettingsPage' )
- ->enableProxyingToOriginalMethods();
-
- if ( null === $slug ) {
- $builder->disableOriginalConstructor();
- } else {
- $builder->setConstructorArgs( array( $slug, $capability ) );
- }
-
- return $builder->getMock();
- }
-
-
- /**
- * Test reading defaults from the settings page.
- *
- * @covers wordpress\src\Shy\WordPress\SettingsPage::__construct()
- * @covers wordpress\src\Shy\WordPress\SettingsPage::getDefaults()
- * @covers wordpress\src\Shy\WordPress\SettingsPage::offsetExists()
- * @covers wordpress\src\Shy\WordPress\SettingsPage::offsetGet()
- * @expectedException OutOfBoundsException
- */
- public function testReading()
- {
- $slug = 'shywp_settingspage_test_slug_reading';
- $defaults = array( 'foo' => 'bar' );
-
- $page = $this->mockSettingsPage( $slug );
- $page->method( 'getDefaults' )->willReturn( $defaults );
-
- $this->assertEquals( $defaults, get_option( $slug ) );
-
- $this->assertArrayHasKey( 'foo', $page );
- $this->assertEquals( $defaults['foo'], $page['foo'] );
-
- $this->assertArrayNotHasKey( 'baz', $page );
- $page['baz'];
- }
-
- /**
- * Test writing to the settings page.
- *
- * @covers wordpress\src\Shy\WordPress\SettingsPage::offsetSet()
- * @expectedException OutOfBoundsException
- */
- public function testWriting()
- {
- $slug = 'shywp_settingspage_test_slug_writing';
- $defaults = array( 'foo' => 'bar' );
-
- $page = $this->mockSettingsPage( $slug );
- $page->method( 'getDefaults' )->willReturn( $defaults );
-
- $page['foo'] = 'foo';
- $this->assertEquals( 'foo', $page['foo'] );
- $page['baz'] = '123';
- }
-
- /**
- * Fail to remove a setting.
- *
- * @covers SettingPage::offsetUnset()
- * @expectedException BadMethodCallException
- */
- public function testRemoving()
- {
- $slug = 'shywp_settingspage_test_slug_removing';
- $defaults = array();
-
- $page = $this->mockSettingsPage( $slug );
- $page->method( 'getDefaults' )->willReturn( $defaults );
-
- unset( $page['baz'] );
- }
-
-
- /**
- * Test whether the settings page can be showed.
- *
- * @covers wordpress\src\Shy\WordPress\SettingsPage::__construct()
- * @covers wordpress\src\Shy\WordPress\SettingsPage::getParentSlug()
- * @covers wordpress\src\Shy\WordPress\SettingsPage::getPageTitle()
- * @covers wordpress\src\Shy\WordPress\SettingsPage::getMenuTitle()
- */
- public function testRegisterPage()
- {
- $this->expectOutputRegex( '/<page&title>/' );
-
- $slug = 'shywp_settingspage_test_slug_registerpage';
-
- $page = $this->mockSettingsPage( $slug );
- $page->method( 'getParentSlug' )->willReturn( 'index.php' );
- $page->method( 'getPageTitle' )->willReturn( '' );
- $page->method( 'getMenuTitle' )->willReturn( '' );
-
- $page->expects( $this->once() )->method( 'registerPage' )->with();
- $page->expects( $this->once() )->method( 'registerSettings' )->with();
-
- // FIXME: Simulate display of backend.
- }
-
-
- /**
- * @covers wordpress\src\Shy\WordPress\SettingsPage::sanitizeOptions()
- */
- public function testSanitize()
- {
- $slug = 'shywp_settingspage_test_slug_sanitize';
-
- $page = $this->mockSettingsPage( $slug );
- $page->method( 'sanitizeOptions' )->will( $this->returnArgument( 0 ) );
- $page->expects( $this->atLeastOnce() )->method( 'sanitizeOptions' );
-
- $this->markTestIncomplete();
- // FIXME: Simulate form submission
- }
-
- public function testRenderTextField()
- {
- $this->expectOutputRegex( '/^ mockSettingsPage();
- $page->renderTextField( array(
- 'label_for' => 'foo',
- 'name' => 'bar',
- ) );
- }
-
- public function testRenderCheckboxField()
- {
- $this->expectOutputRegex( '/^ mockSettingsPage();
- $page->renderCheckboxField( array(
- 'label_for' => 'foo',
- 'name' => 'bar',
- 'caption' => 'baz',
- ) );
- }
-
- public function testRenderPage()
- {
- $this->markTestIncomplete();
- $this->expectOutputRegex( '//' );
-
- $slug = 'shywp_settingspage_test_slug_renderpage';
-
- $page = $this->mockSettingsPage( $slug, 'read' );
- $page->method( 'getPageTitle' )->willReturn( '<3&>' );
- $page->method( 'renderSectionTeaser' )->will( $this->returnCallback( function () use ( $teaser ) {
- echo 'cryptic_teaser';
- } ) );
-
- // FIXME: Simulate view of the settings page
- $page->renderPage();
- }
-}
diff --git a/buena/use/shy-wordpress/tests/autoloader.php b/buena/use/shy-wordpress/tests/autoloader.php
deleted file mode 100644
index dbd8ccc..0000000
--- a/buena/use/shy-wordpress/tests/autoloader.php
+++ /dev/null
@@ -1,20 +0,0 @@
-
- -
- - - - - - - -