comparison src/readpst.c @ 26:9eeba3f4ca4b

more cleanup from Arne
author carl
date Sat, 25 Feb 2006 12:45:57 -0800
parents 73e8959cd86b
children 51d826f31329
comparison
equal deleted inserted replaced
25:73e8959cd86b 26:9eeba3f4ca4b
51 #define D_MKDIR(x) mkdir(x, PERM_DIRS) 51 #define D_MKDIR(x) mkdir(x, PERM_DIRS)
52 #else 52 #else
53 #define D_MKDIR(x) mkdir(x) 53 #define D_MKDIR(x) mkdir(x)
54 #endif 54 #endif
55 struct file_ll { 55 struct file_ll {
56 char *name; 56 char *name;
57 char *dname; 57 char *dname;
58 FILE * output; 58 FILE * output;
59 int32_t stored_count; 59 int32_t stored_count;
60 int32_t email_count; 60 int32_t email_count;
61 int32_t skip_count; 61 int32_t skip_count;
62 int32_t type; 62 int32_t type;
63 struct file_ll *next; 63 struct file_ll *next;
64 }; 64 };
65 void write_email_body(FILE *f, char *body); 65 void write_email_body(FILE *f, char *body);
66 char *removeCR (char *c); 66 char *removeCR (char *c);
67 int32_t usage(); 67 int32_t usage();
68 int32_t version(); 68 int32_t version();
122 // filename for the attachment 122 // filename for the attachment
123 #define RTF_ATTACH_NAME "rtf-body.rtf" 123 #define RTF_ATTACH_NAME "rtf-body.rtf"
124 // mime type for the attachment 124 // mime type for the attachment
125 #define RTF_ATTACH_TYPE "application/rtf" 125 #define RTF_ATTACH_TYPE "application/rtf"
126 int main(int argc, char** argv) { 126 int main(int argc, char** argv) {
127 pst_item *item = NULL; 127 pst_item *item = NULL;
128 pst_file pstfile; 128 pst_file pstfile;
129 pst_desc_ll *d_ptr; 129 pst_desc_ll *d_ptr;
130 char * fname = NULL; 130 char * fname = NULL;
131 char *d_log=NULL; 131 char *d_log=NULL;
132 int c,x; 132 int c,x;
133 int mode = MODE_NORMAL; 133 int mode = MODE_NORMAL;
134 int mode_MH = 0; 134 int mode_MH = 0;
135 int output_mode = OUTPUT_NORMAL; 135 int output_mode = OUTPUT_NORMAL;
136 int contact_mode = CMODE_VCARD; 136 int contact_mode = CMODE_VCARD;
137 int overwrite = 0; 137 int overwrite = 0;
138 // int encrypt = 0; 138 // int encrypt = 0;
139 char *temp = NULL; //temporary char pointer 139 char *temp = NULL; //temporary char pointer
140 int skip_child = 0; 140 int skip_child = 0;
141 struct file_ll *f, *head; 141 struct file_ll *f, *head;
142 prog_name = argv[0]; 142 prog_name = argv[0];
143 143
144 while ((c = getopt(argc, argv, "d:hko:qrMSVwc:"))!= -1) { 144 while ((c = getopt(argc, argv, "d:hko:qrMSVwc:"))!= -1) {
145 switch (c) { 145 switch (c) {
146 case 'c': 146 case 'c':
147 if (optarg!=NULL && optarg[0]=='v') 147 if (optarg!=NULL && optarg[0]=='v')
148 contact_mode=CMODE_VCARD; 148 contact_mode=CMODE_VCARD;
149 else if (optarg!=NULL && optarg[0]=='l') 149 else if (optarg!=NULL && optarg[0]=='l')
150 contact_mode=CMODE_LIST; 150 contact_mode=CMODE_LIST;
151 else { 151 else {
152 usage(); 152 usage();
153 exit(0); 153 exit(0);
154 } 154 }
155 break; 155 break;
156 case 'd': 156 case 'd':
157 d_log = optarg; 157 d_log = optarg;
158 break; 158 break;
159 case 'h': 159 case 'h':
160 usage(); 160 usage();
161 exit(0); 161 exit(0);
162 break; 162 break;
163 case 'V': 163 case 'V':
164 version(); 164 version();
165 exit(0); 165 exit(0);
166 break; 166 break;
167 case 'k': 167 case 'k':
168 mode = MODE_KMAIL; 168 mode = MODE_KMAIL;
169 break; 169 break;
170 case 'M': 170 case 'M':
171 mode = MODE_SEPERATE; 171 mode = MODE_SEPERATE;
172 mode_MH = 1; 172 mode_MH = 1;
173 break; 173 break;
174 case 'o': 174 case 'o':
175 output_dir = optarg; 175 output_dir = optarg;
176 break; 176 break;
177 case 'q': 177 case 'q':
178 output_mode = OUTPUT_QUIET; 178 output_mode = OUTPUT_QUIET;
179 break; 179 break;
180 case 'r': 180 case 'r':
181 mode = MODE_RECURSE; 181 mode = MODE_RECURSE;
182 break; 182 break;
183 case 'S': 183 case 'S':
184 mode = MODE_SEPERATE; 184 mode = MODE_SEPERATE;
185 break; 185 break;
186 case 'w': 186 case 'w':
187 overwrite = 1; 187 overwrite = 1;
188 break; 188 break;
189 default: 189 default:
190 usage(); 190 usage();
191 exit(1); 191 exit(1);
192 break; 192 break;
193 } 193 }
194 } 194 }
195 195
196 #ifdef DEBUG_ALL 196 #ifdef DEBUG_ALL
197 // initialize log file 197 // initialize log file
198 if (d_log == NULL) 198 if (d_log == NULL)
199 d_log = "readpst.log"; 199 d_log = "readpst.log";
200 DEBUG_INIT(d_log); 200 DEBUG_INIT(d_log);
201 DEBUG_REGISTER_CLOSE(); 201 DEBUG_REGISTER_CLOSE();
202 #endif // defined DEBUG_ALL 202 #endif // defined DEBUG_ALL
203 203
204 DEBUG_ENT("main"); 204 DEBUG_ENT("main");
205 205
206 if (argc > optind) { 206 if (argc > optind) {
207 fname = argv[optind]; 207 fname = argv[optind];
208 } else { 208 } else {
209 usage(); 209 usage();
210 exit(2); 210 exit(2);
211 } 211 }
212 212
213 if (output_mode != OUTPUT_QUIET) printf("Opening PST file and indexes...\n"); 213 if (output_mode != OUTPUT_QUIET) printf("Opening PST file and indexes...\n");
214 214
215 DEBUG_MAIN(("main: Opening PST file '%s'\n", fname)); 215 DEBUG_MAIN(("main: Opening PST file '%s'\n", fname));
216 RET_DERROR(pst_open(&pstfile, fname, "r"), 1, ("Error opening File\n")); 216 RET_DERROR(pst_open(&pstfile, fname, "r"), 1, ("Error opening File\n"));
217 DEBUG_MAIN(("main: Loading Indexes\n")); 217 DEBUG_MAIN(("main: Loading Indexes\n"));
218 RET_DERROR(pst_load_index(&pstfile), 2, ("Index Error\n")); 218 RET_DERROR(pst_load_index(&pstfile), 2, ("Index Error\n"));
219 DEBUG_MAIN(("processing file items\n")); 219 DEBUG_MAIN(("processing file items\n"));
220 220
221 pst_load_extended_attributes(&pstfile); 221 pst_load_extended_attributes(&pstfile);
222 222
223 if (chdir(output_dir)) { 223 if (chdir(output_dir)) {
224 x = errno; 224 x = errno;
225 pst_close(&pstfile); 225 pst_close(&pstfile);
226 DIE(("main: Cannot change to output dir %s: %s\n", output_dir, strerror(x))); 226 DIE(("main: Cannot change to output dir %s: %s\n", output_dir, strerror(x)));
227 } 227 }
228 228
229 if (output_mode != OUTPUT_QUIET) printf("About to start processing first record...\n"); 229 if (output_mode != OUTPUT_QUIET) printf("About to start processing first record...\n");
230 230
231 d_ptr = pstfile.d_head; // first record is main record 231 d_ptr = pstfile.d_head; // first record is main record
232 if ((item = _pst_parse_item(&pstfile, d_ptr)) == NULL || item->message_store == NULL) { 232 if ((item = _pst_parse_item(&pstfile, d_ptr)) == NULL || item->message_store == NULL) {
233 DIE(("main: Could not get root record\n")); 233 DIE(("main: Could not get root record\n"));
234 } 234 }
235 235
236 // default the file_as to the same as the main filename if it doesn't exist 236 // default the file_as to the same as the main filename if it doesn't exist
237 if (item->file_as == NULL) { 237 if (item->file_as == NULL) {
238 if ((temp = strrchr(fname, '/')) == NULL) 238 if ((temp = strrchr(fname, '/')) == NULL)
239 if ((temp = strrchr(fname, '\\')) == NULL) 239 if ((temp = strrchr(fname, '\\')) == NULL)
240 temp = fname; 240 temp = fname;
241 else 241 else
242 temp++; // get past the "\\" 242 temp++; // get past the "\\"
243 else 243 else
244 temp++; // get past the "/" 244 temp++; // get past the "/"
245 item->file_as = (char*)xmalloc(strlen(temp)+1); 245 item->file_as = (char*)xmalloc(strlen(temp)+1);
246 strcpy(item->file_as, temp); 246 strcpy(item->file_as, temp);
247 DEBUG_MAIN(("file_as was blank, so am using %s\n", item->file_as)); 247 DEBUG_MAIN(("file_as was blank, so am using %s\n", item->file_as));
248 } 248 }
249 DEBUG_MAIN(("main: Root Folder Name: %s\n", item->file_as)); 249 DEBUG_MAIN(("main: Root Folder Name: %s\n", item->file_as));
250 250
251 251
252 f = (struct file_ll*) malloc(sizeof(struct file_ll));
253 memset(f, 0, sizeof(struct file_ll));
254 f->email_count = 0;
255 f->skip_count = 0;
256 f->next = NULL;
257 head = f;
258 create_enter_dir(f, item->file_as, mode, overwrite);
259 f->type = item->type;
260
261 if ((d_ptr = pst_getTopOfFolders(&pstfile, item)) == NULL) {
262 DIE(("Top of folders record not found. Cannot continue\n"));
263 }
264
265 if (item){
266 _pst_freeItem(item);
267 item = NULL;
268 }
269
270 /* if ((item = _pst_parse_item(&pstfile, d_ptr)) == NULL || item->folder == NULL) {
271 DEBUG_MAIN(("main: Could not get \"Top Of Personal Folder\" record\n"));
272 return -2;
273 }*/
274 d_ptr = d_ptr->child; // do the children of TOPF
275
276 if (output_mode != OUTPUT_QUIET) printf("Processing items...\n");
277
278 DEBUG_MAIN(("main: About to do email stuff\n"));
279 while (d_ptr != NULL) {
280 DEBUG_MAIN(("main: New item record\n"));
281 if (d_ptr->desc == NULL) {
282 DEBUG_WARN(("main: ERROR ?? item's desc record is NULL\n"));
283 f->skip_count++;
284 goto check_parent;
285 }
286 DEBUG_MAIN(("main: Desc Email ID %#x [d_ptr->id = %#x]\n", d_ptr->desc->id, d_ptr->id));
287
288 item = _pst_parse_item(&pstfile, d_ptr);
289 DEBUG_MAIN(("main: About to process item\n"));
290 if (item != NULL && item->email != NULL && item->email->subject != NULL &&
291 item->email->subject->subj != NULL) {
292 // DEBUG_EMAIL(("item->email->subject = %p\n", item->email->subject));
293 // DEBUG_EMAIL(("item->email->subject->subj = %p\n", item->email->subject->subj));
294 }
295 if (item != NULL) {
296 if (item->message_store != NULL) {
297 // there should only be one message_store, and we have already done it
298 DIE(("main: A second message_store has been found. Sorry, this must be an error.\n"));
299 }
300
301
302 if (item->folder != NULL) {
303 // if this is a folder, we want to recurse into it
304 if (output_mode != OUTPUT_QUIET) printf("Processing Folder \"%s\"\n", item->file_as);
305 // f->email_count++;
306 DEBUG_MAIN(("main: I think I may try to go into folder \"%s\"\n", item->file_as));
307 f = (struct file_ll*) malloc(sizeof(struct file_ll)); 252 f = (struct file_ll*) malloc(sizeof(struct file_ll));
308 memset(f, 0, sizeof(struct file_ll)); 253 memset(f, 0, sizeof(struct file_ll));
309
310 f->next = head;
311 f->email_count = 0; 254 f->email_count = 0;
255 f->skip_count = 0;
256 f->next = NULL;
257 head = f;
258 create_enter_dir(f, item->file_as, mode, overwrite);
312 f->type = item->type; 259 f->type = item->type;
313 f->stored_count = item->folder->email_count; 260
314 head = f; 261 if ((d_ptr = pst_getTopOfFolders(&pstfile, item)) == NULL) {
315 262 DIE(("Top of folders record not found. Cannot continue\n"));
316 temp = item->file_as; 263 }
317 temp = check_filename(temp); 264
318 create_enter_dir(f, item->file_as, mode, overwrite); 265 if (item){
319 if (d_ptr->child != NULL) { 266 _pst_freeItem(item);
320 d_ptr = d_ptr->child; 267 item = NULL;
321 skip_child = 1; 268 }
322 } else { 269
323 DEBUG_MAIN(("main: Folder has NO children. Creating directory, and closing again\n")); 270 /* if ((item = _pst_parse_item(&pstfile, d_ptr)) == NULL || item->folder == NULL) {
324 if (output_mode != OUTPUT_QUIET) 271 DEBUG_MAIN(("main: Could not get \"Top Of Personal Folder\" record\n"));
325 printf("\tNo items to process in folder \"%s\", should have been %i\n", f->dname, f->stored_count); 272 return -2;
326 head = f->next; 273 }*/
327 if (f->output != NULL) 274 d_ptr = d_ptr->child; // do the children of TOPF
328 fclose(f->output); 275
329 if (mode == MODE_KMAIL) 276 if (output_mode != OUTPUT_QUIET) printf("Processing items...\n");
330 close_kmail_dir(); 277
331 else if (mode == MODE_RECURSE) 278 DEBUG_MAIN(("main: About to do email stuff\n"));
332 close_recurse_dir(); 279 while (d_ptr != NULL) {
333 else if (mode == MODE_SEPERATE) 280 DEBUG_MAIN(("main: New item record\n"));
334 close_seperate_dir(); 281 if (d_ptr->desc == NULL) {
335 free(f->dname); 282 DEBUG_WARN(("main: ERROR ?? item's desc record is NULL\n"));
336 free(f->name); 283 f->skip_count++;
337 free(f); 284 goto check_parent;
338 285 }
339 f = head; 286 DEBUG_MAIN(("main: Desc Email ID %#x [d_ptr->id = %#x]\n", d_ptr->desc->id, d_ptr->id));
340 } 287
341 _pst_freeItem(item); 288 item = _pst_parse_item(&pstfile, d_ptr);
342 item = NULL; // just for the odd situations! 289 DEBUG_MAIN(("main: About to process item\n"));
343 goto check_parent; 290 if (item != NULL && item->email != NULL && item->email->subject != NULL &&
344 } else if (item->contact != NULL) { 291 item->email->subject->subj != NULL) {
345 // deal with a contact 292 // DEBUG_EMAIL(("item->email->subject = %p\n", item->email->subject));
346 // write them to the file, one per line in this format 293 // DEBUG_EMAIL(("item->email->subject->subj = %p\n", item->email->subject->subj));
347 // Desc Name <email@address>\n 294 }
348 if (mode == MODE_SEPERATE) { 295 if (item != NULL) {
349 mk_seperate_file(f); 296 if (item->message_store != NULL) {
350 } 297 // there should only be one message_store, and we have already done it
351 f->email_count++; 298 DIE(("main: A second message_store has been found. Sorry, this must be an error.\n"));
352 299 }
353 DEBUG_MAIN(("main: Processing Contact\n")); 300
354 if (f->type != PST_TYPE_CONTACT) { 301
355 DEBUG_MAIN(("main: I have a contact, but the folder isn't a contacts folder. " 302 if (item->folder != NULL) {
356 "Will process anyway\n")); 303 // if this is a folder, we want to recurse into it
357 } 304 if (output_mode != OUTPUT_QUIET) printf("Processing Folder \"%s\"\n", item->file_as);
358 if (item->type != PST_TYPE_CONTACT) { 305 // f->email_count++;
359 DEBUG_MAIN(("main: I have an item that has contact info, but doesn't say that" 306 DEBUG_MAIN(("main: I think I may try to go into folder \"%s\"\n", item->file_as));
360 " it is a contact. Type is \"%s\"\n", item->ascii_type)); 307 f = (struct file_ll*) malloc(sizeof(struct file_ll));
361 DEBUG_MAIN(("main: Processing anyway\n")); 308 memset(f, 0, sizeof(struct file_ll));
362 } 309
363 if (item->contact == NULL) { // this is an incorrect situation. Inform user 310 f->next = head;
364 DEBUG_MAIN(("main: ERROR. This contact has not been fully parsed. one of the pre-requisties is NULL\n")); 311 f->email_count = 0;
365 } else { 312 f->type = item->type;
366 if (contact_mode == CMODE_VCARD) 313 f->stored_count = item->folder->email_count;
367 write_vcard(f->output, item->contact, item->comment); 314 head = f;
368 else 315
369 fprintf(f->output, "%s <%s>\n", item->contact->fullname, item->contact->address1); 316 temp = item->file_as;
370 } 317 temp = check_filename(temp);
371 } else if (item->email != NULL && 318 create_enter_dir(f, item->file_as, mode, overwrite);
372 (item->type == PST_TYPE_NOTE || item->type == PST_TYPE_REPORT)) { 319 if (d_ptr->child != NULL) {
373 if (mode == MODE_SEPERATE) { 320 d_ptr = d_ptr->child;
374 mk_seperate_file(f); 321 skip_child = 1;
375 } 322 } else {
376 323 DEBUG_MAIN(("main: Folder has NO children. Creating directory, and closing again\n"));
377 f->email_count++; 324 if (output_mode != OUTPUT_QUIET)
378 325 printf("\tNo items to process in folder \"%s\", should have been %i\n", f->dname, f->stored_count);
379 DEBUG_MAIN(("main: seen an email\n")); 326 head = f->next;
380 write_normal_email(f->output, f->name, item, mode, mode_MH, &pstfile); 327 if (f->output != NULL)
381 } else if (item->type == PST_TYPE_JOURNAL) { 328 fclose(f->output);
382 // deal with journal items 329 if (mode == MODE_KMAIL)
383 if (mode == MODE_SEPERATE) { 330 close_kmail_dir();
384 mk_seperate_file(f); 331 else if (mode == MODE_RECURSE)
385 } 332 close_recurse_dir();
386 f->email_count++; 333 else if (mode == MODE_SEPERATE)
387 334 close_seperate_dir();
388 DEBUG_MAIN(("main: Processing Journal Entry\n")); 335 free(f->dname);
389 if (f->type != PST_TYPE_JOURNAL) { 336 free(f->name);
390 DEBUG_MAIN(("main: I have a journal entry, but folder isn't specified as a journal type. Processing...\n")); 337 free(f);
391 } 338
392 339 f = head;
393 /* if (item->type != PST_TYPE_JOURNAL) { 340 }
394 DEBUG_MAIN(("main: I have an item with journal info, but it's type is \"%s\" \n. Processing...\n", 341 _pst_freeItem(item);
395 item->ascii_type)); 342 item = NULL; // just for the odd situations!
396 }*/ 343 goto check_parent;
397 fprintf(f->output, "BEGIN:VJOURNAL\n"); 344 } else if (item->contact != NULL) {
398 if (item->email->subject != NULL) 345 // deal with a contact
399 fprintf(f->output, "SUMMARY:%s\n", rfc2426_escape(item->email->subject->subj)); 346 // write them to the file, one per line in this format
400 if (item->email->body != NULL) 347 // Desc Name <email@address>\n
401 fprintf(f->output, "DESCRIPTION:%s\n", rfc2426_escape(item->email->body)); 348 if (mode == MODE_SEPERATE) {
402 if (item->journal->start != NULL) 349 mk_seperate_file(f);
403 fprintf(f->output, "DTSTART;VALUE=DATE-TIME:%s\n", rfc2445_datetime_format(item->journal->start)); 350 }
404 fprintf(f->output, "END:VJOURNAL\n\n"); 351 f->email_count++;
405 } else if (item->type == PST_TYPE_APPOINTMENT) { 352
406 // deal with Calendar appointments 353 DEBUG_MAIN(("main: Processing Contact\n"));
407 if (mode == MODE_SEPERATE) { 354 if (f->type != PST_TYPE_CONTACT) {
408 mk_seperate_file(f); 355 DEBUG_MAIN(("main: I have a contact, but the folder isn't a contacts folder. "
409 } 356 "Will process anyway\n"));
410 f->email_count++; 357 }
411 358 if (item->type != PST_TYPE_CONTACT) {
412 DEBUG_MAIN(("main: Processing Appointment Entry\n")); 359 DEBUG_MAIN(("main: I have an item that has contact info, but doesn't say that"
413 if (f->type != PST_TYPE_APPOINTMENT) { 360 " it is a contact. Type is \"%s\"\n", item->ascii_type));
414 DEBUG_MAIN(("main: I have an appointment, but folder isn't specified as an appointment type. Processing...\n")); 361 DEBUG_MAIN(("main: Processing anyway\n"));
415 } 362 }
416 write_appointment(f->output, item->appointment, item->email, item->create_date, item->modify_date); 363 if (item->contact == NULL) { // this is an incorrect situation. Inform user
417 } else { 364 DEBUG_MAIN(("main: ERROR. This contact has not been fully parsed. one of the pre-requisties is NULL\n"));
418 f->skip_count++; 365 } else {
419 DEBUG_MAIN(("main: Unknown item type. %i. Ascii1=\"%s\"\n", 366 if (contact_mode == CMODE_VCARD)
420 item->type, item->ascii_type)); 367 write_vcard(f->output, item->contact, item->comment);
421 } 368 else
422 } else { 369 fprintf(f->output, "%s <%s>\n", item->contact->fullname, item->contact->address1);
423 f->skip_count++; 370 }
424 DEBUG_MAIN(("main: A NULL item was seen\n")); 371 } else if (item->email != NULL &&
425 } 372 (item->type == PST_TYPE_NOTE || item->type == PST_TYPE_REPORT)) {
426 373 if (mode == MODE_SEPERATE) {
427 DEBUG_MAIN(("main: Going to next d_ptr\n")); 374 mk_seperate_file(f);
428 375 }
429 check_parent: 376
430 // _pst_freeItem(item); 377 f->email_count++;
431 while (!skip_child && d_ptr->next == NULL && d_ptr->parent != NULL) { 378
432 DEBUG_MAIN(("main: Going to Parent\n")); 379 DEBUG_MAIN(("main: seen an email\n"));
433 head = f->next; 380 write_normal_email(f->output, f->name, item, mode, mode_MH, &pstfile);
434 if (f->output != NULL) 381 } else if (item->type == PST_TYPE_JOURNAL) {
435 fclose(f->output); 382 // deal with journal items
436 DEBUG_MAIN(("main: Email Count for folder %s is %i\n", f->dname, f->email_count)); 383 if (mode == MODE_SEPERATE) {
437 if (output_mode != OUTPUT_QUIET) 384 mk_seperate_file(f);
438 printf("\t\"%s\" - %i items done, skipped %i, should have been %i\n", 385 }
439 f->dname, f->email_count, f->skip_count, f->stored_count); 386 f->email_count++;
440 if (mode == MODE_KMAIL) 387
441 close_kmail_dir(); 388 DEBUG_MAIN(("main: Processing Journal Entry\n"));
442 else if (mode == MODE_RECURSE) 389 if (f->type != PST_TYPE_JOURNAL) {
443 close_recurse_dir(); 390 DEBUG_MAIN(("main: I have a journal entry, but folder isn't specified as a journal type. Processing...\n"));
444 else if (mode == MODE_SEPERATE) 391 }
445 close_seperate_dir(); 392
446 free(f->name); 393 /* if (item->type != PST_TYPE_JOURNAL) {
447 free(f->dname); 394 DEBUG_MAIN(("main: I have an item with journal info, but it's type is \"%s\" \n. Processing...\n",
448 free(f); 395 item->ascii_type));
449 f = head; 396 }*/
450 if (head == NULL) { //we can't go higher. Must be at start? 397 fprintf(f->output, "BEGIN:VJOURNAL\n");
451 DEBUG_MAIN(("main: We are now trying to go above the highest level. We must be finished\n")); 398 if (item->email->subject != NULL)
452 break; //from main while loop 399 fprintf(f->output, "SUMMARY:%s\n", rfc2426_escape(item->email->subject->subj));
453 } 400 if (item->email->body != NULL)
454 d_ptr = d_ptr->parent; 401 fprintf(f->output, "DESCRIPTION:%s\n", rfc2426_escape(item->email->body));
455 skip_child = 0; 402 if (item->journal->start != NULL)
456 } 403 fprintf(f->output, "DTSTART;VALUE=DATE-TIME:%s\n", rfc2445_datetime_format(item->journal->start));
457 404 fprintf(f->output, "END:VJOURNAL\n\n");
458 if (item != NULL) { 405 } else if (item->type == PST_TYPE_APPOINTMENT) {
459 DEBUG_MAIN(("main: Freeing memory used by item\n")); 406 // deal with Calendar appointments
460 _pst_freeItem(item); 407 if (mode == MODE_SEPERATE) {
461 item = NULL; 408 mk_seperate_file(f);
462 } 409 }
463 410 f->email_count++;
464 if (!skip_child) 411
465 d_ptr = d_ptr->next; 412 DEBUG_MAIN(("main: Processing Appointment Entry\n"));
466 else 413 if (f->type != PST_TYPE_APPOINTMENT) {
467 skip_child = 0; 414 DEBUG_MAIN(("main: I have an appointment, but folder isn't specified as an appointment type. Processing...\n"));
468 415 }
469 if (d_ptr == NULL) { 416 write_appointment(f->output, item->appointment, item->email, item->create_date, item->modify_date);
470 DEBUG_MAIN(("main: d_ptr is now NULL\n")); 417 } else {
471 } 418 f->skip_count++;
472 } 419 DEBUG_MAIN(("main: Unknown item type. %i. Ascii1=\"%s\"\n",
473 if (output_mode != OUTPUT_QUIET) printf("Finished.\n"); 420 item->type, item->ascii_type));
474 DEBUG_MAIN(("main: Finished.\n")); 421 }
475 422 } else {
476 pst_close(&pstfile); 423 f->skip_count++;
477 // fclose(pstfile.fp); 424 DEBUG_MAIN(("main: A NULL item was seen\n"));
478 while (f != NULL) { 425 }
479 if (f->output != NULL) 426
480 fclose(f->output); 427 DEBUG_MAIN(("main: Going to next d_ptr\n"));
481 free(f->name); 428
482 free(f->dname); 429 check_parent:
483 430 // _pst_freeItem(item);
484 if (mode == MODE_KMAIL) 431 while (!skip_child && d_ptr->next == NULL && d_ptr->parent != NULL) {
485 close_kmail_dir(); 432 DEBUG_MAIN(("main: Going to Parent\n"));
486 else if (mode == MODE_RECURSE) 433 head = f->next;
487 close_recurse_dir(); 434 if (f->output != NULL)
488 else if (mode == MODE_SEPERATE) 435 fclose(f->output);
489 // DO SOMETHING HERE 436 DEBUG_MAIN(("main: Email Count for folder %s is %i\n", f->dname, f->email_count));
490 ; 437 if (output_mode != OUTPUT_QUIET)
491 head = f->next; 438 printf("\t\"%s\" - %i items done, skipped %i, should have been %i\n",
492 free (f); 439 f->dname, f->email_count, f->skip_count, f->stored_count);
493 f = head; 440 if (mode == MODE_KMAIL)
494 } 441 close_kmail_dir();
495 442 else if (mode == MODE_RECURSE)
496 DEBUG_RET(); 443 close_recurse_dir();
497 444 else if (mode == MODE_SEPERATE)
498 return 0; 445 close_seperate_dir();
446 free(f->name);
447 free(f->dname);
448 free(f);
449 f = head;
450 if (head == NULL) { //we can't go higher. Must be at start?
451 DEBUG_MAIN(("main: We are now trying to go above the highest level. We must be finished\n"));
452 break; //from main while loop
453 }
454 d_ptr = d_ptr->parent;
455 skip_child = 0;
456 }
457
458 if (item != NULL) {
459 DEBUG_MAIN(("main: Freeing memory used by item\n"));
460 _pst_freeItem(item);
461 item = NULL;
462 }
463
464 if (!skip_child)
465 d_ptr = d_ptr->next;
466 else
467 skip_child = 0;
468
469 if (d_ptr == NULL) {
470 DEBUG_MAIN(("main: d_ptr is now NULL\n"));
471 }
472 }
473 if (output_mode != OUTPUT_QUIET) printf("Finished.\n");
474 DEBUG_MAIN(("main: Finished.\n"));
475
476 pst_close(&pstfile);
477 // fclose(pstfile.fp);
478 while (f != NULL) {
479 if (f->output != NULL)
480 fclose(f->output);
481 free(f->name);
482 free(f->dname);
483
484 if (mode == MODE_KMAIL)
485 close_kmail_dir();
486 else if (mode == MODE_RECURSE)
487 close_recurse_dir();
488 else if (mode == MODE_SEPERATE)
489 // DO SOMETHING HERE
490 ;
491 head = f->next;
492 free (f);
493 f = head;
494 }
495
496 DEBUG_RET();
497
498 return 0;
499 } 499 }
500 void write_email_body(FILE *f, char *body) { 500 void write_email_body(FILE *f, char *body) {
501 char *n = body; 501 char *n = body;
502 // DEBUG_MAIN(("write_email_body(): \"%s\"\n", body)); 502 // DEBUG_MAIN(("write_email_body(): \"%s\"\n", body));
503 DEBUG_ENT("write_email_body"); 503 DEBUG_ENT("write_email_body");
504 while (n != NULL) { 504 while (n != NULL) {
505 if (strncmp(body, "From ", 5) == 0) 505 if (strncmp(body, "From ", 5) == 0)
506 fprintf(f, ">"); 506 fprintf(f, ">");
507 if ((n = strchr(body, '\n'))) { 507 if ((n = strchr(body, '\n'))) {
508 n++; 508 n++;
509 fwrite(body, n-body, 1, f); //write just a line 509 fwrite(body, n-body, 1, f); //write just a line
510 510
511 body = n; 511 body = n;
512 } 512 }
513 } 513 }
514 fwrite(body, strlen(body), 1, f); 514 fwrite(body, strlen(body), 1, f);
515 DEBUG_RET(); 515 DEBUG_RET();
516 } 516 }
517 char *removeCR (char *c) { 517 char *removeCR (char *c) {
518 // converts /r/n to /n 518 // converts /r/n to /n
519 char *a, *b; 519 char *a, *b;
520 DEBUG_ENT("removeCR"); 520 DEBUG_ENT("removeCR");
521 a = b = c; 521 a = b = c;
522 while (*a != '\0') { 522 while (*a != '\0') {
523 *b = *a; 523 *b = *a;
524 if (*a != '\r') 524 if (*a != '\r')
525 b++; 525 b++;
526 a++; 526 a++;
527 } 527 }
528 *b = '\0'; 528 *b = '\0';
529 DEBUG_RET(); 529 DEBUG_RET();
530 return c; 530 return c;
531 } 531 }
532 int usage() { 532 int usage() {
533 DEBUG_ENT("usage"); 533 DEBUG_ENT("usage");
534 version(); 534 version();
535 printf("Usage: %s [OPTIONS] {PST FILENAME}\n", prog_name); 535 printf("Usage: %s [OPTIONS] {PST FILENAME}\n", prog_name);
536 printf("OPTIONS:\n"); 536 printf("OPTIONS:\n");
537 printf("\t-c[v|l]\t- Set the Contact output mode. -cv = VCard, -cl = EMail list\n"); 537 printf("\t-c[v|l]\t- Set the Contact output mode. -cv = VCard, -cl = EMail list\n");
538 printf("\t-d\t- Debug to file. This is a binary log. Use readlog to print it\n"); 538 printf("\t-d\t- Debug to file. This is a binary log. Use readlog to print it\n");
539 printf("\t-h\t- Help. This screen\n"); 539 printf("\t-h\t- Help. This screen\n");
540 printf("\t-k\t- KMail. Output in kmail format\n"); 540 printf("\t-k\t- KMail. Output in kmail format\n");
541 printf("\t-M\t- MH. Write emails in the MH format\n"); 541 printf("\t-M\t- MH. Write emails in the MH format\n");
542 printf("\t-o\t- Output Dir. Directory to write files to. CWD is changed *after* opening pst file\n"); 542 printf("\t-o\t- Output Dir. Directory to write files to. CWD is changed *after* opening pst file\n");
543 printf("\t-q\t- Quiet. Only print error messages\n"); 543 printf("\t-q\t- Quiet. Only print error messages\n");
544 printf("\t-r\t- Recursive. Output in a recursive format\n"); 544 printf("\t-r\t- Recursive. Output in a recursive format\n");
545 printf("\t-S\t- Seperate. Write emails in the seperate format\n"); 545 printf("\t-S\t- Seperate. Write emails in the seperate format\n");
546 printf("\t-V\t- Version. Display program version\n"); 546 printf("\t-V\t- Version. Display program version\n");
547 printf("\t-w\t- Overwrite any output mbox files\n"); 547 printf("\t-w\t- Overwrite any output mbox files\n");
548 DEBUG_RET(); 548 DEBUG_RET();
549 return 0; 549 return 0;
550 } 550 }
551 int version() { 551 int version() {
552 DEBUG_ENT("version"); 552 DEBUG_ENT("version");
553 printf("ReadPST v%s\n", VERSION); 553 printf("ReadPST v%s\n", VERSION);
554 #if BYTE_ORDER == BIG_ENDIAN 554 #if BYTE_ORDER == BIG_ENDIAN
555 printf("Big Endian implementation being used.\n"); 555 printf("Big Endian implementation being used.\n");
556 #elif BYTE_ORDER == LITTLE_ENDIAN 556 #elif BYTE_ORDER == LITTLE_ENDIAN
557 printf("Little Endian implementation being used.\n"); 557 printf("Little Endian implementation being used.\n");
558 #else 558 #else
559 # error "Byte order not supported by this library" 559 # error "Byte order not supported by this library"
560 #endif 560 #endif
561 #ifdef __GNUC__ 561 #ifdef __GNUC__
562 printf("GCC %d.%d : %s %s\n", __GNUC__, __GNUC_MINOR__, __DATE__, __TIME__); 562 printf("GCC %d.%d : %s %s\n", __GNUC__, __GNUC_MINOR__, __DATE__, __TIME__);
563 #endif 563 #endif
564 DEBUG_RET(); 564 DEBUG_RET();
565 return 0; 565 return 0;
566 } 566 }
567 char *mk_kmail_dir(char *fname) { 567 char *mk_kmail_dir(char *fname) {
568 //change to that directory 568 //change to that directory
569 //make a directory based on OUTPUT_KMAIL_DIR_TEMPLATE 569 //make a directory based on OUTPUT_KMAIL_DIR_TEMPLATE
570 //allocate space for OUTPUT_TEMPLATE and form a char* with fname 570 //allocate space for OUTPUT_TEMPLATE and form a char* with fname
571 //return that value 571 //return that value
572 char *dir, *out_name, *index; 572 char *dir, *out_name, *index;
573 int x; 573 int x;
574 DEBUG_ENT("mk_kmail_dir"); 574 DEBUG_ENT("mk_kmail_dir");
575 if (kmail_chdir != NULL && chdir(kmail_chdir)) { 575 if (kmail_chdir != NULL && chdir(kmail_chdir)) {
576 x = errno; 576 x = errno;
577 DIE(("mk_kmail_dir: Cannot change to directory %s: %s\n", kmail_chdir, strerror(x))); 577 DIE(("mk_kmail_dir: Cannot change to directory %s: %s\n", kmail_chdir, strerror(x)));
578 } 578 }
579 dir = malloc(strlen(fname)+strlen(OUTPUT_KMAIL_DIR_TEMPLATE)+1); 579 dir = malloc(strlen(fname)+strlen(OUTPUT_KMAIL_DIR_TEMPLATE)+1);
580 sprintf(dir, OUTPUT_KMAIL_DIR_TEMPLATE, fname); 580 sprintf(dir, OUTPUT_KMAIL_DIR_TEMPLATE, fname);
581 dir = check_filename(dir); 581 dir = check_filename(dir);
582 if (D_MKDIR(dir)) { 582 if (D_MKDIR(dir)) {
583 //error occured 583 //error occured
584 if (errno != EEXIST) { 584 if (errno != EEXIST) {
585 x = errno; 585 x = errno;
586 DIE(("mk_kmail_dir: Cannot create directory %s: %s\n", dir, strerror(x))); 586 DIE(("mk_kmail_dir: Cannot create directory %s: %s\n", dir, strerror(x)));
587 } 587 }
588 } 588 }
589 kmail_chdir = realloc(kmail_chdir, strlen(dir)+1); 589 kmail_chdir = realloc(kmail_chdir, strlen(dir)+1);
590 strcpy(kmail_chdir, dir); 590 strcpy(kmail_chdir, dir);
591 free (dir); 591 free (dir);
592 592
593 //we should remove any existing indexes created by KMail, cause they might be different now 593 //we should remove any existing indexes created by KMail, cause they might be different now
594 index = malloc(strlen(fname)+strlen(KMAIL_INDEX)+1); 594 index = malloc(strlen(fname)+strlen(KMAIL_INDEX)+1);
595 sprintf(index, KMAIL_INDEX, fname); 595 sprintf(index, KMAIL_INDEX, fname);
596 unlink(index); 596 unlink(index);
597 free(index); 597 free(index);
598 598
599 out_name = malloc(strlen(fname)+strlen(OUTPUT_TEMPLATE)+1); 599 out_name = malloc(strlen(fname)+strlen(OUTPUT_TEMPLATE)+1);
600 sprintf(out_name, OUTPUT_TEMPLATE, fname); 600 sprintf(out_name, OUTPUT_TEMPLATE, fname);
601 DEBUG_RET(); 601 DEBUG_RET();
602 return out_name; 602 return out_name;
603 } 603 }
604 int close_kmail_dir() { 604 int close_kmail_dir() {
605 // change .. 605 // change ..
606 int x; 606 int x;
607 DEBUG_ENT("close_kmail_dir"); 607 DEBUG_ENT("close_kmail_dir");
608 if (kmail_chdir != NULL) { //only free kmail_chdir if not NULL. do not change directory 608 if (kmail_chdir != NULL) { //only free kmail_chdir if not NULL. do not change directory
609 free(kmail_chdir); 609 free(kmail_chdir);
610 kmail_chdir = NULL; 610 kmail_chdir = NULL;
611 } else { 611 } else {
612 if (chdir("..")) { 612 if (chdir("..")) {
613 x = errno; 613 x = errno;
614 DIE(("close_kmail_dir: Cannot move up dir (..): %s\n", strerror(x))); 614 DIE(("close_kmail_dir: Cannot move up dir (..): %s\n", strerror(x)));
615 } 615 }
616 } 616 }
617 DEBUG_RET(); 617 DEBUG_RET();
618 return 0; 618 return 0;
619 } 619 }
620 // this will create a directory by that name, then make an mbox file inside 620 // this will create a directory by that name, then make an mbox file inside
621 // that dir. any subsequent dirs will be created by name, and they will 621 // that dir. any subsequent dirs will be created by name, and they will
622 // contain mbox files 622 // contain mbox files
623 char *mk_recurse_dir(char *dir) { 623 char *mk_recurse_dir(char *dir) {
624 int x; 624 int x;
625 char *out_name; 625 char *out_name;
626 DEBUG_ENT("mk_recurse_dir"); 626 DEBUG_ENT("mk_recurse_dir");
627 dir = check_filename(dir); 627 dir = check_filename(dir);
628 if (D_MKDIR (dir)) { 628 if (D_MKDIR (dir)) {
629 if (errno != EEXIST) { // not an error because it exists 629 if (errno != EEXIST) { // not an error because it exists
630 x = errno; 630 x = errno;
631 DIE(("mk_recurse_dir: Cannot create directory %s: %s\n", dir, strerror(x))); 631 DIE(("mk_recurse_dir: Cannot create directory %s: %s\n", dir, strerror(x)));
632 } 632 }
633 } 633 }
634 if (chdir (dir)) { 634 if (chdir (dir)) {
635 x = errno; 635 x = errno;
636 DIE(("mk_recurse_dir: Cannot change to directory %s: %s\n", dir, strerror(x))); 636 DIE(("mk_recurse_dir: Cannot change to directory %s: %s\n", dir, strerror(x)));
637 } 637 }
638 out_name = malloc(strlen("mbox")+1); 638 out_name = malloc(strlen("mbox")+1);
639 strcpy(out_name, "mbox"); 639 strcpy(out_name, "mbox");
640 DEBUG_RET(); 640 DEBUG_RET();
641 return out_name; 641 return out_name;
642 } 642 }
643 int close_recurse_dir() { 643 int close_recurse_dir() {
644 int x; 644 int x;
645 DEBUG_ENT("close_recurse_dir"); 645 DEBUG_ENT("close_recurse_dir");
646 if (chdir("..")) { 646 if (chdir("..")) {
647 x = errno; 647 x = errno;
648 DIE(("close_recurse_dir: Cannot go up dir (..): %s\n", strerror(x))); 648 DIE(("close_recurse_dir: Cannot go up dir (..): %s\n", strerror(x)));
649 } 649 }
650 DEBUG_RET(); 650 DEBUG_RET();
651 return 0; 651 return 0;
652 } 652 }
653 char *mk_seperate_dir(char *dir, int overwrite) { 653 char *mk_seperate_dir(char *dir, int overwrite) {
654 #if !defined(WIN32) && !defined(__CYGWIN__) 654 #if !defined(WIN32) && !defined(__CYGWIN__)
655 DIR * sdir = NULL; 655 DIR * sdir = NULL;
656 struct dirent *dirent = NULL; 656 struct dirent *dirent = NULL;
657 struct stat *filestat = xmalloc(sizeof(struct stat)); 657 struct stat *filestat = xmalloc(sizeof(struct stat));
658 #endif 658 #endif
659 659
660 char *dir_name = NULL; 660 char *dir_name = NULL;
661 int x = 0, y = 0; 661 int x = 0, y = 0;
662 DEBUG_ENT("mk_seperate_dir"); 662 DEBUG_ENT("mk_seperate_dir");
663 /*#if defined(WIN32) || defined(__CYGWIN__) 663 /*#if defined(WIN32) || defined(__CYGWIN__)
664 DIE(("mk_seperate_dir: Win32 applications cannot use this function yet.\n")); 664 DIE(("mk_seperate_dir: Win32 applications cannot use this function yet.\n"));
665 #endif*/ 665 #endif*/
666 666
667 dir_name = xmalloc(strlen(dir)+10); 667 dir_name = xmalloc(strlen(dir)+10);
668 668
669 do { 669 do {
670 if (y == 0) 670 if (y == 0)
671 sprintf(dir_name, "%s", dir); 671 sprintf(dir_name, "%s", dir);
672 else 672 else
673 sprintf(dir_name, "%s" SEP_MAIL_FILE_TEMPLATE, dir, y); // enough for 9 digits allocated above 673 sprintf(dir_name, "%s" SEP_MAIL_FILE_TEMPLATE, dir, y); // enough for 9 digits allocated above
674 674
675 dir_name = check_filename(dir_name); 675 dir_name = check_filename(dir_name);
676 DEBUG_MAIN(("mk_seperate_dir: about to try creating %s\n", dir_name)); 676 DEBUG_MAIN(("mk_seperate_dir: about to try creating %s\n", dir_name));
677 if (D_MKDIR(dir_name)) { 677 if (D_MKDIR(dir_name)) {
678 if (errno != EEXIST) { // if there is an error, and it doesn't already exist 678 if (errno != EEXIST) { // if there is an error, and it doesn't already exist
679 x = errno; 679 x = errno;
680 DIE(("mk_seperate_dir: Cannot create directory %s: %s\n", dir, strerror(x))); 680 DIE(("mk_seperate_dir: Cannot create directory %s: %s\n", dir, strerror(x)));
681 } 681 }
682 } else { 682 } else {
683 break; 683 break;
684 } 684 }
685 y++; 685 y++;
686 } while (overwrite == 0); 686 } while (overwrite == 0);
687 687
688 if (chdir (dir_name)) { 688 if (chdir (dir_name)) {
689 x = errno; 689 x = errno;
690 DIE(("mk_recurse_dir: Cannot change to directory %s: %s\n", dir, strerror(x))); 690 DIE(("mk_recurse_dir: Cannot change to directory %s: %s\n", dir, strerror(x)));
691 } 691 }
692 692
693 if (overwrite) { 693 if (overwrite) {
694 // we should probably delete all files from this directory 694 // we should probably delete all files from this directory
695 #if !defined(WIN32) && !defined(__CYGWIN__) 695 #if !defined(WIN32) && !defined(__CYGWIN__)
696 if ((sdir = opendir("./")) == NULL) { 696 if ((sdir = opendir("./")) == NULL) {
697 WARN(("mk_seperate_dir: Cannot open dir \"%s\" for deletion of old contents\n", "./")); 697 WARN(("mk_seperate_dir: Cannot open dir \"%s\" for deletion of old contents\n", "./"));
698 } else { 698 } else {
699 while ((dirent = readdir(sdir)) != NULL) { 699 while ((dirent = readdir(sdir)) != NULL) {
700 if (lstat(dirent->d_name, filestat) != -1) 700 if (lstat(dirent->d_name, filestat) != -1)
701 if (S_ISREG(filestat->st_mode)) { 701 if (S_ISREG(filestat->st_mode)) {
702 if (unlink(dirent->d_name)) { 702 if (unlink(dirent->d_name)) {
703 y = errno; 703 y = errno;
704 DIE(("mk_seperate_dir: unlink returned error on file %s: %s\n", dirent->d_name, strerror(y))); 704 DIE(("mk_seperate_dir: unlink returned error on file %s: %s\n", dirent->d_name, strerror(y)));
705 } 705 }
706 } 706 }
707 } 707 }
708 } 708 }
709 #endif 709 #endif
710 } 710 }
711 711
712 // overwrite will never change during this function, it is just there so that 712 // overwrite will never change during this function, it is just there so that
713 // if overwrite is set, we only go through this loop once. 713 // if overwrite is set, we only go through this loop once.
714 714
715 // we don't return a filename here cause it isn't necessary. 715 // we don't return a filename here cause it isn't necessary.
716 DEBUG_RET(); 716 DEBUG_RET();
717 return NULL; 717 return NULL;
718 } 718 }
719 int close_seperate_dir() { 719 int close_seperate_dir() {
720 int x; 720 int x;
721 DEBUG_ENT("close_seperate_dir"); 721 DEBUG_ENT("close_seperate_dir");
722 if (chdir("..")) { 722 if (chdir("..")) {
723 x = errno; 723 x = errno;
724 DIE(("close_seperate_dir: Cannot go up dir (..): %s\n", strerror(x))); 724 DIE(("close_seperate_dir: Cannot go up dir (..): %s\n", strerror(x)));
725 } 725 }
726 DEBUG_RET(); 726 DEBUG_RET();
727 return 0; 727 return 0;
728 } 728 }
729 int mk_seperate_file(struct file_ll *f) { 729 int mk_seperate_file(struct file_ll *f) {
730 const int name_offset = 1; 730 const int name_offset = 1;
731 DEBUG_ENT("mk_seperate_file"); 731 DEBUG_ENT("mk_seperate_file");
732 DEBUG_MAIN(("mk_seperate_file: opening next file to save email\n")); 732 DEBUG_MAIN(("mk_seperate_file: opening next file to save email\n"));
733 if (f->email_count > 999999999) { // bigger than nine 9's 733 if (f->email_count > 999999999) { // bigger than nine 9's
734 DIE(("mk_seperate_file: The number of emails in this folder has become too high to handle")); 734 DIE(("mk_seperate_file: The number of emails in this folder has become too high to handle"));
735 } 735 }
736 sprintf(f->name, SEP_MAIL_FILE_TEMPLATE, f->email_count + name_offset); 736 sprintf(f->name, SEP_MAIL_FILE_TEMPLATE, f->email_count + name_offset);
737 if (f->output != NULL) 737 if (f->output != NULL)
738 fclose(f->output); 738 fclose(f->output);
739 f->output = NULL; 739 f->output = NULL;
740 f->name = check_filename(f->name); 740 f->name = check_filename(f->name);
741 if ((f->output = fopen(f->name, "w")) == NULL) { 741 if ((f->output = fopen(f->name, "w")) == NULL) {
742 DIE(("mk_seperate_file: Cannot open file to save email \"%s\"\n", f->name)); 742 DIE(("mk_seperate_file: Cannot open file to save email \"%s\"\n", f->name));
743 } 743 }
744 DEBUG_RET(); 744 DEBUG_RET();
745 return 0; 745 return 0;
746 } 746 }
747 char *my_stristr(char *haystack, char *needle) { 747 char *my_stristr(char *haystack, char *needle) {
748 // my_stristr varies from strstr in that its searches are case-insensitive 748 // my_stristr varies from strstr in that its searches are case-insensitive
749 char *x=haystack, *y=needle, *z = NULL; 749 char *x=haystack, *y=needle, *z = NULL;
750 DEBUG_ENT("my_stristr"); 750 DEBUG_ENT("my_stristr");
751 if (haystack == NULL || needle == NULL) 751 if (haystack == NULL || needle == NULL)
752 return NULL; 752 return NULL;
753 while (*y != '\0' && *x != '\0') { 753 while (*y != '\0' && *x != '\0') {
754 if (tolower(*y) == tolower(*x)) { 754 if (tolower(*y) == tolower(*x)) {
755 // move y on one 755 // move y on one
756 y++; 756 y++;
757 if (z == NULL) { 757 if (z == NULL) {
758 z = x; // store first position in haystack where a match is made 758 z = x; // store first position in haystack where a match is made
759 } 759 }
760 } else { 760 } else {
761 y = needle; // reset y to the beginning of the needle 761 y = needle; // reset y to the beginning of the needle
762 z = NULL; // reset the haystack storage point 762 z = NULL; // reset the haystack storage point
763 } 763 }
764 x++; // advance the search in the haystack 764 x++; // advance the search in the haystack
765 } 765 }
766 DEBUG_RET(); 766 DEBUG_RET();
767 return z; 767 return z;
768 } 768 }
769 char *check_filename(char *fname) { 769 char *check_filename(char *fname) {
770 char *t = fname; 770 char *t = fname;
771 DEBUG_ENT("check_filename"); 771 DEBUG_ENT("check_filename");
772 if (t == NULL) { 772 if (t == NULL) {
773 DEBUG_RET();
774 return fname;
775 }
776 while ((t = strpbrk(t, "/\\:")) != NULL) {
777 // while there are characters in the second string that we don't want
778 *t = '_'; //replace them with an underscore
779 }
773 DEBUG_RET(); 780 DEBUG_RET();
774 return fname; 781 return fname;
775 }
776 while ((t = strpbrk(t, "/\\:")) != NULL) {
777 // while there are characters in the second string that we don't want
778 *t = '_'; //replace them with an underscore
779 }
780 DEBUG_RET();
781 return fname;
782 } 782 }
783 char *rfc2426_escape(char *str) { 783 char *rfc2426_escape(char *str) {
784 static char* buf = NULL; 784 static char* buf = NULL;
785 char *ret, *a, *b; 785 char *ret, *a, *b;
786 int x = 0, y, z; 786 int x = 0, y, z;
787 DEBUG_ENT("rfc2426_escape"); 787 DEBUG_ENT("rfc2426_escape");
788 if (str == NULL) 788 if (str == NULL)
789 ret = str; 789 ret = str;
790 else {
791
792 // calculate space required to escape all the following characters
793 x = strlen(str) +(y=(chr_count(str, ',')*2) + (chr_count(str, '\\')*2) + (chr_count(str, ';')*2) + (chr_count(str, '\n')*2));
794 z = chr_count(str, '\r');
795 if (y == 0 && z == 0)
796 // there isn't any extra space required
797 ret = str;
798 else { 790 else {
799 buf = (char*) realloc(buf, x+1); 791
800 a = str; 792 // calculate space required to escape all the following characters
801 b = buf; 793 x = strlen(str) +(y=(chr_count(str, ',')*2) + (chr_count(str, '\\')*2) + (chr_count(str, ';')*2) + (chr_count(str, '\n')*2));
802 while (*a != '\0') { 794 z = chr_count(str, '\r');
803 switch(*a) { 795 if (y == 0 && z == 0)
804 case ',' : 796 // there isn't any extra space required
805 case '\\': 797 ret = str;
806 case ';' : 798 else {
807 case '\n': 799 buf = (char*) realloc(buf, x+1);
808 *(b++)='\\'; 800 a = str;
809 *b=*a; 801 b = buf;
810 break; 802 while (*a != '\0') {
811 case '\r': 803 switch(*a) {
812 break; 804 case ',' :
813 default: 805 case '\\':
814 *b=*a; 806 case ';' :
815 } 807 case '\n':
816 b++; 808 *(b++)='\\';
817 a++; 809 *b=*a;
818 } 810 break;
819 *b = '\0'; 811 case '\r':
820 ret = buf; 812 break;
821 } 813 default:
822 } 814 *b=*a;
823 DEBUG_RET(); 815 }
824 return ret; 816 b++;
817 a++;
818 }
819 *b = '\0';
820 ret = buf;
821 }
822 }
823 DEBUG_RET();
824 return ret;
825 } 825 }
826 int chr_count(char *str, char x) { 826 int chr_count(char *str, char x) {
827 int r = 0; 827 int r = 0;
828 while (*str != '\0') { 828 while (*str != '\0') {
829 if (*str == x) 829 if (*str == x)
830 r++; 830 r++;
831 str++; 831 str++;
832 } 832 }
833 return r; 833 return r;
834 } 834 }
835 char *rfc2425_datetime_format(FILETIME *ft) { 835 char *rfc2425_datetime_format(FILETIME *ft) {
836 static char * buffer = NULL; 836 static char * buffer = NULL;
837 struct tm *stm = NULL; 837 struct tm *stm = NULL;
838 DEBUG_ENT("rfc2425_datetime_format"); 838 DEBUG_ENT("rfc2425_datetime_format");
839 if (buffer == NULL) 839 if (buffer == NULL)
840 buffer = malloc(30); // should be enough for the date as defined below 840 buffer = malloc(30); // should be enough for the date as defined below
841 841
842 stm = fileTimeToStructTM(ft); 842 stm = fileTimeToStructTM(ft);
843 //Year[4]-Month[2]-Day[2] Hour[2]:Min[2]:Sec[2] 843 //Year[4]-Month[2]-Day[2] Hour[2]:Min[2]:Sec[2]
844 if (strftime(buffer, 30, "%Y-%m-%dT%H:%M:%SZ", stm)==0) { 844 if (strftime(buffer, 30, "%Y-%m-%dT%H:%M:%SZ", stm)==0) {
845 DEBUG_INFO(("Problem occured formatting date\n")); 845 DEBUG_INFO(("Problem occured formatting date\n"));
846 } 846 }
847 DEBUG_RET(); 847 DEBUG_RET();
848 return buffer; 848 return buffer;
849 } 849 }
850 char *rfc2445_datetime_format(FILETIME *ft) { 850 char *rfc2445_datetime_format(FILETIME *ft) {
851 static char* buffer = NULL; 851 static char* buffer = NULL;
852 struct tm *stm = NULL; 852 struct tm *stm = NULL;
853 DEBUG_ENT("rfc2445_datetime_format"); 853 DEBUG_ENT("rfc2445_datetime_format");
854 if (buffer == NULL) 854 if (buffer == NULL)
855 buffer = malloc(30); // should be enough 855 buffer = malloc(30); // should be enough
856 stm = fileTimeToStructTM(ft); 856 stm = fileTimeToStructTM(ft);
857 if (strftime(buffer, 30, "%Y%m%dT%H%M%SZ", stm)==0) { 857 if (strftime(buffer, 30, "%Y%m%dT%H%M%SZ", stm)==0) {
858 DEBUG_INFO(("Problem occured formatting date\n")); 858 DEBUG_INFO(("Problem occured formatting date\n"));
859 } 859 }
860 DEBUG_RET(); 860 DEBUG_RET();
861 return buffer; 861 return buffer;
862 } 862 }
863 // The sole purpose of this function is to bypass the pseudo-header prologue 863 // The sole purpose of this function is to bypass the pseudo-header prologue
864 // that Microsoft Outlook inserts at the beginning of the internet email 864 // that Microsoft Outlook inserts at the beginning of the internet email
865 // headers for emails stored in their "Personal Folders" files. 865 // headers for emails stored in their "Personal Folders" files.
866 char *skip_header_prologue(char *headers) { 866 char *skip_header_prologue(char *headers) {
921 DEBUG_MAIN(("write_inline_attachment: Attachment Size is %i\n", item->current_attach->size)); 921 DEBUG_MAIN(("write_inline_attachment: Attachment Size is %i\n", item->current_attach->size));
922 DEBUG_MAIN(("write_inline_attachment: Attachment Pointer is %p\n", item->current_attach->data)); 922 DEBUG_MAIN(("write_inline_attachment: Attachment Pointer is %p\n", item->current_attach->data));
923 if (current_attach->data != NULL) { 923 if (current_attach->data != NULL) {
924 if ((enc = base64_encode (current_attach->data, current_attach->size)) == NULL) { 924 if ((enc = base64_encode (current_attach->data, current_attach->size)) == NULL) {
925 DEBUG_MAIN(("write_inline_attachment: ERROR base64_encode returned NULL. Must have failed\n")); 925 DEBUG_MAIN(("write_inline_attachment: ERROR base64_encode returned NULL. Must have failed\n"));
926 current_attach = current_attach->next;
927 return; 926 return;
928 } 927 }
929 } 928 }
930 if (boundary) { 929 if (boundary) {
931 fprintf(f_output, "\n--%s\n", boundary); 930 fprintf(f_output, "\n--%s\n", boundary);
1042 // when we see a \n\n or \r\n\r\n 1041 // when we see a \n\n or \r\n\r\n
1043 temp = strstr(item->email->header, "\n\n"); 1042 temp = strstr(item->email->header, "\n\n");
1044 1043
1045 if (temp != NULL) { 1044 if (temp != NULL) {
1046 DEBUG_MAIN(("write_normal_email: Found body text in header\n")); 1045 DEBUG_MAIN(("write_normal_email: Found body text in header\n"));
1047 temp += 2; // get past the \n\n
1048 *temp = '\0'; 1046 *temp = '\0';
1047 } else {
1048 temp = item->email->header + strlen(item->email->header) - 1;
1049 if(*temp == '\n')
1050 *temp = '\0';
1049 } 1051 }
1050 1052
1051 if (mode != MODE_SEPERATE) { 1053 if (mode != MODE_SEPERATE) {
1052 char *soh = NULL; // real start of headers. 1054 char *soh = NULL; // real start of headers.
1053 // don't put rubbish in if we are doing seperate 1055 // don't put rubbish in if we are doing seperate
1054 fprintf(f_output, "From \"%s\" %s\n", item->email->outlook_sender_name, c_time); 1056 fprintf(f_output, "From \"%s\" %s\n", item->email->outlook_sender_name, c_time);
1055 soh = skip_header_prologue(item->email->header); 1057 soh = skip_header_prologue(item->email->header);
1056 fprintf(f_output, "%s\n\n", soh); 1058 fprintf(f_output, "%s\n", soh);
1057 } else { 1059 } else {
1058 fprintf(f_output, "%s\n", item->email->header); 1060 fprintf(f_output, "%s\n", item->email->header);
1059 } 1061 }
1060 } else { 1062 } else {
1061 //make up our own header! 1063 //make up our own header!