comparison src/pst2dii.cpp.in @ 63:cfd6175f9334

Start work on pst2dii to convert to Summation dii load file format.
author Carl Byington <carl@five-ten-sg.com>
date Sat, 23 Feb 2008 14:36:17 -0800
parents
children 2c6040b6e8f8
comparison
equal deleted inserted replaced
62:ee4e0d00bc94 63:cfd6175f9334
1 /*
2
3 Copyright (c) 2008 Carl Byington - 510 Software Group, released under
4 the GPL version 2 or any later version at your choice available at
5 http://www.fsf.org/licenses/gpl.txt
6
7 Based on readpst.c by David Smith
8
9 */
10 #include "gd.h"
11 #include <stdio.h>
12 #include <iostream>
13 #include <unistd.h>
14 #include <string>
15 #include <vector>
16
17 using namespace std;
18
19 extern "C" {
20 #include "define.h"
21 #include "libstrfunc.h"
22 #include "libpst.h"
23 #include "common.h"
24 #include "timeconv.h"
25 #include "lzfu.h"
26 }
27
28 struct file_ll {
29 string name;
30 int32_t stored_count;
31 int32_t email_count;
32 int32_t skip_count;
33 int32_t type;
34 file_ll() {
35 stored_count = 0;
36 email_count = 0;
37 skip_count = 0;
38 type - 0;
39 };
40 };
41
42
43 // global settings
44 char* convert = "@CONVERT@"; // fully qualified path of the convert program from image magick
45 char* prog_name = NULL; // our arg0 name
46 char* bates_prefix = ""; // string to prefix bates numbers
47 int bates_index = 0; // current bates sequence
48 char* output_directory = ".";
49 char* output_file = "load.dii";
50 char* font_file = NULL;
51 int bates_color = 0xff0000; // color of bates header stamp
52 int email_sequence = 0; // current pdf sequence number
53 char pdf_name[PATH_MAX]; // current pdf file name
54 FILE* dii_file = NULL; // the output dii load file
55 pst_file pstfile; // the input pst file
56
57 // pdf writer globals
58 bool pdf_open = false; // is pdf writer started
59 char* pst_folder; // current folder name
60 int page_sequence; // current page number
61 string conversion; // conversion command
62 vector<string> png_names;
63
64 // png writer globals
65 bool png_open = false; // is current page open
66 int line_height; // in pixels
67 int char_width; // in pixels
68 int col_number, col_max; // in characters
69 int line_number, line_max; // lines per page
70 int x_position, y_position; // in pixels
71 int black, red; // text colors
72 gdImagePtr image; // current gd image
73
74 const int DPI = 300;
75 const double sz = 10.0;
76 const int margin = DPI/2;
77 const int LINE_SIZE = 2000;
78 const int PAGE_WIDTH = DPI*17/2;
79 const int PAGE_HEIGHT = DPI*11;
80
81 // max size of the c_time char*. It will store the date of the email
82 #define C_TIME_SIZE 500
83
84 static void open_png();
85 static void close_png();
86
87
88 static int version();
89 static int version()
90 {
91 printf("pst2dii v%s\n", VERSION);
92 #if BYTE_ORDER == BIG_ENDIAN
93 printf("Big Endian implementation being used.\n");
94 #elif BYTE_ORDER == LITTLE_ENDIAN
95 printf("Little Endian implementation being used.\n");
96 #else
97 # error "Byte order not supported by this library"
98 #endif
99 #ifdef __GNUC__
100 printf("GCC %d.%d : %s %s\n", __GNUC__, __GNUC_MINOR__, __DATE__, __TIME__);
101 #endif
102 return 0;
103 }
104
105
106 static int usage();
107 static int usage()
108 {
109 version();
110 printf("Usage: %s [OPTIONS] {PST FILENAME}\n", prog_name);
111 printf("OPTIONS:\n");
112 printf("\t-B bates-prefix \t- Set the bates prefix string\n");
113 printf("\t-O dii-output-file\t- Set the dii load file output filename\n");
114 printf("\t-V \t- Version. Display program version\n");
115 printf("\t-b bates-number \t- Set the starting bates sequence number\n");
116 printf("\t-c bates-color \t- Specify the color of the bates stamps as 6 digit hex\n");
117 printf("\t-d filename \t- Debug to file. This is a binary log. Use readpstlog to print it.\n");
118 printf("\t-f ttf-font-file \t- Set the font file\n");
119 printf("\t-h \t- Help. This screen\n");
120 printf("\t-o dirname \t- Output directory to write files to.\n");
121 return 0;
122 }
123
124
125 static char *removeCR (char *c);
126 static char *removeCR (char *c) {
127 // converts /r/n to /n
128 char *a, *b;
129 DEBUG_ENT("removeCR");
130 a = b = c;
131 while (*a != '\0') {
132 *b = *a;
133 if (*a != '\r')
134 b++;
135 a++;
136 }
137 *b = '\0';
138 DEBUG_RET();
139 return c;
140 }
141
142
143 // The sole purpose of this function is to bypass the pseudo-header prologue
144 // that Microsoft Outlook inserts at the beginning of the internet email
145 // headers for emails stored in their "Personal Folders" files.
146 static char *skip_header_prologue(char *headers);
147 static char *skip_header_prologue(char *headers) {
148 const char *bad = "Microsoft Mail Internet Headers";
149 if (strncmp(headers, bad, strlen(bad)) == 0) {
150 // Found the offensive header prologue
151 char *pc = strchr(headers, '\n');
152 return pc + 1;
153 }
154 return headers;
155 }
156
157
158 static void check_filename(string &fname);
159 static void check_filename(string &fname) {
160 char *t = strdup(fname.c_str());
161 DEBUG_ENT("check_filename");
162 if (!t) {
163 DEBUG_RET();
164 return;
165 }
166 char *tt = t;
167 bool fixed = false;
168 while (t = strpbrk(t, " /\\:")) {
169 // while there are characters in the second string that we don't want
170 *t = '_'; //replace them with an underscore
171 fixed = true;
172 }
173 if (fixed) fname = string(tt);
174 free(tt);
175 DEBUG_RET();
176 }
177
178
179 static string write_separate_attachment(string fname, pst_item_attach* current_attach, int attach_num, pst_file* pst);
180 static string write_separate_attachment(string fname, pst_item_attach* current_attach, int attach_num, pst_file* pst)
181 {
182 FILE *fp = NULL;
183 int x = 0;
184 char *temp = NULL;
185
186 // If there is a long filename (filename2) use that, otherwise
187 // use the 8.3 filename (filename1)
188 char *attach_filename = (current_attach->filename2) ? current_attach->filename2
189 : current_attach->filename1;
190 DEBUG_ENT("write_separate_attachment");
191 check_filename(fname);
192 const char* f_name = fname.c_str();
193 DEBUG_EMAIL(("dirname=%s, pathname=%s, filename=%s\n", output_directory, f_name, attach_filename));
194 int len = strlen(output_directory) + 1 + strlen(f_name) + 15;
195 if (!attach_filename) {
196 // generate our own (dummy) filename for the attachement
197 temp = (char*)xmalloc(len);
198 sprintf(temp, "%s/%s_attach%i", output_directory, f_name, attach_num);
199 } else {
200 // have an attachment name, make sure it's unique
201 temp = (char*)xmalloc(len+strlen(attach_filename));
202 do {
203 if (fp) fclose(fp);
204 if (x == 0)
205 sprintf(temp, "%s/%s_%s", output_directory, f_name, attach_filename);
206 else
207 sprintf(temp, "%s/%s_%s-%i", output_directory, f_name, attach_filename, x);
208 } while ((fp = fopen(temp, "r")) && ++x < 99999999);
209 if (x > 99999999) {
210 DIE(("error finding attachment name. exhausted possibilities to %s\n", temp));
211 }
212 }
213 DEBUG_EMAIL(("Saving attachment to %s\n", temp));
214 if (!(fp = fopen(temp, "wb"))) {
215 WARN(("write_separate_attachment: Cannot open attachment save file \"%s\"\n", temp));
216 } else {
217 if (current_attach->data)
218 fwrite(current_attach->data, 1, current_attach->size, fp);
219 else {
220 (void)pst_attach_to_file(pst, current_attach, fp);
221 }
222 fclose(fp);
223 }
224 string rc(temp);
225 if (temp) free(temp);
226 DEBUG_RET();
227 return rc;
228 }
229
230
231 static void print_pdf_short(char *line, int len, int color);
232 static void print_pdf_short(char *line, int len, int color)
233 {
234 if (line_number >= line_max) {
235 close_png();
236 open_png();
237 }
238 int brect[8];
239 gdFTStringExtra strex;
240 strex.flags = gdFTEX_RESOLUTION;
241 strex.linespacing = 1.20;
242 strex.charmap = 0;
243 strex.hdpi = DPI;
244 strex.vdpi = DPI;
245 char x = line[len];
246 line[len] = '\0';
247 char *p;
248 char *l = line;
249 while (p = strchr(l, '&')) {
250 *p = '\0';
251 char *err = gdImageStringFTEx(image, &brect[0], color, font_file, sz, 0.0, x_position, y_position, l, &strex);
252 if (err) printf(err);
253 x_position += (brect[2]-brect[6]);
254 l = p+1;
255 err = gdImageStringFTEx(image, &brect[0], color, font_file, sz, 0.0, x_position, y_position, "&amp;", &strex);
256 if (err) printf(err);
257 x_position += (brect[2]-brect[6]);
258 }
259 char *err = gdImageStringFTEx(image, &brect[0], color, font_file, sz, 0.0, x_position, y_position, l, &strex);
260 if (err) printf(err);
261 line[len] = x;
262 x_position += (brect[2]-brect[6]);
263 col_number += len;
264 }
265
266
267 static void print_pdf_single(char *line, int color);
268 static void print_pdf_single(char *line, int color)
269 {
270 int n = strlen(line);
271 while (n) {
272 int m = col_max - col_number; // number of chars that will fit on this line
273 m = (n > m) ? m : n;
274 print_pdf_short(line, m, color);
275 line += m;
276 n -= m;
277 if (n) {
278 y_position += line_height;
279 line_number += 1;
280 x_position = margin;
281 col_number = 0;
282 }
283 }
284 }
285
286
287 static void print_pdf_only(char *line, int color);
288 static void print_pdf_only(char *line, int color)
289 {
290 char *p;
291 while (p = strchr(line, '\n')) {
292 *p = '\0';
293 print_pdf_single(line, color);
294 *p = '\n';
295 line = p+1;
296 y_position += line_height;
297 line_number += 1;
298 x_position = margin;
299 col_number = 0;
300 }
301 print_pdf_single(line, color);
302 }
303
304
305 static void print_pdf(char *line);
306 static void print_pdf(char *line)
307 {
308 fwrite(line, 1, strlen(line), dii_file);
309 print_pdf_only(line, black);
310 }
311
312
313 static void open_png()
314 {
315 if (!png_open) {
316 png_open = true;
317 int brect[8];
318 image = gdImageCreate(PAGE_WIDTH, PAGE_HEIGHT);
319 int w = gdImageColorAllocate(image, 255, 255, 255); // background color first one allocated
320 black = gdImageColorAllocate(image, 0, 0, 0);
321 int r = (bates_color & 0xff0000) >> 16;
322 int g = (bates_color & 0x00ff00) >> 8;
323 int b = (bates_color & 0x0000ff);
324 red = gdImageColorAllocate(image, r, g, b);
325
326 gdFTStringExtra strex;
327 strex.flags = gdFTEX_RESOLUTION;
328 strex.linespacing = 1.20;
329 strex.charmap = 0;
330 strex.hdpi = DPI;
331 strex.vdpi = DPI;
332
333 char line[LINE_SIZE];
334 char *err = gdImageStringFTEx(NULL, &brect[0], black, font_file, sz, 0.0, margin, margin, "LMgqQ", &strex);
335 if (err) printf(err);
336 line_height = (brect[3]-brect[7]) * 12/10;
337 char_width = (brect[2]-brect[6]) / 5;
338 col_number = 0;
339 col_max = (PAGE_WIDTH - margin*2) / char_width;
340 line_number = 0;
341 line_max = (PAGE_HEIGHT - margin*2) / line_height;
342 x_position = margin;
343 y_position = margin + line_height;
344 snprintf(line, sizeof(line), "%s%06d\n", bates_prefix, bates_index++);
345 print_pdf_only(line, red);
346 print_pdf_only(pst_folder, red);
347 }
348 }
349
350
351 static void close_png()
352 {
353 if (png_open) {
354 png_open = false;
355 char fn[PATH_MAX];
356 snprintf(fn, sizeof(fn), "page%d.png", ++page_sequence);
357 FILE *pngout = fopen(fn, "wb");
358 if (pngout) {
359 gdImagePng(image, pngout);
360 fclose(pngout);
361 }
362 gdImageDestroy(image); // free memory
363 png_names.push_back(fn);
364 conversion += string(" ") + fn;
365 }
366 }
367
368
369 static void open_pdf(char *line);
370 static void open_pdf(char *line)
371 {
372 pst_folder = line;
373 page_sequence = 0;
374 conversion = string(convert);
375 png_names.clear();
376 open_png();
377 snprintf(pdf_name, sizeof(pdf_name), "dii%06d", ++email_sequence);
378 fprintf(dii_file, "\n@T %s\n", pdf_name);
379 snprintf(pdf_name, sizeof(pdf_name), "%s/dii%06d.pdf", output_directory, email_sequence);
380 }
381
382
383 static void close_pdf();
384 static void close_pdf()
385 {
386 close_png();
387 conversion += string(" ") + pdf_name;
388 system(conversion.c_str());
389 for (vector<string>::iterator i=png_names.begin(); i!=png_names.end(); i++) {
390 remove((*i).c_str());
391 }
392 fprintf(dii_file, "@D %s\n", pdf_name);
393 }
394
395
396 static void write_simple(char *tag, const char *value);
397 static void write_simple(char *tag, const char *value)
398 {
399 if (value) fprintf(dii_file, "@%s %s\n", tag, value);
400 }
401
402
403 static void write_simple(char *tag, string value);
404 static void write_simple(char *tag, string value)
405 {
406 fprintf(dii_file, "@%s %s\n", tag, value.c_str());
407 }
408
409
410 static void write_simple(char *tag, const char *value, const char *value2);
411 static void write_simple(char *tag, const char *value, const char *value2)
412 {
413 if (value) {
414 if (value2) fprintf(dii_file, "@%s \"%s\" <%s>\n", tag, value, value2);
415 else fprintf(dii_file, "@%s \"%s\"\n", tag, value);
416 }
417 }
418
419
420 static string extract_header(char *headers, char *field);
421 static string extract_header(char *headers, char *field)
422 {
423 string rc;
424 int len = strlen(field) + 4;
425 char f[len];
426 snprintf(f, len, "\n%s: ", field);
427 char *p = strstr(headers, f);
428 if (p) {
429 p += strlen(f);
430 char *n = strchr(p, '\n');
431 if (n) {
432 *n = '\0';
433 rc = string(p);
434 *n = '\n';
435 }
436 else {
437 rc = string(p);
438 }
439 }
440 return rc;
441 }
442
443
444 static void write_normal_email(file_ll &f, pst_item* item, pst_file* pst);
445 static void write_normal_email(file_ll &f, pst_item* item, pst_file* pst)
446 {
447 DEBUG_ENT("write_normal_email");
448 char *soh = NULL; // real start of headers.
449 if (item->email->header) {
450 // some of the headers we get from the file are not properly defined.
451 // they can contain some email stuff too. We will cut off the header
452 // when we see a \n\n or \r\n\r\n
453 removeCR(item->email->header);
454 char *temp = strstr(item->email->header, "\n\n");
455 if (temp) {
456 DEBUG_EMAIL(("Found body text in header\n"));
457 temp[1] = '\0'; // stop after first \n
458 }
459 soh = skip_header_prologue(item->email->header);
460 }
461
462 char folder_line[LINE_SIZE];
463 char line[LINE_SIZE];
464 // reset pdf writer to new file
465 int bates = bates_index; // save starting index
466 snprintf(folder_line, sizeof(folder_line), "pst folder = %s\n", f.name.c_str());
467 open_pdf(folder_line);
468
469 // start printing this email
470 fprintf(dii_file, "@FOLDERNAME %s\n", f.name.c_str());
471 string myfrom = extract_header(soh, "From");
472 string myto = extract_header(soh, "To");
473 string mycc = extract_header(soh, "Cc");
474 string mybcc = extract_header(soh, "Bcc");
475 if (myfrom.empty()) write_simple("FROM", item->email->outlook_sender_name, item->email->sender_address);
476 else write_simple("FROM", myfrom);
477 if (myto.empty()) write_simple("TO", item->email->sentto_address, item->email->recip_address);
478 else write_simple("TO", myto);
479 if (mycc.empty()) write_simple("CC", item->email->cc_address);
480 else write_simple("CC", mycc);
481 if (mybcc.empty()) write_simple("BCC", item->email->bcc_address);
482 else write_simple("BCC", mybcc);
483 if (item->email->sent_date) {
484 time_t t = fileTimeToUnixTime(item->email->sent_date, NULL);
485 char c_time[C_TIME_SIZE];
486 strftime(c_time, C_TIME_SIZE, "%F +0000", gmtime(&t));
487 write_simple("DATESENT", c_time);
488 strftime(c_time, C_TIME_SIZE, "%T +0000", gmtime(&t));
489 write_simple("TIMESENT", c_time);
490 }
491 if (item->email->arrival_date) {
492 time_t t = fileTimeToUnixTime(item->email->arrival_date, NULL);
493 char c_time[C_TIME_SIZE];
494 strftime(c_time, C_TIME_SIZE, "%F +0000", gmtime(&t));
495 write_simple("DATERCVD", c_time);
496 strftime(c_time, C_TIME_SIZE, "%T +0000", gmtime(&t));
497 write_simple("TIMERCVD", c_time);
498 }
499 if (item->email->subject) {
500 write_simple("SUBJECT", item->email->subject->subj);
501 }
502 write_simple("MSGID", item->email->messageid);
503 if (item->email->flag) {
504 write_simple("READ", (item->email->flag & 1) ? "Y" : "N");
505 }
506
507 DEBUG_EMAIL(("About to print Header\n"));
508 fprintf(dii_file, "@HEADER\n");
509
510 if (item && item->email && item->email->subject && item->email->subject->subj) {
511 DEBUG_EMAIL(("item->email->subject->subj = %s\n", item->email->subject->subj));
512 }
513
514 if (soh) {
515 // Now, write out the header...
516 print_pdf(soh);
517 int len = strlen(soh);
518 if (!len || (soh[len-1] != '\n')) {
519 snprintf(line, sizeof(line), "\n");
520 print_pdf(line);
521 }
522
523 } else {
524 //make up our own headers
525 char *temp = item->email->outlook_sender;
526 if (!temp) temp = "";
527 snprintf(line, sizeof(line), "From: \"%s\" <%s>\n", item->email->outlook_sender_name, temp);
528 print_pdf(line);
529
530 if (item->email->subject) {
531 snprintf(line, sizeof(line), "Subject: %s\n", item->email->subject->subj);
532 } else {
533 snprintf(line, sizeof(line), "Subject: \n");
534 }
535 print_pdf(line);
536
537 snprintf(line, sizeof(line), "To: %s\n", item->email->sentto_address);
538 print_pdf(line);
539
540 if (item->email->cc_address) {
541 snprintf(line, sizeof(line), "Cc: %s\n", item->email->cc_address);
542 print_pdf(line);
543 }
544
545 if (item->email->sent_date) {
546 time_t em_time = fileTimeToUnixTime(item->email->sent_date, 0);
547 char c_time[C_TIME_SIZE];
548 strftime(c_time, C_TIME_SIZE, "%a, %d %b %Y %H:%M:%S %z", gmtime(&em_time));
549 snprintf(line, sizeof(line), "Date: %s\n", c_time);
550 print_pdf(line);
551 }
552 }
553 snprintf(line, sizeof(line), "\n");
554 print_pdf_only(line, black);
555 fprintf(dii_file, "@HEADER-END\n");
556
557 DEBUG_EMAIL(("About to print Body\n"));
558 fprintf(dii_file, "@EMAIL-BODY\n");
559 if (item->email->body) {
560 removeCR(item->email->body);
561 print_pdf(item->email->body);
562 } else if (item->email->htmlbody) {
563 removeCR(item->email->htmlbody);
564 print_pdf(item->email->htmlbody);
565 } else if (item->email->encrypted_body || item->email->encrypted_htmlbody) {
566 print_pdf("The body of this email is encrypted. This isn't supported yet, but the body is now an attachment\n");
567 }
568 fprintf(dii_file, "@EMAIL-END\n");
569
570 int attach_num = 0;
571 for (pst_item_attach* current_attach = item->attach; current_attach; current_attach = current_attach->next) {
572 DEBUG_EMAIL(("Attempting Attachment encoding\n"));
573 if (!current_attach->data) {
574 DEBUG_EMAIL(("Data of attachment is NULL!. Size is supposed to be %i\n", current_attach->size));
575 }
576 string an = write_separate_attachment(f.name, current_attach, ++attach_num, pst);
577 fprintf(dii_file, "@EATTACH %s\n", an.c_str());
578 }
579 close_pdf();
580 fprintf(dii_file, "@BATESBEG %d\n", bates);
581 fprintf(dii_file, "@BATESEND %d\n", bates_index-1);
582 DEBUG_RET();
583 }
584
585
586 static void create_enter_dir(file_ll &f, file_ll *parent, pst_item *item);
587 static void create_enter_dir(file_ll &f, file_ll *parent, pst_item *item)
588 {
589 f.email_count = 0;
590 f.skip_count = 0;
591 f.type = item->type;
592 f.stored_count = (item->folder) ? item->folder->email_count : 0;
593 f.name = ((parent) ? parent->name + "/" : "") + string(item->file_as);
594 }
595
596
597 static void close_enter_dir(file_ll &f);
598 static void close_enter_dir(file_ll &f)
599 {
600 }
601
602
603 static void process(pst_item *outeritem, file_ll *parent, pst_desc_ll *d_ptr);
604 static void process(pst_item *outeritem, file_ll *parent, pst_desc_ll *d_ptr)
605 {
606 file_ll ff;
607 pst_item *item = NULL;
608 DEBUG_ENT("process");
609 create_enter_dir(ff, parent, outeritem);
610 while (d_ptr) {
611 if (d_ptr->desc) {
612 item = pst_parse_item(&pstfile, d_ptr);
613 DEBUG_INFO(("item pointer is %p\n", item));
614 if (item) {
615 if (item->message_store) {
616 // there should only be one message_store, and we have already done it
617 DIE(("main: A second message_store has been found. Sorry, this must be an error.\n"));
618 }
619
620 if (item->folder && d_ptr->child ) {
621 //if this is a non-empty folder other than deleted items, we want to recurse into it
622 fprintf(stderr, "entering folder %s\n", item->file_as);
623 process(item, &ff, d_ptr->child);
624 } else if (item->email && (item->type == PST_TYPE_NOTE || item->type == PST_TYPE_REPORT)) {
625 ff.email_count++;
626 DEBUG_MAIN(("main: Processing Email\n"));
627 if ((ff.type != PST_TYPE_NOTE) && (ff.type != PST_TYPE_REPORT)) {
628 DEBUG_MAIN(("main: I have an email, but the folder isn't an email folder. Processing anyway\n"));
629 }
630 write_normal_email(ff, item, &pstfile);
631 }
632 pst_freeItem(item);
633 } else {
634 ff.skip_count++;
635 DEBUG_MAIN(("main: A NULL item was seen\n"));
636 }
637 }
638 d_ptr = d_ptr->next;
639 }
640 close_enter_dir(ff);
641 DEBUG_RET();
642 }
643
644
645 int main(int argc, char **argv)
646 {
647 pst_desc_ll *d_ptr;
648 char *fname = NULL;
649 char c;
650 char *d_log = NULL;
651 prog_name = argv[0];
652 pst_item *item = NULL;
653
654 while ((c = getopt(argc, argv, "B:b:c:d:f:o:O:Vh"))!= -1) {
655 switch (c) {
656 case 'B':
657 bates_prefix = optarg;
658 break;
659 case 'b':
660 bates_index = atoi(optarg);
661 break;
662 case 'c':
663 bates_color = (int)strtol(optarg, (char**)NULL, 16);
664 break;
665 case 'f':
666 font_file = optarg;
667 break;
668 case 'o':
669 output_directory = optarg;
670 break;
671 case 'O':
672 output_file = optarg;
673 break;
674 case 'd':
675 d_log = optarg;
676 break;
677 case 'h':
678 usage();
679 exit(0);
680 break;
681 case 'V':
682 version();
683 exit(0);
684 break;
685 default:
686 usage();
687 exit(1);
688 break;
689 }
690 }
691
692 if (argc > optind) {
693 fname = argv[optind];
694 } else {
695 usage();
696 exit(2);
697 }
698
699
700 #ifdef DEBUG_ALL
701 // force a log file
702 if (!d_log) d_log = "pst2dii.log";
703 #endif
704 DEBUG_INIT(d_log);
705 DEBUG_REGISTER_CLOSE();
706 DEBUG_ENT("main");
707 RET_DERROR(pst_open(&pstfile, fname), 1, ("Error opening File\n"));
708 RET_DERROR(pst_load_index(&pstfile), 2, ("Index Error\n"));
709
710 pst_load_extended_attributes(&pstfile);
711
712 d_ptr = pstfile.d_head; // first record is main record
713 item = (pst_item*)pst_parse_item(&pstfile, d_ptr);
714 if (!item || !item->message_store) {
715 DEBUG_RET();
716 DIE(("main: Could not get root record\n"));
717 }
718
719 d_ptr = pst_getTopOfFolders(&pstfile, item);
720 if (!d_ptr) {
721 DEBUG_RET();
722 DIE(("Top of folders record not found. Cannot continue\n"));
723 }
724
725 dii_file = fopen(output_file, "wb");
726 if (dii_file) {
727 process(item, NULL, d_ptr->child); // do the children of TOPF
728 pst_freeItem(item);
729 pst_close(&pstfile);
730 fclose(dii_file);
731 }
732 DEBUG_RET();
733 return 0;
734 }