Security: Block SSRF targets in the HTTP checker (private/reserved IPs, unsafe hosts, redirect chains) using wp_http_validate_url, DNS resolution checks, and reject_unsafe_urls.
Security: Validate edited URLs with esc_url_raw() and the same safety rules (public http/https only).
Security: Escape admin JavaScript output for smart suggestions and diagnostics (XSS hardening).
Fix: Apply the ignore list during scans and HTTP checks (domains/prefixes in Settings are now honored).
Improvement: Relative and root-relative internal links (e.g. /other-post/) are resolved to the full site URL before HTTP checks, so links between articles on the same WordPress site are verified correctly (including deleted targets returning 404).
Improvement: Edit/Unlink and stale-link cleanup recognise the same URL whether it is stored or written as a relative or absolute href.
Fix: Redirect chains that end on an error page (for example 301 to www then 404) are stored as broken with the final status; they are no longer treated as a successful redirect with a misleading suggestion target.
Improvement: Smart suggestions skip instant redirect targets that only toggle www/non-www on HTTPS (or HTTP) when the row is already broken—no “Apply” for a URL that remains a 404.
Improvement: Smart suggestions no longer offer meaningless HTTP-only www/non-www swaps when no HTTPS exists (avoids a green-looking “fix” that does not improve security).
Improvement: When there is no useful alternative for an HTTP-only link, the suggestion panel shows a clear warning notice instead of implying a positive change.
Improvement: The suggestion list only shows a green “OK” style and an Apply button when the suggested URL is considered actionable (not a hard error such as 404).
Improvement: Broken-link notification emails are sent as HTML with a TSO Link Inspector header, clickable broken URLs, article edit links, and a button to open the inspector.
1.9.2
Fix: Plugin Description on the Plugins screen now translates to Catalan and Spanish when the site (or bundled language files) uses those locales.
Fix: Translation files include the English plugin header string as msgid (matches the plugin header text).
Improvement: Load translations when the plugin boots so metadata strings are available before the Plugins list is built.
1.9.1
New: Optional email notifications for hard-broken links only (broken with no redirect destination): immediate mode sends one summary email per automated check batch (full background check or hourly cron), never after manual row/bulk rechecks; digest modes send every 7, 15, or 30 days only when there is something to report.
New: Configurable recipient email for notifications (falls back to the site admin email when left blank).
New: Manual locks filter tab for links marked “Not broken”; manually locked rows are excluded from Broken / Redirect / OK / HTTP insecure / Not checked tabs so the same URL is not counted twice.
Improvement: A full Check now clears last_checked for all rows (including manual locks) so regressions are detected reliably.
Fix: PHP deprecation from registering a hidden settings submenu with a null parent slug (now attached to Tools and removed from the menu).
Fix: Last checked falls back to Date found when a historic row has no check timestamp but already has status data.
Fix: Bulk Unlink completion message no longer says “rechecked”.
Fix: Clearing the list search when switching filter tabs (search query no longer sticks across tabs).
Fix: CSV export encoding (UTF-8 BOM) for Excel and other spreadsheets.
Improvement: Admin list layout for empty filter views, spacing, centered Tools wrapper, and tighter settings layout on small screens.
New: Comment links use an internal source_key, so the same URL can appear both in post content and in comments without overwriting each other in the database.
Improvement: Comment scanning advances via a persistent cursor (comment_ID) so large sites eventually scan all approved comments; the daily cron also keeps draining comments after the post batch finishes (within the time budget).
Improvement: After scanning each comment, stale inspector rows for that comment are removed when URLs disappear from comment body or author website fields.
New: When a comment is permanently deleted in WordPress, matching inspector rows are removed (deleted_comment hook).
Fix: Editing a comment URL from the plugin now fails with an error if the URL cannot be found in that comment (no silent “database-only” update).
Improvement: More redirects treated as trivial noise — drop one interior path segment on the same host (common permalink/category consolidation next to trailing-slash normalization).
1.8.4
Fix: Plain http:// links that return 200 are no longer shown as green “OK”; they use the warning style and an explicit “HTTP — use HTTPS” label. The “OK” filter and OK stat count exclude these rows (they remain under HTTP insecure).
1.8.3
WordPress.org compliance: internal code prefix renamed from tso_lc_ / TSO_LC_ to tsoliin_ / TSOLIIN_ (classes, defines, options, AJAX actions, cron hooks, script handles, nonces, and admin CSS/JS hooks). Existing installs migrate stored options and legacy cron events automatically on upgrade.
Bootstrap entry point is now tsoliin_link_inspector(); custom hook after post updates is tsoliin_after_post_update (replace tso_lc_after_post_update in any custom integrations).
1.8.2
Improvement: Treat WordPress login redirects (for example /wp-admin/ -> wp-login.php?redirect_to=…) as authentication walls, not actionable redirect issues.
1.8.1
Improvement: “Check now” resumes partial background progress when unchecked links are pending, instead of always restarting from 0%.
1.8.0
Rebrand: plugin display name changed to TSO Link Inspector and admin page slugs moved to tso-link-inspector.
i18n slug updated to tso-link-inspector in plugin headers, text-domain constant, and PHP translation calls.
Prefix hardening: bootstrap function renamed to tsoliin_link_inspector() (superseded by the fuller tsoliin_ / TSOLIIN_ prefix in 1.8.3).
1.7.11
Improvement: Retry with GET when HEAD returns 401 (some sites, including Facebook, block HEAD but answer GET).
1.7.10
Improvement: More “transparent” redirects — www canonicalisation compares paths case-insensitively and with decoded segments (fixes edge cases like publico.es → www.publico.es).
Improvement: Chrome Web Store migration (chrome.google.com/webstore/… → chromewebstore.google.com/detail/… + optional ucbcb) treated as OK, not as a redirect to “fix”.
Improvement: LiberKey legacy catalog/browse URLs redirecting to /{lang}.html on the same host treated as transparent (marketing consolidation, not a broken link).
1.7.9
Improvement: Treat Telegram /dl/… “latest installer” redirects to a versioned .exe on *.telegram.org as transparent — no redirect noise, and no Smart Suggestion to replace the stable URL (which would pin the post to one version).
1.7.8
Improvement: Treat common “canonical” redirects as transparent — same hostname with/without www, optional http→https, same path, and query string adds only tracking/consent-style parameters (for example YouTube ucbcb / cbrd, UTM, gclid, fbclid).
1.7.7
Improvement: URLs with a #fragment and a server redirect are treated as OK when the final response is successful (anchors are not sent over HTTP; redirect targets omit them).
Improvement: “Recheck” (single and bulk) no longer clears “Not broken” — manual OK stays until the URL fails or you edit the URL in the post.