From fcdc4c92c0eb6ad0da32c0595b637088dd3e4b00 Mon Sep 17 00:00:00 2001 From: Francis Lachapelle Date: Thu, 21 Mar 2019 11:01:17 -0400 Subject: [PATCH] Improve URLs/emails detection in text mail parts --- NEWS | 1 + SoObjects/SOGo/NSString+Utilities.h | 4 +- SoObjects/SOGo/NSString+Utilities.m | 101 +++++++++++++--------------- 3 files changed, 50 insertions(+), 56 deletions(-) diff --git a/NEWS b/NEWS index 1c202019a..d517e6bb6 100644 --- a/NEWS +++ b/NEWS @@ -11,6 +11,7 @@ Bug fixes - [web] fixed scrolling in calendars list on Android - [web] keep center list of Calendar module visible on small screens - [web] check for duplicate name only if address book name is changed + - [web] improved detection of URLs and email addresses in text mail parts - [core] allow super users to modify any event (#4216) - [core] correctly handle the full cert chain in S/MIME - [core] handle multidays events in freebusy data diff --git a/SoObjects/SOGo/NSString+Utilities.h b/SoObjects/SOGo/NSString+Utilities.h index 0886c2cc7..7f631ce9d 100644 --- a/SoObjects/SOGo/NSString+Utilities.h +++ b/SoObjects/SOGo/NSString+Utilities.h @@ -1,6 +1,6 @@ /* NSString+Utilities.h - this file is part of SOGo * - * Copyright (C) 2006-2017 Inverse inc. + * Copyright (C) 2006-2019 Inverse inc. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -67,8 +67,6 @@ - (NSString *) asQPSubjectString: (NSString *) encoding; -- (NSRange) _rangeOfURLInRange: (NSRange) refRange; - /* LDAP */ - (BOOL) caseInsensitiveMatches: (NSString *) match; diff --git a/SoObjects/SOGo/NSString+Utilities.m b/SoObjects/SOGo/NSString+Utilities.m index 21d2fa621..83a1ef49c 100644 --- a/SoObjects/SOGo/NSString+Utilities.m +++ b/SoObjects/SOGo/NSString+Utilities.m @@ -1,6 +1,6 @@ /* NSString+Utilities.m - this file is part of SOGo * - * Copyright (C) 2006-2017 Inverse inc. + * Copyright (C) 2006-2019 Inverse inc. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -35,7 +35,8 @@ static NSMutableCharacterSet *urlNonEndingChars = nil; static NSMutableCharacterSet *urlAfterEndingChars = nil; -static NSMutableCharacterSet *urlStartChars = nil; +static NSMutableCharacterSet *schemaStartChars = nil; +static NSMutableCharacterSet *emailStartChars = nil; static NSString **cssEscapingStrings = NULL; static unichar *cssEscapingCharacters = NULL; @@ -101,27 +102,19 @@ static int cssEscapingCount; } - (NSRange) _rangeOfURLInRange: (NSRange) refRange + withPrefixChars: (NSCharacterSet *) startChars { int start, length; NSRange workRange; // [urlNonEndingChars addCharactersInString: @">&=,.:;\t \r\n"]; // [urlAfterEndingChars addCharactersInString: @"()[]{}&;<\t \r\n"]; - if (!urlNonEndingChars) - { - urlNonEndingChars = [NSMutableCharacterSet new]; - [urlNonEndingChars addCharactersInString: @"=,.:;&()\t \r\n"]; - } - if (!urlAfterEndingChars) - { - urlAfterEndingChars = [NSMutableCharacterSet new]; - [urlAfterEndingChars addCharactersInString: @"()[]\t \r\n"]; - } - start = refRange.location; + if (start > 0) + start--; // Start with the character before the refRange while (start > -1 - && ![urlAfterEndingChars characterIsMember: - [self characterAtIndex: start]]) + && [startChars characterIsMember: + [self characterAtIndex: start]]) start--; start++; @@ -153,6 +146,7 @@ static int cssEscapingCount; - (void) _handleURLs: (NSMutableString *) selfCopy textToMatch: (NSString *) match + urlPrefixChars: (NSCharacterSet *) startChars prefix: (NSString *) prefix inRanges: (NSMutableArray *) ranges { @@ -162,51 +156,25 @@ static int cssEscapingCount; NSRange *rangePtr; NSString *urlText, *newUrlText; unsigned int length, matchLength, offset; - int startLocation; - - if (!urlStartChars) - { - urlStartChars = [NSMutableCharacterSet new]; - [urlStartChars addCharactersInString: @"abcdefghijklmnopqrstuvwxyz" - @"ABCDEFGHIJKLMNOPQRSTUVWXYZ" - @"0123456789:@"]; - } newRanges = [NSMutableArray array]; matchLength = [match length]; - rest.location = -1; matchRange = [selfCopy rangeOfString: match]; while (matchRange.location != NSNotFound) { - startLocation = matchRange.location; - while (startLocation > rest.location - && [urlStartChars characterIsMember: - [selfCopy characterAtIndex: startLocation]]) - startLocation--; - matchRange.location = startLocation + 1; - - // We avoid going out of bounds if the mail content actually finishes - // with the @ (or something else) character - if (matchRange.location < [selfCopy length]) - { - currentUrlRange = [selfCopy _rangeOfURLInRange: matchRange]; - if (![ranges hasRangeIntersection: currentUrlRange]) - if (currentUrlRange.length > matchLength) - [newRanges addNonNSObject: ¤tUrlRange - withSize: sizeof (NSRange) - copy: YES]; - - rest.location = NSMaxRange (currentUrlRange); - length = [selfCopy length]; - rest.length = length - rest.location; - matchRange = [selfCopy rangeOfString: match - options: 0 range: rest]; - } - else - { - matchRange.location = NSNotFound; - } + currentUrlRange = [selfCopy _rangeOfURLInRange: matchRange + withPrefixChars: startChars]; + if (![ranges hasRangeIntersection: currentUrlRange]) + if (currentUrlRange.length > matchLength) + [newRanges addNonNSObject: ¤tUrlRange + withSize: sizeof (NSRange) + copy: YES]; + rest.location = NSMaxRange (currentUrlRange); + length = [selfCopy length]; + rest.length = length - rest.location; + matchRange = [selfCopy rangeOfString: match + options: 0 range: rest]; } // Make the substitutions, keep track of the new offset @@ -237,14 +205,41 @@ static int cssEscapingCount; NSMutableString *selfCopy; NSMutableArray *ranges; + if (!urlNonEndingChars) + { + urlNonEndingChars = [NSMutableCharacterSet new]; + [urlNonEndingChars addCharactersInString: @"=,.:;&()\t \r\n"]; + } + if (!urlAfterEndingChars) + { + urlAfterEndingChars = [NSMutableCharacterSet new]; + [urlAfterEndingChars addCharactersInString: @"()[]\t \r\n"]; + } + if (!schemaStartChars) + { + schemaStartChars = [NSMutableCharacterSet new]; + [schemaStartChars addCharactersInString: @"abcdefghijklmnopqrstuvwxyz" + @"ABCDEFGHIJKLMNOPQRSTUVWXYZ"]; + } + if (!emailStartChars) + { + emailStartChars = [NSMutableCharacterSet new]; + [emailStartChars addCharactersInString: @"abcdefghijklmnopqrstuvwxyz" + @"ABCDEFGHIJKLMNOPQRSTUVWXYZ" + @"01234567890" + @"!#$%&'*+-/=?^`{|}~."]; + } + ranges = [NSMutableArray array]; selfCopy = [NSMutableString stringWithString: self]; [self _handleURLs: selfCopy textToMatch: @"://" + urlPrefixChars: schemaStartChars prefix: @"" inRanges: ranges]; [self _handleURLs: selfCopy textToMatch: @"@" + urlPrefixChars: emailStartChars prefix: @"mailto:" inRanges: ranges]; [ranges freeNonNSObjects];