#import "NSString+iCal.h"
+@interface NSString (SOGoiCal_Private)
+- (NSString *)iCalCleanString;
+@end
+
@implementation NSString (SOGoiCal)
#if 0
- (NSString *)iCalFoldedString {
- /* RFC2445, 4.1 Content Lines
-
- The iCalendar object is organized into individual lines of text,
- called content lines. Content lines are delimited by a line break,
- which is a CRLF sequence (US-ASCII decimal 13, followed by US-ASCII
- decimal 10).
- Lines of text SHOULD NOT be longer than 75 octets, excluding the line
- break. Long content lines SHOULD be split into a multiple line
- representations using a line "folding" technique. That is, a long
- line can be split between any two characters by inserting a CRLF
- immediately followed by a single linear white space character (i.e.,
- SPACE, US-ASCII decimal 32 or HTAB, US-ASCII decimal 9).
- Any sequence of CRLF followed immediately by a single linear white space
- character is ignored (i.e., removed) when processing the content type.
- */
+ /* RFC2445, 4.1 Content Lines
+
+ The iCalendar object is organized into individual lines of text,
+ called content lines. Content lines are delimited by a line break,
+ which is a CRLF sequence (US-ASCII decimal 13, followed by US-ASCII
+ decimal 10).
+ Lines of text SHOULD NOT be longer than 75 octets, excluding the line
+ break. Long content lines SHOULD be split into a multiple line
+ representations using a line "folding" technique. That is, a long
+ line can be split between any two characters by inserting a CRLF
+ immediately followed by a single linear white space character (i.e.,
+ SPACE, US-ASCII decimal 32 or HTAB, US-ASCII decimal 9).
+ Any sequence of CRLF followed immediately by a single linear white space
+ character is ignored (i.e., removed) when processing the content type.
+ */
}
#endif
-- (NSString *)iCalDQUOTESafeString {
- static NSCharacterSet *escapeSet = nil;
-
- if(escapeSet == nil) {
- escapeSet = [NSCharacterSet characterSetWithCharactersInString:@"\""];
- [escapeSet retain];
+/* strip off any characters from string which are not allowed in iCal */
+- (NSString *)iCalCleanString {
+ static NSCharacterSet *replaceSet = nil;
+ NSRange r, er;
+ NSMutableString *safeString;
+ BOOL needsReplacing;
+ unsigned length;
+
+ if(replaceSet == nil) {
+ replaceSet = [NSCharacterSet characterSetWithCharactersInString:@"\r"];
+ [replaceSet retain];
+ }
+
+ length = [self length];
+ r = NSMakeRange(0, length);
+ er = [self rangeOfCharacterFromSet:replaceSet options:0 range:r];
+ needsReplacing = er.length > 0 ? YES : NO;
+ if(!needsReplacing) {
+ return self; /* cheap */
+ }
+
+ safeString = [NSMutableString stringWithCapacity:length];
+ if(needsReplacing) {
+ NSRange todoRange;
+ /*
+ r == previous range, upto er.location
+ er == escape range
+ todoRange == what we still need to scan
+ */
+ length = r.length;
+ do {
+ r.length = er.location - r.location;
+ if(r.length > 0)
+ [safeString appendString:[self substringWithRange:r]];
+ r.location = NSMaxRange(er);
+ todoRange.location = r.location;
+ todoRange.length = length - r.location;
+ er = [self rangeOfCharacterFromSet:replaceSet
+ options:0
+ range:todoRange];
+ }
+ while(er.length > 0);
+ if(todoRange.length > 0) {
+ [safeString appendString:[self substringWithRange:todoRange]];
}
- return [self iCalEscapedStringWithEscapeSet:escapeSet];
+ }
+ return safeString;
}
-- (NSString *)iCalSafeString {
- static NSCharacterSet *escapeSet = nil;
+- (NSString *)iCalDQUOTESafeString {
+ static NSCharacterSet *escapeSet = nil;
+
+ if(escapeSet == nil) {
+ escapeSet = [NSCharacterSet characterSetWithCharactersInString:@"\""];
+ [escapeSet retain];
+ }
+ return [self iCalEscapedStringWithEscapeSet:escapeSet];
+}
- if(escapeSet == nil) {
- escapeSet = [NSCharacterSet characterSetWithCharactersInString:@"\n,;\""];
- [escapeSet retain];
- }
- return [self iCalEscapedStringWithEscapeSet:escapeSet];
+- (NSString *)iCalSafeString {
+ static NSCharacterSet *escapeSet = nil;
+
+ if(escapeSet == nil) {
+ escapeSet = [NSCharacterSet characterSetWithCharactersInString:@"\n,;\""];
+ [escapeSet retain];
+ }
+ return [self iCalEscapedStringWithEscapeSet:escapeSet];
}
+/* Escape unsafe characters */
- (NSString *)iCalEscapedStringWithEscapeSet:(NSCharacterSet *)_es {
- /* Escape unsafe characters */
- NSMutableString *safeString;
- NSRange r, er;
- BOOL needsEscaping;
- unsigned length;
-
- length = [self length];
- r = NSMakeRange(0, length);
- er = [self rangeOfCharacterFromSet:_es options:0 range:r];
- needsEscaping = er.length > 0 ? YES : NO;
- if(!needsEscaping) {
- return self; /* cheap */
+ NSString *cleanString;
+ NSMutableString *safeString;
+ NSRange r, er;
+ BOOL needsEscaping;
+ unsigned length;
+
+ cleanString = [self iCalCleanString];
+ length = [cleanString length];
+ r = NSMakeRange(0, length);
+ er = [cleanString rangeOfCharacterFromSet:_es options:0 range:r];
+ needsEscaping = er.length > 0 ? YES : NO;
+ if(!needsEscaping) {
+ return cleanString; /* cheap */
+ }
+ /* wild guess */
+ safeString = [NSMutableString stringWithCapacity:length + 10];
+ if(needsEscaping) {
+ NSRange todoRange;
+ /*
+ r == previous range, upto er.location
+ er == escape range
+ todoRange == what we still need to scan
+ */
+ length = r.length;
+ do {
+ NSString *s;
+
+ r.length = er.location - r.location;
+ if(r.length > 0) {
+ s = [cleanString substringWithRange:r];
+ [safeString appendString:s];
+ }
+ [safeString appendString:@"\\"];
+ if([cleanString characterAtIndex:er.location] == '\n') {
+ s = @"n";
+ }
+ else {
+ s = [cleanString substringWithRange:er];
+ }
+ [safeString appendString:s];
+ r.location = NSMaxRange(er);
+ todoRange.location = r.location;
+ todoRange.length = length - r.location;
+ er = [cleanString rangeOfCharacterFromSet:_es
+ options:0
+ range:todoRange];
}
- /* wild guess */
- safeString = [NSMutableString stringWithCapacity:length + 10];
- if(needsEscaping) {
- NSRange todoRange;
- /*
- r == previous range, upto er.location
- er == escape range
- todoRange == what we still need to scan
- */
- length = r.length;
- do {
- NSString *s;
-
- r.length = (er.location - 1) - r.location;
- s = [self substringWithRange:r];
- [safeString appendString:s];
- [safeString appendString:@"\\"];
- if([self characterAtIndex:er.location] == '\n') {
- s = @"n";
- }
- else {
- s = [self substringWithRange:er];
- }
- [safeString appendString:s];
- r.location = NSMaxRange(er);
- todoRange.location = r.location;
- todoRange.length = length - r.location;
- er = [self rangeOfCharacterFromSet:_es
- options:0
- range:todoRange];
- }
- while(er.length > 0);
- if(todoRange.length > 0) {
- [safeString appendString:[self substringWithRange:todoRange]];
- }
+ while(er.length > 0);
+ if(todoRange.length > 0) {
+ [safeString appendString:[cleanString substringWithRange:todoRange]];
}
- return safeString;
+ }
+ return safeString;
}
@end