Commit Graph
7545 Commits
Author SHA1 Message Date
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
Inverle c8d859b88d Update registerHook docs with newer PHP 8.1+ syntax for callables (#9443)
* Update registerHook docs with newer PHP 8.1+ syntax for callables

* Use the correct function name for the second hook

* Use correct return type for the second hook function
2026-10-15 19:51:52 +02:00
Inverle ed34f6a21d Fix wrong order of args in extension compatibility check (#9445)
See https://www.php.net/manual/function.version-compare.php

The extension's minimum required FreshRSS version must be compared against the currently running version, not the other way around.

Assuming the running FreshRSS version is `1.30.1`:

| Minimum required version | Expected status | Before this fix | After this fix |
|---|---|---|---|
| `1.27.0` | ✅ Compatible | ❌ Incompatible | ✅ Compatible |
| `1.30.1` | ✅ Compatible | ✅ Compatible | ✅ Compatible |
| `1.31.0` | ❌ Incompatible | ✅ Compatible | ❌ Incompatible |
2026-10-15 19:47:06 +02:00
HawkForge 6d30fb4af0 Fix Mark as read button left edge in Origine on mobile (#9441)
At max-width 840px the text button is hidden and only the dropdown toggle
is shown. Origine restores its left border and radius with a rule that
used `#nav_menu_read_all .btn` until #9205 turned the ID into a class.
`.nav_menu_read_all .btn` is now weaker than the generic
`.stick .btn + .dropdown > .btn` and `.group .dropdown:last-child > .btn`
rules, so the toggle lost its left border and rounded left corners.
Use the same selector as the other themes.

Closes #9428
2026-10-15 16:34:02 +02:00
EmreandAlexandre Alapetite 87187136ec docs: updates websub_pending entry in sub.php (#9439)
* Update websub_pending entry in sub.php

Translated the websub_pending attribute entry in sub.php in german

* make fix-all

---------

Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
2026-10-15 16:11:57 +02:00
Alexandre Alapetite f617083328 Mitigate some 404 situations (#9435)
* Mitigate some 404 situations
Fix https://github.com/FreshRSS/FreshRSS/issues/9413 (maybe)
See https://www.php.net/function.session-regenerate-id

* Keep error_code in Session as well

* Ensure login_ok is false
2026-10-15 16:11:21 +02:00
EmreandAlexandre Alapetite f800a4304d docs: updates turkish websub_pending entry in sub.php (#9440)
* docs: updates turkish websub_pending entry in sub.php

Modified the websub_pending attribute entry in sub.php in turkish

* make fix-all

---------

Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
2026-10-14 16:24:52 +02:00
Alexandre Alapetite 7e8ef628d9 Better doc and log proxy cases (#9436)
Fix https://github.com/FreshRSS/FreshRSS/issues/9423
And strip redundant proxy scheme.
And add a few more unit tests.
2026-10-13 19:50:38 +02:00
Alexandre Alapetite 15d57cea88 Changelog 2026-10-12 12:05:56 +02:00
M. Önlük 9e53bdd223 Fix missing left outline on Mark as read button (#9426)
The hidden CSRF input was the first child of the form, directly before the
Mark as read button. Theme rules such as `.stick input + .btn` and
`.stick .btn:first-child` therefore treated the button as the second element
of an input + button group: no left border and no rounded left corners.
Move the input back inside the dropdown, as it was before #9205.

Fixes #9359

Changes proposed in this pull request:

- In `app/layout/nav_menu.phtml`, move the hidden `_csrf` input of the "Mark as read" form back inside the `#nav_menu_read` dropdown (where it was before #9205), instead of being the first child of the form right before the `read_all` button.
- Because of that input, many theme rules written for `input + .btn` groups (`.stick input + .btn`, and `.btn:first-child` no longer matching) removed the left border and the rounded left corners of the "Mark as read" button. This affected Alternative Dark, Origine and the themes built on them (Dark, Dark-pink, Origine-compact), Pafat, and gave a stray separator and square corners in Flat, Ansum and Mapco.
2026-10-12 09:21:10 +02:00
0187b15c8e Sanitizer: block data: URI scheme while keeping data:image for images (#9417)
* Sanitizer: block data: URI scheme, keep data:image for images

FreshRSS_SimplePieCustom only disallowed the `javascript` scheme, so
`data:text/html,...` URIs in feed content survived
sanitization on <a href>, <iframe src>, <audio|video|source|track src>.
The default CSP neutralises these on FreshRSS pages, but clients and
deployments without that CSP (API WebViews, extensions using amendCsp(),
proxies stripping headers) could execute them. Same class as
GHSA-3fw6-j8m4-82vj / #9272.

- Sanitize::is_allowed_uri(): element/attribute-aware check that still
  permits inert `data:image/...` on img[src], image[src], video[poster]
  while blocking `data:` elsewhere; replace_urls() now uses it.
  is_allowed_scheme() is unchanged for backward compatibility.
- SimplePieCustom: disallow_uri_schemes(['javascript','data']).
- Tests: 4 blocked-input cases, a data:image keep-alive test and an
  `unsafe:` prefix test. They fail without the patch and pass with it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* Sync SimplePie
https://github.com/FreshRSS/simplepie/pull/92

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
2026-10-11 20:36:09 +02:00
Alexandre Alapetite 308b1726ec CI/CD: Login to Docker Hub (#9433)
Fix Error: Error response from daemon: toomanyrequests: You have reached your unauthenticated pull rate limit. https://www.docker.com/increase-rate-limit
2026-10-11 10:41:18 +02:00
spa77k 9c04882cc1 Document how to use the User CSS and User JS core extensions (#9424)
Closes #9394

## Summary

The _User CSS_ and _User JS_ sections already existed in the user documentation, but they did not say where to find the settings. This explains that each extension has a gear icon (_Manage_) next to its switch, and gives the steps to use both extensions.

## Changes

- `docs/en/users/05_Configuration.md`: describe the extension list (switch, gear icon, name), add the steps for User CSS, and the same for User JS with a note that it might ask to sign in again.
- `docs/en/users/05_Configuration.md`, `docs/en/admins/11_Themes.md`, `docs/en/contributing.md`: the "CustomCSS extension" links pointed to FreshRSS/Extensions, where it is no longer available. They now point to the built-in User CSS section.
- `docs/en/admins/15_extensions.md`, `lib/core-extensions/README.md`: list the two core extensions with links to their documentation. Also fix the `.lib/core-extensions` path.
- `CREDITS.md`: add my name.

Only the English documentation is changed.
2026-10-09 23:04:22 +02:00
Alexandre Alapetite c7c53f4576 WebSub fix POST, fix warning, better message (#9420)
* WebSub fix warning and better message
Contributes to https://github.com/FreshRSS/FreshRSS/issues/9416

* Fix POST conditions
2026-10-09 22:28:18 +02:00
dependabot[bot] aa6b46ba96 chore(deps): bump source-map-js from 1.2.1 to 1.2.2 (#9425)
Bumps [source-map-js](https://github.com/7rulnik/source-map-js) from 1.2.1 to 1.2.2.
- [Release notes](https://github.com/7rulnik/source-map-js/releases)
- [Changelog](https://github.com/7rulnik/source-map-js/blob/main/CHANGELOG.md)
- [Commits](https://github.com/7rulnik/source-map-js/compare/v1.2.1...v1.2.2)

---
updated-dependencies:
- dependency-name: source-map-js
  dependency-version: 1.2.2
  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-09 10:19:00 +02:00
Inverle 07617c48e6 Fix SVGO zero percent filtering in CI (#9422)
Because of the environment variable `CI=true` being passed in GitHub Actions to SVGO, it outputted colored text with ANSI escape sequences, which broke the awk 0% filtering (for unchanged files).

Ref: https://github.com/FreshRSS/FreshRSS/pull/9361#discussion_r4147827482
2026-10-09 08:17:58 +02:00
Alexandre Alapetite 4a3c6b6b60 Fix PHP 8.5+ deprecation sqliteCreateFunction (#9421)
Fix https://github.com/FreshRSS/FreshRSS/issues/8525#issuecomment-6065641500
2026-10-08 22:55:00 +02:00
Alejandro Borrego 219eaf58a7 Add Alejandro Borrego to CREDITS.md (#9412)
Following #9350
Co-authored-by: Alejandro Borrego <210245044+abp002@users.noreply.github.com>
2026-10-06 08:25:51 +02:00
abp002andAlejandro Borrego 48547b4a6c Reduce memory consumption of export (#9350)
Contributes to #6139 (export part; the import will follow in another PR)

Exporting favourites was collecting the whole file in memory. With many articles, it fails with the default PHP memory limit.

## Changes
- New `Minz_View::helperToFile()`, similar to `helperToString()`, writing the output of a helper into a file by chunks of 64 KiB instead of keeping it in memory.
- `FreshRSS_Export_Service`: the `generate*()` methods now return the path of a temporary file instead of the content, and `zip()` builds the archive from those files (`ZipArchive::addFile()` instead of `addFromString()`). Temporary files are created in `TMP_PATH` (already required to be writable) and deleted at the end of the script.
- The export is sent with `readfile()`: Web UI, `cli/export-zip-for-user.php`, `cli/export-opml-for-user.php` and the OPML export of the Google Reader API.
- Note: this changes what `FreshRSS_Export_Service` returns (a path instead of the content). All callers in the repository are updated, and I could not find any public extension using this service.

## Measurements
Peak PHP memory (`memory_get_peak_usage(true)`), SQLite database with synthetic starred articles:

| Scenario | Before | After |
|---|---|---|
| Web, export your favourites, 10,000 articles (69 MB JSON) | 136 MB (fails with the default `memory_limit` of 128 MB) | 6 MB |
| Web, ZIP (OPML + favourites + labelled articles + 4 feeds), 10,000 articles | 152 MB | 6 MB |
| CLI `export-zip-for-user.php`, 10,000 articles | 189 MB (fails with 128 MB) | 8 MB |
| Web, export your favourites, 30,000 articles (208 MB JSON) | 404 MB | 10 MB |

Co-authored-by: Alejandro Borrego <210245044+abp002@users.noreply.github.com>
2026-10-05 21:47:19 +02:00
Alexandre Alapetite c7396a3a68 Update to GT\CssXPath 1.6.0 (#9411)
https://github.com/phpgt/CssXPath/releases/tag/v1.6.0
2026-10-05 21:44:57 +02:00
Alexandre Alapetite 588dd92d77 Start 1.30.2-dev 2026-10-05 21:43:00 +02:00
Alexandre Alapetite 4a810f1624 Release 1.30.1 1.30.1 2026-10-05 21:19:07 +02:00