Properly escape some control chars (and generalized it)

pull/17/merge
Ludovic Marcotte 2014-02-04 15:03:02 -05:00
parent 2ff3b5ef5f
commit 31969d162d
10 changed files with 70 additions and 48 deletions

View File

@ -54,16 +54,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
n = [self n];
if ((o = [n flattenedValueAtIndex: 0 forKey: @""]))
[s appendFormat: @"<LastName xmlns=\"Contacts:\">%@</LastName>", [o stringByEscapingHTMLString]];
[s appendFormat: @"<LastName xmlns=\"Contacts:\">%@</LastName>", [o activeSyncRepresentation]];
if ((o = [n flattenedValueAtIndex: 1 forKey: @""]))
[s appendFormat: @"<FirstName xmlns=\"Contacts:\">%@</FirstName>", [o stringByEscapingHTMLString]];
[s appendFormat: @"<FirstName xmlns=\"Contacts:\">%@</FirstName>", [o activeSyncRepresentation]];
if ((o = [self workCompany]))
[s appendFormat: @"<CompanyName xmlns=\"Contacts:\">%@</CompanyName>", [o stringByEscapingHTMLString]];
[s appendFormat: @"<CompanyName xmlns=\"Contacts:\">%@</CompanyName>", [o activeSyncRepresentation]];
if ((o = [self title]))
[s appendFormat: @"<JobTitle xmlns=\"Contacts:\">%@</JobTitle>", [o stringByEscapingHTMLString]];
[s appendFormat: @"<JobTitle xmlns=\"Contacts:\">%@</JobTitle>", [o activeSyncRepresentation]];
if ((o = [self preferredEMail]))
[s appendFormat: @"<Email1Address xmlns=\"Contacts:\">%@</Email1Address>", o];
@ -84,19 +84,19 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Telephone numbers
if ((o = [self workPhone]) && [o length])
[s appendFormat: @"<BusinessPhoneNumber xmlns=\"Contacts:\">%@</BusinessPhoneNumber>", [o stringByEscapingHTMLString]];
[s appendFormat: @"<BusinessPhoneNumber xmlns=\"Contacts:\">%@</BusinessPhoneNumber>", [o activeSyncRepresentation]];
if ((o = [self homePhone]) && [o length])
[s appendFormat: @"<HomePhoneNumber xmlns=\"Contacts:\">%@</HomePhoneNumber>", [o stringByEscapingHTMLString]];
[s appendFormat: @"<HomePhoneNumber xmlns=\"Contacts:\">%@</HomePhoneNumber>", [o activeSyncRepresentation]];
if ((o = [self fax]) && [o length])
[s appendFormat: @"<BusinessFaxNumber xmlns=\"Contacts:\">%@</BusinessFaxNumber>", [o stringByEscapingHTMLString]];
[s appendFormat: @"<BusinessFaxNumber xmlns=\"Contacts:\">%@</BusinessFaxNumber>", [o activeSyncRepresentation]];
if ((o = [self mobile]) && [o length])
[s appendFormat: @"<MobilePhoneNumber xmlns=\"Contacts:\">%@</MobilePhoneNumber>", [o stringByEscapingHTMLString]];
[s appendFormat: @"<MobilePhoneNumber xmlns=\"Contacts:\">%@</MobilePhoneNumber>", [o activeSyncRepresentation]];
if ((o = [self pager]) && [o length])
[s appendFormat: @"<PagerNumber xmlns=\"Contacts:\">%@</PagerNumber>", [o stringByEscapingHTMLString]];
[s appendFormat: @"<PagerNumber xmlns=\"Contacts:\">%@</PagerNumber>", [o activeSyncRepresentation]];
// Home Address
addresses = [self childrenWithTag: @"adr"
@ -108,19 +108,19 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
homeAdr = [addresses objectAtIndex: 0];
if ((o = [homeAdr flattenedValueAtIndex: 2 forKey: @""]))
[s appendFormat: @"<HomeStreet xmlns=\"Contacts:\">%@</HomeStreet>", [o stringByEscapingHTMLString]];
[s appendFormat: @"<HomeStreet xmlns=\"Contacts:\">%@</HomeStreet>", [o activeSyncRepresentation]];
if ((o = [homeAdr flattenedValueAtIndex: 3 forKey: @""]))
[s appendFormat: @"<HomeCity xmlns=\"Contacts:\">%@</HomeCity>", [o stringByEscapingHTMLString]];
[s appendFormat: @"<HomeCity xmlns=\"Contacts:\">%@</HomeCity>", [o activeSyncRepresentation]];
if ((o = [homeAdr flattenedValueAtIndex: 4 forKey: @""]))
[s appendFormat: @"<HomeState xmlns=\"Contacts:\">%@</HomeState>", [o stringByEscapingHTMLString]];
[s appendFormat: @"<HomeState xmlns=\"Contacts:\">%@</HomeState>", [o activeSyncRepresentation]];
if ((o = [homeAdr flattenedValueAtIndex: 5 forKey: @""]))
[s appendFormat: @"<HomePostalCode xmlns=\"Contacts:\">%@</HomePostalCode>", [o stringByEscapingHTMLString]];
[s appendFormat: @"<HomePostalCode xmlns=\"Contacts:\">%@</HomePostalCode>", [o activeSyncRepresentation]];
if ((o = [homeAdr flattenedValueAtIndex: 6 forKey: @""]))
[s appendFormat: @"<HomeCountry xmlns=\"Contacts:\">%@</HomeCountry>", [o stringByEscapingHTMLString]];
[s appendFormat: @"<HomeCountry xmlns=\"Contacts:\">%@</HomeCountry>", [o activeSyncRepresentation]];
}
// Work Address
@ -133,19 +133,19 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
workAdr = [addresses objectAtIndex: 0];
if ((o = [workAdr flattenedValueAtIndex: 2 forKey: @""]))
[s appendFormat: @"<BusinessStreet xmlns=\"Contacts:\">%@</BusinessStreet>", [o stringByEscapingHTMLString]];
[s appendFormat: @"<BusinessStreet xmlns=\"Contacts:\">%@</BusinessStreet>", [o activeSyncRepresentation]];
if ((o = [workAdr flattenedValueAtIndex: 3 forKey: @""]))
[s appendFormat: @"<BusinessCity xmlns=\"Contacts:\">%@</BusinessCity>", [o stringByEscapingHTMLString]];
[s appendFormat: @"<BusinessCity xmlns=\"Contacts:\">%@</BusinessCity>", [o activeSyncRepresentation]];
if ((o = [workAdr flattenedValueAtIndex: 4 forKey: @""]))
[s appendFormat: @"<BusinessState xmlns=\"Contacts:\">%@</BusinessState>", [o stringByEscapingHTMLString]];
[s appendFormat: @"<BusinessState xmlns=\"Contacts:\">%@</BusinessState>", [o activeSyncRepresentation]];
if ((o = [workAdr flattenedValueAtIndex: 5 forKey: @""]))
[s appendFormat: @"<BusinessPostalCode xmlns=\"Contacts:\">%@</BusinessPostalCode>", [o stringByEscapingHTMLString]];
[s appendFormat: @"<BusinessPostalCode xmlns=\"Contacts:\">%@</BusinessPostalCode>", [o activeSyncRepresentation]];
if ((o = [workAdr flattenedValueAtIndex: 6 forKey: @""]))
[s appendFormat: @"<BusinessCountry xmlns=\"Contacts:\">%@</BusinessCountry>", [o stringByEscapingHTMLString]];
[s appendFormat: @"<BusinessCountry xmlns=\"Contacts:\">%@</BusinessCountry>", [o activeSyncRepresentation]];
}
// Other, less important fields
@ -154,7 +154,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
if ((o = [self note]))
{
o = [o stringByEscapingHTMLString];
o = [o activeSyncRepresentation];
[s appendString: @"<Body xmlns=\"AirSyncBase:\">"];
[s appendFormat: @"<Type>%d</Type>", 1];
[s appendFormat: @"<EstimatedDataSize>%d</EstimatedDataSize>", [o length]];

View File

@ -36,7 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <wbxml/wbxml_conv.h>
#include <wbxml/wbxml_errors.h>
#define WBXMLDEBUG 0
#define WBXMLDEBUG 1
@implementation NSData (ActiveSync)

View File

@ -39,6 +39,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@interface NSString (ActiveSync)
- (NSString *) activeSyncRepresentation;
- (int) activeSyncFolderType;
- (NSString *) realCollectionIdWithFolderType: (SOGoMicrosoftActiveSyncFolderType *) folderType;
- (NSCalendarDate *) calendarDate;

View File

@ -34,10 +34,22 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <Foundation/NSData.h>
#include <Foundation/NSDate.h>
#include <SOGo/NSString+Utilities.h>
#include <NGExtensions/NSString+misc.h>
@implementation NSString (ActiveSync)
- (NSString *) activeSyncRepresentation
{
NSString *s;
s = [self stringByEscapingHTMLString];
return [[s componentsSeparatedByCharactersInSet: [self safeCharacterSet]]
componentsJoinedByString: @""];
}
- (int) activeSyncFolderType
{
if ([self isEqualToString: @"inbox"])

View File

@ -508,26 +508,26 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
[serverId stringByEscapingURL],
[parentId stringByEscapingURL],
type,
[name stringByEscapingHTMLString]];
[name activeSyncRepresentation]];
}
// We add the personal calendar - events
// FIXME: add all calendars
currentFolder = [[context activeUser] personalCalendarFolderInContext: context];
name = [NSString stringWithFormat: @"vevent/%@", [currentFolder nameInContainer]];
[s appendFormat: @"<Add><ServerId>%@</ServerId><ParentId>%@</ParentId><Type>%d</Type><DisplayName>%@</DisplayName></Add>", name, @"0", 8, [[currentFolder displayName] stringByEscapingHTMLString]];
[s appendFormat: @"<Add><ServerId>%@</ServerId><ParentId>%@</ParentId><Type>%d</Type><DisplayName>%@</DisplayName></Add>", name, @"0", 8, [[currentFolder displayName] activeSyncRepresentation]];
// We add the personal calendar - tasks
// FIXME: add all calendars
currentFolder = [[context activeUser] personalCalendarFolderInContext: context];
name = [NSString stringWithFormat: @"vtodo/%@", [currentFolder nameInContainer]];
[s appendFormat: @"<Add><ServerId>%@</ServerId><ParentId>%@</ParentId><Type>%d</Type><DisplayName>%@</DisplayName></Add>", name, @"0", 7, [[currentFolder displayName] stringByEscapingHTMLString]];
[s appendFormat: @"<Add><ServerId>%@</ServerId><ParentId>%@</ParentId><Type>%d</Type><DisplayName>%@</DisplayName></Add>", name, @"0", 7, [[currentFolder displayName] activeSyncRepresentation]];
// We add the personal address book
// FIXME: add all address books
currentFolder = [[context activeUser] personalContactsFolderInContext: context];
name = [NSString stringWithFormat: @"vcard/%@", [currentFolder nameInContainer]];
[s appendFormat: @"<Add><ServerId>%@</ServerId><ParentId>%@</ParentId><Type>%d</Type><DisplayName>%@</DisplayName></Add>", name, @"0", 9, [[currentFolder displayName] stringByEscapingHTMLString]];
[s appendFormat: @"<Add><ServerId>%@</ServerId><ParentId>%@</ParentId><Type>%d</Type><DisplayName>%@</DisplayName></Add>", name, @"0", 9, [[currentFolder displayName] activeSyncRepresentation]];
}
[s appendString: @"</Changes></FolderSync>"];

