changeset 154:581fab9f1dc7

avoid emitting bogus empty email messages into contacts and calendar files
author Carl Byington <carl@five-ten-sg.com>
date Sat, 14 Mar 2009 15:13:27 -0700
parents 0b1766da9be8
children 84e0f6222adf
files ChangeLog regression/regression-tests.bash src/libpst.c src/libpst.h src/lspst.c src/pst2dii.cpp.in src/readpst.c
diffstat 7 files changed, 177 insertions(+), 110 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Thu Mar 12 15:17:32 2009 -0700
+++ b/ChangeLog	Sat Mar 14 15:13:27 2009 -0700
@@ -1,4 +1,4 @@
-LibPST 0.6.30 (2009-xx-xx)
+LibPST 0.6.30 (2009-03-14)
 ===============================
 
     * improve documentation of .pst format.
@@ -12,6 +12,9 @@
     * more code cleanup.
     * use AM_ICONV for better portability of the library location.
     * structure renaming to be more specific.
+    * improve internal doxygen documentation.
+    * avoid emitting bogus empty email messages into contacts and
+      calendar files.
 
 LibPST 0.6.29 (2009-02-24)
 ===============================
--- a/regression/regression-tests.bash	Thu Mar 12 15:17:32 2009 -0700
+++ b/regression/regression-tests.bash	Sat Mar 14 15:13:27 2009 -0700
@@ -38,7 +38,7 @@
     mkdir output$n
     #    ../src/readpst -cv -o output$n $fn >$ba.err 2>&1
     #           readpst -cv -o output$n -d dumper $fn >$ba.err 2>&1
-    $val ../src/readpst -cv -o output$n -d dumper $fn >$ba.err 2>&1
+    $val ../src/readpst -r -cv -o output$n -d dumper $fn >$ba.err 2>&1
          ../src/readpstlog -f I dumper >$ba.log
 
     #../src/getidblock -d -p $fn 0 >$ba.fulldump
@@ -50,7 +50,7 @@
 
 
 val="valgrind --leak-check=full"
-#val=''
+val=''
 
 pushd ..
 make || exit
@@ -83,6 +83,7 @@
     #doldif  19 harris.pst
 else
     dopst   1 ams.pst
+    exit
     dopst   2 sample_64.pst
     dopst   3 test.pst
     dopst   4 big_mail.pst
