Mercurial > libpst
annotate src/lspst.c @ 118:0f1492b7fe8b
patch from Fridrich Strba for building on mingw and general cleanup of autoconf files
add processing for pst files of type 0x0f
start adding support for properly building and installing libpst.so and the header files required to use it.
remove version.h since the version number is now in config.h
more const correctness issues regarding getopt()
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Sat, 31 Jan 2009 12:12:36 -0800 |
parents | 7133b39975f7 |
children | 6395ced2b8b2 |
rev | line source |
---|---|
16 | 1 /*** |
2 * lspst.c | |
3 * Part of the LibPST project | |
4 * Author: Joe Nahmias <joe@nahmias.net> | |
5 * Based on readpst.c by by David Smith <dave.s@earthcorp.com> | |
6 * | |
7 */ | |
8 | |
48 | 9 #include "define.h" |
10 | |
16 | 11 #include <stdio.h> |
12 #include <stdlib.h> | |
13 #include <time.h> | |
14 #include <string.h> | |
15 #include <ctype.h> | |
16 #include <errno.h> | |
50 | 17 #include <unistd.h> |
16 | 18 |
19 #include "libpst.h" | |
118
0f1492b7fe8b
patch from Fridrich Strba for building on mingw and general cleanup of autoconf files
Carl Byington <carl@five-ten-sg.com>
parents:
110
diff
changeset
|
20 #include "common.h" |
16 | 21 #include "timeconv.h" |
43 | 22 |
16 | 23 struct file_ll { |
43 | 24 char *dname; |
25 int32_t stored_count; | |
26 int32_t email_count; | |
27 int32_t skip_count; | |
28 int32_t type; | |
16 | 29 }; |
43 | 30 |
31 | |
16 | 32 void canonicalize_filename(char *fname); |
33 void debug_print(char *fmt, ...); | |
118
0f1492b7fe8b
patch from Fridrich Strba for building on mingw and general cleanup of autoconf files
Carl Byington <carl@five-ten-sg.com>
parents:
110
diff
changeset
|
34 void usage(char *prog_name); |
0f1492b7fe8b
patch from Fridrich Strba for building on mingw and general cleanup of autoconf files
Carl Byington <carl@five-ten-sg.com>
parents:
110
diff
changeset
|
35 void version(); |
43 | 36 |
37 // global settings | |
38 pst_file pstfile; | |
39 | |
16 | 40 |
43 | 41 void create_enter_dir(struct file_ll* f, pst_item *item) |
42 { | |
43 f->email_count = 0; | |
44 f->skip_count = 0; | |
45 f->type = item->type; | |
46 f->stored_count = (item->folder) ? item->folder->email_count : 0; | |
47 f->dname = (char*) xmalloc(strlen(item->file_as)+1); | |
48 strcpy(f->dname, item->file_as); | |
49 } | |
16 | 50 |
51 | |
43 | 52 void close_enter_dir(struct file_ll *f) |
53 { | |
54 free(f->dname); | |
55 } | |
16 | 56 |
57 | |
43 | 58 void process(pst_item *outeritem, pst_desc_ll *d_ptr) |
59 { | |
60 struct file_ll ff; | |
61 pst_item *item = NULL; | |
62 | |
63 DEBUG_ENT("process"); | |
64 memset(&ff, 0, sizeof(ff)); | |
65 create_enter_dir(&ff, outeritem); | |
16 | 66 |
43 | 67 while (d_ptr) { |
68 DEBUG_MAIN(("main: New item record, d_ptr = %p.\n", d_ptr)); | |
69 if (!d_ptr->desc) { | |
70 DEBUG_WARN(("main: ERROR ?? item's desc record is NULL\n")); | |
71 ff.skip_count++; | |
72 } | |
73 else { | |
74 DEBUG_MAIN(("main: Desc Email ID %x [d_ptr->id = %x]\n", d_ptr->desc->id, d_ptr->id)); | |
16 | 75 |
46 | 76 item = pst_parse_item(&pstfile, d_ptr); |
43 | 77 DEBUG_MAIN(("main: About to process item @ %p.\n", item)); |
78 if (item) { | |
79 if (item->message_store) { | |
80 // there should only be one message_store, and we have already done it | |
81 DIE(("main: A second message_store has been found. Sorry, this must be an error.\n")); | |
82 } | |
16 | 83 |
43 | 84 if (item->folder && d_ptr->child) { |
85 // if this is a folder, we want to recurse into it | |
86 printf("Folder \"%s\"\n", item->file_as); | |
87 process(item, d_ptr->child); | |
16 | 88 |
43 | 89 } else if (item->contact && (item->type == PST_TYPE_CONTACT)) { |
90 // Process Contact item | |
91 if (ff.type != PST_TYPE_CONTACT) { | |
92 DEBUG_MAIN(("main: I have a contact, but the folder isn't a contacts folder. Processing anyway\n")); | |
93 } | |
94 printf("Contact"); | |
50 | 95 if (item->contact->fullname) |
43 | 96 printf("\t%s", pst_rfc2426_escape(item->contact->fullname)); |
97 printf("\n"); | |
16 | 98 |
110
7133b39975f7
patch from David Cuadrado to process emails with type PST_TYPE_OTHER
Carl Byington <carl@five-ten-sg.com>
parents:
73
diff
changeset
|
99 } else if (item->email && (item->type == PST_TYPE_NOTE || item->type == PST_TYPE_REPORT || item->type == PST_TYPE_OTHER)) { |
43 | 100 // Process Email item |
110
7133b39975f7
patch from David Cuadrado to process emails with type PST_TYPE_OTHER
Carl Byington <carl@five-ten-sg.com>
parents:
73
diff
changeset
|
101 if ((ff.type != PST_TYPE_NOTE) && (ff.type != PST_TYPE_REPORT) && (ff.type != PST_TYPE_OTHER)) { |
43 | 102 DEBUG_MAIN(("main: I have an email, but the folder isn't an email folder. Processing anyway\n")); |
103 } | |
104 printf("Email"); | |
50 | 105 if (item->email->outlook_sender_name) |
43 | 106 printf("\tFrom: %s", item->email->outlook_sender_name); |
50 | 107 if (item->email->subject && item->email->subject->subj) |
43 | 108 printf("\tSubject: %s", item->email->subject->subj); |
109 printf("\n"); | |
16 | 110 |
43 | 111 } else if (item->journal && (item->type == PST_TYPE_JOURNAL)) { |
112 // Process Journal item | |
113 if (ff.type != PST_TYPE_JOURNAL) { | |
114 DEBUG_MAIN(("main: I have a journal entry, but folder isn't specified as a journal type. Processing...\n")); | |
115 } | |
50 | 116 if (item->email && item->email->subject && item->email->subject->subj) |
117 printf("Journal\t%s\n", pst_rfc2426_escape(item->email->subject->subj)); | |
16 | 118 |
43 | 119 } else if (item->appointment && (item->type == PST_TYPE_APPOINTMENT)) { |
120 // Process Calendar Appointment item | |
121 DEBUG_MAIN(("main: Processing Appointment Entry\n")); | |
122 if (ff.type != PST_TYPE_APPOINTMENT) { | |
123 DEBUG_MAIN(("main: I have an appointment, but folder isn't specified as an appointment type. Processing...\n")); | |
124 } | |
125 printf("Appointment"); | |
50 | 126 if (item->email && item->email->subject) |
43 | 127 printf("\tSUMMARY: %s", pst_rfc2426_escape(item->email->subject->subj)); |
50 | 128 if (item->appointment->start) |
129 printf("\tSTART: %s", pst_rfc2445_datetime_format(item->appointment->start)); | |
130 if (item->appointment->end) | |
131 printf("\tEND: %s", pst_rfc2445_datetime_format(item->appointment->end)); | |
132 printf("\tALL DAY: %s", (item->appointment->all_day==1 ? "Yes" : "No")); | |
43 | 133 printf("\n"); |
16 | 134 |
43 | 135 } else { |
136 ff.skip_count++; | |
137 DEBUG_MAIN(("main: Unknown item type. %i. Ascii1=\"%s\"\n", | |
138 item->type, item->ascii_type)); | |
139 } | |
46 | 140 pst_freeItem(item); |
43 | 141 } else { |
142 ff.skip_count++; | |
143 DEBUG_MAIN(("main: A NULL item was seen\n")); | |
144 } | |
145 d_ptr = d_ptr->next; | |
146 } | |
147 } | |
148 close_enter_dir(&ff); | |
52 | 149 DEBUG_RET(); |
43 | 150 } |
16 | 151 |
43 | 152 |
118
0f1492b7fe8b
patch from Fridrich Strba for building on mingw and general cleanup of autoconf files
Carl Byington <carl@five-ten-sg.com>
parents:
110
diff
changeset
|
153 void usage(char *prog_name) { |
50 | 154 DEBUG_ENT("usage"); |
155 version(); | |
156 printf("Usage: %s [OPTIONS] {PST FILENAME}\n", prog_name); | |
157 printf("OPTIONS:\n"); | |
158 printf("\t-d <filename> \t- Debug to file. This is a binary log. Use readlog to print it\n"); | |
159 printf("\t-h\t- Help. This screen\n"); | |
160 printf("\t-V\t- Version. Display program version\n"); | |
161 DEBUG_RET(); | |
162 } | |
163 | |
164 | |
118
0f1492b7fe8b
patch from Fridrich Strba for building on mingw and general cleanup of autoconf files
Carl Byington <carl@five-ten-sg.com>
parents:
110
diff
changeset
|
165 void version() { |
50 | 166 DEBUG_ENT("version"); |
167 printf("lspst / LibPST v%s\n", VERSION); | |
168 #if BYTE_ORDER == BIG_ENDIAN | |
169 printf("Big Endian implementation being used.\n"); | |
170 #elif BYTE_ORDER == LITTLE_ENDIAN | |
171 printf("Little Endian implementation being used.\n"); | |
172 #else | |
173 # error "Byte order not supported by this library" | |
174 #endif | |
175 #ifdef __GNUC__ | |
176 printf("GCC %d.%d : %s %s\n", __GNUC__, __GNUC_MINOR__, __DATE__, __TIME__); | |
177 #endif | |
178 DEBUG_RET(); | |
179 } | |
180 | |
181 | |
118
0f1492b7fe8b
patch from Fridrich Strba for building on mingw and general cleanup of autoconf files
Carl Byington <carl@five-ten-sg.com>
parents:
110
diff
changeset
|
182 int main(int argc, char* const* argv) { |
43 | 183 pst_item *item = NULL; |
184 pst_desc_ll *d_ptr; | |
185 char *temp = NULL; //temporary char pointer | |
50 | 186 int c; |
43 | 187 char *d_log = NULL; |
16 | 188 |
50 | 189 while ((c = getopt(argc, argv, "d:hV"))!= -1) { |
190 switch (c) { | |
191 case 'd': | |
192 d_log = optarg; | |
193 break; | |
194 case 'h': | |
195 usage(argv[0]); | |
196 exit(0); | |
197 break; | |
198 case 'V': | |
199 version(); | |
200 exit(0); | |
201 break; | |
202 default: | |
203 usage(argv[0]); | |
204 exit(1); | |
205 break; | |
206 } | |
207 } | |
43 | 208 |
48 | 209 #ifdef DEBUG_ALL |
210 // force a log file | |
211 if (!d_log) d_log = "lspst.log"; | |
212 #endif // defined DEBUG_ALL | |
43 | 213 DEBUG_INIT(d_log); |
214 DEBUG_REGISTER_CLOSE(); | |
215 DEBUG_ENT("main"); | |
216 | |
50 | 217 if (argc <= optind) { |
218 usage(argv[0]); | |
219 exit(2); | |
220 } | |
221 | |
43 | 222 // Open PST file |
59
7d5c637aaafb
General cleanup and code fixes.
Carl Byington <carl@five-ten-sg.com>
parents:
52
diff
changeset
|
223 if (pst_open(&pstfile, argv[optind])) DIE(("Error opening File\n")); |
16 | 224 |
43 | 225 // Load PST index |
226 if (pst_load_index(&pstfile)) DIE(("Index Error\n")); | |
227 | |
228 pst_load_extended_attributes(&pstfile); | |
16 | 229 |
43 | 230 d_ptr = pstfile.d_head; // first record is main record |
46 | 231 item = pst_parse_item(&pstfile, d_ptr); |
43 | 232 if (!item || !item->message_store) { |
233 DEBUG_RET(); | |
234 DIE(("main: Could not get root record\n")); | |
235 } | |
16 | 236 |
43 | 237 // default the file_as to the same as the main filename if it doesn't exist |
238 if (!item->file_as) { | |
239 if (!(temp = strrchr(argv[1], '/'))) | |
240 if (!(temp = strrchr(argv[1], '\\'))) | |
241 temp = argv[1]; | |
242 else | |
243 temp++; // get past the "\\" | |
244 else | |
245 temp++; // get past the "/" | |
246 item->file_as = (char*)xmalloc(strlen(temp)+1); | |
247 strcpy(item->file_as, temp); | |
248 } | |
249 fprintf(stderr, "item->file_as = '%s'.\n", item->file_as); | |
16 | 250 |
43 | 251 d_ptr = pst_getTopOfFolders(&pstfile, item); |
252 if (!d_ptr) DIE(("Top of folders record not found. Cannot continue\n")); | |
253 DEBUG_MAIN(("d_ptr(TOF) = %p.\n", d_ptr)); | |
16 | 254 |
43 | 255 process(item, d_ptr->child); // do the childred of TOPF |
46 | 256 pst_freeItem(item); |
43 | 257 pst_close(&pstfile); |
16 | 258 |
43 | 259 DEBUG_RET(); |
260 return 0; | |
16 | 261 } |
43 | 262 |
263 | |
264 // This function will make sure that a filename is in cannonical form. That | |
16 | 265 // is, it will replace any slashes, backslashes, or colons with underscores. |
266 void canonicalize_filename(char *fname) { | |
43 | 267 DEBUG_ENT("canonicalize_filename"); |
268 if (fname == NULL) { | |
269 DEBUG_RET(); | |
270 return; | |
271 } | |
73
3cb02cb1e6cd
Patch from Robert Simpson to fix doubly-linked list in the cache_ptr code, and allow arrays of unicode strings (without converting them).
Carl Byington <carl@five-ten-sg.com>
parents:
59
diff
changeset
|
272 while ((fname = strpbrk(fname, "/\\:"))) |
43 | 273 *fname = '_'; |
274 DEBUG_RET(); | |
16 | 275 } |
43 | 276 |
277 | |
16 | 278 void debug_print(char *fmt, ...) { |
43 | 279 // shamlessly stolen from minprintf() in K&R pg. 156 |
280 va_list ap; | |
281 char *p, *sval; | |
282 void *pval; | |
283 int ival; | |
284 double dval; | |
285 FILE *fp = stderr; | |
16 | 286 |
43 | 287 va_start(ap, fmt); |
288 for(p = fmt; *p; p++) { | |
289 if (*p != '%') { | |
290 fputc(*p, fp); | |
291 continue; | |
292 } | |
293 switch (tolower(*++p)) { | |
294 case 'd': case 'i': | |
295 ival = va_arg(ap, int); | |
296 fprintf(fp, "%d", ival); | |
297 break; | |
298 case 'f': | |
299 dval = va_arg(ap, double); | |
300 fprintf(fp, "%f", dval); | |
301 break; | |
302 case 's': | |
303 for (sval = va_arg(ap, char *); *sval; ++sval) | |
304 fputc(*sval, fp); | |
305 break; | |
306 case 'p': | |
307 pval = va_arg(ap, void *); | |
308 fprintf(fp, "%p", pval); | |
309 break; | |
310 case 'x': | |
311 ival = va_arg(ap, int); | |
312 fprintf(fp, "%#010x", ival); | |
313 break; | |
314 default: | |
315 fputc(*p, fp); | |
316 break; | |
317 } | |
318 } | |
319 va_end(ap); | |
16 | 320 } |
321 | |
322 |