From 2389e4451376862db3b54e2319716615177ea063 Mon Sep 17 00:00:00 2001 From: Francis Lachapelle Date: Mon, 31 Jan 2022 14:51:26 -0500 Subject: [PATCH] fix(core): only escape "%" with the SQL LIKE operator --- SoObjects/Appointments/SOGoAppointmentFolder.m | 12 ++++++------ SoObjects/Contacts/SOGoContactGCSFolder.m | 6 +++--- SoObjects/SOGo/NSString+Utilities.h | 3 ++- SoObjects/SOGo/NSString+Utilities.m | 12 ++++++++---- SoObjects/SOGo/SOGoGCSFolder.m | 9 ++++----- SoObjects/SOGo/SQLSource.m | 2 +- 6 files changed, 24 insertions(+), 20 deletions(-) diff --git a/SoObjects/Appointments/SOGoAppointmentFolder.m b/SoObjects/Appointments/SOGoAppointmentFolder.m index 56cd097381..e18f9418a9 100644 --- a/SoObjects/Appointments/SOGoAppointmentFolder.m +++ b/SoObjects/Appointments/SOGoAppointmentFolder.m @@ -1,5 +1,5 @@ /* - Copyright (C) 2007-2014 Inverse inc. + Copyright (C) 2007-2022 Inverse inc. Copyright (C) 2004-2005 SKYRIX Software AG This file is part of SOGo. @@ -795,7 +795,7 @@ - (NSArray *) bareFetchFields: (NSArray *) fields if ([title length]) [baseWhere addObject: [NSString stringWithFormat: @"c_title isCaseInsensitiveLike: '%%%@%%'", - [title asSafeSQLString]]]; + [title asSafeSQLLikeString]]]; if (component) { @@ -1532,14 +1532,14 @@ - (NSArray *) fetchFields: (NSArray *) _fields if ([filters isEqualToString:@"title_Category_Location"] || [filters isEqualToString:@"entireContent"]) { [baseWhere addObject: [NSString stringWithFormat: @"(c_title isCaseInsensitiveLike: '%%%@%%' OR c_category isCaseInsensitiveLike: '%%%@%%' OR c_location isCaseInsensitiveLike: '%%%@%%')", - [title asSafeSQLString], - [title asSafeSQLString], - [title asSafeSQLString]]]; + [title asSafeSQLLikeString], + [title asSafeSQLLikeString], + [title asSafeSQLLikeString]]]; } } else [baseWhere addObject: [NSString stringWithFormat: @"c_title isCaseInsensitiveLike: '%%%@%%'", - [title asSafeSQLString]]]; + [title asSafeSQLLikeString]]]; } /* prepare mandatory fields */ diff --git a/SoObjects/Contacts/SOGoContactGCSFolder.m b/SoObjects/Contacts/SOGoContactGCSFolder.m index 55a49cd42e..3a4473cdb8 100644 --- a/SoObjects/Contacts/SOGoContactGCSFolder.m +++ b/SoObjects/Contacts/SOGoContactGCSFolder.m @@ -1,5 +1,5 @@ /* - Copyright (C) 2006-2013 Inverse inc. + Copyright (C) 2006-2022 Inverse inc. Copyright (C) 2004-2005 SKYRIX Software AG This file is part of SOGo. @@ -178,7 +178,7 @@ - (EOQualifier *) _qualifierForFilter: (NSString *) filter if ([filter length] > 0) { - filter = [filter asSafeSQLString]; + filter = [filter asSafeSQLLikeString]; if ([criteria isEqualToString: @"name_or_address"]) qs = [NSString stringWithFormat: @"(c_sn isCaseInsensitiveLike: '%%%@%%') OR " @@ -281,7 +281,7 @@ - (NSDictionary *) lookupContactWithName: (NSString *) aName if (aName && [aName length] > 0) { aName = [aName asSafeSQLString]; - qs = [NSString stringWithFormat: @"(c_name='%@')", aName]; + qs = [NSString stringWithFormat: @"(c_name = '%@')", aName]; qualifier = [EOQualifier qualifierWithQualifierFormat: qs]; dbRecords = [[self ocsFolder] fetchFields: folderListingFields matchingQualifier: qualifier]; diff --git a/SoObjects/SOGo/NSString+Utilities.h b/SoObjects/SOGo/NSString+Utilities.h index d6b6e278f8..91c5373cad 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-2015 Inverse inc. + * Copyright (C) 2006-2022 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 @@ -51,6 +51,7 @@ /* SQL safety */ - (NSString *) asSafeSQLString; +- (NSString *) asSafeSQLLikeString; /* Unicode safety */ - (NSString *) safeString; diff --git a/SoObjects/SOGo/NSString+Utilities.m b/SoObjects/SOGo/NSString+Utilities.m index adcb67b7c4..4229c6bdd5 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-2015 Inverse inc. + * Copyright (C) 2006-2022 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 @@ -688,9 +688,13 @@ - (id) objectFromJSONString - (NSString *) asSafeSQLString { - return [[[self stringByReplacingString: @"\\" withString: @"\\\\"] - stringByReplacingString: @"'" withString: @"\\'"] - stringByReplacingString: @"\%" withString: @"\\%"]; + return [[self stringByReplacingString: @"\\" withString: @"\\\\"] + stringByReplacingString: @"'" withString: @"\\'"]; +} + +- (NSString *) asSafeSQLLikeString +{ + return [[self asSafeSQLString] stringByReplacingString: @"\%" withString: @"\\%"]; } - (NSUInteger) countOccurrencesOfString: (NSString *) substring diff --git a/SoObjects/SOGo/SOGoGCSFolder.m b/SoObjects/SOGo/SOGoGCSFolder.m index 271139eceb..c9ce67aae9 100644 --- a/SoObjects/SOGo/SOGoGCSFolder.m +++ b/SoObjects/SOGo/SOGoGCSFolder.m @@ -1,7 +1,7 @@ /* SOGoGCSFolder.m - this file is part of SOGo * * Copyright (C) 2004-2005 SKYRIX Software AG - * Copyright (C) 2006-2014 Inverse inc. + * Copyright (C) 2006-2022 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 @@ -1929,8 +1929,8 @@ - (NSArray *) _fetchComponentsWithNames: (NSArray *) cNames if (sqlFilter) { filterString = [NSMutableString stringWithCapacity: 8192]; - [filterString appendFormat: @"(c_name='%@')", - [cNames componentsJoinedByString: @"' OR c_name='"]]; + [filterString appendFormat: @"(c_name = '%@')", + [cNames componentsJoinedByString: @"' OR c_name = '"]]; if ([sqlFilter length] > 0) [filterString appendFormat: @" AND (%@)", sqlFilter]; qualifier = [EOQualifier qualifierWithQualifierFormat: filterString]; @@ -1972,8 +1972,7 @@ - (NSArray *) _fetchComponentsMatchingObjectNames: (NSArray *) cNames { currentName = [[cNames objectAtIndex: count] asSafeSQLString]; queryNameLength = idQueryOverhead + [currentName length]; - if ((currentSize + queryNameLength) - > maxQuerySize) + if ((currentSize + queryNameLength) > maxQuerySize) { records = [self _fetchComponentsWithNames: currentNames fields: fields]; [components addObjectsFromArray: records]; diff --git a/SoObjects/SOGo/SQLSource.m b/SoObjects/SOGo/SQLSource.m index 3ee912ff7a..9fed8b45bf 100644 --- a/SoObjects/SOGo/SQLSource.m +++ b/SoObjects/SOGo/SQLSource.m @@ -776,7 +776,7 @@ - (NSArray *) fetchContactsMatching: (NSString *) filter if (channel) { lowerFilter = [filter lowercaseString]; - lowerFilter = [lowerFilter stringByReplacingString: @"'" withString: @"''"]; + lowerFilter = [lowerFilter asSafeSQLLikeString]; sql = [NSMutableString stringWithFormat: (@"SELECT *" @" FROM %@"