7566 Commits
Author SHA1 Message Date
ChrisB85andChrisB85 fa040c2ebb Add ChrisB85 to CREDITS.md (#9517)
Requested in #9438.

Co-authored-by: ChrisB85 <792899+ChrisB85@users.noreply.github.com>
2026-10-31 16:54:05 +01:00
Nikolai ShcheglovandAlexandre Alapetite acde1bfbf5 Fix non-ASCII characters in scripts of fetched HTML pages (#9384)
* Fix non-ASCII characters in scripts of fetched HTML pages

To add a <base> to a fetched HTML page, enforceHtmlBase() re-serialises it
with libxml2 saveHTML(). For a whole document, libxml2 2.9 only knows the
charset from <meta http-equiv="Content-Type">: with <meta charset="UTF-8">
or a byte order mark, it writes every non-ASCII character as an HTML entity.
In text that is harmless, but inside <script> entities are not decoded, so
e.g. the JSON read by HTML + XPath + JSON feeds gets "Wall Street&rsquo;s"
instead of "Wall Street’s", which then shows in titles.

UTF-8 documents are now serialised node by node, which writes UTF-8.
Other charsets keep the previous output.

* Clarify comment about the byte order mark

* Remove comment about the byte order mark

* Minor test syntax preference

---------

Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
2026-10-31 14:48:37 +01:00
2ebfff6e7d Add feeds_after_actualize hook (#9438)
Extensions that process new articles in bulk (summaries, exports,
notifications) have no way to react to the end of a refresh:
freshrss_user_maintenance runs before the feeds are fetched, and new
articles stay in the temporary table until the whole loop is done.

The new FeedsAfterActualize hook runs once the new articles are
committed, with the refreshed feeds whose articles changed and the
number of new articles: after a cron or web refresh (actualizeAction,
including the commit-only request of the web interface) and after
actualizeFeedsAndCommit (CLI, API, WebSub, feed added).

Co-authored-by: ChrisB85 <792899+ChrisB85@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 11:38:49 +01:00
Alexandre Alapetite d4964dc1ff WebSub: Implement support for hub.secret (#9430)
* WebSub: Implement support for hub.secret
https://www.w3.org/TR/websub/#signing-content
Fix https://github.com/FreshRSS/FreshRSS/security/advisories/GHSA-498g-vgpq-mr66
`hub.secret` is optional, but improves security.
Reported by @Atharros

* hub.secret SHOULD only be specified when the request was made over HTTPS

* Minor whitespace

* Add legacy support
2026-10-30 22:25:33 +01:00
InverleandAlexandre Alapetite 76e8993579 Replace bcrypt challenge auth with direct password comparison (#9358)
* Replace bcrypt challenge auth with direct password comparison

Closes #2428

Highlights:

* Replaced the bcrypt challenge authentication flow with direct password comparison against the bcrypt hash stored in the user configuration.
  * Removed the `bcrypt.js` dependency, so authentication no longer depends on JavaScript.
  * Removed the nonce and challenge mechanism and the `nonce` endpoint from the `javascript` controller.
  * Removed the JavaScript and HTML code used for the previous authentication flow.
  * Removed the `<noscript>` blocks that were only needed for the previous authentication flow.
* Updated `FreshRSS_FormAuth::checkCredentials()` to accept the username, stored bcrypt hash, and plain-text password directly.
  * The stored password hash must still use the expected bcrypt format.
  * Empty or whitespace-only passwords are rejected even if the hash would otherwise match.
  * The bcrypt 72-byte limit is enforced during normal authentication.
  * Existing bcrypt passwords are handled correctly when the 72-byte limit cuts through a UTF-8 character.
  * Password input is no longer trimmed before authentication or password changes. Leading and trailing whitespace is therefore kept as part of the password.
* Added `FreshRSS_FormAuth::passwordRequirementsMet()` to replace `FreshRSS_password_Util::check()`.
  * New passwords must be between 7 and 72 bytes by default.
  * The minimum length check can be disabled where needed.
  * Password requirements are now checked server-side for all password creation and update paths.
* Added client-side byte-length validation for password fields using `TextEncoder` and `data-max-bytes`.
  * This gives better feedback for UTF-8 passwords.
  * Server-side validation remains authoritative.
* Updated password handling in authentication, re-authentication, self-deletion, user creation, and user update paths so passwords are not trimmed automatically.
* Added `FormAuthTest` to cover:
  * password length limits in bytes
  * UTF-8 passwords around the 72-byte limit
  * bcrypt truncation behavior during authentication
  * malformed and non-bcrypt hashes
  * empty passwords
  * authentication failures and log messages
* Removed `bcrypt.js` from the documented dependencies and updated the authentication documentation.
* Updated the installation and authentication views and JavaScript to match the new password handling.

This simplifies the authentication flow, removes the client-side bcrypt challenge, makes password validation consistent between the client and server, and adds more test coverage while keeping compatibility with existing bcrypt password hashes.

Because the password is now sent directly to the server instead of being processed by `bcrypt.js`, deployments should use HTTPS. Documentation for HTTPS setup can be handled separately.

* Add test case with password truncated down to 71 characters

* Compare log messages too during form auth tests

* Mark the `getLastLog()` method as impure

* Fix: Check password reqs against new password instead of current

* Fix: Add custom JS validator for UTF-8, handle cut-off UTF-8 during login

* Fix: Enforce password requirements everywhere server-side

* Add TODO for updateUser in CLI

* make readme

* Fix extra.js in install.php

* Don't report validity yet if the password is too short or not filled out

* Simplify checking of whether to report validity

* Fix: Do not trim password from user's input

* Also `trim: false` in some userController paths

* Use the proper argument order for PHPUnit's `assertSame()`

* Remove `maxlength` in favor of `data-max-bytes`

But add `pattern` again for some nojs support

* make readme

* composer run-script translations

* Update i18n string for web form admin setting

* i18n: fr

* Minor whitespace

---------

Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
2026-10-30 22:21:26 +01:00
Alexandre Alapetite fd3f75b3a2 Require PHP 8.2+ (#9470)
Drop PHP 8.1 (EOL December 2025), drop Ubuntu 22.04 (EOL May 2027, and there is now 24.04 and 26.04 LTS).
PHP 8.1 is already EOL, and Debian, Alpine, Fedora, Red Hat, Synology have dropped PHP 8.1 already.
See https://github.com/FreshRSS/FreshRSS/discussions/5474#discussioncomment-16791937

With PHP 8.6 around the corner and in particular a relevant `FILTER_FLAG_GLOBAL_RANGE` in PHP 8.2+.
* https://www.php.net/releases/8.2
* https://www.php.net/filter.constants.validation#constant.filter-flag-global-range
* https://www.php.net/class.sensitiveparameter
* https://php.watch/versions/8.2/readonly-classes
* https://www.php.net/function.ini-parse-quantity

Allows updating to PHPUnit 11.x instead of 10.x
https://phpunit.de/supported-versions.html

Contributes to https://github.com/FreshRSS/FreshRSS/issues/9475

* Add regression test for FILTER_FLAG_GLOBAL_RANGE
https://github.com/FreshRSS/FreshRSS/pull/9470#discussion_r4371168720
2026-10-26 21:02:32 +01:00
Frans de JongeandAlexandre Alapetite 54391ce1fb Fix Retry-After cache when proxy is used (#9508)
* Fix Retry-After cache when proxy is used

Because of #8029 and #8218, a proxy would never apply Retry-After.

Possibly related to the problem described in <https://github.com/FreshRSS/FreshRSS/pull/7760#issuecomment-6395796130> by @DamonHD.

* work around line length 168 instead of 165

* Update app/Models/Feed.php

Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
2026-10-26 20:44:26 +01:00
Inverle df96f25fd4 Accept timeouts during lychee CI runs (#9511)
This run would have succeeded for example, if it weren't for `accept_timeouts = false` being set in the config: https://github.com/FreshRSS/FreshRSS/actions/runs/40368577800#summary-121732842378

At the beginning of the original PR (https://github.com/FreshRSS/FreshRSS/pull/9209) I already had `accept_timeouts` set to `true`, but changed my mind later. (it doesn't seem worth it though)
2026-10-26 20:22:58 +01:00
Shaurya Kesarwani 931fb41640 Keep JSON feed attachments as enclosures (#9510)
convertJsonToRss() collected item attachments into
$rssItem['attachments'], but FreshRSS_Entry::fromArray() ignores that
key, so attachments from JSON Feed and JSON dot notation feeds never
reached the generated RSS and were lost. Store them in the entry's
`enclosures` attribute instead, HTML-escaped like the other fields.

- Attachments of JSON Feed and JSON dot notation feeds (`itemAttachment`, `itemAttachmentUrl`, `itemAttachmentType`, `itemAttachmentLength`) were collected by `convertJsonToRss()` into `$rssItem['attachments']`, but `FreshRSS_Entry::fromArray()` never reads that key. So the generated RSS had no `<media:content>` for them and the enclosures were silently dropped. For example, a JSON Feed podcast item with `"attachments": [{"url": "https://example.net/1.mp3", "mime_type": "audio/mpeg"}]` showed up without its audio file.
- The attachments are now stored in the entry's `enclosures` attribute, which is what `rss.phtml` renders. The URL and type are HTML-escaped like the other fields, the length is kept only when numeric, and attachments without a URL are skipped.
- Unit test converting a JSON item with an attachment whose URL contains `&`, asserting the `<media:content url="…&amp;…" type="audio/mpeg" length="1234">` element and valid XML. It fails without the fix.
2026-10-26 08:47:23 +01:00
Alexandre Alapetite 6efe941e0f Changelog 2026-10-25 16:37:51 +01:00
Pythame 87b897c0e4 Add Pythame to CREDITS.md (#9506)
As requested in #9504
2026-10-25 15:23:38 +01:00
Inverle ce34a17e0c Never fail lychee workflow on push events to reduce noise (#9507)
* Never fail lychee workflow on push events to reduce noise

Suggestion for https://github.com/FreshRSS/FreshRSS/pull/9209#issuecomment-6397901959

* Gentoo wiki temp ignore
2026-10-25 15:23:13 +01:00
spa77k 7e9e81d4c7 Update documentation of the article CSS selector (#9505)
Closes #3952

- Replace the outdated Rue89 walkthrough and the list of site-specific selectors (Rue89, PCINpact, Lesnumériques, Phoronix) with step-by-step instructions to find a selector, based on a generic HTML example: use the page source (JavaScript is not run), pick the element containing only the article text, prefer an id or class shared by all articles, and check with the preview button.
- Explain how the retrieved content is used: all matching elements are kept, only new or updated articles are retrieved (with *Reload articles* for existing ones), the content action, the conditions for content retrieval, what happens when nothing matches, sanitized `id`/`class` attributes, and the cookie and user agent options.
- Document *CSS selector of the elements to remove*, including its use without an article CSS selector, where classes must be matched with `[data-sanitized-class~="…"]`.
2026-10-25 13:51:45 +01:00
Pythame bc962e9aad fix: escape labels during JSON import and render tag dropdown as text (#9504)
- Normalize label names parsed from Google Reader JSON categories during import, using the same escaping helper as the other imported string fields.
- Decode stored label names before returning them to the dynamic tag dropdown.
- Build dynamic tag dropdown entries with DOM text nodes instead of HTML string concatenation.
2026-10-25 11:48:58 +01:00
ABDULLAH 7f67975143 Add Abdullah to CREDITS.md (#9503)
As requested in #9502 after the merge of the Arabic translation
2026-10-24 23:38:22 +02:00
ABDULLAH 86b25d1013 Add Arabic (ar) translation (#9502)
* Add Arabic translation

Add a complete Arabic (ar) locale: all interface strings in
app/i18n/ar, Arabic plural forms (nplurals=6), registration of the
language name in gen.lang.ar for all languages, and the regenerated
translation status tables in the READMEs.

* Fix Arabic plural rule flagged by PHPStan
2026-10-24 23:22:43 +02:00
dependabot[bot]andAlexandre Alapetite 743e0422b8 chore(deps): bump the github-actions group with 3 updates (#9501)
Bumps the github-actions group with 3 updates: [ruby/setup-ruby](https://github.com/ruby/setup-ruby), [actions/setup-node](https://github.com/actions/setup-node) and [zizmorcore/zizmor-action](https://github.com/zizmorcore/zizmor-action).


Updates `ruby/setup-ruby` from 1.327.0 to 1.329.0
- [Release notes](https://github.com/ruby/setup-ruby/releases)
- [Changelog](https://github.com/ruby/setup-ruby/blob/master/release.rb)
- [Commits](https://github.com/ruby/setup-ruby/compare/14594264cd68ce8a2345dd349bc3d138a4ef85c8...651ff0d62c5c79bed6d53ec518387aae20e72c1a)

Updates `actions/setup-node` from 7.0.0 to 7.1.0
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/820762786026740c76f36085b0efc47a31fe5020...949feb2413d6458794dcd2491c4babbbce0c15c1)

Updates `zizmorcore/zizmor-action` from 0.6.4 to 0.7.1
- [Release notes](https://github.com/zizmorcore/zizmor-action/releases)
- [Commits](https://github.com/zizmorcore/zizmor-action/compare/cc914d7f3750a2d13d75c7f184a1060aa0e9d482...85b2b9fb8e3325e7a23d7d0a9d7ba5ae0f999e3e)

---
updated-dependencies:
- dependency-name: ruby/setup-ruby
  dependency-version: 1.329.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
- dependency-name: actions/setup-node
  dependency-version: 7.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
- dependency-name: zizmorcore/zizmor-action
  dependency-version: 0.7.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
2026-10-24 23:04:43 +02:00
dependabot[bot] 2bdfdc33f5 chore(deps-dev): bump the bundler group in /docs with 5 updates (#9500)
Bumps the bundler group in /docs with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [jekyll-relative-links](https://github.com/benbalter/jekyll-relative-links) | `0.8.0` | `0.9.1` |
| [jekyll-optional-front-matter](https://github.com/benbalter/jekyll-optional-front-matter) | `0.3.3` | `0.3.4` |
| [jekyll-readme-index](https://github.com/benbalter/jekyll-readme-index) | `0.4.0` | `0.5.1` |
| [jekyll-default-layout](https://github.com/benbalter/jekyll-default-layout) | `0.2.0` | `0.2.1` |
| [jekyll-titles-from-headings](https://github.com/benbalter/jekyll-titles-from-headings) | `0.5.4` | `0.5.7` |


Updates `jekyll-relative-links` from 0.8.0 to 0.9.1
- [Release notes](https://github.com/benbalter/jekyll-relative-links/releases)
- [Changelog](https://github.com/benbalter/jekyll-relative-links/blob/main/CHANGELOG.md)
- [Commits](https://github.com/benbalter/jekyll-relative-links/compare/v0.8.0...v0.9.1)

Updates `jekyll-optional-front-matter` from 0.3.3 to 0.3.4
- [Release notes](https://github.com/benbalter/jekyll-optional-front-matter/releases)
- [Changelog](https://github.com/benbalter/jekyll-optional-front-matter/blob/main/CHANGELOG.md)
- [Commits](https://github.com/benbalter/jekyll-optional-front-matter/compare/v0.3.3...v0.3.4)

Updates `jekyll-readme-index` from 0.4.0 to 0.5.1
- [Release notes](https://github.com/benbalter/jekyll-readme-index/releases)
- [Changelog](https://github.com/benbalter/jekyll-readme-index/blob/main/CHANGELOG.md)
- [Commits](https://github.com/benbalter/jekyll-readme-index/compare/v0.4.0...v0.5.1)

Updates `jekyll-default-layout` from 0.2.0 to 0.2.1
- [Release notes](https://github.com/benbalter/jekyll-default-layout/releases)
- [Changelog](https://github.com/benbalter/jekyll-default-layout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/benbalter/jekyll-default-layout/compare/v0.2.0...v0.2.1)

Updates `jekyll-titles-from-headings` from 0.5.4 to 0.5.7
- [Release notes](https://github.com/benbalter/jekyll-titles-from-headings/releases)
- [Changelog](https://github.com/benbalter/jekyll-titles-from-headings/blob/main/CHANGELOG.md)
- [Commits](https://github.com/benbalter/jekyll-titles-from-headings/compare/v0.5.4...v0.5.7)

---
updated-dependencies:
- dependency-name: jekyll-relative-links
  dependency-version: 0.9.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: bundler
- dependency-name: jekyll-optional-front-matter
  dependency-version: 0.3.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: bundler
- dependency-name: jekyll-readme-index
  dependency-version: 0.5.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: bundler
- dependency-name: jekyll-default-layout
  dependency-version: 0.2.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: bundler
- dependency-name: jekyll-titles-from-headings
  dependency-version: 0.5.7
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: bundler
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-24 22:57:14 +02:00
dependabot[bot] 696590062d chore(deps-dev): bump the stylelint group with 2 updates (#9499)
Bumps the stylelint group with 2 updates: [stylelint](https://github.com/stylelint/stylelint) and [stylelint-order](https://github.com/hudochenkov/stylelint-order).


Updates `stylelint` from 17.15.0 to 17.16.0
- [Release notes](https://github.com/stylelint/stylelint/releases)
- [Changelog](https://github.com/stylelint/stylelint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/stylelint/stylelint/compare/17.15.0...17.16.0)

Updates `stylelint-order` from 8.1.1 to 8.1.2
- [Release notes](https://github.com/hudochenkov/stylelint-order/releases)
- [Changelog](https://github.com/hudochenkov/stylelint-order/blob/master/CHANGELOG.md)
- [Commits](https://github.com/hudochenkov/stylelint-order/compare/8.1.1...8.1.2)

---
updated-dependencies:
- dependency-name: stylelint
  dependency-version: 17.16.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: stylelint
- dependency-name: stylelint-order
  dependency-version: 8.1.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: stylelint
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-24 22:56:54 +02:00
dependabot[bot] 088148d4bd chore(deps-dev): bump the eslint group with 3 updates (#9498)
Bumps the eslint group with 3 updates: [eslint](https://github.com/eslint/eslint), [globals](https://github.com/sindresorhus/globals) and [neostandard](https://github.com/neostandard/neostandard).


Updates `eslint` from 10.11.0 to 10.13.0
- [Release notes](https://github.com/eslint/eslint/releases)
- [Commits](https://github.com/eslint/eslint/compare/v10.11.0...v10.13.0)

Updates `globals` from 17.12.0 to 17.13.0
- [Release notes](https://github.com/sindresorhus/globals/releases)
- [Commits](https://github.com/sindresorhus/globals/compare/v17.12.0...v17.13.0)

Updates `neostandard` from 0.14.0-next.1 to 0.14.1
- [Release notes](https://github.com/neostandard/neostandard/releases)
- [Changelog](https://github.com/neostandard/neostandard/blob/main/CHANGELOG.md)
- [Commits](https://github.com/neostandard/neostandard/compare/v0.14.0-next.1...v0.14.1)

---
updated-dependencies:
- dependency-name: eslint
  dependency-version: 10.13.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: globals
  dependency-version: 17.13.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: neostandard
  dependency-version: 0.14.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: eslint
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-24 22:56:40 +02:00
dependabot[bot] 67db0c4b9d chore(deps-dev): bump the composer-root group with 3 updates (#9497)
Bumps the composer-root group with 3 updates: [phpstan/phpstan](https://github.com/phpstan/phpstan-phar-composer-source), [phpstan/phpstan-phpunit](https://github.com/phpstan/phpstan-phpunit) and [phpstan/phpstan-strict-rules](https://github.com/phpstan/phpstan-strict-rules).


Updates `phpstan/phpstan` from 2.2.16 to 2.3.1
- [Commits](https://github.com/phpstan/phpstan-phar-composer-source/commits)

Updates `phpstan/phpstan-phpunit` from 2.0.19 to 2.1.1
- [Release notes](https://github.com/phpstan/phpstan-phpunit/releases)
- [Commits](https://github.com/phpstan/phpstan-phpunit/compare/2.0.19...2.1.1)

Updates `phpstan/phpstan-strict-rules` from 2.0.12 to 2.1.0
- [Release notes](https://github.com/phpstan/phpstan-strict-rules/releases)
- [Commits](https://github.com/phpstan/phpstan-strict-rules/compare/2.0.12...2.1.0)

---
updated-dependencies:
- dependency-name: phpstan/phpstan
  dependency-version: 2.3.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: composer-root
- dependency-name: phpstan/phpstan-phpunit
  dependency-version: 2.1.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: composer-root
- dependency-name: phpstan/phpstan-strict-rules
  dependency-version: 2.1.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: composer-root
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-24 22:56:19 +02:00
Inverle b8b657488d Fix some broken links from CI scans (#9495)
* Fix some broken links from CI scans

Follow-up of https://github.com/FreshRSS/FreshRSS/pull/9209 and https://github.com/FreshRSS/FreshRSS/pull/9207.

See: https://github.com/FreshRSS/FreshRSS/pull/9209#issuecomment-6383267668

* Apply some selected redirects

* Escape . properly
2026-10-24 22:55:59 +02:00
Inverle 34b9bf43a2 Group auto dependency updates into one PR per ecosystem (#9496)
https://github.com/FreshRSS/FreshRSS/pull/9401#issuecomment-5984319483

(aside from npm exceptions for eslint, stylelint, ... and for separate composer.json: root and lib/)
2026-10-24 22:52:46 +02:00
dependabot[bot] 44fe0d8248 chore(deps): bump fast-uri from 3.1.8 to 3.1.9 (#9494)
Bumps [fast-uri](https://github.com/fastify/fast-uri) from 3.1.8 to 3.1.9.
- [Release notes](https://github.com/fastify/fast-uri/releases)
- [Commits](https://github.com/fastify/fast-uri/compare/v3.1.8...v3.1.9)

---
updated-dependencies:
- dependency-name: fast-uri
  dependency-version: 3.1.9
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-24 14:13:27 +02:00
InverleandAlexandre Alapetite 456b9fbff5 Add a link checker workflow using lychee (#9209)
* Add a link checker workflow using lychee

Depends on #9207 (merged)

https://github.com/lycheeverse/lychee-action

* Adjust cron to run once every month instead

* Apply suggestions

* Pass zizmor's pedantic audit

* Set `failIfEmpty: false` for lychee action

* Add offline Lychee check to catch broken links after renames

* Add workaround for `--files-from` option not respecting `extensions`

* Escape `?` correctly in `.lycheeignore`

* Don't accept timeouts, retry instead

* Bump link checker workflow to `ubuntu-26.04`

* Always scope to host correctly in `.lycheeignore`

* Set `hidden = true` in config to ensure that dotfiles are scanned

* Exclude issue template from the scan

* with open

---------

Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
2026-10-24 09:51:08 +02:00
Ron RichterandClaude Opus 5.5 22c3128b23 Fix escaping of JSON dot notation categories (#9489)
convertJsonToRss() HTML-escapes item fields before rendering the RSS,
but the is_string() guard skipped 'tags', which is always an array.
An unescaped & in a JSON category then produced invalid XML, so
SimplePie rejected the whole document and the feed showed as empty.

Minz_Helper::htmlspecialchars_utf8() already handles arrays,
so the guard is dropped. Add a test for array and string categories.

fix https://github.com/FreshRSS/FreshRSS/issues/9488

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 23:06:29 +02:00
darodi 9e38e2e405 Update CREDITS.md (#9487) 2026-10-22 23:21:28 +02:00
darodi f436b43c82 32-bit systems provide a string for BIGINT (#9486)
Fix #9485
2026-10-22 22:35:47 +02:00
spa77k bf0bedae1c Docker: Explain how to update with volumes and Compose (#9480)
Closes #4942

- Explain in *How to update* that data and extensions stay in the Docker volumes, so updating only means running a newer image with the same volumes, and recommend a back-up first.
- Add the Docker Compose variant (`pull` then `up` with the same `-f` files).
- Warn to keep the same major version of the PostgreSQL image when updating FreshRSS (a new major version refuses to start with older data), pointing to *Migrate database*, and to check `.env` variable names when replacing Compose files with newer copies.
2026-10-22 22:18:30 +02:00
Alexandre Alapetite 7de3c981d4 Start next version 2026-10-21 22:53:14 +02:00
Alexandre Alapetite 08f97bd497 Release FreshRSS 1.30.4
fix https://github.com/FreshRSS/FreshRSS/issues/9475
1.30.4
2026-10-21 22:33:48 +02:00
Nat Welch 2258f411d3 Docker: disable session.upload_progress
Disable this unused option for improved security, as recommended by PHP documentation
https://www.php.net/session.upload-progress
https://www.php.net/session.configuration#ini.session.upload-progress.enabled
2026-10-21 22:27:32 +02:00
Alexandre Alapetite 7181627f2b 1.30.4-dev while waiting for Alpine 2026-10-21 21:47:49 +02:00
Frans de Jonge 4fcd095a84 Translate new Dutch strings (#9479) 2026-10-21 21:04:43 +02:00
Alexandre Alapetite 67a641b2c8 Release 1.30.3
https://www.php.net/archive/2026.php#2026-10-21-5
Excluding Alpine for now
1.30.3
2026-10-21 16:20:20 +02:00
Ricardo SimõesandAlexandre Alapetite f84020a5b4 i18n: Update pt-PT localization (#9473)
* i18n: Update pt-PT localization in feedback.php

- Translate missing strings (resolve TODO comments)
- Fix Brazilian Portuguese terminology to European Portuguese (pt-PT)
- Standardize phrasing according to FreshRSS i18n conventions

* i18n: Update pt-PT localization in admin.php

- Translate missing strings (resolve TODO comments)
- Fix Brazilian Portuguese terminology to European Portuguese (pt-PT)
- Standardize phrasing according to FreshRSS i18n conventions

* i18n: Update pt-PT localization in api.php

- Translate missing strings (resolve TODO comments)
- Fix Brazilian Portuguese terminology to European Portuguese (pt-PT)
- Standardize phrasing according to FreshRSS i18n conventions

* i18n: Update pt-PT localization in conf.php

- Translate missing strings (resolve TODO comments)
- Fix Brazilian Portuguese terminology to European Portuguese (pt-PT)
- Standardize phrasing according to FreshRSS i18n conventions

* i18n: Update pt-PT localization in gen.php

- Translate missing strings (resolve TODO comments)
- Fix Brazilian Portuguese terminology to European Portuguese (pt-PT)
- Standardize phrasing according to FreshRSS i18n conventions

* i18n: Update pt-PT localization in index.php

- Translate missing strings (resolve TODO comments)
- Fix Brazilian Portuguese terminology to European Portuguese (pt-PT)
- Standardize phrasing according to FreshRSS i18n conventions

* i18n: Update pt-PT localization in sub.php

- Translate missing strings (resolve TODO comments)
- Fix Brazilian Portuguese terminology to European Portuguese (pt-PT)
- Standardize phrasing according to FreshRSS i18n conventions

* i18n: Update pt-PT localization in user.php

- Translate missing strings (resolve TODO comments)
- Fix Brazilian Portuguese terminology to European Portuguese (pt-PT)
- Standardize phrasing according to FreshRSS i18n conventions

* i18n: Update pt-PT localization in install.php

- Translate missing strings (resolve TODO comments)
- Fix Brazilian Portuguese terminology to European Portuguese (pt-PT)
- Standardize phrasing according to FreshRSS i18n conventions

* Fixed previous word "Link" not translated

* make fix-all + IGNORE

---------

Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
2026-10-21 15:54:02 +02:00
Inverle 0addf32b36 Translate non-English code comments and identifiers (#9383)
Note: The changes in this PR are entirely AI-authored but manually reviewed and tested

## Summary

Translate the remaining French prose and French-derived identifiers in the main FreshRSS/Minz codebase to English.

Why: helps to understand the code

## Scope

- Minz comments, PHPDoc, and paginator identifiers
- Application comments and related identifiers
- Installer database identifiers
- Theme metadata descriptions and the identified CSS comments, previous discussion: https://github.com/FreshRSS/FreshRSS/pull/8241#discussion_r2553181653
- Related call sites and view helpers

External libraries and intentional i18n/docs content are excluded.
2026-10-20 09:52:31 +02:00
Inverle b33749fe6c New hook: Minz_HookType::AutofillField for auth views (#9362)
* New hook: `Minz_HookType::AutofillField` for auth views

Currently to be used in the Demo extension, because it overrides both the formLogin and reauth views (for autofilling username/password), it can be broken every time there is a slight change in core.
For example, after https://github.com/FreshRSS/FreshRSS/pull/9358.

In the future the hook can be extended to support more fields.

Demo extension PR: https://github.com/FreshRSS/xExtension-Demo/pull/6

* Suggested alternative without returning HTML code
2026-10-19 23:10:38 +02:00
Alexandre Alapetite 020ef5515a Start next version 2026-10-19 23:08:37 +02:00
Alexandre Alapetite 417780ac46 Release 1.30.2 1.30.2 2026-10-19 22:38:20 +02:00
Alexandre Alapetite 8a9471e83b Changelog + credits 2026-10-19 22:28:25 +02:00
spa77kandAlexandre Alapetite c5dd38b0d5 Preserve explicit sort overrides when searching (#9467)
* Preserve explicit sort overrides when searching

Closes #9466

Changes proposed in this pull request:

- Keep an explicit sort override when submitting the header search form, including `c.name`, `f.name` and `lastUserModified`.
- Continue using the already validated `FreshRSS_Context::$sort` value; omit the hidden field when no non-empty override was requested.
- Add header-rendering regression tests for all nine supported sorts, absent/empty overrides and invalid input.

* A bit more fixing

* Fix line mistake

* Forgotten plaintext

* Fix test

---------

Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
2026-10-19 20:27:22 +02:00
Danny 8769b4e29b Do not log the Fever API key on authentication failure (#9468)
## Problem

``p/api/fever.php`` logs the full Fever API key on every authentication failure:

```php
Minz_Log::warning('Fever API: wrong credentials! ' . $feverKey .
    ' ; Remote IP address=' . Minz_Request::connectionRemoteAddress(), API_LOG);
```

The Fever key is the user's equivalent API password and it does not expire, so it lands in ``data/users/<user>/log_api.txt`` (written at the default production log level) where anyone with log read access can harvest it. Failed-auth attempts are exactly the case where the submitted credential should never be persisted — this looks like a leftover from before the earlier log-scrubbing pass (#5001).

## Fix

Keep the remote IP address (useful for brute-force monitoring) but drop the key from the message. One-line change; no behavior change otherwise.
2026-10-19 20:21:35 +02:00
spa77k 6ada118555 Document force-https.txt (#9460)
Closes #4616

The _Force HTTPS_ mechanism (`./force-https.default.txt` and `./data/force-https.txt`) was not documented. This adds a short section to the admin page about configuration without a user interface.
2026-10-19 14:49:45 +02:00
Inverle 0d35f6f0ad i18n: pl (#9458) 2026-10-18 22:22:11 +02:00
tomac4tandInverle 859a2ad039 Fix local DNS leak when fetching feeds through a proxy (#9451)
* Fix local DNS leak when fetching feeds through a proxy

Follow-up to #9390: `getRetryAfterFile()` passed the full URL to
`Minz_Request::serverIsPublic()`, which then resolved the target hostname
with the local resolver (`dns_get_record()`), even when a proxy was
configured. With a socks5h/socks4a proxy this leaks the target hostname
to the local DNS and defeats remote name resolution.

- `Minz_Request::serverIsPublic()`: add an `$allowDnsResolve` parameter,
  and forward it to the recursive call so the guard holds for the whole
  recursion.
- `FreshRSS_http_Util::getRetryAfterFile()`: do not resolve the host name
  when a proxy is configured (`$proxy === ''`), since the proxy is
  responsible for DNS.

---------

Co-authored-by: Inverle <inverle@proton.me>
2026-10-17 17:37:27 +02:00
Alexandre Alapetite 6597590b56 Changelog + missing credits 2026-10-16 13:55:32 +02:00
ImperfectBlu 79499b7619 Add ImperfectBlu to CREDITS.md (#9448)
Adds ImperfectBlu to CREDITS.md, following #9417 and FreshRSS/simplepie#92.
2026-10-16 08:10:42 +02:00
Inverle 74556f806f Disallow user page navigation while refreshing feeds (#9446)
For example to prevent an accidental tab closing during feeds refresh.
(beforeunload confirmation is used to achieve this, similar to leave validation)
2026-10-15 22:29:41 +02:00
HawkForge fca56488c0 Add HawkForge to CREDITS.md (#9442)
Adds HawkForge to CREDITS.md, as requested in #9441.
2026-10-15 22:27:57 +02:00