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