Forum

Welcome to ProjeQtOr new Forum. We migrated old forum to the new website.
You will find all your posts here, with your usual account.
Just one point : you’ll have to reinitialize your password. Use “Lost password” feature.

Bug: Editing a long...
 
Notifications
Clear all

Bug: Editing a long CKEditor field (in Issue "Result") with pasted Outlook HTML wipes most of the content

2 Posts
2 Users
1 Reactions
71 Views
(@karl-binet)
Posts: 129
Active Member
Topic starter
 
[#10139]

Environment: ProjeQtor v13.0.1

Description

When editing a long text field that uses CKEditor (e.g. the Result field of an Issue) that already contains a large amount of rich HTML — specifically content pasted from Outlook/Word, which typically embeds several repeated <style> blocks throughout the body — saving any change to that field wipes out almost all of the existing content and leaves only a small fragment.

Example (minimal reproduction)

Field content before editing (simplified — imagine this pattern repeated many times in a real Outlook paste):

<div>Line kept before the bug strikes</div>
<div>
<style type="text/css">a { color: #464feb; }</style>
<div>Important paragraph #1 that should stay</div>
<style type="text/css">a { color: #464feb; }</style>
<div>Important paragraph #2 that should stay</div>
<style type="text/css">a { color: #464feb; }</style>
<div>Important paragraph #3 that should stay</div>
</div>

Same field after saving a small, unrelated edit:

<div>Line kept before the bug strikes</div>
<div>

Everything between the first <style> tag and the last </style> tag is silently deleted on save. On a real ~25 KB Outlook paste with many scattered <style> blocks, this wipes almost the entire field, leaving only the first line.

Root cause & fix

In model/persistence/SqlElement.php, method updateSqlElement(), a cleanup step meant to strip stray <style> blocks from pasted content uses a regex with a mistaken negative lookahead — it checks for </script> instead of </style> (looks copy-pasted from a <script> stripper). Since the input never contains </script>, the lookahead never blocks anything, so the pattern greedily matches from the first <style to the last </style> in the whole document instead of stopping at each tag's own closer — deleting everything in between. There's also no check on preg_replace()'s return value, so extremely large content could hit pcre.backtrack_limit and return NULL, wiping the field entirely.

I've already applied this fix locally:

 1769          if ($col_new_value&&$isText and $dataLength>4000 and pq_substr(getEditorType(), 0, 2)=='CK') {
 1770            // if (pq_strpos($col_new_value,'<script')!==false) {
-1771            $pattern='/<style\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/style>/i';
+1771            $pattern='/<style\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/i';
 1772            $replacement='';
-1773            $col_new_value=preg_replace($pattern, $replacement, $col_new_value);
+1773            $newValueAfterStyleStrip=preg_replace($pattern, $replacement, $col_new_value);
+1774            if ($newValueAfterStyleStrip!==null) {
+1775              $col_new_value=$newValueAfterStyleStrip;
+1776            }
 1777            // }

This restores the intended behavior (strip each <style>...</style> pair individually) and prevents the field from being wiped if preg_replace() ever fails.

I'm sharing this so it can be added to your bug list and fixed in a future release.

Note: my fix may not be the "correct" solution from your perspective — it's just what let me keep editing the Result field in the meantime, until you come up with a proper fix for a future version.


 
Posted : 04 Sep 2026 14H47
babynus
(@babynus)
Posts: 14966
Main Contributor Admin
 

Hi,

 

Thanks for the fix.

Abviouly, purpose of the line was not to remove style tags, but to remove script tags, that may be hacking sources

Fix is applied on V13.0 and V13.1 and already available through subscription service.
Will be included in V13.1.2.

Note that we did not implement the backtrack_limit workaround as proposed.
We prefered to raise an error as stripping scripts is required.


 
Posted : 07 Oct 2026 11H07
Karl Binet reacted
Share:

Scroll to Top