diff --git a/UI/MailPartViewers/UIxMailPartHTMLViewer.m b/UI/MailPartViewers/UIxMailPartHTMLViewer.m index 0b5e6c0b0..65f5ff397 100644 --- a/UI/MailPartViewers/UIxMailPartHTMLViewer.m +++ b/UI/MailPartViewers/UIxMailPartHTMLViewer.m @@ -130,6 +130,13 @@ static NSString *_sanitizeHtmlForDisplay(NSString *content) BOOL hasEmbeddedCSS; xmlCharEncoding contentEncoding; BOOL rawContent; + // Wrap libxml2-orphaned around the following block element + // (HTML5 pattern ...
auto-closed by libxml2 HTML4 DTD). + NSString *pendingAnchorTag; + NSString *anchorWrapTag; + NSUInteger anchorWrapDepth; + NSString *lastAnchorOpenString; + NSUInteger lastAnchorOpenEnd; } - (NSString *) result; @@ -175,6 +182,9 @@ static NSString *_sanitizeHtmlForDisplay(NSString *content) [result release]; [css release]; [ignoreTag release]; + [pendingAnchorTag release]; + [anchorWrapTag release]; + [lastAnchorOpenString release]; [super dealloc]; } @@ -228,6 +238,15 @@ static NSString *_sanitizeHtmlForDisplay(NSString *content) inCSSDeclaration = NO; hasEmbeddedCSS = NO; embeddedCSSLevel = 0; + + [pendingAnchorTag release]; + [anchorWrapTag release]; + [lastAnchorOpenString release]; + pendingAnchorTag = nil; + anchorWrapTag = nil; + lastAnchorOpenString = nil; + anchorWrapDepth = 0; + lastAnchorOpenEnd = 0; } - (void) endDocument @@ -494,6 +513,32 @@ static NSString *_sanitizeHtmlForDisplay(NSString *content) } else { + // If a libxml2-orphaned is waiting, re-open it around the next + // block element (HTML5 pattern ...
). + // Skip if the next element is itself (avoids invalid nesting). + if (pendingAnchorTag != nil) + { + if ([lowerName isEqualToString: @"a"]) + { + [pendingAnchorTag release]; + pendingAnchorTag = nil; + } + else + { + [result appendString: pendingAnchorTag]; + [anchorWrapTag release]; + anchorWrapTag = [lowerName copy]; + anchorWrapDepth = 1; + [pendingAnchorTag release]; + pendingAnchorTag = nil; + } + } + else if (anchorWrapTag != nil + && [lowerName isEqualToString: anchorWrapTag]) + { + anchorWrapDepth++; + } + resultPart = [NSMutableString string]; [resultPart appendFormat: @"<%@", _rawName]; @@ -599,6 +644,13 @@ static NSString *_sanitizeHtmlForDisplay(NSString *content) [resultPart appendString: @"/"]; [resultPart appendString: @">"]; [result appendString: resultPart]; + + if ([lowerName isEqualToString: @"a"]) + { + [lastAnchorOpenString release]; + lastAnchorOpenString = [resultPart copy]; + lastAnchorOpenEnd = [result length]; + } } } } @@ -655,8 +707,42 @@ static NSString *_sanitizeHtmlForDisplay(NSString *content) } else { + // Empty auto-closed by libxml2 right after opening: + // strip it from result and remember it to wrap the next block. + if ([lowerName isEqualToString: @"a"] + && lastAnchorOpenString != nil + && [result length] == lastAnchorOpenEnd) + { + NSUInteger tagLen = [lastAnchorOpenString length]; + [result deleteCharactersInRange: + NSMakeRange(lastAnchorOpenEnd - tagLen, tagLen)]; + [pendingAnchorTag release]; + pendingAnchorTag = lastAnchorOpenString; + lastAnchorOpenString = nil; + lastAnchorOpenEnd = 0; + return; + } + if ([lowerName isEqualToString: @"a"]) + { + [lastAnchorOpenString release]; + lastAnchorOpenString = nil; + lastAnchorOpenEnd = 0; + } + //NSLog (@"%@", _localName); [result appendFormat: @"", _localName]; + + if (anchorWrapTag != nil + && [lowerName isEqualToString: anchorWrapTag]) + { + anchorWrapDepth--; + if (anchorWrapDepth == 0) + { + [result appendString: @""]; + [anchorWrapTag release]; + anchorWrapTag = nil; + } + } } } } @@ -673,9 +759,17 @@ static NSString *_sanitizeHtmlForDisplay(NSString *content) else if (inBody) { NSString *s; - + s = [NSString stringWithCharacters: _chars length: _len]; + if (pendingAnchorTag != nil + && [[s stringByTrimmingCharactersInSet: + [NSCharacterSet whitespaceAndNewlineCharacterSet]] length] > 0) + { + [pendingAnchorTag release]; + pendingAnchorTag = nil; + } + // HACK: This is to avoid appending the useless junk in the tag // that Outlook adds. It seems to confuse the XML parser for // forwarded messages as we get this in the _body_ of the email