summaryrefslogtreecommitdiff
path: root/app/controllers/nodes_controller.rb
diff options
context:
space:
mode:
authorerdgeist <erdgeist@erdgeist.org>2026-07-09 15:29:40 +0200
committererdgeist <erdgeist@erdgeist.org>2026-07-09 15:29:40 +0200
commit9c3217df50d462d6be4399e3e654d591bf704df7 (patch)
tree627e474b273789667bca9eadffa0e7f626d002bb /app/controllers/nodes_controller.rb
parent8310751d4db2854597d6379b24e346c65622972d (diff)
Fix malformed-HTML fallout across RSS, link rewriting, and flash messaging
Editors' TinyMCE output can contain unclosed void elements like <br>, which is valid HTML5 but invalid XML -- three different places assumed the stricter rule and broke or silently misbehaved on the looser one. The Atom feed's <content type="xhtml"> block required real, well-formed XML structure but was handed a raw, unescaped body string; switched to type="html" with CGI.escapeHTML, matching how title/summary already handle the same content. rewrite_links_in_body used libxml's strict XML parser to rewrite internal links to be locale-prefixed, which raised on exactly this class of malformed markup -- silently, since the whole method was wrapped in rescue; nil, meaning the link rewrite (not the save) quietly failed with no error anywhere. Replaced with Nokogiri's lenient HTML parser, which repairs malformed void elements rather than rejecting them; also drops the bare rescue now that the actual failure mode it was guarding against shouldn't occur, and fixes two adjacent bugs found while in this method: a typo'd /sytem/uploads/ regex that could never match, and a missing https:// exclusion alongside the existing http:// one. Also addresses stale flash messaging surfaced while testing the above: update's save confirmation was being clobbered by edit's own "locked and ready" notice on the very next request, since nothing distinguished a fresh lock acquisition from a redirect back after saving. The save confirmation now names the next step (publish from Status) and flags a stale translation if one exists, using Page#outdated_translations?, already present but previously unused by any controller.
Diffstat (limited to 'app/controllers/nodes_controller.rb')
-rw-r--r--app/controllers/nodes_controller.rb18
1 files changed, 15 insertions, 3 deletions
diff --git a/app/controllers/nodes_controller.rb b/app/controllers/nodes_controller.rb
index 72d4a3e..38d42d9 100644
--- a/app/controllers/nodes_controller.rb
+++ b/app/controllers/nodes_controller.rb
@@ -65,15 +65,16 @@ class NodesController < ApplicationController
65 end 65 end
66 66
67 def edit 67 def edit
68 freshly_locked = @node.lock_owner != current_user
68 @node.lock_for_editing!( current_user ) 69 @node.lock_for_editing!( current_user )
69 @page = @node.autosave || @node.draft || @node.head 70 @page = @node.autosave || @node.draft || @node.head
70 71
71 flash.now[:notice] = "Node locked and ready to edit" unless @node.autosave
72
73 if @node.autosave 72 if @node.autosave
74 flash.now[:notice] = 73 flash.now[:notice] =
75 "This page has unsaved changes from a previous session, shown below. " \ 74 "This page has unsaved changes from a previous session, shown below. " \
76 "Save to keep them, or use \"Discard changes\" below to go back to the last saved version." 75 "Save to keep them, or use \"Discard changes\" below to go back to the last saved version."
76 elsif freshly_locked
77 flash.now[:notice] = "Node locked and ready to edit"
77 end 78 end
78 rescue LockedByAnotherUser => e 79 rescue LockedByAnotherUser => e
79 flash[:error] = e.message 80 flash[:error] = e.message
@@ -85,7 +86,18 @@ class NodesController < ApplicationController
85 @node.autosave!( page_params.merge(:tag_list => params[:tag_list]), current_user ) 86 @node.autosave!( page_params.merge(:tag_list => params[:tag_list]), current_user )
86 @node.save_draft!(current_user) 87 @node.save_draft!(current_user)
87 88
88 flash[:notice] = "Draft has been saved: #{Time.now}" 89 flash[:notice] = "Draft saved. Publish your changes in the Status section once you're done."
90 flash[:status_path] = node_path(@node)
91
92 if @node.draft.translated_locales.size > 1
93 stale_locale = @node.draft.translated_locales.find do |locale|
94 @node.draft.outdated_translations?(locale: locale)
95 end
96 if stale_locale
97 flash[:stale_locale] = stale_locale
98 flash[:stale_locale_path] = edit_node_path(@node, locale: stale_locale)
99 end
100 end
89 101
90 if params[:commit] == "Save + Unlock + Exit" 102 if params[:commit] == "Save + Unlock + Exit"
91 @node.unlock! 103 @node.unlock!