diff --git a/ChangeLog b/ChangeLog index 67ea08d68..935d2b160 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,71 @@ +2011-01-11 Ludovic Marcotte + + * OpenChange/MAPIStoreContactsMessageTable.m + Added more properties: home/work URL, nickname + and department. + +2011-01-11 Wolfgang Sourdeau + + * OpenChange/SOGoTaskObject+MAPIStore.m (-setMAPIProperties): + release fullCalendar and safeCalendar to force a rebuild of + the root object when next requested. + + * OpenChange/SOGoAppointmentObject+MAPIStore.m (-setMAPIProperties): + idem. + + * OpenChange/MAPIStoreContext.m + (-createMessagePropertiesWithMID:inFID:isAssociated:): added a + retain count handling. + (-releaseRecordWithFMID:ofTableType:): same as above. + (-_saveOrSubmitChangesInMessageWithMID:andFlags:save:): cleanup + table caches even for modifications. + + * OpenChange/MAPIStoreMessageTable.m + (-getChildProperty:forKey:withTag:): fixed PR_ACCESS and + PR_ACCESS_LEVEL to avoid displaying the "read-only" status. + + * OpenChange/MAPIStoreTable.m (-cleanupCaches): remove lastChild + from cache too. + + * OpenChange/MAPIStoreTasksMessageTable.m + (-getChildProperty:forKey:withTag:): fixed typo affecting + PidLidTaskStatus. + + * OpenChange/MAPIStoreContext.m (-openMessage:withMID:inFID:): + create a message dictionary in the message cache in order to + enable modifications. + + * OpenChange/MAPIStoreContactsMessageTable.m + (-_element:ofType:excluding:inCard:): new version of the previous + -_phoneOfType:excluding:inCard: method, which now returns the + requested element rather than it's first value and which enables + the specification of the tag. + (-getChildProperty:forKey:withTag:): added support for + PidLidPostalAddressId, PR_POSTAL_ADDRESS_UNICODE, + PR_POST_OFFICE_BOX_UNICODE, PR_STREET_ADDRESS_UNICODE, + PR_LOCALITY_UNICODE, PR_STATE_OR_PROVINCE_UNICODE, + PR_POSTAL_CODE_UNICODE, PR_COUNTRY_UNICODE, PidLidWorkAddress, + PidLidWorkAddressPostOfficeBox, PidLidWorkAddressStreet, + PidLidWorkAddressCity, PidLidWorkAddressState, + PidLidWorkAddressPostalCode and PidLidWorkAddressCountry. + + * OpenChange/MAPIStoreContext.m (-openMessage:forKey:inTable:): + avoid taking NULL values into account when returning the basic + properties. + + * OpenChange/SOGoContactGCSEntry+MAPIStore.m + (-setMAPIProperties:): added support for work address and its + corresponding addresse label. Preliminary support for + "PidLidPostalAddressId" which enables us to set a certain address + as preferred. + Carefully replace existing handled fields to avoid removing them + during modification. + +2011-01-10 Wolfgang Sourdeau + + * OpenChange/MAPIStoreContext.m (-typeLessTag:): removed method as + types are now determined from openchange core. + 2011-01-07 Wolfgang Sourdeau * OpenChange/MAPIStoreContext.m (_typeLessTag:): new method diff --git a/OpenChange/MAPIStoreContactsMessageTable.m b/OpenChange/MAPIStoreContactsMessageTable.m index f7f847d1a..c4dd5ffe6 100644 --- a/OpenChange/MAPIStoreContactsMessageTable.m +++ b/OpenChange/MAPIStoreContactsMessageTable.m @@ -53,45 +53,30 @@ return componentQualifier; } -- (NSString *) _phoneOfType: (NSString *) aType - excluding: (NSString *) aTypeToExclude - inCard: (NGVCard *) card +- (CardElement *) _element: (NSString *) elementTag + ofType: (NSString *) aType + excluding: (NSString *) aTypeToExclude + inCard: (NGVCard *) card { NSArray *elements; - NSArray *phones; - NSString *phone; + CardElement *ce, *found; + NSUInteger count, max; - phones = [card childrenWithTag: @"tel"]; + found = nil; - elements = [phones cardElementsWithAttribute: @"type" - havingValue: aType]; - - phone = nil; - - if ([elements count] > 0) + elements = [[card childrenWithTag: elementTag] + cardElementsWithAttribute: @"type" + havingValue: aType]; + max = [elements count]; + for (count = 0; !found && count < max; count++) { - CardElement *ce; - int i; - - for (i = 0; i < [elements count]; i++) - { - ce = [elements objectAtIndex: i]; - phone = [ce value: 0]; - - if (!aTypeToExclude) - break; - - if (![ce hasAttribute: @"type" havingValue: aTypeToExclude]) - break; - - phone = nil; - } + ce = [elements objectAtIndex: count]; + if (!aTypeToExclude + || ![ce hasAttribute: @"type" havingValue: aTypeToExclude]) + found = ce; } - if (!phone) - phone = @""; - - return phone; + return found; } - (enum MAPISTATUS) getChildProperty: (void **) data @@ -100,6 +85,8 @@ { NSString *stringValue; SOGoContactGCSEntry *child; + CardElement *element; + uint32_t longValue; enum MAPISTATUS rc; rc = MAPI_E_SUCCESS; @@ -134,10 +121,23 @@ break; case PR_COMPANY_NAME_UNICODE: - child = [self lookupChild: childKey]; - /* that's buggy but it's for the demo */ - stringValue = [[[child vCard] org] componentsJoinedByString: @", "]; - *data = [stringValue asUnicodeInMemCtx: memCtx]; + case PR_DEPARTMENT_NAME_UNICODE: + { + NSArray *values; + + child = [self lookupChild: childKey]; + values = [[child vCard] org]; + stringValue = nil; + + if (proptag == PR_COMPANY_NAME_UNICODE && [values count] > 0) + stringValue = [values objectAtIndex: 0]; + else if (proptag == PR_DEPARTMENT_NAME_UNICODE && [values count] > 1) + stringValue = [values objectAtIndex: 1]; + + if (!stringValue) + stringValue = @""; + *data = [stringValue asUnicodeInMemCtx: memCtx]; + } break; case PR_SUBJECT_UNICODE: @@ -160,39 +160,258 @@ case PR_OFFICE_TELEPHONE_NUMBER_UNICODE: child = [self lookupChild: childKey]; - stringValue = [self _phoneOfType: @"work" - excluding: @"fax" - inCard: [child vCard]]; + element = [self _element: @"phone" ofType: @"work" + excluding: @"fax" + inCard: [child vCard]]; + if (element) + stringValue = [element value: 0]; + else + stringValue = @""; *data = [stringValue asUnicodeInMemCtx: memCtx]; break; case PR_HOME_TELEPHONE_NUMBER_UNICODE: child = [self lookupChild: childKey]; - stringValue = [self _phoneOfType: @"home" - excluding: @"fax" - inCard: [child vCard]]; + element = [self _element: @"phone" ofType: @"home" + excluding: @"fax" + inCard: [child vCard]]; + if (element) + stringValue = [element value: 0]; + else + stringValue = @""; *data = [stringValue asUnicodeInMemCtx: memCtx]; break; case PR_MOBILE_TELEPHONE_NUMBER_UNICODE: child = [self lookupChild: childKey]; - stringValue = [self _phoneOfType: @"cell" - excluding: nil - inCard: [child vCard]]; + element = [self _element: @"phone" ofType: @"cell" + excluding: nil + inCard: [child vCard]]; + if (element) + stringValue = [element value: 0]; + else + stringValue = @""; *data = [stringValue asUnicodeInMemCtx: memCtx]; break; case PR_PRIMARY_TELEPHONE_NUMBER_UNICODE: child = [self lookupChild: childKey]; - stringValue = [self _phoneOfType: @"pref" - excluding: nil - inCard: [child vCard]]; + element = [self _element: @"phone" ofType: @"pref" + excluding: nil + inCard: [child vCard]]; + if (element) + stringValue = [element value: 0]; + else + stringValue = @""; *data = [stringValue asUnicodeInMemCtx: memCtx]; break; + case PR_BUSINESS_HOME_PAGE_UNICODE: + case PR_PERSONAL_HOME_PAGE_UNICODE: + { + NSString *type; + + type = (proptag == PR_BUSINESS_HOME_PAGE_UNICODE ? @"work" : @"home"); + + child = [self lookupChild: childKey]; + + element = [self _element: @"url" ofType: type + excluding: nil + inCard: [child vCard]]; + if (element) + stringValue = [element value: 0]; + else + stringValue = @""; + *data = [stringValue asUnicodeInMemCtx: memCtx]; + } + break; + case PidLidEmail1AddressType: case PidLidEmail2AddressType: case PidLidEmail3AddressType: *data = [@"SMTP" asUnicodeInMemCtx: memCtx]; break; + case PidLidPostalAddressId: + child = [self lookupChild: childKey]; + element = [self _element: @"adr" ofType: @"pref" + excluding: nil + inCard: [child vCard]]; + if ([element hasAttribute: @"type" + havingValue: @"home"]) + longValue = 1; + else if ([element hasAttribute: @"type" + havingValue: @"work"]) + longValue = 2; + else + longValue = 0; + *data = MAPILongValue (memCtx, longValue); + break; + + /* preferred address */ + case PR_POSTAL_ADDRESS_UNICODE: + child = [self lookupChild: childKey]; + element = [self _element: @"label" ofType: @"pref" + excluding: nil + inCard: [child vCard]]; + if (element) + stringValue = [element value: 0]; + else + stringValue = @""; + *data = [stringValue asUnicodeInMemCtx: memCtx]; + break; + case PR_POST_OFFICE_BOX_UNICODE: + child = [self lookupChild: childKey]; + element = [self _element: @"adr" ofType: @"pref" + excluding: nil + inCard: [child vCard]]; + if (element) + stringValue = [element value: 0]; + else + stringValue = @""; + *data = [stringValue asUnicodeInMemCtx: memCtx]; + break; + case PR_STREET_ADDRESS_UNICODE: + child = [self lookupChild: childKey]; + element = [self _element: @"adr" ofType: @"pref" + excluding: nil + inCard: [child vCard]]; + if (element) + stringValue = [element value: 2]; + else + stringValue = @""; + *data = [stringValue asUnicodeInMemCtx: memCtx]; + break; + case PR_LOCALITY_UNICODE: + child = [self lookupChild: childKey]; + element = [self _element: @"adr" ofType: @"pref" + excluding: nil + inCard: [child vCard]]; + if (element) + stringValue = [element value: 3]; + else + stringValue = @""; + *data = [stringValue asUnicodeInMemCtx: memCtx]; + break; + case PR_STATE_OR_PROVINCE_UNICODE: + child = [self lookupChild: childKey]; + element = [self _element: @"adr" ofType: @"pref" + excluding: nil + inCard: [child vCard]]; + if (element) + stringValue = [element value: 4]; + else + stringValue = @""; + *data = [stringValue asUnicodeInMemCtx: memCtx]; + break; + case PR_POSTAL_CODE_UNICODE: + child = [self lookupChild: childKey]; + element = [self _element: @"adr" ofType: @"pref" + excluding: nil + inCard: [child vCard]]; + if (element) + stringValue = [element value: 5]; + else + stringValue = @""; + *data = [stringValue asUnicodeInMemCtx: memCtx]; + break; + case PR_COUNTRY_UNICODE: + child = [self lookupChild: childKey]; + element = [self _element: @"adr" ofType: @"pref" + excluding: nil + inCard: [child vCard]]; + if (element) + stringValue = [element value: 6]; + else + stringValue = @""; + *data = [stringValue asUnicodeInMemCtx: memCtx]; + break; + + // case PidLidAddressCountryCode: + + case PidLidWorkAddress: + child = [self lookupChild: childKey]; + element = [self _element: @"label" ofType: @"work" + excluding: nil + inCard: [child vCard]]; + if (element) + stringValue = [element value: 0]; + else + stringValue = @""; + *data = [stringValue asUnicodeInMemCtx: memCtx]; + break; + + case PidLidWorkAddressPostOfficeBox: + child = [self lookupChild: childKey]; + element = [self _element: @"adr" ofType: @"work" + excluding: nil + inCard: [child vCard]]; + if (element) + stringValue = [element value: 0]; + else + stringValue = @""; + *data = [stringValue asUnicodeInMemCtx: memCtx]; + break; + case PidLidWorkAddressStreet: + child = [self lookupChild: childKey]; + element = [self _element: @"adr" ofType: @"work" + excluding: nil + inCard: [child vCard]]; + if (element) + stringValue = [element value: 2]; + else + stringValue = @""; + *data = [stringValue asUnicodeInMemCtx: memCtx]; + break; + case PidLidWorkAddressCity: + child = [self lookupChild: childKey]; + element = [self _element: @"adr" ofType: @"work" + excluding: nil + inCard: [child vCard]]; + if (element) + stringValue = [element value: 3]; + else + stringValue = @""; + *data = [stringValue asUnicodeInMemCtx: memCtx]; + break; + case PidLidWorkAddressState: + child = [self lookupChild: childKey]; + element = [self _element: @"adr" ofType: @"work" + excluding: nil + inCard: [child vCard]]; + if (element) + stringValue = [element value: 4]; + else + stringValue = @""; + *data = [stringValue asUnicodeInMemCtx: memCtx]; + break; + case PidLidWorkAddressPostalCode: + child = [self lookupChild: childKey]; + element = [self _element: @"adr" ofType: @"work" + excluding: nil + inCard: [child vCard]]; + if (element) + stringValue = [element value: 5]; + else + stringValue = @""; + *data = [stringValue asUnicodeInMemCtx: memCtx]; + break; + case PidLidWorkAddressCountry: + child = [self lookupChild: childKey]; + element = [self _element: @"adr" ofType: @"work" + excluding: nil + inCard: [child vCard]]; + if (element) + stringValue = [element value: 6]; + else + stringValue = @""; + *data = [stringValue asUnicodeInMemCtx: memCtx]; + break; + + // PidTagNickname + case PR_NICKNAME_UNICODE: + child = [self lookupChild: childKey]; + stringValue = [[child vCard] nickname]; + *data = [stringValue asUnicodeInMemCtx: memCtx]; + break; + default: rc = [super getChildProperty: data forKey: childKey diff --git a/OpenChange/MAPIStoreContext.m b/OpenChange/MAPIStoreContext.m index f072ad9bc..e4dd38f7c 100644 --- a/OpenChange/MAPIStoreContext.m +++ b/OpenChange/MAPIStoreContext.m @@ -803,11 +803,13 @@ _prepareContextClass (struct mapistore_context *newMemCtx, @" returned for proptag %s(0x%.8x)", propName, tags[count]]; } - - set_SPropValue_proptag (properties->lpProps + properties->cValues, - tags[count], - propValue); - properties->cValues++; + else + { + set_SPropValue_proptag (properties->lpProps + properties->cValues, + tags[count], + propValue); + properties->cValues++; + } } } msg->properties = properties; @@ -821,6 +823,7 @@ _prepareContextClass (struct mapistore_context *newMemCtx, { NSString *childURL, *childKey, *folderURL; MAPIStoreTable *table; + BOOL isAssociated; int rc; childURL = [mapping urlFromID: mid]; @@ -830,9 +833,13 @@ _prepareContextClass (struct mapistore_context *newMemCtx, andFolderURLAt: &folderURL]; table = [self _tableForFID: fid andTableType: MAPISTORE_FAI_TABLE]; if ([[table cachedChildKeys] containsObject: childKey]) - rc = [self openMessage: msg forKey: childKey inTable: table]; + { + isAssociated = YES; + rc = [self openMessage: msg forKey: childKey inTable: table]; + } else { + isAssociated = NO; table = [self _tableForFID: fid andTableType: MAPISTORE_MESSAGE_TABLE]; if ([[table cachedChildKeys] containsObject: childKey]) rc = [self openMessage: msg forKey: childKey inTable: table]; @@ -843,6 +850,11 @@ _prepareContextClass (struct mapistore_context *newMemCtx, else rc = MAPISTORE_ERR_NOT_FOUND; + if (rc == MAPI_E_SUCCESS) + [self createMessagePropertiesWithMID: mid + inFID: fid + isAssociated: isAssociated]; + return rc; } @@ -850,20 +862,39 @@ _prepareContextClass (struct mapistore_context *newMemCtx, inFID: (uint64_t) fid isAssociated: (BOOL) isAssociated { - NSMutableDictionary *newMessage; + NSMutableDictionary *messageProperties; NSNumber *midNbr; + NSUInteger retainCount; - [self logWithFormat: @"METHOD '%s' -- mid: 0x%.16x, fid: 0x%.16x", - __FUNCTION__, mid, fid]; - newMessage = [NSMutableDictionary new]; - [newMessage setObject: [NSNumber numberWithUnsignedLongLong: fid] - forKey: @"fid"]; - midNbr = [NSNumber numberWithUnsignedLongLong: mid]; - [newMessage setObject: midNbr forKey: @"mid"]; - [newMessage setObject: [NSNumber numberWithBool: isAssociated] - forKey: @"associated"]; - [messages setObject: newMessage forKey: midNbr]; - [newMessage release]; + messageProperties = [messages objectForKey: + [NSNumber numberWithUnsignedLongLong: mid]]; + if (messageProperties) + { + [self logWithFormat: + @"METHOD '%s' -- mid: 0x%.16x, fid: 0x%.16x; retainCount++", + __FUNCTION__, mid, fid]; + retainCount = [[messageProperties objectForKey: @"mapiRetainCount"] + unsignedIntValue]; + [messageProperties + setObject: [NSNumber numberWithUnsignedInt: retainCount + 1] + forKey: @"mapiRetainCount"]; + } + else + { + [self logWithFormat: @"METHOD '%s' -- mid: 0x%.16x, fid: 0x%.16x", + __FUNCTION__, mid, fid]; + messageProperties = [NSMutableDictionary new]; + [messageProperties setObject: [NSNumber numberWithUnsignedLongLong: fid] + forKey: @"fid"]; + midNbr = [NSNumber numberWithUnsignedLongLong: mid]; + [messageProperties setObject: midNbr forKey: @"mid"]; + [messageProperties setObject: [NSNumber numberWithBool: isAssociated] + forKey: @"associated"]; + [messageProperties setObject: [NSNumber numberWithInt: 1] + forKey: @"mapiRetainCount"]; + [messages setObject: messageProperties forKey: midNbr]; + [messageProperties release]; + } return MAPISTORE_SUCCESS; } @@ -928,42 +959,36 @@ _prepareContextClass (struct mapistore_context *newMemCtx, NSMutableDictionary *messageProperties; NSString *messageURL; uint64_t fid; - BOOL viewMessage; + BOOL associated; - viewMessage = NO; messageProperties = [messages objectForKey: [NSNumber numberWithUnsignedLongLong: mid]]; if (messageProperties) { messageURL = [mapping urlFromID: mid]; - if ([[messageProperties objectForKey: @"associated"] boolValue]) + associated = [[messageProperties objectForKey: @"associated"] boolValue]; + if (messageURL) { - if (messageURL) + if (associated) message = [self lookupFAIObject: messageURL]; else - { - fid = [[messageProperties objectForKey: @"fid"] - unsignedLongLongValue]; - message = [self _createMessageOfClass: [messageProperties objectForKey: MAPIPropertyKey (PR_MESSAGE_CLASS_UNICODE)] - associated: YES - withMID: mid inFID: fid]; - } + message = [self lookupObject: messageURL]; } else { - if (messageURL) - message = [self lookupObject: messageURL]; - else - { - fid = [[messageProperties objectForKey: @"fid"] - unsignedLongLongValue]; - message = [self _createMessageOfClass: [messageProperties objectForKey: MAPIPropertyKey (PR_MESSAGE_CLASS_UNICODE)] - associated: NO - withMID: mid inFID: fid]; - } + fid = [[messageProperties objectForKey: @"fid"] + unsignedLongLongValue]; + message = [self _createMessageOfClass: [messageProperties objectForKey: MAPIPropertyKey (PR_MESSAGE_CLASS_UNICODE)] + associated: associated + withMID: mid inFID: fid]; } if (message) { + if (associated) + [faiTable cleanupCaches]; + else + [messageTable cleanupCaches]; + [message setMAPIProperties: messageProperties]; if (isSave) [message MAPISave]; @@ -1002,22 +1027,6 @@ _prepareContextClass (struct mapistore_context *newMemCtx, save: NO]; } -- (enum MAPITAGS) _typeLessTag: (enum MAPITAGS) tag -{ - if (tag == 0x300b0000) - tag = PR_SEARCH_KEY; - else if (tag == 0x30070000) - tag = PR_CREATION_TIME; - else if (tag == 0x30080000) - tag = PR_LAST_MODIFICATION_TIME; - else if (tag == 0x0e080000) - tag = PR_MESSAGE_SIZE; - else - [self warnWithFormat: @"unknown typeless tag: 0x%.8x", tag]; - - return tag; -} - - (int) getProperties: (struct SPropTagArray *) sPropTagArray ofTableType: (uint8_t) tableType inRow: (struct SRow *) aRow @@ -1056,8 +1065,6 @@ _prepareContextClass (struct mapistore_context *newMemCtx, for (count = 0; count < sPropTagArray->cValues; count++) { tag = sPropTagArray->aulPropTag[count]; - if ((tag & 0x0000ffff) == 0) - tag = [self _typeLessTag: tag]; propValue = NULL; propRc = [table getChildProperty: &propValue @@ -1184,7 +1191,7 @@ _prepareContextClass (struct mapistore_context *newMemCtx, [self logWithFormat: @"fmid 0x%.16x found", fmid]; for (counter = 0; counter < aRow->cValues; counter++) { - cValue = &(aRow->lpProps[counter]); + cValue = aRow->lpProps + counter; [message setObject: NSObjectFromSPropValue (cValue) forKey: MAPIPropertyKey (cValue->ulPropTag)]; } @@ -1422,20 +1429,32 @@ _prepareContextClass (struct mapistore_context *newMemCtx, - (int) releaseRecordWithFMID: (uint64_t) fmid ofTableType: (uint8_t) tableType { - int rc; NSNumber *midNbr; + NSMutableDictionary *messageProperties; + NSUInteger retainCount; + int rc; switch (tableType) { case MAPISTORE_MESSAGE_TABLE: rc = MAPISTORE_SUCCESS; midNbr = [NSNumber numberWithUnsignedLongLong: fmid]; - if ([messages objectForKey: midNbr]) + messageProperties = [messages objectForKey: midNbr]; + if (messageProperties) { - [self logWithFormat: @"message with mid %.16x successfully removed" - @" from message cache", - fmid]; - [messages removeObjectForKey: midNbr]; + retainCount = [[messageProperties objectForKey: @"mapiRetainCount"] + unsignedIntValue]; + if (retainCount == 1) + { + [self logWithFormat: @"message with mid %.16x successfully removed" + @" from message cache", + fmid]; + [messages removeObjectForKey: midNbr]; + } + else + [messageProperties + setObject: [NSNumber numberWithUnsignedInt: retainCount - 1] + forKey: @"mapiRetainCount"]; } else [self warnWithFormat: @"message with mid %.16x not found" diff --git a/OpenChange/MAPIStoreMessageTable.m b/OpenChange/MAPIStoreMessageTable.m index 069328da7..c0beca286 100644 --- a/OpenChange/MAPIStoreMessageTable.m +++ b/OpenChange/MAPIStoreMessageTable.m @@ -87,10 +87,10 @@ static MAPIStoreMapping *mapping; *data = MAPILongLongValue (memCtx, 0); break; case PR_ACCESS: // TODO - *data = MAPILongValue (memCtx, 0x02); + *data = MAPILongValue (memCtx, 0x03); break; case PR_ACCESS_LEVEL: // TODO - *data = MAPILongValue (memCtx, 0x00000000); + *data = MAPILongValue (memCtx, 0x01); break; case PR_VIEW_STYLE: case PR_VIEW_MAJORVERSION: diff --git a/OpenChange/MAPIStoreTable.m b/OpenChange/MAPIStoreTable.m index 3bff46999..bc46f9496 100644 --- a/OpenChange/MAPIStoreTable.m +++ b/OpenChange/MAPIStoreTable.m @@ -339,6 +339,10 @@ static Class NSDataK, NSStringK; cachedRestrictedKeys = nil; [cachedKeys release]; cachedKeys = nil; + [lastChildKey release]; + lastChildKey = nil; + [lastChild release]; + lastChild = nil; } - (id) lookupChild: (NSString *) childKey diff --git a/OpenChange/MAPIStoreTasksMessageTable.m b/OpenChange/MAPIStoreTasksMessageTable.m index f021879ad..0c7547a39 100644 --- a/OpenChange/MAPIStoreTasksMessageTable.m +++ b/OpenChange/MAPIStoreTasksMessageTable.m @@ -132,7 +132,7 @@ task = [[self lookupChild: childKey] component: NO secure: NO]; status = [task status]; if (![status length] - || [status isEqualToString: @"NEEDS-ACTIONS"]) + || [status isEqualToString: @"NEEDS-ACTION"]) statusValue = 0; else if ([status isEqualToString: @"IN-PROCESS"]) statusValue = 1; diff --git a/OpenChange/SOGoAppointmentObject+MAPIStore.m b/OpenChange/SOGoAppointmentObject+MAPIStore.m index 21bfdf9c7..e11e1745c 100644 --- a/OpenChange/SOGoAppointmentObject+MAPIStore.m +++ b/OpenChange/SOGoAppointmentObject+MAPIStore.m @@ -109,6 +109,11 @@ // MAPIStoreDumpMessageProperties (properties); ASSIGN (content, [vCalendar versitString]); + + [fullCalendar release]; + fullCalendar = nil; + [safeCalendar release]; + safeCalendar = nil; } @end diff --git a/OpenChange/SOGoContactGCSEntry+MAPIStore.m b/OpenChange/SOGoContactGCSEntry+MAPIStore.m index 9a3b78ff6..be576ace7 100644 --- a/OpenChange/SOGoContactGCSEntry+MAPIStore.m +++ b/OpenChange/SOGoContactGCSEntry+MAPIStore.m @@ -20,6 +20,7 @@ * Boston, MA 02111-1307, USA. */ +#import #import #import #import @@ -37,21 +38,15 @@ - (void) setMAPIProperties: (NSDictionary *) properties { - NGVCard *newCard, *oldCard; + NGVCard *newCard; + NSArray *elements; + CardElement *element; + int postalAddressId; id value; [self logWithFormat: @"setMAPIProperties: %@", properties]; - oldCard = [self vCard]; - if (isNew) - newCard = oldCard; - else - { - newCard = [NGVCard new]; - [newCard setUid: [oldCard uid]]; - ASSIGN (card, newCard); - [newCard release]; - } + newCard = [self vCard]; [newCard setTag: @"vcard"]; [newCard setVersion: @"3.0"]; [newCard setProdID: @"-//Inverse inc.//OpenChange+SOGo//EN"]; @@ -62,9 +57,93 @@ if (value) [newCard setFn: value]; + elements = [newCard childrenWithTag: @"email"]; value = [properties objectForKey: MAPIPropertyKey (PidLidEmail1EmailAddress)]; if (value) - [newCard addEmail: value types: nil]; + { + if ([elements count] > 0) + [[elements objectAtIndex: 0] setValue: 0 to: value]; + else + [newCard addEmail: value + types: [NSArray arrayWithObject: @"pref"]]; + } + value = [properties objectForKey: MAPIPropertyKey (PidLidEmail2EmailAddress)]; + if (value) + { + if ([elements count] > 1) + [[elements objectAtIndex: 1] setValue: 0 to: value]; + else + [newCard addEmail: value types: nil]; + } + value = [properties objectForKey: MAPIPropertyKey (PidLidEmail3EmailAddress)]; + if (value) + { + if ([elements count] > 2) + [[elements objectAtIndex: 2] setValue: 0 to: value]; + else + [newCard addEmail: value types: nil]; + } + + postalAddressId = [[properties objectForKey: MAPIPropertyKey (PidLidPostalAddressId)] + intValue]; + + /* Work address */ + value = [properties objectForKey: MAPIPropertyKey (PidLidWorkAddress)]; + if ([value length]) + { + elements = [newCard childrenWithTag: @"label" + andAttribute: @"type" + havingValue: @"work"]; + if ([elements count] > 0) + element = [elements objectAtIndex: 0]; + else + { + element = [CardElement elementWithTag: @"label"]; + [element addAttribute: @"type" value: @"work"]; + [card addChild: element]; + } + if (postalAddressId == 2) + { + [element removeValue: @"pref" + fromAttribute: @"type"]; + [element addAttribute: @"type" + value: @"pref"]; + } + [element setValue: 0 to: value]; + } + + elements = [newCard childrenWithTag: @"adr" + andAttribute: @"type" + havingValue: @"work"]; + if ([elements count] > 0) + element = [elements objectAtIndex: 0]; + else + { + element = [CardElement elementWithTag: @"adr"]; + [element addAttribute: @"type" value: @"work"]; + [card addChild: element]; + } + if (postalAddressId == 2) + [element addAttribute: @"type" + value: @"pref"]; + value = [properties objectForKey: MAPIPropertyKey (PidLidWorkAddressPostOfficeBox)]; + if (value) + [element setValue: 0 to: value]; + value = [properties objectForKey: MAPIPropertyKey (PidLidWorkAddressStreet)]; + if (value) + [element setValue: 2 to: value]; + value = [properties objectForKey: MAPIPropertyKey (PidLidWorkAddressCity)]; + if (value) + [element setValue: 3 to: value]; + value = [properties objectForKey: MAPIPropertyKey (PidLidWorkAddressState)]; + if (value) + [element setValue: 4 to: value]; + value = [properties objectForKey: MAPIPropertyKey (PidLidWorkAddressPostalCode)]; + if (value) + [element setValue: 5 to: value]; + value = [properties objectForKey: MAPIPropertyKey (PidLidWorkAddressCountry)]; + if (value) + [element setValue: 6 to: value]; ASSIGN (content, [newCard versitString]); } diff --git a/OpenChange/SOGoTaskObject+MAPIStore.m b/OpenChange/SOGoTaskObject+MAPIStore.m index d8f00dbec..4a37b4b75 100644 --- a/OpenChange/SOGoTaskObject+MAPIStore.m +++ b/OpenChange/SOGoTaskObject+MAPIStore.m @@ -164,8 +164,12 @@ // } // MAPIStoreDumpMessageProperties (properties); - ASSIGN (content, [vCalendar versitString]); + + [fullCalendar release]; + fullCalendar = nil; + [safeCalendar release]; + safeCalendar = nil; } @end diff --git a/UI/Scheduler/UIxComponentEditor.m b/UI/Scheduler/UIxComponentEditor.m index 6c44fda8c..891796575 100644 --- a/UI/Scheduler/UIxComponentEditor.m +++ b/UI/Scheduler/UIxComponentEditor.m @@ -1253,9 +1253,9 @@ iRANGE(2); currentOwnerIdentity = [currentUser defaultIdentity]; currentOwnerProfile = [NSMutableDictionary dictionary]; - [currentOwnerProfile setObject: [currentOwnerIdentity objectForKey: @"fullName"] + [currentOwnerProfile setObject: ([currentOwnerIdentity objectForKey: @"fullName"] == nil ? @"" : [currentOwnerIdentity objectForKey: @"fullName"]) forKey: @"name"]; - [currentOwnerProfile setObject: [currentOwnerIdentity objectForKey: @"email"] + [currentOwnerProfile setObject: ([currentOwnerIdentity objectForKey: @"email"] == nil ? @"" : [currentOwnerIdentity objectForKey: @"email"]) forKey: @"email"]; [currentOwnerProfile setObject: @"accepted" forKey: @"partstat"];