2007-01-31 18:11:29 +01:00
|
|
|
/* NSString+NGCards.m - this file is part of SOPE
|
|
|
|
*
|
2010-09-28 18:07:58 +02:00
|
|
|
* Copyright (C) 2006-2010 Inverse inc.
|
2007-01-31 18:11:29 +01:00
|
|
|
*
|
|
|
|
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
|
|
|
*
|
|
|
|
* 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
|
|
|
|
* the Free Software Foundation; either version 2, or (at your option)
|
|
|
|
* any later version.
|
|
|
|
*
|
|
|
|
* This file is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; see the file COPYING. If not, write to
|
|
|
|
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
|
|
* Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#import <Foundation/NSArray.h>
|
2007-02-08 17:26:41 +01:00
|
|
|
#import <Foundation/NSCalendarDate.h>
|
2008-07-04 18:06:09 +02:00
|
|
|
#import <Foundation/NSEnumerator.h>
|
2007-01-31 18:11:29 +01:00
|
|
|
#import <Foundation/NSRange.h>
|
|
|
|
#import <Foundation/NSTimeZone.h>
|
2008-07-04 18:06:09 +02:00
|
|
|
|
2007-01-31 18:11:29 +01:00
|
|
|
#import <NGExtensions/NSObject+Logs.h>
|
|
|
|
|
|
|
|
#import <ctype.h>
|
|
|
|
|
|
|
|
#import "NSString+NGCards.h"
|
|
|
|
|
|
|
|
static NSString *commaSeparator = nil;
|
|
|
|
|
|
|
|
@implementation NSString (NGCardsExtensions)
|
|
|
|
|
|
|
|
- (void) _initCommaSeparator
|
|
|
|
{
|
|
|
|
commaSeparator = [NSMutableString stringWithFormat: @"%c", 255];
|
|
|
|
[commaSeparator retain];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSString *) foldedForVersitCards
|
|
|
|
{
|
|
|
|
NSMutableString *foldedString;
|
|
|
|
unsigned int length;
|
|
|
|
NSRange subStringRange;
|
|
|
|
|
2008-07-16 18:24:28 +02:00
|
|
|
foldedString = [NSMutableString string];
|
2007-03-07 22:22:45 +01:00
|
|
|
|
2007-01-31 18:11:29 +01:00
|
|
|
length = [self length];
|
2010-08-03 16:36:33 +02:00
|
|
|
if (length < 77)
|
2007-03-07 22:22:45 +01:00
|
|
|
[foldedString appendString: self];
|
2007-01-31 18:11:29 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
subStringRange = NSMakeRange (0, 75);
|
|
|
|
[foldedString appendFormat: @"%@\r\n",
|
|
|
|
[self substringWithRange: subStringRange]];
|
|
|
|
subStringRange = NSMakeRange (75, 74);
|
2010-08-03 16:36:33 +02:00
|
|
|
while ((length - subStringRange.location) > 75)
|
2007-01-31 18:11:29 +01:00
|
|
|
{
|
|
|
|
[foldedString appendFormat: @" %@\r\n",
|
|
|
|
[self substringWithRange: subStringRange]];
|
|
|
|
subStringRange.location += 74;
|
|
|
|
}
|
|
|
|
subStringRange.length = length - subStringRange.location;
|
|
|
|
[foldedString appendFormat: @" %@",
|
|
|
|
[self substringWithRange: subStringRange]];
|
|
|
|
}
|
|
|
|
|
2007-03-07 22:22:45 +01:00
|
|
|
return foldedString;
|
2007-01-31 18:11:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSArray *) asCardAttributeValues
|
|
|
|
{
|
|
|
|
NSMutableArray *values;
|
|
|
|
NSEnumerator *rawValues;
|
|
|
|
NSString *tmpString, *rawValue, *newString;
|
|
|
|
|
2008-07-16 18:24:28 +02:00
|
|
|
values = [NSMutableArray array];
|
2007-01-31 18:11:29 +01:00
|
|
|
|
|
|
|
if (!commaSeparator)
|
|
|
|
[self _initCommaSeparator];
|
|
|
|
|
|
|
|
tmpString = [self stringByReplacingString: @"\\,"
|
|
|
|
withString: commaSeparator];
|
|
|
|
rawValues = [[tmpString componentsSeparatedByString: @","]
|
|
|
|
objectEnumerator];
|
2008-07-16 18:24:28 +02:00
|
|
|
while ((rawValue = [rawValues nextObject]))
|
2007-01-31 18:11:29 +01:00
|
|
|
{
|
|
|
|
newString = [rawValue stringByReplacingString: commaSeparator
|
|
|
|
withString: @","];
|
|
|
|
[values addObject: [newString stringByTrimmingSpaces]];
|
|
|
|
}
|
|
|
|
|
|
|
|
return values;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSString *) escapedForCards
|
|
|
|
{
|
|
|
|
NSString *string;
|
|
|
|
|
|
|
|
string = [self stringByReplacingString: @"\\"
|
|
|
|
withString: @"\\\\"];
|
2008-12-05 15:39:43 +01:00
|
|
|
// string = [string stringByReplacingString: @","
|
|
|
|
// withString: @"\\,"];
|
|
|
|
// string = [string stringByReplacingString: @":"
|
|
|
|
// withString: @"\\:"];
|
2007-01-31 18:11:29 +01:00
|
|
|
string = [string stringByReplacingString: @";"
|
|
|
|
withString: @"\\;"];
|
|
|
|
string = [string stringByReplacingString: @"\n"
|
|
|
|
withString: @"\\n"];
|
|
|
|
string = [string stringByReplacingString: @"\r"
|
|
|
|
withString: @"\\r"];
|
|
|
|
|
|
|
|
return string;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSString *) unescapedFromCard
|
|
|
|
{
|
|
|
|
NSString *string;
|
|
|
|
|
|
|
|
string = [self stringByReplacingString: @"\\,"
|
|
|
|
withString: @","];
|
|
|
|
string = [string stringByReplacingString: @"\\:"
|
|
|
|
withString: @":"];
|
|
|
|
string = [string stringByReplacingString: @"\\;"
|
|
|
|
withString: @";"];
|
|
|
|
string = [string stringByReplacingString: @"\\n"
|
|
|
|
withString: @"\n"];
|
|
|
|
string = [string stringByReplacingString: @"\\r"
|
|
|
|
withString: @"\r"];
|
|
|
|
string = [string stringByReplacingString: @"\\\\"
|
|
|
|
withString: @"\\"];
|
2008-08-18 17:19:19 +02:00
|
|
|
string = [string stringByReplacingString: @"\\N" // Outlook lameness
|
|
|
|
withString: @"\n"];
|
2007-01-31 18:11:29 +01:00
|
|
|
return string;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSTimeInterval) durationAsTimeInterval
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
eg: DURATION:PT1H
|
|
|
|
P - "period"
|
|
|
|
P2H30M - "2 hours 30 minutes"
|
|
|
|
|
|
|
|
dur-value = (["+"] / "-") "P" (dur-date / dur-time / dur-week)
|
|
|
|
|
|
|
|
dur-date = dur-day [dur-time]
|
|
|
|
dur-time = "T" (dur-hour / dur-minute / dur-second)
|
|
|
|
dur-week = 1*DIGIT "W"
|
|
|
|
dur-hour = 1*DIGIT "H" [dur-minute]
|
|
|
|
dur-minute = 1*DIGIT "M" [dur-second]
|
|
|
|
dur-second = 1*DIGIT "S"
|
|
|
|
dur-day = 1*DIGIT "D"
|
|
|
|
*/
|
|
|
|
unsigned i, len;
|
|
|
|
NSTimeInterval ti;
|
2009-04-21 16:34:22 +02:00
|
|
|
BOOL isNegative, isTime;
|
2007-01-31 18:11:29 +01:00
|
|
|
int val;
|
2008-08-10 19:14:44 +02:00
|
|
|
unichar c;
|
2009-04-21 16:34:22 +02:00
|
|
|
|
2007-01-31 18:11:29 +01:00
|
|
|
ti = 0.0;
|
2009-04-21 16:34:22 +02:00
|
|
|
i = 0;
|
2008-08-10 19:14:44 +02:00
|
|
|
|
2009-04-21 16:34:22 +02:00
|
|
|
c = [self characterAtIndex: i];
|
|
|
|
if (c == '-')
|
|
|
|
{
|
|
|
|
isNegative = YES;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
isNegative = NO;
|
|
|
|
}
|
|
|
|
|
|
|
|
c = [self characterAtIndex: i];
|
|
|
|
if (c == 'P')
|
2008-08-10 19:14:44 +02:00
|
|
|
{
|
2007-01-31 18:11:29 +01:00
|
|
|
val = 0;
|
2008-08-10 19:14:44 +02:00
|
|
|
|
|
|
|
len = [self length];
|
|
|
|
isTime = NO;
|
|
|
|
|
2009-04-21 16:34:22 +02:00
|
|
|
for (i++; i < len; i++)
|
2008-08-10 19:14:44 +02:00
|
|
|
{
|
|
|
|
c = [self characterAtIndex: i];
|
|
|
|
if (c == 't' || c == 'T')
|
|
|
|
{
|
|
|
|
isTime = YES;
|
|
|
|
val = 0;
|
|
|
|
}
|
|
|
|
else if (isdigit (c))
|
|
|
|
val = (val * 10) + (c - 48);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switch (c)
|
|
|
|
{
|
|
|
|
case 'W': /* week */
|
|
|
|
ti += (val * 7 * 24 * 60 * 60);
|
|
|
|
break;
|
|
|
|
case 'D': /* day */
|
|
|
|
ti += (val * 24 * 60 * 60);
|
|
|
|
break;
|
|
|
|
case 'H': /* hour */
|
|
|
|
ti += (val * 60 * 60);
|
|
|
|
break;
|
|
|
|
case 'M': /* min */
|
|
|
|
ti += (val * 60);
|
|
|
|
break;
|
|
|
|
case 'S': /* sec */
|
|
|
|
ti += val;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
[self logWithFormat: @"cannot process duration unit: '%c'", c];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
val = 0;
|
|
|
|
}
|
|
|
|
}
|
2007-01-31 18:11:29 +01:00
|
|
|
}
|
2008-08-10 19:14:44 +02:00
|
|
|
else
|
|
|
|
NSLog(@"Cannot parse iCal duration value: '%@'", self);
|
|
|
|
|
2009-04-21 16:34:22 +02:00
|
|
|
if (isNegative)
|
|
|
|
ti = -ti;
|
|
|
|
|
2007-01-31 18:11:29 +01:00
|
|
|
return ti;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSCalendarDate *) asCalendarDate
|
|
|
|
{
|
|
|
|
NSRange cursor;
|
|
|
|
NSCalendarDate *date;
|
|
|
|
NSTimeZone *utc;
|
2007-06-07 18:20:01 +02:00
|
|
|
unsigned int length;
|
2007-01-31 18:11:29 +01:00
|
|
|
int year, month, day, hour, minute, second;
|
|
|
|
|
2007-06-07 18:20:01 +02:00
|
|
|
length = [self length];
|
|
|
|
if (length > 7)
|
2007-01-31 18:11:29 +01:00
|
|
|
{
|
|
|
|
cursor = NSMakeRange(0, 4);
|
|
|
|
year = [[self substringWithRange: cursor] intValue];
|
|
|
|
cursor.location += cursor.length;
|
|
|
|
cursor.length = 2;
|
2010-09-28 18:07:58 +02:00
|
|
|
if ([[self substringWithRange: cursor] hasPrefix: @"-"])
|
|
|
|
cursor.location += 1;
|
2007-01-31 18:11:29 +01:00
|
|
|
month = [[self substringWithRange: cursor] intValue];
|
|
|
|
cursor.location += cursor.length;
|
2010-09-28 18:07:58 +02:00
|
|
|
if ([[self substringWithRange: cursor] hasPrefix: @"-"])
|
|
|
|
cursor.location += 1;
|
2007-01-31 18:11:29 +01:00
|
|
|
day = [[self substringWithRange: cursor] intValue];
|
|
|
|
|
2007-06-07 18:20:01 +02:00
|
|
|
if (length > 14)
|
|
|
|
{
|
|
|
|
cursor.location += cursor.length + 1;
|
|
|
|
hour = [[self substringWithRange: cursor] intValue];
|
|
|
|
cursor.location += cursor.length;
|
|
|
|
minute = [[self substringWithRange: cursor] intValue];
|
|
|
|
cursor.location += cursor.length;
|
|
|
|
second = [[self substringWithRange: cursor] intValue];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
hour = 0;
|
|
|
|
minute = 0;
|
|
|
|
second = 0;
|
|
|
|
}
|
2007-01-31 18:11:29 +01:00
|
|
|
|
|
|
|
utc = [NSTimeZone timeZoneWithAbbreviation: @"GMT"];
|
|
|
|
date = [NSCalendarDate dateWithYear: year month: month
|
|
|
|
day: day hour: hour minute: minute
|
|
|
|
second: second
|
|
|
|
timeZone: utc];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
date = nil;
|
|
|
|
|
|
|
|
return date;
|
|
|
|
}
|
|
|
|
|
2007-06-07 18:20:01 +02:00
|
|
|
- (BOOL) isAllDayDate
|
|
|
|
{
|
2007-06-07 20:05:45 +02:00
|
|
|
return ([self length] == 8);
|
2007-06-07 18:20:01 +02:00
|
|
|
}
|
|
|
|
|
2007-12-20 22:57:49 +01:00
|
|
|
- (NSArray *) componentsWithSafeSeparator: (unichar) separator
|
2007-01-31 18:11:29 +01:00
|
|
|
{
|
2007-12-20 22:57:49 +01:00
|
|
|
NSMutableArray *components;
|
|
|
|
NSRange currentRange;
|
|
|
|
unichar *stringBuffer;
|
|
|
|
unichar currentChar;
|
|
|
|
unsigned int count, length;
|
|
|
|
BOOL escaped;
|
2007-01-31 18:11:29 +01:00
|
|
|
|
2007-12-20 22:57:49 +01:00
|
|
|
components = [NSMutableArray array];
|
|
|
|
|
|
|
|
length = [self length];
|
2009-06-04 01:06:52 +02:00
|
|
|
stringBuffer = NSZoneMalloc (NULL, sizeof (unichar) * length);
|
2007-12-20 22:57:49 +01:00
|
|
|
[self getCharacters: stringBuffer];
|
2007-01-31 18:11:29 +01:00
|
|
|
|
2007-12-20 22:57:49 +01:00
|
|
|
currentRange = NSMakeRange(0, 0);
|
|
|
|
escaped = NO;
|
|
|
|
count = 0;
|
|
|
|
while (count < length)
|
2007-01-31 18:11:29 +01:00
|
|
|
{
|
2007-12-20 22:57:49 +01:00
|
|
|
if (escaped)
|
|
|
|
currentRange.length++;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
currentChar = *(stringBuffer + count);
|
|
|
|
if (currentChar == '\\')
|
|
|
|
escaped = YES;
|
|
|
|
else if (currentChar == separator)
|
|
|
|
{
|
|
|
|
[components
|
|
|
|
addObject: [self substringWithRange: currentRange]];
|
|
|
|
currentRange = NSMakeRange (count + 1, 0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
currentRange.length++;
|
|
|
|
}
|
|
|
|
count++;
|
2007-01-31 18:11:29 +01:00
|
|
|
}
|
2007-12-20 22:57:49 +01:00
|
|
|
[components
|
|
|
|
addObject: [self substringWithRange: currentRange]];
|
2007-01-31 18:11:29 +01:00
|
|
|
|
2009-06-04 01:06:52 +02:00
|
|
|
NSZoneFree (NULL, stringBuffer);
|
2007-12-20 22:57:49 +01:00
|
|
|
|
|
|
|
return components;
|
2007-01-31 18:11:29 +01:00
|
|
|
}
|
|
|
|
|
2009-09-10 20:31:20 +02:00
|
|
|
- (NSString *) rfc822Email
|
|
|
|
{
|
|
|
|
unsigned idx;
|
|
|
|
|
|
|
|
idx = NSMaxRange([self rangeOfString:@":"]);
|
|
|
|
|
|
|
|
if ((idx > 0) && ([self length] > idx))
|
|
|
|
return [self substringFromIndex: idx];
|
|
|
|
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-01-31 18:11:29 +01:00
|
|
|
@end
|