Mercurial > libpst
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! |