diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
index efb59b68659c7..4df560490fdea 100644
--- a/.github/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -32,11 +32,15 @@ before it will be accepted, we ask that you follow these simple guidelines:
Please be patient as not all items will be viewed or tested immediately (remember, all bug testing for the Joomla! CMS is done by volunteers) and be receptive to feedback about your code.
#### Branches
-Bug fixing PRs should be made to the `5.4-dev` branch. Merged bugfixes will be upmerged into the current branches. New features that do not break backwards compatibility should be made to the `6.3-dev`.
+
+Joomla 5.4 is in security maintenance mode until 12th October 2027, which means it will only receive security fixes.
+Bug fixing PRs should be made to the `6.2-dev` branch. Merged bugfixes will be upmerged into the current branches.
+New features that do not break backwards compatibility should be made to the `6.3-dev` branch, otherwise they should
+be made to the `7.0-dev` branch.
| Branch | Purpose |
|---------|--------------------------------------------------------------------------------------------------------------|
-| 5.4-dev | Branch for the current 5.x Joomla version. |
-| 6.2-dev | Branch for the current 6.x Joomla version. Bugfixes only for 6.2 go into this branch. |
+| 5.4-dev | Branch for the current 5.x Joomla version. Currently in security maintenance mode. |
+| 6.2-dev | Branch for the current 6.x Joomla version. Bugfixes go into this branch. |
| 6.3-dev | Branch for the next minor 6.x Joomla version. New features have to go into this branch. |
| 7.0-dev | Branch for the next major Joomla version. New features that include a b/c break have to go into this branch. |
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 50194981e0087..b1c93d8851028 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -84,13 +84,17 @@ jobs:
- name: Check PHP code style
run: |
set -e
+ if [ "$GITHUB_REPOSITORY" = "joomla/joomla-cms" ]; then
+ ./libraries/vendor/bin/php-cs-fixer check -vvv --diff
+ exit 0
+ fi
./libraries/vendor/bin/php-cs-fixer fix -vvv --diff
git config --global --add safe.directory "$GITHUB_WORKSPACE"
- if [ "$GITHUB_EVENT_NAME" = "push" ] && [ "$GITHUB_REPOSITORY" != "joomla/joomla-cms" ] && ! git diff --quiet; then
+ if [ "$GITHUB_EVENT_NAME" = "push" ] && ! git diff --quiet; then
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add --all
- git commit -m "Fix code style issues [skip ci]"
+ git commit -m "Fix code style issues"
git push origin "HEAD:${{ github.head_ref || github.ref_name }}"
fi
@@ -145,7 +149,7 @@ jobs:
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add phpstan-baseline.neon
- git commit -m "Updated PHPStan baseline [skip ci]"
+ git commit -m "Updated PHPStan baseline"
git push origin "HEAD:${{ github.head_ref || github.ref_name }}"
fi
diff --git a/README.md b/README.md
index bb92cf646f909..165da1ebf2f0f 100644
--- a/README.md
+++ b/README.md
@@ -81,12 +81,12 @@ and it will be regenerated on the next call to Joomla.
Using a simple classification keeps the project **stable**, **transparent**, and **easy** for everyone to contribute.
-| Type of change | What it means | Target branch |
-|---|---|-----------------------------------------------------------------------------------|
-| **Bug / Patch release** | The change fixes an actual error. The software crashes, produces the wrong result, or behaves contrary to its specification. It can be resolved without large‑scale refactoring or new functionality. | **[5.4-dev](https://github.com/joomla/joomla-cms/tree/5.4-dev)** (6.2-dev) **\*** |
-| **Feature / Minor release** | Anything that isn’t a strict bug – new behavior, refactoring, performance improvements, enhancements, UI tweaks, etc. These changes are bundled together for the next minor version. | **[6.3-dev](https://github.com/joomla/joomla-cms/tree/6.3-dev)** |
+| Type of change | What it means | Target branch |
+|---|---|-------------------------------------------------------------------------------------------------------------------------------------|
+| **Bug / Patch release** | The change fixes an actual error. The software crashes, produces the wrong result, or behaves contrary to its specification. It can be resolved without large‑scale refactoring or new functionality. | **[6.2-dev](https://github.com/joomla/joomla-cms/tree/6.2-dev)** **\*** |
+| **Feature / Minor release** | Anything that isn’t a strict bug – new behavior, refactoring, performance improvements, enhancements, UI tweaks, etc. These changes are bundled together for the next minor version. | **[6.3-dev](https://github.com/joomla/joomla-cms/tree/6.3-dev)** |
-**\*** All bugs that already exist in version 5.4.x or 6.2.x should be fixed in `5.4-dev` or `6.2-dev`. Only bugs that are introduced for the first time in version 6.3.x should target the [`6.3-dev`](https://github.com/joomla/joomla-cms/tree/6.3-dev) branch.
+**\*** All bugs that already exist in version 5.4.x or 6.1.x or 6.2.x should be fixed in `6.2-dev`.
A member of the maintainer or bug squad team confirms the classification and sets the appropriate labels when a PR is opened. If a PR is opened in the wrong branch, a maintainer will simply ask you to retarget it to the proper branch.
diff --git a/administrator/components/com_config/src/Model/ApplicationModel.php b/administrator/components/com_config/src/Model/ApplicationModel.php
index 2a66c4c80212a..2dd938f3eed28 100644
--- a/administrator/components/com_config/src/Model/ApplicationModel.php
+++ b/administrator/components/com_config/src/Model/ApplicationModel.php
@@ -343,8 +343,8 @@ public function save($data)
return false;
}
- // Check if we can set the Force SSL option
- if ((int) $data['force_ssl'] !== 0 && (int) $data['force_ssl'] !== (int) $app->get('force_ssl', '0')) {
+ // Check if we can set the Force SSL option unless we are in CLI mode, in which case we skip this check
+ if (!$app->isClient('cli') && (int) $data['force_ssl'] !== 0 && (int) $data['force_ssl'] !== (int) $app->get('force_ssl', '0')) {
try {
// Make an HTTPS request to check if the site is available in HTTPS.
$host = Uri::getInstance()->getHost();
diff --git a/administrator/components/com_fields/forms/filter_fields.xml b/administrator/components/com_fields/forms/filter_fields.xml
index 3a349dbe84514..3d601cd01453c 100644
--- a/administrator/components/com_fields/forms/filter_fields.xml
+++ b/administrator/components/com_fields/forms/filter_fields.xml
@@ -4,6 +4,7 @@
diff --git a/administrator/components/com_fields/forms/filter_groups.xml b/administrator/components/com_fields/forms/filter_groups.xml
index 4491214aa1e5b..3bf726fa414ce 100644
--- a/administrator/components/com_fields/forms/filter_groups.xml
+++ b/administrator/components/com_fields/forms/filter_groups.xml
@@ -4,6 +4,7 @@
diff --git a/administrator/components/com_fields/src/Model/FieldModel.php b/administrator/components/com_fields/src/Model/FieldModel.php
index 18e2d8b5aefb3..376abe272296c 100644
--- a/administrator/components/com_fields/src/Model/FieldModel.php
+++ b/administrator/components/com_fields/src/Model/FieldModel.php
@@ -997,9 +997,11 @@ protected function loadFormData()
public function validate($form, $data, $group = null)
{
// Check if the values are unique. This should only apply for list, checkboxes and radio custom field types
- if (\in_array($data['type'], ['list', 'checkboxes', 'radio'])
+ if (
+ \in_array($data['type'], ['list', 'checkboxes', 'radio'])
&& !empty($data['fieldparams']['options'])
- && \is_array($data['fieldparams']['options'])) {
+ && \is_array($data['fieldparams']['options'])
+ ) {
$tmpValues = [];
foreach ($data['fieldparams']['options'] as $option) {
$tmpValues[] = $option['value'];
diff --git a/administrator/components/com_guidedtours/src/Controller/AjaxController.php b/administrator/components/com_guidedtours/src/Controller/AjaxController.php
index cdf73f68fdfdf..7e3706abb9f49 100644
--- a/administrator/components/com_guidedtours/src/Controller/AjaxController.php
+++ b/administrator/components/com_guidedtours/src/Controller/AjaxController.php
@@ -15,6 +15,7 @@
use Joomla\CMS\MVC\Controller\BaseController;
use Joomla\CMS\Plugin\PluginHelper;
use Joomla\CMS\Response\JsonResponse;
+use Joomla\CMS\Session\Session;
// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
@@ -35,6 +36,12 @@ class AjaxController extends BaseController
*/
public function fetchUserState()
{
+ // The request changes persisted user state, so it must carry a valid token.
+ if (!Session::checkToken('get')) {
+ echo new JsonResponse(null, Text::_('JINVALID_TOKEN'), true);
+ $this->app->close();
+ }
+
$user = $this->app->getIdentity();
$tourId = $this->app->getInput()->getInt('tid', 0);
diff --git a/administrator/components/com_installer/tmpl/update/default.php b/administrator/components/com_installer/tmpl/update/default.php
index e493e91f3b0da..7b17f3cdf8c81 100644
--- a/administrator/components/com_installer/tmpl/update/default.php
+++ b/administrator/components/com_installer/tmpl/update/default.php
@@ -105,11 +105,11 @@
update_site_id; ?>
- security)) : ?>
+ security)) : ?>
security); ?>
-
-
+
+
client_translated; ?>
diff --git a/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php b/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php
index 742ebfcbb0f4a..cd532fae82da9 100644
--- a/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php
+++ b/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php
@@ -511,12 +511,20 @@ public function getAutoUpdateVersion(): ?string
*/
public function getAutoUpdateRequirementsState(): bool
{
+ // Check basic requirements of the *current* system
foreach ($this->getPhpOptions() as $option) {
if ($option->state !== true) {
return false;
}
}
+ // Fetch update and check constraints - if the "otherinfo" is set, we have a constraint issue
+ $updateInfo = $this->getUpdateInformation();
+
+ if (!empty($updateInfo['object']) && !empty((array) $updateInfo['object']->get('otherUpdateInfo'))) {
+ return false;
+ }
+
return true;
}
diff --git a/administrator/components/com_menus/src/Model/ItemModel.php b/administrator/components/com_menus/src/Model/ItemModel.php
index 418ed43c5125b..0e698469872c9 100644
--- a/administrator/components/com_menus/src/Model/ItemModel.php
+++ b/administrator/components/com_menus/src/Model/ItemModel.php
@@ -235,6 +235,15 @@ protected function batchCopy($value, $pks, $contexts)
continue;
}
+ // Check that the user is allowed to access the item
+ $itemMenuTypeId = (int) $this->getMenuTypeId($table->menutype);
+
+ if ($table->menutype === 'main' || !$user->authorise('core.edit', 'com_menus.menu.' . $itemMenuTypeId)) {
+ $this->setError(Text::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EDIT'));
+
+ return false;
+ }
+
// Copy is a bit tricky, because we also need to copy the children
$query = $db->createQuery()
->select($db->quoteName('id'))
diff --git a/administrator/components/com_scheduler/tmpl/logs/default.php b/administrator/components/com_scheduler/tmpl/logs/default.php
index 8872b6ce28196..4b8ab2e5383a4 100644
--- a/administrator/components/com_scheduler/tmpl/logs/default.php
+++ b/administrator/components/com_scheduler/tmpl/logs/default.php
@@ -34,7 +34,7 @@
$this]); ?>
items)) : ?>
-
+
diff --git a/administrator/components/com_templates/tmpl/template/default.php b/administrator/components/com_templates/tmpl/template/default.php
index 881f5cc9c2d93..adb5ee1acf6cb 100644
--- a/administrator/components/com_templates/tmpl/template/default.php
+++ b/administrator/components/com_templates/tmpl/template/default.php
@@ -184,10 +184,10 @@
archive as $file) : ?>
-
+ escape($file); ?>
-
+ escape($file); ?>
diff --git a/administrator/components/com_users/forms/user.xml b/administrator/components/com_users/forms/user.xml
index 199662a2c8207..248beb05ffbe9 100644
--- a/administrator/components/com_users/forms/user.xml
+++ b/administrator/components/com_users/forms/user.xml
@@ -259,6 +259,18 @@
+
+
+
+
+
+
+
diff --git a/administrator/components/com_users/src/View/Group/HtmlView.php b/administrator/components/com_users/src/View/Group/HtmlView.php
index 8f4554368b8d6..5745978bac76d 100644
--- a/administrator/components/com_users/src/View/Group/HtmlView.php
+++ b/administrator/components/com_users/src/View/Group/HtmlView.php
@@ -85,7 +85,7 @@ public function display($tpl = null)
// Add form control fields
$this->form
- ->addControlField('task');
+ ->addControlField('task', 'group.save');
$this->addToolbar();
parent::display($tpl);
diff --git a/administrator/components/com_users/src/View/Level/HtmlView.php b/administrator/components/com_users/src/View/Level/HtmlView.php
index b0821a7334bad..fa4650fdacf8c 100644
--- a/administrator/components/com_users/src/View/Level/HtmlView.php
+++ b/administrator/components/com_users/src/View/Level/HtmlView.php
@@ -76,7 +76,7 @@ public function display($tpl = null)
// Add form control fields
$this->form
- ->addControlField('task');
+ ->addControlField('task', 'level.save');
$this->addToolbar();
parent::display($tpl);
diff --git a/administrator/components/com_users/tmpl/captive/select.php b/administrator/components/com_users/tmpl/captive/select.php
index a062464d23ccb..432ac059d3a8a 100644
--- a/administrator/components/com_users/tmpl/captive/select.php
+++ b/administrator/components/com_users/tmpl/captive/select.php
@@ -51,7 +51,7 @@
href="id)?>">
allowEntryBatching || !$allowEntryBatching) : ?>
@@ -62,16 +62,10 @@ class="img-fluid" />
escape($record->title) ?>
-
-
-
-
-
-
diff --git a/administrator/language/en-GB/com_users.ini b/administrator/language/en-GB/com_users.ini
index 1cd983eb0de7f..e8f1df9203641 100644
--- a/administrator/language/en-GB/com_users.ini
+++ b/administrator/language/en-GB/com_users.ini
@@ -10,6 +10,12 @@ COM_USERS_A11Y_SETTINGS_FIELD_CONTRAST="High Contrast"
COM_USERS_A11Y_SETTINGS_FIELD_FONTSIZE="Increase Font Size"
COM_USERS_A11Y_SETTINGS_FIELD_HIGHLIGHT="Highlight Links"
COM_USERS_A11Y_SETTINGS_FIELD_MONOCHROME="Monochrome"
+COM_USERS_A11Y_SETTINGS_FIELD_SHORTCUT_TIMEOUT="Keyboard Shortcut Timeout"
+COM_USERS_A11Y_SETTINGS_FIELD_SHORTCUT_TIMEOUT_DESC="Customise the maximum time between key presses to activate Joomla-specific keyboard shortcuts."
+COM_USERS_A11Y_SETTINGS_SHORTCUT_TIMEOUT_2000="2 seconds"
+COM_USERS_A11Y_SETTINGS_SHORTCUT_TIMEOUT_3000="3 seconds"
+COM_USERS_A11Y_SETTINGS_SHORTCUT_TIMEOUT_5000="5 seconds"
+COM_USERS_A11Y_SETTINGS_SHORTCUT_TIMEOUT_10000="10 seconds"
COM_USERS_ACTIVATED="Activated"
COM_USERS_ADD_NOTE="Add Note"
COM_USERS_ASSIGNED_GROUPS="Assigned User Groups"
diff --git a/administrator/language/en-GB/guidedtours.joomla_whatsnew_6_2_steps.ini b/administrator/language/en-GB/guidedtours.joomla_whatsnew_6_2_steps.ini
index 12daf14d27a49..0e211ea95441d 100644
--- a/administrator/language/en-GB/guidedtours.joomla_whatsnew_6_2_steps.ini
+++ b/administrator/language/en-GB/guidedtours.joomla_whatsnew_6_2_steps.ini
@@ -1,2 +1,2 @@
-COM_GUIDEDTOURS_TOUR_WHATSNEW_6_2_STEP_0_DESCRIPTION="
Many resources to help you can be found here together with additional links to more resources, documentation, support and how to become involved in Joomla.
Many resources to help you can be found here together with additional links to more resources, documentation, support and how to become involved in Joomla.
"
COM_GUIDEDTOURS_TOUR_WHATSNEW_6_2_STEP_0_TITLE="More Information and Help"
diff --git a/administrator/language/en-GB/plg_installer_packageinstaller.ini b/administrator/language/en-GB/plg_installer_packageinstaller.ini
index b8c5d50b47f3d..6f713fd1099d5 100644
--- a/administrator/language/en-GB/plg_installer_packageinstaller.ini
+++ b/administrator/language/en-GB/plg_installer_packageinstaller.ini
@@ -8,7 +8,7 @@ PLG_INSTALLER_PACKAGEINSTALLER_EXTENSION_PACKAGE_FILE="Extension package file"
PLG_INSTALLER_PACKAGEINSTALLER_INSTALLING="Installing …"
PLG_INSTALLER_PACKAGEINSTALLER_NO_PACKAGE="Please select a package to upload."
PLG_INSTALLER_PACKAGEINSTALLER_PLUGIN_XML_DESCRIPTION="This plugin allows you to install extensions from your local computer."
-PLG_INSTALLER_PACKAGEINSTALLER_SELECT_FILE="Or browse for file"
+PLG_INSTALLER_PACKAGEINSTALLER_SELECT_FILE="Browse for file"
PLG_INSTALLER_PACKAGEINSTALLER_UPLOAD_AND_INSTALL="Upload & Install"
PLG_INSTALLER_PACKAGEINSTALLER_UPLOAD_ERROR_EMPTY="Error: Server returns empty response."
PLG_INSTALLER_PACKAGEINSTALLER_UPLOAD_ERROR_UNKNOWN="Error: Unknown error or invalid JSON output."
diff --git a/administrator/language/en-GB/plg_multifactorauth_totp.ini b/administrator/language/en-GB/plg_multifactorauth_totp.ini
index 7de7c1c7aaf26..9bf8d7bd04b50 100644
--- a/administrator/language/en-GB/plg_multifactorauth_totp.ini
+++ b/administrator/language/en-GB/plg_multifactorauth_totp.ini
@@ -9,6 +9,7 @@ PLG_MULTIFACTORAUTH_TOTP_ERR_VALIDATIONFAILED="You did not enter a valid verific
PLG_MULTIFACTORAUTH_TOTP_LBL_LABEL="Enter the six digit verification code"
PLG_MULTIFACTORAUTH_TOTP_LBL_SETUP_INSTRUCTIONS="Set up your verification code (also known as an \"authenticator code\") using the information below. You can use an authenticator app (such Google Authenticator, Authy, LastPass Authenticator, etc), your favourite password manager (1Password, BitWarden, Keeper, KeePassXC, Strongbox, etc) or, in some cases, your browser."
PLG_MULTIFACTORAUTH_TOTP_LBL_SETUP_PLACEHOLDER="Six Digit Code"
+PLG_MULTIFACTORAUTH_TOTP_LBL_SETUP_QR_ALT="QR code for setting up your authenticator app."
PLG_MULTIFACTORAUTH_TOTP_LBL_SETUP_TABLE_HEADING="Authenticator app setup"
PLG_MULTIFACTORAUTH_TOTP_LBL_SETUP_TABLE_KEY="Enter this key"
PLG_MULTIFACTORAUTH_TOTP_LBL_SETUP_TABLE_LINK="Click this link"
diff --git a/administrator/modules/mod_menu/src/Menu/CssMenu.php b/administrator/modules/mod_menu/src/Menu/CssMenu.php
index 0b6fa25f280a6..6f14d631eefb4 100644
--- a/administrator/modules/mod_menu/src/Menu/CssMenu.php
+++ b/administrator/modules/mod_menu/src/Menu/CssMenu.php
@@ -281,7 +281,7 @@ protected function preprocess($parent)
$language = $this->application->getLanguage();
$dispatcher = $this->application->getDispatcher();
- $noSeparator = true;
+ $noSeparator = false;
$children = $parent->getChildren();
/**
diff --git a/administrator/templates/atum/index.php b/administrator/templates/atum/index.php
index e7db74e97d40b..d3f96f135ae72 100644
--- a/administrator/templates/atum/index.php
+++ b/administrator/templates/atum/index.php
@@ -123,20 +123,27 @@ function adjustColorLightness($r, $g, $b, $percent)
}
}
+$a11yClasses = array_filter([
+ $a11y_font ? 'a11y_font' : null,
+ ($a11y_mono || $monochrome) ? 'monochrome' : null,
+ $a11y_contrast ? 'a11y_contrast' : null,
+ $a11y_highlight ? 'a11y_highlight' : null,
+]);
+
Text::script('TPL_ATUM_MORE_ELEMENTS');
// @see administrator/templates/atum/html/layouts/status.php
$statusModules = LayoutHelper::render('status', ['modules' => 'status']);
?>
->
+>
-
+