Monotone-Parent: 2b628a62ac49757d2bbeda1275fc38d69079752a

Monotone-Revision: 59d4ff7e6c2fe24e74adbe4891af30ece4f5e858

Monotone-Author: wsourdeau@inverse.ca
Monotone-Date: 2011-11-14T03:26:50
Monotone-Branch: ca.inverse.sogo
maint-2.0.2
Wolfgang Sourdeau 2011-11-14 03:26:50 +00:00
parent 97dcdcb97a
commit a137e1679e
55 changed files with 1250 additions and 1043 deletions

View File

@ -1,3 +1,16 @@
2011-11-13 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* OpenChange/MAPIStoreContactsMessage.m (-getPrBody:inMemCtx:):
same as below.
* OpenChange/MAPIStoreAppointmentWrapper.m (-getPrBody:inMemCtx:):
removed parsing hack since things are now done properly from
NGCards.
* Tests/Unit/TestVersit.m (-test_rendering, -test_parsing):
adapted to new NGCards data structure and improved to test further
important use cases.
2011-11-10 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* Tests/Unit/TestVersit.m: new test module for versit parsing and

View File

@ -39,27 +39,19 @@
{
NSMutableDictionary *fields;
NSArray *values;
CardElement *adr;
CardElement *element;
NSString *value;
unsigned int max;
fields = [NSMutableDictionary dictionaryWithCapacity: 16];
value = [vCard fn];
if (value)
[fields setObject: value forKey: @"c_cn"];
values = [vCard n];
if (values)
{
max = [values count];
if (max > 0)
{
[fields setObject: [values objectAtIndex: 0] forKey: @"c_sn"];
if (max > 1)
[fields setObject: [values objectAtIndex: 1]
forKey: @"c_givenName"];
}
}
element = [vCard n];
[fields setObject: [element flattenedValueAtIndex: 0 forKey: @""]
forKey: @"c_sn"];
[fields setObject: [element flattenedValueAtIndex: 1 forKey: @""]
forKey: @"c_givenName"];
value = [vCard preferredTel];
if (value)
[fields setObject: value forKey: @"c_telephoneNumber"];
@ -67,18 +59,17 @@
if (![value isNotNull])
value = @"";
[fields setObject: value forKey: @"c_mail"];
values = [vCard org];
max = [values count];
if (max > 0)
{
[fields setObject: [values objectAtIndex: 0] forKey: @"c_o"];
if (max > 1)
[fields setObject: [values objectAtIndex: 1] forKey: @"c_ou"];
}
adr = [vCard preferredAdr];
if (adr)
[fields setObject: [adr value: 3] forKey: @"c_l"];
value = [[vCard uniqueChildWithTag: @"X-AIM"] value: 0];
element = [vCard org];
[fields setObject: [element flattenedValueAtIndex: 0 forKey: @""]
forKey: @"c_o"];
[fields setObject: [element flattenedValueAtIndex: 1 forKey: @""]
forKey: @"c_ou"];
element = [vCard preferredAdr];
if (element && ![element isVoid])
[fields setObject: [element flattenedValueAtIndex: 3
forKey: @""]
forKey: @"c_l"];
value = [[vCard uniqueChildWithTag: @"X-AIM"] flattenedValuesForKey: @""];
[fields setObject: value forKey: @"c_screenname"];
values = [[vCard categories] trimmedComponents];
if ([values count] > 0)

View File

@ -1026,17 +1026,11 @@ static NSCharacterSet *hexCharacterSet = nil;
{
int rc = MAPISTORE_SUCCESS;
NSString *stringValue;
NSArray *values;
/* FIXME: there is a confusion in NGCards around "comment" and "description" */
stringValue = [event comment];
if ([stringValue length] > 0)
{
/* FIXME: this is a temporary hack: we unescape things although NGVCards
should already have done it at this stage... */
values = [stringValue asCardAttributeValues];
*data = [[values objectAtIndex: 0] asUnicodeInMemCtx: memCtx];
}
*data = [stringValue asUnicodeInMemCtx: memCtx];
else
rc = MAPISTORE_ERR_NOT_FOUND;
@ -1411,7 +1405,8 @@ _fillAppointmentRecurrencePattern (struct AppointmentRecurrencePattern *arp,
{
startDate = [event startDate];
relation = [[trigger relationType] lowercaseString];
interval = [[trigger value] durationAsTimeInterval];
interval = [[trigger flattenedValuesForKey: @""]
durationAsTimeInterval];
if ([relation isEqualToString: @"end"])
relationDate = [event endDate];
else

View File

@ -607,7 +607,9 @@
[alarm setAction: @"DISPLAY"];
trigger = [iCalTrigger elementWithTag: @"trigger"];
[trigger setValueType: @"DURATION"];
[trigger setValue: [NSString stringWithFormat: @"-PT%@M", delta]];
[trigger
setSingleValue: [NSString stringWithFormat: @"-PT%@M", delta]
forKey: @""];
[alarm setTrigger: trigger];
[newEvent addToAlarms: alarm];
[alarm release];

View File

@ -142,7 +142,8 @@ extern NSTimeZone *utcTZ;
inMemCtx: (TALLOC_CTX *) memCtx
{
if (!photoData)
ASSIGN (photoData, [[photo value: 0] dataByDecodingBase64]);
ASSIGN (photoData,
[[photo flattenedValuesForKey: @""] dataByDecodingBase64]);
*data = [photoData asBinaryInMemCtx: memCtx];
@ -153,7 +154,8 @@ extern NSTimeZone *utcTZ;
inMemCtx: (TALLOC_CTX *) memCtx
{
if (!photoData)
ASSIGN (photoData, [[photo value: 0] dataByDecodingBase64]);
ASSIGN (photoData,
[[photo flattenedValuesForKey: @""] dataByDecodingBase64]);
*data = MAPILongValue (memCtx, [photoData length]);

View File

@ -149,18 +149,11 @@
- (int) getPrCompanyName: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
NSArray *values;
NSString *stringValue;
CardElement *org;
values = [[sogoObject vCard] org];
stringValue = nil;
if ([values count] > 0)
stringValue = [values objectAtIndex: 0];
else
stringValue = @"";
*data = [stringValue asUnicodeInMemCtx: memCtx];
org = [[sogoObject vCard] org];
*data = [[org flattenedValueAtIndex: 0 forKey: @""]
asUnicodeInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
}
@ -168,18 +161,11 @@
- (int) getPrDepartmentName: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
NSArray *values;
NSString *stringValue;
CardElement *org;
values = [[sogoObject vCard] org];
stringValue = nil;
if ([values count] > 1)
stringValue = [values objectAtIndex: 1];
else
stringValue = @"";
*data = [stringValue asUnicodeInMemCtx: memCtx];
org = [[sogoObject vCard] org];
*data = [[org flattenedValueAtIndex: 1 forKey: @""]
asUnicodeInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
}
@ -314,7 +300,7 @@
max = [emails count];
for (count = 0; !stringValue && count < max; count++)
{
email = [[emails objectAtIndex: count] value: 0];
email = [[emails objectAtIndex: count] flattenedValuesForKey: @""];
if ([email caseInsensitiveCompare: [card preferredEMail]] != NSOrderedSame)
stringValue = email;
@ -339,16 +325,10 @@
{
int rc = MAPISTORE_SUCCESS;
NSString *stringValue;
NSArray *values;
stringValue = [[sogoObject vCard] note];
if ([stringValue length] > 0)
{
/* FIXME: this is a temporary hack: we unescape things although NGVCards
should already have done it at this stage... */
values = [stringValue asCardAttributeValues];
*data = [[values objectAtIndex: 0] asUnicodeInMemCtx: memCtx];
}
*data = [stringValue asUnicodeInMemCtx: memCtx];
else
rc = MAPISTORE_ERR_NOT_FOUND;
@ -380,7 +360,7 @@
ce = [elements objectAtIndex: count];
if (!aTypeToExclude
|| ![ce hasAttribute: @"type" havingValue: aTypeToExclude])
stringValue = [ce value: pos];
stringValue = [ce flattenedValueAtIndex: pos forKey: @""];
}
if (!stringValue)
@ -471,7 +451,7 @@
NSString *stringValue;
stringValue = [[[sogoObject vCard] uniqueChildWithTag: @"x-aim"]
value: 0];
flattenedValuesForKey: @""];
if (!stringValue)
stringValue = @"";
*data = [stringValue asUnicodeInMemCtx: memCtx];
@ -705,7 +685,9 @@
{
NSString *stringValue;
stringValue = [[[sogoObject vCard] firstChildWithTag: @"n"] value: 0];
stringValue = [[[sogoObject vCard] firstChildWithTag: @"n"]
flattenedValueAtIndex: 0
forKey: @""];
*data = [stringValue asUnicodeInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
@ -716,7 +698,9 @@
{
NSString *stringValue;
stringValue = [[[sogoObject vCard] firstChildWithTag: @"n"] value: 1];
stringValue = [[[sogoObject vCard] firstChildWithTag: @"n"]
flattenedValueAtIndex: 1
forKey: @""];
*data = [stringValue asUnicodeInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
@ -727,7 +711,9 @@
{
NSString *stringValue;
stringValue = [[[sogoObject vCard] firstChildWithTag: @"n"] value: 2];
stringValue = [[[sogoObject vCard] firstChildWithTag: @"n"]
flattenedValueAtIndex: 2
forKey: @""];
*data = [stringValue asUnicodeInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
@ -738,7 +724,9 @@
{
NSString *stringValue;
stringValue = [[[sogoObject vCard] firstChildWithTag: @"n"] value: 3];
stringValue = [[[sogoObject vCard] firstChildWithTag: @"n"]
flattenedValueAtIndex: 3
forKey: @""];
*data = [stringValue asUnicodeInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
@ -749,7 +737,9 @@
{
NSString *stringValue;
stringValue = [[[sogoObject vCard] firstChildWithTag: @"n"] value: 4];
stringValue = [[[sogoObject vCard] firstChildWithTag: @"n"]
flattenedValueAtIndex: 4
forKey: @""];
*data = [stringValue asUnicodeInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
@ -844,9 +834,9 @@
to: photoType];
[photo setValue: 0 ofAttribute: @"encoding"
to: @"b"];
[photo setValue: 0
to: [content stringByReplacingString: @"\n"
withString: @""]];
[photo setSingleValue: [content stringByReplacingString: @"\n"
withString: @""]
atIndex: 0 forKey: @""];
}
}
}
@ -893,7 +883,7 @@
if (value)
{
if ([elements count] > 0)
[[elements objectAtIndex: 0] setValue: 0 to: value];
[[elements objectAtIndex: 0] setSingleValue: value forKey: @""];
else
[newCard addEmail: value
types: [NSArray arrayWithObject: @"pref"]];
@ -902,7 +892,7 @@
if (value)
{
if ([elements count] > 1)
[[elements objectAtIndex: 1] setValue: 0 to: value];
[[elements objectAtIndex: 1] setSingleValue: value forKey: @""];
else
[newCard addEmail: value types: nil];
}
@ -910,7 +900,7 @@
if (value)
{
if ([elements count] > 2)
[[elements objectAtIndex: 2] setValue: 0 to: value];
[[elements objectAtIndex: 2] setSingleValue: value forKey: @""];
else
[newCard addEmail: value types: nil];
}
@ -950,7 +940,7 @@
[element addAttribute: @"type"
value: @"pref"];
}
[element setValue: 0 to: value];
[element setSingleValue: value forKey: @""];
}
elements = [newCard childrenWithTag: @"adr"
@ -968,22 +958,22 @@
[element addAttribute: @"type" value: @"pref"];
value = [properties objectForKey: MAPIPropertyKey(PidLidWorkAddressPostOfficeBox)];
if (value)
[element setValue: 0 to: value];
[element setSingleValue: value atIndex: 0 forKey: @""];
value = [properties objectForKey: MAPIPropertyKey(PidLidWorkAddressStreet)];
if (value)
[element setValue: 2 to: value];
[element setSingleValue: value atIndex: 2 forKey: @""];
value = [properties objectForKey: MAPIPropertyKey(PidLidWorkAddressCity)];
if (value)
[element setValue: 3 to: value];
[element setSingleValue: value atIndex: 3 forKey: @""];
value = [properties objectForKey: MAPIPropertyKey(PidLidWorkAddressState)];
if (value)
[element setValue: 4 to: value];
[element setSingleValue: value atIndex: 4 forKey: @""];
value = [properties objectForKey: MAPIPropertyKey(PidLidWorkAddressPostalCode)];
if (value)
[element setValue: 5 to: value];
[element setSingleValue: value atIndex: 5 forKey: @""];
value = [properties objectForKey: MAPIPropertyKey(PidLidWorkAddressCountry)];
if (value)
[element setValue: 6 to: value];
[element setSingleValue: value atIndex: 6 forKey: @""];
//
// home postal addresses handling
@ -1009,7 +999,7 @@
[element addAttribute: @"type"
value: @"pref"];
}
[element setValue: 0 to: value];
[element setSingleValue: value forKey: @""];
}
elements = [newCard childrenWithTag: @"adr"
@ -1028,22 +1018,22 @@
value = [properties objectForKey: MAPIPropertyKey(PR_HOME_ADDRESS_POST_OFFICE_BOX_UNICODE)];
if (value)
[element setValue: 0 to: value];
[element setSingleValue: value atIndex: 0 forKey: @""];
value = [properties objectForKey: MAPIPropertyKey( PR_HOME_ADDRESS_STREET_UNICODE)];
if (value)
[element setValue: 2 to: value];
[element setSingleValue: value atIndex: 2 forKey: @""];
value = [properties objectForKey: MAPIPropertyKey(PR_HOME_ADDRESS_CITY_UNICODE)];
if (value)
[element setValue: 3 to: value];
[element setSingleValue: value atIndex: 3 forKey: @""];
value = [properties objectForKey: MAPIPropertyKey(PR_HOME_ADDRESS_STATE_OR_PROVINCE_UNICODE)];
if (value)
[element setValue: 4 to: value];
[element setSingleValue: value atIndex: 4 forKey: @""];
value = [properties objectForKey: MAPIPropertyKey(PR_HOME_ADDRESS_POSTAL_CODE_UNICODE)];
if (value)
[element setValue: 5 to: value];
[element setSingleValue: value atIndex: 5 forKey: @""];
value = [properties objectForKey: MAPIPropertyKey(PR_HOME_ADDRESS_COUNTRY_UNICODE)];
if (value)
[element setValue: 6 to: value];
[element setSingleValue: value atIndex: 6 forKey: @""];
//
@ -1052,27 +1042,27 @@
element = [self _elementWithTag: @"tel" ofType: @"work" forCard: newCard];
value = [properties objectForKey: MAPIPropertyKey(PR_OFFICE_TELEPHONE_NUMBER_UNICODE)];
if (value)
[element setValue: 0 to: value];
[element setSingleValue: value forKey: @""];
element = [self _elementWithTag: @"tel" ofType: @"home" forCard: newCard];
value = [properties objectForKey: MAPIPropertyKey(PR_HOME_TELEPHONE_NUMBER_UNICODE)];
if (value)
[element setValue: 0 to: value];
[element setSingleValue: value forKey: @""];
element = [self _elementWithTag: @"tel" ofType: @"fax" forCard: newCard];
value = [properties objectForKey: MAPIPropertyKey(PR_BUSINESS_FAX_NUMBER_UNICODE)];
if (value)
[element setValue: 0 to: value];
[element setSingleValue: value forKey: @""];
element = [self _elementWithTag: @"tel" ofType: @"pager" forCard: newCard];
value = [properties objectForKey: MAPIPropertyKey(PR_PAGER_TELEPHONE_NUMBER_UNICODE)];
if (value)
[element setValue: 0 to: value];
[element setSingleValue: value forKey: @""];
element = [self _elementWithTag: @"tel" ofType: @"cell" forCard: newCard];
value = [properties objectForKey: MAPIPropertyKey(PR_MOBILE_TELEPHONE_NUMBER_UNICODE)];
if (value)
[element setValue: 0 to: value];
[element setSingleValue: value forKey: @""];
//
@ -1100,15 +1090,14 @@
if (value)
{
[[self _elementWithTag: @"url" ofType: @"work" forCard: newCard]
setValue: 0 to: value];
setSingleValue: value forKey: @""];
}
value = [properties objectForKey: MAPIPropertyKey(PidLidInstantMessagingAddress)];
if (value)
{
[[newCard uniqueChildWithTag: @"x-aim"]
setValue: 0
to: value];
setSingleValue: value forKey: @""];
}
value = [properties objectForKey: MAPIPropertyKey(PR_BIRTHDAY)];

View File

@ -96,7 +96,7 @@
[rule setFrequency: iCalRecurrenceFrequenceYearly];
[rule setRepeatInterval: rp->Period / 12];
month = [NSString stringWithFormat: @"%d", [startDate monthOfYear]];
[rule setNamedValue: @"bymonth" to: month];
[rule setSingleValue: month forKey: @"bymonth"];
}
else
[self errorWithFormat:
@ -116,7 +116,7 @@
else
monthDay = [NSString stringWithFormat: @"%d",
rp->PatternTypeSpecific.MonthRecurrencePattern.N];
[rule setNamedValue: @"bymonthday" to: monthDay];
[rule setSingleValue: monthDay forKey: @"bymonthday"];
}
else if ((rp->PatternTypeSpecific.MonthRecurrencePattern.WeekRecurrencePattern
== 0x3e) /* Nth week day */
@ -139,8 +139,9 @@
else
bySetPos = rp->PatternTypeSpecific.MonthRecurrencePattern.N;
[rule setNamedValue: @"bysetpos"
to: [NSString stringWithFormat: @"%d", bySetPos]];
[rule
setSingleValue: [NSString stringWithFormat: @"%d", bySetPos]
forKey: @"bysetpos"];
}
else
{
@ -167,9 +168,10 @@
|| (rp->PatternType & 4) == 4)
{
/* MonthEnd, HjMonth and HjMonthEnd */
[rule setNamedValue: @"bymonthday"
to: [NSString stringWithFormat: @"%d",
rp->PatternTypeSpecific.Day]];
[rule
setSingleValue: [NSString stringWithFormat: @"%d",
rp->PatternTypeSpecific.Day]
forKey: @"bymonthday"];
}
else
[self errorWithFormat: @"invalid value for PatternType: %.4x",
@ -348,7 +350,7 @@
if (mask)
{
rp->PatternTypeSpecific.MonthRecurrencePattern.WeekRecurrencePattern = mask;
bySetPos = [self namedValue: @"bysetpos"];
bySetPos = [self flattenedValuesForKey: @"bysetpos"];
if ([bySetPos length])
rp->PatternTypeSpecific.MonthRecurrencePattern.N
= ([bySetPos hasPrefix: @"-"]

View File

@ -36,7 +36,7 @@
@interface CardElement : NSObject <NSCopying, NSMutableCopying>
{
NSString *tag;
NSMutableArray *values;
NSMutableDictionary *values;
NSMutableDictionary *attributes;
NSString *group;
CardGroup *parent;
@ -51,31 +51,44 @@
singleType: (NSString *) aType
value: (NSString *) aValue;
+ (id) elementWithTag: (NSString *) aTag
attributes: (NSDictionary *) someAttributes
values: (NSArray *) someValues;
- (void) setParent: (CardGroup *) aParent;
- (id) parent;
- (void) setTag: (NSString *) aTag;
- (NSString *) tag;
- (void) setGroup: (NSString *) aGroup;
- (NSString *) group;
- (void) addValue: (NSString *) aValue;
- (void) addValues: (NSArray *) someValues;
- (BOOL) isVoid;
- (void) setValue: (unsigned int) anInt
to: (NSString *) aValue;
- (NSString *) value: (unsigned int) anInt;
- (void) setValues: (NSMutableDictionary *) newValues;
- (NSMutableDictionary *) values;
- (void) setNamedValue: (NSString *) aValueName
to: (NSString *) aValue;
- (NSString *) namedValue: (NSString *) aValueName;
/* ELEM:...;value1,value2,...;... */
- (void) setValues: (NSMutableArray *) newValues
atIndex: (NSUInteger) idx
forKey: (NSString *) key;
- (void) setCommaSeparatedValues: (NSArray *) values;
/* ELEM:...;value;... */
- (void) setSingleValue: (NSString *) newValue
atIndex: (NSUInteger) idx
forKey: (NSString *) key;
/* ELEM:value */
- (void) setSingleValue: (NSString *) newValue
forKey: (NSString *) key;
- (NSMutableArray *) valuesForKey: (NSString *) key;
- (NSMutableArray *) valuesAtIndex: (NSUInteger) idx
forKey: (NSString *) key;
/* This joins all subvalues with "," and ordered values with ";". Handy for
retrieving data from clients which don't escape their data properly. */
- (NSString *) flattenedValuesForKey: (NSString *) key;
- (NSString *) flattenedValueAtIndex: (NSUInteger) idx
forKey: (NSString *) key;
/* attribute values */
- (void) setValue: (unsigned int) anInt
ofAttribute: (NSString *) anAttribute
to: (NSString *) aValue;
@ -87,17 +100,11 @@
- (void) addAttributes: (NSDictionary *) someAttributes;
- (void) removeValue: (NSString *) aValue
fromAttribute: (NSString *) anAttribute;
- (void) addType: (NSString *) aType;
- (NSString *) tag;
- (void) setValues: (NSArray *) newValues;
- (NSArray *) values;
- (NSDictionary *) attributes;
- (NSMutableDictionary *) attributes;
- (BOOL) hasAttribute: (NSString *) aType
havingValue: (NSString *) aValue;
- (BOOL) isVoid;
- (void) addType: (NSString *) aType;
- (NSString *) versitString;

View File

@ -56,7 +56,7 @@
id newElement;
newElement = [self elementWithTag: aTag];
[newElement addValue: aValue];
[newElement setSingleValue: aValue forKey: @""];
return newElement;
}
@ -74,21 +74,6 @@
return newElement;
}
+ (id) elementWithTag: (NSString *) aTag
attributes: (NSDictionary *) someAttributes
values: (NSArray *) someValues
{
id newElement;
newElement = [self new];
[newElement autorelease];
[newElement setTag: aTag];
[newElement addAttributes: someAttributes];
[newElement addValues: someValues];
return newElement;
}
- (id) init
{
if ((self = [super init]))
@ -96,7 +81,7 @@
parent = nil;
tag = nil;
group = nil;
values = [NSMutableArray new];
values = [NSMutableDictionary new];
attributes = [NSMutableDictionary new];
}
@ -142,16 +127,172 @@
return group;
}
- (void) addValue: (NSString *) aValue
/* values */
- (void) setValues: (NSMutableDictionary *) newValues
{
if (!aValue)
aValue = @"";
[values addObject: aValue];
ASSIGN (values, newValues);
}
- (void) addValues: (NSArray *) someValues
- (NSMutableDictionary *) values
{
[values addObjectsFromArray: someValues];
return values;
}
- (void) setValues: (NSMutableArray *) newValues
atIndex: (NSUInteger) idx
forKey: (NSString *) key
{
NSMutableArray *oldValues, *subValues;
oldValues = [self valuesForKey: key];
if (!oldValues)
{
oldValues = [NSMutableArray new];
[values setObject: oldValues forKey: key];
[oldValues release];
}
while ([oldValues count] < (idx + 1))
{
subValues = [NSMutableArray new];
[oldValues addObject: subValues];
[subValues release];
}
if (!newValues)
newValues = [NSMutableArray array];
[oldValues replaceObjectAtIndex: idx withObject: newValues];
}
- (void) setSingleValue: (NSString *) newValue
atIndex: (NSUInteger) idx
forKey: (NSString *) key
{
NSMutableArray *subValues;
if (newValue)
{
subValues = [NSMutableArray new];
[subValues addObject: newValue];
}
else
subValues = nil;
[self setValues: subValues atIndex: idx forKey: key];
[subValues release];
}
- (void) setSingleValue: (NSString *) newValue
forKey: (NSString *) key
{
[self setSingleValue: newValue
atIndex: 0 forKey: key];
}
- (NSMutableArray *) valuesForKey: (NSString *) key
{
return [values objectForKey: [key lowercaseString]];
}
- (NSMutableArray *) valuesAtIndex: (NSUInteger) idx
forKey: (NSString *) key
{
return [[self valuesForKey: key] objectAtIndex: idx];
}
- (NSString *) flattenedValueAtIndex: (NSUInteger) idx
forKey: (NSString *) key
{
NSMutableArray *orderedValues, *sValues;
NSUInteger count, max;
NSMutableString *flattenedValues;
NSString *encoding, *realValue, *value;
flattenedValues = [NSMutableString string];
orderedValues = [self valuesForKey: key];
max = [orderedValues count];
if (max > idx)
{
encoding = [[self value: 0 ofAttribute: @"encoding"]
lowercaseString];
sValues = [orderedValues objectAtIndex: idx];
max = [sValues count];
for (count = 0; count < max; count++)
{
if (count > 0)
[flattenedValues appendString: @","];
realValue = [sValues objectAtIndex: count];
if ([encoding isEqualToString: @"quoted-printable"])
value = [realValue stringByDecodingQuotedPrintable];
else if ([encoding isEqualToString: @"base64"])
value = [realValue stringByDecodingBase64];
else
{
value = realValue;
if ([encoding length] && ![encoding isEqualToString: @"8bit"])
[self logWithFormat: @"unknown encoding '%@'", encoding];
}
[flattenedValues appendString: value];
}
}
return flattenedValues;
}
- (NSString *) flattenedValuesForKey: (NSString *) key
{
NSMutableArray *orderedValues, *sValues;
NSUInteger count, max, sCount, sMax;
NSMutableString *flattenedValues;
NSString *encoding, *realValue, *value;
encoding = [[self value: 0 ofAttribute: @"encoding"]
lowercaseString];
flattenedValues = [NSMutableString string];
orderedValues = [self valuesForKey: key];
max = [orderedValues count];
for (count = 0; count < max; count++)
{
if (count > 0)
[flattenedValues appendString: @";"];
sValues = [orderedValues objectAtIndex: count];
sMax = [sValues count];
for (sCount = 0; sCount < sMax; sCount++)
{
if (sCount > 0)
[flattenedValues appendString: @","];
realValue = [sValues objectAtIndex: sCount];
if ([encoding isEqualToString: @"quoted-printable"])
value = [realValue stringByDecodingQuotedPrintable];
else if ([encoding isEqualToString: @"base64"])
value = [realValue stringByDecodingBase64];
else
{
value = realValue;
if ([encoding length] && ![encoding isEqualToString: @"8bit"])
[self logWithFormat: @"unknown encoding '%@'", encoding];
}
[flattenedValues appendString: value];
}
}
return flattenedValues;
}
/* attributes */
- (NSMutableDictionary *) attributes
{
return attributes;
}
- (void) setAttributesAsCopy: (NSMutableDictionary *) someAttributes
{
ASSIGN (attributes, someAttributes);
}
- (void) addAttribute: (NSString *) anAttribute
@ -219,26 +360,6 @@
[self addAttribute: @"type" value: aType];
}
- (void) setValues: (NSArray *) newValues
{
if (![newValues isKindOfClass: [NSMutableArray class]])
{
newValues = [newValues mutableCopy];
[newValues autorelease];
}
ASSIGN (values, newValues);
}
- (NSArray *) values
{
return values;
}
- (NSDictionary *) attributes
{
return attributes;
}
- (BOOL) hasAttribute: (NSString *) anAttribute
havingValue: (NSString *) aValue
{
@ -249,141 +370,6 @@
return (attribute && [attribute hasCaseInsensitiveString: aValue]);
}
- (void) setValue: (unsigned int) anInt
to: (NSString *) aValue
{
unsigned int count, max;
if (!aValue)
aValue = @"";
max = [values count];
for (count = max; count <= anInt; count++)
[self addValue: @""];
[values replaceObjectAtIndex: anInt withObject: aValue];
}
- (NSString *) value: (unsigned int) anInt
{
NSString *realValue, *value, *encoding;
if ([values count] <= anInt)
value = @"";
else
{
realValue = [values objectAtIndex: anInt];
encoding = [[self value: 0 ofAttribute: @"encoding"] lowercaseString];
if ([encoding length])
{
if ([encoding isEqualToString: @"quoted-printable"])
value = [realValue stringByDecodingQuotedPrintable];
else if ([encoding isEqualToString: @"base64"])
value = [realValue stringByDecodingBase64];
else
{
value = realValue;
if (![encoding isEqualToString: @"8bit"])
[self logWithFormat: @"unknown encoding '%@'", encoding];
}
}
else
value = realValue;
}
return value;
}
- (unsigned int) _namedValue: (NSString *) aValueName
{
NSString *prefix, *value;
unsigned int count, max, result;
result = NSNotFound;
prefix = [NSString stringWithFormat: @"%@=", [aValueName uppercaseString]];
max = [values count];
count = 0;
while (result == NSNotFound && count < max)
{
value = [[values objectAtIndex: count] uppercaseString];
if ([value hasPrefix: prefix])
result = count;
else
count++;
}
return result;
}
- (void) setNamedValue: (NSString *) aValueName
to: (NSString *) aValue
{
NSString *newValue;
unsigned int index;
if (!aValue)
aValue = @"";
newValue = [NSString stringWithFormat: @"%@=%@",
[aValueName uppercaseString],
aValue];
index = [self _namedValue: aValueName];
if (index == NSNotFound)
{
if ([aValue length])
[self addValue: newValue];
}
else
{
if ([aValue length])
[self setValue: index to: newValue];
else
[values removeObjectAtIndex: index];
}
}
- (NSString *) namedValue: (NSString *) aValueName
{
unsigned int index;
NSRange equalSign;
NSString *value;
index = [self _namedValue: aValueName];
if (index == NSNotFound)
value = @"";
else
{
value = [values objectAtIndex: index];
equalSign = [value rangeOfString: @"="];
if (equalSign.location != NSNotFound)
value = [value substringFromIndex: equalSign.location + 1];
}
return value;
}
- (void) setCommaSeparatedValues: (NSArray *) newValues
{
NSMutableString *newValue;
NSUInteger count, max;
NSString *currentValue;
newValue = [NSMutableString stringWithCapacity: 250];
max = [newValues count];
for (count = 0; count < max; count++)
{
currentValue = [[newValues objectAtIndex: count]
stringByReplacingString: @","
withString: @"\\,"];
if (count > 0)
[newValue appendFormat: @",%@", currentValue];
else
[newValue appendString: currentValue];
}
[self setValues: [NSArray arrayWithObject: newValue]];
}
- (void) setValue: (unsigned int) anInt
ofAttribute: (NSString *) anAttribute
to: (NSString *) aValue
@ -423,10 +409,7 @@
- (NSString *) description
{
NSArray *attrs;
NSMutableString *str;
unsigned int count, max;
NSString *attr;
str = [NSMutableString stringWithCapacity:64];
[str appendFormat:@"<%p[%@]:", self, NSStringFromClass([self class])];
@ -435,48 +418,56 @@
else
[str appendFormat: @"%@\n", tag, group];
attrs = [attributes allKeys];
max = [attrs count];
if (max > 0)
{
[str appendFormat: @"\n %d attributes: {\n", [attrs count]];
for (count = 0; count < max; count++)
{
attr = [attrs objectAtIndex: count];
[str appendFormat: @" %@: %@\n",
attr, [attributes objectForKey: attr]];
}
[str appendFormat: @"}"];
}
max = [values count];
if (max > 0)
{
[str appendFormat: @"\n %d values: {\n", [values count]];
for (count = 0; count < max; count++)
[str appendFormat: @" %@\n", [values objectAtIndex: count]];
[str appendFormat: @"}"];
}
[str appendString:@">"];
[str appendString: [self versitString]];
return str;
}
- (BOOL) isVoid
static inline BOOL
_subValuesAreVoid (NSArray *subValues)
{
BOOL result;
NSString *value;
NSEnumerator *enu;
BOOL result = YES;
NSUInteger count, max;
result = YES;
enu = [values objectEnumerator];
value = [enu nextObject];
while (value && result)
max = [subValues count];
for (count = 0; result && count < max; count++)
result = ([[subValues objectAtIndex: count] length] == 0);
return result;
}
static inline BOOL
_orderedValuesAreVoid (NSArray *orderedValues)
{
BOOL result = YES;
NSUInteger count, max;
result = YES;
max = [orderedValues count];
for (count = 0; result && count < max; count++)
result = _subValuesAreVoid ([orderedValues objectAtIndex: count]);
return result;
}
- (BOOL) isVoid
{
BOOL result = YES;
NSArray *keys;
NSMutableArray *orderedValues;
NSUInteger count, max;
result = YES;
keys = [values allKeys];
max = [keys count];
for (count = 0; result && count < max; count++)
{
result = ([value length] == 0);
value = [enu nextObject];
orderedValues = [values objectForKey: [keys objectAtIndex: count]];
result = _orderedValuesAreVoid (orderedValues);
}
return result;
@ -523,11 +514,6 @@
return newElement;
}
- (void) setAttributesAsCopy: (NSMutableDictionary *) someAttributes
{
ASSIGN (attributes, someAttributes);
}
- (CardGroup *) searchParentOfClass: (Class) parentClass
{
CardGroup *current;
@ -594,7 +580,7 @@
newGroup = [group copyWithZone: aZone];
[new setGroup: newGroup];
[newGroup release];
[new setValues: [self deepCopyOfArray: values withZone: aZone]];
[new setValues: [self deepCopyOfDictionary: values withZone: aZone]];
[new setAttributesAsCopy: [self deepCopyOfDictionary: attributes
withZone: aZone]];
@ -604,22 +590,7 @@
/* NSMutableCopying */
- (id) mutableCopyWithZone: (NSZone *) aZone
{
#warning this method really is the same as "copyWithZone:"
CardElement *new;
NSString *newTag, *newGroup;
new = [[self class] new];
newTag = [tag copyWithZone: aZone];
[new setTag: newTag];
[newTag release];
newGroup = [group copyWithZone: aZone];
[new setGroup: newGroup];
[newGroup release];
[new setValues: [self deepCopyOfArray: values withZone: aZone]];
[new setAttributesAsCopy: [self deepCopyOfDictionary: attributes
withZone: aZone]];
return new;
return [self copyWithZone: aZone];
}
@end

View File

@ -281,7 +281,7 @@ static NGCardsSaxHandler *sax = nil;
havingValue: (NSString *) aValue
{
return [children cardElementsWithAttribute: anAttribute
havingValue: aValue];
havingValue: aValue];
}
- (NSArray *) childrenWithTag: (NSString *) aTag
@ -293,7 +293,7 @@ static NGCardsSaxHandler *sax = nil;
elements = [self childrenWithTag: aTag];
return [elements cardElementsWithAttribute: anAttribute
havingValue: aValue];
havingValue: aValue];
}
- (NSArray *) childrenGroupWithTag: (NSString *) aTag
@ -313,7 +313,8 @@ static NGCardsSaxHandler *sax = nil;
{
if ([element isKindOfClass: [CardGroup class]])
{
value = [[element uniqueChildWithTag: aChild] value: 0];
value = [[element uniqueChildWithTag: aChild]
flattenedValuesForKey: @""];
if ([value isEqualToString: aValue])
[elements addObject: element];
}

View File

@ -31,7 +31,7 @@
#import "CardGroup.h"
#import "NSString+NGCards.h"
#import "NSArray+NGCards.h"
#import "NSDictionary+NGCards.h"
#import "CardVersitRenderer.h"
@ -55,9 +55,8 @@
{
NSMutableString *rendering;
NSDictionary *attributes;
NSEnumerator *keys;
NSArray *values, *renderedAttrs;
NSString *key, *finalRendering, *tag;
NSMutableDictionary *values;
NSString *finalRendering, *tag;
if (![anElement isVoid])
{
@ -76,41 +75,16 @@
/* parameters */
attributes = [anElement attributes];
keys = [[attributes allKeys] objectEnumerator];
while ((key = [keys nextObject]))
if ([attributes count])
{
NSString *s;
int i, c;
renderedAttrs = [[attributes objectForKey: key] renderedForCards];
c = [renderedAttrs count];
if (c > 0)
{
[rendering appendFormat: @";%@=", [key uppercaseString]];
for (i = 0; i < c; i++)
{
s = [renderedAttrs objectAtIndex: i];
/* We MUST quote attribute values that have a ":" in them
and that not already quoted */
if ([s length] > 2 && [s rangeOfString: @":"].length &&
[s characterAtIndex: 0] != '"' && ![s hasSuffix: @"\""])
s = [NSString stringWithFormat: @"\"%@\"", s];
[rendering appendFormat: @"%@", s];
if (i+1 < c)
[rendering appendString: @","];
}
}
[rendering appendString: @";"];
[attributes versitRenderInString: rendering asAttributes: YES];
}
/* values */
values = [anElement values];
if ([values count] > 0)
[rendering appendFormat: @":%@",
[[values renderedForCards] componentsJoinedByString: @";"]];
[rendering appendString: @":"];
[values versitRenderInString: rendering asAttributes: NO];
if ([rendering length] > 0)
[rendering appendString: @"\r\n"];
@ -143,12 +117,8 @@
groupTag = [groupTag uppercaseString];
[rendering appendFormat: @"BEGIN:%@\r\n", groupTag];
children = [[aGroup children] objectEnumerator];
currentChild = [children nextObject];
while (currentChild)
{
[rendering appendString: [self render: currentChild]];
currentChild = [children nextObject];
}
while ((currentChild = [children nextObject]))
[rendering appendString: [self render: currentChild]];
[rendering appendFormat: @"END:%@\r\n", groupTag];
return rendering;

View File

@ -1,3 +1,31 @@
2011-11-13 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* iCalTrigger.m (-setValue:, value): removed useless accessors.
* iCalAttachment.m (-setValue:, value): removed useless accessors.
* iCalRecurrenceRule.m (-setRrule): now makes use of the existing
parsing algorithm and get the values from the parsed element.
* iCalEntityObject.m (-setCategories:): now take an array as
parameter.
* NSString+NGCards.m (-vCardSubvalues): new method adapted to the
new CardElement data structure, replaces
"vCardSubvaluesWithSeparator:", since we now know how to properly
separate or escape elements.
* CardElement.m (-init): "values" in now an NSMutableDictionary.
(-setValues:, -values): new primitive accessors;
(-setValues:atIndex:forKey:, -setSingleValue:atIndex:forKey:)
(setSingleValue:forKey:): new helper setters.
(-flattenedValueAtIndex:forKey:, -flattenedValues:forKey:): new
"flattened" helper getters. "Flattening" meaning here that the
first and/or second level array are merged with "," and ";", to
support clients that badly escape(d) their output for fields
taking only one value or a specific set of values.
(-valuesForKey:,-valuesAtIndex:forKey:): new helper getters
2011-11-09 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* NSString+NGCards.m (-escapedForCards): restored the escaping of

View File

@ -69,7 +69,7 @@
/* content */
- (void) startCollectingContent;
- (NSArray *) finishCollectingContent;
- (NSMutableDictionary *) finishCollectingContent;
- (void) startGroupElement: (NSString *) _localName;
- (void) endGroupElement;

View File

@ -181,7 +181,7 @@
else if ([_localName isEqualToString: @"container"])
[self endGroupElement];
else
[currentElement addValues: [self finishCollectingContent]];
[currentElement setValues: [self finishCollectingContent]];
}
/* content */
@ -197,9 +197,9 @@
vcs.collectContent = 1;
}
- (NSArray *) finishCollectingContent
- (NSMutableDictionary *) finishCollectingContent
{
NSArray *contentValues;
NSMutableDictionary *contentValues;
NSString *s;
vcs.collectContent = 0;
@ -211,7 +211,7 @@
free (content);
content = NULL;
// NSLog (@"content: '%@'", s);
contentValues = [s vCardSubvaluesWithSeparator: ';'];
contentValues = [s vCardSubvalues];
}
else
contentValues = nil;

View File

@ -117,11 +117,12 @@ typedef enum
additional: (NSString *) additional
prefixes: (NSString *) prefixes
suffixes: (NSString *) suffixes;
- (NSArray *) n;
/* returns an array of single values */
- (CardElement *) n;
- (void) setOrg: (NSString *) anOrg
units: (NSArray *) someUnits;
- (NSArray *) org;
- (CardElement *) org;
- (void) setCategories: (NSArray *) newCategories;
- (NSArray *) categories;

View File

@ -116,134 +116,134 @@
/* accessors */
- (void) setVersion: (NSString *) _version
- (void) setVersion: (NSString *) _value
{
[[self uniqueChildWithTag: @"version"] setValue: 0 to: _version];
[[self uniqueChildWithTag: @"version"] setSingleValue: _value forKey: @""];
}
- (NSString *) version
{
return [[self uniqueChildWithTag: @"version"] value: 0];
return [[self uniqueChildWithTag: @"version"] flattenedValuesForKey: @""];
}
- (void) setUid: (NSString *) _uid
- (void) setUid: (NSString *) _value
{
[[self uniqueChildWithTag: @"uid"] setValue: 0 to: _uid];
[[self uniqueChildWithTag: @"uid"] setSingleValue: _value forKey: @""];
}
- (NSString *) uid
{
return [[self uniqueChildWithTag: @"uid"] value: 0];
return [[self uniqueChildWithTag: @"uid"] flattenedValuesForKey: @""];
}
- (void) setVClass: (NSString *) _class
- (void) setVClass: (NSString *) _value
{
[[self uniqueChildWithTag: @"class"] setValue: 0 to: _class];
[[self uniqueChildWithTag: @"class"] setSingleValue: _value forKey: @""];
}
- (NSString *) vClass
{
return [[self uniqueChildWithTag: @"class"] value: 0];
return [[self uniqueChildWithTag: @"class"] flattenedValuesForKey: @""];
}
- (void) setProdID: (NSString *) _value
{
[[self uniqueChildWithTag: @"prodid"] setValue: 0 to: _value];
[[self uniqueChildWithTag: @"prodid"] setSingleValue: _value forKey: @""];
}
- (NSString *) prodID
{
return [[self uniqueChildWithTag: @"prodid"] value: 0];
return [[self uniqueChildWithTag: @"prodid"] flattenedValuesForKey: @""];
}
- (void) setProfile: (NSString *) _value
{
[[self uniqueChildWithTag: @"profile"] setValue: 0 to: _value];
[[self uniqueChildWithTag: @"profile"] setSingleValue: _value forKey: @""];
}
- (NSString *) profile
{
return [[self uniqueChildWithTag: @"profile"] value: 0];
return [[self uniqueChildWithTag: @"profile"] flattenedValuesForKey: @""];
}
- (void) setSource: (NSString *) _value
{
[[self uniqueChildWithTag: @"source"] setValue: 0 to: _value];
[[self uniqueChildWithTag: @"source"] setSingleValue: _value forKey: @""];
}
- (NSString *) source
{
return [[self uniqueChildWithTag: @"source"] value: 0];
return [[self uniqueChildWithTag: @"source"] flattenedValuesForKey: @""];
}
- (void) setFn: (NSString *) _value
{
[[self uniqueChildWithTag: @"fn"] setValue: 0 to: _value];
[[self uniqueChildWithTag: @"fn"] setSingleValue: _value forKey: @""];
}
- (NSString *) fn
{
return [[self uniqueChildWithTag: @"fn"] value: 0];
return [[self uniqueChildWithTag: @"fn"] flattenedValuesForKey: @""];
}
- (void) setRole: (NSString *) _value
{
[[self uniqueChildWithTag: @"role"] setValue: 0 to: _value];
[[self uniqueChildWithTag: @"role"] setSingleValue: _value forKey: @""];
}
- (NSString *) role
{
return [[self uniqueChildWithTag: @"role"] value: 0];
return [[self uniqueChildWithTag: @"role"] flattenedValuesForKey: @""];
}
- (void) setTitle: (NSString *) _title
- (void) setTitle: (NSString *) _value
{
[[self uniqueChildWithTag: @"title"] setValue: 0 to: _title];
[[self uniqueChildWithTag: @"title"] setSingleValue: _value forKey: @""];
}
- (NSString *) title
{
return [[self uniqueChildWithTag: @"title"] value: 0];
return [[self uniqueChildWithTag: @"title"] flattenedValuesForKey: @""];
}
- (void) setBday: (NSString *) _value
{
[[self uniqueChildWithTag: @"bday"] setValue: 0 to: _value];
[[self uniqueChildWithTag: @"bday"] setSingleValue: _value forKey: @""];
}
- (NSString *) bday
{
return [[self uniqueChildWithTag: @"bday"] value: 0];
return [[self uniqueChildWithTag: @"bday"] flattenedValuesForKey: @""];
}
- (void) setNote: (NSString *) _value
{
[[self uniqueChildWithTag: @"note"] setValue: 0 to: _value];
[[self uniqueChildWithTag: @"note"] setSingleValue: _value forKey: @""];
}
- (NSString *) note
{
return [[self uniqueChildWithTag: @"note"] value: 0];
return [[self uniqueChildWithTag: @"note"] flattenedValuesForKey: @""];
}
- (void) setTz: (NSString *) _value
{
[[self uniqueChildWithTag: @"tz"] setValue: 0 to: _value];
[[self uniqueChildWithTag: @"tz"] setSingleValue: _value forKey: @""];
}
- (NSString *) tz
{
return [[self uniqueChildWithTag: @"tz"] value: 0];
return [[self uniqueChildWithTag: @"tz"] flattenedValuesForKey: @""];
}
- (void) setNickname: (NSString *) _value
{
[[self uniqueChildWithTag: @"nickname"] setValue: 0 to: _value];
[[self uniqueChildWithTag: @"nickname"] setSingleValue: _value forKey: @""];
}
- (NSString *) nickname
{
return [[self uniqueChildWithTag: @"nickname"] value: 0];
return [[self uniqueChildWithTag: @"nickname"] flattenedValuesForKey: @""];
}
- (void) addTel: (NSString *) phoneNumber
@ -270,20 +270,20 @@
n = [self uniqueChildWithTag: @"n"];
if (family)
[n setValue: 0 to: family];
[n setSingleValue: family atIndex: 0 forKey: @""];
if (given)
[n setValue: 1 to: given];
[n setSingleValue: given atIndex: 1 forKey: @""];
if (additional)
[n setValue: 2 to: additional];
[n setSingleValue: additional atIndex: 2 forKey: @""];
if (prefixes)
[n setValue: 3 to: prefixes];
[n setSingleValue: prefixes atIndex: 3 forKey: @""];
if (suffixes)
[n setValue: 4 to: suffixes];
[n setSingleValue: suffixes atIndex: 4 forKey: @""];
}
- (NSArray *) n
- (CardElement *) n
{
return [[self uniqueChildWithTag: @"n"] values];
return [self uniqueChildWithTag: @"n"];
}
- (void) setOrg: (NSString *) anOrg
@ -294,35 +294,30 @@
org = [self uniqueChildWithTag: @"org"];
if (anOrg)
[org setValue: 0 to: anOrg];
[org setSingleValue: anOrg atIndex: 0 forKey: @""];
if (someUnits)
{
max = [someUnits count];
for (count = 0; count < max; count++)
[org setValue: count + 1 to: [someUnits objectAtIndex: count]];
[org setSingleValue: [someUnits objectAtIndex: count]
atIndex: count + 1 forKey: @""];
}
}
- (NSArray *) org
- (CardElement *) org
{
NSArray *elements, *org;
elements = [self childrenWithTag: @"org"];
if ([elements count] > 0)
org = [[elements objectAtIndex: 0] values];
else
org = nil;
return org;
return [self uniqueChildWithTag: @"org"];
}
- (void) setCategories: (NSArray *) newCategories
{
CardElement *cats;
NSMutableArray *copy;
cats = [self uniqueChildWithTag: @"categories"];
[cats setCommaSeparatedValues: newCategories];
copy = [newCategories mutableCopy];
[cats setValues: copy atIndex: 0 forKey: @""];
[copy release];
}
- (NSArray *) categories
@ -331,7 +326,7 @@
cats = [self uniqueChildWithTag: @"categories"];
return [[cats value: 0] vCardSubvaluesWithSeparator: ','];
return [cats valuesAtIndex: 0 forKey: @""];
}
// - (void) setOrg: (NGVCardOrg *) _v
@ -461,12 +456,12 @@
- (NSString *) preferredEMail
{
return [[self _preferredElementWithTag: @"email"] value: 0];
return [[self _preferredElementWithTag: @"email"] flattenedValuesForKey: @""];
}
- (NSString *) preferredTel
{
return [[self _preferredElementWithTag: @"tel"] value: 0];
return [[self _preferredElementWithTag: @"tel"] flattenedValuesForKey: @""];
}
- (CardElement *) preferredAdr

View File

@ -21,6 +21,7 @@
*/
#import <Foundation/NSArray.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSString.h>
#import <NGExtensions/NGBase64Coding.h>
@ -61,9 +62,11 @@
{
/* We bypass -[values:] because we want to obtain the undecoded
value first. */
if ([values count] > 0)
if ([values count] > 0 && [[values objectForKey: @""] count] > 0 &&
[[[values objectForKey: @""] objectAtIndex: 0] count] > 0)
{
value = [values objectAtIndex: 0];
value = [[[values objectForKey: @""] objectAtIndex: 0]
componentsJoinedByString: @","];
decodedContent = [value dataByDecodingBase64];
}
else

View File

@ -48,12 +48,12 @@
- (void) setReference: (NSString *) newReference
{
[self setValue: 0 to: newReference];
[self setSingleValue: newReference forKey: @""];
}
- (NSString *) reference
{
return [self value: 0];
return [self flattenedValuesForKey: @""];
}
@end

View File

@ -77,45 +77,45 @@
- (void) setProdID: (NSString *) newProdID
{
[[self uniqueChildWithTag: @"prodid"] setValue: 0 to: newProdID];
[[self uniqueChildWithTag: @"prodid"] setSingleValue: newProdID forKey: @""];
}
- (NSString *) prodID
{
return [[self uniqueChildWithTag: @"prodid"] value: 0];
return [[self uniqueChildWithTag: @"prodid"] flattenedValuesForKey: @""];
}
- (void) setVersion: (NSString *) newVersion
{
[[self uniqueChildWithTag: @"version"] setValue: 0
to: newVersion];
[[self uniqueChildWithTag: @"version"] setSingleValue: newVersion
forKey: @""];
}
- (NSString *) version
{
return [[self uniqueChildWithTag: @"version"] value: 0];
return [[self uniqueChildWithTag: @"version"] flattenedValuesForKey: @""];
}
- (void) setUid: (NSString *) newUid
{
[[self uniqueChildWithTag: @"uid"] setValue: 0
to: newUid];
[[self uniqueChildWithTag: @"uid"] setSingleValue: newUid
forKey: @""];
}
- (NSString *) uid
{
return [[self uniqueChildWithTag: @"uid"] value: 0];
return [[self uniqueChildWithTag: @"uid"] flattenedValuesForKey: @""];
}
- (void) setAccessClass: (NSString *) newAccessClass
{
[[self uniqueChildWithTag: @"class"] setValue: 0
to: newAccessClass];
[[self uniqueChildWithTag: @"class"] setSingleValue: newAccessClass
forKey: @""];
}
- (NSString *) accessClass
{
return [[self uniqueChildWithTag: @"class"] value: 0];
return [[self uniqueChildWithTag: @"class"] flattenedValuesForKey: @""];
}
- (NGCardsAccessClass) symbolicAccessClass
@ -141,34 +141,34 @@
- (void) setFn: (NSString *) newFn
{
[[self uniqueChildWithTag: @"fn"] setValue: 0 to: newFn];
[[self uniqueChildWithTag: @"fn"] setSingleValue: newFn forKey: @""];
}
- (NSString *) fn
{
return [[self uniqueChildWithTag: @"fn"] value: 0];
return [[self uniqueChildWithTag: @"fn"] flattenedValuesForKey: @""];
}
- (void) setNickname: (NSString *) newNickname
{
[[self uniqueChildWithTag: @"nickname"] setValue: 0
to: newNickname];
[[self uniqueChildWithTag: @"nickname"] setSingleValue: newNickname
forKey: @""];
}
- (NSString *) nickname
{
return [[self uniqueChildWithTag: @"nickname"] value: 0];
return [[self uniqueChildWithTag: @"nickname"] flattenedValuesForKey: @""];
}
- (void) setDescription: (NSString *) newDescription
{
[[self uniqueChildWithTag: @"description"] setValue: 0
to: newDescription];
[[self uniqueChildWithTag: @"description"] setSingleValue: newDescription
forKey: @""];
}
- (NSString *) description
{
return [[self uniqueChildWithTag: @"description"] value: 0];
return [[self uniqueChildWithTag: @"description"] flattenedValuesForKey: @""];
}
- (void) addCardReference: (NGVCardReference *) newCardRef

View File

@ -35,8 +35,6 @@
- (NSArray *) cardElementsWithAttribute: (NSString *) anAttribute
havingValue: (NSString *) aValue;
- (NSArray *) renderedForCards;
@end
#endif /* NSARRAY_NGCARDS_H */

View File

@ -99,32 +99,4 @@
return matchingElements;
}
- (NSArray *) renderedForCards
{
NSMutableArray *purified;
NSString *string;
int count, max, lastInsert;
max = [self count];
purified = [NSMutableArray arrayWithCapacity: max];
lastInsert = -1;
for (count = 0; count < max; count++)
{
string = [self objectAtIndex: count];
if ([string length] > 0)
{
while (lastInsert < (count - 1))
{
[purified addObject: @""];
lastInsert++;
}
[purified addObject: [string escapedForCards]];
lastInsert = count;
}
}
return purified;
}
@end

View File

@ -29,6 +29,9 @@
- (id) objectForCaseInsensitiveKey: (NSString *) aKey;
- (void) versitRenderInString: (NSMutableString *) aString
asAttributes: (BOOL) asAttribute; /* handling of ":" */
@end
#endif /* NSDICTIONARY_NGCARDS_H */

View File

@ -20,10 +20,95 @@
* Boston, MA 02111-1307, USA.
*/
#import <Foundation/NSArray.h>
#import <Foundation/NSString.h>
#import "NSArray+NGCards.h"
#import "NSString+NGCards.h"
#import "NSDictionary+NGCards.h"
@interface NSArray (NGCardsVersit)
- (BOOL) _renderAsSubValuesInString: (NSMutableString *) aString
asAttributes: (BOOL) asAttributes;
- (BOOL) _renderAsOrderedValuesInString: (NSMutableString *) aString
withKey: (NSString *) key;
@end
@implementation NSArray (NGCardsVersit)
- (BOOL) _renderAsSubValuesInString: (NSMutableString *) aString
asAttributes: (BOOL) asAttributes
{
NSUInteger count, max;
NSString *subValue, *escaped;
BOOL previousWasEmpty = YES, rendered = NO;
max = [self count];
for (count = 0; count < max; count++)
{
if (!previousWasEmpty)
[aString appendString: @","];
subValue = [self objectAtIndex: count];
/* We MUST quote attribute values that have a ":" in them
and that not already quoted */
if (asAttributes && [subValue length] > 2
&& [subValue rangeOfString: @":"].length
&& [subValue characterAtIndex: 0] != '"'
&& ![subValue hasSuffix: @"\""])
subValue = [NSString stringWithFormat: @"\"%@\"", subValue];
escaped = [subValue escapedForCards];
if ([escaped length] > 0)
{
[aString appendString: escaped];
previousWasEmpty = NO;
rendered = YES;
}
else
previousWasEmpty = YES;
}
return rendered;
}
- (BOOL) _renderAsOrderedValuesInString: (NSMutableString *) aString
withKey: (NSString *) key
{
NSUInteger count, max, lastRendered = 0;
BOOL rendered = NO;
NSArray *subValues;
NSMutableString *substring;
max = [self count];
for (count = 0; count < max; count++)
{
subValues = [self objectAtIndex: count];
substring = [NSMutableString string];
if ([subValues _renderAsSubValuesInString: substring
asAttributes: NO])
{
if (lastRendered == 0 && [key length] > 0)
[aString appendFormat: @"%@=", key];
while (lastRendered < count)
{
[aString appendString: @";"];
lastRendered++;
}
[aString appendString: substring];
rendered = YES;
}
}
return rendered;
}
@end
@implementation NSDictionary (NGCardsExtension)
- (id) objectForCaseInsensitiveKey: (NSString *) aKey
@ -37,4 +122,43 @@
return ((realKey) ? [self objectForKey: realKey] : nil);
}
- (void) versitRenderInString: (NSMutableString *) aString
asAttributes: (BOOL) asAttributes
{
NSArray *keys;
NSUInteger count, max, rendered = 0;
NSArray *orderedValues;
NSString *key;
NSMutableString *substring;
keys = [self allKeys];
max = [keys count];
for (count = 0; count < max; count++)
{
key = [keys objectAtIndex: count];
orderedValues = [self objectForKey: key];
substring = [NSMutableString string];
if (asAttributes)
{
if ([orderedValues _renderAsSubValuesInString: substring
asAttributes: YES])
{
if (rendered > 0)
[aString appendString: @";"];
[aString appendFormat: @"%@=%@",
[key uppercaseString], substring];
rendered++;
}
}
else if ([orderedValues _renderAsOrderedValuesInString: substring
withKey: [key uppercaseString]])
{
if (rendered > 0)
[aString appendString: @";"];
[aString appendString: substring];
rendered++;
}
}
}
@end

View File

@ -27,6 +27,7 @@
@class NSArray;
@class NSCalendarDate;
@class NSMutableDictionary;
@class NSTimeZone;
@interface NSString (NGCardsExtensions)
@ -40,7 +41,7 @@
- (NSCalendarDate *) asCalendarDate;
- (BOOL) isAllDayDate;
- (NSArray *) vCardSubvaluesWithSeparator: (unichar) separator;
- (NSMutableDictionary *) vCardSubvalues;
@end

View File

@ -21,6 +21,7 @@
*/
#import <Foundation/NSArray.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSCalendarDate.h>
#import <Foundation/NSEnumerator.h>
#import <Foundation/NSRange.h>
@ -316,25 +317,35 @@
return ([self length] == 8);
}
- (NSArray *) vCardSubvaluesWithSeparator: (unichar) separator
- (NSMutableDictionary *) vCardSubvalues
{
NSMutableArray *components;
/* This schema enables things like this:
ELEM;...:KEY1=subvalue1;KEY2=subvalue1,subvalue2
or
ELEM;...:subvalue1;subvalue1,subvalue2 (where KEY = @"") */
NSMutableDictionary *values; /* key <> ordered values associations */
NSMutableArray *orderedValues = nil; /* those are separated by ';' and contain
subvalues, may or may not be named */
NSMutableArray *subValues = nil; /* those are separeted by ',' */
unichar *stringBuffer, *substringBuffer;
NSString *substring;
NSString *valuesKey, *substring;
unichar currentChar;
NSUInteger substringLength, count, max;
BOOL escaped;
BOOL escaped = NO;
components = [NSMutableArray arrayWithCapacity: 5];
values = [NSMutableDictionary dictionary];
valuesKey = @"";
max = [self length];
stringBuffer = NSZoneMalloc (NULL, sizeof (unichar) * max);
stringBuffer = NSZoneMalloc (NULL, sizeof (unichar) * max + 1);
[self getCharacters: stringBuffer];
substringLength = 0;
escaped = NO;
stringBuffer[max] = 0;
substringBuffer = NSZoneMalloc (NULL, sizeof (unichar) * max);
substringLength = 0;
max += 1; /* we add one step to force the inclusion of the ending '\0' in
the loop */
for (count = 0; count < max; count++)
{
currentChar = stringBuffer[count];
@ -343,7 +354,7 @@
escaped = NO;
if (currentChar == 'n' || currentChar == 'N')
substringBuffer[substringLength] = '\n';
else if (currentChar == 'r')
else if (currentChar == 'r' || currentChar == 'R')
substringBuffer[substringLength] = '\r';
else
substringBuffer[substringLength] = currentChar;
@ -353,16 +364,48 @@
{
if (currentChar == '\\')
escaped = YES;
else if (currentChar == separator)
else if (currentChar == ',' || currentChar == ';' || currentChar == 0)
{
substring
= [[NSString alloc] initWithCharactersNoCopy: substringBuffer
length: substringLength
freeWhenDone: YES];
[components addObject: substring];
[substring release];
substringBuffer = NSZoneMalloc (NULL, sizeof (unichar) * max);
= [[NSString alloc] initWithCharacters: substringBuffer
length: substringLength];
substringLength = 0;
orderedValues = [values objectForKey: valuesKey];
if (!orderedValues)
{
orderedValues = [NSMutableArray new];
[values setObject: orderedValues forKey: valuesKey];
[orderedValues release];
}
if (!subValues)
{
subValues = [NSMutableArray new];
[orderedValues addObject: subValues];
[subValues release];
}
if ([substring length] > 0)
[subValues addObject: substring];
[substring release];
if (currentChar != ',')
{
orderedValues = nil;
subValues = nil;
valuesKey = @"";
}
}
/* hack: 16 chars is an arbitrary limit to distinguish between
"named properties" and the base64 padding character. This might
need further tweaking... */
else if (currentChar == '=' && substringLength < 16)
{
substring
= [[NSString alloc] initWithCharacters: substringBuffer
length: substringLength];
[substring autorelease];
substringLength = 0;
valuesKey = [substring lowercaseString];
}
else
{
@ -372,21 +415,12 @@
}
}
if (substringLength > 0)
{
substring = [[NSString alloc] initWithCharactersNoCopy: substringBuffer
length: substringLength
freeWhenDone: YES];
[components addObject: substring];
[substring release];
}
NSZoneFree (NULL, stringBuffer);
NSZoneFree (NULL, substringBuffer);
return components;
return values;
}
- (NSString *) rfc822Email
{
unsigned idx;

View File

@ -82,41 +82,41 @@
- (void) setAction: (NSString *) _value
{
[[self uniqueChildWithTag: @"action"] setValue: 0
to: _value];
[[self uniqueChildWithTag: @"action"] setSingleValue: _value
forKey: @""];
}
- (NSString *) action
{
return [[self uniqueChildWithTag: @"action"] value: 0];
return [[self uniqueChildWithTag: @"action"] flattenedValuesForKey: @""];
}
- (void) setSummary: (NSString *) _value
{
[[self uniqueChildWithTag: @"summary"] setValue: 0
to: _value];
[[self uniqueChildWithTag: @"summary"] setSingleValue: _value
forKey: @""];
}
- (NSString *) summary
{
return [[self uniqueChildWithTag: @"summary"] value: 0];
return [[self uniqueChildWithTag: @"summary"] flattenedValuesForKey: @""];
}
- (void) setComment: (NSString *) _value
{
[[self uniqueChildWithTag: @"description"] setValue: 0
to: _value];
[[self uniqueChildWithTag: @"description"] setSingleValue: _value
forKey: @""];
}
- (NSString *) comment
{
return [[self uniqueChildWithTag: @"description"] value: 0];
return [[self uniqueChildWithTag: @"description"] flattenedValuesForKey: @""];
}
- (void) setRecurrenceRule: (NSString *) _recurrenceRule
- (void) setRecurrenceRule: (NSString *) _value
{
[[self uniqueChildWithTag: @"rrule"] setValue: 0
to: _recurrenceRule];
[[self uniqueChildWithTag: @"rrule"] setSingleValue: _value
forKey: @""];
}
- (void) setAttendees: (NSArray *) attendees
@ -137,7 +137,7 @@
- (NSString *) recurrenceRule
{
return [[self uniqueChildWithTag: @"rrule"] value: 0];
return [[self uniqueChildWithTag: @"rrule"] flattenedValuesForKey: @""];
}
- (NSCalendarDate *) nextAlarmDate
@ -161,7 +161,8 @@
== NSOrderedSame)
{
relation = [aTrigger relationType];
anInterval = [[aTrigger value] durationAsTimeInterval];
anInterval = [[aTrigger flattenedValuesForKey: @""]
durationAsTimeInterval];
if ([relation caseInsensitiveCompare: @"END"] == NSOrderedSame)
{
if ([parent isKindOfClass: [iCalEvent class]])

View File

@ -28,9 +28,6 @@
@interface iCalAttachment : CardElement
- (void) setValue: (NSString *) aValue;
- (NSString *) value;
- (void) setValueType: (NSString *) aType;
- (NSString *) valueType;

View File

@ -26,16 +26,6 @@
/* accessors */
- (void) setValue: (NSString *) _value
{
[self setValue: 0 to: _value];
}
- (NSString *) value
{
return [self value: 0];
}
- (void) setValueType: (NSString *) _value
{
[self setValue: 0 ofAttribute: @"type" to: _value];

View File

@ -69,45 +69,44 @@
/* accessors */
- (void) setCalscale: (NSString *) _calscale
- (void) setCalscale: (NSString *) _value
{
[[self uniqueChildWithTag: @"calscale"] setValue: 0 to: _calscale];
[[self uniqueChildWithTag: @"calscale"] setSingleValue: _value forKey: @""];
}
- (NSString *) calscale
{
return [[self uniqueChildWithTag: @"calscale"] value: 0];
return [[self uniqueChildWithTag: @"calscale"] flattenedValuesForKey: @""];
}
- (void) setVersion: (NSString *) _version
- (void) setVersion: (NSString *) _value
{
[[self uniqueChildWithTag: @"version"] setValue: 0 to: _version];
[[self uniqueChildWithTag: @"version"] setSingleValue: _value forKey: @""];
}
- (NSString *) version
{
return [[self uniqueChildWithTag: @"version"] value: 0];
return [[self uniqueChildWithTag: @"version"] flattenedValuesForKey: @""];
}
- (void) setProdID: (NSString *) _value
{
[[self uniqueChildWithTag: @"prodid"] setValue: 0 to: _value];
[[self uniqueChildWithTag: @"prodid"] setSingleValue: _value forKey: @""];
}
- (NSString *) prodId
{
return [[self uniqueChildWithTag: @"prodid"] value: 0];
return [[self uniqueChildWithTag: @"prodid"] flattenedValuesForKey: @""];
}
- (void) setMethod: (NSString *) _value
{
[[self uniqueChildWithTag: @"method"] setValue: 0
to: [_value uppercaseString]];
[[self uniqueChildWithTag: @"method"] setSingleValue: _value forKey: @""];
}
- (NSString *) method
{
return [[self uniqueChildWithTag: @"method"] value: 0];
return [[self uniqueChildWithTag: @"method"] flattenedValuesForKey: @""];
}
- (void) addToEvents: (iCalEvent *) _event

View File

@ -137,7 +137,7 @@
else
timeString = @"";
[self setValue: 0 to: timeString];
[self setSingleValue: timeString forKey: @""];
}
- (void) setDateTime: (NSCalendarDate *) dateTime
@ -160,15 +160,17 @@
iCalTimeZone *iTZ;
NSString *date;
NSCalendarDate *initialDate, *dateTime;
NSArray *subValues;
NSMutableArray *dates;
//NSTimeZone *tz;
unsigned count, i;
count = [[self values] count];
subValues = [self valuesAtIndex: 0 forKey: @""];
count = [subValues count];
dates = [NSMutableArray arrayWithCapacity: count];
for (i = 0; i < count; i++)
{
date = [self value: i];
date = [subValues objectAtIndex: i];
iTZ = [self timeZone];
if (iTZ)
@ -204,7 +206,7 @@
- (BOOL) isAllDay
{
return [[self value: 0] isAllDayDate];
return [[self flattenedValuesForKey: @""] isAllDayDate];
}
@end

View File

@ -67,8 +67,8 @@ typedef enum
- (void) setPriority: (NSString *) _value;
- (NSString *) priority;
- (void) setCategories: (NSString *) _value;
- (NSString *)categories;
- (void) setCategories: (NSArray *) _value;
- (NSArray *) categories;
- (void) setUserComment: (NSString *) _userComment;
- (NSString *) userComment;

View File

@ -72,55 +72,55 @@
/* accessors */
- (void) setUid: (NSString *) _uid
- (void) setUid: (NSString *) _value
{
[[self uniqueChildWithTag: @"uid"] setValue: 0 to: _uid];
[[self uniqueChildWithTag: @"uid"] setSingleValue: _value forKey: @""];
}
- (NSString *) uid
{
return [[self uniqueChildWithTag: @"uid"] value: 0];
return [[self uniqueChildWithTag: @"uid"] flattenedValuesForKey: @""];
}
- (void) setSummary: (NSString *) _value
{
[[self uniqueChildWithTag: @"summary"] setValue: 0 to: _value];
[[self uniqueChildWithTag: @"summary"] setSingleValue: _value forKey: @""];
}
- (NSString *) summary
{
return [[self uniqueChildWithTag: @"summary"] value: 0];
return [[self uniqueChildWithTag: @"summary"] flattenedValuesForKey: @""];
}
- (void) setLocation: (NSString *) _value
{
[[self uniqueChildWithTag: @"location"] setValue: 0 to: _value];
[[self uniqueChildWithTag: @"location"] setSingleValue: _value forKey: @""];
}
- (NSString *) location
{
return [[self uniqueChildWithTag: @"location"] value: 0];
return [[self uniqueChildWithTag: @"location"] flattenedValuesForKey: @""];
}
#warning the "comment" accessors are actually "description" accessors, the "comment" ones are missing
- (void) setComment: (NSString *) _value
{
[[self uniqueChildWithTag: @"description"] setValue: 0 to: _value];
[[self uniqueChildWithTag: @"description"] setSingleValue: _value forKey: @""];
}
- (NSString *) comment
{
return [[self uniqueChildWithTag: @"description"] value: 0];
return [[self uniqueChildWithTag: @"description"] flattenedValuesForKey: @""];
}
- (void) setAccessClass: (NSString *) _value
{
[[self uniqueChildWithTag: @"class"] setValue: 0 to: _value];
[[self uniqueChildWithTag: @"class"] setSingleValue: _value forKey: @""];
}
- (NSString *) accessClass
{
return [[self uniqueChildWithTag: @"class"] value: 0];
return [[self uniqueChildWithTag: @"class"] flattenedValuesForKey: @""];
}
- (iCalAccessClass) symbolicAccessClass
@ -146,42 +146,47 @@
- (void) setPriority: (NSString *) _value
{
[[self uniqueChildWithTag: @"priority"] setValue: 0 to: _value];
[[self uniqueChildWithTag: @"priority"] setSingleValue: _value forKey: @""];
}
- (NSString *) priority
{
return [[self uniqueChildWithTag: @"priority"] value: 0];
return [[self uniqueChildWithTag: @"priority"] flattenedValuesForKey: @""];
}
- (void) setCategories: (NSString *) _value
- (void) setCategories: (NSArray *) _value
{
[[self uniqueChildWithTag: @"categories"] setValue: 0 to: _value];
NSMutableArray *copy;
copy = [_value mutableCopy];
[[self uniqueChildWithTag: @"categories"] setValues: copy atIndex: 0
forKey: @""];
[copy release];
}
- (NSString *) categories
- (NSArray *) categories
{
return [[self uniqueChildWithTag: @"categories"] value: 0];
return [[self uniqueChildWithTag: @"categories"] valuesAtIndex: 0 forKey: @""];
}
- (void) setUserComment: (NSString *) _value
{
[[self uniqueChildWithTag: @"usercomment"] setValue: 0 to: _value];
[[self uniqueChildWithTag: @"usercomment"] setSingleValue: _value forKey: @""];
}
- (NSString *) userComment
{
return [[self uniqueChildWithTag: @"usercomment"] value: 0];
return [[self uniqueChildWithTag: @"usercomment"] flattenedValuesForKey: @""];
}
- (void) setStatus: (NSString *) _value
{
[[self uniqueChildWithTag: @"status"] setValue: 0 to: _value];
[[self uniqueChildWithTag: @"status"] setSingleValue: _value forKey: @""];
}
- (NSString *) status
{
return [[self uniqueChildWithTag: @"status"] value: 0];
return [[self uniqueChildWithTag: @"status"] flattenedValuesForKey: @""];
}
- (void) setSequence: (NSNumber *)_value
@ -189,15 +194,15 @@
NSString *sequence;
sequence = [NSString stringWithFormat: @"%@", _value];
[[self uniqueChildWithTag: @"sequence"] setValue: 0
to: sequence];;
[[self uniqueChildWithTag: @"sequence"] setSingleValue: sequence
forKey: @""];
}
- (NSNumber *) sequence
{
NSString *sequence;
sequence = [[self uniqueChildWithTag: @"sequence"] value: 0];
sequence = [[self uniqueChildWithTag: @"sequence"] flattenedValuesForKey: @""];
return [NSNumber numberWithInt: [sequence intValue]];
}
@ -391,16 +396,16 @@
- (void) setAttach: (id) _value
{
NSString *asString;
NSString *aString;
if ([_value isKindOfClass: [NSString class]])
asString = _value;
aString = _value;
else if ([_value isKindOfClass: [NSURL class]])
asString = [_value absoluteString];
aString = [_value absoluteString];
else
asString = @"";
aString = @"";
[[self uniqueChildWithTag: @"attach"] setValue: 0 to: asString];
[[self uniqueChildWithTag: @"attach"] setSingleValue: aString forKey: @""];
}
- (NSURL *) attach
@ -408,7 +413,7 @@
NSString *stringAttach;
NSURL *url;
stringAttach = [[self uniqueChildWithTag: @"attach"] value: 0];
stringAttach = [[self uniqueChildWithTag: @"attach"] flattenedValuesForKey: @""];
url = [NSURL URLWithString: stringAttach];
if (!url && [stringAttach length] > 0)
@ -419,23 +424,23 @@
- (void) setUrl: (id) _value
{
NSString *asString;
NSString *aString;
if ([_value isKindOfClass: [NSString class]])
asString = _value;
aString = _value;
else if ([_value isKindOfClass: [NSURL class]])
asString = [_value absoluteString];
aString = [_value absoluteString];
else
asString = @"";
aString = @"";
[[self uniqueChildWithTag: @"url"] setValue: 0 to: asString];
[[self uniqueChildWithTag: @"url"] setSingleValue: aString forKey: @""];
}
- (NSURL *) url
{
NSString *stringUrl;
stringUrl = [[self uniqueChildWithTag: @"url"] value: 0];
stringUrl = [[self uniqueChildWithTag: @"url"] flattenedValuesForKey: @""];
return [NSURL URLWithString: stringUrl];
}

View File

@ -104,13 +104,12 @@
- (void) setDuration: (NSString *) _value
{
[[self uniqueChildWithTag: @"duration"] setValue: 0
to: _value];
[[self uniqueChildWithTag: @"duration"] setSingleValue: _value forKey: @""];
}
- (NSString *) duration
{
return [[self uniqueChildWithTag: @"duration"] value: 0];
return [[self uniqueChildWithTag: @"duration"] flattenedValuesForKey: @""];
}
- (BOOL) hasDuration
@ -148,15 +147,14 @@
return interval;
}
- (void) setTransparency: (NSString *) _transparency
- (void) setTransparency: (NSString *) _value
{
[[self uniqueChildWithTag: @"transp"] setValue: 0
to: _transparency];
[[self uniqueChildWithTag: @"transp"] setSingleValue: _value forKey: @""];
}
- (NSString *) transparency
{
return [[self uniqueChildWithTag: @"transp"] value: 0];
return [[self uniqueChildWithTag: @"transp"] flattenedValuesForKey: @""];
}
/* convenience */

View File

@ -57,13 +57,13 @@
{
/* iCal.app compatibility:
- "mailto" prefix must be in lowercase; */
[self setValue: 0
to: [NSString stringWithFormat: @"mailto:%@", _s]];
[self setSingleValue: [NSString stringWithFormat: @"mailto:%@", _s]
forKey: @""];
}
- (NSString *) email
{
return [self value: 0];
return [self flattenedValuesForKey: @""];
}
- (NSString *) rfc822Email

View File

@ -194,6 +194,7 @@
#import "NSCalendarDate+NGCards.h"
#import "NSString+NGCards.h"
#import "CardGroup.h"
#import "iCalByDayMask.h"
#import "iCalRecurrenceRule.h"
@ -234,8 +235,7 @@ NSString *iCalWeekDayString[] = { @"SU", @"MO", @"TU", @"WE", @"TH", @"FR",
iCalRecurrenceRule *rule;
rule = [self elementWithTag: @"rrule"];
if ([_iCalRep length] > 0)
[rule addValues: [_iCalRep componentsSeparatedByString: @";"]];
[rule setRrule: _iCalRep];
return rule;
}
@ -269,15 +269,19 @@ NSString *iCalWeekDayString[] = { @"SU", @"MO", @"TU", @"WE", @"TH", @"FR",
- (void) setRrule: (NSString *) _rrule
{
NSEnumerator *newValues;
NSString *newValue;
CardGroup *mockParent;
NSString *wrappedRule;
CardElement *mockRule;
newValues = [[_rrule componentsSeparatedByString: @";"] objectEnumerator];
newValue = [newValues nextObject];
while (newValue)
if ([_rrule length] > 0)
{
[self addValue: newValue];
newValue = [newValues nextObject];
wrappedRule = [NSString stringWithFormat:
@"BEGIN:MOCK\r\nRRULE:%@\r\nEND:MOCK",
_rrule];
mockParent = [CardGroup parseSingleFromSource: wrappedRule];
mockRule = [mockParent uniqueChildWithTag: @"rrule"];
[values release];
values = [[mockRule values] mutableCopy];
}
}
@ -350,75 +354,73 @@ NSString *iCalWeekDayString[] = { @"SU", @"MO", @"TU", @"WE", @"TH", @"FR",
- (void) setFrequency: (iCalRecurrenceFrequency) _frequency
{
[self setNamedValue: @"freq" to: [self frequencyForValue: _frequency]];
[self setSingleValue: [self frequencyForValue: _frequency] forKey: @"freq"];
}
- (iCalRecurrenceFrequency) frequency
{
return [self valueForFrequency: [self namedValue: @"freq"]];
}
- (void) setRepeatCount: (int) _repeatCount
{
[self setNamedValue: @"count"
to: [NSString stringWithFormat: @"%d", _repeatCount]];
}
- (int) repeatCount
{
return [[self namedValue: @"count"] intValue];
return [self valueForFrequency: [self flattenedValuesForKey: @"freq"]];
}
- (void) setUntilDate: (NSCalendarDate *) _untilDate
{
[self setNamedValue: @"until"
to: [_untilDate icalString]];
[self setSingleValue: [_untilDate icalString] forKey: @"until"];
}
- (NSCalendarDate *) untilDate
{
#warning handling of default timezone needs to be implemented
return [[self namedValue: @"until"] asCalendarDate];
return [[self flattenedValuesForKey: @"until"] asCalendarDate];
}
- (void) setInterval: (NSString *) _interval
{
if (_interval && [_interval intValue] == 1)
[self setNamedValue: @"interval" to: nil];
if ([_interval intValue] < 2)
[self setSingleValue: nil forKey: @"interval"];
else
[self setNamedValue: @"interval" to: _interval];
}
- (void) setCount: (NSString *) _count
{
[self setNamedValue: @"count" to: _count];
}
- (void) setUntil: (NSString *) _until
{
[self setNamedValue: @"until" to: _until];
[self setSingleValue: _interval forKey: @"interval"];
}
- (void) setRepeatInterval: (int) _repeatInterval
{
[self setNamedValue: @"interval"
to: [NSString stringWithFormat: @"%d", _repeatInterval]];
[self setInterval: [NSString stringWithFormat: @"%d", _repeatInterval]];
}
- (int) repeatInterval
{
int interval;
interval = [[self namedValue: @"interval"] intValue];
interval = [[self flattenedValuesForKey: @"interval"] intValue];
if (interval < 1)
interval = 1;
return interval;
}
- (void) setRepeatCount: (int) _repeatCount
{
[self setSingleValue: [NSString stringWithFormat: @"%d", _repeatCount]
forKey: @"count"];
}
- (int) repeatCount
{
return [[self flattenedValuesForKey: @"count"] intValue];
}
- (void) setCount: (NSString *) _count
{
[self setSingleValue: _count forKey: @"count"];
}
- (void) setUntil: (NSString *) _until
{
[self setSingleValue: _until forKey: @"until"];
}
- (void) setWkst: (NSString *) _weekStart
{
[self setNamedValue: @"wkst" to: _weekStart];
[self setSingleValue: _weekStart forKey: @"wkst"];
}
#warning we also should handle the user weekstarts
@ -426,7 +428,7 @@ NSString *iCalWeekDayString[] = { @"SU", @"MO", @"TU", @"WE", @"TH", @"FR",
{
NSString *start;
start = [self namedValue: @"wkst"];
start = [self flattenedValuesForKey: @"wkst"];
if (![start length])
start = @"MO";
@ -445,12 +447,16 @@ NSString *iCalWeekDayString[] = { @"SU", @"MO", @"TU", @"WE", @"TH", @"FR",
- (void) setByDay: (NSString *) newByDay
{
[self setNamedValue: @"byday" to: newByDay];
NSMutableArray *byDays;
byDays = [[newByDay componentsSeparatedByString: @","] mutableCopy];
[self setValues: byDays atIndex: 0 forKey: @"byday"];
[byDays release];
}
- (NSString *) byDay
{
return [self namedValue: @"byday"];
return [self flattenedValuesForKey: @"byday"];
}
- (void) setByDayMask: (iCalByDayMask *) newByDayMask
@ -472,12 +478,9 @@ NSString *iCalWeekDayString[] = { @"SU", @"MO", @"TU", @"WE", @"TH", @"FR",
- (NSArray *) byMonthDay
{
NSArray *byMonthDay;
NSString *byMonthDayStr;
byMonthDayStr = [self namedValue: @"bymonthday"];
if ([byMonthDayStr length])
byMonthDay = [byMonthDayStr componentsSeparatedByString: @","];
else
byMonthDay = [self valuesAtIndex: 0 forKey: @"bymonthday"];
if (![byMonthDay count])
byMonthDay = nil;
return byMonthDay;
@ -486,12 +489,9 @@ NSString *iCalWeekDayString[] = { @"SU", @"MO", @"TU", @"WE", @"TH", @"FR",
- (NSArray *) byMonth
{
NSArray *byMonth;
NSString *byMonthStr;
byMonthStr = [self namedValue: @"bymonth"];
if ([byMonthStr length])
byMonth = [byMonthStr componentsSeparatedByString: @","];
else
byMonth = [self valuesAtIndex: 0 forKey: @"bymonth"];
if (![byMonth count])
byMonth = nil;
return byMonth;
@ -507,9 +507,9 @@ NSString *iCalWeekDayString[] = { @"SU", @"MO", @"TU", @"WE", @"TH", @"FR",
* - BYSECOND
* - BYSETPOS
*/
return ([[self namedValue: @"bymonthday"] length] ||
[[self namedValue: @"byday"] length] ||
[[self namedValue: @"bymonth"] length]);
return ([[self valuesAtIndex: 0 forKey: @"bymonthday"] count] ||
[[self valuesAtIndex: 0 forKey: @"byday"] count] ||
[[self valuesAtIndex: 0 forKey: @"bymonth"] count]);
}
- (BOOL) isInfinite

View File

@ -247,7 +247,7 @@
while ((dateString = [dateList nextObject]))
{
exDates = [(iCalDateTime*) dateString values];
exDates = [(iCalDateTime*) dateString valuesAtIndex: 0 forKey: @""];
for (i = 0; i < [exDates count]; i++)
{
dateString = [exDates objectAtIndex: i];

View File

@ -179,12 +179,12 @@ static NSArray *knownTimeZones;
- (void) setTzId: (NSString *) tzId
{
[[self uniqueChildWithTag: @"tzid"] setValue: 0 to: tzId];
[[self uniqueChildWithTag: @"tzid"] setSingleValue: tzId forKey: @""];
}
- (NSString *) tzId
{
return [[self uniqueChildWithTag: @"tzid"] value: 0];
return [[self uniqueChildWithTag: @"tzid"] flattenedValuesForKey: @""];
}
- (NSCalendarDate *) _occurrenceForPeriodNamed: (NSString *) pName

View File

@ -20,6 +20,7 @@
* Boston, MA 02111-1307, USA.
*/
#import <Foundation/NSArray.h>
#import <Foundation/NSCalendarDate.h>
#import <Foundation/NSString.h>
#import <Foundation/NSTimeZone.h>
@ -63,7 +64,7 @@
seconds = 0;
offsetTo = [[self uniqueChildWithTag: offsetName]
value: 0];
flattenedValuesForKey: @""];
length = [offsetTo length];
negative = [offsetTo hasPrefix: @"-"];
if (negative)
@ -140,7 +141,7 @@
[tzStart setTimeZone: [NSTimeZone timeZoneWithName: @"GMT"]];
tmpDate = [NSCalendarDate dateWithYear: [refDate yearOfCommonEra]
month: [[rrule namedValue: @"bymonth"] intValue]
month: [[[rrule byMonth] objectAtIndex: 0] intValue]
day: 1 hour: [tzStart hourOfDay]
minute: [tzStart minuteOfHour] second: 0
timeZone: [NSTimeZone timeZoneWithName: @"GMT"]];

View File

@ -47,13 +47,14 @@
- (void) setPercentComplete: (NSString *) _value
{
[[self uniqueChildWithTag: @"percent-complete"] setValue: 0
to: _value];
[[self uniqueChildWithTag: @"percent-complete"] setSingleValue: _value
forKey: @""];
}
- (NSString *) percentComplete
{
return [[self uniqueChildWithTag: @"percent-complete"] value: 0];
return [[self uniqueChildWithTag: @"percent-complete"]
flattenedValuesForKey: @""];
}
- (void) setDue: (NSCalendarDate *) newDueDate

View File

@ -26,9 +26,6 @@
@interface iCalTrigger : CardElement
- (void) setValue: (NSString *) theValue;
- (NSString *) value;
- (void) setValueType: (NSString *) theType;
- (NSString *) valueType;

View File

@ -27,16 +27,6 @@
/* accessors */
- (void) setValue: (NSString *) theValue
{
[self setValue: 0 to: theValue];
}
- (NSString *) value
{
return [self value: 0];
}
- (void) setValueType: (NSString *) theValue
{
[self setValue: 0 ofAttribute: @"value" to: theValue];

View File

@ -21,7 +21,7 @@
*/
/* This class implements most of the XML iCalendar spec as defined here:
http://tools.ietf.org/html/draft-daboo-et-al-icalendar-in-xml-04 */
http://tools.ietf.org/html/rfc6321 */
#import <Foundation/NSArray.h>
#import <Foundation/NSEnumerator.h>
@ -161,28 +161,38 @@
- (NSString *) _xmlRenderValue
{
NSMutableString *rendering;
NSString *valueTag, *currentValue;
int count, max;
BOOL displayed;
NSArray *keys, *orderedValues, *subValues;
NSString *key, *valueTag;
NSUInteger count, max, oCount, oMax, sCount, sMax;
#warning this code should be fix to comply better with the RFC
rendering = [NSMutableString stringWithCapacity: 64];
valueTag = [self xmlValueTag];
rendering = [NSMutableString stringWithCapacity: 64];
max = [values count];
displayed = NO;
keys = [values allKeys];
max = [keys count];
for (count = 0; count < max; count++)
{
currentValue = [[values objectAtIndex: count]
stringByEscapingXMLString];
if ([currentValue length] > 0)
key = [keys objectAtIndex: count];
orderedValues = [values objectForKey: key];
oMax = [orderedValues count];
for (oCount = 0; oCount < oMax; oCount++)
{
if (!displayed)
{
[self _appendPaddingValues: count withTag: valueTag
intoString: rendering];
displayed = YES;
}
[rendering appendFormat: @"<%@>%@</%@>",
valueTag, currentValue, valueTag];
if ([key length] > 0)
[rendering appendFormat: @"<%@>", [key lowercaseString]];
else
[rendering appendFormat: @"<%@>", valueTag];
subValues = [orderedValues objectAtIndex: oCount];
sMax = [subValues count];
for (sCount = 0; sCount < sMax; sCount++)
[rendering appendString: [[subValues objectAtIndex: sCount] stringByEscapingXMLString]];
if ([key length] > 0)
[rendering appendFormat: @"</%@>", [key lowercaseString]];
else
[rendering appendFormat: @"</%@>", valueTag];
}
}
@ -247,39 +257,39 @@
@end
@implementation iCalRecurrenceRule (iCalXMLExtension)
// @implementation iCalRecurrenceRule (iCalXMLExtension)
- (NSString *) _xmlRenderValue
{
NSMutableString *rendering;
NSArray *valueParts;
NSString *valueTag, *currentValue;
int count, max;
// - (NSString *) _xmlRenderValue
// {
// NSMutableString *rendering;
// NSArray *valueParts;
// NSString *valueTag, *currentValue;
// int count, max;
max = [values count];
rendering = [NSMutableString stringWithCapacity: 64];
for (count = 0; count < max; count++)
{
currentValue = [[values objectAtIndex: count]
stringByEscapingXMLString];
if ([currentValue length] > 0)
{
valueParts = [currentValue componentsSeparatedByString: @"="];
if ([valueParts count] == 2)
{
valueTag = [[valueParts objectAtIndex: 0] lowercaseString];
[rendering appendFormat: @"<%@>%@</%@>",
valueTag,
[valueParts objectAtIndex: 1],
valueTag];
}
}
}
// max = [values count];
// rendering = [NSMutableString stringWithCapacity: 64];
// for (count = 0; count < max; count++)
// {
// currentValue = [[values objectAtIndex: count]
// stringByEscapingXMLString];
// if ([currentValue length] > 0)
// {
// valueParts = [currentValue componentsSeparatedByString: @"="];
// if ([valueParts count] == 2)
// {
// valueTag = [[valueParts objectAtIndex: 0] lowercaseString];
// [rendering appendFormat: @"<%@>%@</%@>",
// valueTag,
// [valueParts objectAtIndex: 1],
// valueTag];
// }
// }
// }
return rendering;
}
// return rendering;
// }
@end
// @end
@implementation iCalUTCOffset (iCalXMLExtension)

View File

@ -857,8 +857,9 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir
NSArray *rules, *exRules, *exDates, *ranges;
NSArray *elements, *components;
NSString *content;
NSCalendarDate *checkStartDate, *checkEndDate, *firstStartDate,
*firstEndDate;
iCalDateTime *dtstart;
NSCalendarDate *checkStartDate, *checkEndDate, *firstStartDate, *firstEndDate;
iCalEvent *component;
iCalTimeZone *eventTimeZone;
unsigned count, max, offset;
@ -898,8 +899,8 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir
{
// Retrieve the range of the first/master event
component = [components objectAtIndex: 0];
dtstart = (iCalDateTime *)[component uniqueChildWithTag: @"dtstart"];
firstStartDate = [[[dtstart values] lastObject] asCalendarDate];
dtstart = (iCalDateTime *) [component uniqueChildWithTag: @"dtstart"];
firstStartDate = [dtstart dateTime];
firstEndDate = [firstStartDate addTimeInterval: [component occurenceInterval]];
firstRange = [NGCalendarDateRange calendarDateRangeWithStartDate: firstStartDate
@ -2655,7 +2656,7 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir
tz = nil;
element = [components objectAtIndex: i];
// Use the timezone of the start date.
startDate = (iCalDateTime *)[element uniqueChildWithTag: @"dtstart"];
startDate = (iCalDateTime *) [element uniqueChildWithTag: @"dtstart"];
if (startDate)
{
timezone = [startDate timeZone];

View File

@ -271,21 +271,16 @@
*/
- (NGCalendarDateRange *) firstOccurenceRange
{
iCalDateTime *firstStartDate;
NSCalendarDate *start, *end;
NGCalendarDateRange *firstRange;
firstRange = nil;
firstStartDate = (iCalDateTime *)[self uniqueChildWithTag: @"dtstart"];
if ([[firstStartDate values] count] > 0)
{
start = [[[firstStartDate values] lastObject] asCalendarDate];
end = [start addTimeInterval: [self occurenceInterval]];
start = [self startDate];
end = [start addTimeInterval: [self occurenceInterval]];
firstRange = [NGCalendarDateRange calendarDateRangeWithStartDate: start
endDate: end];
}
firstRange = [NGCalendarDateRange calendarDateRangeWithStartDate: start
endDate: end];
return firstRange;
}

View File

@ -27,10 +27,12 @@
#import <Foundation/NSTimeZone.h>
#import <NGCards/iCalDateTime.h>
#import <NGCards/iCalEvent.h>
#import <NGCards/iCalRecurrenceRule.h>
#import <NGCards/iCalRecurrenceCalculator.h>
#import <NGCards/iCalTimeZone.h>
#import <NGCards/NSString+NGCards.h>
#import <NGCards/NSDictionary+NGCards.h>
#import <NGExtensions/NGCalendarDateRange.h>
#import "iCalRepeatableEntityObject+SOGo.h"
@ -40,10 +42,12 @@
- (NSArray *) _indexedRules: (NSArray *) rules
{
NSMutableArray *ma;
unsigned int i, count;
NSString *valuesString;
NSUInteger i, count;
NSMutableString *ruleString;
iCalRecurrenceRule *rule;
#warning we could return an NSArray instead and feed it as such to the iCalRecurrenceRule in SOGoAppointmentFolder...
ma = nil;
count = [rules count];
@ -53,9 +57,11 @@
for (i = 0; i < count; i++)
{
rule = [rules objectAtIndex:i];
#warning we could return an NSArray instead and feed it as such to the iCalRecurrenceRule in SOGoAppointmentFolder...
valuesString = [[rule values] componentsJoinedByString: @";"];
[ma addObject: valuesString];
ruleString = [NSMutableString new];
[[rule values] versitRenderInString: ruleString
asAttributes: NO];
[ma addObject: ruleString];
[ruleString release];
}
}
@ -138,7 +144,7 @@
else
{
startDate = theOccurenceDate;
if ([self isAllDay])
if ([self isKindOfClass: [iCalEvent class]] && [(iCalEvent *) self isAllDay])
{
// The event lasts all-day and has no timezone (floating); we convert the range of the first event
// to the occurence's timezone.

View File

@ -38,6 +38,7 @@
NSArray *array;
NSMutableArray *marray;
NSMutableDictionary *entry;
CardElement *element;
id tmp;
entry = [NSMutableDictionary dictionary];
@ -49,13 +50,14 @@
@"organizationalPerson", @"inetOrgPerson",
@"mozillaAbPersonObsolete", nil]
forKey: @"objectclass"];
tmp = ([[self n] count] > 1 ? [[self n] objectAtIndex: 1] : nil);
if (tmp)
element = [self n];
tmp = [element flattenedValueAtIndex: 1 forKey: @""];
if ([tmp length] > 0)
[entry setObject: tmp forKey: @"givenName"];
tmp = ([[self n] count] ? [[self n] objectAtIndex: 0] : nil);
if (tmp)
tmp = [element flattenedValueAtIndex: 0 forKey: @""];
if ([tmp length] > 0)
[entry setObject: tmp forKey: @"sn"];
tmp = [self fn];
@ -74,11 +76,12 @@
marray = [NSMutableArray arrayWithArray: [self childrenWithTag: @"email"]];
[marray removeObjectsInArray: [self childrenWithTag: @"email"
andAttribute: @"type"
havingValue: @"pref"]];
andAttribute: @"type"
havingValue: @"pref"]];
if ([marray count])
{
buffer = [[marray objectAtIndex: [marray count]-1] value: 0];
buffer = [[marray objectAtIndex: [marray count]-1]
flattenedValuesForKey: @""];
if ([buffer caseInsensitiveCompare: [self preferredEMail]] != NSOrderedSame)
[entry setObject: buffer forKey: @"mozillaSecondEmail"];
@ -86,58 +89,75 @@
array = [self childrenWithTag: @"tel" andAttribute: @"type" havingValue: @"home"];
if ([array count])
[entry setObject: [[array objectAtIndex: 0] value: 0] forKey: @"homePhone"];
[entry setObject: [[array objectAtIndex: 0] flattenedValuesForKey: @""]
forKey: @"homePhone"];
array = [self childrenWithTag: @"tel" andAttribute: @"type" havingValue: @"fax"];
if ([array count])
[entry setObject: [[array objectAtIndex: 0] value: 0] forKey: @"fax"];
[entry setObject: [[array objectAtIndex: 0] flattenedValuesForKey: @""]
forKey: @"fax"];
array = [self childrenWithTag: @"tel" andAttribute: @"type" havingValue: @"cell"];
if ([array count])
[entry setObject: [[array objectAtIndex: 0] value: 0] forKey: @"mobile"];
[entry setObject: [[array objectAtIndex: 0] flattenedValuesForKey: @""]
forKey: @"mobile"];
array = [self childrenWithTag: @"tel" andAttribute: @"type" havingValue: @"pager"];
if ([array count])
[entry setObject: [[array objectAtIndex: 0] value: 0] forKey: @"pager"];
[entry setObject: [[array objectAtIndex: 0] flattenedValuesForKey: @""]
forKey: @"pager"];
array = [self childrenWithTag: @"adr" andAttribute: @"type" havingValue: @"home"];
if ([array count])
{
tmp = [array objectAtIndex: 0];
[entry setObject: [tmp value: 1] forKey: @"mozillaHomeStreet2"];
[entry setObject: [tmp value: 2] forKey: @"homeStreet"];
[entry setObject: [tmp value: 3] forKey: @"mozillaHomeLocalityName"];
[entry setObject: [tmp value: 4] forKey: @"mozillaHomeState"];
[entry setObject: [tmp value: 5] forKey: @"mozillaHomePostalCode"];
[entry setObject: [tmp value: 6] forKey: @"mozillaHomeCountryName"];
[entry setObject: [tmp flattenedValueAtIndex: 1 forKey: @""]
forKey: @"mozillaHomeStreet2"];
[entry setObject: [tmp flattenedValueAtIndex: 2 forKey: @""]
forKey: @"homeStreet"];
[entry setObject: [tmp flattenedValueAtIndex: 3 forKey: @""]
forKey: @"mozillaHomeLocalityName"];
[entry setObject: [tmp flattenedValueAtIndex: 4 forKey: @""]
forKey: @"mozillaHomeState"];
[entry setObject: [tmp flattenedValueAtIndex: 5 forKey: @""]
forKey: @"mozillaHomePostalCode"];
[entry setObject: [tmp flattenedValueAtIndex: 6 forKey: @""]
forKey: @"mozillaHomeCountryName"];
}
array = [self org];
if (array && [array count])
[entry setObject: [array objectAtIndex: 0] forKey: @"o"];
element = [self org];
tmp = [element flattenedValueAtIndex: 0 forKey: @""];
if ([tmp length] > 0)
[entry setObject: tmp forKey: @"o"];
array = [self childrenWithTag: @"adr" andAttribute: @"type" havingValue: @"work"];
if ([array count])
{
tmp = [array objectAtIndex: 0];
[entry setObject: [tmp value: 1] forKey: @"mozillaWorkStreet2"];
[entry setObject: [tmp value: 2] forKey: @"street"];
[entry setObject: [tmp value: 3] forKey: @"l"];
[entry setObject: [tmp value: 4] forKey: @"st"];
[entry setObject: [tmp value: 5] forKey: @"postalCode"];
[entry setObject: [tmp value: 6] forKey: @"c"];
[entry setObject: [tmp flattenedValueAtIndex: 1 forKey: @""]
forKey: @"mozillaWorkStreet2"];
[entry setObject: [tmp flattenedValueAtIndex: 2 forKey: @""]
forKey: @"street"];
[entry setObject: [tmp flattenedValueAtIndex: 3 forKey: @""]
forKey: @"l"];
[entry setObject: [tmp flattenedValueAtIndex: 4 forKey: @""]
forKey: @"st"];
[entry setObject: [tmp flattenedValueAtIndex: 5 forKey: @""]
forKey: @"postalCode"];
[entry setObject: [tmp flattenedValueAtIndex: 6 forKey: @""]
forKey: @"c"];
}
array = [self childrenWithTag: @"tel" andAttribute: @"type" havingValue: @"work"];
if ([array count])
[entry setObject: [[array objectAtIndex: 0] value: 0]
[entry setObject: [[array objectAtIndex: 0] flattenedValuesForKey: @""]
forKey: @"telephoneNumber"];
array = [self childrenWithTag: @"url" andAttribute: @"type" havingValue: @"work"];
if ([array count])
[entry setObject: [[array objectAtIndex: 0] value: 0]
[entry setObject: [[array objectAtIndex: 0] flattenedValuesForKey: @""]
forKey: @"workurl"];
array = [self childrenWithTag: @"url" andAttribute: @"type" havingValue: @"home"];
if ([array count])
[entry setObject: [[array objectAtIndex: 0] value: 0]
[entry setObject: [[array objectAtIndex: 0] flattenedValuesForKey: @""]
forKey: @"homeurl"];
tmp = [self note];

View File

@ -77,7 +77,8 @@
if ([photo isInline])
data = [photo decodedContent];
else
data = [[photo value: 0] dataUsingEncoding: NSISOLatin1StringEncoding];
data = [[photo flattenedValuesForKey: @""]
dataUsingEncoding: NSISOLatin1StringEncoding];
if (data)
{
response = [localContext response];

View File

@ -178,36 +178,34 @@
if (!country)
country = [ldifEntry objectForKey: @"countryname"];
element = [CardElement elementWithTag: @"adr"
attributes: nil values: nil];
element = [CardElement elementWithTag: @"adr"];
[element setValue: 0 ofAttribute: @"type" to: @"work"];
if (streetAddress)
[element setValue: 2 to: streetAddress];
[element setSingleValue: streetAddress atIndex: 2 forKey: @""];
if (location)
[element setValue: 3 to: location];
[element setSingleValue: location atIndex: 3 forKey: @""];
if (region)
[element setValue: 4 to: region];
[element setSingleValue: region atIndex: 4 forKey: @""];
if (postalCode)
[element setValue: 5 to: postalCode];
[element setSingleValue: postalCode atIndex: 5 forKey: @""];
if (country)
[element setValue: 6 to: country];
[element setSingleValue: country atIndex: 6 forKey: @""];
if (streetAddress || location || region || postalCode || country)
[vcard addChild: element];
// We handle the org/orgunit stuff
element = [CardElement elementWithTag: @"org"
attributes: nil values: nil];
element = [CardElement elementWithTag: @"org"];
org = [ldifEntry objectForKey: @"o"];
orgunit = [ldifEntry objectForKey: @"ou"];
if (!orgunit)
orgunit = [ldifEntry objectForKey: @"orgunit"];
if (org)
[element setValue: 0 to: org];
[element setSingleValue: org atIndex: 0 forKey: @""];
if (orgunit)
[element setValue: 1 to: orgunit];
[element setSingleValue: orgunit atIndex: 1 forKey: @""];
if (org || orgunit)
[vcard addChild: element];

View File

@ -43,42 +43,95 @@
/* 1. simple value */
element = [CardElement elementWithTag: @"elem"];
[element setValue: 0 to: @"value"];
[element setSingleValue: @"value" forKey: @""];
result = [renderer render: element];
testEquals(result, @"ELEM:value\r\n");
/* 2. two values */
element = [CardElement elementWithTag: @"elem"];
[element setValue: 0 to: @"value1"];
[element setValue: 1 to: @"value2"];
[element setSingleValue: @"value2" atIndex: 1
forKey: @""];
[element setSingleValue: @"value1" atIndex: 0
forKey: @""];
result = [renderer render: element];
testEquals(result, @"ELEM:value1;value2\r\n");
/* 3. one value with commma */
element = [CardElement elementWithTag: @"elem"];
[element setValue: 0 to: @"value1, with a comma"];
[element setSingleValue: @"value1, with a comma" forKey: @""];
result = [renderer render: element];
testEquals(result, @"ELEM:value1\\, with a comma\r\n");
/* 4. one value with a semicolon */
element = [CardElement elementWithTag: @"elem"];
[element setValue: 0 to: @"value1; with a semi-colon"];
[element setSingleValue: @"value1; with a semi-colon" forKey: @""];
result = [renderer render: element];
testEquals(result, @"ELEM:value1\\; with a semi-colon\r\n");
/* 4. 3 named values:
/* 5. 3 named values:
1. with multiple subvalues
2. with commas
3. with semicolon */
element = [CardElement elementWithTag: @"elem"];
[element setNamedValue: @"named1"
to: [NSArray arrayWithObjects: @"1", @"2", @"3", nil]];
[element setNamedValue: @"named2"
to: @"1,2,3"];
[element setNamedValue: @"named3"
to: @"text1;text2"];
[element setValues: [NSArray arrayWithObjects: @"1", @"2", @"3", nil]
atIndex: 0 forKey: @"named1"];
[element setSingleValue: @"1,2,3" forKey: @"named2"];
[element setSingleValue: @"text1;text2" forKey: @"named3"];
result = [renderer render: element];
testEquals(result, @"ELEM:NAMED1=1,2,3;NAMED2=1\\,2\\,3;NAMED3:text1\\;text2\r\n");
testEquals(result, @"ELEM:NAMED1=1,2,3;NAMED2=1\\,2\\,3;NAMED3=text1\\;text2\r\n");
/* 6. values with 1 ordered value with a whitespace starting subvalues */
element = [CardElement elementWithTag: @"elem"];
[element setValues: [NSArray arrayWithObjects: @"", @"1", nil]
atIndex: 0 forKey: @""];
result = [renderer render: element];
testEquals(result, @"ELEM:1\r\n");
/* 7. values with 1 ordered value with a subvalue, a whitespace and another subvalue */
element = [CardElement elementWithTag: @"elem"];
[element setValues: [NSArray arrayWithObjects: @"1", @"", @"2", nil]
atIndex: 0 forKey: @""];
result = [renderer render: element];
testEquals(result, @"ELEM:1,2\r\n");
/* 8.a. values with 1 empty ordered value and another non-empty one */
element = [CardElement elementWithTag: @"elem"];
[element setValues: [NSArray arrayWithObjects: nil]
atIndex: 0 forKey: @""];
[element setValues: [NSArray arrayWithObjects: @"1", nil]
atIndex: 1 forKey: @""];
result = [renderer render: element];
testEquals(result, @"ELEM:;1\r\n");
/* 8.b. a variant thereof: array with spaces */
[element setValues: [NSArray arrayWithObjects: @"", @"", nil]
atIndex: 0 forKey: @""];
result = [renderer render: element];
testEquals(result, @"ELEM:;1\r\n");
/* 8.c. a variant thereof: nil array */
[element setValues: nil atIndex: 0 forKey: @""];
result = [renderer render: element];
testEquals(result, @"ELEM:;1\r\n");
/* 9. values with 1 non-empty ordered value and another empty one */
element = [CardElement elementWithTag: @"elem"];
[element setValues: [NSArray arrayWithObjects: @"1", nil]
atIndex: 0 forKey: @""];
[element setValues: [NSArray arrayWithObjects: nil]
atIndex: 1 forKey: @""];
result = [renderer render: element];
testEquals(result, @"ELEM:1\r\n");
/* 10. named values with 1 nil value, 1 empty value and another non-nil one */
element = [CardElement elementWithTag: @"elem"];
[element setSingleValue: nil forKey: @"empty"];
[element setSingleValue: nil forKey: @"empty2"];
[element setSingleValue: @"coucou" forKey: @"nonempty"];
result = [renderer render: element];
testEquals(result, @"ELEM:NONEMPTY=coucou\r\n");
/** tests about parameters handling could be nice */
}
- (void) test_parsing
@ -87,52 +140,62 @@
CardElement *element;
NSString *versit;
versit = @"BEGIN:group1\r\nELEMENT:value\r\nEND:group1\r\n";
versit = @"BEGIN:GROUP1\r\nELEMENT:value\r\nEND:GROUP1";
group = [CardGroup parseSingleFromSource: versit];
testEquals([group versitString], versit);
element = [group firstChildWithTag: @"element"];
testEquals([element value: 0], @"value");
testEquals([element flattenedValueAtIndex: 0 forKey: @""], @"value");
versit = @"BEGIN:group1\r\nELEMENT:value1;value2\r\nEND:group1\r\n";
versit = @"BEGIN:GROUP1\r\nELEMENT:value1;value2\r\nEND:GROUP1";
group = [CardGroup parseSingleFromSource: versit];
testEquals([group versitString], versit);
element = [group firstChildWithTag: @"element"];
testEquals([element value: 0], @"value1");
testEquals([element value: 1], @"value2");
testEquals([element flattenedValueAtIndex: 0 forKey: @""], @"value1");
testEquals([element flattenedValueAtIndex: 1 forKey: @""], @"value2");
versit = @"BEGIN:group1\r\nELEMENT:value\\, with comma\r\nEND:group1\r\n";
versit = @"BEGIN:GROUP1\r\nELEMENT:value\\, with comma\r\nEND:GROUP1";
group = [CardGroup parseSingleFromSource: versit];
testEquals([group versitString], versit);
element = [group firstChildWithTag: @"element"];
testEquals([element value: 0], @"value, with comma");
testEquals([element flattenedValueAtIndex: 0 forKey: @""], @"value, with comma");
versit = @"BEGIN:group1\r\nELEMENT:value,with comma\r\nEND:group1\r\n";
versit = @"BEGIN:GROUP1\r\nELEMENT:value,with comma\r\nEND:GROUP1";
group = [CardGroup parseSingleFromSource: versit];
testEquals([group versitString], versit);
element = [group firstChildWithTag: @"element"];
testEquals([element value: 0], ([NSArray arrayWithObjects: @"value", @"with comma", nil]));
testEquals([element valuesAtIndex: 0 forKey: @""], ([NSArray arrayWithObjects: @"value", @"with comma", nil]));
versit = @"BEGIN:group1\r\nELEMENT:NAMED1=subvalue;NAMED2=subvalue1,subvalue2\r\nEND:group1\r\n";
versit = @"BEGIN:GROUP1\r\nELEMENT:NAMED1=subvalue;NAMED2=subvalue1,subvalue2\r\nEND:GROUP1";
group = [CardGroup parseSingleFromSource: versit];
/* we avoid this test here as nothing guarantees that the order of named
values will be preserved... */
// testEquals([group versitString], versit);
element = [group firstChildWithTag: @"element"];
testEquals([element namedValue: @"named1"], @"subvalue");
testEquals([element namedValue: @"named2"],
testEquals([element flattenedValueAtIndex: 0 forKey: @"NAMED1"], @"subvalue");
testEquals([element valuesAtIndex: 0 forKey: @"named2"],
([NSArray arrayWithObjects: @"subvalue1", @"subvalue2", nil]));
versit = @"BEGIN:group1\r\nELEMENT;PARAM1=test:value\r\nEND:group1\r\n";
versit = @"BEGIN:GROUP1\r\nELEMENT;PARAM1=test:value\r\nEND:GROUP1";
group = [CardGroup parseSingleFromSource: versit];
testEquals([group versitString], versit);
element = [group firstChildWithTag: @"element"];
testEquals([element value: 0], @"value");
testEquals([element flattenedValueAtIndex: 0 forKey: @""], @"value");
testEquals([element value: 0 ofAttribute: @"param1"], @"test");
versit = @"BEGIN:group1\r\nELEMENT;PARAM1=paramvalue1,paramvalue2:value\r\nEND:group1\r\n";
versit = @"BEGIN:GROUP1\r\nELEMENT;PARAM1=paramvalue1,paramvalue2:value\r\nEND:GROUP1";
group = [CardGroup parseSingleFromSource: versit];
testEquals([group versitString], versit);
element = [group firstChildWithTag: @"element"];
testEquals([element value: 0], @"value");
testEquals([element flattenedValueAtIndex: 0 forKey: @""], @"value");
testEquals([element value: 0 ofAttribute: @"param1"], @"paramvalue1");
testEquals([element value: 1 ofAttribute: @"param1"], @"paramvalue2");
versit = @"BEGIN:group1\r\nELEMENT;PARAM1=\"paramvalue1, with comma\":value\r\nEND:group1\r\n";
versit = @"BEGIN:GROUP1\r\nELEMENT;PARAM1=paramvalue1\\, with comma:value\r\nEND:GROUP1";
group = [CardGroup parseSingleFromSource: versit];
testEquals([group versitString], versit);
element = [group firstChildWithTag: @"element"];
testEquals([element value: 0], @"value");
testEquals([element value: 0 ofAttribute: @"param1"], @"value1, with comma");
testEquals([element flattenedValueAtIndex: 0 forKey: @""], @"value");
testEquals([element value: 0 ofAttribute: @"param1"], @"paramvalue1, with comma");
}
@end

View File

@ -64,7 +64,7 @@
cardReferences = [[self cardReferences] objectEnumerator];
while ((currentReference = [cardReferences nextObject]))
[cardNames addObject: [currentReference value: 0]];
[cardNames addObject: [currentReference flattenedValuesForKey: @""]];
return cardNames;
}

View File

@ -366,7 +366,7 @@
for (i = 0; i < [elements count]; i++)
{
ce = [elements objectAtIndex: i];
value = [ce value: 0];
value = [ce flattenedValuesForKey: @""];
if (!aTypeToExclude)
break;
@ -398,13 +398,13 @@
if (max > 0)
{
potential = [[elements objectAtIndex: 0] value: 0];
potential = [[elements objectAtIndex: 0] flattenedValuesForKey: @""];
if (!workMail)
{
if (homeMail && homeMail == potential)
{
if (max > 1)
workMail = [[elements objectAtIndex: 1] value: 0];
workMail = [[elements objectAtIndex: 1] flattenedValuesForKey: @""];
}
else
workMail = potential;
@ -412,7 +412,7 @@
if (!homeMail && max > 1)
{
if (workMail && workMail == potential)
homeMail = [[elements objectAtIndex: 1] value: 0];
homeMail = [[elements objectAtIndex: 1] flattenedValuesForKey: @""];
else
homeMail = potential;
}
@ -430,32 +430,32 @@
[self _setSnapshotValue: @"homeMail" to: homeMail];
[self _setSnapshotValue: @"mozillaUseHtmlMail"
to: [[card uniqueChildWithTag: @"x-mozilla-html"] value: 0]];
to: [[card uniqueChildWithTag: @"x-mozilla-html"] flattenedValuesForKey: @""]];
}
- (void) _setupOrgFields
{
NSMutableArray *orgServices;
NSArray *org;
NSRange aRange;
unsigned int max;
CardElement *org;
NSString *service;
NSUInteger count, max;
org = [card org];
max = [org count];
if (max > 0)
[self _setSnapshotValue: @"workCompany"
to: [org flattenedValueAtIndex: 0 forKey: @""]];
max = [[org valuesForKey: @""] count];
if (max > 1)
{
[self _setSnapshotValue: @"workCompany" to: [org objectAtIndex: 0]];
if (max > 1)
orgServices = [NSMutableArray arrayWithCapacity: max];
for (count = 1; count < max; count++)
{
aRange = NSMakeRange (1, max - 1);
orgServices = [NSMutableArray arrayWithArray: [org subarrayWithRange: aRange]];
while ([orgServices containsObject: @""])
[orgServices removeObject: @""];
[self _setSnapshotValue: @"workService"
to: [orgServices componentsJoinedByString: @", "]];
service = [org flattenedValueAtIndex: count forKey: @""];
if ([service length] > 0)
[orgServices addObject: service];
}
[self _setSnapshotValue: @"workService"
to: [orgServices componentsJoinedByString: @", "]];
}
}
@ -481,21 +481,14 @@
- (void) initSnapshot
{
NSArray *n, *elements;
NSArray *elements;
CardElement *element;
unsigned int max;
n = [card n];
if (n)
{
max = [n count];
if (max > 0)
{
[self _setSnapshotValue: @"sn" to: [n objectAtIndex: 0]];
if (max > 1)
[self _setSnapshotValue: @"givenName" to: [n objectAtIndex: 1]];
}
}
element = [card n];
[self _setSnapshotValue: @"sn"
to: [element flattenedValueAtIndex: 0 forKey: @""]];
[self _setSnapshotValue: @"givenName"
to: [element flattenedValueAtIndex: 1 forKey: @""]];
[self _setSnapshotValue: @"fn" to: [card fn]];
[self _setSnapshotValue: @"nickname" to: [card nickname]];
@ -538,7 +531,7 @@
[self _setupEmailFields];
[self _setSnapshotValue: @"screenName"
to: [[card uniqueChildWithTag: @"x-aim"] value: 0]];
to: [[card uniqueChildWithTag: @"x-aim"] flattenedValuesForKey: @""]];
elements = [card childrenWithTag: @"adr"
andAttribute: @"type" havingValue: @"work"];
@ -546,17 +539,17 @@
{
element = [elements objectAtIndex: 0];
[self _setSnapshotValue: @"workExtendedAddress"
to: [element value: 1]];
to: [element flattenedValueAtIndex: 1 forKey: @""]];
[self _setSnapshotValue: @"workStreetAddress"
to: [element value: 2]];
to: [element flattenedValueAtIndex: 2 forKey: @""]];
[self _setSnapshotValue: @"workCity"
to: [element value: 3]];
to: [element flattenedValueAtIndex: 3 forKey: @""]];
[self _setSnapshotValue: @"workState"
to: [element value: 4]];
to: [element flattenedValueAtIndex: 4 forKey: @""]];
[self _setSnapshotValue: @"workPostalCode"
to: [element value: 5]];
to: [element flattenedValueAtIndex: 5 forKey: @""]];
[self _setSnapshotValue: @"workCountry"
to: [element value: 6]];
to: [element flattenedValueAtIndex: 6 forKey: @""]];
}
elements = [card childrenWithTag: @"adr"
@ -565,17 +558,17 @@
{
element = [elements objectAtIndex: 0];
[self _setSnapshotValue: @"homeExtendedAddress"
to: [element value: 1]];
to: [element flattenedValueAtIndex: 1 forKey: @""]];
[self _setSnapshotValue: @"homeStreetAddress"
to: [element value: 2]];
to: [element flattenedValueAtIndex: 2 forKey: @""]];
[self _setSnapshotValue: @"homeCity"
to: [element value: 3]];
to: [element flattenedValueAtIndex: 3 forKey: @""]];
[self _setSnapshotValue: @"homeState"
to: [element value: 4]];
to: [element flattenedValueAtIndex: 4 forKey: @""]];
[self _setSnapshotValue: @"homePostalCode"
to: [element value: 5]];
to: [element flattenedValueAtIndex: 5 forKey: @""]];
[self _setSnapshotValue: @"homeCountry"
to: [element value: 6]];
to: [element flattenedValueAtIndex: 6 forKey: @""]];
}
elements = [card childrenWithTag: @"url"];
@ -591,7 +584,7 @@
[elements count] > 0)
{
[self _setSnapshotValue: @"homeURL"
to: [[elements objectAtIndex: 0] value: 0]];
to: [[elements objectAtIndex: 0] flattenedValuesForKey: @""]];
}
// If we do have a "work" URL but no "home" URL but two
// values URLs present, let's add the second one as the home URL
@ -603,11 +596,11 @@
for (i = 0; i < [elements count]; i++)
{
if ([[[elements objectAtIndex: i] value: 0]
if ([[[elements objectAtIndex: i] flattenedValuesForKey: @""]
caseInsensitiveCompare: [snapshot objectForKey: @"workURL"]] != NSOrderedSame)
{
[self _setSnapshotValue: @"homeURL"
to: [[elements objectAtIndex: i] value: 0]];
to: [[elements objectAtIndex: i] flattenedValuesForKey: @""]];
break;
}
}
@ -615,7 +608,7 @@
[self _setSnapshotValue: @"calFBURL"
to: [[card uniqueChildWithTag: @"FBURL"] value: 0]];
to: [[card uniqueChildWithTag: @"FBURL"] flattenedValuesForKey: @""]];
[self _setSnapshotValue: @"title" to: [card title]];
[self _setupOrgFields];
@ -686,7 +679,7 @@
photoURL = [NSString stringWithFormat: @"%@/photo%d",
baseInlineURL, count];
else
photoURL = [photo value: 0];
photoURL = [photo flattenedValuesForKey: @""];
[photosURL addObject: photoURL];
}
}
@ -721,17 +714,16 @@
CardElement *phone;
phone = [self _elementWithTag: @"tel" ofType: @"work"];
[phone setValue: 0 to: [snapshot objectForKey: @"telephoneNumber"]];
[phone setSingleValue: [snapshot objectForKey: @"telephoneNumber"] forKey: @""];
phone = [self _elementWithTag: @"tel" ofType: @"home"];
[phone setValue: 0 to: [snapshot objectForKey: @"homeTelephoneNumber"]];
[phone setSingleValue: [snapshot objectForKey: @"homeTelephoneNumber"] forKey: @""];
phone = [self _elementWithTag: @"tel" ofType: @"cell"];
[phone setValue: 0 to: [snapshot objectForKey: @"mobile"]];
[phone setSingleValue: [snapshot objectForKey: @"mobile"] forKey: @""];
phone = [self _elementWithTag: @"tel" ofType: @"fax"];
[phone setValue: 0
to: [snapshot objectForKey: @"facsimileTelephoneNumber"]];
[phone setSingleValue: [snapshot objectForKey: @"facsimileTelephoneNumber"]
forKey: @""];
phone = [self _elementWithTag: @"tel" ofType: @"pager"];
[phone setValue: 0
to: [snapshot objectForKey: @"pager"]];
[phone setSingleValue: [snapshot objectForKey: @"pager"] forKey: @""];
}
- (void) _saveEmails
@ -739,9 +731,9 @@
CardElement *workMail, *homeMail;
workMail = [self _elementWithTag: @"email" ofType: @"work"];
[workMail setValue: 0 to: [snapshot objectForKey: @"workMail"]];
[workMail setSingleValue: [snapshot objectForKey: @"workMail"] forKey: @""];
homeMail = [self _elementWithTag: @"email" ofType: @"home"];
[homeMail setValue: 0 to: [snapshot objectForKey: @"homeMail"]];
[homeMail setSingleValue: [snapshot objectForKey: @"homeMail"] forKey: @""];
if (preferredEmail)
{
if ([preferredEmail isEqualToString: @"work"])
@ -751,8 +743,8 @@
}
[[card uniqueChildWithTag: @"x-mozilla-html"]
setValue: 0
to: [snapshot objectForKey: @"mozillaUseHtmlMail"]];
setSingleValue: [snapshot objectForKey: @"mozillaUseHtmlMail"]
forKey: @""];
}
- (void) _saveSnapshot
@ -773,20 +765,32 @@
[card setTz: [snapshot objectForKey: @"tz"]];
element = [self _elementWithTag: @"adr" ofType: @"home"];
[element setValue: 1 to: [snapshot objectForKey: @"homeExtendedAddress"]];
[element setValue: 2 to: [snapshot objectForKey: @"homeStreetAddress"]];
[element setValue: 3 to: [snapshot objectForKey: @"homeCity"]];
[element setValue: 4 to: [snapshot objectForKey: @"homeState"]];
[element setValue: 5 to: [snapshot objectForKey: @"homePostalCode"]];
[element setValue: 6 to: [snapshot objectForKey: @"homeCountry"]];
[element setSingleValue: [snapshot objectForKey: @"homeExtendedAddress"]
atIndex: 1 forKey: @""];
[element setSingleValue: [snapshot objectForKey: @"homeStreetAddress"]
atIndex: 2 forKey: @""];
[element setSingleValue: [snapshot objectForKey: @"homeCity"]
atIndex: 3 forKey: @""];
[element setSingleValue: [snapshot objectForKey: @"homeState"]
atIndex: 4 forKey: @""];
[element setSingleValue: [snapshot objectForKey: @"homePostalCode"]
atIndex: 5 forKey: @""];
[element setSingleValue: [snapshot objectForKey: @"homeCountry"]
atIndex: 6 forKey: @""];
element = [self _elementWithTag: @"adr" ofType: @"work"];
[element setValue: 1 to: [snapshot objectForKey: @"workExtendedAddress"]];
[element setValue: 2 to: [snapshot objectForKey: @"workStreetAddress"]];
[element setValue: 3 to: [snapshot objectForKey: @"workCity"]];
[element setValue: 4 to: [snapshot objectForKey: @"workState"]];
[element setValue: 5 to: [snapshot objectForKey: @"workPostalCode"]];
[element setValue: 6 to: [snapshot objectForKey: @"workCountry"]];
[element setSingleValue: [snapshot objectForKey: @"workExtendedAddress"]
atIndex: 1 forKey: @""];
[element setSingleValue: [snapshot objectForKey: @"workStreetAddress"]
atIndex: 2 forKey: @""];
[element setSingleValue: [snapshot objectForKey: @"workCity"]
atIndex: 3 forKey: @""];
[element setSingleValue: [snapshot objectForKey: @"workState"]
atIndex: 4 forKey: @""];
[element setSingleValue: [snapshot objectForKey: @"workPostalCode"]
atIndex: 5 forKey: @""];
[element setSingleValue: [snapshot objectForKey: @"workCountry"]
atIndex: 6 forKey: @""];
element = [CardElement simpleElementWithTag: @"fburl"
value: [snapshot objectForKey: @"calFBURL"]];
@ -799,13 +803,13 @@
[self _savePhoneValues];
[self _saveEmails];
[[self _elementWithTag: @"url" ofType: @"home"]
setValue: 0 to: [snapshot objectForKey: @"homeURL"]];
setSingleValue: [snapshot objectForKey: @"homeURL"] forKey: @""];
[[self _elementWithTag: @"url" ofType: @"work"]
setValue: 0 to: [snapshot objectForKey: @"workURL"]];
setSingleValue: [snapshot objectForKey: @"workURL"] forKey: @""];
[[card uniqueChildWithTag: @"x-aim"]
setValue: 0
to: [snapshot objectForKey: @"screenName"]];
setSingleValue: [snapshot objectForKey: @"screenName"]
forKey: @""];
}
- (id <WOActionResults>) saveAction
@ -814,7 +818,6 @@
id result;
NSString *jsRefreshMethod;
SoSecurityManager *sm;
NSException *ex;
contact = [self clientObject];
card = [contact vCard];
@ -836,7 +839,7 @@
if (![sm validatePermission: SoPerm_AddDocumentsImagesAndFiles
onObject: componentAddressBook
inContext: context])
ex = [contact moveToFolder: (SOGoGCSFolder *)componentAddressBook]; // TODO: handle exception
[contact moveToFolder: (SOGoGCSFolder *)componentAddressBook]; // TODO: handle exception
}
}

