Improve URLs/emails detection in text mail parts

pull/251/head
Francis Lachapelle 2019-03-21 11:01:17 -04:00
parent 7acfd8a2cd
commit fcdc4c92c0
3 changed files with 50 additions and 56 deletions

1
NEWS
View File

@ -11,6 +11,7 @@ Bug fixes
- [web] fixed scrolling in calendars list on Android - [web] fixed scrolling in calendars list on Android
- [web] keep center list of Calendar module visible on small screens - [web] keep center list of Calendar module visible on small screens
- [web] check for duplicate name only if address book name is changed - [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] allow super users to modify any event (#4216)
- [core] correctly handle the full cert chain in S/MIME - [core] correctly handle the full cert chain in S/MIME
- [core] handle multidays events in freebusy data - [core] handle multidays events in freebusy data

View File

@ -1,6 +1,6 @@
/* NSString+Utilities.h - this file is part of SOGo /* 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 * 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 * it under the terms of the GNU General Public License as published by
@ -67,8 +67,6 @@
- (NSString *) asQPSubjectString: (NSString *) encoding; - (NSString *) asQPSubjectString: (NSString *) encoding;
- (NSRange) _rangeOfURLInRange: (NSRange) refRange;
/* LDAP */ /* LDAP */
- (BOOL) caseInsensitiveMatches: (NSString *) match; - (BOOL) caseInsensitiveMatches: (NSString *) match;

View File

@ -1,6 +1,6 @@
/* NSString+Utilities.m - this file is part of SOGo /* 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 * 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 * it under the terms of the GNU General Public License as published by
@ -35,7 +35,8 @@
static NSMutableCharacterSet *urlNonEndingChars = nil; static NSMutableCharacterSet *urlNonEndingChars = nil;
static NSMutableCharacterSet *urlAfterEndingChars = nil; static NSMutableCharacterSet *urlAfterEndingChars = nil;
static NSMutableCharacterSet *urlStartChars = nil; static NSMutableCharacterSet *schemaStartChars = nil;
static NSMutableCharacterSet *emailStartChars = nil;
static NSString **cssEscapingStrings = NULL; static NSString **cssEscapingStrings = NULL;
static unichar *cssEscapingCharacters = NULL; static unichar *cssEscapingCharacters = NULL;
@ -101,27 +102,19 @@ static int cssEscapingCount;
} }
- (NSRange) _rangeOfURLInRange: (NSRange) refRange - (NSRange) _rangeOfURLInRange: (NSRange) refRange
withPrefixChars: (NSCharacterSet *) startChars
{ {
int start, length; int start, length;
NSRange workRange; NSRange workRange;
// [urlNonEndingChars addCharactersInString: @">&=,.:;\t \r\n"]; // [urlNonEndingChars addCharactersInString: @">&=,.:;\t \r\n"];
// [urlAfterEndingChars 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; start = refRange.location;
if (start > 0)
start--; // Start with the character before the refRange
while (start > -1 while (start > -1
&& ![urlAfterEndingChars characterIsMember: && [startChars characterIsMember:
[self characterAtIndex: start]]) [self characterAtIndex: start]])
start--; start--;
start++; start++;
@ -153,6 +146,7 @@ static int cssEscapingCount;
- (void) _handleURLs: (NSMutableString *) selfCopy - (void) _handleURLs: (NSMutableString *) selfCopy
textToMatch: (NSString *) match textToMatch: (NSString *) match
urlPrefixChars: (NSCharacterSet *) startChars
prefix: (NSString *) prefix prefix: (NSString *) prefix
inRanges: (NSMutableArray *) ranges inRanges: (NSMutableArray *) ranges
{ {
@ -162,51 +156,25 @@ static int cssEscapingCount;
NSRange *rangePtr; NSRange *rangePtr;
NSString *urlText, *newUrlText; NSString *urlText, *newUrlText;
unsigned int length, matchLength, offset; unsigned int length, matchLength, offset;
int startLocation;
if (!urlStartChars)
{
urlStartChars = [NSMutableCharacterSet new];
[urlStartChars addCharactersInString: @"abcdefghijklmnopqrstuvwxyz"
@"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
@"0123456789:@"];
}
newRanges = [NSMutableArray array]; newRanges = [NSMutableArray array];
matchLength = [match length]; matchLength = [match length];
rest.location = -1;
matchRange = [selfCopy rangeOfString: match]; matchRange = [selfCopy rangeOfString: match];
while (matchRange.location != NSNotFound) while (matchRange.location != NSNotFound)
{ {
startLocation = matchRange.location; currentUrlRange = [selfCopy _rangeOfURLInRange: matchRange
while (startLocation > rest.location withPrefixChars: startChars];
&& [urlStartChars characterIsMember: if (![ranges hasRangeIntersection: currentUrlRange])
[selfCopy characterAtIndex: startLocation]]) if (currentUrlRange.length > matchLength)
startLocation--; [newRanges addNonNSObject: &currentUrlRange
matchRange.location = startLocation + 1; withSize: sizeof (NSRange)
copy: YES];
// We avoid going out of bounds if the mail content actually finishes rest.location = NSMaxRange (currentUrlRange);
// with the @ (or something else) character length = [selfCopy length];
if (matchRange.location < [selfCopy length]) rest.length = length - rest.location;
{ matchRange = [selfCopy rangeOfString: match
currentUrlRange = [selfCopy _rangeOfURLInRange: matchRange]; options: 0 range: rest];
if (![ranges hasRangeIntersection: currentUrlRange])
if (currentUrlRange.length > matchLength)
[newRanges addNonNSObject: &currentUrlRange
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;
}
} }
// Make the substitutions, keep track of the new offset // Make the substitutions, keep track of the new offset
@ -237,14 +205,41 @@ static int cssEscapingCount;
NSMutableString *selfCopy; NSMutableString *selfCopy;
NSMutableArray *ranges; 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]; ranges = [NSMutableArray array];
selfCopy = [NSMutableString stringWithString: self]; selfCopy = [NSMutableString stringWithString: self];
[self _handleURLs: selfCopy [self _handleURLs: selfCopy
textToMatch: @"://" textToMatch: @"://"
urlPrefixChars: schemaStartChars
prefix: @"" prefix: @""
inRanges: ranges]; inRanges: ranges];
[self _handleURLs: selfCopy [self _handleURLs: selfCopy
textToMatch: @"@" textToMatch: @"@"
urlPrefixChars: emailStartChars
prefix: @"mailto:" prefix: @"mailto:"
inRanges: ranges]; inRanges: ranges];
[ranges freeNonNSObjects]; [ranges freeNonNSObjects];