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);