View File

@ -58,14 +58,6 @@
/* accessors */
- (NSString *) _cardStringWithLabel: (NSString *) label
value: (NSString *) value
{
return [self _cardStringWithLabel: label
value: value
url: nil];
}
- (NSString *) _cardStringWithLabel: (NSString *) label
value: (NSString *) value
url: (NSString *) url
@ -89,6 +81,14 @@
return cardString;
}
- (NSString *) _cardStringWithLabel: (NSString *) label
value: (NSString *) value
{
return [self _cardStringWithLabel: label
value: value
url: nil];
}
- (NSString *) displayName
{
return [self _cardStringWithLabel: @"Display Name:"
@ -103,25 +103,24 @@
- (NSString *) fullName
{
NSArray *n;
NSString *fn;
unsigned int max;
CardElement *n;
NSString *fn, *firstName, *lastName;
fn = [card fn];
if ([fn length] == 0)
{
n = [card n];
if (n)
{
max = [n count];
if (max > 0)
{
if (max > 1)
fn = [NSString stringWithFormat: @"%@ %@", [n objectAtIndex: 1], [n objectAtIndex: 0]];
else
fn = [n objectAtIndex: 0];
}
}
lastName = [n flattenedValueAtIndex: 0 forKey: @""];
firstName = [n flattenedValueAtIndex: 1 forKey: @""];
if ([firstName length] > 0)
{
if ([lastName length] > 0)
fn = [NSString stringWithFormat: @"%@ %@", firstName, lastName];
else
fn = firstName;
}
else
fn = lastName;
}
return fn;
@ -172,7 +171,7 @@
for (i = 0; i < [emails count]; i++)
{
email = [[emails objectAtIndex: i] value: 0];
email = [[emails objectAtIndex: i] flattenedValuesForKey: @""];
if ([email caseInsensitiveCompare: [card preferredEMail]] != NSOrderedSame)
{
@ -192,7 +191,7 @@
{
NSString *screenName, *goim;
screenName = [[card uniqueChildWithTag: @"x-aim"] value: 0];
screenName = [[card uniqueChildWithTag: @"x-aim"] flattenedValuesForKey: @""];
if ([screenName length] > 0)
goim = [NSString stringWithFormat: @"<a href=\"aim:goim?screenname=%@\""
@">%@</a>", screenName, screenName];
@ -250,7 +249,7 @@
for (i = 0; i < [elements count]; i++)
{
ce = [elements objectAtIndex: i];
phone = [ce value: 0];
phone = [ce flattenedValuesForKey: @""];
if (!aTypeToExclude)
break;
@ -315,17 +314,23 @@
- (NSString *) homePobox
{
return [self _cardStringWithLabel: nil value: [homeAdr value: 0]];
return [self _cardStringWithLabel: nil
value: [homeAdr flattenedValueAtIndex: 0
forKey: @""]];
}
- (NSString *) homeExtendedAddress
{
return [self _cardStringWithLabel: nil value: [homeAdr value: 1]];
return [self _cardStringWithLabel: nil
value: [homeAdr flattenedValueAtIndex: 1
forKey: @""]];
}
- (NSString *) homeStreetAddress
{
return [self _cardStringWithLabel: nil value: [homeAdr value: 2]];
return [self _cardStringWithLabel: nil
value: [homeAdr flattenedValueAtIndex: 2
forKey: @""]];
}
- (NSString *) homeCityAndProv
@ -333,8 +338,8 @@
NSString *city, *prov;
NSMutableString *data;
city = [homeAdr value: 3];
prov = [homeAdr value: 4];
city = [homeAdr flattenedValueAtIndex: 3 forKey: @""];
prov = [homeAdr flattenedValueAtIndex: 4 forKey: @""];
data = [NSMutableString string];
[data appendString: city];
@ -350,8 +355,8 @@
NSString *postalCode, *country;
NSMutableString *data;
postalCode = [homeAdr value: 5];
country = [homeAdr value: 6];
postalCode = [homeAdr flattenedValueAtIndex: 5 forKey: @""];
country = [homeAdr flattenedValueAtIndex: 6 forKey: @""];
data = [NSMutableString string];
[data appendString: postalCode];
@ -391,7 +396,7 @@
andAttribute: @"type"
havingValue: aType];
if ([elements count] > 0)
url = [[elements objectAtIndex: 0] value: 0];
url = [[elements objectAtIndex: 0] flattenedValuesForKey: @""];
else
url = nil;
@ -416,7 +421,7 @@
workURL = nil;
if ([elements count] > 0)
workURL = [[elements objectAtIndex: 0] value: 0];
workURL = [[elements objectAtIndex: 0] flattenedValuesForKey: @""];
elements = [card childrenWithTag: @"url"];
@ -424,9 +429,10 @@
{
for (i = 0; i < [elements count]; i++)
{
if ([[[elements objectAtIndex: i] value: 0] caseInsensitiveCompare: workURL] != NSOrderedSame)
if ([[[elements objectAtIndex: i] flattenedValuesForKey: @""]
caseInsensitiveCompare: workURL] != NSOrderedSame)
{
s = [[elements objectAtIndex: i] value: 0];
s = [[elements objectAtIndex: i] flattenedValuesForKey: @""];
break;
}
}
@ -434,7 +440,7 @@
}
else if (!workURL && [elements count] > 0)
{
s = [[elements objectAtIndex: 0] value: 0];
s = [[elements objectAtIndex: 0] flattenedValuesForKey: @""];
}
if (s && [s length] > 0)
@ -474,18 +480,23 @@
- (NSString *) workService
{
NSMutableArray *orgServices;
NSArray *org;
NSRange aRange;
NSString *services;
NSArray *values;
CardElement *org;
NSString *service, *services;
NSUInteger count, max;
org = [card org];
if (org && [org count] > 1)
values = [org valuesForKey: @""];
max = [values count];
if (max > 1)
{
aRange = NSMakeRange(1, [org count]-1);
orgServices = [NSMutableArray arrayWithArray: [org subarrayWithRange: aRange]];
while ([orgServices containsObject: @""])
[orgServices removeObject: @""];
orgServices = [NSMutableArray arrayWithCapacity: max];
for (count = 1; count < max; count++)
{
service = [org flattenedValueAtIndex: count forKey: @""];
if ([service length] > 0)
[orgServices addObject: service];
}
services = [orgServices componentsJoinedByString: @", "];
}
@ -497,13 +508,12 @@
- (NSString *) workCompany
{
NSArray *org;
CardElement *org;
NSString *company;
org = [card org];
if (org && [org count] > 0)
company = [org objectAtIndex: 0];
else
company = [org flattenedValueAtIndex: 0 forKey: @""];
if ([company length] == 0)
company = nil;
return [self _cardStringWithLabel: nil value: company];
@ -511,17 +521,23 @@
- (NSString *) workPobox
{
return [self _cardStringWithLabel: nil value: [workAdr value: 0]];
return [self _cardStringWithLabel: nil
value: [workAdr flattenedValueAtIndex: 0
forKey: @""]];
}
- (NSString *) workExtendedAddress
{
return [self _cardStringWithLabel: nil value: [workAdr value: 1]];
return [self _cardStringWithLabel: nil
value: [workAdr flattenedValueAtIndex: 1
forKey: @""]];
}
- (NSString *) workStreetAddress
{
return [self _cardStringWithLabel: nil value: [workAdr value: 2]];
return [self _cardStringWithLabel: nil
value: [workAdr flattenedValueAtIndex: 2
forKey: @""]];
}
- (NSString *) workCityAndProv
@ -529,8 +545,8 @@
NSString *city, *prov;
NSMutableString *data;
city = [workAdr value: 3];
prov = [workAdr value: 4];
city = [workAdr flattenedValueAtIndex: 3 forKey: @""];
prov = [workAdr flattenedValueAtIndex: 4 forKey: @""];
data = [NSMutableString string];
[data appendString: city];
@ -546,8 +562,8 @@
NSString *postalCode, *country;
NSMutableString *data;
postalCode = [workAdr value: 5];
country = [workAdr value: 6];
postalCode = [workAdr flattenedValueAtIndex: 5 forKey: @""];
country = [workAdr flattenedValueAtIndex: 6 forKey: @""];
data = [NSMutableString string];
[data appendString: postalCode];
@ -681,7 +697,7 @@
photoURL = [NSString stringWithFormat: @"%@/photo%d",
baseInlineURL, count];
else
photoURL = [photo value: 0];
photoURL = [photo flattenedValuesForKey: @""];
[photosURL addObject: photoURL];
}
}

View File

@ -184,7 +184,7 @@
[newWorkMail setTag: @"email"];
[newWorkMail addType: @"work"];
[newCard addChild: newWorkMail];
[newWorkMail setValue: 0 to: workMail];
[newWorkMail setSingleValue: workMail forKey: @""];
[newCard setFn: fn];
// Add vCard to current folder

View File

@ -268,10 +268,9 @@
- (NSString *) formattedMailtoString: (NGVCard *) card
{
NSString *email;
NSString *firstName, *lastName, *email;
NSMutableString *fn, *rc = nil;
NSArray *n;
unsigned int max;
CardElement *n;
if ([card isKindOfClass: [NGVCard class]])
email = [card preferredEMail];
@ -291,17 +290,17 @@
&& [card isKindOfClass: [NGVCard class]])
{
n = [card n];
if (n)
lastName = [n flattenedValueAtIndex: 0 forKey: @""];
firstName = [n flattenedValueAtIndex: 1 forKey: @""];
if ([firstName length] > 0)
{
max = [n count];
if (max > 0)
{
if (max > 1)
fn = [NSMutableString stringWithFormat: @"%@ %@", [n objectAtIndex: 1], [n objectAtIndex: 0]];
else
fn = [NSMutableString stringWithString: [n objectAtIndex: 0]];
}
if ([lastName length] > 0)
fn = [NSMutableString stringWithFormat: @"%@ %@", firstName, lastName];
else
fn = [NSMutableString stringWithString: firstName];
}
else if ([lastName length] > 0)
fn = [NSMutableString stringWithString: lastName];
}
if ([fn length] > 0)
{

View File

@ -292,13 +292,13 @@ iRANGE(2);
- (void) _loadCategories
{
NSString *compCategories, *simpleCategory;
NSString *simpleCategory;
NSArray *compCategories;
compCategories = [component categories];
if ([compCategories length] > 0)
if ([compCategories count] > 0)
{
simpleCategory = [[compCategories componentsSeparatedByString: @","]
objectAtIndex: 0];
simpleCategory = [compCategories objectAtIndex: 0];
ASSIGN (category, simpleCategory);
}
}
@ -405,7 +405,7 @@ iRANGE(2);
{
repeatType = @"3";
if ([[rule namedValue: @"bymonth"] length])
if ([[rule flattenedValuesForKey: @"bymonth"] length])
{
if ([[rule byDay] length])
{
@ -420,13 +420,13 @@ iRANGE(2);
[self setRepeat2: @"1"];
[self setRepeat5: [NSString stringWithFormat: @"%d", firstOccurrence]];
[self setRepeat6: [NSString stringWithFormat: @"%d", [dayMask firstDay]]];
[self setRepeat7: [NSString stringWithFormat: @"%d", [[rule namedValue: @"bymonth"] intValue]-1]];
[self setRepeat7: [NSString stringWithFormat: @"%d", [[rule flattenedValuesForKey: @"bymonth"] intValue]-1]];
}
else
{
[self setRepeat2: @"0"];
[self setRepeat3: [rule namedValue: @"bymonthday"]];
[self setRepeat4: [NSString stringWithFormat: @"%d", [[rule namedValue: @"bymonth"] intValue]-1]];
[self setRepeat3: [rule flattenedValuesForKey: @"bymonthday"]];
[self setRepeat4: [NSString stringWithFormat: @"%d", [[rule flattenedValuesForKey: @"bymonth"] intValue]-1]];
}
}
else if ([rule repeatInterval] == 1)
@ -440,7 +440,7 @@ iRANGE(2);
{
repeat = @"CUSTOM";
[self setRange1: @"1"];
[self setRange2: [rule namedValue: @"count"]];
[self setRange2: [rule flattenedValuesForKey: @"count"]];
}
else if ([rule untilDate])
{
@ -519,7 +519,7 @@ iRANGE(2);
|| [reminderAction isEqualToString: @"email"])
&& [[aTrigger valueType] caseInsensitiveCompare: @"DURATION"] == NSOrderedSame)
{
duration = [aTrigger value];
duration = [aTrigger flattenedValuesForKey: @""];
i = [reminderValues indexOfObject: duration];
if (i == NSNotFound || [reminderAction isEqualToString: @"email"])
@ -611,8 +611,7 @@ iRANGE(2);
ASSIGN (privacy, [component accessClass]);
ASSIGN (priority, [component priority]);
ASSIGN (status, [component status]);
ASSIGN (categories,
[[component categories] vCardSubvaluesWithSeparator: ',']);
ASSIGN (categories, [component categories]);
if ([[[component organizer] rfc822Email] length])
{
ASSIGN (organizer, [component organizer]);
@ -1853,6 +1852,7 @@ RANGE(2);
{
int type, range;
NSMutableArray *values;
// We decode the range
range = [[self range1] intValue];
@ -1990,14 +1990,21 @@ RANGE(2);
occurence = [[self repeat3] intValue] + 1;
if (occurence > 5) // the first/second/third/fourth/fifth ..
occurence = -1; // the last ..
[theRule setNamedValue: @"byday"
to: [NSString stringWithFormat: @"%d%@",
occurence, day]];
[theRule setSingleValue: [NSString stringWithFormat: @"%d%@",
occurence, day]
forKey: @"byday"];
}
else
{
if ([[self repeat5] intValue] > 0)
[theRule setNamedValue: @"bymonthday" to: [self repeat5]];
{
values = [[[self repeat5]
componentsSeparatedByString: @","]
mutableCopy];
[theRule setValues: values
atIndex: 0 forKey: @"bymonthday"];
[values release];
}
}
}
}
@ -2037,22 +2044,27 @@ RANGE(2);
occurence = [[self repeat5] intValue] + 1;
if (occurence > 5) // the first/second/third/fourth/fifth ..
occurence = -1; // the last ..
[theRule setNamedValue: @"byday"
to: [NSString stringWithFormat: @"%d%@",
occurence, day]];
[theRule setNamedValue: @"bymonth"
to: [NSString stringWithFormat: @"%d",
[[self repeat7] intValue] + 1]];
[theRule setSingleValue: [NSString stringWithFormat: @"%d%@",
occurence, day]
forKey: @"byday"];
[theRule setSingleValue: [NSString stringWithFormat: @"%d",
[[self repeat7] intValue] + 1]
forKey: @"bymonth"];
}
else
{
if ([[self repeat3] intValue] > 0
&& [[self repeat4] intValue] > 0)
{
[theRule setNamedValue: @"bymonthday"
to: [self repeat3]];
[theRule setNamedValue: @"bymonth"
to: [NSString stringWithFormat: @"%d", ([[self repeat4] intValue]+1)]];
values = [[[self repeat3]
componentsSeparatedByString: @","]
mutableCopy];
[theRule setValues: values atIndex: 0
forKey: @"bymonthday"];
[values release];
[theRule setSingleValue: [NSString stringWithFormat: @"%d",
[[self repeat4] intValue] + 1]
forKey: @"bymonth"];
}
}
}
@ -2111,7 +2123,7 @@ RANGE(2);
[component setComment: comment];
[component setAttach: attachUrl];
[component setAccessClass: privacy];
[component setCategories: category];
[component setCategories: categories];
[self _handleAttendeesEdition];
[self _handleOrganizer];
clientObject = [self clientObject];
@ -2146,7 +2158,7 @@ RANGE(2);
if ([aValue length]) {
// Predefined alarm
[anAlarm setAction: @"DISPLAY"];
[aTrigger setValue: aValue];
[aTrigger setSingleValue: aValue forKey: @""];
}
else {
// Custom alarm
@ -2177,7 +2189,7 @@ RANGE(2);
aValue = [aValue stringByAppendingFormat: @"%i%@",
[reminderQuantity intValue],
[reminderUnit substringToIndex: 1]];
[aTrigger setValue: aValue];
[aTrigger setSingleValue: aValue forKey: @""];
[aTrigger setRelationType: reminderRelation];
}
else