Commit Graph
414 Commits
Author SHA1 Message Date
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
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 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
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 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
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
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
dependabot[bot] 522c560922 chore(deps-dev): bump jekyll-default-layout from 0.1.5 to 0.2.0 in /docs (#9407)
Bumps [jekyll-default-layout](https://github.com/benbalter/jekyll-default-layout) from 0.1.5 to 0.2.0.
- [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.1.5...v0.2.0)

---
updated-dependencies:
- dependency-name: jekyll-default-layout
  dependency-version: 0.2.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-05 06:10:15 +02:00
dependabot[bot] fc099016d3 chore(deps-dev): bump jekyll-relative-links from 0.7.0 to 0.8.0 in /docs (#9405)
Bumps [jekyll-relative-links](https://github.com/benbalter/jekyll-relative-links) from 0.7.0 to 0.8.0.
- [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.7.0...v0.8.0)

---
updated-dependencies:
- dependency-name: jekyll-relative-links
  dependency-version: 0.8.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-05 06:09:31 +02:00
dependabot[bot] a28ae9056e chore(deps-dev): bump jekyll-readme-index from 0.3.0 to 0.4.0 in /docs (#9403)
Bumps [jekyll-readme-index](https://github.com/benbalter/jekyll-readme-index) from 0.3.0 to 0.4.0.
- [Release notes](https://github.com/benbalter/jekyll-readme-index/releases)
- [Changelog](https://github.com/benbalter/jekyll-readme-index/blob/master/CHANGELOG.md)
- [Commits](https://github.com/benbalter/jekyll-readme-index/compare/v0.3.0...v0.4.0)

---
updated-dependencies:
- dependency-name: jekyll-readme-index
  dependency-version: 0.4.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-04 23:03:30 +02:00
dependabot[bot] e03c1616c6 chore(deps-dev): bump jekyll-optional-front-matter in /docs (#9404)
Bumps [jekyll-optional-front-matter](https://github.com/benbalter/jekyll-optional-front-matter) from 0.3.2 to 0.3.3.
- [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.2...v0.3.3)

---
updated-dependencies:
- dependency-name: jekyll-optional-front-matter
  dependency-version: 0.3.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-04 22:57:57 +02:00
dependabot[bot] fc1b40a70a chore(deps-dev): bump jekyll-titles-from-headings in /docs (#9402)
Bumps [jekyll-titles-from-headings](https://github.com/benbalter/jekyll-titles-from-headings) from 0.5.3 to 0.5.4.
- [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.3...v0.5.4)

---
updated-dependencies:
- dependency-name: jekyll-titles-from-headings
  dependency-version: 0.5.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-04 22:56:51 +02:00
InverleandAlexandre Alapetite 0285dc8970 Check SVG optimization in the tests CI workflow with SVGO (#9361)
* Check SVG optimization in the tests CI workflow with SVGO

Previously it was only recommended by the documentation that SVG images should be optimized using [SVGOMG](https://github.com/jakearchibald/svgomg), the web GUI version of https://github.com/svg/svgo (CLI)


Now all SVG images are optimized, and optimization is mandatory enforced by the tests CI workflow.
\+ SVGs are sanitized of potentially malicious JS code using the https://svgo.dev/docs/plugins/removeScripts/ plugin

* Output prettified SVGs instead and remove unchanged files from stdout

Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>

* Use `removeScripts` SVGO plugin to reduce risk of malicious SVGs

* Move the CLI options to the JS config instead

* Disable `removeComments` plugin included in the default preset

* editorconfig, and easier config

---------

Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
2026-09-29 16:18:01 +02:00
Yuchen Shi 818b57a9a9 Update documentation of TRUSTED_PROXY syntax and document limitations. (#9283)
* Update documentation of TRUSTED_PROXY syntax and document limitations.

Single IPs are now supported as of #9301.
Document the existing limitation of domain names, see #9210.

For IPs without `/`, I manually tested the behavior and found requests got rejected on my server before #9301. After #9301 is merged, I've tested again and found that requests are now authorized as expected. So I've updated the corresponding documentation to say "_IPs or_ ranges" where applicable.

Domain names are still silently ignored as of writing. I looked at the code, as described in #9210 investigation steps, and concluded that they are WAI (working as _implemented_ , not sure if _intended_ ). I don't particularly like the existing behavior (failures with no debuggable warnings or logs) but I try to document it as-is without judgement.

* Update TRUSTED_PROXY comments accordingly for Docker usage.

Single IPs are now supported as of #9301.
Document the existing limitation of domain names, see #9210.
2026-09-28 08:53:12 +02:00
Pavel Miniutka fcc41b6ea0 Add Belarusian (be) translation (#9351)
Complete interface translation under app/i18n/be/. The locale is
registered in all app/i18n/*/gen.php, .typos.toml, docs and READMEs.
2026-09-26 14:57:04 +02:00
Zain QureshiandClaude Opus 5.5 0a5c0ca148 docs: fix dead section anchors in English First steps guide (#9348)
Changes proposed in this pull request:

- `docs/en/users/02_First_steps.md` links to four section anchors that don't exist on the English pages. The ids look like literal translations of the French headings, but the English headings are worded differently:
  - `04_Subscriptions.md#import-and-export` -> `#import-export` (`## Import / export`)
  - `04_Subscriptions.md#feed-management` -> `#subscription-management` (`## Subscription management`)
  - `05_Configuration.md#changing-the-view` -> `#display` (`## Display`, the section the French page links as "Personnaliser la vue")
  - `05_Configuration.md#reading-options` -> `#reading` (`## Reading`)
- The French page already resolves correctly, so this only touches the English source.

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-25 08:53:17 +02:00
Alexandre AlapetiteandInverle cea88ace69 Reword explanations for edge/latest channels (#9270)
* Reword explanations for edge/latest channels
Highlight the fact that we do not backport bug fixes or security fixes to previous releases.
Simplify also a slightly obsolte MySQL doc to favour SQLite

* Merge i18n: az

* Update Polish translations to specify rolling/versioned releases

Co-authored-by: Inverle <inverle@proton.me>

* Update 05_Release_new_version.md

---------

Co-authored-by: Inverle <inverle@proton.me>
2026-09-08 23:25:18 +02:00
Inverle 0a44b7d017 Follow-up #9169 remove form IDs everywhere (#9205)
* Follow-up #9169 remove form IDs everywhere

* Add some `<form name>` alongside `class`
2026-08-29 23:21:39 +02:00
Luis Carlos SimitanaandAlexandre Alapetite 03e871e5be Add configurable log_level system setting (#9185)
* Add configurable log_level system setting

Minz_Log currently only distinguishes 'production' (errors and
warnings only) from any other environment (everything, including
debug messages), with no granularity in between.

Introduce an optional 'log_level' system setting (error, warning,
notice, info, or debug) that overrides the verbosity implied by
'environment'. It defaults to an empty string, which preserves the
exact current behaviour.

Fixes #7594

* Slight rewrite

---------

Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
2026-08-25 16:18:30 +02:00
InverleandAlexandre Alapetite a84c0a8bc2 Fix all broken links in the entire repository (#9207)
* Fix all broken links in the entire repository

* Update docs/CHANGELOG-old2.md

Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>

* Update config.default.php

Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>

* Update README.md

Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>

* Update docs/i18n/freshrss.fr.po

Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>

* Update docs/i18n/templates/freshrss.pot

Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>

* Update README.md

Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>

* Update docs/fr/users/01_Installation.md

Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>

* Update docs/fr/users/01_Installation.md

Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>

* Update docs/en/internationalization.md

Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>

* Manual fixes, preferences
* Prefer canonical when known, prefer shorter, prefer roots, prefer URLs with content negotation (e.g. language preference)
* Keep 302, 307 unchanged
* Use only `.example`, `example.net` or similarly reserved domains for URL examples

* Fix language negotiation for developer.mozilla.org

* Restore a Stackoverflow 302

* Fix some example.com

---------

Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
2026-08-19 16:19:21 +02:00
CronandAlexandre Alapetite 09478222ce Docker/OIDC: redirect to a default URL on expired auth state instead of 400-ing (#9143)
## Problem

With OIDC on the official Docker image, interactive SSO logins intermittently return `HTTP 400` at the `/i/oidc/` callback. The failure tracks login duration. `mod_auth_openidc` sets an anti-CSRF state cookie bounded by `OIDCStateTimeout` (default 300 s). If a login through an external IdP takes longer than that (MFA, a slow provider screen, the user stepping away), the cookie is already gone when the callback returns. The image does not set `OIDCDefaultURL`, so the module has no fallback and returns an error instead of restarting the login.

Apache log:

```
oidc_response_proto_state_restore: state has expired
oidc_response_process: invalid authorization response state and
        no default SSO URL is set, sending an error...
→ GET /i/oidc/?code=…&state=… 400
```

This is [documented mod_auth_openidc behaviour](https://github.com/OpenIDC/mod_auth_openidc/blob/72c9f479c2d228477ff0a9518964f61879c83fb6/auth_openidc.conf#L723-L733) when `OIDCDefaultURL` is unset. Both `OIDCDefaultURL` and `OIDCStateTimeout` are `RSRC_CONF` (server config only), so the `./FreshRSS/p/i/.htaccess` escape hatch cannot set them and the fix has to live in the image.

Reproduce: log out, start SSO, wait more than 5 minutes on the IdP screen, complete.

## Fix

Add `OIDC_DEFAULT_URL`, wired through the existing `${OIDC_*}` env pattern, defaulting to `/i/` (the index, consistent with `OIDCRedirectURI /i/oidc/`). On an expired or unmatchable state the module now redirects to `/i/`, which is protected and starts a fresh login against the existing IdP session. `OIDCStateTimeout` stays at 300 s; the window is fine, the missing fallback was the bug.

`OIDC_STATE_TIMEOUT` is intentionally not exposed. It can be added the same way if there is a reason to tune the window.

* Docker/OIDC: redirect to a default URL on expired auth state instead of 400-ing

Adds OIDC_DEFAULT_URL (default /i/), wired through the existing ${OIDC_*} env
pattern, so an expired or unmatchable mod_auth_openidc state redirects to the
FreshRSS index and restarts the login instead of returning HTTP 400.

* git commit update

---------

Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
2026-07-24 17:55:36 +02:00
ccf7c7a9dc Clarify archiving/purge documentation (#9135)
* Clarify archiving/purge documentation

Explain purge policy priority (feed > category > global), the discovery-date based purge logic, and that purging is only triggered on a random subset of feed refreshes (or via Purge now / cli/purge.php).

Fixes #6863.

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

* Typographic quotes

* No changelog for (minor) documentation

---------

Co-authored-by: Gerard Alvear <gerard.alvear@logiqd.me>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
2026-07-23 14:08:54 +02:00
Frans de JongeandAlexandre Alapetite d519a8a9e6 AI skills: suggestion to limit the number of PRs (#9141)
* AI skills: suggestion to limit the number of PRs

* review comments

* tweak phrasing

* Bump to 10

---------

Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
2026-07-23 13:13:47 +02:00
InverleandAlexandre Alapetite 48abfd58fa Improve SSRF mitigations by restricting CURLOPT_PROXY (#8950)
* Improve SSRF mitigations by restricting `CURLOPT_PROXY`

Follow-up of https://github.com/FreshRSS/FreshRSS/pull/8400
SimplePie PR: https://github.com/FreshRSS/simplepie/pull/83

* Reword docs

* Change single quote to backquote in docs

* Fix `cURL error 5: Could not resolve proxy: Array` error

* Sync SimplePie

* A few fixes

* Implement suggestion

* A few more fixes

* Sync composer
https://github.com/FreshRSS/simplepie/pull/83

---------

Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
2026-07-23 13:05:53 +02:00
30968c4065 Document OpenBSD httpd API configuration (#9061)
* Document OpenBSD httpd API configuration

Closes #7493. Adds an OpenBSD httpd example for FreshRSS with PATH_INFO preserved for the Google Reader API. 

* Document caching considerations for OpenBSD httpd

* A few edits

---------

Co-authored-by: Gerard Alvear <gerard.alvear@logiqd.me>
Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
2026-07-20 18:02:10 +02:00
Gerard Alvear PorrasandGerard Alvear 88acb5bae5 Document HTTP proxy tunnelling option (#9054)
Closes #7209. Documents CURLOPT_HTTPPROXYTUNNEL with a data/config.php example for HTTPS feeds through HTTP CONNECT proxies.

Co-authored-by: Gerard Alvear <gerard.alvear@logiqd.me>
2026-07-19 12:04:57 +02:00
44c6de6492 Add Nextcloud Bookmarks sharing service (#9032)
* Add Nextcloud Bookmarks sharing service

Adds a new self-hosted sharing option that posts articles to a
Nextcloud instance's Bookmarks app bookmarklet endpoint, following
the same pattern as the existing Linkding and Shaarli entries.

Closes #8053

* i18n: use Nextcloud Bookmarks translations

* Update i18n

* Fix wrong search&replace

---------

Co-authored-by: Gerard Alvear <gerard.alvear@logiqd.me>
Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
2026-07-18 20:33:01 +02:00
Gerard Alvear PorrasandGerard Alvear 8e8c8d26b8 Document TT-RSS article migration (#9062)
Co-authored-by: Gerard Alvear <gerard.alvear@logiqd.me>
2026-07-18 20:21:51 +02:00
d2ee8f3d79 Add LinkAce as a sharing service (#9024)
* Add LinkAce as a sharing service

LinkAce is a self-hosted bookmark manager with a bookmarklet-style
add endpoint, similar to Linkding and Shaarli. Add a 'linkace' entry
to app/shares.php using its documented bookmarklet URL scheme, add
the corresponding translation key, and list it in the sharing
services documentation.

Fixes #6698

* i18n Ignore

---------

Co-authored-by: Gerard Alvear <gerard.alvear@logiqd.me>
Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
2026-07-18 20:12:31 +02:00
Gerard Alvear PorrasandGerard Alvear cf298e2680 Docker: use double quotes for CRON_MIN examples (#9011)
The Docker Quick Run / cron examples use single-quoted `-e 'CRON_MIN=1,31'`. This works on Linux/macOS shells and PowerShell, but not on Windows `cmd.exe`, which does not strip single quotes from arguments — they end up included literally in the variable, so the cron job never gets scheduled correctly. Using `-e CRON_MIN=*/20` (no quotes) works, which was the original report.


Fixes #4818

* Docs: remove CRON_MIN quoting

---------

Co-authored-by: Gerard Alvear <gerard.alvear@logiqd.me>
2026-07-15 13:45:02 +02:00
Gerard Alvear PorrasandGerard Alvear c1e711274c Mirror the official Fever API documentation (#9014)
The original Fever API docs at feedafever.com/api are offline, and only
an archive.org snapshot remains linked from our Fever API page. Add a
Markdown mirror of that content (with Alkarex's HTML-to-Markdown
translation) directly into the docs so it is preserved even if the
archive.org copy disappears.

The mirror is a faithful copy of Alkarex's translation, including the
"API Public Beta" intro paragraphs, with only the heading levels
adjusted to fit this page.

Fixes #7331

Co-authored-by: Gerard Alvear <gerard.alvear@logiqd.me>
2026-07-13 00:04:14 +02:00
Gerard Alvear PorrasandGerard Alvear 5f94330503 Mailer: allow disabling SMTPAutoTLS via config (#9026)
PHPMailer enables SMTPAutoTLS by default, meaning it opportunistically
upgrades a plain SMTP connection to STARTTLS whenever the server
advertises support for it, regardless of the 'secure' => '' setting
documented in config.default.php. Minz_Mailer never read or set
$mail->SMTPAutoTLS, so this behaviour could not be turned off, making
it impossible to talk to SMTP servers with a self-signed or otherwise
untrusted certificate (e.g. a mail server on an internal Docker
network) without importing a custom CA.

Add a new 'auto_tls' key to the 'smtp' config array, defaulting to
true to preserve current behaviour, and wire it through to
$mail->SMTPAutoTLS in Minz_Mailer. Document the new option.

Fixes #2997

Co-authored-by: Gerard Alvear <gerard.alvear@logiqd.me>
2026-07-12 23:55:32 +02:00
28bc73afed Dispatch a JS event when an entry finishes being marked read/unread (#9031)
* Dispatch a JS event when an entry finishes being marked read/unread

Extensions that render their own read/unread indicator outside of the
main article list (e.g. a custom reading pane) had no way to know when
a mark read/unread AJAX request completed, so their own UI could get
stuck (e.g. a spinner never reset).

Dispatch a `freshrss:entryStateChange` event on `document` with the
entry id and new state once the toggle has been applied, following the
existing `freshrss:*` JavaScript event convention used elsewhere in
main.js.

Fixes #8862

* Minor preferences

---------

Co-authored-by: Gerard Alvear <gerard.alvear@logiqd.me>
Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
2026-07-12 23:04:12 +02:00
Gerard Alvear PorrasandGerard Alvear e95243ae68 Document OIDC token endpoint authentication method (#9027)
Explain that mod_auth_openidc defaults to client_secret_basic since
our reference Apache configuration does not set
OIDCProviderTokenEndpointAuth. If the identity provider's discovery
metadata advertises a token_endpoint_auth_methods_supported array
instead, mod_auth_openidc picks the first mutually supported method
from that array rather than falling back to client_secret_basic.
Also point to the .htaccess override for administrators who need
something else.

This only addresses the token-endpoint-auth-method part of #6102;
the redirect-URI-port question raised in that issue is out of scope
here.

Addresses the token-endpoint-auth-method part of #6102

Co-authored-by: Gerard Alvear <gerard.alvear@logiqd.me>
2026-07-11 17:35:01 +02:00
Jam Balaya 310bcb5e90 Add read status hook for entries (#8995)
- Add a new `EntriesRead` / `entries_read` hook for extensions.
- Trigger the hook when `markRead()` changes entry read/unread state for explicit entry IDs.
- Cover both the default DAO path and the SQLite/PGSQL DAO path.
- Add Minz hook tests for the new hook signature and argument passing.

## Why

Extensions can already react to favorite/bookmark changes through `EntriesFavorite`. This adds the matching read/unread hook requested in #4051 for extensions that need to collect stats or react to manual read state changes.

Closes #4051
2026-07-07 09:04:32 +02:00
Inverle cb13091b37 Fix GH issue links with label filter in docs (#8993)
The "good first issue" and "help wanted" links under https://freshrss.github.io/FreshRSS/en/contributing.html#fix-a-bug aren't working.
2026-07-06 13:22:52 +02:00
Inverle c3d0bd5b55 Clarify in docs favicons/ should not be skipped during backup (#8992)
Alternative for https://github.com/FreshRSS/FreshRSS/pull/8972, at least until the migration system is improved to support rollbacks.
2026-07-06 11:16:56 +02:00
ffc5a966c3 Migrate markdownlint-cli to markdownlint-cli2 (single config file) (#8987)
* Migrate markdownlint-cli to markdownlint-cli2

Replace markdownlint-cli with markdownlint-cli2 and consolidate the three
separate configuration points (.markdownlint.json rules, .markdownlintignore
excludes, and the '**/*.md' glob in the npm scripts) into a single
.markdownlint-cli2.jsonc holding config + globs + ignores.

The npm script names (markdownlint / markdownlint_fix) are unchanged, so the
CI step and the test/fix compound scripts need no change. markdownlint-cli2
v0.23.0 bundles the same markdownlint v0.41.0, so linting behaviour is
identical (112 files, 0 errors).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Add JSONC to .editorconfig

* Reduce obvious comments

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
2026-07-05 14:18:49 +02:00
Jam BalayaandClaude Opus 4.8 cf2ceafca1 OPML: include each feed's refresh interval (TTL) in export/import (#8982)
Feeds moved between instances via OPML lost their refresh interval,
forcing manual reconfiguration. Add a 'frss:ttl' attribute (signed, so a
negative value also carries the muted state) to the OPML export, and read
it back on import. Documented in docs/en/developers/OPML.md.

For https://github.com/FreshRSS/FreshRSS/issues/5914

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-04 21:55:13 +02:00
InverleandAlexandre Alapetite dcec27c69d Add SSRF mitigations using filter_var and CURLOPT_RESOLVE (#8400)
* Add SSRF mitigations using `filter_var` and `CURLOPT_RESOLVE`
The idea is to prevent FreshRSS from sending any HTTP requests to internal services, except for the ones that are explicitly allowed in the config.

Based on https://github.com/moodle/moodle/blob/6e82b46a480826d1a85394d9e5087f7d82d1dd52/lib/filelib.php#L3818 and https://github.com/symfony/symfony/blob/8.1/src/Symfony/Component/HttpClient/NoPrivateNetworkHttpClient.php

https://github.com/FreshRSS/simplepie/pull/76
https://github.com/FreshRSS/simplepie/pull/78

* Add allowlist setting in Web UI

* make readme

* Update app/i18n/fr/admin.php

Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>

* make readme again

* make readme

* Further work

Still WIP and needs testing etc.

* Readd previous if check for domain combination allowlist

* Turn POST to GET after redirect

* Improve

* Update config.default.php

Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>

* make readme

* Skip SSRF check if `CURLOPT_PROXY` is set

* make readme

* Fix `!empty()` mistake

* Respect max redirects feed option when fetching with `httpGet()`

* Respect max redirects during SimplePie fetching + fix bypass

bypass fix: `CURLOPT_FOLLOWLOCATION` was moved below so that emulated redirects are enforced.

* Avoid FreshRSS and Minz code in SimplePie
https://github.com/FreshRSS/FreshRSS/pull/8400#discussion_r2935375980

* Corrected hook code

* phpdoc wrong return type

* Add CIDR support in allowlist

* Implement simple DNS caching

* Suppress `dns_get_record()` warnings

* A bit of proof-reading

* Minor typo

* Fix proxy logic

* Fix HTTP POST redirect logic

* Proofread checkCIDR
Add fixes for several situations

* Remove credentials from URL in logs

* Ensure `CURLOPT_FOLLOWLOCATION` is `false` by setting it at the end

* Fix codesniffer long line

* Fix potential bypass due to wrong return value

If there were no records returned by `dns_get_record()`, no overrides to `CURLOPT_RESOLVE` would get passed,
and a potential bypass could occur, when cURL would try to resolve the domain by itself.

* Put the URL at the end in logs

* Add documentation and environment variable support

* make readme

* Fix wrong behavior in case of IP

* Fix duplicate selector in CSS

* Minor type check change

* i18n fr, en

* Minor type check change

* Fix whitespace i18n fr

* make fix-all

* Fix `$ips_ok` not being returned after domain records were cached

* make readme

* PHPStan fix

* make readme

* Minor syntax in SimplePie

* Only return `null` if no allowed IPs were found

* Add wildcard *, help message

* Consistent docs with help message

* i18n: pl

* SimplePie compatibility PHP 7.2

* make fix-all

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

* 💥 Breaking change in the Changelog

* Document `INTERNAL_HOST_ALLOWLIST` in Docker docs

* Remove `Cookie` and `Authorization` headers in `httpGet()` during cross-origin redirect

* Minor whitespace
And same comment convention than below

* Remove authentication headers and change POST to GET on redirect in SimplePie

* Remove .local in Docker example

* Fill in default ports when comparing URL origins

* Remove .local from other places than the Docker example

* Rewrite WebSub subscribe to use `httpGet()`

* make fix-all

* Also unset `CURLOPT_USERPWD` during redirects

* phpcs fix

* Always unset `CURLOPT_FOLLOWLOCATION`

* Bump SimplePie
https://github.com/FreshRSS/simplepie/pull/78

* Update logic for CURLOPT_FOLLOWLOCATION

* Fix PHPStan

* Changelog fix security section

* Update most common RSS Bridge case
https://hub.docker.com/r/rssbridge/rss-bridge

* Replace misleading 127.0.0.1:8080 example for Docker
This does not make sense for a Docker container

---------

Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
2026-06-28 18:51:04 +02:00
dependabot[bot] 69eff07d92 chore(deps): bump concurrent-ruby (#8940)
Bumps the bundler group with 1 update in the /docs directory: [concurrent-ruby](https://github.com/ruby-concurrency/concurrent-ruby).


Updates `concurrent-ruby` from 1.3.6 to 1.3.7
- [Release notes](https://github.com/ruby-concurrency/concurrent-ruby/releases)
- [Changelog](https://github.com/ruby-concurrency/concurrent-ruby/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ruby-concurrency/concurrent-ruby/compare/v1.3.6...v1.3.7)

---
updated-dependencies:
- dependency-name: concurrent-ruby
  dependency-version: 1.3.7
  dependency-type: indirect
  dependency-group: bundler
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-23 22:00:22 +02:00
dependabot[bot] 6f1b66eb2b chore(deps-dev): bump faraday (#8939)
Bumps the bundler group with 1 update in the /docs directory: [faraday](https://github.com/lostisland/faraday).


Updates `faraday` from 2.14.2 to 2.14.3
- [Release notes](https://github.com/lostisland/faraday/releases)
- [Changelog](https://github.com/lostisland/faraday/blob/main/CHANGELOG.md)
- [Commits](https://github.com/lostisland/faraday/compare/v2.14.2...v2.14.3)

---
updated-dependencies:
- dependency-name: faraday
  dependency-version: 2.14.3
  dependency-type: indirect
  dependency-group: bundler
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-23 21:45:35 +02:00
Nathan 521981a96a Document PHP-FPM write restrictions for data path (#8936)
Closes #8882
- avoid recommending `/usr/share/` for writable FreshRSS data in the general install docs
- update the Debian/Ubuntu git install path and symlink example to `/var/www/FreshRSS`
- add an FAQ entry for PHP-FPM hardening that can make `/usr/` read-only despite correct Unix permissions
2026-06-22 12:25:06 +02:00
Salvador Castro 80d1db8dc7 docs: mention THIRDPARTY_EXTENSIONS_PATH override in extension install instructions (#8930)
Closes #8927
2026-06-21 19:09:42 +02:00
93f989b977 Add a warning message to the API password section, add a log warning when a client uses GET, use POST in sample curl API usage (#8845)
* Add a warning message to the API password section, add a log warning when a client uses GET, use POST in sample curl API usage

References #8834.

* Apply suggestion from @Inverle

Co-authored-by: Inverle <inverle@proton.me>

* Apply suggestion from @Inverle (Polish translation)

Co-authored-by: Inverle <inverle@proton.me>

* French translation

* Dutch translation

* German

* Apply suggestion from @Inverle api via post

Co-authored-by: Inverle <inverle@proton.me>

* Apply suggestion from @Inverle via POST (French)

Co-authored-by: Inverle <inverle@proton.me>

* Add user-agent

* update translation info in README

* avoid phpcs line too long

* also trigger on email as suggested by @Inverle

* i18n: fr typography

* make fix-all

---------

Co-authored-by: Inverle <inverle@proton.me>
Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
2026-05-20 20:09:02 +02:00
dependabot[bot] ae79f48f4b chore(deps-dev): bump faraday (#8858)
Bumps the bundler group with 1 update in the /docs directory: [faraday](https://github.com/lostisland/faraday).


Updates `faraday` from 2.14.1 to 2.14.2
- [Release notes](https://github.com/lostisland/faraday/releases)
- [Changelog](https://github.com/lostisland/faraday/blob/main/CHANGELOG.md)
- [Commits](https://github.com/lostisland/faraday/compare/v2.14.1...v2.14.2)

---
updated-dependencies:
- dependency-name: faraday
  dependency-version: 2.14.2
  dependency-type: indirect
  dependency-group: bundler
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-18 17:20:42 +02:00
polybjornandBjørn A. Andersen d74337deb6 feat(cli): automatic periodic SQLite export with retention (#8819)
Add an opt-in CLI that exports each user's database to
`data/users/<user>/sqlite-backups/<YYYYMMDDTHHMMSSZ>.sqlite` (UTC) and
prunes older files to a configured count. Gated by two new settings,
`auto_sqlite_export.enabled` and `auto_sqlite_export.retention`.

Kept separate from `cli/db-backup.php` / `cli/db-restore.php`, which
stay the fixed-filename migration tool. First step of #8183.

Co-authored-by: Bjørn A. Andersen <polybjorn@users.noreply.github.com>
2026-05-12 08:44:00 +02:00
polybjornandBjørn A. Andersen 769c87cef1 chore(themes): remove loader.gif and convert remaining consumers to the CSS spinner (#8812)
#button-update-loading and the generic .loading class (used by
#first_load) painted loader.gif as a background. Both now use the
#load_more.loading::after border-rotation spinner from #8804. The
unused #slider-content .loader rule is also removed. Drops the
--frss-loading-image variable, all twelve loader.gif files, and
references in the theme contribution docs.

Co-authored-by: Bjørn A. Andersen <polybjorn@users.noreply.github.com>
2026-05-11 20:23:20 +02:00
polybjornandBjørn A. Andersen 1936306277 chore(themes): rename "Nord theme" to "Nord" (#8805)
Rename the Nord theme display name from "Nord theme" to "Nord". The upstream Nord palette project at https://www.nordtheme.com refers to itself consistently as "Nord" throughout its branding; the "theme" suffix is redundant. The rename also matches the other entries in the theme picker (Ansum, Dark, Mapco, Pafat, Swage), which all use a single short name.

The theme directory, file paths, and CSS class names are unchanged. Only the user-facing display name in the theme picker (and the corresponding rows in the user docs) is affected.

Co-authored-by: Bjørn A. Andersen <polybjorn@users.noreply.github.com>
2026-05-11 00:16:28 +02:00
polybjornandBjørn A. Andersen 4b96b01460 chore(docs): upgrade Jekyll 3 to 4 and Ruby to 3.4.9 (#8772)
Jekyll 3 is unmaintained and its safe_yaml dependency breaks on
Ruby 3.4+ where base64 left the default stdlib. The docs workflow
already runs `bundle exec jekyll build` directly, so GitHub Pages'
Jekyll 3 lock does not apply here.

Changes:

* Pin `jekyll ~> 4.3`. Replace `jekyll-commonmark-ghpages` (pinned
  to Jekyll 3) with upstream `jekyll-commonmark`. Drop unused
  `jekyll-paginate`. Add `gem 'base64'` so the lockfile stays valid
  on Ruby 3.4+ where it became a bundled gem.
* Move CommonMark options into `_config.yml` to match what the
  `-ghpages` variant enabled by default: SMART, FOOTNOTES, UNSAFE
  (so inline HTML like `<br>` in tables still renders), plus the
  strikethrough, autolink, table, and tagfilter extensions. Set
  Rouge as the highlighter.
* Strip the leading slash from `defaults.scope.path` (`/en/*` to
  `en`). Jekyll 4 requires no leading slash, otherwise `page.lang`
  silently fails to propagate and `jekyll-i18n_tags` crashes the
  build.
* Pass `generateId=true` to the existing `anchor_headings.html`
  include so headings get slugified IDs. The `-ghpages` variant
  produced these by default.
* Bump CI Ruby to 3.4.9 and `cache-version` to invalidate the old
  Jekyll 3 gem cache on the first run.

Build is about 9x faster (1.0s vs 9.2s). Compared the rendered
output page by page against the Jekyll 3 baseline; remaining
differences are whitespace, footnote class names (no CSS depends
on either set), and one HTML entity (`&#8617;`) becoming the
literal `↩`. Visually and functionally the same.

Co-authored-by: Bjørn A. Andersen <polybjorn@users.noreply.github.com>
2026-05-03 14:17:55 +02:00