Mercurial > libpst
comparison src/readpst.c @ 199:e3a46f66332b
more changes in recurrence decoding
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Wed, 13 May 2009 11:59:55 -0700 |
parents | 7c60d6d1c681 |
children | d360f96f71f6 |
comparison
equal
deleted
inserted
replaced
198:7c60d6d1c681 | 199:e3a46f66332b |
---|---|
55 void write_schedule_part_data(FILE* f_output, pst_item* item, const char* sender, const char* method); | 55 void write_schedule_part_data(FILE* f_output, pst_item* item, const char* sender, const char* method); |
56 void write_schedule_part(FILE* f_output, pst_item* item, const char* sender, const char* boundary); | 56 void write_schedule_part(FILE* f_output, pst_item* item, const char* sender, const char* boundary); |
57 void write_normal_email(FILE* f_output, char f_name[], pst_item* item, int mode, int mode_MH, pst_file* pst, int save_rtf, char** extra_mime_headers); | 57 void write_normal_email(FILE* f_output, char f_name[], pst_item* item, int mode, int mode_MH, pst_file* pst, int save_rtf, char** extra_mime_headers); |
58 void write_vcard(FILE* f_output, pst_item *item, pst_item_contact* contact, char comment[]); | 58 void write_vcard(FILE* f_output, pst_item *item, pst_item_contact* contact, char comment[]); |
59 void write_journal(FILE* f_output, pst_item* item); | 59 void write_journal(FILE* f_output, pst_item* item); |
60 int file_time_compare(FILETIME* left, FILETIME* right); | 60 void write_appointment(FILE* f_output, pst_item *item, int event_open); |
61 void write_appointment(FILE* f_output, pst_item *item); | |
62 void create_enter_dir(struct file_ll* f, pst_item *item); | 61 void create_enter_dir(struct file_ll* f, pst_item *item); |
63 void close_enter_dir(struct file_ll *f); | 62 void close_enter_dir(struct file_ll *f); |
64 | 63 |
65 const char* prog_name; | 64 const char* prog_name; |
66 char* output_dir = "."; | 65 char* output_dir = "."; |
218 DEBUG_MAIN(("main: I have an appointment, but the folder type %"PRIi32" isn't an appointment folder. Skipping it\n", ff.type)); | 217 DEBUG_MAIN(("main: I have an appointment, but the folder type %"PRIi32" isn't an appointment folder. Skipping it\n", ff.type)); |
219 } | 218 } |
220 else { | 219 else { |
221 ff.item_count++; | 220 ff.item_count++; |
222 if (mode == MODE_SEPARATE) mk_separate_file(&ff); | 221 if (mode == MODE_SEPARATE) mk_separate_file(&ff); |
223 write_appointment(ff.output, item); | 222 write_appointment(ff.output, item, 0); |
224 fprintf(ff.output, "\n"); | 223 fprintf(ff.output, "\n"); |
225 } | 224 } |
226 | 225 |
227 } else if (item->message_store) { | 226 } else if (item->message_store) { |
228 // there should only be one message_store, and we have already done it | 227 // there should only be one message_store, and we have already done it |
1040 | 1039 |
1041 void write_schedule_part_data(FILE* f_output, pst_item* item, const char* sender, const char* method) | 1040 void write_schedule_part_data(FILE* f_output, pst_item* item, const char* sender, const char* method) |
1042 { | 1041 { |
1043 fprintf(f_output, "BEGIN:VCALENDAR\n"); | 1042 fprintf(f_output, "BEGIN:VCALENDAR\n"); |
1044 fprintf(f_output, "VERSION:2.0\n"); | 1043 fprintf(f_output, "VERSION:2.0\n"); |
1045 fprintf(f_output, "PRODID:LibPST\n"); | 1044 fprintf(f_output, "PRODID:LibPST v%s\n", VERSION); |
1046 fprintf(f_output, "METHOD:%s\n", method); | 1045 fprintf(f_output, "METHOD:%s\n", method); |
1046 fprintf(f_output, "BEGIN:VEVENT\n"); | |
1047 fprintf(f_output, "ORGANIZER;CN=\"%s\":MAILTO:%s\n", item->email->outlook_sender_name.str, sender); | 1047 fprintf(f_output, "ORGANIZER;CN=\"%s\":MAILTO:%s\n", item->email->outlook_sender_name.str, sender); |
1048 write_appointment(f_output, item); | 1048 write_appointment(f_output, item, 1); |
1049 fprintf(f_output, "END:VCALENDAR\n"); | 1049 fprintf(f_output, "END:VCALENDAR\n"); |
1050 } | 1050 } |
1051 | 1051 |
1052 | 1052 |
1053 void write_schedule_part(FILE* f_output, pst_item* item, const char* sender, const char* boundary) | 1053 void write_schedule_part(FILE* f_output, pst_item* item, const char* sender, const char* boundary) |
1054 { | 1054 { |
1055 const char* method = "REQUEST"; | 1055 const char* method = "REQUEST"; |
1056 const char* charset = "utf-8"; | 1056 const char* charset = "utf-8"; |
1057 char fname[20]; | 1057 char fname[30]; |
1058 if (!item->appointment) return; | 1058 if (!item->appointment) return; |
1059 | 1059 |
1060 // inline appointment request | 1060 // inline appointment request |
1061 fprintf(f_output, "\n--%s\n", boundary); | 1061 fprintf(f_output, "\n--%s\n", boundary); |
1062 fprintf(f_output, "Content-Type: %s; method=\"%s\"; charset=\"%s\"\n\n", "text/calendar", method, charset); | 1062 fprintf(f_output, "Content-Type: %s; method=\"%s\"; charset=\"%s\"\n\n", "text/calendar", method, charset); |
1357 } | 1357 } |
1358 | 1358 |
1359 | 1359 |
1360 void write_vcard(FILE* f_output, pst_item *item, pst_item_contact* contact, char comment[]) | 1360 void write_vcard(FILE* f_output, pst_item *item, pst_item_contact* contact, char comment[]) |
1361 { | 1361 { |
1362 char time_buffer[30]; | |
1362 // We can only call rfc escape once per printf, since the second call | 1363 // We can only call rfc escape once per printf, since the second call |
1363 // may free the buffer returned by the first call. | 1364 // may free the buffer returned by the first call. |
1364 // I had tried to place those into a single printf - Carl. | 1365 // I had tried to place those into a single printf - Carl. |
1365 | 1366 |
1366 DEBUG_ENT("write_vcard"); | 1367 DEBUG_ENT("write_vcard"); |
1436 if (contact->address2.str) | 1437 if (contact->address2.str) |
1437 fprintf(f_output, "EMAIL:%s\n", pst_rfc2426_escape(contact->address2.str)); | 1438 fprintf(f_output, "EMAIL:%s\n", pst_rfc2426_escape(contact->address2.str)); |
1438 if (contact->address3.str) | 1439 if (contact->address3.str) |
1439 fprintf(f_output, "EMAIL:%s\n", pst_rfc2426_escape(contact->address3.str)); | 1440 fprintf(f_output, "EMAIL:%s\n", pst_rfc2426_escape(contact->address3.str)); |
1440 if (contact->birthday) | 1441 if (contact->birthday) |
1441 fprintf(f_output, "BDAY:%s\n", pst_rfc2425_datetime_format(contact->birthday)); | 1442 fprintf(f_output, "BDAY:%s\n", pst_rfc2425_datetime_format(contact->birthday, sizeof(time_buffer), time_buffer)); |
1442 | 1443 |
1443 if (contact->home_address.str) { | 1444 if (contact->home_address.str) { |
1444 //fprintf(f_output, "ADR;TYPE=home:%s;%s;%s;%s;%s;%s;%s\n", | 1445 //fprintf(f_output, "ADR;TYPE=home:%s;%s;%s;%s;%s;%s;%s\n", |
1445 fprintf(f_output, "ADR;TYPE=home:%s;", (!contact->home_po_box.str) ? "" : pst_rfc2426_escape(contact->home_po_box.str)); | 1446 fprintf(f_output, "ADR;TYPE=home:%s;", (!contact->home_po_box.str) ? "" : pst_rfc2426_escape(contact->home_po_box.str)); |
1446 fprintf(f_output, "%s;", ""); // extended Address | 1447 fprintf(f_output, "%s;", ""); // extended Address |
1507 } | 1508 } |
1508 | 1509 |
1509 | 1510 |
1510 void write_journal(FILE* f_output, pst_item* item) | 1511 void write_journal(FILE* f_output, pst_item* item) |
1511 { | 1512 { |
1513 char time_buffer[30]; | |
1512 pst_item_journal* journal = item->journal; | 1514 pst_item_journal* journal = item->journal; |
1513 | 1515 |
1514 // make everything utf8 | 1516 // make everything utf8 |
1515 pst_convert_utf8_null(item, &item->subject); | 1517 pst_convert_utf8_null(item, &item->subject); |
1516 pst_convert_utf8_null(item, &item->body); | 1518 pst_convert_utf8_null(item, &item->body); |
1517 | 1519 |
1518 fprintf(f_output, "BEGIN:VJOURNAL\n"); | 1520 fprintf(f_output, "BEGIN:VJOURNAL\n"); |
1519 fprintf(f_output, "DTSTAMP:%s\n", pst_rfc2445_datetime_format_now()); | 1521 fprintf(f_output, "DTSTAMP:%s\n", pst_rfc2445_datetime_format_now(sizeof(time_buffer), time_buffer)); |
1520 if (item->create_date) | 1522 if (item->create_date) |
1521 fprintf(f_output, "CREATED:%s\n", pst_rfc2445_datetime_format(item->create_date)); | 1523 fprintf(f_output, "CREATED:%s\n", pst_rfc2445_datetime_format(item->create_date, sizeof(time_buffer), time_buffer)); |
1522 if (item->modify_date) | 1524 if (item->modify_date) |
1523 fprintf(f_output, "LAST-MOD:%s\n", pst_rfc2445_datetime_format(item->modify_date)); | 1525 fprintf(f_output, "LAST-MOD:%s\n", pst_rfc2445_datetime_format(item->modify_date, sizeof(time_buffer), time_buffer)); |
1524 if (item->subject.str) | 1526 if (item->subject.str) |
1525 fprintf(f_output, "SUMMARY:%s\n", pst_rfc2426_escape(item->subject.str)); | 1527 fprintf(f_output, "SUMMARY:%s\n", pst_rfc2426_escape(item->subject.str)); |
1526 if (item->body.str) | 1528 if (item->body.str) |
1527 fprintf(f_output, "DESCRIPTION:%s\n", pst_rfc2426_escape(item->body.str)); | 1529 fprintf(f_output, "DESCRIPTION:%s\n", pst_rfc2426_escape(item->body.str)); |
1528 if (journal && journal->start) | 1530 if (journal && journal->start) |
1529 fprintf(f_output, "DTSTART;VALUE=DATE-TIME:%s\n", pst_rfc2445_datetime_format(journal->start)); | 1531 fprintf(f_output, "DTSTART;VALUE=DATE-TIME:%s\n", pst_rfc2445_datetime_format(journal->start, sizeof(time_buffer), time_buffer)); |
1530 fprintf(f_output, "END:VJOURNAL\n"); | 1532 fprintf(f_output, "END:VJOURNAL\n"); |
1531 } | 1533 } |
1532 | 1534 |
1533 | 1535 |
1534 /** | 1536 void write_appointment(FILE* f_output, pst_item* item, int event_open) |
1535 compare two FILETIME objects after converting to unix time_t. This | 1537 { |
1536 allows FILETIMEs that are beyond the range of time_t representaion to | 1538 char time_buffer[30]; |
1537 be converted to 0, and therefore seem to be less than the right | |
1538 side. The actual recurrence end values seen in pst files are very | |
1539 large (outside the range of 32 bit time_t), but still finite. That is | |
1540 a strange way to represent an infinite recurrence. | |
1541 */ | |
1542 int file_time_compare(FILETIME* left, FILETIME* right) | |
1543 { | |
1544 time_t delta = pst_fileTimeToUnixTime(left) - pst_fileTimeToUnixTime(right); | |
1545 if (delta < 0) return -1; | |
1546 if (delta > 0) return 1; | |
1547 return 0; | |
1548 } | |
1549 | |
1550 | |
1551 void write_appointment(FILE* f_output, pst_item* item) | |
1552 { | |
1553 pst_item_appointment* appointment = item->appointment; | 1539 pst_item_appointment* appointment = item->appointment; |
1554 | 1540 |
1555 // make everything utf8 | 1541 // make everything utf8 |
1556 pst_convert_utf8_null(item, &item->subject); | 1542 pst_convert_utf8_null(item, &item->subject); |
1557 pst_convert_utf8_null(item, &item->body); | 1543 pst_convert_utf8_null(item, &item->body); |
1558 pst_convert_utf8_null(item, &appointment->location); | 1544 pst_convert_utf8_null(item, &appointment->location); |
1559 | 1545 |
1560 fprintf(f_output, "BEGIN:VEVENT\n"); | 1546 if (!event_open) fprintf(f_output, "BEGIN:VEVENT\n"); |
1561 fprintf(f_output, "DTSTAMP:%s\n", pst_rfc2445_datetime_format_now()); | 1547 fprintf(f_output, "DTSTAMP:%s\n", pst_rfc2445_datetime_format_now(sizeof(time_buffer), time_buffer)); |
1562 if (item->create_date) | 1548 if (item->create_date) |
1563 fprintf(f_output, "CREATED:%s\n", pst_rfc2445_datetime_format(item->create_date)); | 1549 fprintf(f_output, "CREATED:%s\n", pst_rfc2445_datetime_format(item->create_date, sizeof(time_buffer), time_buffer)); |
1564 if (item->modify_date) | 1550 if (item->modify_date) |
1565 fprintf(f_output, "LAST-MOD:%s\n", pst_rfc2445_datetime_format(item->modify_date)); | 1551 fprintf(f_output, "LAST-MOD:%s\n", pst_rfc2445_datetime_format(item->modify_date, sizeof(time_buffer), time_buffer)); |
1566 if (item->subject.str) | 1552 if (item->subject.str) |
1567 fprintf(f_output, "SUMMARY:%s\n", pst_rfc2426_escape(item->subject.str)); | 1553 fprintf(f_output, "SUMMARY:%s\n", pst_rfc2426_escape(item->subject.str)); |
1568 if (item->body.str) | 1554 if (item->body.str) |
1569 fprintf(f_output, "DESCRIPTION:%s\n", pst_rfc2426_escape(item->body.str)); | 1555 fprintf(f_output, "DESCRIPTION:%s\n", pst_rfc2426_escape(item->body.str)); |
1570 if (appointment && appointment->start) | 1556 if (appointment && appointment->start) |
1571 fprintf(f_output, "DTSTART;VALUE=DATE-TIME:%s\n", pst_rfc2445_datetime_format(appointment->start)); | 1557 fprintf(f_output, "DTSTART;VALUE=DATE-TIME:%s\n", pst_rfc2445_datetime_format(appointment->start, sizeof(time_buffer), time_buffer)); |
1572 if (appointment && appointment->end) | 1558 if (appointment && appointment->end) |
1573 fprintf(f_output, "DTEND;VALUE=DATE-TIME:%s\n", pst_rfc2445_datetime_format(appointment->end)); | 1559 fprintf(f_output, "DTEND;VALUE=DATE-TIME:%s\n", pst_rfc2445_datetime_format(appointment->end, sizeof(time_buffer), time_buffer)); |
1574 if (appointment && appointment->location.str) | 1560 if (appointment && appointment->location.str) |
1575 fprintf(f_output, "LOCATION:%s\n", pst_rfc2426_escape(appointment->location.str)); | 1561 fprintf(f_output, "LOCATION:%s\n", pst_rfc2426_escape(appointment->location.str)); |
1576 if (appointment) { | 1562 if (appointment) { |
1577 switch (appointment->showas) { | 1563 switch (appointment->showas) { |
1578 case PST_FREEBUSY_TENTATIVE: | 1564 case PST_FREEBUSY_TENTATIVE: |
1586 fprintf(f_output, "STATUS:CONFIRMED\n"); | 1572 fprintf(f_output, "STATUS:CONFIRMED\n"); |
1587 break; | 1573 break; |
1588 } | 1574 } |
1589 if (appointment->is_recurring) { | 1575 if (appointment->is_recurring) { |
1590 const char* rules[] = {"DAILY", "WEEKLY", "MONTHLY", "YEARLY"}; | 1576 const char* rules[] = {"DAILY", "WEEKLY", "MONTHLY", "YEARLY"}; |
1577 const char* days[] = {"SU", "MO", "TU", "WE", "TH", "FR", "SA"}; | |
1591 pst_recurrence *rdata = pst_convert_recurrence(appointment); | 1578 pst_recurrence *rdata = pst_convert_recurrence(appointment); |
1592 fprintf(f_output, "RRULE:FREQ=%s", rules[rdata->type]); | 1579 fprintf(f_output, "RRULE:FREQ=%s", rules[rdata->type]); |
1593 if (rdata->count) fprintf(f_output, ";COUNT=%u", rdata->count); | 1580 if (rdata->count) fprintf(f_output, ";COUNT=%u", rdata->count); |
1594 if (rdata->interval) fprintf(f_output, ";INTERVAL=%u", rdata->interval); | 1581 if (rdata->interval) fprintf(f_output, ";INTERVAL=%u", rdata->interval); |
1582 if (rdata->dayofmonth) fprintf(f_output, ";BYMONTHDAY=%d", rdata->dayofmonth); | |
1583 if (rdata->monthofyear) fprintf(f_output, ";BYMONTH=%d", rdata->monthofyear); | |
1584 if (rdata->position) fprintf(f_output, ";BYSETPOS=%d", rdata->position); | |
1585 if (rdata->bydaymask) { | |
1586 char byday[40]; | |
1587 int empty = 1; | |
1588 int i=0; | |
1589 memset(byday, 0, sizeof(byday)); | |
1590 for (i=0; i<6; i++) { | |
1591 int bit = 1 << i; | |
1592 if (bit & rdata->bydaymask) { | |
1593 char temp[40]; | |
1594 snprintf(temp, sizeof(temp), "%s%s%s", byday, (empty) ? "BYDAY=" : ";", days[i]); | |
1595 strcpy(byday, temp); | |
1596 empty = 0; | |
1597 } | |
1598 } | |
1599 } | |
1595 fprintf(f_output, "\n"); | 1600 fprintf(f_output, "\n"); |
1596 pst_free_recurrence(rdata); | 1601 pst_free_recurrence(rdata); |
1597 } | 1602 } |
1598 switch (appointment->label) { | 1603 switch (appointment->label) { |
1599 case PST_APP_LABEL_NONE: | 1604 case PST_APP_LABEL_NONE: |