Mercurial > libpst
view src/libpst.h @ 308:97c53c6868ab
add -m option to readpst to create Outlook .msg files
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Sun, 13 Dec 2009 14:48:20 -0800 |
parents | 1d50ff3c5091 |
children | c4537664ff50 |
line wrap: on
line source
/*** * libpst.h * Part of LibPST project * Written by David Smith * dave.s@earthcorp.com */ // LibPST - Library for Accessing Outlook .pst files // Dave Smith - davesmith@users.sourceforge.net #ifndef __PST_LIBPST_H #define __PST_LIBPST_H #include "common.h" // switch to maximal packing for all structures in the libpst interface // this is reverted at the end of this file #ifdef _MSC_VER #pragma pack(push, 1) #endif #if defined(__GNUC__) || defined (__SUNPRO_C) || defined(__SUNPRO_CC) #pragma pack(1) #endif #define PST_TYPE_NOTE 1 #define PST_TYPE_SCHEDULE 2 #define PST_TYPE_APPOINTMENT 8 #define PST_TYPE_CONTACT 9 #define PST_TYPE_JOURNAL 10 #define PST_TYPE_STICKYNOTE 11 #define PST_TYPE_TASK 12 #define PST_TYPE_OTHER 13 #define PST_TYPE_REPORT 14 // defines types of possible encryption #define PST_NO_ENCRYPT 0 #define PST_COMP_ENCRYPT 1 #define PST_ENCRYPT 2 // defines different types of mappings #define PST_MAP_ATTRIB (uint32_t)1 #define PST_MAP_HEADER (uint32_t)2 // define my custom email attributes. #define PST_ATTRIB_HEADER -1 // defines types of free/busy values for appointment->showas #define PST_FREEBUSY_FREE 0 #define PST_FREEBUSY_TENTATIVE 1 #define PST_FREEBUSY_BUSY 2 #define PST_FREEBUSY_OUT_OF_OFFICE 3 // defines labels for appointment->label #define PST_APP_LABEL_NONE 0 #define PST_APP_LABEL_IMPORTANT 1 #define PST_APP_LABEL_BUSINESS 2 #define PST_APP_LABEL_PERSONAL 3 #define PST_APP_LABEL_VACATION 4 #define PST_APP_LABEL_MUST_ATTEND 5 #define PST_APP_LABEL_TRAVEL_REQ 6 #define PST_APP_LABEL_NEEDS_PREP 7 #define PST_APP_LABEL_BIRTHDAY 8 #define PST_APP_LABEL_ANNIVERSARY 9 #define PST_APP_LABEL_PHONE_CALL 10 // define type of recuring event #define PST_APP_RECUR_NONE 0 #define PST_APP_RECUR_DAILY 1 #define PST_APP_RECUR_WEEKLY 2 #define PST_APP_RECUR_MONTHLY 3 #define PST_APP_RECUR_YEARLY 4 // define attachment types #define PST_ATTACH_NONE 0 #define PST_ATTACH_BY_VALUE 1 #define PST_ATTACH_BY_REF 2 #define PST_ATTACH_BY_REF_RESOLV 3 #define PST_ATTACH_BY_REF_ONLY 4 #define PST_ATTACH_EMBEDDED 5 #define PST_ATTACH_OLE 6 typedef struct pst_entryid { int32_t u1; char entryid[16]; uint32_t id; } pst_entryid; typedef struct pst_index_ll { uint64_t i_id; uint64_t offset; uint64_t size; int64_t u1; struct pst_index_ll *next; } pst_index_ll; typedef struct pst_id2_tree { uint64_t id2; pst_index_ll *id; struct pst_id2_tree *child; struct pst_id2_tree *next; } pst_id2_tree; typedef struct pst_desc_tree { uint64_t d_id; uint64_t parent_d_id; pst_index_ll *desc; pst_index_ll *assoc_tree; int32_t no_child; struct pst_desc_tree *prev; struct pst_desc_tree *next; struct pst_desc_tree *parent; struct pst_desc_tree *child; struct pst_desc_tree *child_tail; } pst_desc_tree; /** The string is either utf8 encoded, or it is in the code page * specified by the containing mapi object. It can be forced into * utf8 by calling pst_convert_utf8() or pst_convert_utf8_null(). */ typedef struct pst_string { /** @li 1 true * @li 0 false */ int is_utf8; char *str; } pst_string; /** a simple wrapper for binary blobs */ typedef struct pst_binary { size_t size; char *data; } pst_binary; /** This contains the email related mapi elements */ typedef struct pst_item_email { /** mapi element 0x0e06 PR_MESSAGE_DELIVERY_TIME */ FILETIME *arrival_date; /** mapi element 0x0002 PR_ALTERNATE_RECIPIENT_ALLOWED * @li 1 true * @li 0 not set * @li -1 false */ int autoforward; /** mapi element 0x0e03 PR_DISPLAY_CC */ pst_string cc_address; /** mapi element 0x0e02 PR_DISPLAY_BCC */ pst_string bcc_address; /** mapi element 0x0071 PR_CONVERSATION_INDEX */ pst_binary conversation_index; /** mapi element 0x3a03 PR_CONVERSION_PROHIBITED * @li 1 true * @li 0 false */ int conversion_prohibited; /** mapi element 0x0e01 PR_DELETE_AFTER_SUBMIT * @li 1 true * @li 0 false */ int delete_after_submit; /** mapi element 0x0023 PR_ORIGINATOR_DELIVERY_REPORT_REQUESTED * @li 1 true * @li 0 false */ int delivery_report; /** mapi element 0x6f04 */ pst_binary encrypted_body; /** mapi element 0x6f02 */ pst_binary encrypted_htmlbody; /** mapi element 0x007d PR_TRANSPORT_MESSAGE_HEADERS */ pst_string header; /** mapi element 0x1013 */ pst_string htmlbody; /** mapi element 0x0017 PR_IMPORTANCE * @li 0 low * @li 1 normal * @li 2 high */ int32_t importance; /** mapi element 0x1042 */ pst_string in_reply_to; /** mapi element 0x0058 PR_MESSAGE_CC_ME, this user is listed explicitly in the CC address * @li 1 true * @li 0 false */ int message_cc_me; /** mapi element 0x0059 PR_MESSAGE_RECIP_ME, this user appears in TO, CC or BCC address list * @li 1 true * @li 0 false */ int message_recip_me; /** mapi element 0x0057 PR_MESSAGE_TO_ME, this user is listed explicitly in the TO address * @li 1 true * @li 0 false */ int message_to_me; /** mapi element 0x1035 */ pst_string messageid; /** mapi element 0x002e PR_ORIGINAL_SENSITIVITY * @li 0=none * @li 1=personal * @li 2=private * @li 3=company confidential */ int32_t original_sensitivity; /** mapi element 0x0072 PR_ORIGINAL_DISPLAY_BCC */ pst_string original_bcc; /** mapi element 0x0073 PR_ORIGINAL_DISPLAY_CC */ pst_string original_cc; /** mapi element 0x0074 PR_ORIGINAL_DISPLAY_TO */ pst_string original_to; /** mapi element 0x0051 PR_RECEIVED_BY_SEARCH_KEY */ pst_string outlook_recipient; /** mapi element 0x0044 PR_RCVD_REPRESENTING_NAME */ pst_string outlook_recipient_name; /** mapi element 0x0052 PR_RCVD_REPRESENTING_SEARCH_KEY */ pst_string outlook_recipient2; /** mapi element 0x003b PR_SENT_REPRESENTING_SEARCH_KEY */ pst_string outlook_sender; /** mapi element 0x0042 PR_SENT_REPRESENTING_NAME */ pst_string outlook_sender_name; /** mapi element 0x0c1d PR_SENDER_SEARCH_KEY */ pst_string outlook_sender2; /** mapi element 0x0026 PR_PRIORITY * @li 0 nonurgent * @li 1 normal * @li 2 urgent */ /** mapi element */ int32_t priority; /** mapi element 0x0070 PR_CONVERSATION_TOPIC */ pst_string processed_subject; /** mapi element 0x0029 PR_READ_RECEIPT_REQUESTED * @li 1 true * @li 0 false */ int read_receipt; /** mapi element 0x0075 PR_RECEIVED_BY_ADDRTYPE */ pst_string recip_access; /** mapi element 0x0076 PR_RECEIVED_BY_EMAIL_ADDRESS */ pst_string recip_address; /** mapi element 0x0077 PR_RCVD_REPRESENTING_ADDRTYPE */ pst_string recip2_access; /** mapi element 0x0078 PR_RCVD_REPRESENTING_EMAIL_ADDRESS */ pst_string recip2_address; /** mapi element 0x0c17 PR_REPLY_REQUESTED * @li 1 true * @li 0 false */ int reply_requested; /** mapi element 0x0050 PR_REPLY_RECIPIENT_NAMES */ pst_string reply_to; /** mapi element 0x1046, this seems to be the message-id of the rfc822 mail that is being returned */ pst_string return_path_address; /** mapi element 0x1007 PR_RTF_SYNC_BODY_COUNT, * a count of the *significant* charcters in the rtf body. Doesn't count * whitespace and other ignorable characters. */ int32_t rtf_body_char_count; /** mapi element 0x1006 PR_RTF_SYNC_BODY_CRC */ int32_t rtf_body_crc; /** mapi element 0x1008 PR_RTF_SYNC_BODY_TAG, * the first couple of lines of RTF body so that after modification, then beginning can * once again be found. */ pst_string rtf_body_tag; /** mapi element 0x1009 PR_RTF_COMPRESSED, * the compressed rtf body data. * Use pst_lzfu_decompress() to retrieve the actual rtf body data. */ pst_binary rtf_compressed; /** mapi element 0x0e1f PR_RTF_IN_SYNC, * True means that the rtf version is same as text body. * False means rtf version is more up-to-date than text body. * If this value doesn't exist, text body is more up-to-date than rtf and * cannot update to the rtf. * @li 1 true * @li 0 false */ int rtf_in_sync; /** mapi element 0x1010 PR_RTF_SYNC_PREFIX_COUNT, * a count of the ignored characters before the first significant character */ int32_t rtf_ws_prefix_count; /** mapi element 0x1011 PR_RTF_SYNC_TRAILING_COUNT, * a count of the ignored characters after the last significant character */ int32_t rtf_ws_trailing_count; /** mapi element 0x0064 PR_SENT_REPRESENTING_ADDRTYPE */ pst_string sender_access; /** mapi element 0x0065 PR_SENT_REPRESENTING_EMAIL_ADDRESS */ pst_string sender_address; /** mapi element 0x0c1e PR_SENDER_ADDRTYPE */ pst_string sender2_access; /** mapi element 0x0c1f PR_SENDER_EMAIL_ADDRESS */ pst_string sender2_address; /** mapi element 0x0036 PR_SENSITIVITY * @li 0=none * @li 1=personal * @li 2=private * @li 3=company confidential */ int32_t sensitivity; /** mapi element 0x0039 PR_CLIENT_SUBMIT_TIME */ FILETIME *sent_date; /** mapi element 0x0e0a PR_SENTMAIL_ENTRYID */ pst_entryid *sentmail_folder; /** mapi element 0x0e04 PR_DISPLAY_TO */ pst_string sentto_address; /** mapi element 0x1001 PR_REPORT_TEXT, delivery report dsn body */ pst_string report_text; /** mapi element 0x0032 PR_REPORT_TIME, delivery report time */ FILETIME *report_time; /** mapi element 0x0c04 PR_NDR_REASON_CODE */ int32_t ndr_reason_code; /** mapi element 0x0c05 PR_NDR_DIAG_CODE */ int32_t ndr_diag_code; /** mapi element 0x0c1b PR_SUPPLEMENTARY_INFO */ pst_string supplementary_info; /** mapi element 0x0c20 PR_NDR_STATUS_CODE */ int32_t ndr_status_code; // elements added for .msg processing /** mapi element 0x0040 PR_RECEIVED_BY_NAME */ pst_string outlook_received_name1; /** mapi element 0x0c1a PR_SENDER_NAME */ pst_string outlook_sender_name2; /** mapi element 0x0e1d PR_NORMALIZED_SUBJECT */ pst_string outlook_normalized_subject; /** mapi element 0x300b PR_SEARCH_KEY */ pst_string outlook_search_key; } pst_item_email; /** This contains the folder related mapi elements */ typedef struct pst_item_folder { /** mapi element 0x3602 PR_CONTENT_COUNT */ int32_t item_count; /** mapi element 0x3603 PR_CONTENT_UNREAD */ int32_t unseen_item_count; /** mapi element 0x3617 PR_ASSOC_CONTENT_COUNT Associated content are items that are attached to this folder, but are hidden from users. */ int32_t assoc_count; /** mapi element 0x360a PR_SUBFOLDERS * @li 1 true * @li 0 false */ /** mapi element */ int subfolder; } pst_item_folder; /** This contains the message store related mapi elements */ typedef struct pst_item_message_store { /** mapi element 0x35e0 */ pst_entryid *top_of_personal_folder; /** mapi element 0x35e2 */ pst_entryid *default_outbox_folder; /** mapi element 0x35e3 */ pst_entryid *deleted_items_folder; /** mapi element 0x35e4 */ pst_entryid *sent_items_folder; /** mapi element 0x35e5 */ pst_entryid *user_views_folder; /** mapi element 0x35e6 */ pst_entryid *common_view_folder; /** mapi element 0x35e7 */ pst_entryid *search_root_folder; /** mapi element 0x7c07 */ pst_entryid *top_of_folder; /** mapi element 0x35df, * bit mask of folders in this message store * @li 0x1 FOLDER_IPM_SUBTREE_VALID * @li 0x2 FOLDER_IPM_INBOX_VALID * @li 0x4 FOLDER_IPM_OUTBOX_VALID * @li 0x8 FOLDER_IPM_WASTEBOX_VALID * @li 0x10 FOLDER_IPM_SENTMAIL_VALID * @li 0x20 FOLDER_VIEWS_VALID * @li 0x40 FOLDER_COMMON_VIEWS_VALID * @li 0x80 FOLDER_FINDER_VALID */ int32_t valid_mask; /** mapi element 0x76ff */ int32_t pwd_chksum; } pst_item_message_store; /** This contains the contact related mapi elements */ typedef struct pst_item_contact { /** mapi element 0x3a00 PR_ACCOUNT */ pst_string account_name; /** mapi element 0x3003 PR_EMAIL_ADDRESS, or 0x8083 */ pst_string address1; /** mapi element 0x8085 */ pst_string address1a; /** mapi element 0x8084 */ pst_string address1_desc; /** mapi element 0x3002 PR_ADDRTYPE, or 0x8082 */ pst_string address1_transport; /** mapi element 0x8093 */ pst_string address2; /** mapi element 0x8095 */ pst_string address2a; /** mapi element 0x8094 */ pst_string address2_desc; /** mapi element 0x8092 */ pst_string address2_transport; /** mapi element 0x80a3 */ pst_string address3; /** mapi element 0x80a5 */ pst_string address3a; /** mapi element 0x80a4 */ pst_string address3_desc; /** mapi element 0x80a2 */ pst_string address3_transport; /** mapi element 0x3a30 PR_ASSISTANT */ pst_string assistant_name; /** mapi element 0x3a2e PR_ASSISTANT_TELEPHONE_NUMBER */ pst_string assistant_phone; /** mapi element 0x8535 */ pst_string billing_information; /** mapi element 0x3a42 PR_BIRTHDAY */ FILETIME *birthday; /** mapi element 0x801b */ pst_string business_address; /** mapi element 0x3a27 PR_BUSINESS_ADDRESS_CITY */ pst_string business_city; /** mapi element 0x3a26 PR_BUSINESS_ADDRESS_COUNTRY */ pst_string business_country; /** mapi element 0x3a24 PR_BUSINESS_FAX_NUMBER */ pst_string business_fax; /** mapi element 0x3a51 PR_BUSINESS_HOME_PAGE */ pst_string business_homepage; /** mapi element 0x3a08 PR_BUSINESS_TELEPHONE_NUMBER */ pst_string business_phone; /** mapi element 0x3a1b PR_BUSINESS2_TELEPHONE_NUMBER */ pst_string business_phone2; /** mapi element 0x3a2b PR_BUSINESS_PO_BOX */ pst_string business_po_box; /** mapi element 0x3a2a PR_BUSINESS_POSTAL_CODE */ pst_string business_postal_code; /** mapi element 0x3a28 PR_BUSINESS_ADDRESS_STATE_OR_PROVINCE */ pst_string business_state; /** mapi element 0x3a29 PR_BUSINESS_ADDRESS_STREET */ pst_string business_street; /** mapi element 0x3a02 PR_CALLBACK_TELEPHONE_NUMBER */ pst_string callback_phone; /** mapi element 0x3a1e PR_CAR_TELEPHONE_NUMBER */ pst_string car_phone; /** mapi element 0x3a57 PR_COMPANY_MAIN_PHONE_NUMBER */ pst_string company_main_phone; /** mapi element 0x3a16 PR_COMPANY_NAME */ pst_string company_name; /** mapi element 0x3a49 PR_COMPUTER_NETWORK_NAME */ pst_string computer_name; /** mapi element 0x3a4a PR_CUSTOMER_ID */ pst_string customer_id; /** mapi element 0x3a15 PR_POSTAL_ADDRESS */ pst_string def_postal_address; /** mapi element 0x3a18 PR_DEPARTMENT_NAME */ pst_string department; /** mapi element 0x3a45 PR_DISPLAY_NAME_PREFIX */ pst_string display_name_prefix; /** mapi element 0x3a06 PR_GIVEN_NAME */ pst_string first_name; /** mapi element 0x8530 */ pst_string followup; /** mapi element 0x80d8 */ pst_string free_busy_address; /** mapi element 0x3a4c PR_FTP_SITE */ pst_string ftp_site; /** mapi element 0x8005 */ pst_string fullname; /** mapi element 0x3a4d PR_GENDER * @li 0 unspecified * @li 1 female * @li 2 male */ int16_t gender; /** mapi element 0x3a07 PR_GOVERNMENT_ID_NUMBER */ pst_string gov_id; /** mapi element 0x3a43 PR_HOBBIES */ pst_string hobbies; /** mapi element 0x801a */ pst_string home_address; /** mapi element 0x3a59 PR_HOME_ADDRESS_CITY */ pst_string home_city; /** mapi element 0x3a5a PR_HOME_ADDRESS_COUNTRY */ pst_string home_country; /** mapi element 0x3a25 PR_HOME_FAX_NUMBER */ pst_string home_fax; /** mapi element 0x3a09 PR_HOME_TELEPHONE_NUMBER */ pst_string home_phone; /** mapi element 0x3a2f PR_HOME2_TELEPHONE_NUMBER */ pst_string home_phone2; /** mapi element 0x3a5e PR_HOME_ADDRESS_POST_OFFICE_BOX */ pst_string home_po_box; /** mapi element 0x3a5b PR_HOME_ADDRESS_POSTAL_CODE */ pst_string home_postal_code; /** mapi element 0x3a5c PR_HOME_ADDRESS_STATE_OR_PROVINCE */ pst_string home_state; /** mapi element 0x3a5d PR_HOME_ADDRESS_STREET */ pst_string home_street; /** mapi element 0x3a0a PR_INITIALS */ pst_string initials; /** mapi element 0x3a2d PR_ISDN_NUMBER */ pst_string isdn_phone; /** mapi element 0x3a17 PR_TITLE */ pst_string job_title; /** mapi element 0x3a0b PR_KEYWORD */ pst_string keyword; /** mapi element 0x3a0c PR_LANGUAGE */ pst_string language; /** mapi element 0x3a0d PR_LOCATION */ pst_string location; /** mapi element 0x3a0e PR_MAIL_PERMISSION * @li 1 true * @li 0 false */ int mail_permission; /** mapi element 0x3a4e PR_MANAGER_NAME */ pst_string manager_name; /** mapi element 0x3a44 PR_MIDDLE_NAME */ pst_string middle_name; /** mapi element 0x8534 */ pst_string mileage; /** mapi element 0x3a1c PR_MOBILE_TELEPHONE_NUMBER */ pst_string mobile_phone; /** mapi element 0x3a4f PR_NICKNAME */ pst_string nickname; /** mapi element 0x3a19 PR_OFFICE_LOCATION */ pst_string office_loc; /** mapi element 0x3a0f PR_MHS_COMMON_NAME */ pst_string common_name; /** mapi element 0x3a10 PR_ORGANIZATIONAL_ID_NUMBER */ pst_string org_id; /** mapi element 0x801c */ pst_string other_address; /** mapi element 0x3a5f PR_OTHER_ADDRESS_CITY */ pst_string other_city; /** mapi element 0x3a60 PR_OTHER_ADDRESS_COUNTRY */ pst_string other_country; /** mapi element 0x3a1f PR_OTHER_TELEPHONE_NUMBER */ pst_string other_phone; /** mapi element 0x3a64 PR_OTHER_ADDRESS_POST_OFFICE_BOX */ pst_string other_po_box; /** mapi element 0x3a61 PR_OTHER_ADDRESS_POSTAL_CODE */ pst_string other_postal_code; /** mapi element 0x3a62 PR_OTHER_ADDRESS_STATE_OR_PROVINCE */ pst_string other_state; /** mapi element 0x3a63 PR_OTHER_ADDRESS_STREET */ pst_string other_street; /** mapi element 0x3a21 PR_PAGER_TELEPHONE_NUMBER */ pst_string pager_phone; /** mapi element 0x3a50 PR_PERSONAL_HOME_PAGE */ pst_string personal_homepage; /** mapi element 0x3a47 PR_PREFERRED_BY_NAME */ pst_string pref_name; /** mapi element 0x3a23 PR_PRIMARY_FAX_NUMBER */ pst_string primary_fax; /** mapi element 0x3a1a PR_PRIMARY_TELEPHONE_NUMBER */ pst_string primary_phone; /** mapi element 0x3a46 PR_PROFESSION */ pst_string profession; /** mapi element 0x3a1d PR_RADIO_TELEPHONE_NUMBER */ pst_string radio_phone; /** mapi element 0x3a40 PR_SEND_RICH_INFO * @li 1 true * @li 0 false */ int rich_text; /** mapi element 0x3a48 PR_SPOUSE_NAME */ pst_string spouse_name; /** mapi element 0x3a05 PR_GENERATION (Jr., Sr., III, etc) */ pst_string suffix; /** mapi element 0x3a11 PR_SURNAME */ pst_string surname; /** mapi element 0x3a2c PR_TELEX_NUMBER */ pst_string telex; /** mapi element 0x3a20 PR_TRANSMITTABLE_DISPLAY_NAME */ pst_string transmittable_display_name; /** mapi element 0x3a4b PR_TTYTDD_PHONE_NUMBER */ pst_string ttytdd_phone; /** mapi element 0x3a41 PR_WEDDING_ANNIVERSARY */ FILETIME *wedding_anniversary; /** mapi element 0x8045 */ pst_string work_address_street; /** mapi element 0x8046 */ pst_string work_address_city; /** mapi element 0x8047 */ pst_string work_address_state; /** mapi element 0x8048 */ pst_string work_address_postalcode; /** mapi element 0x8049 */ pst_string work_address_country; /** mapi element 0x804a */ pst_string work_address_postofficebox; } pst_item_contact; /** This contains the attachment related mapi elements */ typedef struct pst_item_attach { /** mapi element 0x3704 PR_ATTACH_FILENAME */ pst_string filename1; /** mapi element 0x3707 PR_ATTACH_LONG_FILENAME */ pst_string filename2; /** mapi element 0x370e PR_ATTACH_MIME_TAG */ pst_string mimetype; /** mapi element 0x3701 PR_ATTACH_DATA_OBJ */ pst_binary data; /** only used if the attachment is by reference, in which case this is the id2 reference */ uint64_t id2_val; /** calculated from id2_val during creation of record */ uint64_t i_id; /** id2 tree needed to resolve attachments by reference */ pst_id2_tree *id2_head; /** mapi element 0x3705 PR_ATTACH_METHOD * @li 0 no attachment * @li 1 attach by value * @li 2 attach by reference * @li 3 attach by reference resolve * @li 4 attach by reference only * @li 5 embedded message * @li 6 OLE */ int32_t method; /** mapi element 0x370b PR_RENDERING_POSITION */ int32_t position; /** mapi element 0x3710 PR_ATTACH_MIME_SEQUENCE */ int32_t sequence; struct pst_item_attach *next; } pst_item_attach; /** linked list of extra header fields */ typedef struct pst_item_extra_field { char *field_name; char *value; struct pst_item_extra_field *next; } pst_item_extra_field; /** This contains the journal related mapi elements */ typedef struct pst_item_journal { /** mapi element 0x8706 */ FILETIME *start; /** mapi element 0x8708 */ FILETIME *end; /** mapi element 0x8700 */ pst_string type; /** mapi element 0x8712 */ pst_string description; } pst_item_journal; /** This contains the recurrence data separated into fields. http://www.geocities.com/cainrandom/dev/MAPIRecurrence.html */ typedef struct pst_recurrence { /** 0x30043004 */ uint32_t signature; /** @li 0 daily * @li 1 weekly * @li 2 monthly * @li 3 yearly */ uint32_t type; /** implies number of recurrence parameters * @li 0 has 3 parameters * @li 1 has 4 parameters * @li 2 has 4 parameters * @li 3 has 5 parameters */ uint32_t sub_type; /** must be contiguous, not an array to make python interface easier */ uint32_t parm1; uint32_t parm2; uint32_t parm3; uint32_t parm4; uint32_t parm5; /** type of termination of the recurrence @li 0 terminates on a date @li 1 terminates based on integer number of occurrences @li 2 never terminates */ uint32_t termination; /** recurrence interval in terms of the recurrence type */ uint32_t interval; /** bit mask of days of the week */ uint32_t bydaymask; /** day of month for monthly and yearly recurrences */ uint32_t dayofmonth; /** month of year for yearly recurrences */ uint32_t monthofyear; /** occurence of day for 2nd Tuesday of month, in which case position is 2 */ uint32_t position; /** number of occurrences, even if recurrence terminates based on date */ uint32_t count; // there is more data, including the termination date, // but we can get that from other mapi elements. } pst_recurrence; /** This contains the appointment related mapi elements */ typedef struct pst_item_appointment { /** mapi element 0x820d PR_OUTLOOK_EVENT_START_DATE */ FILETIME *start; /** mapi element 0x820e PR_OUTLOOK_EVENT_START_END */ FILETIME *end; /** mapi element 0x8208 PR_OUTLOOK_EVENT_LOCATION */ pst_string location; /** mapi element 0x8503 PR_OUTLOOK_COMMON_REMINDER_SET * @li 1 true * @li 0 false */ int alarm; /** mapi element 0x8560 */ FILETIME *reminder; /** mapi element 0x8501 PR_OUTLOOK_COMMON_REMINDER_MINUTES_BEFORE */ int32_t alarm_minutes; /** mapi element 0x851f */ pst_string alarm_filename; /** mapi element 0x8234 */ pst_string timezonestring; /** mapi element 0x8205 PR_OUTLOOK_EVENT_SHOW_TIME_AS * @li 0 free * @li 1 tentative * @li 2 busy * @li 3 out of office*/ int32_t showas; /** mapi element 0x8214 * @li 0 None * @li 1 Important * @li 2 Business * @li 3 Personal * @li 4 Vacation * @li 5 Must Attend * @li 6 Travel Required * @li 7 Needs Preparation * @li 8 Birthday * @li 9 Anniversary * @li 10 Phone Call */ int32_t label; /** mapi element 0x8215 PR_OUTLOOK_EVENT_ALL_DAY * @li 1 true * @li 0 false */ int all_day; /** mapi element 0x8223 PR_OUTLOOK_EVENT_IS_RECURRING * @li 1 true * @li 0 false */ int is_recurring; /** mapi element 0x8231 * @li 0 none * @li 1 daily * @li 2 weekly * @li 3 monthly * @li 4 yearly */ int32_t recurrence_type; /** mapi element 0x8232 recurrence description */ pst_string recurrence_description; /** mapi element 0x8216 recurrence data */ pst_binary recurrence_data; /** mapi element 0x8235 PR_OUTLOOK_EVENT_RECURRENCE_START */ FILETIME *recurrence_start; /** mapi element 0x8236 PR_OUTLOOK_EVENT_RECURRENCE_END */ FILETIME *recurrence_end; } pst_item_appointment; /** This contains the common mapi elements, and pointers to structures for * each major mapi item type. It represents a complete mapi object. */ typedef struct pst_item { /** email mapi elements */ pst_item_email *email; /** folder mapi elements */ pst_item_folder *folder; /** contact mapi elements */ pst_item_contact *contact; /** linked list of attachments */ pst_item_attach *attach; /** message store mapi elements */ pst_item_message_store *message_store; /** linked list of extra headers and such */ pst_item_extra_field *extra_fields; /** journal mapi elements */ pst_item_journal *journal; /** calendar mapi elements */ pst_item_appointment *appointment; /** derived from mapi elements 0x001a PR_MESSAGE_CLASS or 0x3613 PR_CONTAINER_CLASS * @li 1 PST_TYPE_NOTE * @li 2 PST_TYPE_SCHEDULE * @li 8 PST_TYPE_APPOINTMENT * @li 9 PST_TYPE_CONTACT * @li 10 PST_TYPE_JOURNAL * @li 11 PST_TYPE_STICKYNOTE * @li 12 PST_TYPE_TASK * @li 13 PST_TYPE_OTHER * @li 14 PST_TYPE_REPORT */ int type; /** mapi element 0x001a PR_MESSAGE_CLASS or 0x3613 PR_CONTAINER_CLASS */ char *ascii_type; /** mapi element 0x0e07 PR_MESSAGE_FLAGS * @li 0x01 Read * @li 0x02 Unmodified * @li 0x04 Submit * @li 0x08 Unsent * @li 0x10 Has Attachments * @li 0x20 From Me * @li 0x40 Associated * @li 0x80 Resend * @li 0x100 RN Pending * @li 0x200 NRN Pending */ int32_t flags; /** mapi element 0x3001 PR_DISPLAY_NAME */ pst_string file_as; /** mapi element 0x3004 PR_COMMENT */ pst_string comment; /** derived from extra_fields["content-type"] if it contains a charset= subfield */ pst_string body_charset; /** mapi element 0x1000 PR_BODY */ pst_string body; /** mapi element 0x0037 PR_SUBJECT */ pst_string subject; /** mapi element 0x3fde PR_INTERNET_CPID */ int32_t internet_cpid; /** mapi element 0x3ffd PR_MESSAGE_CODEPAGE */ int32_t message_codepage; /** mapi element 0x0e08 PR_MESSAGE_SIZE */ int32_t message_size; /** mapi element 0x8554 PR_OUTLOOK_VERSION */ pst_string outlook_version; /** mapi element 0x0ff9 PR_RECORD_KEY */ pst_binary record_key; /** mapi element 0x65e3 PR_PREDECESSOR_CHANGE_LIST */ pst_binary predecessor_change; /** mapi element 0x0063 PR_RESPONSE_REQUESTED * @li 1 true * @li 0 false */ int response_requested; /** mapi element 0x3007 PR_CREATION_TIME */ FILETIME *create_date; /** mapi element 0x3008 PR_LAST_MODIFICATION_TIME */ FILETIME *modify_date; /** mapi element 0x002b PR_RECIPIENT_REASSIGNMENT_PROHIBITED * @li 1 true * @li 0 false */ int private_member; } pst_item; /** Linked list of extended attributes. * This is used to convert mapi_id values in the pst file into * cannonical mapi_id values to be used in this code. This list * is kept in sorted order, where the key is the 'map' field. * Some mapi_id values are converted to cannonical mapi_id values * (PST_MAP_ATTRIB), and others are converted to a string * (PST_ATTRIB_HEADER). */ typedef struct pst_x_attrib_ll { /** @li 1 PST_MAP_ATTRIB map->int attribute @li 2 PST_MAP_HEADER map->string header */ uint32_t mytype; /** key for the mapping */ uint32_t map; /** data target of the mapping, either uint32_t or string */ void *data; /** link to next item in the list */ struct pst_x_attrib_ll *next; } pst_x_attrib_ll; /** this is only used for internal debugging */ typedef struct pst_block_recorder { struct pst_block_recorder *next; int64_t offset; size_t size; int readcount; } pst_block_recorder; typedef struct pst_file { /** file pointer to opened PST file */ FILE* fp; /** original cwd when the file was opened */ char* cwd; /** original file name when the file was opened */ char* fname; /** the head and tail of the linked list of index structures */ pst_index_ll *i_head, *i_tail; /** the head and tail of the top level of the descriptor tree */ pst_desc_tree *d_head, *d_tail; /** the head of the extended attributes linked list */ pst_x_attrib_ll *x_head; /** the head of the block recorder, a debug artifact * used to detect cases where we might read the same * block multiple times while processing a pst file. */ pst_block_recorder *block_head; /** @li 0 is 32-bit pst file, pre Outlook 2003; * @li 1 is 64-bit pst file, Outlook 2003 or later */ int do_read64; /** file offset of the first b-tree node in the index tree */ uint64_t index1; /** back pointer value in the first b-tree node in the index tree */ uint64_t index1_back; /** file offset of the first b-tree node in the descriptor tree*/ uint64_t index2; /** back pointer value in the first b-tree node in the descriptor tree */ uint64_t index2_back; /** size of the pst file */ uint64_t size; /** @li 0 PST_NO_ENCRYPT, none * @li 1 PST_COMP_ENCRYPT, simple byte substitution cipher with fixed key * @li 2 PST_ENCRYPT, german enigma 3 rotor cipher with fixed key */ unsigned char encryption; /** index type or file type * @li 0x0e 32 bit pre Outlook 2003 * @li 0x0f 32 bit pre Outlook 2003 * @li 0x15 64 bit Outlook 2003 or later * @li 0x17 64 bit Outlook 2003 or later */ unsigned char ind_type; } pst_file; /** Open a pst file. * @param pf pointer to uninitialized pst_file structure. This structure * will be filled in by this function. * @param name name of the file, suitable for fopen(). * @return 0 if ok, -1 if error */ int pst_open(pst_file *pf, const char *name); /** Reopen the pst file after a fork * @param pf pointer to the pst_file structure setup by pst_open(). * @return 0 if ok, -1 if error */ int pst_reopen(pst_file *pf); /** Load the index entries from the pst file. This loads both the * i_id linked list, and the d_id tree, and should normally be the * first call after pst_open(). * @param pf pointer to the pst_file structure setup by pst_open(). */ int pst_load_index (pst_file *pf); /** Load the extended attribute mapping table from the pst file. This * should normally be the second call after pst_open(). * @param pf pointer to the pst_file structure setup by pst_open(). */ int pst_load_extended_attributes(pst_file *pf); /** Close a pst file. * @param pf pointer to the pst_file structure setup by pst_open(). */ int pst_close(pst_file *pf); /** Get the top of folders descriptor tree. This is the main descriptor tree * that needs to be walked to look at every item in the pst file. * @param pf pointer to the pst_file structure setup by pst_open(). * @param root root item, which can be obtained by pst_parse_item(pf, pf->d_head, NULL). */ pst_desc_tree* pst_getTopOfFolders(pst_file *pf, const pst_item *root); /** Assemble the binary attachment into a single buffer. * @param pf pointer to the pst_file structure setup by pst_open(). * @param attach pointer to the attachment record * @return structure containing size of and pointer to the buffer. * the caller must free this buffer. */ pst_binary pst_attach_to_mem(pst_file *pf, pst_item_attach *attach); /** Write a binary attachment to a file. * @param pf pointer to the pst_file structure setup by pst_open(). * @param attach pointer to the attachment record * @param fp pointer to an open FILE. */ size_t pst_attach_to_file(pst_file *pf, pst_item_attach *attach, FILE* fp); /** Write a binary attachment base64 encoded to a file. * @param pf pointer to the pst_file structure setup by pst_open(). * @param attach pointer to the attachment record * @param fp pointer to an open FILE. */ size_t pst_attach_to_file_base64(pst_file *pf, pst_item_attach *attach, FILE* fp); /** Walk the descriptor tree. * @param d pointer to the current item in the descriptor tree. * @return pointer to the next item in the descriptor tree. */ pst_desc_tree* pst_getNextDptr(pst_desc_tree* d); /** Assemble a mapi object from a descriptor pointer. * @param pf pointer to the pst_file structure setup by pst_open(). * @param d_ptr pointer to an item in the descriptor tree. * @param m_head normally NULL. This is only used when processing embedded * attached rfc822 messages, in which case it is attach->id2_head. * @return pointer to the mapi object. Must be free'd by pst_freeItem(). */ pst_item* pst_parse_item (pst_file *pf, pst_desc_tree *d_ptr, pst_id2_tree *m_head); /** Free the item returned by pst_parse_item(). * @param item pointer to item returned from pst_parse_item(). */ void pst_freeItem(pst_item *item); /** Lookup the i_id in the index linked list, and return a pointer to the element. * @param pf pointer to the pst_file structure setup by pst_open(). * @param i_id key for the index linked list * @return pointer to the element, or NULL if not found. */ pst_index_ll* pst_getID(pst_file* pf, uint64_t i_id); /** Get an ID block from the file using pst_ff_getIDblock() and decrypt if necessary. * @param pf pointer to the pst_file structure setup by pst_open(). * @param i_id ID of block to retrieve * @param buf reference to pointer to buffer that will contain the data block. * If this pointer is non-NULL, it will first be free()d. * @return Size of block read into memory */ size_t pst_ff_getIDblock_dec(pst_file *pf, uint64_t i_id, char **buf); /** fwrite with checking for null pointer. * @param ptr pointer to the buffer * @param size size of each item * @param nmemb number of items * @param stream output file * @return number of bytes written, zero if ptr==NULL */ size_t pst_fwrite(const void* ptr, size_t size, size_t nmemb, FILE* stream); /** Add any necessary escape characters for rfc2426 vcard format * @param[in] str pointer to input string * @param[in,out] result pointer to a char* pointer that may be realloc'ed if needed * @param[in,out] resultlen size of the result buffer * @return pointer to output string, either the input pointer if * there are no characters that need escapes, or a pointer * to a possibly realloc'ed result buffer. */ char* pst_rfc2426_escape(char* str, char** result, size_t* resultlen); /** Convert a FILETIME into rfc2425 date/time format 1953-10-15T23:10:00Z * which is the same as one of the forms in the ISO3601 standard * @param[in] ft time to be converted * @param[in] buflen length of the output buffer * @param[out] result pointer to output buffer, must be at least 30 bytes * @return time in rfc2425 format */ char* pst_rfc2425_datetime_format(const FILETIME* ft, int buflen, char* result); /** Convert a FILETIME into rfc2445 date/time format 19531015T231000Z * @param[in] ft time to be converted * @param[in] buflen length of the output buffer * @param[out] result pointer to output buffer, must be at least 30 bytes * @return time in rfc2445 format */ char* pst_rfc2445_datetime_format(const FILETIME* ft, int buflen, char* result); /** Convert the current time rfc2445 date/time format 19531015T231000Z * @param[in] buflen length of the output buffer * @param[out] result pointer to output buffer, must be at least 30 bytes * @return time in rfc2445 format */ char* pst_rfc2445_datetime_format_now(int buflen, char* result); /** Get the default character set for this item. This is used to find * the charset for pst_string elements that are not already in utf8 encoding. * @param item pointer to the mapi item of interest * @param[in] buflen length of the output buffer * @param[out] result pointer to output buffer, must be at least 30 bytes * @return default character set as a string useable by iconv() */ const char* pst_default_charset(pst_item *item, int buflen, char* result); /** Convert str to utf8 if possible; null strings are preserved. * @param item pointer to the containing mapi item * @param str pointer to the mapi string of interest */ void pst_convert_utf8_null(pst_item *item, pst_string *str); /** Convert str to utf8 if possible; null strings are converted into empty strings. * @param item pointer to the containing mapi item * @param str pointer to the mapi string of interest */ void pst_convert_utf8(pst_item *item, pst_string *str); /** Decode raw recurrence data into a better structure. * @param appt pointer to appointment structure * @return pointer to decoded recurrence structure that must be free'd by the caller. */ pst_recurrence* pst_convert_recurrence(pst_item_appointment* appt); /** Free a recurrence structure. * @param r input pointer to be freed */ void pst_free_recurrence(pst_recurrence* r); // switch from maximal packing back to default packing // undo the packing from the beginning of this file #ifdef _MSC_VER #pragma pack(pop) #endif #if defined(__GNUC__) || defined (__SUNPRO_C) || defined(__SUNPRO_CC) #pragma pack() #endif #endif