Evolution Connector for Microsoft Exchange Programmer’s Reference Manual |
---|
Free/Busy Searches |
The OWA XML Free/Busy interface
In Connector versions up to and including 2.0, we get free/busy data by using the XML interface to OWA. The request URL looks like:
/public/?Cmd=freebusy &start=2002-10-23T04:00:00Z &end=2002-11-27T05:00:00Z &interval=30 &u=SMTP:danw@xcs.ximian.com &u=SMTP:eleanor@xcs.ximian.com
(Line breaks inserted for clarity. The actual URL would all be on one
line of course.) This must be sent with a proper
User-Agent
header to make it believe you are
IE (or you'll get the HTML form instead.)
You can add as many users as you like.
The response (with a status of 200
OK
) looks like:
<a:response xmlns:a="WM"> <a:recipients> <a:item> <a:displayname>All Attendees</a:displayname> <a:type>1</a:type> <a:fbdata>00000022220000000000000001221000222222...</a:fbdata> </a:item> <a:item> <a:displayname>Dan Winship</a:displayname> <a:email type="SMTP">danw@xcs.ximian.com</a:email> <a:type>1</a:type> <a:fbdata>00000000000000000000000000220000222222...</a:fbdata> </a:item> <a:item> <a:displayname>Eleanor Garcia</a:displayname> <a:email type="SMTP">eleanor@xcs.ximian.com</a:email> <a:type>1</a:type> <a:fbdata>00000022220000000000000001111000000000...</a:fbdata> </a:item> </a:recipients> </a:response>
Each character in the fbdata
section represents a
length of "interval
" minutes (the interval
specified in the request URL), with the following mapping:
|
Free |
|
Tentative |
|
Busy |
|
Out of Office |
The Lower-level Free/Busy Interface
Note
There is some code in
e2k-freebusy.c
that works with these interfaces, but it is not very heavily tested
and is not currently used by Connector.
Public Free/Busy file
OWA's free/busy data is generated from the
data in /public/NON_IPM_SUBTREE/SCHEDULE%2B%20FREE%20BUSY/
.
Under that directory, there is a directory for each
Exchange organization. Eg:
EX:_xF8FF_o=Ximian%20XCS_xF8FF_ou=XCS
In that directory is a file for each user, eg:
USER-_xF8FF_CN=RECIPIENTS_xF8FF_CN=DANW.EML
So, given that my legacyExchangeDN
is
/o=Ximian XCS/ou=XCS/cn=Recipients/cn=danw
you can find my public free/busy file. ("_xF8FF_
" is
the URI-encoded form of '/
' when it's not a path
separator. e2k_uri_encode
handles this.). The legacyExchangeDN
is
also stored as the PR_FREEBUSY_EMAIL_ADDRESS
property on the message, so we can also just search for that.
The PR_FREEBUSY_START_RANGE
and
PR_FREEBUSY_END_RANGE
properties on this message
give the start and end times of the published range, in systime
(minutes since 16010101T00000000Z
) format. These
always fall on month boundaries. (The start time is always the
beginning of the current month, and the end time is determined by the
PR_FREEBUSY_NUM_MONTHS
property on the private
free/busy file (described below).)
Four pairs of multivalued properties give the actual free/busy data.
|
all events |
|
tentative events |
|
busy events |
|
out-of-office events |
The _MONTHS
properties are arrays of
struct { guint month:4; /* 1 = January */ guint year :28; };
Each element of this array has a corresponding element in the
_EVENTS
array containing the events in that month
and year as an array of:
struct { guint16 start; /* minutes since start of month */ guint16 end; /* minutes since start of month */ };
If there are no events of a given type in the given interval, then Outlook leaves the two properties for that type unset. (If there are no events at all, then all 8 properties will be unset.) But when Exchange regenerates them itself, it just creates them empty instead.
Additionally, several other properties are used:
|
the last modtime |
MAPI proptag |
Unknown. (Usually
|
MAPI proptag |
Unknown. (Usually
|
There is also one more property,
http://schemas.microsoft.com/mapi/string/{8CDA1CAE-AFDB-11D2-9379-00C04FA357AA}/microsoft.cdo.calendar.fbhistory
,
of type PT_MV_BINARY
, which seems to always contain
3 24-byte items. The first two bytes of each are a month-year like the
_MONTHS
properties (and for an up-to-date free/busy
file, the 3 items will be this month, next month, and the month
after). There are then 6 0 bytes, followed by 8 bytes of data that are
almost always the same in each of the 3 items, followed by 8 0 bytes.
The purpose of this data is currently unknown. The middle chunk of
data seems to get changed every time the free/busy data is updated. It
may be a timestamp of some unknown sort?
Personal Free/Busy file
Each user also has a personal free/busy message, at:
/exchange/
username
/NON_IPM_SUBTREE/Freebusy%20Data/LocalFreebusy.EML
This is known to be used for at least three things:
The user's free/busy information is stored on it (in a completely different format from the public free/busy file), as described below.
The user's list of delegates and their "see private items" permissions are stored on it, as described in "Delegates".
Certain preferences that allow the account to be used as a "resource" are stored here, as described in "Direct Booking".
When you create an event via WebDAV, the server will eventually update the free/busy file with that data, but this is subject to various delays and exceptions that we don't understand. Among other things, Outlook uses the free/busy file to decide what dates to make bold in the minicalendar, which is why Connector-created appointments don't always show up there right away even when Outlook does display the event itself.
The free/busy data is stored in the
PR_PERSONAL_FREEBUSY
property as follows:
struct { guint32 magic; /* 0xdeadbeef */ guint32 header_len; /* 0x00000040 */ guint32 unknown_1; /* 0x00010000 */ guint32 unknown_2; /* 0x00000000 */ guint32 num_groups; /* number of free/busy groups */ guint32 num_events; /* total number of free/busy objects */ guint32 unknown_3; /* 0x00000008 */ guint32 unknown_4; /* 0x00000004 */ guint64 first_event; /* Windows filetime of start of first event */ guint64 last_event; /* Windows filetime of end of last event */ guint64 start_valid; /* Windows filetime of start of range */ guint64 end_valid; /* Windows filetime of end of range */ struct { guint32 index; /* Index of first event belonging to this group */ guint32 count; /* Number of events in this group */ } groups[num_groups]; struct { guint32 offset; /* Offset in minutes of event from start of group */ guint len:13; /* Length of event in minutes */ guint status:3; /* Status (1 = tentative, 2 = busy, 3 = oof) */ } events[num_events]; };
The first group starts at the time indicated by
start_valid
, so an event in group
0
with an offset
of
0
starts at
start_valid
. Group
N
starts at time
(
.
If there are no events in the timeframe of a group, its
start_valid
+
N
* 0x10000
)index
and count
will both be 0
.
There is no particular correlation between free/busy events and events on the calendar: two adjacent calendar events can be stored as a single free/busy event, and a given calendar event may be split across two or more free/busy groups.
The number of months covered by the free/busy data is in
PR_FREEBUSY_NUM_MONTHS
.
A posting on the MAPI-L
list claimed that setting PR_DISABLE_FULL_FIDELITY
to 0
on the free/busy message will force
Outlook to regenerate it, but I haven't
tested this.