Monotone-Parent: a9886e6c9acfb5c097b185a254e620a6a0094f1f

Monotone-Revision: 9109f0600492701322f24fb53d86a39821e26dc4

Monotone-Author: wsourdeau@inverse.ca
Monotone-Date: 2011-09-30T20:01:50
Monotone-Branch: ca.inverse.sogo
This commit is contained in:
Wolfgang Sourdeau 2011-09-30 20:01:50 +00:00
parent 18686beb11
commit 01e387b7b9
8 changed files with 554 additions and 172 deletions

View file

@ -1,5 +1,19 @@
2011-09-30 Wolfgang Sourdeau <wsourdeau@inverse.ca> 2011-09-30 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* OpenChange/MAPIStoreMailMessage.m (-getMessageData:inMemCtx:):
same as below.
* OpenChange/MAPIStoreCalendarMessage.m
(-getMessageData:inMemCtx:): delegated code to
MAPIStoreAppointmentWrapper so that organizers and invitees are
properly reported both in invitation emails and events.
* OpenChange/MAPIStoreMessage.m (MAPIStoreInternalEntryId)
(MAPIStoreExternalEntryId): new helper functions that return an
NSData with the entry id for the requested user or contact.
(-getMessageData:inMemCtx:): adapted to the new mapistore_message
struct and column handling.
* OpenChange/NSData+MAPIStore.m (-appendUInt16): new method. * OpenChange/NSData+MAPIStore.m (-appendUInt16): new method.
* OpenChange/EOQualifier+MAPIFS.m (-[EOKeyValueQUalifier * OpenChange/EOQualifier+MAPIFS.m (-[EOKeyValueQUalifier

View file

@ -47,6 +47,9 @@ extern NSTimeZone *utcTZ;
inTimeZone: (NSTimeZone *) newTimeZone; inTimeZone: (NSTimeZone *) newTimeZone;
/* getters */ /* getters */
- (void) fillMessageData: (struct mapistore_message *) dataPtr
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPrIconIndex: (void **) data - (int) getPrIconIndex: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx; inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPrOwnerApptId: (void **) data - (int) getPrOwnerApptId: (void **) data

View file

@ -24,6 +24,7 @@
#import <Foundation/NSCalendarDate.h> #import <Foundation/NSCalendarDate.h>
#import <Foundation/NSCharacterSet.h> #import <Foundation/NSCharacterSet.h>
#import <Foundation/NSData.h> #import <Foundation/NSData.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSTimeZone.h> #import <Foundation/NSTimeZone.h>
#import <NGExtensions/NSObject+Logs.h> #import <NGExtensions/NSObject+Logs.h>
#import <NGCards/iCalDateTime.h> #import <NGCards/iCalDateTime.h>
@ -31,7 +32,9 @@
#import <NGCards/iCalRecurrenceRule.h> #import <NGCards/iCalRecurrenceRule.h>
#import <NGCards/iCalTimeZone.h> #import <NGCards/iCalTimeZone.h>
#import <NGCards/iCalPerson.h> #import <NGCards/iCalPerson.h>
#import <SOGo/SOGoUserManager.h>
#import "MAPIStoreMessage.h"
#import "MAPIStoreRecurrenceUtils.h" #import "MAPIStoreRecurrenceUtils.h"
#import "MAPIStoreTypes.h" #import "MAPIStoreTypes.h"
#import "NSData+MAPIStore.h" #import "NSData+MAPIStore.h"
@ -118,6 +121,229 @@ static NSCharacterSet *hexCharacterSet = nil;
[super dealloc]; [super dealloc];
} }
- (void) fillMessageData: (struct mapistore_message *) msgData
inMemCtx: (TALLOC_CTX *) memCtx
{
NSString *username, *cn, *email;
NSData *entryId;
NSArray *attendees;
iCalPerson *person;
iCalPersonPartStat partStat;
uint32_t partStatValue;
SOGoUserManager *mgr;
NSDictionary *contactInfos;
struct mapistore_message_recipient *recipient;
int count, max, p;
msgData->columns = set_SPropTagArray (msgData, 9,
PR_OBJECT_TYPE,
PR_DISPLAY_TYPE,
PR_7BIT_DISPLAY_NAME_UNICODE,
PR_SMTP_ADDRESS_UNICODE,
PR_SEND_INTERNET_ENCODING,
PR_RECIPIENT_DISPLAY_NAME_UNICODE,
PR_RECIPIENT_FLAGS,
PR_RECIPIENT_ENTRYID,
PR_RECIPIENT_TRACKSTATUS);
// ,
// PR_RECORD_KEY);
attendees = [event attendees];
max = [attendees count];
if (max > 0)
{
mgr = [SOGoUserManager sharedUserManager];
msgData->recipients_count = max + 1;
msgData->recipients = talloc_array (msgData, struct mapistore_message_recipient *, max + 1);
for (count = 0; count < max; count++)
{
msgData->recipients[count]
= talloc_zero (msgData, struct mapistore_message_recipient);
recipient = msgData->recipients[count];
person = [attendees objectAtIndex: count];
cn = [person cn];
email = [person rfc822Email];
if ([cn length] == 0)
cn = email;
contactInfos = [mgr contactInfosForUserWithUIDorEmail: email];
if (contactInfos)
{
username = [contactInfos objectForKey: @"c_uid"];
recipient->username = [username asUnicodeInMemCtx: msgData];
entryId = MAPIStoreInternalEntryId (username);
}
else
entryId = MAPIStoreExternalEntryId (cn, email);
recipient->type = MAPI_TO;
/* properties */
p = 0;
recipient->data = talloc_array (msgData, void *, msgData->columns->cValues);
memset (recipient->data, 0, msgData->columns->cValues * sizeof (void *));
// PR_OBJECT_TYPE = MAPI_MAILUSER (see MAPI_OBJTYPE)
recipient->data[p] = MAPILongValue (msgData, MAPI_MAILUSER);
p++;
// PR_DISPLAY_TYPE = DT_MAILUSER (see MS-NSPI)
recipient->data[p] = MAPILongValue (msgData, 0);
p++;
// PR_7BIT_DISPLAY_NAME_UNICODE
recipient->data[p] = [cn asUnicodeInMemCtx: msgData];
p++;
// PR_SMTP_ADDRESS_UNICODE
recipient->data[p] = [email asUnicodeInMemCtx: msgData];
p++;
// PR_SEND_INTERNET_ENCODING = 0x00060000 (plain text, see OXCMAIL)
recipient->data[p] = MAPILongValue (msgData, 0x00060000);
p++;
// PR_RECIPIENT_DISPLAY_NAME_UNICODE
recipient->data[p] = [cn asUnicodeInMemCtx: msgData];
p++;
// PR_RECIPIENT_FLAGS
recipient->data[p] = MAPILongValue (msgData, 1);
p++;
// PR_RECIPIENT_ENTRYID
recipient->data[p] = [entryId asBinaryInMemCtx: msgData];
p++;
// PR_RECIPIENT_TRACKSTATUS
/*
respNone 0x00000000
No response is required for this object. This is the case for Appointment objects and Meeting Response objects.
respOrganized 0x00000001
This Meeting object belongs to the organizer.
respTentative 0x00000002
This value on the attendee's Meeting object indicates that the
attendee has tentatively accepted the Meeting Request object.
respAccepted 0x00000003
This value on the attendee's Meeting object indicates that the
attendee has accepted the Meeting Request object.
respDeclined 0x00000004
This value on the attendee's Meeting object indicates that the attendee has declined the Meeting Request
object.
respNotResponded 0x00000005
This value on the attendee's Meeting object indicates that the attendee has
not yet responded. This value is on the Meet
*/
partStat = [person participationStatus];
switch (partStat)
{
case iCalPersonPartStatAccepted:
partStatValue = 3;
break;
case iCalPersonPartStatDeclined:
partStatValue = 4;
break;
case iCalPersonPartStatTentative:
partStatValue = 2;
break;
default:
partStatValue = 5;
}
recipient->data[p] = MAPILongValue (msgData, partStatValue);
p++;
// // PR_RECORD_KEY
// recipient->data[p] = [entryId asBinaryInMemCtx: msgData];
// p++;
}
/* On with the organizer: */
{
msgData->recipients[max]
= talloc_zero (msgData, struct mapistore_message_recipient);
recipient = msgData->recipients[max];
person = [event organizer];
cn = [person cn];
email = [person rfc822Email];
contactInfos = [mgr contactInfosForUserWithUIDorEmail: email];
if (contactInfos)
{
username = [contactInfos objectForKey: @"c_uid"];
recipient->username = [username asUnicodeInMemCtx: msgData];
entryId = MAPIStoreInternalEntryId (username);
}
else
entryId = MAPIStoreExternalEntryId (cn, email);
recipient->type = MAPI_TO;
p = 0;
recipient->data = talloc_array (msgData, void *, msgData->columns->cValues);
memset (recipient->data, 0, msgData->columns->cValues * sizeof (void *));
// PR_OBJECT_TYPE = MAPI_MAILUSER (see MAPI_OBJTYPE)
recipient->data[p] = MAPILongValue (msgData, MAPI_MAILUSER);
p++;
// PR_DISPLAY_TYPE = DT_MAILUSER (see MS-NSPI)
recipient->data[p] = MAPILongValue (msgData, 0);
p++;
// PR_7BIT_DISPLAY_NAME_UNICODE
recipient->data[p] = [cn asUnicodeInMemCtx: msgData];
p++;
// PR_SMTP_ADDRESS_UNICODE
recipient->data[p] = [email asUnicodeInMemCtx: msgData];
p++;
// PR_SEND_INTERNET_ENCODING = 0x00060000 (plain text, see OXCMAIL)
recipient->data[p] = MAPILongValue (msgData, 0x00060000);
p++;
// PR_RECIPIENT_DISPLAY_NAME_UNICODE
recipient->data[p] = [cn asUnicodeInMemCtx: msgData];
p++;
// PR_RECIPIENT_FLAGS
recipient->data[p] = MAPILongValue (msgData, 3);
p++;
// PR_RECIPIENT_ENTRYID = NULL
recipient->data[p] = [entryId asBinaryInMemCtx: msgData];
p++;
// PR_RECIPIENT_TRACKSTATUS
/*
respNone 0x00000000
No response is required for this object. This is the case for Appointment objects and Meeting Response objects.
respOrganized 0x00000001
This Meeting object belongs to the organizer.
respTentative 0x00000002
This value on the attendee's Meeting object indicates that the
attendee has tentatively accepted the Meeting Request object.
respAccepted 0x00000003
This value on the attendee's Meeting object indicates that the
attendee has accepted the Meeting Request object.
respDeclined 0x00000004
This value on the attendee's Meeting object indicates that the attendee has declined the Meeting Request
object.
respNotResponded 0x00000005
This value on the attendee's Meeting object indicates that the attendee has
not yet responded. This value is on the Meet
*/
recipient->data[p] = MAPILongValue (msgData, 1);
p++;
// // PR_RECORD_KEY
// recipient->data[p] = [entryId asBinaryInMemCtx: msgData];
// p++;
}
}
}
- (int) getPrIconIndex: (void **) data // TODO - (int) getPrIconIndex: (void **) data // TODO
inMemCtx: (TALLOC_CTX *) memCtx inMemCtx: (TALLOC_CTX *) memCtx
{ {

View file

@ -255,58 +255,11 @@
- (void) getMessageData: (struct mapistore_message **) dataPtr - (void) getMessageData: (struct mapistore_message **) dataPtr
inMemCtx: (TALLOC_CTX *) memCtx inMemCtx: (TALLOC_CTX *) memCtx
{ {
NSString *text;
NSArray *attendees;
iCalPerson *person;
struct SRowSet *recipients;
int count, max;
iCalEvent *event;
struct mapistore_message *msgData; struct mapistore_message *msgData;
[super getMessageData: &msgData inMemCtx: memCtx]; [super getMessageData: &msgData inMemCtx: memCtx];
[[self appointmentWrapper] fillMessageData: msgData
event = [sogoObject component: NO secure: NO]; inMemCtx: memCtx];
attendees = [event attendees];
max = [attendees count];
recipients = talloc_zero (msgData, struct SRowSet);
recipients->cRows = max;
recipients->aRow = talloc_array (recipients, struct SRow, max);
for (count = 0; count < max; count++)
{
recipients->aRow[count].ulAdrEntryPad = 0;
recipients->aRow[count].cValues = 3;
recipients->aRow[count].lpProps = talloc_array (recipients->aRow,
struct SPropValue,
4);
// TODO (0x01 = primary recipient)
set_SPropValue_proptag (recipients->aRow[count].lpProps,
PR_RECIPIENT_TYPE,
MAPILongValue (recipients->aRow[count].lpProps, 0x01));
set_SPropValue_proptag (recipients->aRow[count].lpProps + 1,
PR_ADDRTYPE_UNICODE,
[@"SMTP" asUnicodeInMemCtx: recipients->aRow]);
person = [attendees objectAtIndex: count];
text = [person rfc822Email];
if (!text)
text = @"";
set_SPropValue_proptag (recipients->aRow[count].lpProps + 2,
PR_EMAIL_ADDRESS_UNICODE,
[text asUnicodeInMemCtx: recipients->aRow]);
text = [person cn];
if ([text length] > 0)
{
recipients->aRow[count].cValues++;
set_SPropValue_proptag (recipients->aRow[count].lpProps + 3,
PR_DISPLAY_NAME_UNICODE,
[text asUnicodeInMemCtx: recipients->aRow]);
}
}
msgData->recipients = recipients;
*dataPtr = msgData; *dataPtr = msgData;
} }

View file

@ -28,11 +28,13 @@
#import <SOGo/NSArray+Utilities.h> #import <SOGo/NSArray+Utilities.h>
#import <SOGo/NSDictionary+Utilities.h> #import <SOGo/NSDictionary+Utilities.h>
#import <SOGo/SOGoUser.h> #import <SOGo/SOGoUser.h>
#import <SOGo/SOGoUserManager.h>
#import <Mailer/SOGoDraftObject.h> #import <Mailer/SOGoDraftObject.h>
#import <NGObjWeb/WOContext+SoObjects.h> #import <NGObjWeb/WOContext+SoObjects.h>
#import "MAPIStoreContext.h" #import "MAPIStoreContext.h"
#import "MAPIStoreTypes.h" #import "MAPIStoreTypes.h"
#import "NSData+MAPIStore.h"
#import "NSObject+MAPIStore.h" #import "NSObject+MAPIStore.h"
#import "NSString+MAPIStore.h" #import "NSString+MAPIStore.h"
@ -92,14 +94,17 @@ typedef void (*getMessageData_inMemCtx_) (MAPIStoreMessage *, SEL,
- (void) getMessageData: (struct mapistore_message **) dataPtr - (void) getMessageData: (struct mapistore_message **) dataPtr
inMemCtx: (TALLOC_CTX *) memCtx inMemCtx: (TALLOC_CTX *) memCtx
{ {
struct SRowSet *recipients;
NSArray *to; NSArray *to;
NSInteger count, max; NSInteger count, max, p;
NSString *text; NSString *username, *cn, *email;
NSData *entryId;
NSDictionary *contactInfos;
SOGoUserManager *mgr;
NSDictionary *headers; NSDictionary *headers;
NGMailAddress *currentAddress; NGMailAddress *currentAddress;
NGMailAddressParser *parser; NGMailAddressParser *parser;
struct mapistore_message *msgData; struct mapistore_message *msgData;
struct mapistore_message_recipient *recipient;
getMessageData_inMemCtx_ superMethod; getMessageData_inMemCtx_ superMethod;
if ([sogoObject isKindOfClass: SOGoDraftObjectK]) if ([sogoObject isKindOfClass: SOGoDraftObjectK])
@ -117,53 +122,99 @@ typedef void (*getMessageData_inMemCtx_) (MAPIStoreMessage *, SEL,
to = [headers objectForKey: @"to"]; to = [headers objectForKey: @"to"];
max = [to count]; max = [to count];
recipients = talloc_zero (msgData, struct SRowSet);
recipients->cRows = max; msgData->columns = set_SPropTagArray (msgData, 9,
recipients->aRow = talloc_array (recipients, struct SRow, max); PR_OBJECT_TYPE,
for (count = 0; count < max; count++) PR_DISPLAY_TYPE,
PR_7BIT_DISPLAY_NAME_UNICODE,
PR_SMTP_ADDRESS_UNICODE,
PR_SEND_INTERNET_ENCODING,
PR_RECIPIENT_DISPLAY_NAME_UNICODE,
PR_RECIPIENT_FLAGS,
PR_RECIPIENT_ENTRYID,
PR_RECIPIENT_TRACKSTATUS);
if (max > 0)
{ {
recipients->aRow[count].ulAdrEntryPad = 0; mgr = [SOGoUserManager sharedUserManager];
recipients->aRow[count].cValues = 3; msgData->recipients_count = max;
recipients->aRow[count].lpProps = talloc_array (recipients->aRow, msgData->recipients = talloc_array (msgData, struct mapistore_message_recipient *, max);
struct SPropValue, for (count = 0; count < max; count++)
4);
// TODO (0x01 = primary recipient)
set_SPropValue_proptag (recipients->aRow[count].lpProps + 0,
PR_RECIPIENT_TYPE,
MAPILongValue (recipients->aRow, 0x01));
set_SPropValue_proptag (recipients->aRow[count].lpProps + 1,
PR_ADDRTYPE_UNICODE,
[@"SMTP" asUnicodeInMemCtx: recipients->aRow]);
parser = [NGMailAddressParser
mailAddressParserWithString: [to objectAtIndex: count]];
currentAddress = [parser parse];
if ([currentAddress isKindOfClass: NGMailAddressK])
{ {
// text = [currentAddress personalName]; msgData->recipients[count]
// if (![text length]) = talloc_zero (msgData, struct mapistore_message_recipient);
text = [currentAddress address]; recipient = msgData->recipients[count];
if (!text) recipient->data = talloc_array (msgData, void *, msgData->columns->cValues);
text = @""; memset (recipient->data, 0, msgData->columns->cValues * sizeof (void *));
set_SPropValue_proptag (recipients->aRow[count].lpProps + 2,
PR_EMAIL_ADDRESS_UNICODE,
[text asUnicodeInMemCtx: recipients->aRow]);
text = [currentAddress displayName]; email = nil;
if ([text length] > 0) cn = nil;
parser = [NGMailAddressParser
mailAddressParserWithString: [to objectAtIndex: count]];
currentAddress = [parser parse];
if ([currentAddress isKindOfClass: NGMailAddressK])
{ {
recipients->aRow[count].cValues++; email = [currentAddress address];
set_SPropValue_proptag (recipients->aRow[count].lpProps + 3, cn = [currentAddress displayName];
PR_DISPLAY_NAME_UNICODE, contactInfos = [mgr contactInfosForUserWithUIDorEmail: email];
[text asUnicodeInMemCtx: recipients->aRow]);
// PR_ACCOUNT_UNICODE
if (contactInfos)
{
username = [contactInfos objectForKey: @"c_uid"];
recipient->username = [username asUnicodeInMemCtx: msgData];
entryId = MAPIStoreInternalEntryId (username);
}
else
entryId = MAPIStoreExternalEntryId (cn, email);
} }
else
{
entryId = nil;
[self warnWithFormat: @"address could not be parsed"
@" properly (ignored)"];
}
recipient->type = MAPI_TO;
/* properties */
p = 0;
recipient->data = talloc_array (msgData, void *, msgData->columns->cValues);
memset (recipient->data, 0, msgData->columns->cValues * sizeof (void *));
// PR_OBJECT_TYPE = MAPI_MAILUSER (see MAPI_OBJTYPE)
recipient->data[p] = MAPILongValue (msgData, MAPI_MAILUSER);
p++;
// PR_DISPLAY_TYPE = DT_MAILUSER (see MS-NSPI)
recipient->data[p] = MAPILongValue (msgData, 0);
p++;
// PR_7BIT_DISPLAY_NAME_UNICODE
recipient->data[p] = [cn asUnicodeInMemCtx: msgData];
p++;
// PR_SMTP_ADDRESS_UNICODE
recipient->data[p] = [email asUnicodeInMemCtx: msgData];
p++;
// PR_SEND_INTERNET_ENCODING = 0x00060000 (plain text, see OXCMAIL)
recipient->data[p] = MAPILongValue (msgData, 0x00060000);
p++;
// PR_RECIPIENT_DISPLAY_NAME_UNICODE
recipient->data[p] = [cn asUnicodeInMemCtx: msgData];
p++;
// PR_RECIPIENT_FLAGS
recipient->data[p] = NULL;
p++;
// PR_RECIPIENT_ENTRYID
recipient->data[p] = [entryId asShortBinaryInMemCtx: msgData];
p++;
} }
else
[self warnWithFormat: @"address could not be parsed properly (ignored)"];
} }
msgData->recipients = recipients;
*dataPtr = msgData; *dataPtr = msgData;
} }
else else

View file

@ -31,6 +31,7 @@
#import <NGCards/iCalCalendar.h> #import <NGCards/iCalCalendar.h>
#import <SOGo/NSArray+Utilities.h> #import <SOGo/NSArray+Utilities.h>
#import <SOGo/NSString+Utilities.h> #import <SOGo/NSString+Utilities.h>
#import <SOGo/SOGoUserManager.h>
#import <Mailer/NSData+Mail.h> #import <Mailer/NSData+Mail.h>
#import <Mailer/SOGoMailBodyPart.h> #import <Mailer/SOGoMailBodyPart.h>
#import <Mailer/SOGoMailObject.h> #import <Mailer/SOGoMailObject.h>
@ -1175,57 +1176,113 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
- (void) getMessageData: (struct mapistore_message **) dataPtr - (void) getMessageData: (struct mapistore_message **) dataPtr
inMemCtx: (TALLOC_CTX *) memCtx inMemCtx: (TALLOC_CTX *) memCtx
{ {
struct SRowSet *recipients;
NSArray *to; NSArray *to;
NSInteger count, max; NSInteger count, max, p;
NGImap4EnvelopeAddress *currentAddress; NGImap4EnvelopeAddress *currentAddress;
NSString *text; NSString *username, *cn, *email;
NSData *entryId;
NSDictionary *contactInfos;
SOGoUserManager *mgr;
struct mapistore_message *msgData; struct mapistore_message *msgData;
struct mapistore_message_recipient *recipient;
[super getMessageData: &msgData inMemCtx: memCtx]; [super getMessageData: &msgData inMemCtx: memCtx];
/* Retrieve recipients from the message */
to = [sogoObject toEnvelopeAddresses]; if (!headerSetup)
max = [to count]; [self _fetchHeaderData];
recipients = talloc_zero (msgData, struct SRowSet);
recipients->cRows = max; if (mailIsEvent)
recipients->aRow = talloc_array (recipients, struct SRow, max); [[self _appointmentWrapper] fillMessageData: msgData
for (count = 0; count < max; count++) inMemCtx: memCtx];
else
{ {
recipients->aRow[count].ulAdrEntryPad = 0; /* Retrieve recipients from the message */
recipients->aRow[count].cValues = 3; to = [sogoObject toEnvelopeAddresses];
recipients->aRow[count].lpProps = talloc_array (recipients->aRow, max = [to count];
struct SPropValue,
4);
// TODO (0x01 = primary recipient) msgData->columns = set_SPropTagArray (msgData, 9,
set_SPropValue_proptag (recipients->aRow[count].lpProps + 0, PR_OBJECT_TYPE,
PR_RECIPIENT_TYPE, PR_DISPLAY_TYPE,
MAPILongValue (recipients->aRow, 0x01)); PR_7BIT_DISPLAY_NAME_UNICODE,
PR_SMTP_ADDRESS_UNICODE,
PR_SEND_INTERNET_ENCODING,
PR_RECIPIENT_DISPLAY_NAME_UNICODE,
PR_RECIPIENT_FLAGS,
PR_RECIPIENT_ENTRYID,
PR_RECIPIENT_TRACKSTATUS);
set_SPropValue_proptag (recipients->aRow[count].lpProps + 1, if (max > 0)
PR_ADDRTYPE_UNICODE,
[@"SMTP" asUnicodeInMemCtx: recipients->aRow]);
currentAddress = [to objectAtIndex: count];
// text = [currentAddress personalName];
// if (![text length])
text = [currentAddress baseEMail];
if (!text)
text = @"";
set_SPropValue_proptag (recipients->aRow[count].lpProps + 2,
PR_EMAIL_ADDRESS_UNICODE,
[text asUnicodeInMemCtx: recipients->aRow]);
text = [currentAddress personalName];
if ([text length] > 0)
{ {
recipients->aRow[count].cValues++; mgr = [SOGoUserManager sharedUserManager];
set_SPropValue_proptag (recipients->aRow[count].lpProps + 3, msgData->recipients_count = max;
PR_DISPLAY_NAME_UNICODE, msgData->recipients = talloc_array (msgData, struct mapistore_message_recipient *, max);
[text asUnicodeInMemCtx: recipients->aRow]); for (count = 0; count < max; count++)
{
msgData->recipients[count]
= talloc_zero (msgData, struct mapistore_message_recipient);
recipient = msgData->recipients[count];
currentAddress = [to objectAtIndex: count];
cn = [currentAddress personalName];
email = [currentAddress baseEMail];
if ([cn length] == 0)
cn = email;
contactInfos = [mgr contactInfosForUserWithUIDorEmail: email];
if (contactInfos)
{
username = [contactInfos objectForKey: @"c_uid"];
// recipient->username = [username asUnicodeInMemCtx: msgData];
// entryId = MAPIStoreInternalEntryId (username);
entryId = MAPIStoreExternalEntryId (cn, email);
}
else
entryId = MAPIStoreExternalEntryId (cn, email);
recipient->type = MAPI_TO;
/* properties */
p = 0;
recipient->data = talloc_array (msgData, void *, msgData->columns->cValues);
memset (recipient->data, 0, msgData->columns->cValues * sizeof (void *));
// PR_OBJECT_TYPE = MAPI_MAILUSER (see MAPI_OBJTYPE)
recipient->data[p] = MAPILongValue (msgData, MAPI_MAILUSER);
p++;
// PR_DISPLAY_TYPE = DT_MAILUSER (see MS-NSPI)
recipient->data[p] = MAPILongValue (msgData, 0);
p++;
// PR_7BIT_DISPLAY_NAME_UNICODE
recipient->data[p] = [cn asUnicodeInMemCtx: msgData];
p++;
// PR_SMTP_ADDRESS_UNICODE
recipient->data[p] = [email asUnicodeInMemCtx: msgData];
p++;
// PR_SEND_INTERNET_ENCODING = 0x00060000 (plain text, see OXCMAIL)
recipient->data[p] = MAPILongValue (msgData, 0x00060000);
p++;
// PR_RECIPIENT_DISPLAY_NAME_UNICODE
recipient->data[p] = [cn asUnicodeInMemCtx: msgData];
p++;
// PR_RECIPIENT_FLAGS
recipient->data[p] = MAPILongValue (msgData, 0x01);
p++;
// PR_RECIPIENT_ENTRYID
recipient->data[p] = [entryId asBinaryInMemCtx: msgData];
p++;
// PR_RECIPIENT_TRACKSTATUS
recipient->data[p] = MAPILongValue (msgData, 0x00);
p++;
}
} }
} }
msgData->recipients = recipients;
*dataPtr = msgData; *dataPtr = msgData;
} }

View file

@ -37,6 +37,9 @@
#import "MAPIStoreObject.h" #import "MAPIStoreObject.h"
extern NSData *MAPIStoreInternalEntryId (NSString *username);
extern NSData *MAPIStoreExternalEntryId (NSString *cn, NSString *email);
@interface MAPIStoreMessage : MAPIStoreObject @interface MAPIStoreMessage : MAPIStoreObject
{ {
NSArray *attachmentKeys; NSArray *attachmentKeys;

View file

@ -21,6 +21,7 @@
*/ */
#import <Foundation/NSArray.h> #import <Foundation/NSArray.h>
#import <Foundation/NSData.h>
#import <Foundation/NSDictionary.h> #import <Foundation/NSDictionary.h>
#import <Foundation/NSString.h> #import <Foundation/NSString.h>
#import <Foundation/NSURL.h> #import <Foundation/NSURL.h>
@ -33,7 +34,9 @@
#import "MAPIStoreAttachmentTable.h" #import "MAPIStoreAttachmentTable.h"
#import "MAPIStoreContext.h" #import "MAPIStoreContext.h"
#import "MAPIStoreFolder.h" #import "MAPIStoreFolder.h"
#import "MAPIStorePropertySelectors.h"
#import "MAPIStoreTypes.h" #import "MAPIStoreTypes.h"
#import "NSData+MAPIStore.h"
#import "NSObject+MAPIStore.h" #import "NSObject+MAPIStore.h"
#import "NSString+MAPIStore.h" #import "NSString+MAPIStore.h"
@ -46,6 +49,102 @@
#include <mapistore/mapistore_errors.h> #include <mapistore/mapistore_errors.h>
#include <mapistore/mapistore_nameid.h> #include <mapistore/mapistore_nameid.h>
NSData *MAPIStoreInternalEntryId (NSString *username)
{
NSMutableData *entryId;
static uint8_t providerUid[] = { 0xdc, 0xa7, 0x40, 0xc8,
0xc0, 0x42, 0x10, 0x1a,
0xb4, 0xb9, 0x08, 0x00,
0x2b, 0x2f, 0xe1, 0x82 };
NSString *x500dn;
/* structure:
flags: 32
provideruid: 32 * 4
version: 32
type: 32
X500DN: variable */
entryId = [NSMutableData dataWithCapacity: 256];
[entryId appendUInt32: 0]; // flags
[entryId appendBytes: providerUid length: 16]; // provideruid
[entryId appendUInt32: 1]; // version
[entryId appendUInt32: 0]; // type (local mail user)
/* X500DN */
/* FIXME: the DN will likely work on DEMO installations for now but we
really should get the dn prefix from the server */
x500dn = [NSString stringWithFormat: @"/O=FIRST ORGANIZATION"
@"/OU=FIRST ADMINISTRATIVE GROUP"
@"/CN=RECIPIENTS/CN=%@", username];
[entryId appendData: [x500dn dataUsingEncoding: NSISOLatin1StringEncoding]];
[entryId appendUInt8: 0];
return entryId;
}
NSData *MAPIStoreExternalEntryId (NSString *cn, NSString *email)
{
NSMutableData *entryId;
static uint8_t providerUid[] = { 0x81, 0x2b, 0x1f, 0xa4,
0xbe, 0xa3, 0x10, 0x19,
0x9d, 0x6e, 0x00, 0xdd,
0x01, 0x0f, 0x54, 0x02 };
uint8_t flags21, flags22;
/* structure:
flags: 32
provideruid: 32 * 4
version: 16
{
PaD: 1
MAE: 2
Format: 4
M: 1
U: 1
R: 2
L: 1
Pad: 4
}
DisplayName: variable
AddressType: variable
EmailAddress: variable */
entryId = [NSMutableData dataWithCapacity: 256];
[entryId appendUInt32: 0]; // flags
[entryId appendBytes: providerUid length: 16]; // provideruid
[entryId appendUInt16: 0]; // version
flags21 = 0; /* PaD, MAE, R, Pad = 0 */
flags21 |= 0x16; /* Format: text and HTML */
flags21 |= 0x01; /* M: mime format */
flags22 = 0x90; /* U: unicode, L: no lookup */
[entryId appendUInt8: flags21];
[entryId appendUInt8: flags22];
/* DisplayName */
if (!cn)
cn = @"";
[entryId
appendData: [cn dataUsingEncoding: NSUTF16LittleEndianStringEncoding]];
[entryId appendUInt16: 0];
/* AddressType */
[entryId
appendData: [@"SMTP" dataUsingEncoding: NSUTF16LittleEndianStringEncoding]];
[entryId appendUInt16: 0];
/* EMailAddress */
if (!email)
email = @"";
[entryId
appendData: [email dataUsingEncoding: NSUTF16LittleEndianStringEncoding]];
[entryId appendUInt16: 0];
return entryId;
}
@interface SOGoObject (MAPIStoreProtocol) @interface SOGoObject (MAPIStoreProtocol)
- (NSString *) davEntityTag; - (NSString *) davEntityTag;
@ -77,12 +176,6 @@
- (void) getMessageData: (struct mapistore_message **) dataPtr - (void) getMessageData: (struct mapistore_message **) dataPtr
inMemCtx: (TALLOC_CTX *) memCtx inMemCtx: (TALLOC_CTX *) memCtx
{ {
static enum MAPITAGS tags[] = { PR_SUBJECT_PREFIX_UNICODE,
PR_NORMALIZED_SUBJECT_UNICODE };
struct SRowSet *recipients;
struct SRow *properties;
NSInteger count, max;
const char *propName;
void *propValue; void *propValue;
struct mapistore_message *msgData; struct mapistore_message *msgData;
@ -91,40 +184,22 @@
msgData = talloc_zero (memCtx, struct mapistore_message); msgData = talloc_zero (memCtx, struct mapistore_message);
recipients = talloc_zero (msgData, struct SRowSet); if ([self getPrSubjectPrefix: &propValue
recipients->cRows = 0; inMemCtx: msgData] == MAPISTORE_SUCCESS
recipients->aRow = NULL; && propValue)
msgData->recipients = recipients; msgData->subject_prefix = propValue;
else
msgData->subject_prefix = "";
max = 2; if ([self getPrNormalizedSubject: &propValue
properties = talloc_zero (msgData, struct SRow); inMemCtx: msgData] == MAPISTORE_SUCCESS
properties->cValues = 0; && propValue)
properties->ulAdrEntryPad = 0; msgData->normalized_subject = propValue;
properties->lpProps = talloc_array (properties, struct SPropValue, max); else
for (count = 0; count < max; count++) msgData->normalized_subject = "";
{
if ([self getProperty: &propValue withTag: tags[count] inMemCtx: msgData] msgData->columns = talloc_zero(msgData, struct SPropTagArray);
== MAPISTORE_SUCCESS) msgData->recipients_count = 0;
{
if (propValue == NULL)
{
propName = get_proptag_name (tags[count]);
if (!propName)
propName = "<unknown>";
[self errorWithFormat: @"both 'success' and NULL data"
@" returned for proptag %s(0x%.8x)",
propName, tags[count]];
}
else
{
set_SPropValue_proptag (properties->lpProps + properties->cValues,
tags[count],
propValue);
properties->cValues++;
}
}
}
msgData->properties = properties;
*dataPtr = msgData; *dataPtr = msgData;
} }