View File

@ -344,13 +344,13 @@ struct GlobalObjectId {
// From
value = [self _emailAddressesFrom: [[self envelope] from]];
if (value)
[s appendFormat: @"<From xmlns=\"Email:\">%@</From>", [value stringByEscapingHTMLString]];
[s appendFormat: @"<From xmlns=\"Email:\">%@</From>", [value activeSyncRepresentation]];
// To - "The value of this element contains one or more e-mail addresses.
// If there are multiple e-mail addresses, they are separated by commas."
value = [self _emailAddressesFrom: [[self envelope] to]];
if (value)
[s appendFormat: @"<To xmlns=\"Email:\">%@</To>", [value stringByEscapingHTMLString]];
[s appendFormat: @"<To xmlns=\"Email:\">%@</To>", [value activeSyncRepresentation]];
// DisplayTo
[s appendFormat: @"<DisplayTo xmlns=\"Email:\">\"%@\"</DisplayTo>", [[context activeUser] login]];
@ -358,14 +358,14 @@ struct GlobalObjectId {
// Cc - same syntax as the To field
value = [self _emailAddressesFrom: [[self envelope] cc]];
if (value)
[s appendFormat: @"<Cc xmlns=\"Email:\">%@</Cc>", [value stringByEscapingHTMLString]];
[s appendFormat: @"<Cc xmlns=\"Email:\">%@</Cc>", [value activeSyncRepresentation]];
// Subject
value = [self decodedSubject];
if (value)
{
[s appendFormat: @"<Subject xmlns=\"Email:\">%@</Subject>", [value stringByEscapingHTMLString]];
[s appendFormat: @"<ThreadTopic xmlns=\"Email:\">%@</ThreadTopic>", [value stringByEscapingHTMLString]];
[s appendFormat: @"<Subject xmlns=\"Email:\">%@</Subject>", [value activeSyncRepresentation]];
[s appendFormat: @"<ThreadTopic xmlns=\"Email:\">%@</ThreadTopic>", [value activeSyncRepresentation]];
}
// DateReceived
@ -459,7 +459,7 @@ struct GlobalObjectId {
content = [[NSString alloc] initWithData: d encoding: NSUTF8StringEncoding];
AUTORELEASE(content);
content = [content stringByEscapingHTMLString];
content = [content activeSyncRepresentation];
len = [content length];
[s appendString: @"<Body xmlns=\"AirSyncBase:\">"];
@ -483,7 +483,7 @@ struct GlobalObjectId {
value = [attachmentKeys objectAtIndex: i];
[s appendString: @"<Attachment>"];
[s appendFormat: @"<DisplayName>%@</DisplayName>", [[value objectForKey: @"filename"] stringByEscapingHTMLString]];
[s appendFormat: @"<DisplayName>%@</DisplayName>", [[value objectForKey: @"filename"] activeSyncRepresentation]];
// FileReference must be a unique identifier across the whole store. We use the following structure:
// mail/<foldername>/<message UID/<pathofpart>

View File

@ -138,11 +138,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Subject -- http://msdn.microsoft.com/en-us/library/ee157192(v=exchg.80).aspx
if ([[self summary] length])
[s appendFormat: @"<Subject xmlns=\"Calendar:\">%@</Subject>", [[self summary] stringByEscapingHTMLString]];
[s appendFormat: @"<Subject xmlns=\"Calendar:\">%@</Subject>", [[self summary] activeSyncRepresentation]];
// Location
if ([[self location] length])
[s appendFormat: @"<Location xmlns=\"Calendar:\">%@</Location>", [[self location] stringByEscapingHTMLString]];
[s appendFormat: @"<Location xmlns=\"Calendar:\">%@</Location>", [[self location] activeSyncRepresentation]];
// Importance - NOT SUPPORTED - DO NOT ENABLE
//o = [self priority];
@ -184,7 +184,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
o = [self comment];
if ([o length])
{
o = [o stringByEscapingHTMLString];
o = [o activeSyncRepresentation];
[s appendString: @"<Body xmlns=\"AirSyncBase:\">"];
[s appendFormat: @"<Type>%d</Type>", 1];
[s appendFormat: @"<EstimatedDataSize>%d</EstimatedDataSize>", [o length]];

View File

@ -97,11 +97,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Subject
o = [self summary];
if ([o length])
[s appendFormat: @"<Subject xmlns=\"Tasks:\">%@</Subject>", [[self summary] stringByEscapingHTMLString]];
[s appendFormat: @"<Subject xmlns=\"Tasks:\">%@</Subject>", [[self summary] activeSyncRepresentation]];
if ((o = [self comment]))
{
o = [o stringByEscapingHTMLString];
o = [o activeSyncRepresentation];
[s appendString: @"<Body xmlns=\"AirSyncBase:\">"];
[s appendFormat: @"<Type>%d</Type>", 1];
[s appendFormat: @"<EstimatedDataSize>%d</EstimatedDataSize>", [o length]];

View File

@ -1,6 +1,6 @@
/* NSString+Utilities.h - this file is part of SOGo
*
* Copyright (C) 2006-2013 Inverse inc.
* Copyright (C) 2006-2014 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
@ -23,6 +23,7 @@
#import <Foundation/NSString.h>
@class NSCharacterSet;
@class NSDictionary;
@class NSObject;
@ -49,6 +50,7 @@
- (NSString *) asSafeSQLString;
/* JSON */
- (NSCharacterSet *) safeCharacterSet;
- (NSString *) jsonRepresentation;
- (BOOL) isJSONString;
- (id) objectFromJSONString;

View File

@ -1,6 +1,6 @@
/* NSString+Utilities.m - this file is part of SOGo
*
* Copyright (C) 2006-2013 Inverse inc.
* Copyright (C) 2006-2014 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
@ -46,6 +46,10 @@ static NSString **cssEscapingStrings = NULL;
static unichar *cssEscapingCharacters = NULL;
static int cssEscapingCount;
static unichar thisCharCode[29];
static NSString *controlCharString = nil;
static NSCharacterSet *controlCharSet = nil;
@implementation NSString (SOGoURLExtension)
- (NSString *) composeURLWithAction: (NSString *) action
@ -274,16 +278,12 @@ static int cssEscapingCount;
return [NSString stringWithFormat: @"\"%@\"", representation];
}
- (NSString *) jsonRepresentation
- (NSCharacterSet *) safeCharacterSet
{
static unichar thisCharCode[29];
static NSString *controlCharString = nil;
static NSCharacterSet *controlCharSet = nil;
NSString *cleanedString;
int i, j;
if (!controlCharSet)
{
int i, j;
// Create an array of chars for all control characters between 0x00 and 0x1F,
// apart from \t, \n, \f and \r (0x08, 0x09, 0x0A, 0x0C and 0x0D)
for (i = 0, j = 0x00; j < 0x08; i++, j++) {
@ -293,7 +293,7 @@ static int cssEscapingCount;
for (j = 0x0E; j <= 0x1F; i++, j++) {
thisCharCode[i] = j;
}
// Also add some unicode separators
thisCharCode[i++] = 0x2028; // line separator
thisCharCode[i++] = 0x2029; // paragraph separator
@ -302,8 +302,15 @@ static int cssEscapingCount;
[controlCharSet retain];
}
return controlCharSet;
}
- (NSString *) jsonRepresentation
{
NSString *cleanedString;
// Escape double quotes and remove control characters
cleanedString = [[[self doubleQuotedString] componentsSeparatedByCharactersInSet: controlCharSet]
cleanedString = [[[self doubleQuotedString] componentsSeparatedByCharactersInSet: [self safeCharacterSet]]
componentsJoinedByString: @""];
return cleanedString;
}