Mercurial > libpst
comparison src/readpst.c @ 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 | cda7c812ec01 |
children | ab384fed78c5 |
comparison
equal
deleted
inserted
replaced
153:0b1766da9be8 | 154:581fab9f1dc7 |
---|---|
9 #include "lzfu.h" | 9 #include "lzfu.h" |
10 | 10 |
11 #define OUTPUT_TEMPLATE "%s" | 11 #define OUTPUT_TEMPLATE "%s" |
12 #define OUTPUT_KMAIL_DIR_TEMPLATE ".%s.directory" | 12 #define OUTPUT_KMAIL_DIR_TEMPLATE ".%s.directory" |
13 #define KMAIL_INDEX ".%s.index" | 13 #define KMAIL_INDEX ".%s.index" |
14 #define SEP_MAIL_FILE_TEMPLATE "%i" /* "%09i" */ | 14 #define SEP_MAIL_FILE_TEMPLATE "%i" |
15 | 15 |
16 // max size of the c_time char*. It will store the date of the email | 16 // max size of the c_time char*. It will store the date of the email |
17 #define C_TIME_SIZE 500 | 17 #define C_TIME_SIZE 500 |
18 | 18 |
19 struct file_ll { | 19 struct file_ll { |
29 void process(pst_item *outeritem, pst_desc_ll *d_ptr); | 29 void process(pst_item *outeritem, pst_desc_ll *d_ptr); |
30 void write_email_body(FILE *f, char *body); | 30 void write_email_body(FILE *f, char *body); |
31 void removeCR(char *c); | 31 void removeCR(char *c); |
32 void usage(); | 32 void usage(); |
33 void version(); | 33 void version(); |
34 char* mk_kmail_dir(char*); | 34 char* mk_kmail_dir(char* fname); |
35 int close_kmail_dir(); | 35 int close_kmail_dir(); |
36 char* mk_recurse_dir(char*); | 36 char* mk_recurse_dir(char* dir, int32_t folder_type); |
37 int close_recurse_dir(); | 37 int close_recurse_dir(); |
38 char* mk_separate_dir(char *dir); | 38 char* mk_separate_dir(char *dir); |
39 int close_separate_dir(); | 39 int close_separate_dir(); |
40 int mk_separate_file(struct file_ll *f); | 40 int mk_separate_file(struct file_ll *f); |
41 char* my_stristr(char *haystack, char *needle); | 41 char* my_stristr(char *haystack, char *needle); |
107 #define RTF_ATTACH_NAME "rtf-body.rtf" | 107 #define RTF_ATTACH_NAME "rtf-body.rtf" |
108 // mime type for the attachment | 108 // mime type for the attachment |
109 #define RTF_ATTACH_TYPE "application/rtf" | 109 #define RTF_ATTACH_TYPE "application/rtf" |
110 | 110 |
111 // global settings | 111 // global settings |
112 int mode = MODE_NORMAL; | 112 int mode = MODE_NORMAL; |
113 int mode_MH = 0; | 113 int mode_MH = 0; // a submode of MODE_SEPARATE |
114 int output_mode = OUTPUT_NORMAL; | 114 int output_mode = OUTPUT_NORMAL; |
115 int contact_mode = CMODE_VCARD; | 115 int contact_mode = CMODE_VCARD; |
116 int deleted_mode = DMODE_EXCLUDE; | 116 int deleted_mode = DMODE_EXCLUDE; |
117 int contact_mode_specified = 0; | |
117 int overwrite = 0; | 118 int overwrite = 0; |
118 int save_rtf_body = 1; | 119 int save_rtf_body = 1; |
119 pst_file pstfile; | 120 pst_file pstfile; |
120 regex_t meta_charset_pattern; | 121 regex_t meta_charset_pattern; |
121 | 122 |
148 //if this is a non-empty folder other than deleted items, we want to recurse into it | 149 //if this is a non-empty folder other than deleted items, we want to recurse into it |
149 if (output_mode != OUTPUT_QUIET) printf("Processing Folder \"%s\"\n", item->file_as.str); | 150 if (output_mode != OUTPUT_QUIET) printf("Processing Folder \"%s\"\n", item->file_as.str); |
150 process(item, d_ptr->child); | 151 process(item, d_ptr->child); |
151 | 152 |
152 } else if (item->contact && (item->type == PST_TYPE_CONTACT)) { | 153 } else if (item->contact && (item->type == PST_TYPE_CONTACT)) { |
153 // deal with a contact | |
154 // write them to the file, one per line in this format | |
155 // Desc Name <email@address>\n | |
156 if (mode == MODE_SEPARATE) mk_separate_file(&ff); | 154 if (mode == MODE_SEPARATE) mk_separate_file(&ff); |
157 ff.email_count++; | 155 ff.email_count++; |
158 DEBUG_MAIN(("main: Processing Contact\n")); | 156 DEBUG_MAIN(("main: Processing Contact\n")); |
159 if (ff.type != PST_TYPE_CONTACT) { | 157 if (ff.type != PST_TYPE_CONTACT) { |
160 DEBUG_MAIN(("main: I have a contact, but the folder isn't a contacts folder. Processing anyway\n")); | 158 DEBUG_MAIN(("main: I have a contact, but the folder type %"PRIi32" isn't a contacts folder. Processing anyway\n", ff.type)); |
161 } | 159 } |
162 if (contact_mode == CMODE_VCARD) { | 160 if (contact_mode == CMODE_VCARD) { |
163 pst_convert_utf8_null(item, &item->comment); | 161 pst_convert_utf8_null(item, &item->comment); |
164 write_vcard(ff.output, item, item->contact, item->comment.str); | 162 write_vcard(ff.output, item, item->contact, item->comment.str); |
165 } | 163 } |
167 pst_convert_utf8(item, &item->contact->fullname); | 165 pst_convert_utf8(item, &item->contact->fullname); |
168 pst_convert_utf8(item, &item->contact->address1); | 166 pst_convert_utf8(item, &item->contact->address1); |
169 fprintf(ff.output, "%s <%s>\n", item->contact->fullname.str, item->contact->address1.str); | 167 fprintf(ff.output, "%s <%s>\n", item->contact->fullname.str, item->contact->address1.str); |
170 } | 168 } |
171 | 169 |
172 } else if (item->email && (item->type == PST_TYPE_NOTE || item->type == PST_TYPE_REPORT || item->type == PST_TYPE_OTHER)) { | 170 } else if (item->email && (item->type == PST_TYPE_NOTE || item->type == PST_TYPE_REPORT)) { |
173 char *extra_mime_headers = NULL; | 171 char *extra_mime_headers = NULL; |
174 if (mode == MODE_SEPARATE) mk_separate_file(&ff); | 172 if (mode == MODE_SEPARATE) mk_separate_file(&ff); |
175 ff.email_count++; | 173 ff.email_count++; |
176 DEBUG_MAIN(("main: Processing Email\n")); | 174 DEBUG_MAIN(("main: Processing Email\n")); |
177 if ((ff.type != PST_TYPE_NOTE) && (ff.type != PST_TYPE_REPORT) && (ff.type != PST_TYPE_OTHER)) { | 175 if ((ff.type != PST_TYPE_NOTE) && (ff.type != PST_TYPE_REPORT)) { |
178 DEBUG_MAIN(("main: I have an email, but the folder isn't an email folder. Processing anyway\n")); | 176 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)); |
179 } | 177 } |
180 write_normal_email(ff.output, ff.name, item, mode, mode_MH, &pstfile, save_rtf_body, &extra_mime_headers); | 178 write_normal_email(ff.output, ff.name, item, mode, mode_MH, &pstfile, save_rtf_body, &extra_mime_headers); |
181 | 179 |
182 } else if (item->journal && (item->type == PST_TYPE_JOURNAL)) { | 180 } else if (item->journal && (item->type == PST_TYPE_JOURNAL)) { |
183 // deal with journal items | |
184 if (mode == MODE_SEPARATE) mk_separate_file(&ff); | 181 if (mode == MODE_SEPARATE) mk_separate_file(&ff); |
185 ff.email_count++; | 182 ff.email_count++; |
186 DEBUG_MAIN(("main: Processing Journal Entry\n")); | 183 DEBUG_MAIN(("main: Processing Journal Entry\n")); |
187 if (ff.type != PST_TYPE_JOURNAL) { | 184 if (ff.type != PST_TYPE_JOURNAL) { |
188 DEBUG_MAIN(("main: I have a journal entry, but the folder isn't a journal folder. Processing anyway\n")); | 185 DEBUG_MAIN(("main: I have a journal entry, but the folder type %"PRIi32" isn't a journal folder. Processing anyway\n", ff.type)); |
189 } | 186 } |
190 fprintf(ff.output, "BEGIN:VJOURNAL\n"); | 187 fprintf(ff.output, "BEGIN:VJOURNAL\n"); |
191 if (item->subject.str) { | 188 if (item->subject.str) { |
192 pst_convert_utf8(item, &item->subject); | 189 pst_convert_utf8(item, &item->subject); |
193 fprintf(ff.output, "SUMMARY:%s\n", pst_rfc2426_escape(item->subject.str)); | 190 fprintf(ff.output, "SUMMARY:%s\n", pst_rfc2426_escape(item->subject.str)); |
199 if (item->journal->start) | 196 if (item->journal->start) |
200 fprintf(ff.output, "DTSTART;VALUE=DATE-TIME:%s\n", pst_rfc2445_datetime_format(item->journal->start)); | 197 fprintf(ff.output, "DTSTART;VALUE=DATE-TIME:%s\n", pst_rfc2445_datetime_format(item->journal->start)); |
201 fprintf(ff.output, "END:VJOURNAL\n\n"); | 198 fprintf(ff.output, "END:VJOURNAL\n\n"); |
202 | 199 |
203 } else if (item->appointment && (item->type == PST_TYPE_APPOINTMENT)) { | 200 } else if (item->appointment && (item->type == PST_TYPE_APPOINTMENT)) { |
204 // deal with Calendar appointments | |
205 if (mode == MODE_SEPARATE) mk_separate_file(&ff); | 201 if (mode == MODE_SEPARATE) mk_separate_file(&ff); |
206 ff.email_count++; | 202 ff.email_count++; |
207 DEBUG_MAIN(("main: Processing Appointment Entry\n")); | 203 DEBUG_MAIN(("main: Processing Appointment Entry\n")); |
208 if (ff.type != PST_TYPE_APPOINTMENT) { | 204 if (ff.type != PST_TYPE_APPOINTMENT) { |
209 DEBUG_MAIN(("main: I have an appointment, but folder isn't specified as an appointment type. Processing...\n")); | 205 DEBUG_MAIN(("main: I have an appointment, but folder type %"PRIi32" isn't an appointment folder. Processing anyway\n", ff.type)); |
210 } | 206 } |
211 write_appointment(ff.output, item, item->appointment, item->create_date, item->modify_date); | 207 write_appointment(ff.output, item, item->appointment, item->create_date, item->modify_date); |
212 | 208 |
213 } else if (item->message_store) { | 209 } else if (item->message_store) { |
214 // there should only be one message_store, and we have already done it | 210 // there should only be one message_store, and we have already done it |
259 break; | 255 break; |
260 case 'C': | 256 case 'C': |
261 mode = MODE_DECSPEW; | 257 mode = MODE_DECSPEW; |
262 break; | 258 break; |
263 case 'c': | 259 case 'c': |
264 if (optarg && optarg[0]=='v') | 260 if (optarg && optarg[0]=='v') { |
265 contact_mode=CMODE_VCARD; | 261 contact_mode=CMODE_VCARD; |
266 else if (optarg && optarg[0]=='l') | 262 contact_mode_specified = 1; |
263 } | |
264 else if (optarg && optarg[0]=='l') { | |
267 contact_mode=CMODE_LIST; | 265 contact_mode=CMODE_LIST; |
266 contact_mode_specified = 1; | |
267 } | |
268 else { | 268 else { |
269 usage(); | 269 usage(); |
270 exit(0); | 270 exit(0); |
271 } | 271 } |
272 break; | 272 break; |
300 case 'r': | 300 case 'r': |
301 mode = MODE_RECURSE; | 301 mode = MODE_RECURSE; |
302 break; | 302 break; |
303 case 'S': | 303 case 'S': |
304 mode = MODE_SEPARATE; | 304 mode = MODE_SEPARATE; |
305 mode_MH = 0; | |
305 break; | 306 break; |
306 case 'w': | 307 case 'w': |
307 overwrite = 1; | 308 overwrite = 1; |
308 break; | 309 break; |
309 default: | 310 default: |
536 | 537 |
537 | 538 |
538 // this will create a directory by that name, then make an mbox file inside | 539 // this will create a directory by that name, then make an mbox file inside |
539 // that dir. any subsequent dirs will be created by name, and they will | 540 // that dir. any subsequent dirs will be created by name, and they will |
540 // contain mbox files | 541 // contain mbox files |
541 char *mk_recurse_dir(char *dir) { | 542 char *mk_recurse_dir(char *dir, int32_t folder_type) { |
542 int x; | 543 int x; |
543 char *out_name; | 544 char *out_name; |
544 DEBUG_ENT("mk_recurse_dir"); | 545 DEBUG_ENT("mk_recurse_dir"); |
545 check_filename(dir); | 546 check_filename(dir); |
546 if (D_MKDIR (dir)) { | 547 if (D_MKDIR (dir)) { |
551 } | 552 } |
552 if (chdir (dir)) { | 553 if (chdir (dir)) { |
553 x = errno; | 554 x = errno; |
554 DIE(("mk_recurse_dir: Cannot change to directory %s: %s\n", dir, strerror(x))); | 555 DIE(("mk_recurse_dir: Cannot change to directory %s: %s\n", dir, strerror(x))); |
555 } | 556 } |
556 out_name = malloc(strlen("mbox")+1); | 557 switch (folder_type) { |
557 strcpy(out_name, "mbox"); | 558 case PST_TYPE_APPOINTMENT: |
559 out_name = strdup("calendar"); | |
560 break; | |
561 case PST_TYPE_CONTACT: | |
562 out_name = strdup("contacts"); | |
563 break; | |
564 case PST_TYPE_JOURNAL: | |
565 out_name = strdup("journal"); | |
566 break; | |
567 case PST_TYPE_STICKYNOTE: | |
568 case PST_TYPE_TASK: | |
569 case PST_TYPE_NOTE: | |
570 case PST_TYPE_OTHER: | |
571 case PST_TYPE_REPORT: | |
572 default: | |
573 out_name = strdup("mbox"); | |
574 break; | |
575 } | |
558 DEBUG_RET(); | 576 DEBUG_RET(); |
559 return out_name; | 577 return out_name; |
560 } | 578 } |
561 | 579 |
562 | 580 |
1556 f->type = item->type; | 1574 f->type = item->type; |
1557 f->stored_count = (item->folder) ? item->folder->email_count : 0; | 1575 f->stored_count = (item->folder) ? item->folder->email_count : 0; |
1558 | 1576 |
1559 DEBUG_ENT("create_enter_dir"); | 1577 DEBUG_ENT("create_enter_dir"); |
1560 if (mode == MODE_KMAIL) | 1578 if (mode == MODE_KMAIL) |
1561 f->name = mk_kmail_dir(item->file_as.str); //create directory and form filename | 1579 f->name = mk_kmail_dir(item->file_as.str); |
1562 else if (mode == MODE_RECURSE) | 1580 else if (mode == MODE_RECURSE) |
1563 f->name = mk_recurse_dir(item->file_as.str); | 1581 f->name = mk_recurse_dir(item->file_as.str, f->type); |
1564 else if (mode == MODE_SEPARATE) { | 1582 else if (mode == MODE_SEPARATE) { |
1565 // do similar stuff to recurse here. | 1583 // do similar stuff to recurse here. |
1566 mk_separate_dir(item->file_as.str); | 1584 mk_separate_dir(item->file_as.str); |
1567 f->name = (char*) xmalloc(10); | 1585 f->name = (char*) xmalloc(10); |
1568 memset(f->name, 0, 10); | 1586 memset(f->name, 0, 10); |