Mercurial > libpst
comparison src/libpst.c @ 198:7c60d6d1c681
decode more recurrence mapi elements
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Tue, 12 May 2009 19:34:49 -0700 |
parents | 320cfcba8058 |
children | e3a46f66332b |
comparison
equal
deleted
inserted
replaced
197:07ceebd115ce | 198:7c60d6d1c681 |
---|---|
516 DEBUG_RET(); | 516 DEBUG_RET(); |
517 return topnode; | 517 return topnode; |
518 } | 518 } |
519 | 519 |
520 | 520 |
521 size_t pst_attach_to_mem(pst_file *pf, pst_item_attach *attach, char **b) { | 521 pst_binary pst_attach_to_mem(pst_file *pf, pst_item_attach *attach) { |
522 pst_index_ll *ptr; | 522 pst_index_ll *ptr; |
523 pst_holder h = {b, NULL, 0}; | 523 pst_binary rc; |
524 size_t size = 0; | 524 pst_holder h = {&rc.data, NULL, 0}; |
525 *b = NULL; | 525 rc.size = 0; |
526 rc.data = NULL; | |
526 DEBUG_ENT("pst_attach_to_mem"); | 527 DEBUG_ENT("pst_attach_to_mem"); |
527 if ((!attach->data.data) && (attach->i_id != (uint64_t)-1)) { | 528 if ((!attach->data.data) && (attach->i_id != (uint64_t)-1)) { |
528 ptr = pst_getID(pf, attach->i_id); | 529 ptr = pst_getID(pf, attach->i_id); |
529 if (ptr) { | 530 if (ptr) { |
530 size = pst_ff_getID2data(pf, ptr, &h); | 531 rc.size = pst_ff_getID2data(pf, ptr, &h); |
531 } else { | 532 } else { |
532 DEBUG_WARN(("Couldn't find ID pointer. Cannot handle attachment\n")); | 533 DEBUG_WARN(("Couldn't find ID pointer. Cannot handle attachment\n")); |
533 *b = NULL; | |
534 } | 534 } |
535 } else { | 535 } else { |
536 size = attach->data.size; | 536 rc = attach->data; |
537 *b = attach->data.data; | |
538 attach->data.data = NULL; // prevent pst_free_item() from trying to free this | 537 attach->data.data = NULL; // prevent pst_free_item() from trying to free this |
539 attach->data.size = 0; // since we have given that buffer to the caller | 538 attach->data.size = 0; // since we have given that buffer to the caller |
540 } | 539 } |
541 DEBUG_RET(); | 540 DEBUG_RET(); |
542 return size; | 541 return rc; |
543 } | 542 } |
544 | 543 |
545 | 544 |
546 size_t pst_attach_to_file(pst_file *pf, pst_item_attach *attach, FILE* fp) { | 545 size_t pst_attach_to_file(pst_file *pf, pst_item_attach *attach, FILE* fp) { |
547 pst_index_ll *ptr; | 546 pst_index_ll *ptr; |
2061 #define LIST_COPY_EMAIL_BIN(label, targ) { \ | 2060 #define LIST_COPY_EMAIL_BIN(label, targ) { \ |
2062 MALLOC_EMAIL(item); \ | 2061 MALLOC_EMAIL(item); \ |
2063 LIST_COPY_BIN(targ); \ | 2062 LIST_COPY_BIN(targ); \ |
2064 DEBUG_EMAIL((label"\n")); \ | 2063 DEBUG_EMAIL((label"\n")); \ |
2065 } | 2064 } |
2065 #define LIST_COPY_APPT_BIN(label, targ) { \ | |
2066 MALLOC_APPOINTMENT(item); \ | |
2067 LIST_COPY_BIN(targ); \ | |
2068 DEBUG_EMAIL((label"\n")); \ | |
2069 DEBUG_EMAIL_HEXPRINT(targ.data, targ.size); \ | |
2070 } | |
2066 | 2071 |
2067 #define NULL_CHECK(x) { if (!x) { DEBUG_WARN(("NULL_CHECK: Null Found\n")); break;} } | 2072 #define NULL_CHECK(x) { if (!x) { DEBUG_WARN(("NULL_CHECK: Null Found\n")); break;} } |
2068 | 2073 |
2069 | 2074 |
2070 /** | 2075 /** |
2161 item->type = PST_TYPE_REPORT; | 2166 item->type = PST_TYPE_REPORT; |
2162 else if (pst_strincmp("IPM.Activity", item->ascii_type, 12) == 0) | 2167 else if (pst_strincmp("IPM.Activity", item->ascii_type, 12) == 0) |
2163 item->type = PST_TYPE_JOURNAL; | 2168 item->type = PST_TYPE_JOURNAL; |
2164 else if (pst_strincmp("IPM.Appointment", item->ascii_type, 15) == 0) | 2169 else if (pst_strincmp("IPM.Appointment", item->ascii_type, 15) == 0) |
2165 item->type = PST_TYPE_APPOINTMENT; | 2170 item->type = PST_TYPE_APPOINTMENT; |
2166 //else if (pst_strincmp("IPM.Schedule.Meeting", item->ascii_type, 20) == 0) | 2171 else if (pst_strincmp("IPM.Schedule.Meeting", item->ascii_type, 20) == 0) |
2167 // item->type = PST_TYPE_APPOINTMENT; | 2172 item->type = PST_TYPE_SCHEDULE; // meeting requests and responses transported over email |
2168 // these seem to be appointments, but they are inside the email folder, | |
2169 // and unless we are in separate mode, we would dump an appointment | |
2170 // into the middle of a mailbox file. | |
2171 else if (pst_strincmp("IPM.StickyNote", item->ascii_type, 14) == 0) | 2173 else if (pst_strincmp("IPM.StickyNote", item->ascii_type, 14) == 0) |
2172 item->type = PST_TYPE_STICKYNOTE; | 2174 item->type = PST_TYPE_STICKYNOTE; |
2173 else if (pst_strincmp("IPM.Task", item->ascii_type, 8) == 0) | 2175 else if (pst_strincmp("IPM.Task", item->ascii_type, 8) == 0) |
2174 item->type = PST_TYPE_TASK; | 2176 item->type = PST_TYPE_TASK; |
2175 else | 2177 else |
2924 "Phone Call"); | 2926 "Phone Call"); |
2925 break; | 2927 break; |
2926 case 0x8215: // PR_OUTLOOK_EVENT_ALL_DAY | 2928 case 0x8215: // PR_OUTLOOK_EVENT_ALL_DAY |
2927 LIST_COPY_APPT_BOOL("All day flag", item->appointment->all_day); | 2929 LIST_COPY_APPT_BOOL("All day flag", item->appointment->all_day); |
2928 break; | 2930 break; |
2931 case 0x8216: // PR_OUTLOOK_EVENT_RECURRENCE_DATA | |
2932 LIST_COPY_APPT_BIN("Appointment recurrence data", item->appointment->recurrence_data); | |
2933 break; | |
2934 case 0x8223: // PR_OUTLOOK_EVENT_IS_RECURRING | |
2935 LIST_COPY_APPT_BOOL("Is recurring", item->appointment->is_recurring); | |
2936 break; | |
2929 case 0x8231: // Recurrence type | 2937 case 0x8231: // Recurrence type |
2930 LIST_COPY_APPT_ENUM("Appointment reccurence", item->appointment->recurrence_type, 0, 5, | 2938 LIST_COPY_APPT_ENUM("Appointment recurrence type ", item->appointment->recurrence_type, 0, 5, |
2931 "None", | 2939 "None", |
2932 "Daily", | 2940 "Daily", |
2933 "Weekly", | 2941 "Weekly", |
2934 "Monthly", | 2942 "Monthly", |
2935 "Yearly"); | 2943 "Yearly"); |
2936 break; | 2944 break; |
2937 case 0x8232: // Recurrence description | 2945 case 0x8232: // Recurrence description |
2938 LIST_COPY_APPT_STR("Appointment recurrence description", item->appointment->recurrence); | 2946 LIST_COPY_APPT_STR("Appointment recurrence description", item->appointment->recurrence_description); |
2939 break; | 2947 break; |
2940 case 0x8234: // TimeZone as String | 2948 case 0x8234: // TimeZone as String |
2941 LIST_COPY_APPT_STR("TimeZone of times", item->appointment->timezonestring); | 2949 LIST_COPY_APPT_STR("TimeZone of times", item->appointment->timezonestring); |
2942 break; | 2950 break; |
2943 case 0x8235: // PR_OUTLOOK_EVENT_RECURRENCE_START | 2951 case 0x8235: // PR_OUTLOOK_EVENT_RECURRENCE_START |
3331 SAFE_FREE(item->message_store->search_root_folder); | 3339 SAFE_FREE(item->message_store->search_root_folder); |
3332 SAFE_FREE(item->message_store->top_of_folder); | 3340 SAFE_FREE(item->message_store->top_of_folder); |
3333 free(item->message_store); | 3341 free(item->message_store); |
3334 } | 3342 } |
3335 if (item->contact) { | 3343 if (item->contact) { |
3336 SAFE_FREE_STR(item->contact->access_method); | |
3337 SAFE_FREE_STR(item->contact->account_name); | 3344 SAFE_FREE_STR(item->contact->account_name); |
3338 SAFE_FREE_STR(item->contact->address1); | 3345 SAFE_FREE_STR(item->contact->address1); |
3339 SAFE_FREE_STR(item->contact->address1a); | 3346 SAFE_FREE_STR(item->contact->address1a); |
3340 SAFE_FREE_STR(item->contact->address1_desc); | 3347 SAFE_FREE_STR(item->contact->address1_desc); |
3341 SAFE_FREE_STR(item->contact->address1_transport); | 3348 SAFE_FREE_STR(item->contact->address1_transport); |
3441 et = item->extra_fields->next; | 3448 et = item->extra_fields->next; |
3442 free(item->extra_fields); | 3449 free(item->extra_fields); |
3443 item->extra_fields = et; | 3450 item->extra_fields = et; |
3444 } | 3451 } |
3445 if (item->journal) { | 3452 if (item->journal) { |
3453 SAFE_FREE(item->journal->start); | |
3446 SAFE_FREE(item->journal->end); | 3454 SAFE_FREE(item->journal->end); |
3447 SAFE_FREE(item->journal->start); | |
3448 SAFE_FREE_STR(item->journal->type); | 3455 SAFE_FREE_STR(item->journal->type); |
3449 free(item->journal); | 3456 free(item->journal); |
3450 } | 3457 } |
3451 if (item->appointment) { | 3458 if (item->appointment) { |
3459 SAFE_FREE(item->appointment->start); | |
3460 SAFE_FREE(item->appointment->end); | |
3452 SAFE_FREE_STR(item->appointment->location); | 3461 SAFE_FREE_STR(item->appointment->location); |
3453 SAFE_FREE(item->appointment->reminder); | 3462 SAFE_FREE(item->appointment->reminder); |
3454 SAFE_FREE_STR(item->appointment->alarm_filename); | 3463 SAFE_FREE_STR(item->appointment->alarm_filename); |
3455 SAFE_FREE(item->appointment->start); | |
3456 SAFE_FREE(item->appointment->end); | |
3457 SAFE_FREE_STR(item->appointment->timezonestring); | 3464 SAFE_FREE_STR(item->appointment->timezonestring); |
3458 SAFE_FREE_STR(item->appointment->recurrence); | 3465 SAFE_FREE_STR(item->appointment->recurrence_description); |
3466 SAFE_FREE_BIN(item->appointment->recurrence_data); | |
3459 SAFE_FREE(item->appointment->recurrence_start); | 3467 SAFE_FREE(item->appointment->recurrence_start); |
3460 SAFE_FREE(item->appointment->recurrence_end); | 3468 SAFE_FREE(item->appointment->recurrence_end); |
3461 free(item->appointment); | 3469 free(item->appointment); |
3462 } | 3470 } |
3463 SAFE_FREE(item->ascii_type); | 3471 SAFE_FREE(item->ascii_type); |
4163 } | 4171 } |
4164 | 4172 |
4165 | 4173 |
4166 char *pst_rfc2425_datetime_format(const FILETIME *ft) { | 4174 char *pst_rfc2425_datetime_format(const FILETIME *ft) { |
4167 static char buffer[30]; | 4175 static char buffer[30]; |
4168 struct tm *stm = NULL; | 4176 struct tm* stm = NULL; |
4169 DEBUG_ENT("rfc2425_datetime_format"); | 4177 DEBUG_ENT("rfc2425_datetime_format"); |
4170 stm = pst_fileTimeToStructTM(ft); | 4178 stm = pst_fileTimeToStructTM(ft); |
4171 if (strftime(buffer, sizeof(buffer), "%Y-%m-%dT%H:%M:%SZ", stm)==0) { | 4179 if (strftime(buffer, sizeof(buffer), "%Y-%m-%dT%H:%M:%SZ", stm)==0) { |
4172 DEBUG_INFO(("Problem occured formatting date\n")); | 4180 DEBUG_INFO(("Problem occured formatting date\n")); |
4173 } | 4181 } |
4176 } | 4184 } |
4177 | 4185 |
4178 | 4186 |
4179 char *pst_rfc2445_datetime_format(const FILETIME *ft) { | 4187 char *pst_rfc2445_datetime_format(const FILETIME *ft) { |
4180 static char buffer[30]; | 4188 static char buffer[30]; |
4181 struct tm *stm = NULL; | 4189 struct tm* stm = NULL; |
4182 DEBUG_ENT("rfc2445_datetime_format"); | 4190 DEBUG_ENT("rfc2445_datetime_format"); |
4183 stm = pst_fileTimeToStructTM(ft); | 4191 stm = pst_fileTimeToStructTM(ft); |
4184 if (strftime(buffer, sizeof(buffer), "%Y%m%dT%H%M%SZ", stm)==0) { | 4192 if (strftime(buffer, sizeof(buffer), "%Y%m%dT%H%M%SZ", stm)==0) { |
4193 DEBUG_INFO(("Problem occured formatting date\n")); | |
4194 } | |
4195 DEBUG_RET(); | |
4196 return buffer; | |
4197 } | |
4198 | |
4199 | |
4200 char *pst_rfc2445_datetime_format_now() { | |
4201 static char buffer[30]; | |
4202 struct tm stm; | |
4203 time_t t = time(NULL); | |
4204 DEBUG_ENT("rfc2445_datetime_format_now"); | |
4205 gmtime_r(&t, &stm); | |
4206 if (strftime(buffer, sizeof(buffer), "%Y%m%dT%H%M%SZ", &stm)==0) { | |
4185 DEBUG_INFO(("Problem occured formatting date\n")); | 4207 DEBUG_INFO(("Problem occured formatting date\n")); |
4186 } | 4208 } |
4187 DEBUG_RET(); | 4209 DEBUG_RET(); |
4188 return buffer; | 4210 return buffer; |
4189 } | 4211 } |
4285 str->is_utf8 = 1; | 4307 str->is_utf8 = 1; |
4286 } | 4308 } |
4287 free(newer); | 4309 free(newer); |
4288 DEBUG_RET(); | 4310 DEBUG_RET(); |
4289 } | 4311 } |
4312 | |
4313 | |
4314 /** Decode raw recurrence data into a better structure. | |
4315 * @param appt pointer to appointment structure | |
4316 * @return pointer to decoded recurrence structure that must be free'd by the caller. | |
4317 */ | |
4318 pst_recurrence* pst_convert_recurrence(pst_item_appointment* appt) | |
4319 { | |
4320 int m[4] = {3,4,4,5}; | |
4321 pst_recurrence *r = pst_malloc(sizeof(pst_recurrence)); | |
4322 memset(r, 0, sizeof(pst_recurrence)); | |
4323 size_t s = appt->recurrence_data.size; | |
4324 size_t i = 0; | |
4325 char* p = appt->recurrence_data.data; | |
4326 if (p) { | |
4327 if (i+4 <= s) { r->signature = PST_LE_GET_UINT32(p+i); i += 4; } | |
4328 if (i <= s) { r->type = PST_LE_GET_UINT8(p+i) - 0x0a; i += 2; } | |
4329 if (i+4 <= s) { r->sub_type = PST_LE_GET_UINT32(p+i); i += 4; } | |
4330 if (r->sub_type <= 3) { | |
4331 int n = m[r->sub_type]; | |
4332 int j = 0; | |
4333 for (j=0; j<n; j++) { | |
4334 if (i+4 <= s) { *(&r->parm1 + j) = PST_LE_GET_UINT32(p+i); i += 4; } | |
4335 } | |
4336 } | |
4337 if (i <= s) { r->termination = PST_LE_GET_UINT8(p+i) - 0x21; i += 4; } | |
4338 if (i+4 <= s) { r->count = PST_LE_GET_UINT32(p+i); i += 4; } | |
4339 switch (r->type) { | |
4340 case 0: // daily | |
4341 r->interval = r->parm2 / (24 * 60); // was minutes between recurrences | |
4342 if (r->sub_type) r->interval = 0; // !! don't handle sub-type 1 yet | |
4343 break; | |
4344 case 1: // weekly | |
4345 r->interval = r->parm2; | |
4346 break; | |
4347 case 2: // monthly | |
4348 r->interval = r->parm2; | |
4349 // two flavors, every month on the Dth day, and every month on the Nth Tuesday | |
4350 // those are not handled here. | |
4351 break; | |
4352 case 3: // yearly | |
4353 r->interval = 0; | |
4354 // two flavors, every year on the Dth day of the Mth month, and every year on the Nth Tuesday of the Mth month | |
4355 // those are not handled here. | |
4356 break; | |
4357 default: | |
4358 break; | |
4359 } | |
4360 } | |
4361 return r; | |
4362 } | |
4363 | |
4364 | |
4365 /** Free a recurrence structure. | |
4366 * @param r input pointer to be freed | |
4367 */ | |
4368 void pst_free_recurrence(pst_recurrence* r) | |
4369 { | |
4370 if (r) free(r); | |
4371 } |