Mercurial > libpst
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, "&", &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 } |