--- a/src/libpst.c	Thu Mar 12 15:17:32 2009 -0700
+++ b/src/libpst.c	Sat Mar 14 15:13:27 2009 -0700
@@ -275,7 +275,7 @@
 {
     DEBUG_ENT("add_descriptor_to_list");
     //DEBUG_INDEX(("Added node %#"PRIx64" parent %#"PRIx64" real parent %#"PRIx64" prev %#"PRIx64" next %#"PRIx64"\n",
-    //             node->id, node->parent_id,
+    //             node->id, node->parent_d_id,
     //             (node->parent ? node->parent->id : (uint64_t)0),
     //             (node->prev   ? node->prev->id   : (uint64_t)0),
     //             (node->next   ? node->next->id   : (uint64_t)0)));
@@ -335,10 +335,10 @@
         DEBUG_INDEX(("%#"PRIx64" is its own parent. What is this world coming to?\n"));
         add_descriptor_to_list(node, &pf->d_head, &pf->d_tail);
     } else {
-        //DEBUG_INDEX(("Searching for parent %#"PRIx64" of %#"PRIx64"\n", node->parent_id, node->id));
+        //DEBUG_INDEX(("Searching for parent %#"PRIx64" of %#"PRIx64"\n", node->parent_d_id, node->d_id));
         pst_desc_ll *parent = pst_getDptr(pf, node->parent_d_id);
         if (parent) {
-            //DEBUG_INDEX(("Found parent %#"PRIx64"\n", node->parent_id));
+            //DEBUG_INDEX(("Found parent %#"PRIx64"\n", node->parent_d_id));
             parent->no_child++;
             node->parent = parent;
             add_descriptor_to_list(node, &parent->child, &parent->child_tail);
@@ -687,8 +687,8 @@
         memcpy(desc, buf, sizeof(pst_descn));
         LE64_CPU(desc->d_id);
         LE64_CPU(desc->desc_id);
-        LE64_CPU(desc->list_id);
-        LE32_CPU(desc->parent_id);
+        LE64_CPU(desc->tree_id);
+        LE32_CPU(desc->parent_d_id);
         LE32_CPU(desc->u1);
         r = sizeof(pst_descn);
     }
@@ -1999,20 +1999,15 @@
                 case 0x0017: // PR_IMPORTANCE - How important the sender deems it to be
                     LIST_COPY_EMAIL_ENUM("Importance Level", item->email->importance, 0, 3, "Low", "Normal", "High");
                     break;
-                case 0x001A: // PR_MESSAGE_CLASS Ascii type of messages - NOT FOLDERS
-                    // must be case insensitive
+                case 0x001A: // PR_MESSAGE_CLASS IPM.x
                     LIST_COPY(item->ascii_type, (char*));
                     if (pst_strincmp("IPM.Note", item->ascii_type, 8) == 0)
-                        // the string begins with IPM.Note...
                         item->type = PST_TYPE_NOTE;
                     else if (pst_stricmp("IPM", item->ascii_type) == 0)
-                        // the whole string is just IPM
                         item->type = PST_TYPE_NOTE;
                     else if (pst_strincmp("IPM.Contact", item->ascii_type, 11) == 0)
-                        // the string begins with IPM.Contact...
                         item->type = PST_TYPE_CONTACT;
                     else if (pst_strincmp("REPORT.IPM.Note", item->ascii_type, 15) == 0)
-                        // the string begins with the above
                         item->type = PST_TYPE_REPORT;
                     else if (pst_strincmp("IPM.Activity", item->ascii_type, 12) == 0)
                         item->type = PST_TYPE_JOURNAL;
@@ -2022,18 +2017,13 @@
                         item->type = PST_TYPE_TASK;
                     else
                         item->type = PST_TYPE_OTHER;
-
-                    DEBUG_EMAIL(("IPM.x - %s\n", item->ascii_type));
+                    DEBUG_EMAIL(("Message class %s [%"PRIi32"] \n", item->ascii_type, item->type));
                     break;
                 case 0x0023: // PR_ORIGINATOR_DELIVERY_REPORT_REQUESTED
                     // set if the sender wants a delivery report from all recipients
                     LIST_COPY_EMAIL_BOOL("Global Delivery Report", item->email->delivery_report);
                     break;
                 case 0x0026: // PR_PRIORITY
-                    // Priority of a message
-                    // -1 NonUrgent
-                    //  0 Normal
-                    //  1 Urgent
                     LIST_COPY_EMAIL_ENUM("Priority", item->email->priority, 1, 3, "NonUrgent", "Normal", "Urgent");
                     break;
                 case 0x0029: // PR_READ_RECEIPT_REQUESTED
@@ -2043,13 +2033,15 @@
                     LIST_COPY_BOOL("Reassignment Prohibited (Private)", item->private_member);
                     break;
                 case 0x002E: // PR_ORIGINAL_SENSITIVITY - the sensitivity of the message before being replied to or forwarded
-                    LIST_COPY_EMAIL_ENUM("Original Sensitivity", item->email->orig_sensitivity, 0, 4, "None", "Personal", "Private", "Company Confidential");
+                    LIST_COPY_EMAIL_ENUM("Original Sensitivity", item->email->original_sensitivity, 0, 4,
+                        "None", "Personal", "Private", "Company Confidential");
                     break;
                 case 0x0032: // PR_REPORT_TIME
                     LIST_COPY_EMAIL_TIME("Report time", item->email->report_time);
                     break;
                 case 0x0036: // PR_SENSITIVITY - sender's opinion of the sensitivity of an email
-                    LIST_COPY_EMAIL_ENUM("Sensitivity", item->email->sensitivity, 0, 4, "None", "Personal", "Private", "Company Confidential");
+                    LIST_COPY_EMAIL_ENUM("Sensitivity", item->email->sensitivity, 0, 4,
+                        "None", "Personal", "Private", "Company Confidential");
                     break;
                 case 0x0037: // PR_SUBJECT raw subject
                     {
@@ -2200,17 +2192,7 @@
                     LIST_COPY_EMAIL_TIME("Date 3 (Delivery Time)", item->email->arrival_date);
                     break;
                 case 0x0E07: // PR_MESSAGE_FLAGS Email Flag
-                    // 0x01 - Read
-                    // 0x02 - Unmodified
-                    // 0x04 - Submit
-                    // 0x08 - Unsent
-                    // 0x10 - Has Attachments
-                    // 0x20 - From Me
-                    // 0x40 - Associated
-                    // 0x80 - Resend
-                    // 0x100 - RN Pending
-                    // 0x200 - NRN Pending
-                    LIST_COPY_EMAIL_INT32("Message Flags", item->email->flag);
+                    LIST_COPY_EMAIL_INT32("Message Flags", item->flags);
                     break;
                 case 0x0E08: // PR_MESSAGE_SIZE Total size of a message object
                     LIST_COPY_INT32("Message Size", item->message_size);
@@ -2303,15 +2285,6 @@
                     DEBUG_EMAIL(("Record Search 2 -- NOT HANDLED\n"));
                     break;
                 case 0x35DF: // PR_VALID_FOLDER_MASK
-                    // States which folders are valid for this message store
-                    // FOLDER_IPM_SUBTREE_VALID  0x1
-                    // FOLDER_IPM_INBOX_VALID    0x2
-                    // FOLDER_IPM_OUTBOX_VALID   0x4
-                    // FOLDER_IPM_WASTEBOX_VALID 0x8
-                    // FOLDER_IPM_SENTMAIL_VALID 0x10
-                    // FOLDER_VIEWS_VALID        0x20
-                    // FOLDER_COMMON_VIEWS_VALID 0x40
-                    // FOLDER_FINDER_VALID       0x80
                     LIST_COPY_STORE_INT32("Valid Folder Mask", item->message_store->valid_mask);
                     break;
                 case 0x35E0: // PR_IPM_SUBTREE_ENTRYID Top of Personal Folder Record
@@ -2346,29 +2319,30 @@
                     LIST_COPY_BOOL("Has Subfolders", item->folder->subfolder);
                     break;
                 case 0x3613: // PR_CONTAINER_CLASS IPF.x
-                    DEBUG_EMAIL(("IPF.x - "));
                     LIST_COPY(item->ascii_type, (char*));
-                    if (strncmp("IPF.Note", item->ascii_type, 8) == 0)
+                    if (pst_strincmp("IPF.Note", item->ascii_type, 8) == 0)
                         item->type = PST_TYPE_NOTE;
-                    else if (strncmp("IPF.Contact", item->ascii_type, 11) == 0)
+                    else if (pst_stricmp("IPF", item->ascii_type) == 0)
+                        item->type = PST_TYPE_NOTE;
+                    else if (pst_strincmp("IPF.Contact", item->ascii_type, 11) == 0)
                         item->type = PST_TYPE_CONTACT;
-                    else if (strncmp("IPF.Journal", item->ascii_type, 11) == 0)
+                    else if (pst_strincmp("IPF.Journal", item->ascii_type, 11) == 0)
                         item->type = PST_TYPE_JOURNAL;
-                    else if (strncmp("IPF.Appointment", item->ascii_type, 15) == 0)
+                    else if (pst_strincmp("IPF.Appointment", item->ascii_type, 15) == 0)
                         item->type = PST_TYPE_APPOINTMENT;
-                    else if (strncmp("IPF.StickyNote", item->ascii_type, 14) == 0)
+                    else if (pst_strincmp("IPF.StickyNote", item->ascii_type, 14) == 0)
                         item->type = PST_TYPE_STICKYNOTE;
-                    else if (strncmp("IPF.Task", item->ascii_type, 8) == 0)
+                    else if (pst_strincmp("IPF.Task", item->ascii_type, 8) == 0)
                         item->type = PST_TYPE_TASK;
                     else
                         item->type = PST_TYPE_OTHER;
 
-                    DEBUG_EMAIL(("%s [%i]\n", item->ascii_type, item->type));
+                    DEBUG_EMAIL(("Container class %s [%"PRIi32"]\n", item->ascii_type, item->type));
                     break;
                 case 0x3617: // PR_ASSOC_CONTENT_COUNT
                     // associated content are items that are attached to this folder
                     // but are hidden from users
-                    LIST_COPY_FOLDER_INT32("Associate Content count", item->folder->assoc_count);
+                    LIST_COPY_FOLDER_INT32("Associated Content count", item->folder->assoc_count);
                     break;
                 case 0x3701: // PR_ATTACH_DATA_OBJ binary data of attachment
                     DEBUG_EMAIL(("Binary Data [Size %i] - ", list->elements[x]->size));
@@ -2764,7 +2738,8 @@
                     LIST_COPY_CONTACT_STR("Internet Free/Busy", item->contact->free_busy_address);
                     break;
                 case 0x8205: // Show on Free/Busy as
-                    LIST_COPY_APPT_ENUM("Appointment shows as", item->appointment->showas, 0, 4, "Free", "Tentative", "Busy", "Out Of Office");
+                    LIST_COPY_APPT_ENUM("Appointment shows as", item->appointment->showas, 0, 4,
+                        "Free", "Tentative", "Busy", "Out Of Office");
                     break;
                 case 0x8208: // Location of an appointment
                     LIST_COPY_APPT_STR("Appointment Location", item->appointment->location);
@@ -2793,7 +2768,7 @@
                     LIST_COPY_APPT_BOOL("All day flag", item->appointment->all_day);
                     break;
                 case 0x8231: // Recurrence type
-                    LIST_COPY_APPT_ENUM("Appointment reccurs", item->appointment->recurrence_type, 0, 5,
+                    LIST_COPY_APPT_ENUM("Appointment reccurence", item->appointment->recurrence_type, 0, 5,
                         "None",
                         "Daily",
                         "Weekly",
--- a/src/libpst.h	Thu Mar 12 15:17:32 2009 -0700
+++ b/src/libpst.h	Sat Mar 14 15:13:27 2009 -0700
@@ -49,9 +49,9 @@
 #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_FREE          0
+#define PST_FREEBUSY_TENTATIVE     1
+#define PST_FREEBUSY_BUSY          2
 #define PST_FREEBUSY_OUT_OF_OFFICE 3
 
 // defines labels for appointment->label
@@ -172,29 +172,39 @@
 } pst_string;
 
 
+/** This struct defines an email message
+ */
 typedef struct pst_item_email {
     FILETIME   *arrival_date;
-    int         autoforward;            // 1 = true, 0 = not set, -1 = false
+    /** 1 = true, 0 = not set, -1 = false */
+    int         autoforward;
     pst_string  cc_address;
     pst_string  bcc_address;
     int32_t     conversation_index;
-    int         conversion_prohibited;  // 1 = true, 0 = false
-    int         delete_after_submit;    // 1 = true, 0 = false
-    int         delivery_report;        // 1 = true, 0 = false
+    /** 1 = true, 0 = false */
+    int         conversion_prohibited;
+    /** 1 = true, 0 = false */
+    int         delete_after_submit;
+    /** 1 = true, 0 = false */
+    int         delivery_report;
     char       *encrypted_body;
     size_t      encrypted_body_size;
     char       *encrypted_htmlbody;
     size_t      encrypted_htmlbody_size;
-    int32_t     flag;
     pst_string  header;
     pst_string  htmlbody;
+    /** 0=low, 1=normal, 2=high */
     int32_t     importance;
     pst_string  in_reply_to;
-    int         message_cc_me;          // 1 = true, 0 = false
-    int         message_recip_me;       // 1 = true, 0 = false
-    int         message_to_me;          // 1 = true, 0 = false
+    /** 1 = true, 0 = false */
+    int         message_cc_me;
+    /** 1 = true, 0 = false */
+    int         message_recip_me;
+    /** 1 = true, 0 = false */
+    int         message_to_me;
     pst_string  messageid;
-    int32_t     orig_sensitivity;
+    /** 0=none, 1=personal, 2=private, 3=company confidential */
+    int32_t     original_sensitivity;
     pst_string  original_bcc;
     pst_string  original_cc;
     pst_string  original_to;
@@ -204,14 +214,17 @@
     pst_string  outlook_sender;
     pst_string  outlook_sender_name;
     pst_string  outlook_sender2;
+    /** 0=nonurgent, 1=normal, 2=urgent */
     int32_t     priority;
     pst_string  processed_subject;
-    int         read_receipt;           // 1 = true, 0 = false
+    /** 1 = true, 0 = false */
+    int         read_receipt;
     pst_string  recip_access;
     pst_string  recip_address;
     pst_string  recip2_access;
     pst_string  recip2_address;
-    int         reply_requested;        // 1 = true, 0 = false
+    /** 1 = true, 0 = false */
+    int         reply_requested;
     pst_string  reply_to;
     pst_string  return_path_address;
     int32_t     rtf_body_char_count;
@@ -219,13 +232,15 @@
     pst_string  rtf_body_tag;
     char       *rtf_compressed;
     uint32_t    rtf_compressed_size;
-    int         rtf_in_sync;            // 1 = true, 0 = doesn't exist, -1 = false
+    /** 1 = true, 0 = false */
+    int         rtf_in_sync;
     int32_t     rtf_ws_prefix_count;
     int32_t     rtf_ws_trailing_count;
     pst_string  sender_access;
     pst_string  sender_address;
     pst_string  sender2_access;
     pst_string  sender2_address;
+    /** 0=none, 1=personal, 2=private, 3=company confidential */
     int32_t     sensitivity;
     FILETIME    *sent_date;
     pst_entryid *sentmail_folder;
@@ -244,7 +259,8 @@
     int32_t  email_count;
     int32_t  unseen_email_count;
     int32_t  assoc_count;
-    int      subfolder;               // 1 = true, 0 = false
+    /** 1 = true, 0 = false */
+    int      subfolder;
 } pst_item_folder;
 
 
@@ -257,11 +273,23 @@
     pst_entryid *common_view_folder;            // 0x35e6
     pst_entryid *search_root_folder;            // 0x35e7
     pst_entryid *top_of_folder;                 // 0x7c07
-    int32_t valid_mask;                         // 0x35df  // what folders the message store contains
+    /** what folders the message store contains
+        @li FOLDER_IPM_SUBTREE_VALID  0x1
+        @li FOLDER_IPM_INBOX_VALID    0x2
+        @li FOLDER_IPM_OUTBOX_VALID   0x4
+        @li FOLDER_IPM_WASTEBOX_VALID 0x8
+        @li FOLDER_IPM_SENTMAIL_VALID 0x10
+        @li FOLDER_VIEWS_VALID        0x20
+        @li FOLDER_COMMON_VIEWS_VALID 0x40
+        @li FOLDER_FINDER_VALID       0x80
+     */
+    int32_t valid_mask;                         // 0x35df
     int32_t pwd_chksum;                         // 0x76ff
 } pst_item_message_store;
 
 
+/** This struct defines a contact
+ */
 typedef struct pst_item_contact {
     pst_string  access_method;
     pst_string  account_name;
@@ -306,6 +334,7 @@
     pst_string  free_busy_address;
     pst_string  ftp_site;
     pst_string  fullname;
+    /** 0=unspecified, 1=female, 2=male */
     int16_t     gender;
     pst_string  gov_id;
     pst_string  hobbies;
@@ -325,7 +354,8 @@
     pst_string  keyword;
     pst_string  language;
     pst_string  location;
-    int         mail_permission;                // 1 = true, 0 = false
+    /** 1 = true, 0 = false */
+    int         mail_permission;
     pst_string  manager_name;
     pst_string  middle_name;
     pst_string  mileage;
@@ -349,7 +379,8 @@
     pst_string  primary_phone;
     pst_string  profession;
     pst_string  radio_phone;
-    int         rich_text;                      // 1 = true, 0 = false
+    /** 1 = true, 0 = false */
+    int         rich_text;
     pst_string  spouse_name;
     pst_string  suffix;
     pst_string  surname;
@@ -373,8 +404,11 @@
     char       *data;
     size_t      size;
     uint64_t    id2_val;
-    uint64_t    id_val;     // calculated from id2_val during creation of record
-    pst_id2_ll *id2_head;   // deep copy from child
+    /** calculated from id2_val during creation of record */
+    uint64_t    id_val;
+    /** deep copy from child */
+    pst_id2_ll *id2_head;
+    /** 0=no attachment, 1=attach by value, 2=attach by reference, 3=attach by reference resolve, 4=attach by reference only, 5=embedded message, 6=OLE */
     int32_t     method;
     int32_t     position;
     int32_t     sequence;
@@ -389,6 +423,8 @@
 } pst_item_extra_field;
 
 
+/** This struct defines a journal entry
+ */
 typedef struct pst_item_journal {
     FILETIME   *end;
     FILETIME   *start;
@@ -397,19 +433,38 @@
 } pst_item_journal;
 
 
+/** This struct defines an appointment
+ */
 typedef struct pst_item_appointment {
     FILETIME   *end;
     pst_string  location;
-    int         alarm;              // 1 = true, 0 = false
+    /** 1 = true, 0 = false */
+    int         alarm;
     FILETIME   *reminder;
     int32_t     alarm_minutes;
     pst_string  alarm_filename;
     FILETIME   *start;
     pst_string  timezonestring;
+    /** 0=free, 1=tentative, 2=busy, 3=out of office*/
     int32_t     showas;
+    /** @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;
-    int         all_day;            // 1 = true, 0 = false
+    /** 1 = true, 0 = false */
+    int         all_day;
+    /** recurrence description */
     pst_string  recurrence;
+    /** 0=none, 1=daily, 2=weekly, 3=monthly, 4=yearly */
     int32_t     recurrence_type;
     FILETIME   *recurrence_start;
     FILETIME   *recurrence_end;
@@ -427,21 +482,38 @@
     struct pst_item_appointment   *appointment;     // data referring to a calendar entry
     int         type;
     char       *ascii_type;
+    /** @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;
     pst_string  file_as;
     pst_string  comment;
-    pst_string  body_charset;           // null if not specified
-    pst_string  body;                   // email, journal
-    pst_string  subject;                // email, journal
+    /** null if not specified */
+    pst_string  body_charset;
+    /** used by email and journal types */
+    pst_string  body;
+    /** used by email and journal types */
+    pst_string  subject;
     int32_t     internet_cpid;
     int32_t     message_codepage;
     int32_t     message_size;
     pst_string  outlook_version;
     char       *record_key;             // probably 16 bytes long.
     size_t      record_key_size;
-    int         response_requested;     // 1 = true, 0 = false
+    /** 1 = true, 0 = false */
+    int         response_requested;
     FILETIME   *create_date;
     FILETIME   *modify_date;
-    int         private_member;         // 1 = true, 0 = false
+    /** 1 = true, 0 = false */
+    int         private_member;
 } pst_item;
 
 
--- a/src/lspst.c	Thu Mar 12 15:17:32 2009 -0700
+++ b/src/lspst.c	Sat Mar 14 15:13:27 2009 -0700
@@ -85,9 +85,9 @@
                         printf("\t%s", pst_rfc2426_escape(item->contact->fullname.str));
                     printf("\n");
 
-                } else if (item->email && (item->type == PST_TYPE_NOTE || item->type == PST_TYPE_REPORT || item->type == PST_TYPE_OTHER)) {
+                } else if (item->email && (item->type == PST_TYPE_NOTE || item->type == PST_TYPE_REPORT)) {
                     // Process Email item
-                    if ((ff.type != PST_TYPE_NOTE) && (ff.type != PST_TYPE_REPORT) && (ff.type != PST_TYPE_OTHER)) {
+                    if ((ff.type != PST_TYPE_NOTE) && (ff.type != PST_TYPE_REPORT)) {
                         DEBUG_MAIN(("main: I have an email, but the folder isn't an email folder. Processing anyway\n"));
                     }
                     printf("Email");
--- a/src/pst2dii.cpp.in	Thu Mar 12 15:17:32 2009 -0700
+++ b/src/pst2dii.cpp.in	Sat Mar 14 15:13:27 2009 -0700
@@ -499,9 +499,7 @@
         write_simple("SUBJECT", item->subject.str);
     }
     write_simple("MSGID", item->email->messageid.str);
-    if (item->email->flag) {
-        write_simple("READ", (item->email->flag & 1) ? "Y" : "N");
-    }
+    write_simple("READ", (item->flags & 1) ? "Y" : "N");
 
     DEBUG_EMAIL(("About to print Header\n"));
     fprintf(dii_file, "@HEADER\n");
--- a/src/readpst.c	Thu Mar 12 15:17:32 2009 -0700
+++ b/src/readpst.c	Sat Mar 14 15:13:27 2009 -0700
@@ -11,7 +11,7 @@
 #define OUTPUT_TEMPLATE "%s"
 #define OUTPUT_KMAIL_DIR_TEMPLATE ".%s.directory"
 #define KMAIL_INDEX ".%s.index"
-#define SEP_MAIL_FILE_TEMPLATE "%i" /* "%09i" */
+#define SEP_MAIL_FILE_TEMPLATE "%i"
 
 // max size of the c_time char*. It will store the date of the email
 #define C_TIME_SIZE 500
@@ -31,9 +31,9 @@
 void      removeCR(char *c);
 void      usage();
 void      version();
-char*     mk_kmail_dir(char*);
+char*     mk_kmail_dir(char* fname);
 int       close_kmail_dir();
-char*     mk_recurse_dir(char*);
+char*     mk_recurse_dir(char* dir, int32_t folder_type);
 int       close_recurse_dir();
 char*     mk_separate_dir(char *dir);
 int       close_separate_dir();
@@ -109,11 +109,12 @@
 #define RTF_ATTACH_TYPE "application/rtf"
 
 // global settings
-int mode = MODE_NORMAL;
-int mode_MH = 0;
-int output_mode = OUTPUT_NORMAL;
+int mode         = MODE_NORMAL;
+int mode_MH      = 0;   // a submode of MODE_SEPARATE
+int output_mode  = OUTPUT_NORMAL;
 int contact_mode = CMODE_VCARD;
 int deleted_mode = DMODE_EXCLUDE;
+int contact_mode_specified = 0;
 int overwrite = 0;
 int save_rtf_body = 1;
 pst_file pstfile;
@@ -150,14 +151,11 @@
                     process(item, d_ptr->child);
 
                 } else if (item->contact && (item->type == PST_TYPE_CONTACT)) {
-                    // deal with a contact
-                    // write them to the file, one per line in this format
-                    // Desc Name <email@address>\n
                     if (mode == MODE_SEPARATE) mk_separate_file(&ff);
                     ff.email_count++;
                     DEBUG_MAIN(("main: Processing Contact\n"));
                     if (ff.type != PST_TYPE_CONTACT) {
-                        DEBUG_MAIN(("main: I have a contact, but the folder isn't a contacts folder. Processing anyway\n"));
+                        DEBUG_MAIN(("main: I have a contact, but the folder type %"PRIi32" isn't a contacts folder. Processing anyway\n", ff.type));
                     }
                     if (contact_mode == CMODE_VCARD) {
                         pst_convert_utf8_null(item, &item->comment);
@@ -169,23 +167,22 @@
                         fprintf(ff.output, "%s <%s>\n", item->contact->fullname.str, item->contact->address1.str);
                     }
 
-                } else if (item->email && (item->type == PST_TYPE_NOTE || item->type == PST_TYPE_REPORT || item->type == PST_TYPE_OTHER)) {
+                } else if (item->email && (item->type == PST_TYPE_NOTE || item->type == PST_TYPE_REPORT)) {
                     char *extra_mime_headers = NULL;
                     if (mode == MODE_SEPARATE) mk_separate_file(&ff);
                     ff.email_count++;
                     DEBUG_MAIN(("main: Processing Email\n"));
-                    if ((ff.type != PST_TYPE_NOTE) && (ff.type != PST_TYPE_REPORT) && (ff.type != PST_TYPE_OTHER)) {
-                        DEBUG_MAIN(("main: I have an email, but the folder isn't an email folder. Processing anyway\n"));
+                    if ((ff.type != PST_TYPE_NOTE) && (ff.type != PST_TYPE_REPORT)) {
+                        DEBUG_MAIN(("main: I have an email type %"PRIi32", but the folder type %"PRIi32" isn't an email folder. Processing anyway\n", item->type, ff.type));
                     }
                     write_normal_email(ff.output, ff.name, item, mode, mode_MH, &pstfile, save_rtf_body, &extra_mime_headers);
 
                 } else if (item->journal && (item->type == PST_TYPE_JOURNAL)) {
-                    // deal with journal items
                     if (mode == MODE_SEPARATE) mk_separate_file(&ff);
                     ff.email_count++;
                     DEBUG_MAIN(("main: Processing Journal Entry\n"));
                     if (ff.type != PST_TYPE_JOURNAL) {
-                        DEBUG_MAIN(("main: I have a journal entry, but the folder isn't a journal folder. Processing anyway\n"));
+                        DEBUG_MAIN(("main: I have a journal entry, but the folder type %"PRIi32" isn't a journal folder. Processing anyway\n", ff.type));
                     }
                     fprintf(ff.output, "BEGIN:VJOURNAL\n");
                     if (item->subject.str) {
@@ -201,12 +198,11 @@
                     fprintf(ff.output, "END:VJOURNAL\n\n");
 
                 } else if (item->appointment && (item->type == PST_TYPE_APPOINTMENT)) {
-                    // deal with Calendar appointments
                     if (mode == MODE_SEPARATE) mk_separate_file(&ff);
                     ff.email_count++;
                     DEBUG_MAIN(("main: Processing Appointment Entry\n"));
                     if (ff.type != PST_TYPE_APPOINTMENT) {
-                        DEBUG_MAIN(("main: I have an appointment, but folder isn't specified as an appointment type. Processing...\n"));
+                        DEBUG_MAIN(("main: I have an appointment, but folder type %"PRIi32" isn't an appointment folder. Processing anyway\n", ff.type));
                     }
                     write_appointment(ff.output, item, item->appointment, item->create_date, item->modify_date);
 
@@ -261,10 +257,14 @@
             mode = MODE_DECSPEW;
             break;
         case 'c':
-            if (optarg && optarg[0]=='v')
+            if (optarg && optarg[0]=='v') {
                 contact_mode=CMODE_VCARD;
-            else if (optarg && optarg[0]=='l')
+                contact_mode_specified = 1;
+            }
+            else if (optarg && optarg[0]=='l') {
                 contact_mode=CMODE_LIST;
+                contact_mode_specified = 1;
+            }
             else {
                 usage();
                 exit(0);
@@ -302,6 +302,7 @@
             break;
         case 'S':
             mode = MODE_SEPARATE;
+            mode_MH = 0;
             break;
         case 'w':
             overwrite = 1;
@@ -538,7 +539,7 @@
 // this will create a directory by that name, then make an mbox file inside
 // that dir.  any subsequent dirs will be created by name, and they will
 // contain mbox files
-char *mk_recurse_dir(char *dir) {
+char *mk_recurse_dir(char *dir, int32_t folder_type) {
     int x;
     char *out_name;
     DEBUG_ENT("mk_recurse_dir");
@@ -553,8 +554,25 @@
         x = errno;
         DIE(("mk_recurse_dir: Cannot change to directory %s: %s\n", dir, strerror(x)));
     }
-    out_name = malloc(strlen("mbox")+1);
-    strcpy(out_name, "mbox");
+    switch (folder_type) {
+        case PST_TYPE_APPOINTMENT:
+            out_name = strdup("calendar");
+            break;
+        case PST_TYPE_CONTACT:
+            out_name = strdup("contacts");
+            break;
+        case PST_TYPE_JOURNAL:
+            out_name = strdup("journal");
+            break;
+        case PST_TYPE_STICKYNOTE:
+        case PST_TYPE_TASK:
+        case PST_TYPE_NOTE:
+        case PST_TYPE_OTHER:
+        case PST_TYPE_REPORT:
+        default:
+            out_name = strdup("mbox");
+            break;
+    }
     DEBUG_RET();
     return out_name;
 }
@@ -1558,9 +1576,9 @@
 
     DEBUG_ENT("create_enter_dir");
     if (mode == MODE_KMAIL)
-        f->name = mk_kmail_dir(item->file_as.str); //create directory and form filename
+        f->name = mk_kmail_dir(item->file_as.str);
     else if (mode == MODE_RECURSE)
-        f->name = mk_recurse_dir(item->file_as.str);
+        f->name = mk_recurse_dir(item->file_as.str, f->type);
     else if (mode == MODE_SEPARATE) {
         // do similar stuff to recurse here.
         mk_separate_dir(item->file_as.str);