mirror of
https://github.com/inverse-inc/sogo.git
synced 2026-10-03 11:00:33 +00:00
fix(mail): Keep content of Outlook downlevel-revealed conditional comments. Fixes #6167.
This commit is contained in:
@@ -1089,14 +1089,75 @@ static int cssEscapingCount;
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *) cleanInvalidHTMLTags {
|
- (NSString *) cleanInvalidHTMLTags {
|
||||||
// Clean HTML invalid tags as reported in https://bugs.sogo.nu/view.php?id=5755
|
// Clean HTML invalid tags as reported in https://bugs.sogo.nu/view.php?id=5755 and https://bugs.sogo.nu/view.php?id=6167
|
||||||
NSString *s;
|
// libxml2 (HTML4) sees a standalone empty comment (<!--> or <!--->) as an
|
||||||
|
// unterminated comment and drops the rest of the document, so remove it.
|
||||||
s = [NSString stringWithString: self];
|
// Only do it outside of comments: the Outlook "downlevel-revealed" pattern
|
||||||
s = [s stringByReplacingOccurrencesOfString:@"<!-->" withString:@""];
|
// <!--[if !mso]><!--> ... <!--<![endif]--> ends its first comment with
|
||||||
s = [s stringByReplacingOccurrencesOfString:@"<!--<!" withString:@"<!--"];
|
// "<!-->", and removing it would hide the content in between.
|
||||||
|
NSString *result;
|
||||||
|
unichar *in, *out;
|
||||||
|
NSUInteger len, i, j, o;
|
||||||
|
|
||||||
return s;
|
len = [self length];
|
||||||
|
if (len == 0)
|
||||||
|
return [NSString string];
|
||||||
|
|
||||||
|
// Work on raw buffers: linear time, bounded memory (no per-comment objects)
|
||||||
|
in = NSZoneMalloc (NULL, len * sizeof (unichar));
|
||||||
|
out = NSZoneMalloc (NULL, len * sizeof (unichar));
|
||||||
|
[self getCharacters: in];
|
||||||
|
i = o = 0;
|
||||||
|
|
||||||
|
while (i < len)
|
||||||
|
{
|
||||||
|
if (i + 3 < len
|
||||||
|
&& in[i] == '<' && in[i+1] == '!' && in[i+2] == '-' && in[i+3] == '-')
|
||||||
|
{
|
||||||
|
j = i + 4;
|
||||||
|
if (j < len && in[j] == '>')
|
||||||
|
{
|
||||||
|
// <!-->
|
||||||
|
i = j + 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (j + 1 < len && in[j] == '-' && in[j+1] == '>')
|
||||||
|
{
|
||||||
|
// <!--->
|
||||||
|
i = j + 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Regular comment: keep it untouched up to its end ("-->" or "--!>",
|
||||||
|
// as libxml2 accepts both), or up to the end if unterminated
|
||||||
|
while (j < len)
|
||||||
|
{
|
||||||
|
if (j + 2 < len && in[j] == '-' && in[j+1] == '-' && in[j+2] == '>')
|
||||||
|
{
|
||||||
|
j += 3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (j + 3 < len && in[j] == '-' && in[j+1] == '-'
|
||||||
|
&& in[j+2] == '!' && in[j+3] == '>')
|
||||||
|
{
|
||||||
|
j += 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
memcpy (out + o, in + i, (j - i) * sizeof (unichar));
|
||||||
|
o += j - i;
|
||||||
|
i = j;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
out[o++] = in[i++];
|
||||||
|
}
|
||||||
|
|
||||||
|
result = [NSString stringWithCharacters: out length: o];
|
||||||
|
NSZoneFree (NULL, in);
|
||||||
|
NSZoneFree (NULL, out);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -127,7 +127,15 @@
|
|||||||
- (void) test_stringCleanInvalidHTMLTags
|
- (void) test_stringCleanInvalidHTMLTags
|
||||||
{
|
{
|
||||||
testEquals([[NSString stringWithString:@"<div>Test<!--></div>"] cleanInvalidHTMLTags], @"<div>Test</div>");
|
testEquals([[NSString stringWithString:@"<div>Test<!--></div>"] cleanInvalidHTMLTags], @"<div>Test</div>");
|
||||||
testEquals([[NSString stringWithString:@"<div><!--[if !mso]><span>Test</span><!--<![endif]--></div>"] cleanInvalidHTMLTags], @"<div><!--[if !mso]><span>Test</span><!--[endif]--></div>");
|
testEquals([[NSString stringWithString:@"<div>Test<!---></div>"] cleanInvalidHTMLTags], @"<div>Test</div>");
|
||||||
|
testEquals([[NSString stringWithString:@"<div>A<!-->B<!-- c -->C<!-->D</div>"] cleanInvalidHTMLTags], @"<div>AB<!-- c -->CD</div>");
|
||||||
|
testEquals([[NSString stringWithString:@"<div><!--[if !mso]><span>Test</span><!--<![endif]--></div>"] cleanInvalidHTMLTags], @"<div><!--[if !mso]><span>Test</span><!--<![endif]--></div>");
|
||||||
|
// Outlook "downlevel-revealed" conditional comment: content must stay visible
|
||||||
|
testEquals([[NSString stringWithString:@"<a><!--[if !mso]><!--> <div><img src=\"x\"/></div> <!--<![endif]--><!--[if mso]><v:fill/><![endif]--></a>"] cleanInvalidHTMLTags], @"<a><!--[if !mso]><!--> <div><img src=\"x\"/></div> <!--<![endif]--><!--[if mso]><v:fill/><![endif]--></a>");
|
||||||
|
// libxml2 also ends a comment with "--!>"
|
||||||
|
testEquals([[NSString stringWithString:@"A<!-- x --!>B<!-->C"] cleanInvalidHTMLTags], @"A<!-- x --!>BC");
|
||||||
|
// unterminated comment is left as is
|
||||||
|
testEquals([[NSString stringWithString:@"<div>A<!-- B</div>"] cleanInvalidHTMLTags], @"<div>A<!-- B</div>");
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) test_stringRemoveHTMLTagsExceptAnchorTags
|
- (void) test_stringRemoveHTMLTagsExceptAnchorTags
|
||||||
|
|||||||
Reference in New Issue
Block a user