feat: add .htaccess reset option to MokoRestore
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 2s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Generic: Repo Health / Access control (pull_request) Successful in 1s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 5s
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 5s
Universal: Secret Scanning / Gitleaks Secret Scan (pull_request) Successful in 7s
Universal: Auto Version Bump / Version Bump (push) Successful in 10s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 6s
Universal: PR Check / Validate PR (pull_request) Failing after 19s
Generic: Repo Health / Scripts governance (push) Has been cancelled
Generic: Repo Health / Repository health (push) Has been cancelled
Generic: Repo Health / Report Issues (push) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report Issues (pull_request) Has been cancelled

Add checkbox in Step 4 to reset .htaccess to Joomla defaults.
Backs up existing as .htaccess.bak before overwriting. Optional
and unchecked by default to preserve custom rules.
This commit is contained in:
Jonathan Miller
2026-06-14 21:22:30 -05:00
parent cb3f1ab3cc
commit b785b0e748
@@ -452,6 +452,11 @@ function actionConfig(array $data): array
@unlink($bakPath);
}
// Reset .htaccess to Joomla defaults if requested
if (($data['reset_htaccess'] ?? '0') === '1') {
writeDefaultHtaccess(RESTORE_DIR);
}
return ['success' => true, 'message' => 'Joomla configuration rebuilt with fresh credentials and secret'];
}
@@ -505,7 +510,122 @@ JCONFIG;
@mkdir($tmpPath, 0755, true);
@mkdir($logPath, 0755, true);
return ['success' => true, 'message' => 'configuration.php created from scratch with fresh secret'];
// Reset .htaccess to Joomla defaults if requested
if (($data['reset_htaccess'] ?? '0') === '1') {
writeDefaultHtaccess(RESTORE_DIR);
}
return ['success' => true, 'message' => 'Joomla configuration created from scratch with fresh secret'];
}
/**
* Write a clean Joomla default .htaccess file.
* Backs up the existing one as .htaccess.bak first.
*/
function writeDefaultHtaccess(string $siteRoot): void
{
$htaccess = $siteRoot . '/.htaccess';
// Backup existing .htaccess before overwriting
if (is_file($htaccess)) {
copy($htaccess, $htaccess . '.bak');
}
$default = <<<'HTACCESS'
##
# @package Joomla
# @copyright (C) 2005 Open Source Matters, Inc. <https://www.joomla.org>
# @license GNU General Public License version 2 or later; see LICENSE.txt
##
##
# READ THIS COMPLETELY IF YOU CHOOSE TO USE THIS FILE!
#
# The line 'Options +FollowSymLinks' may cause problems with some server
# configurations. It is required for the use of Apache mod_rewrite, but
# it may have already been set by your server administrator in a way that
# disallows changing it in this .htaccess file. If using it causes your
# server to report an error, comment it out, reload your site in your
# browser and test your SEF URLs. If they work, then it has been set by
# your server administrator and you do not need to set it here.
##
## No directory listings
<IfModule autoindex>
IndexIgnore *
</IfModule>
## Suppress mime type detection in browsers for unknown types
<IfModule mod_headers.c>
Header always set X-Content-Type-Options "nosniff"
</IfModule>
## Can be commented out if causes errors, see notes above.
Options +FollowSymLinks
Options -Indexes
## Disable inline JavaScript when directly opening SVG files or embedding them with the object-tag
<FilesMatch "\.svg$">
<IfModule mod_headers.c>
Header always set Content-Security-Policy "script-src 'none'"
</IfModule>
</FilesMatch>
## Mod_rewrite in use.
RewriteEngine On
## Begin - Rewrite rules to block out some common exploits.
# If you experience problems on your site then comment out the operations listed
# below by adding a # to the beginning of the line.
# This attempts to block the most common type of exploit `attempts` on Joomla!
#
# Block any script trying to base64_encode data within the URL.
RewriteCond %{QUERY_STRING} base64_encode[^(]*\([^)]*\) [OR]
# Block any script that includes a <script> tag in URL.
RewriteCond %{QUERY_STRING} (<|%3C)([^s]*s)+cript.*(>|%3E) [NC,OR]
# Block any script trying to set a PHP GLOBALS variable via URL.
RewriteCond %{QUERY_STRING} GLOBALS(=|\[|\%[0-9A-Z]{0,2}) [OR]
# Block any script trying to modify a _REQUEST variable via URL.
RewriteCond %{QUERY_STRING} _REQUEST(=|\[|\%[0-9A-Z]{0,2})
# Return 403 Forbidden header and show the content of the root home page
RewriteRule .* index.php [F]
#
## End - Rewrite rules to block out some common exploits.
## Begin - Custom redirects
#
# If you need to redirect some pages, or set a canonical non-www to
# www redirect (or vice versa), place that code here. Ensure those
# redirects use the correct RewriteRule syntax and the [R=301,L] flags.
#
## End - Custom redirects
##
# Uncomment the following line if your webserver's URL
# is not directly related to physical file paths.
# Update Your Joomla! Directory (just / for root).
##
# RewriteBase /
## Begin - Joomla! core SEF Section.
#
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
#
# If the requested path and file is not /index.php and the request
# has not already been internally rewritten to the index.php script
RewriteCond %{REQUEST_URI} !^/index\.php
# and the requested path and file matches no existing file
RewriteCond %{REQUEST_FILENAME} !-f
# and the requested path and file matches no existing directory
RewriteCond %{REQUEST_FILENAME} !-d
# internally rewrite the request to the index.php script
RewriteRule .* index.php [L]
#
## End - Joomla! core SEF Section.
HTACCESS;
file_put_contents($htaccess, $default);
}
function actionListAdmins(array $data): array
@@ -893,6 +1013,17 @@ body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica N
</div>
</div>
<div style="border:1px solid #e2e8f0;border-radius:8px;padding:1.25rem;margin-bottom:1.25rem;background:#f8fafc">
<div style="font-weight:600;font-size:0.9rem;color:#334155;margin-bottom:1rem;display:flex;align-items:center;gap:0.5rem">
<span style="font-size:1.1rem">&#128736;</span> Server
</div>
<div class="mr-field" style="display:flex;align-items:center;gap:0.5rem">
<input type="checkbox" id="resetHtaccess" style="width:auto">
<label for="resetHtaccess" style="margin:0;cursor:pointer">Reset .htaccess to Joomla defaults</label>
</div>
<div class="mr-hint">Check this if restoring to a different server. The backup's .htaccess may contain server-specific rewrite rules that won't work here.</div>
</div>
<div class="mr-alert mr-alert-info">
<span>&#128274;</span> A new Joomla secret key will be generated automatically. This invalidates active sessions (users will need to log in again) but does not affect passwords or user accounts.
</div>
@@ -1185,6 +1316,7 @@ async function runConfig() {
smtp_host: document.getElementById('smtpHost').value,
smtp_user: document.getElementById('smtpUser').value,
smtp_pass: document.getElementById('smtpPass').value,
reset_htaccess: document.getElementById('resetHtaccess').checked ? '1' : '0',
});
const r = await post('config', params);