1 /***
2  * libpst.h
3  * Part of LibPST project
4  * Written by David Smith
5  *            dave.s@earthcorp.com
6  */
7 // LibPST - Library for Accessing Outlook .pst files
8 // Dave Smith - davesmith@users.sourceforge.net
9 
10 #ifndef __PST_LIBPST_H
11 #define __PST_LIBPST_H
12 
13 #include "common.h"
14 
15 
16 #ifdef __cplusplus
17 extern "C" {
18 #endif
19 
20 
21 // switch to maximal packing for all structures in the libpst interface
22 // this is reverted at the end of this file
23 #ifdef _MSC_VER
24     #pragma pack(push, 1)
25 #endif
26 #if defined(__GNUC__) || defined (__SUNPRO_C) || defined(__SUNPRO_CC)
27     #pragma pack(1)
28 #endif
29 
30 
31 #define PST_TYPE_NOTE        1
32 #define PST_TYPE_SCHEDULE    2
33 #define PST_TYPE_APPOINTMENT 8
34 #define PST_TYPE_CONTACT     9
35 #define PST_TYPE_JOURNAL    10
36 #define PST_TYPE_STICKYNOTE 11
37 #define PST_TYPE_TASK       12
38 #define PST_TYPE_OTHER      13
39 #define PST_TYPE_REPORT     14
40 #define PST_TYPE_MAX        15
41 
42 // defines types of possible encryption
43 #define PST_NO_ENCRYPT   0
44 #define PST_COMP_ENCRYPT 1
45 #define PST_ENCRYPT      2
46 
47 // defines different types of mappings
48 #define PST_MAP_ATTRIB (uint32_t)1
49 #define PST_MAP_HEADER (uint32_t)2
50 
51 // define my custom email attributes.
52 #define PST_ATTRIB_HEADER -1
53 
54 // defines types of free/busy values for appointment->showas
55 #define PST_FREEBUSY_FREE          0
56 #define PST_FREEBUSY_TENTATIVE     1
57 #define PST_FREEBUSY_BUSY          2
58 #define PST_FREEBUSY_OUT_OF_OFFICE 3
59 
60 // defines labels for appointment->label
61 #define PST_APP_LABEL_NONE        0
62 #define PST_APP_LABEL_IMPORTANT   1
63 #define PST_APP_LABEL_BUSINESS    2
64 #define PST_APP_LABEL_PERSONAL    3
65 #define PST_APP_LABEL_VACATION    4
66 #define PST_APP_LABEL_MUST_ATTEND 5
67 #define PST_APP_LABEL_TRAVEL_REQ  6
68 #define PST_APP_LABEL_NEEDS_PREP  7
69 #define PST_APP_LABEL_BIRTHDAY    8
70 #define PST_APP_LABEL_ANNIVERSARY 9
71 #define PST_APP_LABEL_PHONE_CALL  10
72 
73 // define type of recurring event
74 #define PST_APP_RECUR_NONE        0
75 #define PST_APP_RECUR_DAILY       1
76 #define PST_APP_RECUR_WEEKLY      2
77 #define PST_APP_RECUR_MONTHLY     3
78 #define PST_APP_RECUR_YEARLY      4
79 
80 // define attachment types
81 #define PST_ATTACH_NONE             0
82 #define PST_ATTACH_BY_VALUE         1
83 #define PST_ATTACH_BY_REF           2
84 #define PST_ATTACH_BY_REF_RESOLV    3
85 #define PST_ATTACH_BY_REF_ONLY      4
86 #define PST_ATTACH_EMBEDDED         5
87 #define PST_ATTACH_OLE              6
88 
89 // define flags
90 #define PST_FLAG_READ			0x01
91 #define PST_FLAG_UNMODIFIED		0x02
92 #define PST_FLAG_SUBMIT			0x04
93 #define PST_FLAG_UNSENT			0x08
94 #define PST_FLAG_HAS_ATTACHMENT	0x10
95 #define PST_FLAG_FROM_ME		0x20
96 #define PST_FLAG_ASSOCIATED		0x40
97 #define PST_FLAG_RESEND			0x80
98 #define PST_FLAG_RN_PENDING		0x100
99 #define PST_FLAG_NRN_PENDING	0x200
100 
101 
102 typedef struct pst_entryid {
103     int32_t u1;
104     char entryid[16];
105     uint32_t id;
106 } pst_entryid;
107 
108 
109 typedef struct pst_index_ll {
110     uint64_t i_id;
111     uint64_t offset;
112     uint64_t size;
113     uint64_t inflated_size;
114     int64_t  u1;
115 } pst_index_ll;
116 
117 
118 typedef struct pst_id2_tree {
119     uint64_t            id2;
120     pst_index_ll        *id;
121     struct pst_id2_tree *child;
122     struct pst_id2_tree *next;
123 } pst_id2_tree;
124 
125 
126 typedef struct pst_desc_tree {
127     uint64_t              d_id;
128     uint64_t              parent_d_id;
129     pst_index_ll         *desc;
130     pst_index_ll         *assoc_tree;
131     int32_t               no_child;
132     struct pst_desc_tree *prev;
133     struct pst_desc_tree *next;
134     struct pst_desc_tree *parent;
135     struct pst_desc_tree *child;
136     struct pst_desc_tree *child_tail;
137 } pst_desc_tree;
138 
139 
140 /** The string is either utf8 encoded, or it is in the code page
141  *  specified by the containing mapi object. It can be forced into
142  *  utf8 by calling pst_convert_utf8() or pst_convert_utf8_null().
143  */
144 typedef struct pst_string {
145     /** @li 1 true
146      *  @li 0 false */
147     int     is_utf8;
148     char   *str;
149 } pst_string;
150 
151 
152 /** a simple wrapper for binary blobs */
153 typedef struct pst_binary {
154     size_t  size;
155     char   *data;
156 } pst_binary;
157 
158 
159 /** This contains the email related mapi elements
160  */
161 typedef struct pst_item_email {
162     /** mapi element 0x0e06 PR_MESSAGE_DELIVERY_TIME */
163     FILETIME   *arrival_date;
164     /** mapi element 0x0002 PR_ALTERNATE_RECIPIENT_ALLOWED
165      *  @li 1 true
166      *  @li 0 not set
167      *  @li -1 false */
168     int         autoforward;
169     /** mapi element 0x0e03 PR_DISPLAY_CC */
170     pst_string  cc_address;
171     /** mapi element 0x0e02 PR_DISPLAY_BCC */
172     pst_string  bcc_address;
173     /** mapi element 0x0071 PR_CONVERSATION_INDEX */
174     pst_binary  conversation_index;
175     /** mapi element 0x3a03 PR_CONVERSION_PROHIBITED
176      *  @li 1 true
177      *  @li 0 false */
178     int         conversion_prohibited;
179     /** mapi element 0x0e01 PR_DELETE_AFTER_SUBMIT
180      *  @li 1 true
181      *  @li 0 false */
182     int         delete_after_submit;
183     /** mapi element 0x0023 PR_ORIGINATOR_DELIVERY_REPORT_REQUESTED
184      *  @li 1 true
185      *  @li 0 false */
186     int         delivery_report;
187     /** mapi element 0x6f04 */
188     pst_binary  encrypted_body;
189     /** mapi element 0x6f02 */
190     pst_binary  encrypted_htmlbody;
191     /** mapi element 0x007d PR_TRANSPORT_MESSAGE_HEADERS */
192     pst_string  header;
193     /** mapi element 0x1013 */
194     pst_string  htmlbody;
195     /** mapi element 0x0017 PR_IMPORTANCE
196      *  @li 0 low
197      *  @li 1 normal
198      *  @li 2 high */
199     int32_t     importance;
200     /** mapi element 0x1042 */
201     pst_string  in_reply_to;
202     /** mapi element 0x0058 PR_MESSAGE_CC_ME, this user is listed explicitly in the CC address
203      *  @li 1 true
204      *  @li 0 false */
205     int         message_cc_me;
206     /** mapi element 0x0059 PR_MESSAGE_RECIP_ME, this user appears in TO, CC or BCC address list
207      *  @li 1 true
208      *  @li 0 false */
209     int         message_recip_me;
210     /** mapi element 0x0057 PR_MESSAGE_TO_ME, this user is listed explicitly in the TO address
211      *  @li 1 true
212      *  @li 0 false */
213     int         message_to_me;
214     /** mapi element 0x1035 */
215     pst_string  messageid;
216     /** mapi element 0x002e PR_ORIGINAL_SENSITIVITY
217      *  @li 0=none
218      *  @li 1=personal
219      *  @li 2=private
220      *  @li 3=company confidential */
221     int32_t     original_sensitivity;
222     /** mapi element 0x0072 PR_ORIGINAL_DISPLAY_BCC */
223     pst_string  original_bcc;
224     /** mapi element 0x0073 PR_ORIGINAL_DISPLAY_CC */
225     pst_string  original_cc;
226     /** mapi element 0x0074 PR_ORIGINAL_DISPLAY_TO */
227     pst_string  original_to;
228     /** mapi element 0x0051 PR_RECEIVED_BY_SEARCH_KEY */
229     pst_string  outlook_recipient;
230     /** mapi element 0x0044 PR_RCVD_REPRESENTING_NAME */
231     pst_string  outlook_recipient_name;
232     /** mapi element 0x0052 PR_RCVD_REPRESENTING_SEARCH_KEY */
233     pst_string  outlook_recipient2;
234     /** mapi element 0x003b PR_SENT_REPRESENTING_SEARCH_KEY */
235     pst_string  outlook_sender;
236     /** mapi element 0x0042 PR_SENT_REPRESENTING_NAME */
237     pst_string  outlook_sender_name;
238     /** mapi element 0x0c1d PR_SENDER_SEARCH_KEY */
239     pst_string  outlook_sender2;
240     /** mapi element 0x0026 PR_PRIORITY
241      *  @li 0 nonurgent
242      *  @li 1 normal
243      *  @li 2 urgent */
244     /** mapi element  */
245     int32_t     priority;
246     /** mapi element 0x0070 PR_CONVERSATION_TOPIC */
247     pst_string  processed_subject;
248     /** mapi element 0x0029 PR_READ_RECEIPT_REQUESTED
249      *  @li 1 true
250      *  @li 0 false */
251     int         read_receipt;
252     /** mapi element 0x0075 PR_RECEIVED_BY_ADDRTYPE */
253     pst_string  recip_access;
254     /** mapi element 0x0076 PR_RECEIVED_BY_EMAIL_ADDRESS */
255     pst_string  recip_address;
256     /** mapi element 0x0077 PR_RCVD_REPRESENTING_ADDRTYPE */
257     pst_string  recip2_access;
258     /** mapi element 0x0078 PR_RCVD_REPRESENTING_EMAIL_ADDRESS */
259     pst_string  recip2_address;
260     /** mapi element 0x0c17 PR_REPLY_REQUESTED
261      *  @li 1 true
262      *  @li 0 false */
263     int         reply_requested;
264     /** mapi element 0x0050 PR_REPLY_RECIPIENT_NAMES */
265     pst_string  reply_to;
266     /** mapi element 0x1046, this seems to be the message-id of the rfc822 mail that is being returned */
267     pst_string  return_path_address;
268     /** mapi element 0x1007 PR_RTF_SYNC_BODY_COUNT,
269      *  a count of the *significant* characters in the rtf body. Doesn't count
270      *  whitespace and other ignorable characters. */
271     int32_t     rtf_body_char_count;
272     /** mapi element 0x1006 PR_RTF_SYNC_BODY_CRC */
273     int32_t     rtf_body_crc;
274     /** mapi element 0x1008 PR_RTF_SYNC_BODY_TAG,
275      *  the first couple of lines of RTF body so that after modification, then beginning can
276      *  once again be found. */
277     pst_string  rtf_body_tag;
278     /** mapi element 0x1009 PR_RTF_COMPRESSED,
279      *  the compressed rtf body data.
280      *  Use pst_lzfu_decompress() to retrieve the actual rtf body data. */
281     pst_binary  rtf_compressed;
282     /** mapi element 0x0e1f PR_RTF_IN_SYNC,
283      *  True means that the rtf version is same as text body.
284      *  False means rtf version is more up-to-date than text body.
285      *  If this value doesn't exist, text body is more up-to-date than rtf and
286      *  cannot update to the rtf.
287      *  @li 1 true
288      *  @li 0 false */
289     int         rtf_in_sync;
290     /** mapi element 0x1010 PR_RTF_SYNC_PREFIX_COUNT,
291      *  a count of the ignored characters before the first significant character */
292     int32_t     rtf_ws_prefix_count;
293     /** mapi element 0x1011 PR_RTF_SYNC_TRAILING_COUNT,
294      *  a count of the ignored characters after the last significant character */
295     int32_t     rtf_ws_trailing_count;
296     /** mapi element 0x0064 PR_SENT_REPRESENTING_ADDRTYPE */
297     pst_string  sender_access;
298     /** mapi element 0x0065 PR_SENT_REPRESENTING_EMAIL_ADDRESS */
299     pst_string  sender_address;
300     /** mapi element 0x0c1e PR_SENDER_ADDRTYPE */
301     pst_string  sender2_access;
302     /** mapi element 0x0c1f PR_SENDER_EMAIL_ADDRESS */
303     pst_string  sender2_address;
304     /** mapi element 0x0036 PR_SENSITIVITY
305      *  @li 0=none
306      *  @li 1=personal
307      *  @li 2=private
308      *  @li 3=company confidential */
309     int32_t     sensitivity;
310     /** mapi element 0x0039 PR_CLIENT_SUBMIT_TIME */
311     FILETIME    *sent_date;
312     /** mapi element 0x0e0a PR_SENTMAIL_ENTRYID */
313     pst_entryid *sentmail_folder;
314     /** mapi element 0x0e04 PR_DISPLAY_TO */
315     pst_string  sentto_address;
316     /** mapi element 0x1001 PR_REPORT_TEXT, delivery report dsn body */
317     pst_string  report_text;
318     /** mapi element 0x0032 PR_REPORT_TIME, delivery report time */
319     FILETIME   *report_time;
320     /** mapi element 0x0c04 PR_NDR_REASON_CODE */
321     int32_t     ndr_reason_code;
322     /** mapi element 0x0c05 PR_NDR_DIAG_CODE */
323     int32_t     ndr_diag_code;
324     /** mapi element 0x0c1b PR_SUPPLEMENTARY_INFO */
325     pst_string  supplementary_info;
326     /** mapi element 0x0c20 PR_NDR_STATUS_CODE */
327     int32_t     ndr_status_code;
328 
329     // elements added for .msg processing
330     /** mapi element 0x0040 PR_RECEIVED_BY_NAME */
331     pst_string  outlook_received_name1;
332     /** mapi element 0x0c1a PR_SENDER_NAME */
333     pst_string  outlook_sender_name2;
334     /** mapi element 0x0e1d PR_NORMALIZED_SUBJECT */
335     pst_string  outlook_normalized_subject;
336     /** mapi element 0x300b PR_SEARCH_KEY */
337     pst_string  outlook_search_key;
338 } pst_item_email;
339 
340 
341 /** This contains the folder related mapi elements
342  */
343 typedef struct pst_item_folder {
344     /** mapi element 0x3602 PR_CONTENT_COUNT */
345     int32_t  item_count;
346     /** mapi element 0x3603 PR_CONTENT_UNREAD */
347     int32_t  unseen_item_count;
348     /** mapi element 0x3617 PR_ASSOC_CONTENT_COUNT
349         Associated content are items that are attached to this folder, but are hidden from users.
350     */
351     int32_t  assoc_count;
352     /** mapi element 0x360a PR_SUBFOLDERS
353      *  @li 1 true
354      *  @li 0 false */
355     /** mapi element  */
356     int      subfolder;
357 } pst_item_folder;
358 
359 
360 /** This contains the message store related mapi elements
361  */
362 typedef struct pst_item_message_store {
363     /** mapi element 0x35e0 */
364     pst_entryid *top_of_personal_folder;
365     /** mapi element 0x35e2 */
366     pst_entryid *default_outbox_folder;
367     /** mapi element 0x35e3 */
368     pst_entryid *deleted_items_folder;
369     /** mapi element 0x35e4 */
370     pst_entryid *sent_items_folder;
371     /** mapi element 0x35e5 */
372     pst_entryid *user_views_folder;
373     /** mapi element 0x35e6 */
374     pst_entryid *common_view_folder;
375     /** mapi element 0x35e7 */
376     pst_entryid *search_root_folder;
377     /** mapi element 0x7c07 */
378     pst_entryid *top_of_folder;
379     /** mapi element 0x35df,
380      *  bit mask of folders in this message store
381      *  @li  0x1 FOLDER_IPM_SUBTREE_VALID
382      *  @li  0x2 FOLDER_IPM_INBOX_VALID
383      *  @li  0x4 FOLDER_IPM_OUTBOX_VALID
384      *  @li  0x8 FOLDER_IPM_WASTEBOX_VALID
385      *  @li 0x10 FOLDER_IPM_SENTMAIL_VALID
386      *  @li 0x20 FOLDER_VIEWS_VALID
387      *  @li 0x40 FOLDER_COMMON_VIEWS_VALID
388      *  @li 0x80 FOLDER_FINDER_VALID */
389     int32_t valid_mask;
390     /** mapi element 0x76ff */
391     int32_t pwd_chksum;
392 } pst_item_message_store;
393 
394 
395 /** This contains the contact related mapi elements
396  */
397 typedef struct pst_item_contact {
398     /** mapi element 0x3a00 PR_ACCOUNT */
399     pst_string  account_name;
400     /** mapi element 0x3003 PR_EMAIL_ADDRESS, or 0x8083 */
401     pst_string  address1;
402     /** mapi element 0x8085 */
403     pst_string  address1a;
404     /** mapi element 0x8084 */
405     pst_string  address1_desc;
406     /** mapi element 0x3002 PR_ADDRTYPE, or 0x8082 */
407     pst_string  address1_transport;
408     /** mapi element 0x8093 */
409     pst_string  address2;
410     /** mapi element 0x8095 */
411     pst_string  address2a;
412     /** mapi element 0x8094 */
413     pst_string  address2_desc;
414     /** mapi element 0x8092 */
415     pst_string  address2_transport;
416     /** mapi element 0x80a3 */
417     pst_string  address3;
418     /** mapi element 0x80a5 */
419     pst_string  address3a;
420     /** mapi element 0x80a4 */
421     pst_string  address3_desc;
422     /** mapi element 0x80a2 */
423     pst_string  address3_transport;
424     /** mapi element 0x3a30 PR_ASSISTANT */
425     pst_string  assistant_name;
426     /** mapi element 0x3a2e PR_ASSISTANT_TELEPHONE_NUMBER */
427     pst_string  assistant_phone;
428     /** mapi element 0x8535 */
429     pst_string  billing_information;
430     /** mapi element 0x3a42 PR_BIRTHDAY */
431     FILETIME   *birthday;
432     /** mapi element 0x801b */
433     pst_string  business_address;
434     /** mapi element 0x3a27 PR_BUSINESS_ADDRESS_CITY */
435     pst_string  business_city;
436     /** mapi element 0x3a26 PR_BUSINESS_ADDRESS_COUNTRY */
437     pst_string  business_country;
438     /** mapi element 0x3a24 PR_BUSINESS_FAX_NUMBER */
439     pst_string  business_fax;
440     /** mapi element 0x3a51 PR_BUSINESS_HOME_PAGE */
441     pst_string  business_homepage;
442     /** mapi element 0x3a08 PR_BUSINESS_TELEPHONE_NUMBER */
443     pst_string  business_phone;
444     /** mapi element 0x3a1b PR_BUSINESS2_TELEPHONE_NUMBER */
445     pst_string  business_phone2;
446     /** mapi element 0x3a2b PR_BUSINESS_PO_BOX */
447     pst_string  business_po_box;
448     /** mapi element 0x3a2a PR_BUSINESS_POSTAL_CODE */
449     pst_string  business_postal_code;
450     /** mapi element 0x3a28 PR_BUSINESS_ADDRESS_STATE_OR_PROVINCE */
451     pst_string  business_state;
452     /** mapi element 0x3a29 PR_BUSINESS_ADDRESS_STREET */
453     pst_string  business_street;
454     /** mapi element 0x3a02 PR_CALLBACK_TELEPHONE_NUMBER */
455     pst_string  callback_phone;
456     /** mapi element 0x3a1e PR_CAR_TELEPHONE_NUMBER */
457     pst_string  car_phone;
458     /** mapi element 0x3a57 PR_COMPANY_MAIN_PHONE_NUMBER */
459     pst_string  company_main_phone;
460     /** mapi element 0x3a16 PR_COMPANY_NAME */
461     pst_string  company_name;
462     /** mapi element 0x3a49 PR_COMPUTER_NETWORK_NAME */
463     pst_string  computer_name;
464     /** mapi element 0x3a4a PR_CUSTOMER_ID */
465     pst_string  customer_id;
466     /** mapi element 0x3a15 PR_POSTAL_ADDRESS */
467     pst_string  def_postal_address;
468     /** mapi element 0x3a18 PR_DEPARTMENT_NAME */
469     pst_string  department;
470     /** mapi element 0x3a45 PR_DISPLAY_NAME_PREFIX */
471     pst_string  display_name_prefix;
472     /** mapi element 0x3a06 PR_GIVEN_NAME */
473     pst_string  first_name;
474     /** mapi element 0x8530 */
475     pst_string  followup;
476     /** mapi element 0x80d8 */
477     pst_string  free_busy_address;
478     /** mapi element 0x3a4c PR_FTP_SITE */
479     pst_string  ftp_site;
480     /** mapi element 0x8005 */
481     pst_string  fullname;
482     /** mapi element 0x3a4d PR_GENDER
483      *  @li 0 unspecified
484      *  @li 1 female
485      *  @li 2 male */
486     int16_t     gender;
487     /** mapi element 0x3a07 PR_GOVERNMENT_ID_NUMBER */
488     pst_string  gov_id;
489     /** mapi element 0x3a43 PR_HOBBIES */
490     pst_string  hobbies;
491     /** mapi element 0x801a */
492     pst_string  home_address;
493     /** mapi element 0x3a59 PR_HOME_ADDRESS_CITY */
494     pst_string  home_city;
495     /** mapi element 0x3a5a PR_HOME_ADDRESS_COUNTRY */
496     pst_string  home_country;
497     /** mapi element 0x3a25 PR_HOME_FAX_NUMBER */
498     pst_string  home_fax;
499     /** mapi element 0x3a09 PR_HOME_TELEPHONE_NUMBER */
500     pst_string  home_phone;
501     /** mapi element 0x3a2f PR_HOME2_TELEPHONE_NUMBER */
502     pst_string  home_phone2;
503     /** mapi element 0x3a5e PR_HOME_ADDRESS_POST_OFFICE_BOX */
504     pst_string  home_po_box;
505     /** mapi element 0x3a5b PR_HOME_ADDRESS_POSTAL_CODE */
506     pst_string  home_postal_code;
507     /** mapi element 0x3a5c PR_HOME_ADDRESS_STATE_OR_PROVINCE */
508     pst_string  home_state;
509     /** mapi element 0x3a5d PR_HOME_ADDRESS_STREET */
510     pst_string  home_street;
511     /** mapi element 0x3a0a PR_INITIALS */
512     pst_string  initials;
513     /** mapi element 0x3a2d PR_ISDN_NUMBER */
514     pst_string  isdn_phone;
515     /** mapi element 0x3a17 PR_TITLE */
516     pst_string  job_title;
517     /** mapi element 0x3a0b PR_KEYWORD */
518     pst_string  keyword;
519     /** mapi element 0x3a0c PR_LANGUAGE */
520     pst_string  language;
521     /** mapi element 0x3a0d PR_LOCATION */
522     pst_string  location;
523     /** mapi element 0x3a0e PR_MAIL_PERMISSION
524      *  @li 1 true
525      *  @li 0 false */
526     int         mail_permission;
527     /** mapi element 0x3a4e PR_MANAGER_NAME */
528     pst_string  manager_name;
529     /** mapi element 0x3a44 PR_MIDDLE_NAME */
530     pst_string  middle_name;
531     /** mapi element 0x8534 */
532     pst_string  mileage;
533     /** mapi element 0x3a1c PR_MOBILE_TELEPHONE_NUMBER */
534     pst_string  mobile_phone;
535     /** mapi element 0x3a4f PR_NICKNAME */
536     pst_string  nickname;
537     /** mapi element 0x3a19 PR_OFFICE_LOCATION */
538     pst_string  office_loc;
539     /** mapi element 0x3a0f PR_MHS_COMMON_NAME */
540     pst_string  common_name;
541     /** mapi element 0x3a10 PR_ORGANIZATIONAL_ID_NUMBER */
542     pst_string  org_id;
543     /** mapi element 0x801c */
544     pst_string  other_address;
545     /** mapi element 0x3a5f PR_OTHER_ADDRESS_CITY */
546     pst_string  other_city;
547     /** mapi element 0x3a60 PR_OTHER_ADDRESS_COUNTRY */
548     pst_string  other_country;
549     /** mapi element 0x3a1f PR_OTHER_TELEPHONE_NUMBER */
550     pst_string  other_phone;
551     /** mapi element 0x3a64 PR_OTHER_ADDRESS_POST_OFFICE_BOX */
552     pst_string  other_po_box;
553     /** mapi element 0x3a61 PR_OTHER_ADDRESS_POSTAL_CODE */
554     pst_string  other_postal_code;
555     /** mapi element 0x3a62 PR_OTHER_ADDRESS_STATE_OR_PROVINCE */
556     pst_string  other_state;
557     /** mapi element 0x3a63 PR_OTHER_ADDRESS_STREET */
558     pst_string  other_street;
559     /** mapi element 0x3a21 PR_PAGER_TELEPHONE_NUMBER */
560     pst_string  pager_phone;
561     /** mapi element 0x3a50 PR_PERSONAL_HOME_PAGE */
562     pst_string  personal_homepage;
563     /** mapi element 0x3a47 PR_PREFERRED_BY_NAME */
564     pst_string  pref_name;
565     /** mapi element 0x3a23 PR_PRIMARY_FAX_NUMBER */
566     pst_string  primary_fax;
567     /** mapi element 0x3a1a PR_PRIMARY_TELEPHONE_NUMBER */
568     pst_string  primary_phone;
569     /** mapi element 0x3a46 PR_PROFESSION */
570     pst_string  profession;
571     /** mapi element 0x3a1d PR_RADIO_TELEPHONE_NUMBER */
572     pst_string  radio_phone;
573     /** mapi element 0x3a40 PR_SEND_RICH_INFO
574      *  @li 1 true
575      *  @li 0 false */
576     int         rich_text;
577     /** mapi element 0x3a48 PR_SPOUSE_NAME */
578     pst_string  spouse_name;
579     /** mapi element 0x3a05 PR_GENERATION (Jr., Sr., III, etc) */
580     pst_string  suffix;
581     /** mapi element 0x3a11 PR_SURNAME */
582     pst_string  surname;
583     /** mapi element 0x3a2c PR_TELEX_NUMBER */
584     pst_string  telex;
585     /** mapi element 0x3a20 PR_TRANSMITTABLE_DISPLAY_NAME */
586     pst_string  transmittable_display_name;
587     /** mapi element 0x3a4b PR_TTYTDD_PHONE_NUMBER */
588     pst_string  ttytdd_phone;
589     /** mapi element 0x3a41 PR_WEDDING_ANNIVERSARY */
590     FILETIME   *wedding_anniversary;
591     /** mapi element 0x8045 */
592     pst_string  work_address_street;
593     /** mapi element 0x8046 */
594     pst_string  work_address_city;
595     /** mapi element 0x8047 */
596     pst_string  work_address_state;
597     /** mapi element 0x8048 */
598     pst_string  work_address_postalcode;
599     /** mapi element 0x8049 */
600     pst_string  work_address_country;
601     /** mapi element 0x804a */
602     pst_string  work_address_postofficebox;
603 } pst_item_contact;
604 
605 
606 /** This contains the attachment related mapi elements
607  */
608 typedef struct pst_item_attach {
609     /** mapi element 0x3704 PR_ATTACH_FILENAME */
610     pst_string      filename1;
611     /** mapi element 0x3707 PR_ATTACH_LONG_FILENAME */
612     pst_string      filename2;
613     /** mapi element 0x370e PR_ATTACH_MIME_TAG */
614     pst_string      mimetype;
615     /** mapi element 0x3712 PR_ATTACH_CONTENT_ID  */
616     pst_string      content_id;
617     /** mapi element 0x3701 PR_ATTACH_DATA_OBJ */
618     pst_binary      data;
619     /** only used if the attachment is by reference, in which case this is the id2 reference */
620     uint64_t        id2_val;
621     /** calculated from id2_val during creation of record */
622     uint64_t        i_id;
623     /** id2 tree needed to resolve attachments by reference */
624     pst_id2_tree    *id2_head;
625     /** mapi element 0x3705 PR_ATTACH_METHOD
626      *  @li 0 no attachment
627      *  @li 1 attach by value
628      *  @li 2 attach by reference
629      *  @li 3 attach by reference resolve
630      *  @li 4 attach by reference only
631      *  @li 5 embedded message
632      *  @li 6 OLE */
633     int32_t         method;
634     /** mapi element 0x370b PR_RENDERING_POSITION */
635     int32_t         position;
636     /** mapi element 0x3710 PR_ATTACH_MIME_SEQUENCE */
637     int32_t         sequence;
638     struct pst_item_attach *next;
639 } pst_item_attach;
640 
641 
642 /** linked list of extra header fields */
643 typedef struct pst_item_extra_field {
644     char   *field_name;
645     char   *value;
646     struct pst_item_extra_field *next;
647 } pst_item_extra_field;
648 
649 
650 /** This contains the journal related mapi elements
651  */
652 typedef struct pst_item_journal {
653     /** mapi element 0x8706 */
654     FILETIME   *start;
655     /** mapi element 0x8708 */
656     FILETIME   *end;
657     /** mapi element 0x8700 */
658     pst_string  type;
659     /** mapi element 0x8712 */
660     pst_string  description;
661 } pst_item_journal;
662 
663 
664 /** This contains the recurrence data separated into fields.
665     http://www.geocities.com/cainrandom/dev/MAPIRecurrence.html
666 */
667 typedef struct pst_recurrence {
668     /** 0x30043004 */
669     uint32_t    signature;
670     /** @li 0 daily
671      *  @li 1 weekly
672      *  @li 2 monthly
673      *  @li 3 yearly */
674     uint32_t    type;
675     /** implies number of recurrence parameters
676      *  @li 0 has 3 parameters
677      *  @li 1 has 4 parameters
678      *  @li 2 has 4 parameters
679      *  @li 3 has 5 parameters
680      */
681     uint32_t    sub_type;
682     /** must be contiguous, not an array to make Python interface easier */
683     uint32_t    parm1;
684     uint32_t    parm2;
685     uint32_t    parm3;
686     uint32_t    parm4;
687     uint32_t    parm5;
688     /** type of termination of the recurrence
689         @li 0 terminates on a date
690         @li 1 terminates based on integer number of occurrences
691         @li 2 never terminates
692      */
693     uint32_t    termination;
694     /** recurrence interval in terms of the recurrence type */
695     uint32_t    interval;
696     /** bit mask of days of the week */
697     uint32_t    bydaymask;
698     /** day of month for monthly and yearly recurrences */
699     uint32_t    dayofmonth;
700     /** month of year for yearly recurrences */
701     uint32_t    monthofyear;
702     /** occurrence of day for 2nd Tuesday of month, in which case position is 2 */
703     uint32_t    position;
704     /** number of occurrences, even if recurrence terminates based on date */
705     uint32_t    count;
706     // there is more data, including the termination date,
707     // but we can get that from other mapi elements.
708 } pst_recurrence;
709 
710 
711 /** This contains the appointment related mapi elements
712  */
713 typedef struct pst_item_appointment {
714     /** mapi element 0x820d PR_OUTLOOK_EVENT_START_DATE */
715     FILETIME   *start;
716     /** mapi element 0x820e PR_OUTLOOK_EVENT_START_END */
717     FILETIME   *end;
718     /** mapi element 0x8208 PR_OUTLOOK_EVENT_LOCATION */
719     pst_string  location;
720     /** mapi element 0x8503 PR_OUTLOOK_COMMON_REMINDER_SET
721      *  @li 1 true
722      *  @li 0 false */
723     int         alarm;
724     /** mapi element 0x8560 */
725     FILETIME   *reminder;
726     /** mapi element 0x8501 PR_OUTLOOK_COMMON_REMINDER_MINUTES_BEFORE */
727     int32_t     alarm_minutes;
728     /** mapi element 0x851f */
729     pst_string  alarm_filename;
730     /** mapi element 0x8234 */
731     pst_string  timezonestring;
732     /** mapi element 0x8205 PR_OUTLOOK_EVENT_SHOW_TIME_AS
733      *  @li 0 free
734      *  @li 1 tentative
735      *  @li 2 busy
736      *  @li 3 out of office*/
737     int32_t     showas;
738     /** mapi element 0x8214
739      *  @li 0 None
740      *  @li 1 Important
741      *  @li 2 Business
742      *  @li 3 Personal
743      *  @li 4 Vacation
744      *  @li 5 Must Attend
745      *  @li 6 Travel Required
746      *  @li 7 Needs Preparation
747      *  @li 8 Birthday
748      *  @li 9 Anniversary
749      *  @li 10 Phone Call */
750     int32_t     label;
751     /** mapi element 0x8215 PR_OUTLOOK_EVENT_ALL_DAY
752      *  @li 1 true
753      *  @li 0 false */
754     int         all_day;
755     /** mapi element 0x8223 PR_OUTLOOK_EVENT_IS_RECURRING
756      *  @li 1 true
757      *  @li 0 false */
758     int         is_recurring;
759     /** mapi element 0x8231
760      *  @li 0 none
761      *  @li 1 daily
762      *  @li 2 weekly
763      *  @li 3 monthly
764      *  @li 4 yearly */
765     int32_t     recurrence_type;
766     /** mapi element 0x8232 recurrence description */
767     pst_string  recurrence_description;
768     /** mapi element 0x8216 recurrence data */
769     pst_binary  recurrence_data;
770     /** mapi element 0x8235 PR_OUTLOOK_EVENT_RECURRENCE_START */
771     FILETIME   *recurrence_start;
772     /** mapi element 0x8236 PR_OUTLOOK_EVENT_RECURRENCE_END  */
773     FILETIME   *recurrence_end;
774 } pst_item_appointment;
775 
776 
777 /** This contains the common mapi elements, and pointers to structures for
778  *  each major mapi item type. It represents a complete mapi object.
779  */
780 typedef struct pst_item {
781     /** pointer to the pst_file */
782     struct pst_file        *pf;
783     /** block id that can be used to generate uid */
784     uint64_t               block_id;
785     /** email mapi elements */
786     pst_item_email         *email;
787     /** folder mapi elements */
788     pst_item_folder        *folder;
789     /** contact mapi elements */
790     pst_item_contact       *contact;
791     /** linked list of attachments */
792     pst_item_attach        *attach;
793     /** message store mapi elements */
794     pst_item_message_store *message_store;
795     /** linked list of extra headers and such */
796     pst_item_extra_field   *extra_fields;
797     /** journal mapi elements */
798     pst_item_journal       *journal;
799     /** calendar mapi elements */
800     pst_item_appointment   *appointment;
801     /** derived from mapi elements 0x001a PR_MESSAGE_CLASS or 0x3613 PR_CONTAINER_CLASS
802      *  @li  1 PST_TYPE_NOTE
803      *  @li  2 PST_TYPE_SCHEDULE
804      *  @li  8 PST_TYPE_APPOINTMENT
805      *  @li  9 PST_TYPE_CONTACT
806      *  @li 10 PST_TYPE_JOURNAL
807      *  @li 11 PST_TYPE_STICKYNOTE
808      *  @li 12 PST_TYPE_TASK
809      *  @li 13 PST_TYPE_OTHER
810      *  @li 14 PST_TYPE_REPORT */
811     int         type;
812     /** mapi element 0x001a PR_MESSAGE_CLASS or 0x3613 PR_CONTAINER_CLASS */
813     char       *ascii_type;
814     /** mapi element 0x0e07 PR_MESSAGE_FLAGS
815      *  @li 0x01 Read
816      *  @li 0x02 Unmodified
817      *  @li 0x04 Submit
818      *  @li 0x08 Unsent
819      *  @li 0x10 Has Attachments
820      *  @li 0x20 From Me
821      *  @li 0x40 Associated
822      *  @li 0x80 Resend
823      *  @li 0x100 RN Pending
824      *  @li 0x200 NRN Pending */
825     int32_t     flags;
826     /** mapi element 0x3001 PR_DISPLAY_NAME */
827     pst_string  file_as;
828     /** mapi element 0x3004 PR_COMMENT */
829     pst_string  comment;
830     /** derived from extra_fields["content-type"] if it contains a charset= subfield  */
831     pst_string  body_charset;
832     /** mapi element 0x1000 PR_BODY */
833     pst_string  body;
834     /** mapi element 0x0037 PR_SUBJECT */
835     pst_string  subject;
836     /** mapi element 0x3fde PR_INTERNET_CPID */
837     int32_t     internet_cpid;
838     /** mapi element 0x3ffd PR_MESSAGE_CODEPAGE */
839     int32_t     message_codepage;
840     /** mapi element 0x0e08 PR_MESSAGE_SIZE */
841     int32_t     message_size;
842     /** mapi element 0x8554 PR_OUTLOOK_VERSION */
843     pst_string  outlook_version;
844     /** mapi element 0x0ff9 PR_RECORD_KEY */
845     pst_binary  record_key;
846     /** mapi element 0x65e3 PR_PREDECESSOR_CHANGE_LIST */
847     pst_binary  predecessor_change;
848     /** mapi element 0x0063 PR_RESPONSE_REQUESTED
849      *  @li 1 true
850      *  @li 0 false */
851     int         response_requested;
852     /** mapi element 0x3007 PR_CREATION_TIME */
853     FILETIME   *create_date;
854     /** mapi element 0x3008 PR_LAST_MODIFICATION_TIME */
855     FILETIME   *modify_date;
856     /** mapi element 0x002b PR_RECIPIENT_REASSIGNMENT_PROHIBITED
857      *  @li 1 true
858      *  @li 0 false */
859     int         private_member;
860 } pst_item;
861 
862 
863 /** Linked list of extended attributes.
864  *  This is used to convert mapi_id values in the pst file into
865  *  canonical mapi_id values to be used in this code. This list
866  *  is kept in sorted order, where the key is the 'map' field.
867  *  Some mapi_id values are converted to canonical mapi_id values
868  *  (PST_MAP_ATTRIB), and others are converted to a string
869  *  (PST_ATTRIB_HEADER).
870  */
871 typedef struct pst_x_attrib_ll {
872     /** @li 1 PST_MAP_ATTRIB map->int attribute
873         @li 2 PST_MAP_HEADER map->string header
874      */
875     uint32_t mytype;
876     /** key for the mapping */
877     uint32_t map;
878     /** data target of the mapping, either uint32_t or string */
879     void     *data;
880     /** link to next item in the list */
881     struct pst_x_attrib_ll *next;
882 } pst_x_attrib_ll;
883 
884 
885 /** this is only used for internal debugging */
886 typedef struct pst_block_recorder {
887     struct pst_block_recorder  *next;
888     int64_t                     offset;
889     size_t                      size;
890     int                         readcount;
891 } pst_block_recorder;
892 
893 
894 typedef struct pst_file {
895     /** file pointer to opened PST file */
896     FILE*   fp;
897     /** original cwd when the file was opened */
898     char*   cwd;
899     /** original file name when the file was opened */
900     char*   fname;
901     /** default character set for items without one */
902     const char*   charset;
903     /** the array of index structures */
904     pst_index_ll *i_table;
905     size_t i_count, i_capacity;
906     /** the head and tail of the top level of the descriptor tree */
907     pst_desc_tree  *d_head, *d_tail;
908     /** the head of the extended attributes linked list */
909     pst_x_attrib_ll *x_head;
910     /** the head of the block recorder, a debug artifact
911      *  used to detect cases where we might read the same
912      *  block multiple times while processing a pst file. */
913     pst_block_recorder *block_head;
914 
915     /** @li 0 is 32-bit pst file, pre Outlook 2003;
916      *  @li 1 is 64-bit pst file, Outlook 2003 or later;
917      *  @li 2 is 64-bit OST file, Outlook 2013 or later */
918     int do_read64;
919     /** file offset of the first b-tree node in the index tree */
920     uint64_t index1;
921     /** back pointer value in the first b-tree node in the index tree */
922     uint64_t index1_back;
923     /** file offset of the first b-tree node in the descriptor tree*/
924     uint64_t index2;
925     /** back pointer value in the first b-tree node in the descriptor tree */
926     uint64_t index2_back;
927     /** size of the pst file */
928     uint64_t size;
929     /** @li 0 PST_NO_ENCRYPT, none
930      *  @li 1 PST_COMP_ENCRYPT, simple byte substitution cipher with fixed key
931      *  @li 2 PST_ENCRYPT, German enigma 3 rotor cipher with fixed key */
932     unsigned char encryption;
933     /** index type or file type
934      *  @li 0x0e 32 bit pre Outlook 2003
935      *  @li 0x0f 32 bit pre Outlook 2003
936      *  @li 0x15 64 bit Outlook 2003 or later
937      *  @li 0x17 64 bit Outlook 2003 or later */
938     unsigned char ind_type;
939 } pst_file;
940 
941 
942 /** Open a pst file.
943  * @param pf       pointer to uninitialized pst_file structure. This structure
944  *                 will be filled in by this function.
945  * @param name     name of the file, suitable for fopen().
946  * @param charset  default charset for item with unspecified character sets
947  * @return 0 if ok, -1 if error
948  */
949 int             pst_open(pst_file *pf, const char *name, const char *charset);
950 
951 
952 /** Reopen the pst file after a fork
953  * @param pf   pointer to the pst_file structure setup by pst_open().
954  * @return 0 if ok, -1 if error
955  */
956 int             pst_reopen(pst_file *pf);
957 
958 
959 /** Load the index entries from the pst file. This loads both the
960  *  i_id linked list, and the d_id tree, and should normally be the
961  *  first call after pst_open().
962  * @param pf pointer to the pst_file structure setup by pst_open().
963  */
964 int             pst_load_index (pst_file *pf);
965 
966 
967 /** Load the extended attribute mapping table from the pst file. This
968  *  should normally be the second call after pst_open().
969  * @param pf pointer to the pst_file structure setup by pst_open().
970  */
971 int             pst_load_extended_attributes(pst_file *pf);
972 
973 
974 /** Close a pst file.
975  * @param pf pointer to the pst_file structure setup by pst_open().
976  */
977 int             pst_close(pst_file *pf);
978 
979 
980 /** Get the top of folders descriptor tree. This is the main descriptor tree
981  *  that needs to be walked to look at every item in the pst file.
982  * @param pf   pointer to the pst_file structure setup by pst_open().
983  * @param root root item, which can be obtained by pst_parse_item(pf, pf->d_head, NULL).
984  */
985 pst_desc_tree*  pst_getTopOfFolders(pst_file *pf, const pst_item *root);
986 
987 
988 /** Assemble the binary attachment into a single buffer.
989  * @param pf     pointer to the pst_file structure setup by pst_open().
990  * @param attach pointer to the attachment record
991  * @return       structure containing size of and pointer to the buffer.
992  *               the caller must free this buffer.
993  */
994 pst_binary      pst_attach_to_mem(pst_file *pf, pst_item_attach *attach);
995 
996 
997 /** Write a binary attachment to a file.
998  * @param pf     pointer to the pst_file structure setup by pst_open().
999  * @param attach pointer to the attachment record
1000  * @param fp     pointer to an open FILE.
1001  */
1002 size_t          pst_attach_to_file(pst_file *pf, pst_item_attach *attach, FILE* fp);
1003 
1004 
1005 /** Write a binary attachment base64 encoded to a file.
1006  * @param pf     pointer to the pst_file structure setup by pst_open().
1007  * @param attach pointer to the attachment record
1008  * @param fp     pointer to an open FILE.
1009  */
1010 size_t          pst_attach_to_file_base64(pst_file *pf, pst_item_attach *attach, FILE* fp);
1011 
1012 
1013 /** Walk the descriptor tree.
1014  * @param d pointer to the current item in the descriptor tree.
1015  * @return  pointer to the next item in the descriptor tree.
1016  */
1017 pst_desc_tree*  pst_getNextDptr(pst_desc_tree* d);
1018 
1019 
1020 /** Assemble a mapi object from a descriptor pointer.
1021  * @param pf     pointer to the pst_file structure setup by pst_open().
1022  * @param d_ptr  pointer to an item in the descriptor tree.
1023  * @param m_head normally NULL. This is only used when processing embedded
1024  *               attached rfc822 messages, in which case it is attach->id2_head.
1025  * @return pointer to the mapi object. Must be free'd by pst_freeItem().
1026  */
1027 pst_item*       pst_parse_item (pst_file *pf, pst_desc_tree *d_ptr, pst_id2_tree *m_head);
1028 
1029 
1030 /** Free the item returned by pst_parse_item().
1031  * @param item  pointer to item returned from pst_parse_item().
1032  */
1033 void            pst_freeItem(pst_item *item);
1034 
1035 
1036 /** Lookup the i_id in the index linked list, and return a pointer to the element.
1037  * @param pf     pointer to the pst_file structure setup by pst_open().
1038  * @param i_id   key for the index linked list
1039  * @return pointer to the element, or NULL if not found.
1040  */
1041 pst_index_ll*   pst_getID(pst_file* pf, uint64_t i_id);
1042 
1043 
1044 /** Get an ID block from the file using pst_ff_getIDblock() and decrypt if necessary.
1045  * @param pf   pointer to the pst_file structure setup by pst_open().
1046  * @param i_id ID of block to retrieve
1047  * @param buf  reference to pointer to buffer that will contain the data block.
1048  *             If this pointer is non-NULL, it will first be free()d.
1049  * @return     Size of block read into memory
1050  */
1051 size_t          pst_ff_getIDblock_dec(pst_file *pf, uint64_t i_id, char **buf);
1052 
1053 
1054 /** compare strings case-insensitive.
1055  *  @return  -1 if a < b, 0 if a==b, 1 if a > b
1056  */
1057 int pst_stricmp(char *a, char *b);
1058 
1059 
1060 /** fwrite with checking for null pointer.
1061  * @param ptr pointer to the buffer
1062  * @param size  size of each item
1063  * @param nmemb number of items
1064  * @param stream output file
1065  * @return number of bytes written, zero if ptr==NULL
1066  */
1067 size_t          pst_fwrite(const void* ptr, size_t size, size_t nmemb, FILE* stream);
1068 
1069 
1070 /** Add any necessary escape characters for rfc2426 vcard format
1071  * @param[in]     str       pointer to input string
1072  * @param[in,out] result    pointer to a char* pointer that may be realloc'ed if needed
1073  * @param[in,out] resultlen size of the result buffer
1074  * @return    pointer to output string, either the input pointer if
1075  *            there are no characters that need escapes, or a pointer
1076  *            to a possibly realloc'ed result buffer.
1077  */
1078 char*           pst_rfc2426_escape(char* str, char** result, size_t* resultlen);
1079 
1080 
1081 /** Convert a FILETIME into rfc2425 date/time format 1953-10-15T23:10:00Z
1082  *  which is the same as one of the forms in the ISO3601 standard
1083  * @param[in]  ft      time to be converted
1084  * @param[in]  buflen  length of the output buffer
1085  * @param[out] result  pointer to output buffer, must be at least 30 bytes
1086  * @return   time in rfc2425 format
1087  */
1088 char*           pst_rfc2425_datetime_format(const FILETIME* ft, int buflen, char* result);
1089 
1090 
1091 /** Convert a FILETIME into rfc2445 date/time format 19531015T231000Z
1092  * @param[in]  ft      time to be converted
1093  * @param[in]  buflen  length of the output buffer
1094  * @param[out] result  pointer to output buffer, must be at least 30 bytes
1095  * @return   time in rfc2445 format
1096  */
1097 char*           pst_rfc2445_datetime_format(const FILETIME* ft, int buflen, char* result);
1098 
1099 
1100 /** Convert the current time rfc2445 date/time format 19531015T231000Z
1101  * @param[in]  buflen  length of the output buffer
1102  * @param[out] result  pointer to output buffer, must be at least 30 bytes
1103  * @return   time in rfc2445 format
1104  */
1105 char*           pst_rfc2445_datetime_format_now(int buflen, char* result);
1106 
1107 
1108 /** Get the default character set for this item. This is used to find
1109  *  the charset for pst_string elements that are not already in utf8 encoding.
1110  * @param      item    pointer to the mapi item of interest
1111  * @param[in]  buflen  length of the output buffer
1112  * @param[out] result  pointer to output buffer, must be at least 30 bytes
1113  * @return default character set as a string usable by iconv()
1114  */
1115 const char*     pst_default_charset(pst_item *item, int buflen, char* result);
1116 
1117 
1118 /** Convert str to rfc2231 encoding of str
1119  *  @param str   pointer to the mapi string of interest
1120  */
1121 void            pst_rfc2231(pst_string *str);
1122 
1123 
1124 /** Convert str to rfc2047 encoding of str, possibly enclosed in quotes if it contains spaces
1125  *  @param item          pointer to the containing mapi item
1126  *  @param str           pointer to the mapi string of interest
1127  *  @param needs_quote   true if strings containing spaces should be wrapped in quotes
1128  */
1129 void            pst_rfc2047(pst_item *item, pst_string *str, int needs_quote);
1130 
1131 
1132 /** Convert str to utf8 if possible; null strings are preserved.
1133  * @param item  pointer to the containing mapi item
1134  * @param str   pointer to the mapi string of interest
1135  */
1136 void            pst_convert_utf8_null(pst_item *item, pst_string *str);
1137 
1138 
1139 /** Convert str to utf8 if possible; null strings are converted into empty strings.
1140  * @param item  pointer to the containing mapi item
1141  * @param str   pointer to the mapi string of interest
1142  */
1143 void            pst_convert_utf8(pst_item *item, pst_string *str);
1144 
1145 
1146 /** Decode raw recurrence data into a better structure.
1147  * @param appt pointer to appointment structure
1148  * @return     pointer to decoded recurrence structure that must be free'd by the caller.
1149  */
1150 pst_recurrence* pst_convert_recurrence(pst_item_appointment* appt);
1151 
1152 
1153 /** Free a recurrence structure.
1154  * @param r input pointer to be freed
1155  */
1156 void            pst_free_recurrence(pst_recurrence* r);
1157 
1158 
1159 
1160 // switch from maximal packing back to default packing
1161 // undo the packing from the beginning of this file
1162 #ifdef _MSC_VER
1163     #pragma pack(pop)
1164 #endif
1165 #if defined(__GNUC__) || defined (__SUNPRO_C) || defined(__SUNPRO_CC)
1166     #pragma pack()
1167 #endif
1168 
1169 
1170 
1171 #ifdef __cplusplus
1172 }
1173 #endif
1174 
1175 
1176 
1177 #endif
1178