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