- (NSString *)iCalCleanString;
@end
+#include "common.h"
+
+@interface SOGoICalStringEscaper : NSObject <NGStringEscaping>
+{
+}
++ (id)sharedEscaper;
+@end
+
+@implementation SOGoICalStringEscaper
++ (id)sharedEscaper {
+ static id sharedInstance = nil;
+ if(!sharedInstance) {
+ sharedInstance = [[self alloc] init];
+ }
+ return sharedInstance;
+}
+
+- (NSString *)stringByEscapingString:(NSString *)_s {
+ unichar c;
+
+ if(!_s || [_s length] == 0)
+ return nil;
+
+ c = [_s characterAtIndex:0];
+ if(c == '\n') {
+ return @"\\n";
+ }
+ else if(c == '\r') {
+ return nil; /* effectively remove char */
+ }
+ return [NSString stringWithFormat:@"\\%@", _s];
+}
+
+@end
+
@implementation NSString (SOGoiCal)
#if 0
/* 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 safeString;
+ return [self stringByEscapingCharactersFromSet:replaceSet
+ usingStringEscaping:[SOGoICalStringEscaper sharedEscaper]];
}
- (NSString *)iCalDQUOTESafeString {
/* Escape unsafe characters */
- (NSString *)iCalEscapedStringWithEscapeSet:(NSCharacterSet *)_es {
- 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];
- }
- while(er.length > 0);
- if(todoRange.length > 0) {
- [safeString appendString:[cleanString substringWithRange:todoRange]];
- }
- }
- return safeString;
+ NSString *s;
+
+ s = [self iCalCleanString];
+ return [s stringByEscapingCharactersFromSet:_es
+ usingStringEscaping:[SOGoICalStringEscaper sharedEscaper]];
}
@end