comparison src/readpst.c @ 43:f6db1f060a95

start on outlook 2003 64 bit format
author carl
date Sun, 06 Jan 2008 14:47:06 -0800
parents 183ae993b9ad
children b961bcdadd0e
comparison
equal deleted inserted replaced
42:7a97f50c39c5 43:f6db1f060a95
1 /*** 1 /***
2 * readpst.c 2 * readpst.c
3 * Part of the LibPST project 3 * Part of the LibPST project
4 * Written by David Smith 4 * Written by David Smith
5 * dave.s@earthcorp.com 5 * dave.s@earthcorp.com
6 */ 6 */
7 #include <stdio.h> 7 #include <stdio.h>
8 #include <stdlib.h> 8 #include <stdlib.h>
9 #include <time.h> 9 #include <time.h>
10 #include <string.h> 10 #include <string.h>
11 #include <ctype.h> 11 #include <ctype.h>
12 #include <limits.h> 12 #include <limits.h>
13 #include <errno.h> 13 #include <errno.h>
14 #include "vbuf.h"
14 15
15 #ifndef _WIN32 16 #ifndef _WIN32
16 # include <unistd.h> 17 # include <unistd.h>
17 # include <sys/stat.h> //mkdir 18 # include <sys/stat.h> //mkdir
18 19
51 #define D_MKDIR(x) mkdir(x, PERM_DIRS) 52 #define D_MKDIR(x) mkdir(x, PERM_DIRS)
52 #else 53 #else
53 #define D_MKDIR(x) mkdir(x) 54 #define D_MKDIR(x) mkdir(x)
54 #endif 55 #endif
55 struct file_ll { 56 struct file_ll {
56 char *name; 57 char *name;
57 char *dname; 58 char *dname;
58 FILE * output; 59 FILE * output;
59 int32_t stored_count; 60 int32_t stored_count;
60 int32_t email_count; 61 int32_t email_count;
61 int32_t skip_count; 62 int32_t skip_count;
62 int32_t type; 63 int32_t type;
63 }; 64 };
64 65
65 void process(pst_item *outeritem, pst_desc_ll *d_ptr); 66 void process(pst_item *outeritem, pst_desc_ll *d_ptr);
66 void write_email_body(FILE *f, char *body); 67 void write_email_body(FILE *f, char *body);
67 char* removeCR (char *c); 68 char* removeCR (char *c);
68 int32_t usage(); 69 int usage();
69 int32_t version(); 70 int version();
70 char* mk_kmail_dir(char*); 71 char* mk_kmail_dir(char*);
71 int32_t close_kmail_dir(); 72 int close_kmail_dir();
72 char* mk_recurse_dir(char*); 73 char* mk_recurse_dir(char*);
73 int32_t close_recurse_dir(); 74 int close_recurse_dir();
74 char* mk_seperate_dir(char *dir); 75 char* mk_seperate_dir(char *dir);
75 int32_t close_seperate_dir(); 76 int close_seperate_dir();
76 int32_t mk_seperate_file(struct file_ll *f); 77 int mk_seperate_file(struct file_ll *f);
77 char* my_stristr(char *haystack, char *needle); 78 char* my_stristr(char *haystack, char *needle);
78 void check_filename(char *fname); 79 void check_filename(char *fname);
79 char* rfc2426_escape(char *str); 80 char* skip_header_prologue(char *headers);
80 int32_t chr_count(char *str, char x); 81 void write_separate_attachment(char f_name[], pst_item_attach* current_attach, int attach_num, pst_file* pst);
81 char* rfc2425_datetime_format(FILETIME *ft); 82 void write_inline_attachment(FILE* f_output, pst_item_attach* current_attach, char boundary[], pst_file* pst);
82 char* rfc2445_datetime_format(FILETIME *ft); 83 void write_normal_email(FILE* f_output, char f_name[], pst_item* item, int mode, int mode_MH, pst_file* pst, int save_rtf);
83 char* skip_header_prologue(char *headers); 84 void write_vcard(FILE* f_output, pst_item_contact* contact, char comment[]);
84 void write_separate_attachment(char f_name[], pst_item_attach* current_attach, int attach_num, pst_file* pst); 85 void write_appointment(FILE* f_output, pst_item_appointment* appointment,
85 void write_inline_attachment(FILE* f_output, pst_item_attach* current_attach, char boundary[], pst_file* pst); 86 pst_item_email* email, FILETIME* create_date, FILETIME* modify_date);
86 void write_normal_email(FILE* f_output, char f_name[], pst_item* item, int mode, int mode_MH, pst_file* pst, int save_rtf); 87 void create_enter_dir(struct file_ll* f, pst_item *item);
87 void write_vcard(FILE* f_output, pst_item_contact* contact, char comment[]); 88 void close_enter_dir(struct file_ll *f);
88 void write_appointment(FILE* f_output, pst_item_appointment* appointment,
89 pst_item_email* email, FILETIME* create_date, FILETIME* modify_date);
90 void create_enter_dir(struct file_ll* f, pst_item *item);
91 void close_enter_dir(struct file_ll *f);
92 89
93 char* prog_name; 90 char* prog_name;
94 char* output_dir = "."; 91 char* output_dir = ".";
95 char* kmail_chdir = NULL; 92 char* kmail_chdir = NULL;
96 // Normal mode just creates mbox format files in the current directory. Each file is named 93 // Normal mode just creates mbox format files in the current directory. Each file is named
104 #define MODE_RECURSE 2 101 #define MODE_RECURSE 2
105 // seperate mode is similar directory structure to RECURSE. The emails are stored in 102 // seperate mode is similar directory structure to RECURSE. The emails are stored in
106 // seperate files, numbering from 1 upward. Attachments belonging to the emails are 103 // seperate files, numbering from 1 upward. Attachments belonging to the emails are
107 // saved as email_no-filename (e.g. 1-samplefile.doc or 000001-Attachment2.zip) 104 // saved as email_no-filename (e.g. 1-samplefile.doc or 000001-Attachment2.zip)
108 #define MODE_SEPERATE 3 105 #define MODE_SEPERATE 3
106 // Decrypt the whole file (even the parts that aren't encrypted) and ralph it to stdout
107 #define MODE_DECSPEW 4
109 108
110 109
111 // Output Normal just prints the standard information about what is going on 110 // Output Normal just prints the standard information about what is going on
112 #define OUTPUT_NORMAL 0 111 #define OUTPUT_NORMAL 0
113 // Output Quiet is provided so that only errors are printed 112 // Output Quiet is provided so that only errors are printed
116 // default mime-type for attachments that have a null mime-type 115 // default mime-type for attachments that have a null mime-type
117 #define MIME_TYPE_DEFAULT "application/octet-stream" 116 #define MIME_TYPE_DEFAULT "application/octet-stream"
118 117
119 // output mode for contacts 118 // output mode for contacts
120 #define CMODE_VCARD 0 119 #define CMODE_VCARD 0
121 #define CMODE_LIST 1 120 #define CMODE_LIST 1
122 121
123 // output settings for RTF bodies 122 // output settings for RTF bodies
124 // filename for the attachment 123 // filename for the attachment
125 #define RTF_ATTACH_NAME "rtf-body.rtf" 124 #define RTF_ATTACH_NAME "rtf-body.rtf"
126 // mime type for the attachment 125 // mime type for the attachment
137 136
138 137
139 138
140 void process(pst_item *outeritem, pst_desc_ll *d_ptr) 139 void process(pst_item *outeritem, pst_desc_ll *d_ptr)
141 { 140 {
142 struct file_ll ff; 141 struct file_ll ff;
143 pst_item *item = NULL; 142 pst_item *item = NULL;
144 143
145 DEBUG_ENT("process"); 144 DEBUG_ENT("process");
146 memset(&ff, 0, sizeof(ff)); 145 memset(&ff, 0, sizeof(ff));
147 create_enter_dir(&ff, outeritem); 146 create_enter_dir(&ff, outeritem);
148 147
149 while (d_ptr) { 148 while (d_ptr) {
150 DEBUG_MAIN(("main: New item record\n")); 149 DEBUG_MAIN(("main: New item record\n"));
151 if (!d_ptr->desc) { 150 if (!d_ptr->desc) {
152 DEBUG_WARN(("main: ERROR ?? item's desc record is NULL\n")); 151 DEBUG_WARN(("main: ERROR ?? item's desc record is NULL\n"));
153 ff.skip_count++; 152 ff.skip_count++;
154 } 153 }
155 else { 154 else {
156 DEBUG_MAIN(("main: Desc Email ID %#x [d_ptr->id = %#x]\n", d_ptr->desc->id, d_ptr->id)); 155 DEBUG_MAIN(("main: Desc Email ID %#x [d_ptr->id = %#x]\n", d_ptr->desc->id, d_ptr->id));
157 156
158 item = _pst_parse_item(&pstfile, d_ptr); 157 item = _pst_parse_item(&pstfile, d_ptr);
159 DEBUG_MAIN(("main: About to process item\n")); 158 DEBUG_MAIN(("main: About to process item\n"));
160 if (item && item->email && item->email->subject && item->email->subject->subj) { 159 if (item && item->email && item->email->subject && item->email->subject->subj) {
161 DEBUG_EMAIL(("item->email->subject = %p\n", item->email->subject)); 160 DEBUG_EMAIL(("item->email->subject = %p\n", item->email->subject));
162 DEBUG_EMAIL(("item->email->subject->subj = %p\n", item->email->subject->subj)); 161 DEBUG_EMAIL(("item->email->subject->subj = %p\n", item->email->subject->subj));
163 } 162 }
164 if (item) { 163 if (item) {
165 if (item->message_store) { 164 if (item->message_store) {
166 // there should only be one message_store, and we have already done it 165 // there should only be one message_store, and we have already done it
167 DIE(("main: A second message_store has been found. Sorry, this must be an error.\n")); 166 DIE(("main: A second message_store has been found. Sorry, this must be an error.\n"));
168 } 167 }
169 168
170 if (item->folder && d_ptr->child && strcasecmp(item->file_as, "Deleted Items")) { 169 if (item->folder && d_ptr->child && strcasecmp(item->file_as, "Deleted Items")) {
171 //if this is a non-empty folder other than deleted items, we want to recurse into it 170 //if this is a non-empty folder other than deleted items, we want to recurse into it
172 if (output_mode != OUTPUT_QUIET) printf("Processing Folder \"%s\"\n", item->file_as); 171 if (output_mode != OUTPUT_QUIET) printf("Processing Folder \"%s\"\n", item->file_as);
173 process(item, d_ptr->child); 172 process(item, d_ptr->child);
174 173
175 } else if (item->contact) { 174 } else if (item->contact && (item->type == PST_TYPE_CONTACT)) {
176 // deal with a contact 175 // deal with a contact
177 // write them to the file, one per line in this format 176 // write them to the file, one per line in this format
178 // Desc Name <email@address>\n 177 // Desc Name <email@address>\n
179 if (mode == MODE_SEPERATE) mk_seperate_file(&ff); 178 if (mode == MODE_SEPERATE) mk_seperate_file(&ff);
180 ff.email_count++; 179 ff.email_count++;
181 DEBUG_MAIN(("main: Processing Contact\n")); 180 DEBUG_MAIN(("main: Processing Contact\n"));
182 if (ff.type != PST_TYPE_CONTACT) { 181 if (ff.type != PST_TYPE_CONTACT) {
183 DEBUG_MAIN(("main: I have a contact, but the folder isn't a contacts folder. " 182 DEBUG_MAIN(("main: I have a contact, but the folder isn't a contacts folder. Processing anyway\n"));
184 "Will process anyway\n")); 183 }
185 } 184 if (contact_mode == CMODE_VCARD)
186 if (item->type != PST_TYPE_CONTACT) { 185 write_vcard(ff.output, item->contact, item->comment);
187 DEBUG_MAIN(("main: I have an item that has contact info, but doesn't say that" 186 else
188 " it is a contact. Type is \"%s\"\n", item->ascii_type)); 187 fprintf(ff.output, "%s <%s>\n", item->contact->fullname, item->contact->address1);
189 DEBUG_MAIN(("main: Processing anyway\n")); 188
190 } 189 } else if (item->email && (item->type == PST_TYPE_NOTE || item->type == PST_TYPE_REPORT)) {
191 if (!item->contact) { // this is an incorrect situation. Inform user 190 if (mode == MODE_SEPERATE) mk_seperate_file(&ff);
192 DEBUG_MAIN(("main: ERROR. This contact has not been fully parsed. one of the pre-requisties is NULL\n")); 191 ff.email_count++;
193 } else { 192 DEBUG_MAIN(("main: Processing Email\n"));
194 if (contact_mode == CMODE_VCARD) 193 if ((ff.type != PST_TYPE_NOTE) && (ff.type != PST_TYPE_REPORT)) {
195 write_vcard(ff.output, item->contact, item->comment); 194 DEBUG_MAIN(("main: I have an email, but the folder isn't an email folder. Processing anyway\n"));
196 else 195 }
197 fprintf(ff.output, "%s <%s>\n", item->contact->fullname, item->contact->address1); 196 write_normal_email(ff.output, ff.name, item, mode, mode_MH, &pstfile, save_rtf_body);
198 } 197
199 198 } else if (item->journal && (item->type == PST_TYPE_JOURNAL)) {
200 } else if (item->email && (item->type == PST_TYPE_NOTE || item->type == PST_TYPE_REPORT)) { 199 // deal with journal items
201 if (mode == MODE_SEPERATE) mk_seperate_file(&ff); 200 if (mode == MODE_SEPERATE) mk_seperate_file(&ff);
202 ff.email_count++; 201 ff.email_count++;
203 DEBUG_MAIN(("main: seen an email\n")); 202 DEBUG_MAIN(("main: Processing Journal Entry\n"));
204 write_normal_email(ff.output, ff.name, item, mode, mode_MH, &pstfile, save_rtf_body); 203 if (ff.type != PST_TYPE_JOURNAL) {
205 204 DEBUG_MAIN(("main: I have a journal entry, but the folder isn't a journal folder. Processing anyway\n"));
206 } else if (item->type == PST_TYPE_JOURNAL) { 205 }
207 // deal with journal items 206 fprintf(ff.output, "BEGIN:VJOURNAL\n");
208 if (mode == MODE_SEPERATE) mk_seperate_file(&ff); 207 if (item->email->subject)
209 ff.email_count++; 208 fprintf(ff.output, "SUMMARY:%s\n", pst_rfc2426_escape(item->email->subject->subj));
210 209 if (item->email->body)
211 DEBUG_MAIN(("main: Processing Journal Entry\n")); 210 fprintf(ff.output, "DESCRIPTION:%s\n", pst_rfc2426_escape(item->email->body));
212 if (ff.type != PST_TYPE_JOURNAL) { 211 if (item->journal->start)
213 DEBUG_MAIN(("main: I have a journal entry, but folder isn't specified as a journal type. Processing...\n")); 212 fprintf(ff.output, "DTSTART;VALUE=DATE-TIME:%s\n", pst_rfc2445_datetime_format(item->journal->start));
214 } 213 fprintf(ff.output, "END:VJOURNAL\n\n");
215 214
216 /* if (item->type != PST_TYPE_JOURNAL) { 215 } else if (item->appointment && (item->type == PST_TYPE_APPOINTMENT)) {
217 DEBUG_MAIN(("main: I have an item with journal info, but it's type is \"%s\" \n. Processing...\n", 216 // deal with Calendar appointments
218 item->ascii_type)); 217 if (mode == MODE_SEPERATE) mk_seperate_file(&ff);
219 }*/ 218 ff.email_count++;
220 fprintf(ff.output, "BEGIN:VJOURNAL\n"); 219 DEBUG_MAIN(("main: Processing Appointment Entry\n"));
221 if (item->email->subject) 220 if (ff.type != PST_TYPE_APPOINTMENT) {
222 fprintf(ff.output, "SUMMARY:%s\n", rfc2426_escape(item->email->subject->subj)); 221 DEBUG_MAIN(("main: I have an appointment, but folder isn't specified as an appointment type. Processing...\n"));
223 if (item->email->body) 222 }
224 fprintf(ff.output, "DESCRIPTION:%s\n", rfc2426_escape(item->email->body)); 223 write_appointment(ff.output, item->appointment, item->email, item->create_date, item->modify_date);
225 if (item->journal->start) 224
226 fprintf(ff.output, "DTSTART;VALUE=DATE-TIME:%s\n", rfc2445_datetime_format(item->journal->start)); 225 } else {
227 fprintf(ff.output, "END:VJOURNAL\n\n"); 226 ff.skip_count++;
228 227 DEBUG_MAIN(("main: Unknown item type. %i. Ascii1=\"%s\"\n",
229 } else if (item->type == PST_TYPE_APPOINTMENT) { 228 item->type, item->ascii_type));
230 // deal with Calendar appointments 229 }
231 if (mode == MODE_SEPERATE) mk_seperate_file(&ff); 230 _pst_freeItem(item);
232 ff.email_count++; 231 } else {
233 DEBUG_MAIN(("main: Processing Appointment Entry\n")); 232 ff.skip_count++;
234 if (ff.type != PST_TYPE_APPOINTMENT) { 233 DEBUG_MAIN(("main: A NULL item was seen\n"));
235 DEBUG_MAIN(("main: I have an appointment, but folder isn't specified as an appointment type. Processing...\n")); 234 }
236 } 235 d_ptr = d_ptr->next;
237 write_appointment(ff.output, item->appointment, item->email, item->create_date, item->modify_date); 236 }
238 237 }
239 } else { 238 close_enter_dir(&ff);
240 ff.skip_count++; 239 DEBUG_RET();
241 DEBUG_MAIN(("main: Unknown item type. %i. Ascii1=\"%s\"\n",
242 item->type, item->ascii_type));
243 }
244 _pst_freeItem(item);
245 } else {
246 ff.skip_count++;
247 DEBUG_MAIN(("main: A NULL item was seen\n"));
248 }
249 d_ptr = d_ptr->next;
250 }
251 }
252 close_enter_dir(&ff);
253 DEBUG_RET();
254 } 240 }
255 241
256 242
257 243
258 int main(int argc, char** argv) { 244 int main(int argc, char** argv) {
259 pst_item *item = NULL; 245 pst_item *item = NULL;
260 pst_desc_ll *d_ptr; 246 pst_desc_ll *d_ptr;
261 char * fname = NULL; 247 char * fname = NULL;
262 char *d_log=NULL; 248 char *d_log=NULL;
263 int c,x; 249 int c,x;
264 char *temp = NULL; //temporary char pointer 250 char *temp = NULL; //temporary char pointer
265 prog_name = argv[0]; 251 prog_name = argv[0];
266 252
267 // command-line option handling 253 // command-line option handling
268 while ((c = getopt(argc, argv, "bd:hko:qrMSVwc:"))!= -1) { 254 while ((c = getopt(argc, argv, "bCc:d:hko:qrSMVw"))!= -1) {
269 switch (c) { 255 switch (c) {
270 case 'b': 256 case 'b':
271 save_rtf_body = 0; 257 save_rtf_body = 0;
272 break; 258 break;
273 case 'c': 259 case 'C':
274 if (optarg && optarg[0]=='v') 260 mode = MODE_DECSPEW;
275 contact_mode=CMODE_VCARD; 261 break;
276 else if (optarg && optarg[0]=='l') 262 case 'c':
277 contact_mode=CMODE_LIST; 263 if (optarg && optarg[0]=='v')
278 else { 264 contact_mode=CMODE_VCARD;
279 usage(); 265 else if (optarg && optarg[0]=='l')
280 exit(0); 266 contact_mode=CMODE_LIST;
281 } 267 else {
282 break; 268 usage();
283 case 'd': 269 exit(0);
284 d_log = optarg; 270 }
285 break; 271 break;
286 case 'h': 272 case 'd':
287 usage(); 273 d_log = optarg;
288 exit(0); 274 break;
289 break; 275 case 'h':
290 case 'V': 276 usage();
291 version(); 277 exit(0);
292 exit(0); 278 break;
293 break; 279 case 'V':
294 case 'k': 280 version();
295 mode = MODE_KMAIL; 281 exit(0);
296 break; 282 break;
297 case 'M': 283 case 'k':
298 mode = MODE_SEPERATE; 284 mode = MODE_KMAIL;
299 mode_MH = 1; 285 break;
300 break; 286 case 'M':
301 case 'o': 287 mode = MODE_SEPERATE;
302 output_dir = optarg; 288 mode_MH = 1;
303 break; 289 break;
304 case 'q': 290 case 'o':
305 output_mode = OUTPUT_QUIET; 291 output_dir = optarg;
306 break; 292 break;
307 case 'r': 293 case 'q':
308 mode = MODE_RECURSE; 294 output_mode = OUTPUT_QUIET;
309 break; 295 break;
310 case 'S': 296 case 'r':
311 mode = MODE_SEPERATE; 297 mode = MODE_RECURSE;
312 break; 298 break;
313 case 'w': 299 case 'S':
314 overwrite = 1; 300 mode = MODE_SEPERATE;
315 break; 301 break;
316 default: 302 case 'w':
317 usage(); 303 overwrite = 1;
318 exit(1); 304 break;
319 break; 305 default:
320 } 306 usage();
321 } 307 exit(1);
322 308 break;
323 if (argc > optind) { 309 }
324 fname = argv[optind]; 310 }
325 } else { 311
326 usage(); 312 if (argc > optind) {
327 exit(2); 313 fname = argv[optind];
328 } 314 } else {
329 315 usage();
330 #ifdef DEBUG_ALL 316 exit(2);
331 // force a log file 317 }
332 if (!d_log) d_log = "readpst.log"; 318
333 #endif // defined DEBUG_ALL 319 unicode_init();
334 DEBUG_INIT(d_log); 320
335 DEBUG_REGISTER_CLOSE(); 321 #ifdef DEBUG_ALL
336 DEBUG_ENT("main"); 322 // force a log file
337 323 if (!d_log) d_log = "readpst.log";
338 if (output_mode != OUTPUT_QUIET) printf("Opening PST file and indexes...\n"); 324 #endif // defined DEBUG_ALL
339 325 DEBUG_INIT(d_log);
340 RET_DERROR(pst_open(&pstfile, fname, "r"), 1, ("Error opening File\n")); 326 DEBUG_REGISTER_CLOSE();
341 RET_DERROR(pst_load_index(&pstfile), 2, ("Index Error\n")); 327 DEBUG_ENT("main");
342 328
343 pst_load_extended_attributes(&pstfile); 329 if (mode == MODE_DECSPEW) {
344 330 FILE *fp;
345 if (chdir(output_dir)) { 331 char buf[1024];
346 x = errno; 332 int l=0;
347 pst_close(&pstfile); 333 if (NULL == (fp = fopen(fname, "rb"))) {
348 DEBUG_RET(); 334 fprintf(stderr, "Couldn't open file %s\n", fname );
349 DIE(("main: Cannot change to output dir %s: %s\n", output_dir, strerror(x))); 335 return 1;
350 } 336 }
351 337
352 if (output_mode != OUTPUT_QUIET) printf("About to start processing first record...\n"); 338 while (0 != ( l = fread( buf, 1, 1024, fp))) {
353 339 if (0 != _pst_decrypt( buf, l, PST_COMP_ENCRYPT))
354 d_ptr = pstfile.d_head; // first record is main record 340 fprintf(stderr, "_pst_decrypt() failed (I'll try to continue)\n");
355 item = (pst_item*)_pst_parse_item(&pstfile, d_ptr); 341
356 if (!item || !item->message_store) { 342 if (l != fwrite( buf, 1, l, stdout)) {
357 DEBUG_RET(); 343 fprintf(stderr, "Couldn't output to stdout?\n");
358 DIE(("main: Could not get root record\n")); 344 return 1;
359 } 345 }
360 346 }
361 // default the file_as to the same as the main filename if it doesn't exist 347 return 0;
362 if (!item->file_as) { 348 }
363 if (!(temp = strrchr(fname, '/'))) 349
364 if (!(temp = strrchr(fname, '\\'))) 350 if (output_mode != OUTPUT_QUIET) printf("Opening PST file and indexes...\n");
365 temp = fname; 351
366 else 352 RET_DERROR(pst_open(&pstfile, fname, "r"), 1, ("Error opening File\n"));
367 temp++; // get past the "\\" 353 RET_DERROR(pst_load_index(&pstfile), 2, ("Index Error\n"));
368 else 354
369 temp++; // get past the "/" 355 pst_load_extended_attributes(&pstfile);
370 item->file_as = (char*)xmalloc(strlen(temp)+1); 356
371 strcpy(item->file_as, temp); 357 if (chdir(output_dir)) {
372 DEBUG_MAIN(("file_as was blank, so am using %s\n", item->file_as)); 358 x = errno;
373 } 359 pst_close(&pstfile);
374 DEBUG_MAIN(("main: Root Folder Name: %s\n", item->file_as)); 360 DEBUG_RET();
375 361 DIE(("main: Cannot change to output dir %s: %s\n", output_dir, strerror(x)));
376 d_ptr = pst_getTopOfFolders(&pstfile, item); 362 }
377 if (!d_ptr) { 363
378 DEBUG_RET(); 364 if (output_mode != OUTPUT_QUIET) printf("About to start processing first record...\n");
379 DIE(("Top of folders record not found. Cannot continue\n")); 365
380 } 366 d_ptr = pstfile.d_head; // first record is main record
381 367 item = _pst_parse_item(&pstfile, d_ptr);
382 process(item, d_ptr->child); // do the children of TOPF 368 if (!item || !item->message_store) {
383 _pst_freeItem(item); 369 DEBUG_RET();
384 pst_close(&pstfile); 370 DIE(("main: Could not get root record\n"));
385 371 }
386 DEBUG_RET(); 372
387 return 0; 373 // default the file_as to the same as the main filename if it doesn't exist
374 if (!item->file_as) {
375 if (!(temp = strrchr(fname, '/')))
376 if (!(temp = strrchr(fname, '\\')))
377 temp = fname;
378 else
379 temp++; // get past the "\\"
380 else
381 temp++; // get past the "/"
382 item->file_as = (char*)xmalloc(strlen(temp)+1);
383 strcpy(item->file_as, temp);
384 DEBUG_MAIN(("file_as was blank, so am using %s\n", item->file_as));
385 }
386 DEBUG_MAIN(("main: Root Folder Name: %s\n", item->file_as));
387
388 d_ptr = pst_getTopOfFolders(&pstfile, item);
389 if (!d_ptr) {
390 DEBUG_RET();
391 DIE(("Top of folders record not found. Cannot continue\n"));
392 }
393
394 process(item, d_ptr->child); // do the children of TOPF
395 _pst_freeItem(item);
396 pst_close(&pstfile);
397
398 DEBUG_RET();
399 return 0;
388 } 400 }
389 401
390 402
391 void write_email_body(FILE *f, char *body) { 403 void write_email_body(FILE *f, char *body) {
392 char *n = body; 404 char *n = body;
393 // DEBUG_MAIN(("write_email_body(): \"%s\"\n", body)); 405 // DEBUG_MAIN(("write_email_body(): \"%s\"\n", body));
394 DEBUG_ENT("write_email_body"); 406 DEBUG_ENT("write_email_body");
395 while (n) { 407 while (n) {
396 if (strncmp(body, "From ", 5) == 0) 408 if (strncmp(body, "From ", 5) == 0)
397 fprintf(f, ">"); 409 fprintf(f, ">");
398 if ((n = strchr(body, '\n'))) { 410 if ((n = strchr(body, '\n'))) {
399 n++; 411 n++;
400 fwrite(body, n-body, 1, f); //write just a line 412 fwrite(body, n-body, 1, f); //write just a line
401 413
402 body = n; 414 body = n;
403 } 415 }
404 } 416 }
405 fwrite(body, strlen(body), 1, f); 417 fwrite(body, strlen(body), 1, f);
406 DEBUG_RET(); 418 DEBUG_RET();
407 } 419 }
408 420
409 421
410 char *removeCR (char *c) { 422 char *removeCR (char *c) {
411 // converts /r/n to /n 423 // converts /r/n to /n
412 char *a, *b; 424 char *a, *b;
413 DEBUG_ENT("removeCR"); 425 DEBUG_ENT("removeCR");
414 a = b = c; 426 a = b = c;
415 while (*a != '\0') { 427 while (*a != '\0') {
416 *b = *a; 428 *b = *a;
417 if (*a != '\r') 429 if (*a != '\r')
418 b++; 430 b++;
419 a++; 431 a++;
420 } 432 }
421 *b = '\0'; 433 *b = '\0';
422 DEBUG_RET(); 434 DEBUG_RET();
423 return c; 435 return c;
424 } 436 }
425 437
426 438
427 int usage() { 439 int usage() {
428 DEBUG_ENT("usage"); 440 DEBUG_ENT("usage");
429 version(); 441 version();
430 printf("Usage: %s [OPTIONS] {PST FILENAME}\n", prog_name); 442 printf("Usage: %s [OPTIONS] {PST FILENAME}\n", prog_name);
431 printf("OPTIONS:\n"); 443 printf("OPTIONS:\n");
432 printf("\t-b\t- Don't save RTF-Body attachments\n"); 444 printf("\t-b\t- Don't save RTF-Body attachments\n");
433 printf("\t-c[v|l]\t- Set the Contact output mode. -cv = VCard, -cl = EMail list\n"); 445 printf("\t-c[v|l]\t- Set the Contact output mode. -cv = VCard, -cl = EMail list\n");
434 printf("\t-d <filename> \t- Debug to file. This is a binary log. Use readlog to print it\n"); 446 printf("\t-d <filename> \t- Debug to file. This is a binary log. Use readlog to print it\n");
435 printf("\t-h\t- Help. This screen\n"); 447 printf("\t-h\t- Help. This screen\n");
436 printf("\t-k\t- KMail. Output in kmail format\n"); 448 printf("\t-k\t- KMail. Output in kmail format\n");
437 printf("\t-M\t- MH. Write emails in the MH format\n"); 449 printf("\t-M\t- MH. Write emails in the MH format\n");
438 printf("\t-o <dirname>\t- Output Dir. Directory to write files to. CWD is changed *after* opening pst file\n"); 450 printf("\t-o <dirname>\t- Output Dir. Directory to write files to. CWD is changed *after* opening pst file\n");
439 printf("\t-q\t- Quiet. Only print error messages\n"); 451 printf("\t-q\t- Quiet. Only print error messages\n");
440 printf("\t-r\t- Recursive. Output in a recursive format\n"); 452 printf("\t-r\t- Recursive. Output in a recursive format\n");
441 printf("\t-S\t- Seperate. Write emails in the seperate format\n"); 453 printf("\t-S\t- Seperate. Write emails in the seperate format\n");
442 printf("\t-V\t- Version. Display program version\n"); 454 printf("\t-V\t- Version. Display program version\n");
443 printf("\t-w\t- Overwrite any output mbox files\n"); 455 printf("\t-w\t- Overwrite any output mbox files\n");
444 DEBUG_RET(); 456 printf("\t-C\t- Decrypt the entire file and output on stdout (not typically useful)\n");
445 return 0; 457 DEBUG_RET();
458 return 0;
446 } 459 }
447 460
448 461
449 int version() { 462 int version() {
450 DEBUG_ENT("version"); 463 DEBUG_ENT("version");
451 printf("ReadPST v%s\n", VERSION); 464 printf("ReadPST v%s\n", VERSION);
452 #if BYTE_ORDER == BIG_ENDIAN 465 #if BYTE_ORDER == BIG_ENDIAN
453 printf("Big Endian implementation being used.\n"); 466 printf("Big Endian implementation being used.\n");
454 #elif BYTE_ORDER == LITTLE_ENDIAN 467 #elif BYTE_ORDER == LITTLE_ENDIAN
455 printf("Little Endian implementation being used.\n"); 468 printf("Little Endian implementation being used.\n");
456 #else 469 #else
457 # error "Byte order not supported by this library" 470 # error "Byte order not supported by this library"
458 #endif 471 #endif
459 #ifdef __GNUC__ 472 #ifdef __GNUC__
460 printf("GCC %d.%d : %s %s\n", __GNUC__, __GNUC_MINOR__, __DATE__, __TIME__); 473 printf("GCC %d.%d : %s %s\n", __GNUC__, __GNUC_MINOR__, __DATE__, __TIME__);
461 #endif 474 #endif
462 DEBUG_RET(); 475 DEBUG_RET();
463 return 0; 476 return 0;
464 } 477 }
465 478
466 479
467 char *mk_kmail_dir(char *fname) { 480 char *mk_kmail_dir(char *fname) {
468 //change to that directory 481 //change to that directory
469 //make a directory based on OUTPUT_KMAIL_DIR_TEMPLATE 482 //make a directory based on OUTPUT_KMAIL_DIR_TEMPLATE
470 //allocate space for OUTPUT_TEMPLATE and form a char* with fname 483 //allocate space for OUTPUT_TEMPLATE and form a char* with fname
471 //return that value 484 //return that value
472 char *dir, *out_name, *index; 485 char *dir, *out_name, *index;
473 int x; 486 int x;
474 DEBUG_ENT("mk_kmail_dir"); 487 DEBUG_ENT("mk_kmail_dir");
475 if (kmail_chdir && chdir(kmail_chdir)) { 488 if (kmail_chdir && chdir(kmail_chdir)) {
476 x = errno; 489 x = errno;
477 DIE(("mk_kmail_dir: Cannot change to directory %s: %s\n", kmail_chdir, strerror(x))); 490 DIE(("mk_kmail_dir: Cannot change to directory %s: %s\n", kmail_chdir, strerror(x)));
478 } 491 }
479 dir = malloc(strlen(fname)+strlen(OUTPUT_KMAIL_DIR_TEMPLATE)+1); 492 dir = malloc(strlen(fname)+strlen(OUTPUT_KMAIL_DIR_TEMPLATE)+1);
480 sprintf(dir, OUTPUT_KMAIL_DIR_TEMPLATE, fname); 493 sprintf(dir, OUTPUT_KMAIL_DIR_TEMPLATE, fname);
481 check_filename(dir); 494 check_filename(dir);
482 if (D_MKDIR(dir)) { 495 if (D_MKDIR(dir)) {
483 //error occured 496 //error occured
484 if (errno != EEXIST) { 497 if (errno != EEXIST) {
485 x = errno; 498 x = errno;
486 DIE(("mk_kmail_dir: Cannot create directory %s: %s\n", dir, strerror(x))); 499 DIE(("mk_kmail_dir: Cannot create directory %s: %s\n", dir, strerror(x)));
487 } 500 }
488 } 501 }
489 kmail_chdir = realloc(kmail_chdir, strlen(dir)+1); 502 kmail_chdir = realloc(kmail_chdir, strlen(dir)+1);
490 strcpy(kmail_chdir, dir); 503 strcpy(kmail_chdir, dir);
491 free (dir); 504 free (dir);
492 505
493 //we should remove any existing indexes created by KMail, cause they might be different now 506 //we should remove any existing indexes created by KMail, cause they might be different now
494 index = malloc(strlen(fname)+strlen(KMAIL_INDEX)+1); 507 index = malloc(strlen(fname)+strlen(KMAIL_INDEX)+1);
495 sprintf(index, KMAIL_INDEX, fname); 508 sprintf(index, KMAIL_INDEX, fname);
496 unlink(index); 509 unlink(index);
497 free(index); 510 free(index);
498 511
499 out_name = malloc(strlen(fname)+strlen(OUTPUT_TEMPLATE)+1); 512 out_name = malloc(strlen(fname)+strlen(OUTPUT_TEMPLATE)+1);
500 sprintf(out_name, OUTPUT_TEMPLATE, fname); 513 sprintf(out_name, OUTPUT_TEMPLATE, fname);
501 DEBUG_RET(); 514 DEBUG_RET();
502 return out_name; 515 return out_name;
503 } 516 }
504 517
505 518
506 int close_kmail_dir() { 519 int close_kmail_dir() {
507 // change .. 520 // change ..
508 int x; 521 int x;
509 DEBUG_ENT("close_kmail_dir"); 522 DEBUG_ENT("close_kmail_dir");
510 if (kmail_chdir) { //only free kmail_chdir if not NULL. do not change directory 523 if (kmail_chdir) { //only free kmail_chdir if not NULL. do not change directory
511 free(kmail_chdir); 524 free(kmail_chdir);
512 kmail_chdir = NULL; 525 kmail_chdir = NULL;
513 } else { 526 } else {
514 if (chdir("..")) { 527 if (chdir("..")) {
515 x = errno; 528 x = errno;
516 DIE(("close_kmail_dir: Cannot move up dir (..): %s\n", strerror(x))); 529 DIE(("close_kmail_dir: Cannot move up dir (..): %s\n", strerror(x)));
517 } 530 }
518 } 531 }
519 DEBUG_RET(); 532 DEBUG_RET();
520 return 0; 533 return 0;
521 } 534 }
522 535
523 536
524 // this will create a directory by that name, then make an mbox file inside 537 // this will create a directory by that name, then make an mbox file inside
525 // that dir. any subsequent dirs will be created by name, and they will 538 // that dir. any subsequent dirs will be created by name, and they will
526 // contain mbox files 539 // contain mbox files
527 char *mk_recurse_dir(char *dir) { 540 char *mk_recurse_dir(char *dir) {
528 int x; 541 int x;
529 char *out_name; 542 char *out_name;
530 DEBUG_ENT("mk_recurse_dir"); 543 DEBUG_ENT("mk_recurse_dir");
531 check_filename(dir); 544 check_filename(dir);
532 if (D_MKDIR (dir)) { 545 if (D_MKDIR (dir)) {
533 if (errno != EEXIST) { // not an error because it exists 546 if (errno != EEXIST) { // not an error because it exists
534 x = errno; 547 x = errno;
535 DIE(("mk_recurse_dir: Cannot create directory %s: %s\n", dir, strerror(x))); 548 DIE(("mk_recurse_dir: Cannot create directory %s: %s\n", dir, strerror(x)));
536 } 549 }
537 } 550 }
538 if (chdir (dir)) { 551 if (chdir (dir)) {
539 x = errno; 552 x = errno;
540 DIE(("mk_recurse_dir: Cannot change to directory %s: %s\n", dir, strerror(x))); 553 DIE(("mk_recurse_dir: Cannot change to directory %s: %s\n", dir, strerror(x)));
541 } 554 }
542 out_name = malloc(strlen("mbox")+1); 555 out_name = malloc(strlen("mbox")+1);
543 strcpy(out_name, "mbox"); 556 strcpy(out_name, "mbox");
544 DEBUG_RET(); 557 DEBUG_RET();
545 return out_name; 558 return out_name;
546 } 559 }
547 560
548 561
549 int close_recurse_dir() { 562 int close_recurse_dir() {
550 int x; 563 int x;
551 DEBUG_ENT("close_recurse_dir"); 564 DEBUG_ENT("close_recurse_dir");
552 if (chdir("..")) { 565 if (chdir("..")) {
553 x = errno; 566 x = errno;
554 DIE(("close_recurse_dir: Cannot go up dir (..): %s\n", strerror(x))); 567 DIE(("close_recurse_dir: Cannot go up dir (..): %s\n", strerror(x)));
555 } 568 }
556 DEBUG_RET(); 569 DEBUG_RET();
557 return 0; 570 return 0;
558 } 571 }
559 572
560 573
561 char *mk_seperate_dir(char *dir) { 574 char *mk_seperate_dir(char *dir) {
562 DEBUG_ENT("mk_seperate_dir"); 575 DEBUG_ENT("mk_seperate_dir");
563 576
564 size_t dirsize = strlen(dir) + 10; 577 size_t dirsize = strlen(dir) + 10;
565 char dir_name[dirsize]; 578 char dir_name[dirsize];
566 int x = 0, y = 0; 579 int x = 0, y = 0;
567 580
568 do { 581 do {
569 if (y == 0) 582 if (y == 0)
570 snprintf(dir_name, dirsize, "%s", dir); 583 snprintf(dir_name, dirsize, "%s", dir);
571 else 584 else
572 snprintf(dir_name, dirsize, "%s" SEP_MAIL_FILE_TEMPLATE, dir, y); // enough for 9 digits allocated above 585 snprintf(dir_name, dirsize, "%s" SEP_MAIL_FILE_TEMPLATE, dir, y); // enough for 9 digits allocated above
573 586
574 check_filename(dir_name); 587 check_filename(dir_name);
575 DEBUG_MAIN(("about to try creating %s\n", dir_name)); 588 DEBUG_MAIN(("about to try creating %s\n", dir_name));
576 if (D_MKDIR(dir_name)) { 589 if (D_MKDIR(dir_name)) {
577 if (errno != EEXIST) { // if there is an error, and it doesn't already exist 590 if (errno != EEXIST) { // if there is an error, and it doesn't already exist
578 x = errno; 591 x = errno;
579 DIE(("mk_seperate_dir: Cannot create directory %s: %s\n", dir, strerror(x))); 592 DIE(("mk_seperate_dir: Cannot create directory %s: %s\n", dir, strerror(x)));
580 } 593 }
581 } else { 594 } else {
582 break; 595 break;
583 } 596 }
584 y++; 597 y++;
585 } while (overwrite == 0); 598 } while (overwrite == 0);
586 599
587 if (chdir(dir_name)) { 600 if (chdir(dir_name)) {
588 x = errno; 601 x = errno;
589 DIE(("mk_recurse_dir: Cannot change to directory %s: %s\n", dir, strerror(x))); 602 DIE(("mk_recurse_dir: Cannot change to directory %s: %s\n", dir, strerror(x)));
590 } 603 }
591 604
592 if (overwrite) { 605 if (overwrite) {
593 // we should probably delete all files from this directory 606 // we should probably delete all files from this directory
594 #if !defined(WIN32) && !defined(__CYGWIN__) 607 #if !defined(WIN32) && !defined(__CYGWIN__)
595 DIR * sdir = NULL; 608 DIR * sdir = NULL;
596 struct dirent *dirent = NULL; 609 struct dirent *dirent = NULL;
597 struct stat filestat; 610 struct stat filestat;
598 if (!(sdir = opendir("./"))) { 611 if (!(sdir = opendir("./"))) {
599 WARN(("mk_seperate_dir: Cannot open dir \"%s\" for deletion of old contents\n", "./")); 612 WARN(("mk_seperate_dir: Cannot open dir \"%s\" for deletion of old contents\n", "./"));
600 } else { 613 } else {
601 while ((dirent = readdir(sdir))) { 614 while ((dirent = readdir(sdir))) {
602 if (lstat(dirent->d_name, &filestat) != -1) 615 if (lstat(dirent->d_name, &filestat) != -1)
603 if (S_ISREG(filestat.st_mode)) { 616 if (S_ISREG(filestat.st_mode)) {
604 if (unlink(dirent->d_name)) { 617 if (unlink(dirent->d_name)) {
605 y = errno; 618 y = errno;
606 DIE(("mk_seperate_dir: unlink returned error on file %s: %s\n", dirent->d_name, strerror(y))); 619 DIE(("mk_seperate_dir: unlink returned error on file %s: %s\n", dirent->d_name, strerror(y)));
607 } 620 }
608 } 621 }
609 } 622 }
610 } 623 }
611 #endif 624 #endif
612 } 625 }
613 626
614 // we don't return a filename here cause it isn't necessary. 627 // we don't return a filename here cause it isn't necessary.
615 DEBUG_RET(); 628 DEBUG_RET();
616 return NULL; 629 return NULL;
617 } 630 }
618 631
619 632
620 int close_seperate_dir() { 633 int close_seperate_dir() {
621 int x; 634 int x;
622 DEBUG_ENT("close_seperate_dir"); 635 DEBUG_ENT("close_seperate_dir");
623 if (chdir("..")) { 636 if (chdir("..")) {
624 x = errno; 637 x = errno;
625 DIE(("close_seperate_dir: Cannot go up dir (..): %s\n", strerror(x))); 638 DIE(("close_seperate_dir: Cannot go up dir (..): %s\n", strerror(x)));
626 } 639 }
627 DEBUG_RET(); 640 DEBUG_RET();
628 return 0; 641 return 0;
629 } 642 }
630 643
631 644
632 int mk_seperate_file(struct file_ll *f) { 645 int mk_seperate_file(struct file_ll *f) {
633 const int name_offset = 1; 646 const int name_offset = 1;
634 DEBUG_ENT("mk_seperate_file"); 647 DEBUG_ENT("mk_seperate_file");
635 DEBUG_MAIN(("opening next file to save email\n")); 648 DEBUG_MAIN(("opening next file to save email\n"));
636 if (f->email_count > 999999999) { // bigger than nine 9's 649 if (f->email_count > 999999999) { // bigger than nine 9's
637 DIE(("mk_seperate_file: The number of emails in this folder has become too high to handle")); 650 DIE(("mk_seperate_file: The number of emails in this folder has become too high to handle"));
638 } 651 }
639 sprintf(f->name, SEP_MAIL_FILE_TEMPLATE, f->email_count + name_offset); 652 sprintf(f->name, SEP_MAIL_FILE_TEMPLATE, f->email_count + name_offset);
640 if (f->output) fclose(f->output); 653 if (f->output) fclose(f->output);
641 f->output = NULL; 654 f->output = NULL;
642 check_filename(f->name); 655 check_filename(f->name);
643 if (!(f->output = fopen(f->name, "w"))) { 656 if (!(f->output = fopen(f->name, "w"))) {
644 DIE(("mk_seperate_file: Cannot open file to save email \"%s\"\n", f->name)); 657 DIE(("mk_seperate_file: Cannot open file to save email \"%s\"\n", f->name));
645 } 658 }
646 DEBUG_RET(); 659 DEBUG_RET();
647 return 0; 660 return 0;
648 } 661 }
649 662
650 663
651 char *my_stristr(char *haystack, char *needle) { 664 char *my_stristr(char *haystack, char *needle) {
652 // my_stristr varies from strstr in that its searches are case-insensitive 665 // my_stristr varies from strstr in that its searches are case-insensitive
653 char *x=haystack, *y=needle, *z = NULL; 666 char *x=haystack, *y=needle, *z = NULL;
654 DEBUG_ENT("my_stristr"); 667 DEBUG_ENT("my_stristr");
655 if (!haystack || !needle) 668 if (!haystack || !needle)
656 return NULL; 669 return NULL;
657 while (*y != '\0' && *x != '\0') { 670 while (*y != '\0' && *x != '\0') {
658 if (tolower(*y) == tolower(*x)) { 671 if (tolower(*y) == tolower(*x)) {
659 // move y on one 672 // move y on one
660 y++; 673 y++;
661 if (!z) { 674 if (!z) {
662 z = x; // store first position in haystack where a match is made 675 z = x; // store first position in haystack where a match is made
663 } 676 }
664 } else { 677 } else {
665 y = needle; // reset y to the beginning of the needle 678 y = needle; // reset y to the beginning of the needle
666 z = NULL; // reset the haystack storage point 679 z = NULL; // reset the haystack storage point
667 } 680 }
668 x++; // advance the search in the haystack 681 x++; // advance the search in the haystack
669 } 682 }
670 DEBUG_RET(); 683 DEBUG_RET();
671 return z; 684 return z;
672 } 685 }
673 686
674 687
675 void check_filename(char *fname) { 688 void check_filename(char *fname) {
676 char *t = fname; 689 char *t = fname;
677 DEBUG_ENT("check_filename"); 690 DEBUG_ENT("check_filename");
678 if (!t) { 691 if (!t) {
679 DEBUG_RET(); 692 DEBUG_RET();
680 return fname; 693 }
681 } 694 while ((t = strpbrk(t, "/\\:"))) {
682 while ((t = strpbrk(t, "/\\:"))) { 695 // while there are characters in the second string that we don't want
683 // while there are characters in the second string that we don't want 696 *t = '_'; //replace them with an underscore
684 *t = '_'; //replace them with an underscore 697 }
685 } 698 DEBUG_RET();
686 DEBUG_RET();
687 return fname;
688 }
689
690
691 char *rfc2426_escape(char *str) {
692 static char* buf = NULL;
693 char *ret, *a, *b;
694 int x = 0, y, z;
695 DEBUG_ENT("rfc2426_escape");
696 if (!str)
697 ret = str;
698 else {
699
700 // calculate space required to escape all the following characters
701 y = chr_count(str, ',')
702 + chr_count(str, '\\')
703 + chr_count(str, ';')
704 + chr_count(str, '\n');
705 z = chr_count(str, '\r');
706 if (y == 0 && z == 0)
707 // there isn't any extra space required
708 ret = str;
709 else {
710 x = strlen(str) + y - z + 1; // don't forget room for the NUL
711 buf = (char*) realloc(buf, x);
712 a = str;
713 b = buf;
714 while (*a != '\0') {
715 switch (*a) {
716 case ',' :
717 case '\\':
718 case ';' :
719 *(b++) = '\\';
720 *b = *a;
721 break;
722 case '\n': // newlines are encoded as "\n"
723 *(b++) = '\\';
724 *b = 'n';
725 break;
726 case '\r': // skip cr
727 b--;
728 break;
729 default:
730 *b=*a;
731 }
732 b++;
733 a++;
734 }
735 *b = '\0'; // NUL-terminate the string (buf)
736 ret = buf;
737 }
738 }
739 DEBUG_RET();
740 return ret;
741 }
742
743
744 int chr_count(char *str, char x) {
745 int r = 0;
746 while (*str != '\0') {
747 if (*str == x)
748 r++;
749 str++;
750 }
751 return r;
752 }
753
754
755 char *rfc2425_datetime_format(FILETIME *ft) {
756 static char* buffer = NULL;
757 struct tm *stm = NULL;
758 DEBUG_ENT("rfc2425_datetime_format");
759 if (!buffer) buffer = malloc(30); // should be enough for the date as defined below
760 stm = fileTimeToStructTM(ft);
761 if (strftime(buffer, 30, "%Y-%m-%dT%H:%M:%SZ", stm)==0) {
762 DEBUG_INFO(("Problem occured formatting date\n"));
763 }
764 DEBUG_RET();
765 return buffer;
766 }
767
768
769 char *rfc2445_datetime_format(FILETIME *ft) {
770 static char* buffer = NULL;
771 struct tm *stm = NULL;
772 DEBUG_ENT("rfc2445_datetime_format");
773 if (!buffer) buffer = malloc(30); // should be enough for the date as defined below
774 stm = fileTimeToStructTM(ft);
775 if (strftime(buffer, 30, "%Y%m%dT%H%M%SZ", stm)==0) {
776 DEBUG_INFO(("Problem occured formatting date\n"));
777 }
778 DEBUG_RET();
779 return buffer;
780 } 699 }
781 700
782 701
783 // The sole purpose of this function is to bypass the pseudo-header prologue 702 // The sole purpose of this function is to bypass the pseudo-header prologue
784 // that Microsoft Outlook inserts at the beginning of the internet email 703 // that Microsoft Outlook inserts at the beginning of the internet email
785 // headers for emails stored in their "Personal Folders" files. 704 // headers for emails stored in their "Personal Folders" files.
786 char *skip_header_prologue(char *headers) { 705 char *skip_header_prologue(char *headers) {
787 const char *bad = "Microsoft Mail Internet Headers"; 706 const char *bad = "Microsoft Mail Internet Headers";
788 if ( strncmp(headers, bad, strlen(bad)) == 0 ) { 707 if ( strncmp(headers, bad, strlen(bad)) == 0 ) {
789 // Found the offensive header prologue 708 // Found the offensive header prologue
790 char *pc = strchr(headers, '\n'); 709 char *pc = strchr(headers, '\n');
791 return pc + 1; 710 return pc + 1;
792 } 711 }
793 return headers; 712 return headers;
794 } 713 }
795 714
796 715
797 void write_separate_attachment(char f_name[], pst_item_attach* current_attach, int attach_num, pst_file* pst) 716 void write_separate_attachment(char f_name[], pst_item_attach* current_attach, int attach_num, pst_file* pst)
798 { 717 {
799 DEBUG_ENT("write_separate_attachment"); 718 DEBUG_ENT("write_separate_attachment");
800 FILE *fp = NULL; 719 FILE *fp = NULL;
801 int x = 0; 720 int x = 0;
802 char *temp = NULL; 721 char *temp = NULL;
803 722
804 // If there is a long filename (filename2) use that, otherwise 723 // If there is a long filename (filename2) use that, otherwise
805 // use the 8.3 filename (filename1) 724 // use the 8.3 filename (filename1)
806 char *attach_filename = (current_attach->filename2) ? current_attach->filename2 725 char *attach_filename = (current_attach->filename2) ? current_attach->filename2
807 : current_attach->filename1; 726 : current_attach->filename1;
808 727
809 check_filename(f_name); 728 check_filename(f_name);
810 if (!attach_filename) { 729 if (!attach_filename) {
811 // generate our own (dummy) filename for the attachement 730 // generate our own (dummy) filename for the attachement
812 temp = xmalloc(strlen(f_name)+15); 731 temp = xmalloc(strlen(f_name)+15);
813 sprintf(temp, "%s-attach%i", f_name, attach_num); 732 sprintf(temp, "%s-attach%i", f_name, attach_num);
814 } else { 733 } else {
815 // have an attachment name, make sure it's unique 734 // have an attachment name, make sure it's unique
816 temp = xmalloc(strlen(f_name)+strlen(attach_filename)+15); 735 temp = xmalloc(strlen(f_name)+strlen(attach_filename)+15);
817 do { 736 do {
818 if (fp) fclose(fp); 737 if (fp) fclose(fp);
819 if (x == 0) 738 if (x == 0)
820 sprintf(temp, "%s-%s", f_name, attach_filename); 739 sprintf(temp, "%s-%s", f_name, attach_filename);
821 else 740 else
822 sprintf(temp, "%s-%s-%i", f_name, attach_filename, x); 741 sprintf(temp, "%s-%s-%i", f_name, attach_filename, x);
823 } while ((fp = fopen(temp, "r")) && ++x < 99999999); 742 } while ((fp = fopen(temp, "r")) && ++x < 99999999);
824 if (x > 99999999) { 743 if (x > 99999999) {
825 DIE(("error finding attachment name. exhausted possibilities to %s\n", temp)); 744 DIE(("error finding attachment name. exhausted possibilities to %s\n", temp));
826 } 745 }
827 } 746 }
828 DEBUG_EMAIL(("Saving attachment to %s\n", temp)); 747 DEBUG_EMAIL(("Saving attachment to %s\n", temp));
829 if (!(fp = fopen(temp, "w"))) { 748 if (!(fp = fopen(temp, "w"))) {
830 WARN(("write_separate_attachment: Cannot open attachment save file \"%s\"\n", temp)); 749 WARN(("write_separate_attachment: Cannot open attachment save file \"%s\"\n", temp));
831 } else { 750 } else {
832 if (current_attach->data) 751 if (current_attach->data)
833 fwrite(current_attach->data, 1, current_attach->size, fp); 752 fwrite(current_attach->data, 1, current_attach->size, fp);
834 else { 753 else {
835 pst_attach_to_file(pst, current_attach, fp); 754 pst_attach_to_file(pst, current_attach, fp);
836 } 755 }
837 fclose(fp); 756 fclose(fp);
838 } 757 }
839 if (temp) free(temp); 758 if (temp) free(temp);
840 DEBUG_RET(); 759 DEBUG_RET();
841 } 760 }
842 761
843 762
844 void write_inline_attachment(FILE* f_output, pst_item_attach* current_attach, char boundary[], pst_file* pst) 763 void write_inline_attachment(FILE* f_output, pst_item_attach* current_attach, char boundary[], pst_file* pst)
845 { 764 {
846 DEBUG_ENT("write_inline_attachment"); 765 DEBUG_ENT("write_inline_attachment");
847 char *enc; // base64 encoded attachment 766 char *enc; // base64 encoded attachment
848 DEBUG_EMAIL(("Attachment Size is %i\n", current_attach->size)); 767 DEBUG_EMAIL(("Attachment Size is %i\n", current_attach->size));
849 DEBUG_EMAIL(("Attachment Pointer is %p\n", current_attach->data)); 768 DEBUG_EMAIL(("Attachment Pointer is %p\n", current_attach->data));
850 if (current_attach->data) { 769 if (current_attach->data) {
851 enc = base64_encode (current_attach->data, current_attach->size); 770 enc = base64_encode (current_attach->data, current_attach->size);
852 if (!enc) { 771 if (!enc) {
853 DEBUG_EMAIL(("ERROR base64_encode returned NULL. Must have failed\n")); 772 DEBUG_EMAIL(("ERROR base64_encode returned NULL. Must have failed\n"));
854 return; 773 return;
855 } 774 }
856 } 775 }
857 if (boundary) { 776 if (boundary) {
858 char *attach_filename; 777 char *attach_filename;
859 fprintf(f_output, "\n--%s\n", boundary); 778 fprintf(f_output, "\n--%s\n", boundary);
860 if (!current_attach->mimetype) { 779 if (!current_attach->mimetype) {
861 fprintf(f_output, "Content-type: %s\n", MIME_TYPE_DEFAULT); 780 fprintf(f_output, "Content-type: %s\n", MIME_TYPE_DEFAULT);
862 } else { 781 } else {
863 fprintf(f_output, "Content-type: %s\n", current_attach->mimetype); 782 fprintf(f_output, "Content-type: %s\n", current_attach->mimetype);
864 } 783 }
865 fprintf(f_output, "Content-transfer-encoding: base64\n"); 784 fprintf(f_output, "Content-transfer-encoding: base64\n");
866 // If there is a long filename (filename2) use that, otherwise 785 // If there is a long filename (filename2) use that, otherwise
867 // use the 8.3 filename (filename1) 786 // use the 8.3 filename (filename1)
868 if (current_attach->filename2) { 787 if (current_attach->filename2) {
869 attach_filename = current_attach->filename2; 788 attach_filename = current_attach->filename2;
870 } else { 789 } else {
871 attach_filename = current_attach->filename1; 790 attach_filename = current_attach->filename1;
872 } 791 }
873 if (!attach_filename) { 792 if (!attach_filename) {
874 fprintf(f_output, "Content-Disposition: inline\n\n"); 793 fprintf(f_output, "Content-Disposition: inline\n\n");
875 } else { 794 } else {
876 fprintf(f_output, "Content-Disposition: attachment; filename=\"%s\"\n\n", attach_filename); 795 fprintf(f_output, "Content-Disposition: attachment; filename=\"%s\"\n\n", attach_filename);
877 } 796 }
878 } 797 }
879 if (current_attach->data) { 798 if (current_attach->data) {
880 fwrite(enc, 1, strlen(enc), f_output); 799 fwrite(enc, 1, strlen(enc), f_output);
881 DEBUG_EMAIL(("Attachment Size after encoding is %i\n", strlen(enc))); 800 DEBUG_EMAIL(("Attachment Size after encoding is %i\n", strlen(enc)));
882 free(enc); // caught by valgrind 801 free(enc); // caught by valgrind
883 } else { 802 } else {
884 pst_attach_to_file_base64(pst, current_attach, f_output); 803 pst_attach_to_file_base64(pst, current_attach, f_output);
885 } 804 }
886 fprintf(f_output, "\n\n"); 805 fprintf(f_output, "\n\n");
887 DEBUG_RET(); 806 DEBUG_RET();
888 } 807 }
889 808
890 809
891 void write_normal_email(FILE* f_output, char f_name[], pst_item* item, int mode, int mode_MH, pst_file* pst, int save_rtf) 810 void write_normal_email(FILE* f_output, char f_name[], pst_item* item, int mode, int mode_MH, pst_file* pst, int save_rtf)
892 { 811 {
893 DEBUG_ENT("write_normal_email"); 812 DEBUG_ENT("write_normal_email");
894 char *boundary = NULL; // the boundary marker between multipart sections 813 char *boundary = NULL; // the boundary marker between multipart sections
895 int boundary_created = 0; // we have not (yet) created a new boundary 814 int boundary_created = 0; // we have not (yet) created a new boundary
896 char *temp = NULL; 815 char *temp = NULL;
897 int attach_num, base64_body = 0; 816 int attach_num, base64_body = 0;
898 time_t em_time; 817 time_t em_time;
899 char *c_time; 818 char *c_time;
900 pst_item_attach* current_attach; 819 pst_item_attach* current_attach;
901 820
902 // convert the sent date if it exists, or set it to a fixed date 821 // convert the sent date if it exists, or set it to a fixed date
903 if (item->email->sent_date) { 822 if (item->email->sent_date) {
904 em_time = fileTimeToUnixTime(item->email->sent_date, 0); 823 em_time = fileTimeToUnixTime(item->email->sent_date, 0);
905 c_time = ctime(&em_time); 824 c_time = ctime(&em_time);
906 if (c_time) 825 if (c_time)
907 c_time[strlen(c_time)-1] = '\0'; //remove end \n 826 c_time[strlen(c_time)-1] = '\0'; //remove end \n
908 else 827 else
909 c_time = "Fri Dec 28 12:06:21 2001"; 828 c_time = "Fri Dec 28 12:06:21 2001";
910 } else 829 } else
911 c_time= "Fri Dec 28 12:06:21 2001"; 830 c_time= "Fri Dec 28 12:06:21 2001";
912 831
913 // we will always look at the header to discover some stuff 832 // we will always look at the header to discover some stuff
914 if (item->email->header ) { 833 if (item->email->header ) {
915 char *b1, *b2; 834 char *b1, *b2;
916 // see if there is a boundary variable there 835 // see if there is a boundary variable there
917 // this search MUST be made case insensitive (DONE). 836 // this search MUST be made case insensitive (DONE).
918 // Also, we should check to find out if we are looking 837 // Also, we should check to find out if we are looking
919 // at the boundary associated with content-type, and that 838 // at the boundary associated with content-type, and that
920 // the content type really is multipart 839 // the content type really is multipart
921 840
922 removeCR(item->email->header); 841 removeCR(item->email->header);
923 842
924 if ((b2 = my_stristr(item->email->header, "boundary="))) { 843 if ((b2 = my_stristr(item->email->header, "boundary="))) {
925 int len; 844 int len;
926 b2 += strlen("boundary="); // move boundary to first char of marker 845 b2 += strlen("boundary="); // move boundary to first char of marker
927 846
928 if (*b2 == '"') { 847 if (*b2 == '"') {
929 b2++; 848 b2++;
930 b1 = strchr(b2, '"'); // find terminating quote 849 b1 = strchr(b2, '"'); // find terminating quote
931 } else { 850 } else {
932 b1 = b2; 851 b1 = b2;
933 while (isgraph(*b1)) // find first char that isn't part of boundary 852 while (isgraph(*b1)) // find first char that isn't part of boundary
934 b1++; 853 b1++;
935 } 854 }
936 len = b1 - b2; 855 len = b1 - b2;
937 boundary = malloc(len+1); //malloc that length 856 boundary = malloc(len+1); //malloc that length
938 strncpy(boundary, b2, len); // copy boundary to another variable 857 strncpy(boundary, b2, len); // copy boundary to another variable
939 boundary[len] = '\0'; 858 boundary[len] = '\0';
940 b1 = b2 = boundary; 859 b1 = b2 = boundary;
941 while (*b2 != '\0') { // remove any CRs and Tabs 860 while (*b2 != '\0') { // remove any CRs and Tabs
942 if (*b2 != '\n' && *b2 != '\r' && *b2 != '\t') { 861 if (*b2 != '\n' && *b2 != '\r' && *b2 != '\t') {
943 *b1 = *b2; 862 *b1 = *b2;
944 b1++; 863 b1++;
945 } 864 }
946 b2++; 865 b2++;
947 } 866 }
948 *b1 = '\0'; 867 *b1 = '\0';
949 868
950 DEBUG_EMAIL(("Found boundary of - %s\n", boundary)); 869 DEBUG_EMAIL(("Found boundary of - %s\n", boundary));
951 } else { 870 } else {
952 DEBUG_EMAIL(("boundary not found in header\n")); 871 DEBUG_EMAIL(("boundary not found in header\n"));
953 } 872 }
954 873
955 // also possible to set 7bit encoding detection here. 874 // also possible to set 7bit encoding detection here.
956 if ((b2 = my_stristr(item->email->header, "Content-Transfer-Encoding:"))) { 875 if ((b2 = my_stristr(item->email->header, "Content-Transfer-Encoding:"))) {
957 if ((b2 = strchr(b2, ':'))) { 876 if ((b2 = strchr(b2, ':'))) {
958 b2++; // skip to the : at the end of the string 877 b2++; // skip to the : at the end of the string
959 878
960 while (*b2 == ' ' || *b2 == '\t') 879 while (*b2 == ' ' || *b2 == '\t')
961 b2++; 880 b2++;
962 if (pst_strincmp(b2, "base64", 6)==0) { 881 if (pst_strincmp(b2, "base64", 6)==0) {
963 DEBUG_EMAIL(("body is base64 encoded\n")); 882 DEBUG_EMAIL(("body is base64 encoded\n"));
964 base64_body = 1; 883 base64_body = 1;
965 } 884 }
966 } else { 885 } else {
967 DEBUG_WARN(("found a ':' during the my_stristr, but not after that..\n")); 886 DEBUG_WARN(("found a ':' during the my_stristr, but not after that..\n"));
968 } 887 }
969 } 888 }
970 } 889 }
971 890
972 if (!boundary && (item->attach || (item->email->body && item->email->htmlbody) 891 if (!boundary && (item->attach || (item->email->body && item->email->htmlbody)
973 || item->email->rtf_compressed || item->email->encrypted_body 892 || item->email->rtf_compressed || item->email->encrypted_body
974 || item->email->encrypted_htmlbody)) { 893 || item->email->encrypted_htmlbody)) {
975 // we need to create a boundary here. 894 // we need to create a boundary here.
976 DEBUG_EMAIL(("must create own boundary. oh dear.\n")); 895 DEBUG_EMAIL(("must create own boundary. oh dear.\n"));
977 boundary = malloc(50 * sizeof(char)); // allow 50 chars for boundary 896 boundary = malloc(50 * sizeof(char)); // allow 50 chars for boundary
978 boundary[0] = '\0'; 897 boundary[0] = '\0';
979 sprintf(boundary, "--boundary-LibPST-iamunique-%i_-_-", rand()); 898 sprintf(boundary, "--boundary-LibPST-iamunique-%i_-_-", rand());
980 DEBUG_EMAIL(("created boundary is %s\n", boundary)); 899 DEBUG_EMAIL(("created boundary is %s\n", boundary));
981 boundary_created = 1; 900 boundary_created = 1;
982 } 901 }
983 902
984 DEBUG_EMAIL(("About to print Header\n")); 903 DEBUG_EMAIL(("About to print Header\n"));
985 904
986 if (item && item->email && item->email->subject && item->email->subject->subj) { 905 if (item && item->email && item->email->subject && item->email->subject->subj) {
987 DEBUG_EMAIL(("item->email->subject->subj = %s\n", item->email->subject->subj)); 906 DEBUG_EMAIL(("item->email->subject->subj = %s\n", item->email->subject->subj));
988 } 907 }
989 908
990 if (item->email->header) { 909 if (item->email->header) {
991 int len; 910 int len;
992 char *soh = NULL; // real start of headers. 911 char *soh = NULL; // real start of headers.
993 912
994 // some of the headers we get from the file are not properly defined. 913 // some of the headers we get from the file are not properly defined.
995 // they can contain some email stuff too. We will cut off the header 914 // they can contain some email stuff too. We will cut off the header
996 // when we see a \n\n or \r\n\r\n 915 // when we see a \n\n or \r\n\r\n
997 removeCR(item->email->header); 916 removeCR(item->email->header);
998 temp = strstr(item->email->header, "\n\n"); 917 temp = strstr(item->email->header, "\n\n");
999 918
1000 if (temp) { 919 if (temp) {
1001 DEBUG_EMAIL(("Found body text in header\n")); 920 DEBUG_EMAIL(("Found body text in header\n"));
1002 temp[1] = '\0'; // stop after first \n 921 temp[1] = '\0'; // stop after first \n
1003 } 922 }
1004 923
1005 // Now, write out the header... 924 // Now, write out the header...
1006 soh = skip_header_prologue(item->email->header); 925 soh = skip_header_prologue(item->email->header);
1007 if (mode != MODE_SEPERATE) { 926 if (mode != MODE_SEPERATE) {
1008 // don't put rubbish in if we are doing seperate 927 // don't put rubbish in if we are doing seperate
1009 if (strncmp(soh, "X-From_: ", 9) == 0 ) { 928 if (strncmp(soh, "X-From_: ", 9) == 0 ) {
1010 fputs("From ", f_output); 929 fputs("From ", f_output);
1011 soh += 9; 930 soh += 9;
1012 } else 931 } else
1013 fprintf(f_output, "From \"%s\" %s\n", item->email->outlook_sender_name, c_time); 932 fprintf(f_output, "From \"%s\" %s\n", item->email->outlook_sender_name, c_time);
1014 } 933 }
1015 fprintf(f_output, "%s", soh); 934 fprintf(f_output, "%s", soh);
1016 len = strlen(soh); 935 len = strlen(soh);
1017 if (!len || (soh[len-1] != '\n')) fprintf(f_output, "\n"); 936 if (!len || (soh[len-1] != '\n')) fprintf(f_output, "\n");
1018 937
1019 } else { 938 } else {
1020 //make up our own header! 939 //make up our own header!
1021 if (mode != MODE_SEPERATE) { 940 if (mode != MODE_SEPERATE) {
1022 // don't want this first line for this mode 941 // don't want this first line for this mode
1023 if (item->email->outlook_sender_name) { 942 if (item->email->outlook_sender_name) {
1024 temp = item->email->outlook_sender_name; 943 temp = item->email->outlook_sender_name;
1025 } else { 944 } else {
1026 temp = "(readpst_null)"; 945 temp = "(readpst_null)";
1027 } 946 }
1028 fprintf(f_output, "From \"%s\" %s\n", temp, c_time); 947 fprintf(f_output, "From \"%s\" %s\n", temp, c_time);
1029 } 948 }
1030 949
1031 temp = item->email->outlook_sender; 950 temp = item->email->outlook_sender;
1032 if (!temp) temp = ""; 951 if (!temp) temp = "";
1033 fprintf(f_output, "From: \"%s\" <%s>\n", item->email->outlook_sender_name, temp); 952 fprintf(f_output, "From: \"%s\" <%s>\n", item->email->outlook_sender_name, temp);
1034 953
1035 if (item->email->subject) { 954 if (item->email->subject) {
1036 fprintf(f_output, "Subject: %s\n", item->email->subject->subj); 955 fprintf(f_output, "Subject: %s\n", item->email->subject->subj);
1037 } else { 956 } else {
1038 fprintf(f_output, "Subject: \n"); 957 fprintf(f_output, "Subject: \n");
1039 } 958 }
1040 959
1041 fprintf(f_output, "To: %s\n", item->email->sentto_address); 960 fprintf(f_output, "To: %s\n", item->email->sentto_address);
1042 if (item->email->cc_address) { 961 if (item->email->cc_address) {
1043 fprintf(f_output, "Cc: %s\n", item->email->cc_address); 962 fprintf(f_output, "Cc: %s\n", item->email->cc_address);
1044 } 963 }
1045 964
1046 if (item->email->sent_date) { 965 if (item->email->sent_date) {
1047 c_time = (char*) xmalloc(C_TIME_SIZE); 966 c_time = (char*) xmalloc(C_TIME_SIZE);
1048 strftime(c_time, C_TIME_SIZE, "%a, %d %b %Y %H:%M:%S %z", gmtime(&em_time)); 967 strftime(c_time, C_TIME_SIZE, "%a, %d %b %Y %H:%M:%S %z", gmtime(&em_time));
1049 fprintf(f_output, "Date: %s\n", c_time); 968 fprintf(f_output, "Date: %s\n", c_time);
1050 free(c_time); 969 free(c_time);
1051 } 970 }
1052 } 971 }
1053 972
1054 fprintf(f_output, "MIME-Version: 1.0\n"); 973 fprintf(f_output, "MIME-Version: 1.0\n");
1055 if (boundary && boundary_created) { 974 if (boundary && boundary_created) {
1056 // if we created the boundary, then it has NOT already been printed 975 // if we created the boundary, then it has NOT already been printed
1057 // in the headers above. 976 // in the headers above.
1058 if (item->attach) { 977 if (item->attach) {
1059 // write the boundary stuff if we have attachments 978 // write the boundary stuff if we have attachments
1060 fprintf(f_output, "Content-type: multipart/mixed;\n\tboundary=\"%s\"\n", boundary); 979 fprintf(f_output, "Content-type: multipart/mixed;\n\tboundary=\"%s\"\n", boundary);
1061 } else if (boundary) { 980 } else if (boundary) {
1062 // else if we have multipart/alternative then tell it so 981 // else if we have multipart/alternative then tell it so
1063 fprintf(f_output, "Content-type: multipart/alternative;\n\tboundary=\"%s\"\n", boundary); 982 fprintf(f_output, "Content-type: multipart/alternative;\n\tboundary=\"%s\"\n", boundary);
1064 } else if (item->email->htmlbody) { 983 } else if (item->email->htmlbody) {
1065 fprintf(f_output, "Content-type: text/html\n"); 984 fprintf(f_output, "Content-type: text/html\n");
1066 } 985 }
1067 } 986 }
1068 fprintf(f_output, "\n"); // start the body 987 fprintf(f_output, "\n"); // start the body
1069 DEBUG_EMAIL(("About to print Body\n")); 988 DEBUG_EMAIL(("About to print Body\n"));
1070 989
1071 if (item->email->body) { 990 if (item->email->body) {
1072 if (boundary) { 991 if (boundary) {
1073 fprintf(f_output, "\n--%s\n", boundary); 992 fprintf(f_output, "\n--%s\n", boundary);
1074 fprintf(f_output, "Content-type: text/plain\n"); 993 fprintf(f_output, "Content-type: text/plain\n");
1075 if (base64_body) 994 if (base64_body)
1076 fprintf(f_output, "Content-Transfer-Encoding: base64\n"); 995 fprintf(f_output, "Content-Transfer-Encoding: base64\n");
1077 fprintf(f_output, "\n"); 996 fprintf(f_output, "\n");
1078 } 997 }
1079 removeCR(item->email->body); 998 removeCR(item->email->body);
1080 if (base64_body) { 999 if (base64_body) {
1081 char *enc = base64_encode(item->email->body, strlen(item->email->body)); 1000 char *enc = base64_encode(item->email->body, strlen(item->email->body));
1082 if (enc) { 1001 if (enc) {
1083 write_email_body(f_output, enc); 1002 write_email_body(f_output, enc);
1084 free(enc); 1003 free(enc);
1085 } 1004 }
1086 } 1005 }
1087 else { 1006 else {
1088 write_email_body(f_output, item->email->body); 1007 write_email_body(f_output, item->email->body);
1089 } 1008 }
1090 } 1009 }
1091 1010
1092 if (item->email->htmlbody) { 1011 if (item->email->htmlbody) {
1093 if (boundary) { 1012 if (boundary) {
1094 fprintf(f_output, "\n--%s\n", boundary); 1013 fprintf(f_output, "\n--%s\n", boundary);
1095 fprintf(f_output, "Content-type: text/html\n"); 1014 fprintf(f_output, "Content-type: text/html\n");
1096 if (base64_body) fprintf(f_output, "Content-Transfer-Encoding: base64\n"); 1015 if (base64_body) fprintf(f_output, "Content-Transfer-Encoding: base64\n");
1097 fprintf(f_output, "\n"); 1016 fprintf(f_output, "\n");
1098 } 1017 }
1099 removeCR(item->email->htmlbody); 1018 removeCR(item->email->htmlbody);
1100 if (base64_body) { 1019 if (base64_body) {
1101 char *enc = base64_encode(item->email->htmlbody, strlen(item->email->htmlbody)); 1020 char *enc = base64_encode(item->email->htmlbody, strlen(item->email->htmlbody));
1102 if (enc) { 1021 if (enc) {
1103 write_email_body(f_output, enc); 1022 write_email_body(f_output, enc);
1104 free(enc); 1023 free(enc);
1105 } 1024 }
1106 } 1025 }
1107 else { 1026 else {
1108 write_email_body(f_output, item->email->htmlbody); 1027 write_email_body(f_output, item->email->htmlbody);
1109 } 1028 }
1110 } 1029 }
1111 1030
1112 if (item->email->rtf_compressed && save_rtf) { 1031 if (item->email->rtf_compressed && save_rtf) {
1113 //int32_t tester; 1032 //int32_t tester;
1114 DEBUG_EMAIL(("Adding RTF body as attachment\n")); 1033 DEBUG_EMAIL(("Adding RTF body as attachment\n"));
1115 current_attach = (pst_item_attach*)xmalloc(sizeof(pst_item_attach)); 1034 current_attach = (pst_item_attach*)xmalloc(sizeof(pst_item_attach));
1116 memset(current_attach, 0, sizeof(pst_item_attach)); 1035 memset(current_attach, 0, sizeof(pst_item_attach));
1117 current_attach->next = item->attach; 1036 current_attach->next = item->attach;
1118 item->attach = current_attach; 1037 item->attach = current_attach;
1119 current_attach->data = lzfu_decompress(item->email->rtf_compressed, item->email->rtf_compressed_size, &current_attach->size); 1038 current_attach->data = lzfu_decompress(item->email->rtf_compressed, item->email->rtf_compressed_size, &current_attach->size);
1120 current_attach->filename2 = xmalloc(strlen(RTF_ATTACH_NAME)+2); 1039 current_attach->filename2 = xmalloc(strlen(RTF_ATTACH_NAME)+2);
1121 strcpy(current_attach->filename2, RTF_ATTACH_NAME); 1040 strcpy(current_attach->filename2, RTF_ATTACH_NAME);
1122 current_attach->mimetype = xmalloc(strlen(RTF_ATTACH_TYPE)+2); 1041 current_attach->mimetype = xmalloc(strlen(RTF_ATTACH_TYPE)+2);
1123 strcpy(current_attach->mimetype, RTF_ATTACH_TYPE); 1042 strcpy(current_attach->mimetype, RTF_ATTACH_TYPE);
1124 //memcpy(&tester, item->email->rtf_compressed+sizeof(int32_t), sizeof(int32_t)); 1043 //memcpy(&tester, item->email->rtf_compressed+sizeof(int32_t), sizeof(int32_t));
1125 //LE32_CPU(tester); 1044 //LE32_CPU(tester);
1126 //printf("lz produced %d bytes, rtf claims %d bytes\n", current_attach->size, tester); 1045 //printf("lz produced %d bytes, rtf claims %d bytes\n", current_attach->size, tester);
1127 } 1046 }
1128 1047
1129 if (item->email->encrypted_body || item->email->encrypted_htmlbody) { 1048 if (item->email->encrypted_body || item->email->encrypted_htmlbody) {
1130 // if either the body or htmlbody is encrypted, add them as attachments 1049 // if either the body or htmlbody is encrypted, add them as attachments
1131 if (item->email->encrypted_body) { 1050 if (item->email->encrypted_body) {
1132 DEBUG_EMAIL(("Adding Encrypted Body as attachment\n")); 1051 DEBUG_EMAIL(("Adding Encrypted Body as attachment\n"));
1133 current_attach = (pst_item_attach*) xmalloc(sizeof(pst_item_attach)); 1052 current_attach = (pst_item_attach*) xmalloc(sizeof(pst_item_attach));
1134 memset(current_attach, 0, sizeof(pst_item_attach)); 1053 memset(current_attach, 0, sizeof(pst_item_attach));
1135 current_attach->next = item->attach; 1054 current_attach->next = item->attach;
1136 item->attach = current_attach; 1055 item->attach = current_attach;
1137 current_attach->data = item->email->encrypted_body; 1056 current_attach->data = item->email->encrypted_body;
1138 current_attach->size = item->email->encrypted_body_size; 1057 current_attach->size = item->email->encrypted_body_size;
1139 item->email->encrypted_body = NULL; 1058 item->email->encrypted_body = NULL;
1140 } 1059 }
1141 1060
1142 if (item->email->encrypted_htmlbody) { 1061 if (item->email->encrypted_htmlbody) {
1143 DEBUG_EMAIL(("Adding encrypted HTML body as attachment\n")); 1062 DEBUG_EMAIL(("Adding encrypted HTML body as attachment\n"));
1144 current_attach = (pst_item_attach*) xmalloc(sizeof(pst_item_attach)); 1063 current_attach = (pst_item_attach*) xmalloc(sizeof(pst_item_attach));
1145 memset(current_attach, 0, sizeof(pst_item_attach)); 1064 memset(current_attach, 0, sizeof(pst_item_attach));
1146 current_attach->next = item->attach; 1065 current_attach->next = item->attach;
1147 item->attach = current_attach; 1066 item->attach = current_attach;
1148 current_attach->data = item->email->encrypted_htmlbody; 1067 current_attach->data = item->email->encrypted_htmlbody;
1149 current_attach->size = item->email->encrypted_htmlbody_size; 1068 current_attach->size = item->email->encrypted_htmlbody_size;
1150 item->email->encrypted_htmlbody = NULL; 1069 item->email->encrypted_htmlbody = NULL;
1151 } 1070 }
1152 write_email_body(f_output, "The body of this email is encrypted. This isn't supported yet, but the body is now an attachment\n"); 1071 write_email_body(f_output, "The body of this email is encrypted. This isn't supported yet, but the body is now an attachment\n");
1153 } 1072 }
1154 1073
1155 // attachments 1074 // attachments
1156 attach_num = 0; 1075 attach_num = 0;
1157 for (current_attach = item->attach; current_attach; current_attach = current_attach->next) { 1076 for (current_attach = item->attach; current_attach; current_attach = current_attach->next) {
1158 DEBUG_EMAIL(("Attempting Attachment encoding\n")); 1077 DEBUG_EMAIL(("Attempting Attachment encoding\n"));
1159 if (!current_attach->data) { 1078 if (!current_attach->data) {
1160 DEBUG_EMAIL(("Data of attachment is NULL!. Size is supposed to be %i\n", current_attach->size)); 1079 DEBUG_EMAIL(("Data of attachment is NULL!. Size is supposed to be %i\n", current_attach->size));
1161 } 1080 }
1162 if (mode == MODE_SEPERATE && !mode_MH) 1081 if (mode == MODE_SEPERATE && !mode_MH)
1163 write_separate_attachment(f_name, current_attach, ++attach_num, pst); 1082 write_separate_attachment(f_name, current_attach, ++attach_num, pst);
1164 else 1083 else
1165 write_inline_attachment(f_output, current_attach, boundary, pst); 1084 write_inline_attachment(f_output, current_attach, boundary, pst);
1166 } 1085 }
1167 if (mode != MODE_SEPERATE) { /* do not add a boundary after the last attachment for mode_MH */ 1086 if (mode != MODE_SEPERATE) { /* do not add a boundary after the last attachment for mode_MH */
1168 DEBUG_EMAIL(("Writing buffer between emails\n")); 1087 DEBUG_EMAIL(("Writing buffer between emails\n"));
1169 if (boundary) fprintf(f_output, "\n--%s--\n", boundary); 1088 if (boundary) fprintf(f_output, "\n--%s--\n", boundary);
1170 fprintf(f_output, "\n\n"); 1089 fprintf(f_output, "\n\n");
1171 } 1090 }
1172 if (boundary) free (boundary); 1091 if (boundary) free (boundary);
1173 DEBUG_RET(); 1092 DEBUG_RET();
1174 } 1093 }
1175 1094
1176 1095
1177 void write_vcard(FILE* f_output, pst_item_contact* contact, char comment[]) 1096 void write_vcard(FILE* f_output, pst_item_contact* contact, char comment[])
1178 { 1097 {
1179 // We can only call rfc escape once per printf, since the second call 1098 // We can only call rfc escape once per printf, since the second call
1180 // may free the buffer returned by the first call. 1099 // may free the buffer returned by the first call.
1181 // I had tried to place those into a single printf - Carl. 1100 // I had tried to place those into a single printf - Carl.
1182 1101
1183 DEBUG_ENT("write_vcard"); 1102 DEBUG_ENT("write_vcard");
1184 // the specification I am following is (hopefully) RFC2426 vCard Mime Directory Profile 1103 // the specification I am following is (hopefully) PST_RFC2426 vCard Mime Directory Profile
1185 fprintf(f_output, "BEGIN:VCARD\n"); 1104 fprintf(f_output, "BEGIN:VCARD\n");
1186 fprintf(f_output, "FN:%s\n", rfc2426_escape(contact->fullname)); 1105 fprintf(f_output, "FN:%s\n", pst_rfc2426_escape(contact->fullname));
1187 1106
1188 //fprintf(f_output, "N:%s;%s;%s;%s;%s\n", 1107 //fprintf(f_output, "N:%s;%s;%s;%s;%s\n",
1189 fprintf(f_output, "N:%s;", (!contact->surname) ? "" : rfc2426_escape(contact->surname)); 1108 fprintf(f_output, "N:%s;", (!contact->surname) ? "" : pst_rfc2426_escape(contact->surname));
1190 fprintf(f_output, "%s;", (!contact->first_name) ? "" : rfc2426_escape(contact->first_name)); 1109 fprintf(f_output, "%s;", (!contact->first_name) ? "" : pst_rfc2426_escape(contact->first_name));
1191 fprintf(f_output, "%s;", (!contact->middle_name) ? "" : rfc2426_escape(contact->middle_name)); 1110 fprintf(f_output, "%s;", (!contact->middle_name) ? "" : pst_rfc2426_escape(contact->middle_name));
1192 fprintf(f_output, "%s;", (!contact->display_name_prefix) ? "" : rfc2426_escape(contact->display_name_prefix)); 1111 fprintf(f_output, "%s;", (!contact->display_name_prefix) ? "" : pst_rfc2426_escape(contact->display_name_prefix));
1193 fprintf(f_output, "%s\n", (!contact->suffix) ? "" : rfc2426_escape(contact->suffix)); 1112 fprintf(f_output, "%s\n", (!contact->suffix) ? "" : pst_rfc2426_escape(contact->suffix));
1194 1113
1195 if (contact->nickname) 1114 if (contact->nickname)
1196 fprintf(f_output, "NICKNAME:%s\n", rfc2426_escape(contact->nickname)); 1115 fprintf(f_output, "NICKNAME:%s\n", pst_rfc2426_escape(contact->nickname));
1197 if (contact->address1) 1116 if (contact->address1)
1198 fprintf(f_output, "EMAIL:%s\n", rfc2426_escape(contact->address1)); 1117 fprintf(f_output, "EMAIL:%s\n", pst_rfc2426_escape(contact->address1));
1199 if (contact->address2) 1118 if (contact->address2)
1200 fprintf(f_output, "EMAIL:%s\n", rfc2426_escape(contact->address2)); 1119 fprintf(f_output, "EMAIL:%s\n", pst_rfc2426_escape(contact->address2));
1201 if (contact->address3) 1120 if (contact->address3)
1202 fprintf(f_output, "EMAIL:%s\n", rfc2426_escape(contact->address3)); 1121 fprintf(f_output, "EMAIL:%s\n", pst_rfc2426_escape(contact->address3));
1203 if (contact->birthday) 1122 if (contact->birthday)
1204 fprintf(f_output, "BDAY:%s\n", rfc2425_datetime_format(contact->birthday)); 1123 fprintf(f_output, "BDAY:%s\n", pst_rfc2425_datetime_format(contact->birthday));
1205 1124
1206 if (contact->home_address) { 1125 if (contact->home_address) {
1207 //fprintf(f_output, "ADR;TYPE=home:%s;%s;%s;%s;%s;%s;%s\n", 1126 //fprintf(f_output, "ADR;TYPE=home:%s;%s;%s;%s;%s;%s;%s\n",
1208 fprintf(f_output, "ADR;TYPE=home:%s;", (!contact->home_po_box) ? "" : rfc2426_escape(contact->home_po_box)); 1127 fprintf(f_output, "ADR;TYPE=home:%s;", (!contact->home_po_box) ? "" : pst_rfc2426_escape(contact->home_po_box));
1209 fprintf(f_output, "%s;", ""); // extended Address 1128 fprintf(f_output, "%s;", ""); // extended Address
1210 fprintf(f_output, "%s;", (!contact->home_street) ? "" : rfc2426_escape(contact->home_street)); 1129 fprintf(f_output, "%s;", (!contact->home_street) ? "" : pst_rfc2426_escape(contact->home_street));
1211 fprintf(f_output, "%s;", (!contact->home_city) ? "" : rfc2426_escape(contact->home_city)); 1130 fprintf(f_output, "%s;", (!contact->home_city) ? "" : pst_rfc2426_escape(contact->home_city));
1212 fprintf(f_output, "%s;", (!contact->home_state) ? "" : rfc2426_escape(contact->home_state)); 1131 fprintf(f_output, "%s;", (!contact->home_state) ? "" : pst_rfc2426_escape(contact->home_state));
1213 fprintf(f_output, "%s;", (!contact->home_postal_code) ? "" : rfc2426_escape(contact->home_postal_code)); 1132 fprintf(f_output, "%s;", (!contact->home_postal_code) ? "" : pst_rfc2426_escape(contact->home_postal_code));
1214 fprintf(f_output, "%s\n", (!contact->home_country) ? "" : rfc2426_escape(contact->home_country)); 1133 fprintf(f_output, "%s\n", (!contact->home_country) ? "" : pst_rfc2426_escape(contact->home_country));
1215 fprintf(f_output, "LABEL;TYPE=home:%s\n", rfc2426_escape(contact->home_address)); 1134 fprintf(f_output, "LABEL;TYPE=home:%s\n", pst_rfc2426_escape(contact->home_address));
1216 } 1135 }
1217 1136
1218 if (contact->business_address) { 1137 if (contact->business_address) {
1219 //fprintf(f_output, "ADR;TYPE=work:%s;%s;%s;%s;%s;%s;%s\n", 1138 //fprintf(f_output, "ADR;TYPE=work:%s;%s;%s;%s;%s;%s;%s\n",
1220 fprintf(f_output, "ADR;TYPE=work:%s;", (!contact->business_po_box) ? "" : rfc2426_escape(contact->business_po_box)); 1139 fprintf(f_output, "ADR;TYPE=work:%s;", (!contact->business_po_box) ? "" : pst_rfc2426_escape(contact->business_po_box));
1221 fprintf(f_output, "%s;", ""); // extended Address 1140 fprintf(f_output, "%s;", ""); // extended Address
1222 fprintf(f_output, "%s;", (!contact->business_street) ? "" : rfc2426_escape(contact->business_street)); 1141 fprintf(f_output, "%s;", (!contact->business_street) ? "" : pst_rfc2426_escape(contact->business_street));
1223 fprintf(f_output, "%s;", (!contact->business_city) ? "" : rfc2426_escape(contact->business_city)); 1142 fprintf(f_output, "%s;", (!contact->business_city) ? "" : pst_rfc2426_escape(contact->business_city));
1224 fprintf(f_output, "%s;", (!contact->business_state) ? "" : rfc2426_escape(contact->business_state)); 1143 fprintf(f_output, "%s;", (!contact->business_state) ? "" : pst_rfc2426_escape(contact->business_state));
1225 fprintf(f_output, "%s;", (!contact->business_postal_code) ? "" : rfc2426_escape(contact->business_postal_code)); 1144 fprintf(f_output, "%s;", (!contact->business_postal_code) ? "" : pst_rfc2426_escape(contact->business_postal_code));
1226 fprintf(f_output, "%s\n", (!contact->business_country) ? "" : rfc2426_escape(contact->business_country)); 1145 fprintf(f_output, "%s\n", (!contact->business_country) ? "" : pst_rfc2426_escape(contact->business_country));
1227 fprintf(f_output, "LABEL;TYPE=work:%s\n", rfc2426_escape(contact->business_address)); 1146 fprintf(f_output, "LABEL;TYPE=work:%s\n", pst_rfc2426_escape(contact->business_address));
1228 } 1147 }
1229 1148
1230 if (contact->other_address) { 1149 if (contact->other_address) {
1231 //fprintf(f_output, "ADR;TYPE=postal:%s;%s;%s;%s;%s;%s;%s\n", 1150 //fprintf(f_output, "ADR;TYPE=postal:%s;%s;%s;%s;%s;%s;%s\n",
1232 fprintf(f_output, "ADR;TYPE=postal:%s;",(!contact->other_po_box) ? "" : rfc2426_escape(contact->other_po_box)); 1151 fprintf(f_output, "ADR;TYPE=postal:%s;",(!contact->other_po_box) ? "" : pst_rfc2426_escape(contact->other_po_box));
1233 fprintf(f_output, "%s;", ""); // extended Address 1152 fprintf(f_output, "%s;", ""); // extended Address
1234 fprintf(f_output, "%s;", (!contact->other_street) ? "" : rfc2426_escape(contact->other_street)); 1153 fprintf(f_output, "%s;", (!contact->other_street) ? "" : pst_rfc2426_escape(contact->other_street));
1235 fprintf(f_output, "%s;", (!contact->other_city) ? "" : rfc2426_escape(contact->other_city)); 1154 fprintf(f_output, "%s;", (!contact->other_city) ? "" : pst_rfc2426_escape(contact->other_city));
1236 fprintf(f_output, "%s;", (!contact->other_state) ? "" : rfc2426_escape(contact->other_state)); 1155 fprintf(f_output, "%s;", (!contact->other_state) ? "" : pst_rfc2426_escape(contact->other_state));
1237 fprintf(f_output, "%s;", (!contact->other_postal_code) ? "" : rfc2426_escape(contact->other_postal_code)); 1156 fprintf(f_output, "%s;", (!contact->other_postal_code) ? "" : pst_rfc2426_escape(contact->other_postal_code));
1238 fprintf(f_output, "%s\n", (!contact->other_country) ? "" : rfc2426_escape(contact->other_country)); 1157 fprintf(f_output, "%s\n", (!contact->other_country) ? "" : pst_rfc2426_escape(contact->other_country));
1239 fprintf(f_output, "LABEL;TYPE=postal:%s\n", rfc2426_escape(contact->other_address)); 1158 fprintf(f_output, "LABEL;TYPE=postal:%s\n", pst_rfc2426_escape(contact->other_address));
1240 } 1159 }
1241 1160
1242 if (contact->business_fax) fprintf(f_output, "TEL;TYPE=work,fax:%s\n", rfc2426_escape(contact->business_fax)); 1161 if (contact->business_fax) fprintf(f_output, "TEL;TYPE=work,fax:%s\n", pst_rfc2426_escape(contact->business_fax));
1243 if (contact->business_phone) fprintf(f_output, "TEL;TYPE=work,voice:%s\n", rfc2426_escape(contact->business_phone)); 1162 if (contact->business_phone) fprintf(f_output, "TEL;TYPE=work,voice:%s\n", pst_rfc2426_escape(contact->business_phone));
1244 if (contact->business_phone2) fprintf(f_output, "TEL;TYPE=work,voice:%s\n", rfc2426_escape(contact->business_phone2)); 1163 if (contact->business_phone2) fprintf(f_output, "TEL;TYPE=work,voice:%s\n", pst_rfc2426_escape(contact->business_phone2));
1245 if (contact->car_phone) fprintf(f_output, "TEL;TYPE=car,voice:%s\n", rfc2426_escape(contact->car_phone)); 1164 if (contact->car_phone) fprintf(f_output, "TEL;TYPE=car,voice:%s\n", pst_rfc2426_escape(contact->car_phone));
1246 if (contact->home_fax) fprintf(f_output, "TEL;TYPE=home,fax:%s\n", rfc2426_escape(contact->home_fax)); 1165 if (contact->home_fax) fprintf(f_output, "TEL;TYPE=home,fax:%s\n", pst_rfc2426_escape(contact->home_fax));
1247 if (contact->home_phone) fprintf(f_output, "TEL;TYPE=home,voice:%s\n", rfc2426_escape(contact->home_phone)); 1166 if (contact->home_phone) fprintf(f_output, "TEL;TYPE=home,voice:%s\n", pst_rfc2426_escape(contact->home_phone));
1248 if (contact->home_phone2) fprintf(f_output, "TEL;TYPE=home,voice:%s\n", rfc2426_escape(contact->home_phone2)); 1167 if (contact->home_phone2) fprintf(f_output, "TEL;TYPE=home,voice:%s\n", pst_rfc2426_escape(contact->home_phone2));
1249 if (contact->isdn_phone) fprintf(f_output, "TEL;TYPE=isdn:%s\n", rfc2426_escape(contact->isdn_phone)); 1168 if (contact->isdn_phone) fprintf(f_output, "TEL;TYPE=isdn:%s\n", pst_rfc2426_escape(contact->isdn_phone));
1250 if (contact->mobile_phone) fprintf(f_output, "TEL;TYPE=cell,voice:%s\n", rfc2426_escape(contact->mobile_phone)); 1169 if (contact->mobile_phone) fprintf(f_output, "TEL;TYPE=cell,voice:%s\n", pst_rfc2426_escape(contact->mobile_phone));
1251 if (contact->other_phone) fprintf(f_output, "TEL;TYPE=msg:%s\n", rfc2426_escape(contact->other_phone)); 1170 if (contact->other_phone) fprintf(f_output, "TEL;TYPE=msg:%s\n", pst_rfc2426_escape(contact->other_phone));
1252 if (contact->pager_phone) fprintf(f_output, "TEL;TYPE=pager:%s\n", rfc2426_escape(contact->pager_phone)); 1171 if (contact->pager_phone) fprintf(f_output, "TEL;TYPE=pager:%s\n", pst_rfc2426_escape(contact->pager_phone));
1253 if (contact->primary_fax) fprintf(f_output, "TEL;TYPE=fax,pref:%s\n", rfc2426_escape(contact->primary_fax)); 1172 if (contact->primary_fax) fprintf(f_output, "TEL;TYPE=fax,pref:%s\n", pst_rfc2426_escape(contact->primary_fax));
1254 if (contact->primary_phone) fprintf(f_output, "TEL;TYPE=phone,pref:%s\n", rfc2426_escape(contact->primary_phone)); 1173 if (contact->primary_phone) fprintf(f_output, "TEL;TYPE=phone,pref:%s\n", pst_rfc2426_escape(contact->primary_phone));
1255 if (contact->radio_phone) fprintf(f_output, "TEL;TYPE=pcs:%s\n", rfc2426_escape(contact->radio_phone)); 1174 if (contact->radio_phone) fprintf(f_output, "TEL;TYPE=pcs:%s\n", pst_rfc2426_escape(contact->radio_phone));
1256 if (contact->telex) fprintf(f_output, "TEL;TYPE=bbs:%s\n", rfc2426_escape(contact->telex)); 1175 if (contact->telex) fprintf(f_output, "TEL;TYPE=bbs:%s\n", pst_rfc2426_escape(contact->telex));
1257 if (contact->job_title) fprintf(f_output, "TITLE:%s\n", rfc2426_escape(contact->job_title)); 1176 if (contact->job_title) fprintf(f_output, "TITLE:%s\n", pst_rfc2426_escape(contact->job_title));
1258 if (contact->profession) fprintf(f_output, "ROLE:%s\n", rfc2426_escape(contact->profession)); 1177 if (contact->profession) fprintf(f_output, "ROLE:%s\n", pst_rfc2426_escape(contact->profession));
1259 if (contact->assistant_name || contact->assistant_phone) { 1178 if (contact->assistant_name || contact->assistant_phone) {
1260 fprintf(f_output, "AGENT:BEGIN:VCARD\n"); 1179 fprintf(f_output, "AGENT:BEGIN:VCARD\n");
1261 if (contact->assistant_name) fprintf(f_output, "FN:%s\n", rfc2426_escape(contact->assistant_name)); 1180 if (contact->assistant_name) fprintf(f_output, "FN:%s\n", pst_rfc2426_escape(contact->assistant_name));
1262 if (contact->assistant_phone) fprintf(f_output, "TEL:%s\n", rfc2426_escape(contact->assistant_phone)); 1181 if (contact->assistant_phone) fprintf(f_output, "TEL:%s\n", pst_rfc2426_escape(contact->assistant_phone));
1263 } 1182 }
1264 if (contact->company_name) fprintf(f_output, "ORG:%s\n", rfc2426_escape(contact->company_name)); 1183 if (contact->company_name) fprintf(f_output, "ORG:%s\n", pst_rfc2426_escape(contact->company_name));
1265 if (comment) fprintf(f_output, "NOTE:%s\n", rfc2426_escape(comment)); 1184 if (comment) fprintf(f_output, "NOTE:%s\n", pst_rfc2426_escape(comment));
1266 1185
1267 fprintf(f_output, "VERSION: 3.0\n"); 1186 fprintf(f_output, "VERSION: 3.0\n");
1268 fprintf(f_output, "END:VCARD\n\n"); 1187 fprintf(f_output, "END:VCARD\n\n");
1269 DEBUG_RET(); 1188 DEBUG_RET();
1270 } 1189 }
1271 1190
1272 1191
1273 void write_appointment(FILE* f_output, pst_item_appointment* appointment, 1192 void write_appointment(FILE* f_output, pst_item_appointment* appointment,
1274 pst_item_email* email, FILETIME* create_date, FILETIME* modify_date) 1193 pst_item_email* email, FILETIME* create_date, FILETIME* modify_date)
1275 { 1194 {
1276 fprintf(f_output, "BEGIN:VEVENT\n"); 1195 fprintf(f_output, "BEGIN:VEVENT\n");
1277 if (create_date) 1196 if (create_date)
1278 fprintf(f_output, "CREATED:%s\n", 1197 fprintf(f_output, "CREATED:%s\n",
1279 rfc2445_datetime_format(create_date)); 1198 pst_rfc2445_datetime_format(create_date));
1280 if (modify_date) 1199 if (modify_date)
1281 fprintf(f_output, "LAST-MOD:%s\n", 1200 fprintf(f_output, "LAST-MOD:%s\n",
1282 rfc2445_datetime_format(modify_date)); 1201 pst_rfc2445_datetime_format(modify_date));
1283 if (email && email->subject) 1202 if (email && email->subject)
1284 fprintf(f_output, "SUMMARY:%s\n", 1203 fprintf(f_output, "SUMMARY:%s\n",
1285 rfc2426_escape(email->subject->subj)); 1204 pst_rfc2426_escape(email->subject->subj));
1286 if (email && email->body) 1205 if (email && email->body)
1287 fprintf(f_output, "DESCRIPTION:%s\n", 1206 fprintf(f_output, "DESCRIPTION:%s\n",
1288 rfc2426_escape(email->body)); 1207 pst_rfc2426_escape(email->body));
1289 if (appointment && appointment->start) 1208 if (appointment && appointment->start)
1290 fprintf(f_output, "DTSTART;VALUE=DATE-TIME:%s\n", 1209 fprintf(f_output, "DTSTART;VALUE=DATE-TIME:%s\n",
1291 rfc2445_datetime_format(appointment->start)); 1210 pst_rfc2445_datetime_format(appointment->start));
1292 if (appointment && appointment->end) 1211 if (appointment && appointment->end)
1293 fprintf(f_output, "DTEND;VALUE=DATE-TIME:%s\n", 1212 fprintf(f_output, "DTEND;VALUE=DATE-TIME:%s\n",
1294 rfc2445_datetime_format(appointment->end)); 1213 pst_rfc2445_datetime_format(appointment->end));
1295 if (appointment && appointment->location) 1214 if (appointment && appointment->location)
1296 fprintf(f_output, "LOCATION:%s\n", 1215 fprintf(f_output, "LOCATION:%s\n",
1297 rfc2426_escape(appointment->location)); 1216 pst_rfc2426_escape(appointment->location));
1298 if (appointment) { 1217 if (appointment) {
1299 switch (appointment->showas) { 1218 switch (appointment->showas) {
1300 case PST_FREEBUSY_TENTATIVE: 1219 case PST_FREEBUSY_TENTATIVE:
1301 fprintf(f_output, "STATUS:TENTATIVE\n"); 1220 fprintf(f_output, "STATUS:TENTATIVE\n");
1302 break; 1221 break;
1303 case PST_FREEBUSY_FREE: 1222 case PST_FREEBUSY_FREE:
1304 // mark as transparent and as confirmed 1223 // mark as transparent and as confirmed
1305 fprintf(f_output, "TRANSP:TRANSPARENT\n"); 1224 fprintf(f_output, "TRANSP:TRANSPARENT\n");
1306 case PST_FREEBUSY_BUSY: 1225 case PST_FREEBUSY_BUSY:
1307 case PST_FREEBUSY_OUT_OF_OFFICE: 1226 case PST_FREEBUSY_OUT_OF_OFFICE:
1308 fprintf(f_output, "STATUS:CONFIRMED\n"); 1227 fprintf(f_output, "STATUS:CONFIRMED\n");
1309 break; 1228 break;
1310 } 1229 }
1311 switch (appointment->label) { 1230 switch (appointment->label) {
1312 case PST_APP_LABEL_NONE: 1231 case PST_APP_LABEL_NONE:
1313 fprintf(f_output, "CATEGORIES:NONE\n"); 1232 fprintf(f_output, "CATEGORIES:NONE\n");
1314 break; 1233 break;
1315 case PST_APP_LABEL_IMPORTANT: 1234 case PST_APP_LABEL_IMPORTANT:
1316 fprintf(f_output, "CATEGORIES:IMPORTANT\n"); 1235 fprintf(f_output, "CATEGORIES:IMPORTANT\n");
1317 break; 1236 break;
1318 case PST_APP_LABEL_BUSINESS: 1237 case PST_APP_LABEL_BUSINESS:
1319 fprintf(f_output, "CATEGORIES:BUSINESS\n"); 1238 fprintf(f_output, "CATEGORIES:BUSINESS\n");
1320 break; 1239 break;
1321 case PST_APP_LABEL_PERSONAL: 1240 case PST_APP_LABEL_PERSONAL:
1322 fprintf(f_output, "CATEGORIES:PERSONAL\n"); 1241 fprintf(f_output, "CATEGORIES:PERSONAL\n");
1323 break; 1242 break;
1324 case PST_APP_LABEL_VACATION: 1243 case PST_APP_LABEL_VACATION:
1325 fprintf(f_output, "CATEGORIES:VACATION\n"); 1244 fprintf(f_output, "CATEGORIES:VACATION\n");
1326 break; 1245 break;
1327 case PST_APP_LABEL_MUST_ATTEND: 1246 case PST_APP_LABEL_MUST_ATTEND:
1328 fprintf(f_output, "CATEGORIES:MUST-ATTEND\n"); 1247 fprintf(f_output, "CATEGORIES:MUST-ATTEND\n");
1329 break; 1248 break;
1330 case PST_APP_LABEL_TRAVEL_REQ: 1249 case PST_APP_LABEL_TRAVEL_REQ:
1331 fprintf(f_output, "CATEGORIES:TRAVEL-REQUIRED\n"); 1250 fprintf(f_output, "CATEGORIES:TRAVEL-REQUIRED\n");
1332 break; 1251 break;
1333 case PST_APP_LABEL_NEEDS_PREP: 1252 case PST_APP_LABEL_NEEDS_PREP:
1334 fprintf(f_output, "CATEGORIES:NEEDS-PREPARATION\n"); 1253 fprintf(f_output, "CATEGORIES:NEEDS-PREPARATION\n");
1335 break; 1254 break;
1336 case PST_APP_LABEL_BIRTHDAY: 1255 case PST_APP_LABEL_BIRTHDAY:
1337 fprintf(f_output, "CATEGORIES:BIRTHDAY\n"); 1256 fprintf(f_output, "CATEGORIES:BIRTHDAY\n");
1338 break; 1257 break;
1339 case PST_APP_LABEL_ANNIVERSARY: 1258 case PST_APP_LABEL_ANNIVERSARY:
1340 fprintf(f_output, "CATEGORIES:ANNIVERSARY\n"); 1259 fprintf(f_output, "CATEGORIES:ANNIVERSARY\n");
1341 break; 1260 break;
1342 case PST_APP_LABEL_PHONE_CALL: 1261 case PST_APP_LABEL_PHONE_CALL:
1343 fprintf(f_output, "CATEGORIES:PHONE-CALL\n"); 1262 fprintf(f_output, "CATEGORIES:PHONE-CALL\n");
1344 break; 1263 break;
1345 } 1264 }
1346 } 1265 }
1347 fprintf(f_output, "END:VEVENT\n\n"); 1266 fprintf(f_output, "END:VEVENT\n\n");
1348 } 1267 }
1349 1268
1350 1269
1351 void create_enter_dir(struct file_ll* f, pst_item *item) 1270 void create_enter_dir(struct file_ll* f, pst_item *item)
1352 { 1271 {
1353 f->email_count = 0; 1272 f->email_count = 0;
1354 f->skip_count = 0; 1273 f->skip_count = 0;
1355 f->type = item->type; 1274 f->type = item->type;
1356 f->stored_count = (item->folder) ? item->folder->email_count : 0; 1275 f->stored_count = (item->folder) ? item->folder->email_count : 0;
1357 1276
1358 DEBUG_ENT("create_enter_dir"); 1277 DEBUG_ENT("create_enter_dir");
1359 if (mode == MODE_KMAIL) 1278 if (mode == MODE_KMAIL)
1360 f->name = mk_kmail_dir(item->file_as); //create directory and form filename 1279 f->name = mk_kmail_dir(item->file_as); //create directory and form filename
1361 else if (mode == MODE_RECURSE) 1280 else if (mode == MODE_RECURSE)
1362 f->name = mk_recurse_dir(item->file_as); 1281 f->name = mk_recurse_dir(item->file_as);
1363 else if (mode == MODE_SEPERATE) { 1282 else if (mode == MODE_SEPERATE) {
1364 // do similar stuff to recurse here. 1283 // do similar stuff to recurse here.
1365 mk_seperate_dir(item->file_as); 1284 mk_seperate_dir(item->file_as);
1366 f->name = (char*) xmalloc(10); 1285 f->name = (char*) xmalloc(10);
1367 memset(f->name, 0, 10); 1286 memset(f->name, 0, 10);
1368 // sprintf(f->name, SEP_MAIL_FILE_TEMPLATE, f->email_count); 1287 // sprintf(f->name, SEP_MAIL_FILE_TEMPLATE, f->email_count);
1369 } else { 1288 } else {
1370 f->name = (char*) xmalloc(strlen(item->file_as)+strlen(OUTPUT_TEMPLATE)+1); 1289 f->name = (char*) xmalloc(strlen(item->file_as)+strlen(OUTPUT_TEMPLATE)+1);
1371 sprintf(f->name, OUTPUT_TEMPLATE, item->file_as); 1290 sprintf(f->name, OUTPUT_TEMPLATE, item->file_as);
1372 } 1291 }
1373 1292
1374 f->dname = (char*) xmalloc(strlen(item->file_as)+1); 1293 f->dname = (char*) xmalloc(strlen(item->file_as)+1);
1375 strcpy(f->dname, item->file_as); 1294 strcpy(f->dname, item->file_as);
1376 1295
1377 if (overwrite != 1) { 1296 if (overwrite != 1) {
1378 int x = 0; 1297 int x = 0;
1379 char *temp = (char*) xmalloc (strlen(f->name)+10); //enough room for 10 digits 1298 char *temp = (char*) xmalloc (strlen(f->name)+10); //enough room for 10 digits
1380 1299
1381 sprintf(temp, "%s", f->name); 1300 sprintf(temp, "%s", f->name);
1382 check_filename(temp); 1301 check_filename(temp);
1383 while ((f->output = fopen(temp, "r"))) { 1302 while ((f->output = fopen(temp, "r"))) {
1384 DEBUG_MAIN(("need to increase filename because one already exists with that name\n")); 1303 DEBUG_MAIN(("need to increase filename because one already exists with that name\n"));
1385 DEBUG_MAIN(("- increasing it to %s%d\n", f->name, x)); 1304 DEBUG_MAIN(("- increasing it to %s%d\n", f->name, x));
1386 x++; 1305 x++;
1387 sprintf(temp, "%s%08d", f->name, x); 1306 sprintf(temp, "%s%08d", f->name, x);
1388 DEBUG_MAIN(("- trying \"%s\"\n", f->name)); 1307 DEBUG_MAIN(("- trying \"%s\"\n", f->name));
1389 if (x == 99999999) { 1308 if (x == 99999999) {
1390 DIE(("create_enter_dir: Why can I not create a folder %s? I have tried %i extensions...\n", f->name, x)); 1309 DIE(("create_enter_dir: Why can I not create a folder %s? I have tried %i extensions...\n", f->name, x));
1391 } 1310 }
1392 fclose(f->output); 1311 fclose(f->output);
1393 } 1312 }
1394 if (x > 0) { //then the f->name should change 1313 if (x > 0) { //then the f->name should change
1395 free (f->name); 1314 free (f->name);
1396 f->name = temp; 1315 f->name = temp;
1397 } else { 1316 } else {
1398 free(temp); 1317 free(temp);
1399 } 1318 }
1400 } 1319 }
1401 1320
1402 DEBUG_MAIN(("f->name = %s\nitem->folder_name = %s\n", f->name, item->file_as)); 1321 DEBUG_MAIN(("f->name = %s\nitem->folder_name = %s\n", f->name, item->file_as));
1403 if (mode != MODE_SEPERATE) { 1322 if (mode != MODE_SEPERATE) {
1404 check_filename(f->name); 1323 check_filename(f->name);
1405 if (!(f->output = fopen(f->name, "w"))) { 1324 if (!(f->output = fopen(f->name, "w"))) {
1406 DIE(("create_enter_dir: Could not open file \"%s\" for write\n", f->name)); 1325 DIE(("create_enter_dir: Could not open file \"%s\" for write\n", f->name));
1407 } 1326 }
1408 } 1327 }
1409 DEBUG_RET(); 1328 DEBUG_RET();
1410 } 1329 }
1411 1330
1412 1331
1413 void close_enter_dir(struct file_ll *f) 1332 void close_enter_dir(struct file_ll *f)
1414 { 1333 {
1415 DEBUG_MAIN(("main: Email Count for folder %s is %i\n", f->dname, f->email_count)); 1334 DEBUG_MAIN(("main: Email Count for folder %s is %i\n", f->dname, f->email_count));
1416 if (output_mode != OUTPUT_QUIET) 1335 if (output_mode != OUTPUT_QUIET)
1417 printf("\t\"%s\" - %i items done, skipped %i, should have been %i\n", 1336 printf("\t\"%s\" - %i items done, skipped %i, should have been %i\n",
1418 f->dname, f->email_count, f->skip_count, f->stored_count); 1337 f->dname, f->email_count, f->skip_count, f->stored_count);
1419 if (f->output) fclose(f->output); 1338 if (f->output) fclose(f->output);
1420 free(f->name); 1339 free(f->name);
1421 free(f->dname); 1340 free(f->dname);
1422 1341
1423 if (mode == MODE_KMAIL) 1342 if (mode == MODE_KMAIL)
1424 close_kmail_dir(); 1343 close_kmail_dir();
1425 else if (mode == MODE_RECURSE) 1344 else if (mode == MODE_RECURSE)
1426 close_recurse_dir(); 1345 close_recurse_dir();
1427 else if (mode == MODE_SEPERATE) 1346 else if (mode == MODE_SEPERATE)
1428 close_seperate_dir(); 1347 close_seperate_dir();
1429 } 1348 }
1430 1349