mirror of
https://github.com/inverse-inc/sogo.git
synced 2026-08-29 10:17:35 +00:00
fix(mail): escape angularJS directive for description
This commit is contained in:
@@ -78,7 +78,8 @@
|
|||||||
|
|
||||||
/* XSS protection */
|
/* XSS protection */
|
||||||
- (NSString *) removeHTMLTagsExceptAnchorTags;
|
- (NSString *) removeHTMLTagsExceptAnchorTags;
|
||||||
- (NSString *) stringWithoutHTMLInjection: (BOOL)stripHTMLCode;
|
- (NSString *) stringWithoutHTMLInjection: (BOOL)stripHTMLCode
|
||||||
|
stripAngular: (BOOL)stripAngular;
|
||||||
|
|
||||||
#ifndef GNUSTEP_BASE_LIBRARY
|
#ifndef GNUSTEP_BASE_LIBRARY
|
||||||
- (BOOL) boolValue;
|
- (BOOL) boolValue;
|
||||||
|
|||||||
@@ -936,7 +936,7 @@ static int cssEscapingCount;
|
|||||||
* @param stripHTMLCode Remove all HTML code from content
|
* @param stripHTMLCode Remove all HTML code from content
|
||||||
* @return A safe string
|
* @return A safe string
|
||||||
*/
|
*/
|
||||||
- (NSString *) stringWithoutHTMLInjection: (BOOL)stripHTMLCode
|
- (NSString *) stringWithoutHTMLInjection: (BOOL)stripHTMLCode stripAngular: (BOOL)stripAngular
|
||||||
{
|
{
|
||||||
NSString *result, *text, *newResult;
|
NSString *result, *text, *newResult;
|
||||||
NSScanner *theScanner;
|
NSScanner *theScanner;
|
||||||
@@ -1058,6 +1058,22 @@ static int cssEscapingCount;
|
|||||||
// Remove @import css (in style tags)
|
// Remove @import css (in style tags)
|
||||||
regex = [NSRegularExpression regularExpressionWithPattern:@"(<[\\s\\u200B	

\\\\0]*s[\\s\\u200B	

\\\\0]*t[\\s\\u200B	

\\\\0]*y[\\s\\u200B	

\\\\0]*l[\\s\\u200B	

\\\\0]*e.*)([\\s\\u200B	

\\\\0]*@[\\s\\u200B	

\\\\0]*i[\\s\\u200B	

\\\\0]*m[\\s\\u200B	

\\\\0]*p[\\s\\u200B	

\\\\0]*o[\\s\\u200B	

\\\\0]*r[\\s\\u200B	

\\\\0]*t)(.*<[\\s\\u200B	

\\\\0]*\\/[\\s\\u200B	

\\\\0]*s[\\s\\u200B	

\\\\0]*t[\\s\\u200B	

\\\\0]*y[\\s\\u200B	

\\\\0]*l[\\s\\u200B	

\\\\0]*e[\\s\\u200B	

\\\\0]*>)"
|
regex = [NSRegularExpression regularExpressionWithPattern:@"(<[\\s\\u200B	

\\\\0]*s[\\s\\u200B	

\\\\0]*t[\\s\\u200B	

\\\\0]*y[\\s\\u200B	

\\\\0]*l[\\s\\u200B	

\\\\0]*e.*)([\\s\\u200B	

\\\\0]*@[\\s\\u200B	

\\\\0]*i[\\s\\u200B	

\\\\0]*m[\\s\\u200B	

\\\\0]*p[\\s\\u200B	

\\\\0]*o[\\s\\u200B	

\\\\0]*r[\\s\\u200B	

\\\\0]*t)(.*<[\\s\\u200B	

\\\\0]*\\/[\\s\\u200B	

\\\\0]*s[\\s\\u200B	

\\\\0]*t[\\s\\u200B	

\\\\0]*y[\\s\\u200B	

\\\\0]*l[\\s\\u200B	

\\\\0]*e[\\s\\u200B	

\\\\0]*>)"
|
||||||
options: NSRegularExpressionCaseInsensitive error:&error];
|
options: NSRegularExpressionCaseInsensitive error:&error];
|
||||||
|
newResult = [regex stringByReplacingMatchesInString:result options:0 range:NSMakeRange(0, [result length]) withTemplate:@"onrep***="];
|
||||||
|
result = [NSString stringWithString: newResult];
|
||||||
|
|
||||||
|
|
||||||
|
if(stripAngular) {
|
||||||
|
// Remove {{ and }} as they are interprated by angularJS with no way of escaping
|
||||||
|
regex = [NSRegularExpression regularExpressionWithPattern:@"(\\{\\{)|({{)"
|
||||||
|
options: NSRegularExpressionCaseInsensitive error:&error];
|
||||||
|
newResult = [regex stringByReplacingMatchesInString:result options:0 range:NSMakeRange(0, [result length]) withTemplate:@"{\\\\{"];
|
||||||
|
result = [NSString stringWithString: newResult];
|
||||||
|
regex = [NSRegularExpression regularExpressionWithPattern:@"(\\}\\})|(}})"
|
||||||
|
options: NSRegularExpressionCaseInsensitive error:&error];
|
||||||
|
newResult = [regex stringByReplacingMatchesInString:result options:0 range:NSMakeRange(0, [result length]) withTemplate:@"}/}"];
|
||||||
|
result = [NSString stringWithString: newResult];
|
||||||
|
}
|
||||||
|
|
||||||
newResult = result;
|
newResult = result;
|
||||||
while([regex numberOfMatchesInString:newResult options:0 range:NSMakeRange(0, [newResult length])] > 0) {
|
while([regex numberOfMatchesInString:newResult options:0 range:NSMakeRange(0, [newResult length])] > 0) {
|
||||||
newResult = [regex stringByReplacingMatchesInString:newResult options:0 range:NSMakeRange(0, [newResult length]) withTemplate:@"$1@im****$3"];
|
newResult = [regex stringByReplacingMatchesInString:newResult options:0 range:NSMakeRange(0, [newResult length]) withTemplate:@"$1@im****$3"];
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ static const NSString *kCacheMotdKey = @"admin-motd";
|
|||||||
NSException *error;
|
NSException *error;
|
||||||
NSString *safeMotd;
|
NSString *safeMotd;
|
||||||
|
|
||||||
safeMotd = [motd stringWithoutHTMLInjection: NO];
|
safeMotd = [motd stringWithoutHTMLInjection: NO stripAngular: NO];
|
||||||
error = [[[GCSFolderManager defaultFolderManager] adminFolder] writeMotd: safeMotd];
|
error = [[[GCSFolderManager defaultFolderManager] adminFolder] writeMotd: safeMotd];
|
||||||
if (!error) {
|
if (!error) {
|
||||||
[[SOGoCache sharedCache] setValue:safeMotd forKey:kCacheMotdKey];
|
[[SOGoCache sharedCache] setValue:safeMotd forKey:kCacheMotdKey];
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ NSString *SOGoPasswordRecoverySecondaryEmail = @"SecondaryEmail";
|
|||||||
rc = NO;
|
rc = NO;
|
||||||
|
|
||||||
if ([fullName length])
|
if ([fullName length])
|
||||||
[identity setObject: [fullName stringWithoutHTMLInjection: YES] forKey: @"fullName"];
|
[identity setObject: [fullName stringWithoutHTMLInjection: YES stripAngular:NO] forKey: @"fullName"];
|
||||||
if ([email length])
|
if ([email length])
|
||||||
[identity setObject: email forKey: @"email"];
|
[identity setObject: email forKey: @"email"];
|
||||||
if ([replyTo length])
|
if ([replyTo length])
|
||||||
@@ -864,7 +864,7 @@ NSString *SOGoPasswordRecoverySecondaryEmail = @"SecondaryEmail";
|
|||||||
if (mailIdentity && [mailIdentity objectForKey: @"fullName"]) {
|
if (mailIdentity && [mailIdentity objectForKey: @"fullName"]) {
|
||||||
fullName = [NSString stringWithString: [mailIdentity objectForKey: @"fullName"]];
|
fullName = [NSString stringWithString: [mailIdentity objectForKey: @"fullName"]];
|
||||||
if (fullName) {
|
if (fullName) {
|
||||||
[mailIdentity setObject: [fullName stringWithoutHTMLInjection: YES] forKey: @"fullName"];
|
[mailIdentity setObject: [fullName stringWithoutHTMLInjection: YES stripAngular:NO] forKey: @"fullName"];
|
||||||
[mailIdentities setObject: mailIdentity atIndexedSubscript: i];
|
[mailIdentities setObject: mailIdentity atIndexedSubscript: i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,7 +61,7 @@
|
|||||||
request = [context request];
|
request = [context request];
|
||||||
params = [[request contentAsString] objectFromJSONString];
|
params = [[request contentAsString] objectFromJSONString];
|
||||||
|
|
||||||
name = [[params objectForKey: @"name"] stringWithoutHTMLInjection: YES];
|
name = [[params objectForKey: @"name"] stringWithoutHTMLInjection: YES stripAngular:NO];
|
||||||
nameInContainer = nil;
|
nameInContainer = nil;
|
||||||
|
|
||||||
if ([name length] > 0)
|
if ([name length] > 0)
|
||||||
|
|||||||
@@ -485,7 +485,7 @@ static Class SOGoContactGCSEntryK = Nil;
|
|||||||
co = [self clientObject];
|
co = [self clientObject];
|
||||||
card = [co vCard];
|
card = [co vCard];
|
||||||
request = [context request];
|
request = [context request];
|
||||||
params = [[[request contentAsString] stringWithoutHTMLInjection: YES] objectFromJSONString];
|
params = [[[request contentAsString] stringWithoutHTMLInjection: YES stripAngular:NO] objectFromJSONString];
|
||||||
forceSave = [[params objectForKey: @"ignoreDuplicate"] boolValue];
|
forceSave = [[params objectForKey: @"ignoreDuplicate"] boolValue];
|
||||||
|
|
||||||
[self setAttributes: params];
|
[self setAttributes: params];
|
||||||
|
|||||||
@@ -339,7 +339,7 @@
|
|||||||
[list retain];
|
[list retain];
|
||||||
|
|
||||||
request = [context request];
|
request = [context request];
|
||||||
params = [[[request contentAsString] stringWithoutHTMLInjection: YES] objectFromJSONString];
|
params = [[[request contentAsString] stringWithoutHTMLInjection: YES stripAngular:NO] objectFromJSONString];
|
||||||
|
|
||||||
o = [params objectForKey: @"refs"];
|
o = [params objectForKey: @"refs"];
|
||||||
if (![o isKindOfClass: [NSArray class]])
|
if (![o isKindOfClass: [NSArray class]])
|
||||||
|
|||||||
@@ -587,7 +587,7 @@
|
|||||||
|
|
||||||
//Sanitise the html content
|
//Sanitise the html content
|
||||||
if([d objectForKey:@"content"]){
|
if([d objectForKey:@"content"]){
|
||||||
[d setObject: [[d objectForKey:@"content"] stringWithoutHTMLInjection: NO] forKey: @"content"];
|
[d setObject: [[d objectForKey:@"content"] stringWithoutHTMLInjection: NO stripAngular:YES] forKey: @"content"];
|
||||||
}
|
}
|
||||||
|
|
||||||
return d;
|
return d;
|
||||||
|
|||||||
@@ -201,7 +201,7 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
content = [[[self generateResponse] contentAsString] stringWithoutHTMLInjection: NO];
|
content = [[[self generateResponse] contentAsString] stringWithoutHTMLInjection: NO stripAngular:YES];
|
||||||
if ([self respondsToSelector:@selector(getException)]) {
|
if ([self respondsToSelector:@selector(getException)]) {
|
||||||
e = [self getException];
|
e = [self getException];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,7 +79,7 @@
|
|||||||
|
|
||||||
request = [context request];
|
request = [context request];
|
||||||
params = [[request contentAsString] objectFromJSONString];
|
params = [[request contentAsString] objectFromJSONString];
|
||||||
folderName = [[params objectForKey: @"name"] stringWithoutHTMLInjection: YES];
|
folderName = [[params objectForKey: @"name"] stringWithoutHTMLInjection: YES stripAngular:NO];
|
||||||
if ([folderName length] > 0)
|
if ([folderName length] > 0)
|
||||||
{
|
{
|
||||||
encodedFolderName = [folderName stringByEncodingImap4FolderName];
|
encodedFolderName = [folderName stringByEncodingImap4FolderName];
|
||||||
@@ -145,7 +145,7 @@
|
|||||||
// Retrieve new folder name from JSON payload
|
// Retrieve new folder name from JSON payload
|
||||||
request = [context request];
|
request = [context request];
|
||||||
params = [[request contentAsString] objectFromJSONString];
|
params = [[request contentAsString] objectFromJSONString];
|
||||||
newFolderName = [[params objectForKey: @"name"] stringWithoutHTMLInjection: YES];
|
newFolderName = [[params objectForKey: @"name"] stringWithoutHTMLInjection: YES stripAngular:NO];
|
||||||
|
|
||||||
if (!newFolderName || [newFolderName length] == 0)
|
if (!newFolderName || [newFolderName length] == 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1178,7 +1178,7 @@
|
|||||||
[msg addObject: [NSNumber numberWithBool: [self isMessageFlagged]]];
|
[msg addObject: [NSNumber numberWithBool: [self isMessageFlagged]]];
|
||||||
|
|
||||||
// Subject
|
// Subject
|
||||||
[msg addObject: [[[self messageSubject] stringWithoutHTMLInjection: YES] stringWithoutHTMLInjection: NO]];
|
[msg addObject: [[[self messageSubject] stringWithoutHTMLInjection: YES stripAngular:NO] stringWithoutHTMLInjection: NO stripAngular:NO]];
|
||||||
|
|
||||||
// From
|
// From
|
||||||
from = [[message objectForKey: @"envelope"] from];
|
from = [[message objectForKey: @"envelope"] from];
|
||||||
|
|||||||
@@ -363,7 +363,7 @@ static NSString *mailETag = nil;
|
|||||||
if ([self formattedDate])
|
if ([self formattedDate])
|
||||||
[data setObject: [self formattedDate] forKey: @"date"];
|
[data setObject: [self formattedDate] forKey: @"date"];
|
||||||
if ([self messageSubject])
|
if ([self messageSubject])
|
||||||
[data setObject: [[[self messageSubject] stringWithoutHTMLInjection: YES] stringWithoutHTMLInjection: NO] forKey: @"subject"];
|
[data setObject: [[[self messageSubject] stringWithoutHTMLInjection: YES stripAngular:YES] stringWithoutHTMLInjection: NO stripAngular:YES] forKey: @"subject"];
|
||||||
if ((addresses = [addressFormatter dictionariesForArray: [co fromEnvelopeAddresses]]))
|
if ((addresses = [addressFormatter dictionariesForArray: [co fromEnvelopeAddresses]]))
|
||||||
[data setObject: addresses forKey: @"from"];
|
[data setObject: addresses forKey: @"from"];
|
||||||
if ((addresses = [addressFormatter dictionariesForArray: [co toEnvelopeAddresses]]))
|
if ((addresses = [addressFormatter dictionariesForArray: [co toEnvelopeAddresses]]))
|
||||||
|
|||||||
@@ -1091,7 +1091,7 @@ static const NSString *kJwtKey = @"jwt";
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Check common injection
|
//Check common injection
|
||||||
loginClean = [login stringWithoutHTMLInjection: YES];
|
loginClean = [login stringWithoutHTMLInjection: YES stripAngular:NO];
|
||||||
if(![loginClean isEqualToString: login])
|
if(![loginClean isEqualToString: login])
|
||||||
{
|
{
|
||||||
loginClean = @"";
|
loginClean = @"";
|
||||||
|
|||||||
@@ -1750,7 +1750,7 @@ static NSArray *reminderValues = nil;
|
|||||||
id o, v;
|
id o, v;
|
||||||
|
|
||||||
requestStr = [[context request] contentAsString];
|
requestStr = [[context request] contentAsString];
|
||||||
requestStr = [requestStr stringWithoutHTMLInjection: NO];
|
requestStr = [requestStr stringWithoutHTMLInjection: NO stripAngular:NO];
|
||||||
o = [requestStr objectFromJSONString];
|
o = [requestStr objectFromJSONString];
|
||||||
results = nil;
|
results = nil;
|
||||||
|
|
||||||
|
|||||||
@@ -403,7 +403,7 @@ static SoProduct *commonProduct = nil;
|
|||||||
theme = [[context request] formValueForKey: @"theme"];
|
theme = [[context request] formValueForKey: @"theme"];
|
||||||
if ([theme length])
|
if ([theme length])
|
||||||
{
|
{
|
||||||
safeTheme = [theme stringWithoutHTMLInjection: YES];
|
safeTheme = [theme stringWithoutHTMLInjection: YES stripAngular:NO];
|
||||||
if([safeTheme isEqualToString: theme])
|
if([safeTheme isEqualToString: theme])
|
||||||
rel = [NSString stringWithFormat: @"%@?theme=%@", rel, theme];
|
rel = [NSString stringWithFormat: @"%@?theme=%@", rel, theme];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -556,7 +556,7 @@
|
|||||||
|
|
||||||
ex = nil;
|
ex = nil;
|
||||||
request = [context request];
|
request = [context request];
|
||||||
params = [[[request contentAsString] stringWithoutHTMLInjection: NO] objectFromJSONString];
|
params = [[[request contentAsString] stringWithoutHTMLInjection: NO stripAngular:NO] objectFromJSONString];
|
||||||
if (params == nil)
|
if (params == nil)
|
||||||
{
|
{
|
||||||
ex = [NSException exceptionWithName: @"JSONParsingException"
|
ex = [NSException exceptionWithName: @"JSONParsingException"
|
||||||
|
|||||||
@@ -182,7 +182,7 @@ _intValueFromHex (NSString *hexString)
|
|||||||
fActiveTasks = [folder activeTasks];
|
fActiveTasks = [folder activeTasks];
|
||||||
|
|
||||||
[calendar setObject: folderName forKey: @"id"];
|
[calendar setObject: folderName forKey: @"id"];
|
||||||
[calendar setObject: [fDisplayName stringWithoutHTMLInjection: YES] forKey: @"name"];
|
[calendar setObject: [fDisplayName stringWithoutHTMLInjection: YES stripAngular:NO] forKey: @"name"];
|
||||||
[calendar setObject: [folder calendarColor] forKey: @"color"];
|
[calendar setObject: [folder calendarColor] forKey: @"color"];
|
||||||
isActive = [NSNumber numberWithBool: [folder isActive]];
|
isActive = [NSNumber numberWithBool: [folder isActive]];
|
||||||
[calendar setObject: isActive forKey: @"active"];
|
[calendar setObject: isActive forKey: @"active"];
|
||||||
|
|||||||
@@ -335,7 +335,7 @@
|
|||||||
|
|
||||||
ex = nil;
|
ex = nil;
|
||||||
request = [context request];
|
request = [context request];
|
||||||
params = [[[request contentAsString] stringWithoutHTMLInjection: NO] objectFromJSONString];
|
params = [[[request contentAsString] stringWithoutHTMLInjection: NO stripAngular:NO] objectFromJSONString];
|
||||||
if (params == nil)
|
if (params == nil)
|
||||||
{
|
{
|
||||||
ex = [NSException exceptionWithName: @"JSONParsingException"
|
ex = [NSException exceptionWithName: @"JSONParsingException"
|
||||||
|
|||||||
@@ -299,7 +299,7 @@
|
|||||||
<label class="pseudo-input-label">
|
<label class="pseudo-input-label">
|
||||||
<var:string label:value="Description"/>
|
<var:string label:value="Description"/>
|
||||||
</label>
|
</label>
|
||||||
<div>
|
<div ng-non-bindable="">
|
||||||
<md-content>
|
<md-content>
|
||||||
<var:string value="authorativeEvent.comment.stringByDetectingURLs" const:insertBR="1" const:escapeHTML="NO"/>
|
<var:string value="authorativeEvent.comment.stringByDetectingURLs" const:insertBR="1" const:escapeHTML="NO"/>
|
||||||
</md-content>
|
</md-content>
|
||||||
|
|||||||
Reference in New Issue
Block a user