Mercurial > libpst
annotate src/readpst.c @ 42:7a97f50c39c5 stable-0-5-12 **FUNKY**
security fix for potential buffer overrun in lz decompress
author | carl |
---|---|
date | Tue, 02 Oct 2007 16:10:36 -0700 |
parents | 183ae993b9ad |
children | f6db1f060a95 |
rev | line source |
---|---|
16 | 1 /*** |
2 * readpst.c | |
3 * Part of the LibPST project | |
4 * Written by David Smith | |
5 * dave.s@earthcorp.com | |
6 */ | |
7 #include <stdio.h> | |
8 #include <stdlib.h> | |
9 #include <time.h> | |
10 #include <string.h> | |
11 #include <ctype.h> | |
12 #include <limits.h> | |
13 #include <errno.h> | |
14 | |
15 #ifndef _WIN32 | |
16 # include <unistd.h> | |
17 # include <sys/stat.h> //mkdir | |
18 | |
19 // for reading of directory and clearing in function mk_seperate_dir | |
20 # include <sys/types.h> | |
21 # include <dirent.h> | |
22 #else | |
23 # include <direct.h> | |
24 # define chdir _chdir | |
25 # define int32_t __int32 | |
26 #endif | |
27 | |
28 #ifndef __GNUC__ | |
29 # include "XGetopt.h" | |
30 #endif | |
31 | |
32 #include "libstrfunc.h" // for base64_encoding | |
33 | |
21 | 34 #include "version.h" |
16 | 35 #include "define.h" |
36 #include "libpst.h" | |
37 #include "common.h" | |
38 #include "timeconv.h" | |
39 #include "lzfu.h" | |
40 #define OUTPUT_TEMPLATE "%s" | |
41 #define OUTPUT_KMAIL_DIR_TEMPLATE ".%s.directory" | |
42 #define KMAIL_INDEX ".%s.index" | |
25 | 43 #define SEP_MAIL_FILE_TEMPLATE "%i" /* "%09i" */ |
16 | 44 |
45 // max size of the c_time char*. It will store the date of the email | |
46 #define C_TIME_SIZE 500 | |
47 #define PERM_DIRS 0777 | |
48 | |
49 // macro used for creating directories | |
50 #ifndef WIN32 | |
51 #define D_MKDIR(x) mkdir(x, PERM_DIRS) | |
52 #else | |
53 #define D_MKDIR(x) mkdir(x) | |
54 #endif | |
55 struct file_ll { | |
26 | 56 char *name; |
57 char *dname; | |
58 FILE * output; | |
59 int32_t stored_count; | |
60 int32_t email_count; | |
61 int32_t skip_count; | |
62 int32_t type; | |
16 | 63 }; |
31 | 64 |
39 | 65 void process(pst_item *outeritem, pst_desc_ll *d_ptr); |
34
07177825c91b
fix signed/unsigned to allow very small pst files with only leaf nodes
carl
parents:
33
diff
changeset
|
66 void write_email_body(FILE *f, char *body); |
07177825c91b
fix signed/unsigned to allow very small pst files with only leaf nodes
carl
parents:
33
diff
changeset
|
67 char* removeCR (char *c); |
16 | 68 int32_t usage(); |
69 int32_t version(); | |
34
07177825c91b
fix signed/unsigned to allow very small pst files with only leaf nodes
carl
parents:
33
diff
changeset
|
70 char* mk_kmail_dir(char*); |
16 | 71 int32_t close_kmail_dir(); |
34
07177825c91b
fix signed/unsigned to allow very small pst files with only leaf nodes
carl
parents:
33
diff
changeset
|
72 char* mk_recurse_dir(char*); |
16 | 73 int32_t close_recurse_dir(); |
39 | 74 char* mk_seperate_dir(char *dir); |
16 | 75 int32_t close_seperate_dir(); |
76 int32_t mk_seperate_file(struct file_ll *f); | |
34
07177825c91b
fix signed/unsigned to allow very small pst files with only leaf nodes
carl
parents:
33
diff
changeset
|
77 char* my_stristr(char *haystack, char *needle); |
41
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
39
diff
changeset
|
78 void check_filename(char *fname); |
34
07177825c91b
fix signed/unsigned to allow very small pst files with only leaf nodes
carl
parents:
33
diff
changeset
|
79 char* rfc2426_escape(char *str); |
07177825c91b
fix signed/unsigned to allow very small pst files with only leaf nodes
carl
parents:
33
diff
changeset
|
80 int32_t chr_count(char *str, char x); |
07177825c91b
fix signed/unsigned to allow very small pst files with only leaf nodes
carl
parents:
33
diff
changeset
|
81 char* rfc2425_datetime_format(FILETIME *ft); |
07177825c91b
fix signed/unsigned to allow very small pst files with only leaf nodes
carl
parents:
33
diff
changeset
|
82 char* rfc2445_datetime_format(FILETIME *ft); |
07177825c91b
fix signed/unsigned to allow very small pst files with only leaf nodes
carl
parents:
33
diff
changeset
|
83 char* skip_header_prologue(char *headers); |
07177825c91b
fix signed/unsigned to allow very small pst files with only leaf nodes
carl
parents:
33
diff
changeset
|
84 void write_separate_attachment(char f_name[], pst_item_attach* current_attach, int attach_num, pst_file* pst); |
07177825c91b
fix signed/unsigned to allow very small pst files with only leaf nodes
carl
parents:
33
diff
changeset
|
85 void write_inline_attachment(FILE* f_output, pst_item_attach* current_attach, char boundary[], pst_file* pst); |
07177825c91b
fix signed/unsigned to allow very small pst files with only leaf nodes
carl
parents:
33
diff
changeset
|
86 void write_normal_email(FILE* f_output, char f_name[], pst_item* item, int mode, int mode_MH, pst_file* pst, int save_rtf); |
07177825c91b
fix signed/unsigned to allow very small pst files with only leaf nodes
carl
parents:
33
diff
changeset
|
87 void write_vcard(FILE* f_output, pst_item_contact* contact, char comment[]); |
07177825c91b
fix signed/unsigned to allow very small pst files with only leaf nodes
carl
parents:
33
diff
changeset
|
88 void write_appointment(FILE* f_output, pst_item_appointment* appointment, |
07177825c91b
fix signed/unsigned to allow very small pst files with only leaf nodes
carl
parents:
33
diff
changeset
|
89 pst_item_email* email, FILETIME* create_date, FILETIME* modify_date); |
39 | 90 void create_enter_dir(struct file_ll* f, pst_item *item); |
91 void close_enter_dir(struct file_ll *f); | |
34
07177825c91b
fix signed/unsigned to allow very small pst files with only leaf nodes
carl
parents:
33
diff
changeset
|
92 |
07177825c91b
fix signed/unsigned to allow very small pst files with only leaf nodes
carl
parents:
33
diff
changeset
|
93 char* prog_name; |
07177825c91b
fix signed/unsigned to allow very small pst files with only leaf nodes
carl
parents:
33
diff
changeset
|
94 char* output_dir = "."; |
07177825c91b
fix signed/unsigned to allow very small pst files with only leaf nodes
carl
parents:
33
diff
changeset
|
95 char* kmail_chdir = NULL; |
16 | 96 // Normal mode just creates mbox format files in the current directory. Each file is named |
97 // the same as the folder's name that it represents | |
98 #define MODE_NORMAL 0 | |
99 // KMail mode creates a directory structure suitable for being used directly | |
100 // by the KMail application | |
101 #define MODE_KMAIL 1 | |
102 // recurse mode creates a directory structure like the PST file. Each directory | |
103 // contains only one file which stores the emails in mbox format. | |
104 #define MODE_RECURSE 2 | |
105 // seperate mode is similar directory structure to RECURSE. The emails are stored in | |
106 // seperate files, numbering from 1 upward. Attachments belonging to the emails are | |
107 // saved as email_no-filename (e.g. 1-samplefile.doc or 000001-Attachment2.zip) | |
108 #define MODE_SEPERATE 3 | |
109 | |
110 | |
111 // Output Normal just prints the standard information about what is going on | |
112 #define OUTPUT_NORMAL 0 | |
113 // Output Quiet is provided so that only errors are printed | |
114 #define OUTPUT_QUIET 1 | |
115 | |
116 // default mime-type for attachments that have a null mime-type | |
117 #define MIME_TYPE_DEFAULT "application/octet-stream" | |
118 | |
119 // output mode for contacts | |
120 #define CMODE_VCARD 0 | |
121 #define CMODE_LIST 1 | |
122 | |
123 // output settings for RTF bodies | |
124 // filename for the attachment | |
125 #define RTF_ATTACH_NAME "rtf-body.rtf" | |
126 // mime type for the attachment | |
127 #define RTF_ATTACH_TYPE "application/rtf" | |
34
07177825c91b
fix signed/unsigned to allow very small pst files with only leaf nodes
carl
parents:
33
diff
changeset
|
128 |
39 | 129 // global settings |
130 int mode = MODE_NORMAL; | |
131 int mode_MH = 0; | |
132 int output_mode = OUTPUT_NORMAL; | |
133 int contact_mode = CMODE_VCARD; | |
134 int overwrite = 0; | |
135 int save_rtf_body = 1; | |
136 pst_file pstfile; | |
137 | |
138 | |
139 | |
140 void process(pst_item *outeritem, pst_desc_ll *d_ptr) | |
141 { | |
142 struct file_ll ff; | |
143 pst_item *item = NULL; | |
144 | |
145 DEBUG_ENT("process"); | |
146 memset(&ff, 0, sizeof(ff)); | |
147 create_enter_dir(&ff, outeritem); | |
148 | |
149 while (d_ptr) { | |
150 DEBUG_MAIN(("main: New item record\n")); | |
151 if (!d_ptr->desc) { | |
152 DEBUG_WARN(("main: ERROR ?? item's desc record is NULL\n")); | |
153 ff.skip_count++; | |
154 } | |
155 else { | |
156 DEBUG_MAIN(("main: Desc Email ID %#x [d_ptr->id = %#x]\n", d_ptr->desc->id, d_ptr->id)); | |
157 | |
158 item = _pst_parse_item(&pstfile, d_ptr); | |
159 DEBUG_MAIN(("main: About to process item\n")); | |
160 if (item && item->email && item->email->subject && item->email->subject->subj) { | |
161 DEBUG_EMAIL(("item->email->subject = %p\n", item->email->subject)); | |
162 DEBUG_EMAIL(("item->email->subject->subj = %p\n", item->email->subject->subj)); | |
163 } | |
164 if (item) { | |
165 if (item->message_store) { | |
166 // there should only be one message_store, and we have already done it | |
167 DIE(("main: A second message_store has been found. Sorry, this must be an error.\n")); | |
168 } | |
169 | |
170 if (item->folder && d_ptr->child && strcasecmp(item->file_as, "Deleted Items")) { | |
171 //if this is a non-empty folder other than deleted items, we want to recurse into it | |
172 if (output_mode != OUTPUT_QUIET) printf("Processing Folder \"%s\"\n", item->file_as); | |
173 process(item, d_ptr->child); | |
174 | |
175 } else if (item->contact) { | |
176 // deal with a contact | |
177 // write them to the file, one per line in this format | |
178 // Desc Name <email@address>\n | |
179 if (mode == MODE_SEPERATE) mk_seperate_file(&ff); | |
180 ff.email_count++; | |
181 DEBUG_MAIN(("main: Processing Contact\n")); | |
182 if (ff.type != PST_TYPE_CONTACT) { | |
183 DEBUG_MAIN(("main: I have a contact, but the folder isn't a contacts folder. " | |
184 "Will process anyway\n")); | |
185 } | |
186 if (item->type != PST_TYPE_CONTACT) { | |
187 DEBUG_MAIN(("main: I have an item that has contact info, but doesn't say that" | |
188 " it is a contact. Type is \"%s\"\n", item->ascii_type)); | |
189 DEBUG_MAIN(("main: Processing anyway\n")); | |
190 } | |
191 if (!item->contact) { // this is an incorrect situation. Inform user | |
192 DEBUG_MAIN(("main: ERROR. This contact has not been fully parsed. one of the pre-requisties is NULL\n")); | |
193 } else { | |
194 if (contact_mode == CMODE_VCARD) | |
195 write_vcard(ff.output, item->contact, item->comment); | |
196 else | |
197 fprintf(ff.output, "%s <%s>\n", item->contact->fullname, item->contact->address1); | |
198 } | |
199 | |
200 } else if (item->email && (item->type == PST_TYPE_NOTE || item->type == PST_TYPE_REPORT)) { | |
201 if (mode == MODE_SEPERATE) mk_seperate_file(&ff); | |
202 ff.email_count++; | |
203 DEBUG_MAIN(("main: seen an email\n")); | |
204 write_normal_email(ff.output, ff.name, item, mode, mode_MH, &pstfile, save_rtf_body); | |
205 | |
206 } else if (item->type == PST_TYPE_JOURNAL) { | |
207 // deal with journal items | |
208 if (mode == MODE_SEPERATE) mk_seperate_file(&ff); | |
209 ff.email_count++; | |
210 | |
211 DEBUG_MAIN(("main: Processing Journal Entry\n")); | |
212 if (ff.type != PST_TYPE_JOURNAL) { | |
213 DEBUG_MAIN(("main: I have a journal entry, but folder isn't specified as a journal type. Processing...\n")); | |
214 } | |
215 | |
216 /* if (item->type != PST_TYPE_JOURNAL) { | |
217 DEBUG_MAIN(("main: I have an item with journal info, but it's type is \"%s\" \n. Processing...\n", | |
218 item->ascii_type)); | |
219 }*/ | |
220 fprintf(ff.output, "BEGIN:VJOURNAL\n"); | |
221 if (item->email->subject) | |
222 fprintf(ff.output, "SUMMARY:%s\n", rfc2426_escape(item->email->subject->subj)); | |
223 if (item->email->body) | |
224 fprintf(ff.output, "DESCRIPTION:%s\n", rfc2426_escape(item->email->body)); | |
225 if (item->journal->start) | |
226 fprintf(ff.output, "DTSTART;VALUE=DATE-TIME:%s\n", rfc2445_datetime_format(item->journal->start)); | |
227 fprintf(ff.output, "END:VJOURNAL\n\n"); | |
228 | |
229 } else if (item->type == PST_TYPE_APPOINTMENT) { | |
230 // deal with Calendar appointments | |
231 if (mode == MODE_SEPERATE) mk_seperate_file(&ff); | |
232 ff.email_count++; | |
233 DEBUG_MAIN(("main: Processing Appointment Entry\n")); | |
234 if (ff.type != PST_TYPE_APPOINTMENT) { | |
235 DEBUG_MAIN(("main: I have an appointment, but folder isn't specified as an appointment type. Processing...\n")); | |
236 } | |
237 write_appointment(ff.output, item->appointment, item->email, item->create_date, item->modify_date); | |
238 | |
239 } else { | |
240 ff.skip_count++; | |
241 DEBUG_MAIN(("main: Unknown item type. %i. Ascii1=\"%s\"\n", | |
242 item->type, item->ascii_type)); | |
243 } | |
244 _pst_freeItem(item); | |
245 } else { | |
246 ff.skip_count++; | |
247 DEBUG_MAIN(("main: A NULL item was seen\n")); | |
248 } | |
249 d_ptr = d_ptr->next; | |
250 } | |
251 } | |
252 close_enter_dir(&ff); | |
253 DEBUG_RET(); | |
254 } | |
255 | |
256 | |
34
07177825c91b
fix signed/unsigned to allow very small pst files with only leaf nodes
carl
parents:
33
diff
changeset
|
257 |
16 | 258 int main(int argc, char** argv) { |
26 | 259 pst_item *item = NULL; |
260 pst_desc_ll *d_ptr; | |
261 char * fname = NULL; | |
262 char *d_log=NULL; | |
263 int c,x; | |
31 | 264 char *temp = NULL; //temporary char pointer |
26 | 265 prog_name = argv[0]; |
16 | 266 |
31 | 267 // command-line option handling |
268 while ((c = getopt(argc, argv, "bd:hko:qrMSVwc:"))!= -1) { | |
26 | 269 switch (c) { |
31 | 270 case 'b': |
271 save_rtf_body = 0; | |
272 break; | |
26 | 273 case 'c': |
31 | 274 if (optarg && optarg[0]=='v') |
26 | 275 contact_mode=CMODE_VCARD; |
31 | 276 else if (optarg && optarg[0]=='l') |
26 | 277 contact_mode=CMODE_LIST; |
278 else { | |
279 usage(); | |
280 exit(0); | |
281 } | |
282 break; | |
283 case 'd': | |
284 d_log = optarg; | |
285 break; | |
286 case 'h': | |
287 usage(); | |
288 exit(0); | |
289 break; | |
290 case 'V': | |
291 version(); | |
292 exit(0); | |
293 break; | |
294 case 'k': | |
295 mode = MODE_KMAIL; | |
296 break; | |
297 case 'M': | |
298 mode = MODE_SEPERATE; | |
299 mode_MH = 1; | |
300 break; | |
301 case 'o': | |
302 output_dir = optarg; | |
303 break; | |
304 case 'q': | |
305 output_mode = OUTPUT_QUIET; | |
306 break; | |
307 case 'r': | |
308 mode = MODE_RECURSE; | |
309 break; | |
310 case 'S': | |
311 mode = MODE_SEPERATE; | |
312 break; | |
313 case 'w': | |
314 overwrite = 1; | |
315 break; | |
316 default: | |
317 usage(); | |
318 exit(1); | |
319 break; | |
320 } | |
16 | 321 } |
322 | |
26 | 323 if (argc > optind) { |
324 fname = argv[optind]; | |
325 } else { | |
326 usage(); | |
327 exit(2); | |
328 } | |
16 | 329 |
39 | 330 #ifdef DEBUG_ALL |
331 // force a log file | |
332 if (!d_log) d_log = "readpst.log"; | |
333 #endif // defined DEBUG_ALL | |
334 DEBUG_INIT(d_log); | |
335 DEBUG_REGISTER_CLOSE(); | |
336 DEBUG_ENT("main"); | |
337 | |
26 | 338 if (output_mode != OUTPUT_QUIET) printf("Opening PST file and indexes...\n"); |
16 | 339 |
26 | 340 RET_DERROR(pst_open(&pstfile, fname, "r"), 1, ("Error opening File\n")); |
341 RET_DERROR(pst_load_index(&pstfile), 2, ("Index Error\n")); | |
16 | 342 |
26 | 343 pst_load_extended_attributes(&pstfile); |
16 | 344 |
26 | 345 if (chdir(output_dir)) { |
346 x = errno; | |
347 pst_close(&pstfile); | |
39 | 348 DEBUG_RET(); |
26 | 349 DIE(("main: Cannot change to output dir %s: %s\n", output_dir, strerror(x))); |
350 } | |
16 | 351 |
26 | 352 if (output_mode != OUTPUT_QUIET) printf("About to start processing first record...\n"); |
16 | 353 |
26 | 354 d_ptr = pstfile.d_head; // first record is main record |
39 | 355 item = (pst_item*)_pst_parse_item(&pstfile, d_ptr); |
356 if (!item || !item->message_store) { | |
357 DEBUG_RET(); | |
26 | 358 DIE(("main: Could not get root record\n")); |
359 } | |
16 | 360 |
26 | 361 // default the file_as to the same as the main filename if it doesn't exist |
31 | 362 if (!item->file_as) { |
363 if (!(temp = strrchr(fname, '/'))) | |
364 if (!(temp = strrchr(fname, '\\'))) | |
26 | 365 temp = fname; |
366 else | |
367 temp++; // get past the "\\" | |
368 else | |
369 temp++; // get past the "/" | |
370 item->file_as = (char*)xmalloc(strlen(temp)+1); | |
371 strcpy(item->file_as, temp); | |
372 DEBUG_MAIN(("file_as was blank, so am using %s\n", item->file_as)); | |
373 } | |
374 DEBUG_MAIN(("main: Root Folder Name: %s\n", item->file_as)); | |
16 | 375 |
39 | 376 d_ptr = pst_getTopOfFolders(&pstfile, item); |
377 if (!d_ptr) { | |
378 DEBUG_RET(); | |
26 | 379 DIE(("Top of folders record not found. Cannot continue\n")); |
16 | 380 } |
381 | |
39 | 382 process(item, d_ptr->child); // do the children of TOPF |
383 _pst_freeItem(item); | |
26 | 384 pst_close(&pstfile); |
16 | 385 |
26 | 386 DEBUG_RET(); |
387 return 0; | |
16 | 388 } |
31 | 389 |
390 | |
16 | 391 void write_email_body(FILE *f, char *body) { |
26 | 392 char *n = body; |
31 | 393 // DEBUG_MAIN(("write_email_body(): \"%s\"\n", body)); |
26 | 394 DEBUG_ENT("write_email_body"); |
31 | 395 while (n) { |
26 | 396 if (strncmp(body, "From ", 5) == 0) |
397 fprintf(f, ">"); | |
398 if ((n = strchr(body, '\n'))) { | |
399 n++; | |
400 fwrite(body, n-body, 1, f); //write just a line | |
16 | 401 |
26 | 402 body = n; |
403 } | |
16 | 404 } |
26 | 405 fwrite(body, strlen(body), 1, f); |
406 DEBUG_RET(); | |
16 | 407 } |
31 | 408 |
409 | |
16 | 410 char *removeCR (char *c) { |
26 | 411 // converts /r/n to /n |
412 char *a, *b; | |
413 DEBUG_ENT("removeCR"); | |
414 a = b = c; | |
415 while (*a != '\0') { | |
416 *b = *a; | |
417 if (*a != '\r') | |
418 b++; | |
419 a++; | |
420 } | |
421 *b = '\0'; | |
422 DEBUG_RET(); | |
423 return c; | |
16 | 424 } |
31 | 425 |
426 | |
16 | 427 int usage() { |
26 | 428 DEBUG_ENT("usage"); |
429 version(); | |
430 printf("Usage: %s [OPTIONS] {PST FILENAME}\n", prog_name); | |
431 printf("OPTIONS:\n"); | |
31 | 432 printf("\t-b\t- Don't save RTF-Body attachments\n"); |
26 | 433 printf("\t-c[v|l]\t- Set the Contact output mode. -cv = VCard, -cl = EMail list\n"); |
31 | 434 printf("\t-d <filename> \t- Debug to file. This is a binary log. Use readlog to print it\n"); |
26 | 435 printf("\t-h\t- Help. This screen\n"); |
436 printf("\t-k\t- KMail. Output in kmail format\n"); | |
437 printf("\t-M\t- MH. Write emails in the MH format\n"); | |
31 | 438 printf("\t-o <dirname>\t- Output Dir. Directory to write files to. CWD is changed *after* opening pst file\n"); |
26 | 439 printf("\t-q\t- Quiet. Only print error messages\n"); |
440 printf("\t-r\t- Recursive. Output in a recursive format\n"); | |
441 printf("\t-S\t- Seperate. Write emails in the seperate format\n"); | |
442 printf("\t-V\t- Version. Display program version\n"); | |
443 printf("\t-w\t- Overwrite any output mbox files\n"); | |
444 DEBUG_RET(); | |
445 return 0; | |
16 | 446 } |
31 | 447 |
448 | |
16 | 449 int version() { |
26 | 450 DEBUG_ENT("version"); |
451 printf("ReadPST v%s\n", VERSION); | |
16 | 452 #if BYTE_ORDER == BIG_ENDIAN |
26 | 453 printf("Big Endian implementation being used.\n"); |
16 | 454 #elif BYTE_ORDER == LITTLE_ENDIAN |
26 | 455 printf("Little Endian implementation being used.\n"); |
16 | 456 #else |
457 # error "Byte order not supported by this library" | |
458 #endif | |
459 #ifdef __GNUC__ | |
26 | 460 printf("GCC %d.%d : %s %s\n", __GNUC__, __GNUC_MINOR__, __DATE__, __TIME__); |
16 | 461 #endif |
26 | 462 DEBUG_RET(); |
463 return 0; | |
16 | 464 } |
31 | 465 |
466 | |
16 | 467 char *mk_kmail_dir(char *fname) { |
26 | 468 //change to that directory |
469 //make a directory based on OUTPUT_KMAIL_DIR_TEMPLATE | |
470 //allocate space for OUTPUT_TEMPLATE and form a char* with fname | |
471 //return that value | |
472 char *dir, *out_name, *index; | |
473 int x; | |
474 DEBUG_ENT("mk_kmail_dir"); | |
31 | 475 if (kmail_chdir && chdir(kmail_chdir)) { |
26 | 476 x = errno; |
477 DIE(("mk_kmail_dir: Cannot change to directory %s: %s\n", kmail_chdir, strerror(x))); | |
16 | 478 } |
26 | 479 dir = malloc(strlen(fname)+strlen(OUTPUT_KMAIL_DIR_TEMPLATE)+1); |
480 sprintf(dir, OUTPUT_KMAIL_DIR_TEMPLATE, fname); | |
41
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
39
diff
changeset
|
481 check_filename(dir); |
26 | 482 if (D_MKDIR(dir)) { |
483 //error occured | |
484 if (errno != EEXIST) { | |
485 x = errno; | |
486 DIE(("mk_kmail_dir: Cannot create directory %s: %s\n", dir, strerror(x))); | |
487 } | |
488 } | |
489 kmail_chdir = realloc(kmail_chdir, strlen(dir)+1); | |
490 strcpy(kmail_chdir, dir); | |
491 free (dir); | |
16 | 492 |
26 | 493 //we should remove any existing indexes created by KMail, cause they might be different now |
494 index = malloc(strlen(fname)+strlen(KMAIL_INDEX)+1); | |
495 sprintf(index, KMAIL_INDEX, fname); | |
496 unlink(index); | |
497 free(index); | |
16 | 498 |
26 | 499 out_name = malloc(strlen(fname)+strlen(OUTPUT_TEMPLATE)+1); |
500 sprintf(out_name, OUTPUT_TEMPLATE, fname); | |
501 DEBUG_RET(); | |
502 return out_name; | |
16 | 503 } |
31 | 504 |
505 | |
16 | 506 int close_kmail_dir() { |
26 | 507 // change .. |
508 int x; | |
509 DEBUG_ENT("close_kmail_dir"); | |
31 | 510 if (kmail_chdir) { //only free kmail_chdir if not NULL. do not change directory |
26 | 511 free(kmail_chdir); |
512 kmail_chdir = NULL; | |
513 } else { | |
514 if (chdir("..")) { | |
515 x = errno; | |
516 DIE(("close_kmail_dir: Cannot move up dir (..): %s\n", strerror(x))); | |
517 } | |
16 | 518 } |
26 | 519 DEBUG_RET(); |
520 return 0; | |
16 | 521 } |
31 | 522 |
523 | |
16 | 524 // this will create a directory by that name, then make an mbox file inside |
525 // that dir. any subsequent dirs will be created by name, and they will | |
526 // contain mbox files | |
527 char *mk_recurse_dir(char *dir) { | |
26 | 528 int x; |
529 char *out_name; | |
530 DEBUG_ENT("mk_recurse_dir"); | |
41
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
39
diff
changeset
|
531 check_filename(dir); |
26 | 532 if (D_MKDIR (dir)) { |
533 if (errno != EEXIST) { // not an error because it exists | |
534 x = errno; | |
535 DIE(("mk_recurse_dir: Cannot create directory %s: %s\n", dir, strerror(x))); | |
536 } | |
16 | 537 } |
26 | 538 if (chdir (dir)) { |
539 x = errno; | |
540 DIE(("mk_recurse_dir: Cannot change to directory %s: %s\n", dir, strerror(x))); | |
541 } | |
542 out_name = malloc(strlen("mbox")+1); | |
543 strcpy(out_name, "mbox"); | |
544 DEBUG_RET(); | |
545 return out_name; | |
16 | 546 } |
31 | 547 |
548 | |
16 | 549 int close_recurse_dir() { |
26 | 550 int x; |
551 DEBUG_ENT("close_recurse_dir"); | |
552 if (chdir("..")) { | |
553 x = errno; | |
554 DIE(("close_recurse_dir: Cannot go up dir (..): %s\n", strerror(x))); | |
555 } | |
556 DEBUG_RET(); | |
557 return 0; | |
16 | 558 } |
31 | 559 |
560 | |
39 | 561 char *mk_seperate_dir(char *dir) { |
31 | 562 DEBUG_ENT("mk_seperate_dir"); |
16 | 563 |
41
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
39
diff
changeset
|
564 size_t dirsize = strlen(dir) + 10; |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
39
diff
changeset
|
565 char dir_name[dirsize]; |
26 | 566 int x = 0, y = 0; |
16 | 567 |
26 | 568 do { |
569 if (y == 0) | |
41
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
39
diff
changeset
|
570 snprintf(dir_name, dirsize, "%s", dir); |
26 | 571 else |
41
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
39
diff
changeset
|
572 snprintf(dir_name, dirsize, "%s" SEP_MAIL_FILE_TEMPLATE, dir, y); // enough for 9 digits allocated above |
16 | 573 |
41
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
39
diff
changeset
|
574 check_filename(dir_name); |
31 | 575 DEBUG_MAIN(("about to try creating %s\n", dir_name)); |
26 | 576 if (D_MKDIR(dir_name)) { |
577 if (errno != EEXIST) { // if there is an error, and it doesn't already exist | |
578 x = errno; | |
579 DIE(("mk_seperate_dir: Cannot create directory %s: %s\n", dir, strerror(x))); | |
580 } | |
581 } else { | |
582 break; | |
583 } | |
584 y++; | |
585 } while (overwrite == 0); | |
16 | 586 |
41
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
39
diff
changeset
|
587 if (chdir(dir_name)) { |
26 | 588 x = errno; |
589 DIE(("mk_recurse_dir: Cannot change to directory %s: %s\n", dir, strerror(x))); | |
590 } | |
16 | 591 |
26 | 592 if (overwrite) { |
593 // we should probably delete all files from this directory | |
16 | 594 #if !defined(WIN32) && !defined(__CYGWIN__) |
41
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
39
diff
changeset
|
595 DIR * sdir = NULL; |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
39
diff
changeset
|
596 struct dirent *dirent = NULL; |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
39
diff
changeset
|
597 struct stat filestat; |
31 | 598 if (!(sdir = opendir("./"))) { |
26 | 599 WARN(("mk_seperate_dir: Cannot open dir \"%s\" for deletion of old contents\n", "./")); |
600 } else { | |
31 | 601 while ((dirent = readdir(sdir))) { |
41
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
39
diff
changeset
|
602 if (lstat(dirent->d_name, &filestat) != -1) |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
39
diff
changeset
|
603 if (S_ISREG(filestat.st_mode)) { |
26 | 604 if (unlink(dirent->d_name)) { |
605 y = errno; | |
606 DIE(("mk_seperate_dir: unlink returned error on file %s: %s\n", dirent->d_name, strerror(y))); | |
607 } | |
608 } | |
609 } | |
16 | 610 } |
26 | 611 #endif |
16 | 612 } |
613 | |
26 | 614 // we don't return a filename here cause it isn't necessary. |
615 DEBUG_RET(); | |
616 return NULL; | |
16 | 617 } |
31 | 618 |
619 | |
16 | 620 int close_seperate_dir() { |
26 | 621 int x; |
622 DEBUG_ENT("close_seperate_dir"); | |
623 if (chdir("..")) { | |
624 x = errno; | |
625 DIE(("close_seperate_dir: Cannot go up dir (..): %s\n", strerror(x))); | |
626 } | |
627 DEBUG_RET(); | |
628 return 0; | |
16 | 629 } |
31 | 630 |
631 | |
16 | 632 int mk_seperate_file(struct file_ll *f) { |
26 | 633 const int name_offset = 1; |
634 DEBUG_ENT("mk_seperate_file"); | |
31 | 635 DEBUG_MAIN(("opening next file to save email\n")); |
26 | 636 if (f->email_count > 999999999) { // bigger than nine 9's |
637 DIE(("mk_seperate_file: The number of emails in this folder has become too high to handle")); | |
638 } | |
639 sprintf(f->name, SEP_MAIL_FILE_TEMPLATE, f->email_count + name_offset); | |
39 | 640 if (f->output) fclose(f->output); |
26 | 641 f->output = NULL; |
41
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
39
diff
changeset
|
642 check_filename(f->name); |
31 | 643 if (!(f->output = fopen(f->name, "w"))) { |
26 | 644 DIE(("mk_seperate_file: Cannot open file to save email \"%s\"\n", f->name)); |
645 } | |
646 DEBUG_RET(); | |
647 return 0; | |
16 | 648 } |
31 | 649 |
650 | |
16 | 651 char *my_stristr(char *haystack, char *needle) { |
31 | 652 // my_stristr varies from strstr in that its searches are case-insensitive |
26 | 653 char *x=haystack, *y=needle, *z = NULL; |
654 DEBUG_ENT("my_stristr"); | |
31 | 655 if (!haystack || !needle) |
26 | 656 return NULL; |
657 while (*y != '\0' && *x != '\0') { | |
658 if (tolower(*y) == tolower(*x)) { | |
659 // move y on one | |
660 y++; | |
31 | 661 if (!z) { |
26 | 662 z = x; // store first position in haystack where a match is made |
663 } | |
664 } else { | |
665 y = needle; // reset y to the beginning of the needle | |
666 z = NULL; // reset the haystack storage point | |
667 } | |
668 x++; // advance the search in the haystack | |
16 | 669 } |
26 | 670 DEBUG_RET(); |
671 return z; | |
16 | 672 } |
31 | 673 |
674 | |
41
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
39
diff
changeset
|
675 void check_filename(char *fname) { |
26 | 676 char *t = fname; |
677 DEBUG_ENT("check_filename"); | |
31 | 678 if (!t) { |
26 | 679 DEBUG_RET(); |
680 return fname; | |
681 } | |
31 | 682 while ((t = strpbrk(t, "/\\:"))) { |
26 | 683 // while there are characters in the second string that we don't want |
684 *t = '_'; //replace them with an underscore | |
685 } | |
16 | 686 DEBUG_RET(); |
687 return fname; | |
688 } | |
31 | 689 |
690 | |
16 | 691 char *rfc2426_escape(char *str) { |
26 | 692 static char* buf = NULL; |
693 char *ret, *a, *b; | |
694 int x = 0, y, z; | |
695 DEBUG_ENT("rfc2426_escape"); | |
31 | 696 if (!str) |
26 | 697 ret = str; |
16 | 698 else { |
26 | 699 |
700 // calculate space required to escape all the following characters | |
31 | 701 y = chr_count(str, ',') |
702 + chr_count(str, '\\') | |
703 + chr_count(str, ';') | |
704 + chr_count(str, '\n'); | |
26 | 705 z = chr_count(str, '\r'); |
706 if (y == 0 && z == 0) | |
707 // there isn't any extra space required | |
708 ret = str; | |
709 else { | |
38 | 710 x = strlen(str) + y - z + 1; // don't forget room for the NUL |
31 | 711 buf = (char*) realloc(buf, x); |
26 | 712 a = str; |
713 b = buf; | |
714 while (*a != '\0') { | |
31 | 715 switch (*a) { |
26 | 716 case ',' : |
717 case '\\': | |
718 case ';' : | |
31 | 719 *(b++) = '\\'; |
720 *b = *a; | |
26 | 721 break; |
31 | 722 case '\n': // newlines are encoded as "\n" |
723 *(b++) = '\\'; | |
724 *b = 'n'; | |
725 break; | |
726 case '\r': // skip cr | |
727 b--; | |
26 | 728 break; |
729 default: | |
730 *b=*a; | |
731 } | |
732 b++; | |
733 a++; | |
734 } | |
31 | 735 *b = '\0'; // NUL-terminate the string (buf) |
26 | 736 ret = buf; |
737 } | |
16 | 738 } |
26 | 739 DEBUG_RET(); |
740 return ret; | |
16 | 741 } |
31 | 742 |
743 | |
16 | 744 int chr_count(char *str, char x) { |
26 | 745 int r = 0; |
746 while (*str != '\0') { | |
747 if (*str == x) | |
748 r++; | |
749 str++; | |
750 } | |
751 return r; | |
16 | 752 } |
31 | 753 |
754 | |
16 | 755 char *rfc2425_datetime_format(FILETIME *ft) { |
39 | 756 static char* buffer = NULL; |
26 | 757 struct tm *stm = NULL; |
758 DEBUG_ENT("rfc2425_datetime_format"); | |
39 | 759 if (!buffer) buffer = malloc(30); // should be enough for the date as defined below |
26 | 760 stm = fileTimeToStructTM(ft); |
761 if (strftime(buffer, 30, "%Y-%m-%dT%H:%M:%SZ", stm)==0) { | |
762 DEBUG_INFO(("Problem occured formatting date\n")); | |
763 } | |
764 DEBUG_RET(); | |
765 return buffer; | |
16 | 766 } |
31 | 767 |
768 | |
16 | 769 char *rfc2445_datetime_format(FILETIME *ft) { |
26 | 770 static char* buffer = NULL; |
771 struct tm *stm = NULL; | |
772 DEBUG_ENT("rfc2445_datetime_format"); | |
39 | 773 if (!buffer) buffer = malloc(30); // should be enough for the date as defined below |
26 | 774 stm = fileTimeToStructTM(ft); |
775 if (strftime(buffer, 30, "%Y%m%dT%H%M%SZ", stm)==0) { | |
776 DEBUG_INFO(("Problem occured formatting date\n")); | |
777 } | |
778 DEBUG_RET(); | |
779 return buffer; | |
16 | 780 } |
31 | 781 |
782 | |
16 | 783 // The sole purpose of this function is to bypass the pseudo-header prologue |
784 // that Microsoft Outlook inserts at the beginning of the internet email | |
785 // headers for emails stored in their "Personal Folders" files. | |
786 char *skip_header_prologue(char *headers) { | |
787 const char *bad = "Microsoft Mail Internet Headers"; | |
788 if ( strncmp(headers, bad, strlen(bad)) == 0 ) { | |
789 // Found the offensive header prologue | |
31 | 790 char *pc = strchr(headers, '\n'); |
16 | 791 return pc + 1; |
792 } | |
793 return headers; | |
794 } | |
795 | |
31 | 796 |
25 | 797 void write_separate_attachment(char f_name[], pst_item_attach* current_attach, int attach_num, pst_file* pst) |
798 { | |
31 | 799 DEBUG_ENT("write_separate_attachment"); |
25 | 800 FILE *fp = NULL; |
801 int x = 0; | |
31 | 802 char *temp = NULL; |
803 | |
804 // If there is a long filename (filename2) use that, otherwise | |
805 // use the 8.3 filename (filename1) | |
806 char *attach_filename = (current_attach->filename2) ? current_attach->filename2 | |
807 : current_attach->filename1; | |
25 | 808 |
809 check_filename(f_name); | |
31 | 810 if (!attach_filename) { |
811 // generate our own (dummy) filename for the attachement | |
25 | 812 temp = xmalloc(strlen(f_name)+15); |
813 sprintf(temp, "%s-attach%i", f_name, attach_num); | |
814 } else { | |
31 | 815 // have an attachment name, make sure it's unique |
816 temp = xmalloc(strlen(f_name)+strlen(attach_filename)+15); | |
25 | 817 do { |
31 | 818 if (fp) fclose(fp); |
25 | 819 if (x == 0) |
31 | 820 sprintf(temp, "%s-%s", f_name, attach_filename); |
25 | 821 else |
31 | 822 sprintf(temp, "%s-%s-%i", f_name, attach_filename, x); |
823 } while ((fp = fopen(temp, "r")) && ++x < 99999999); | |
25 | 824 if (x > 99999999) { |
825 DIE(("error finding attachment name. exhausted possibilities to %s\n", temp)); | |
826 } | |
827 } | |
31 | 828 DEBUG_EMAIL(("Saving attachment to %s\n", temp)); |
829 if (!(fp = fopen(temp, "w"))) { | |
25 | 830 WARN(("write_separate_attachment: Cannot open attachment save file \"%s\"\n", temp)); |
831 } else { | |
31 | 832 if (current_attach->data) |
25 | 833 fwrite(current_attach->data, 1, current_attach->size, fp); |
834 else { | |
835 pst_attach_to_file(pst, current_attach, fp); | |
836 } | |
837 fclose(fp); | |
838 } | |
31 | 839 if (temp) free(temp); |
840 DEBUG_RET(); | |
25 | 841 } |
842 | |
31 | 843 |
25 | 844 void write_inline_attachment(FILE* f_output, pst_item_attach* current_attach, char boundary[], pst_file* pst) |
845 { | |
31 | 846 DEBUG_ENT("write_inline_attachment"); |
25 | 847 char *enc; // base64 encoded attachment |
31 | 848 DEBUG_EMAIL(("Attachment Size is %i\n", current_attach->size)); |
849 DEBUG_EMAIL(("Attachment Pointer is %p\n", current_attach->data)); | |
850 if (current_attach->data) { | |
851 enc = base64_encode (current_attach->data, current_attach->size); | |
852 if (!enc) { | |
853 DEBUG_EMAIL(("ERROR base64_encode returned NULL. Must have failed\n")); | |
25 | 854 return; |
855 } | |
856 } | |
857 if (boundary) { | |
31 | 858 char *attach_filename; |
25 | 859 fprintf(f_output, "\n--%s\n", boundary); |
31 | 860 if (!current_attach->mimetype) { |
25 | 861 fprintf(f_output, "Content-type: %s\n", MIME_TYPE_DEFAULT); |
862 } else { | |
863 fprintf(f_output, "Content-type: %s\n", current_attach->mimetype); | |
864 } | |
865 fprintf(f_output, "Content-transfer-encoding: base64\n"); | |
31 | 866 // If there is a long filename (filename2) use that, otherwise |
867 // use the 8.3 filename (filename1) | |
868 if (current_attach->filename2) { | |
869 attach_filename = current_attach->filename2; | |
870 } else { | |
871 attach_filename = current_attach->filename1; | |
872 } | |
873 if (!attach_filename) { | |
25 | 874 fprintf(f_output, "Content-Disposition: inline\n\n"); |
875 } else { | |
31 | 876 fprintf(f_output, "Content-Disposition: attachment; filename=\"%s\"\n\n", attach_filename); |
25 | 877 } |
878 } | |
31 | 879 if (current_attach->data) { |
25 | 880 fwrite(enc, 1, strlen(enc), f_output); |
31 | 881 DEBUG_EMAIL(("Attachment Size after encoding is %i\n", strlen(enc))); |
36 | 882 free(enc); // caught by valgrind |
25 | 883 } else { |
884 pst_attach_to_file_base64(pst, current_attach, f_output); | |
885 } | |
886 fprintf(f_output, "\n\n"); | |
31 | 887 DEBUG_RET(); |
25 | 888 } |
889 | |
31 | 890 |
891 void write_normal_email(FILE* f_output, char f_name[], pst_item* item, int mode, int mode_MH, pst_file* pst, int save_rtf) | |
25 | 892 { |
31 | 893 DEBUG_ENT("write_normal_email"); |
894 char *boundary = NULL; // the boundary marker between multipart sections | |
895 int boundary_created = 0; // we have not (yet) created a new boundary | |
25 | 896 char *temp = NULL; |
897 int attach_num, base64_body = 0; | |
898 time_t em_time; | |
899 char *c_time; | |
31 | 900 pst_item_attach* current_attach; |
25 | 901 |
902 // convert the sent date if it exists, or set it to a fixed date | |
31 | 903 if (item->email->sent_date) { |
25 | 904 em_time = fileTimeToUnixTime(item->email->sent_date, 0); |
905 c_time = ctime(&em_time); | |
31 | 906 if (c_time) |
25 | 907 c_time[strlen(c_time)-1] = '\0'; //remove end \n |
908 else | |
909 c_time = "Fri Dec 28 12:06:21 2001"; | |
910 } else | |
911 c_time= "Fri Dec 28 12:06:21 2001"; | |
912 | |
913 // we will always look at the header to discover some stuff | |
31 | 914 if (item->email->header ) { |
25 | 915 char *b1, *b2; |
916 // see if there is a boundary variable there | |
917 // this search MUST be made case insensitive (DONE). | |
31 | 918 // Also, we should check to find out if we are looking |
919 // at the boundary associated with content-type, and that | |
920 // the content type really is multipart | |
25 | 921 |
922 removeCR(item->email->header); | |
923 | |
31 | 924 if ((b2 = my_stristr(item->email->header, "boundary="))) { |
925 int len; | |
25 | 926 b2 += strlen("boundary="); // move boundary to first char of marker |
31 | 927 |
25 | 928 if (*b2 == '"') { |
929 b2++; | |
930 b1 = strchr(b2, '"'); // find terminating quote | |
931 } else { | |
932 b1 = b2; | |
933 while (isgraph(*b1)) // find first char that isn't part of boundary | |
934 b1++; | |
935 } | |
31 | 936 len = b1 - b2; |
937 boundary = malloc(len+1); //malloc that length | |
938 strncpy(boundary, b2, len); // copy boundary to another variable | |
939 boundary[len] = '\0'; | |
25 | 940 b1 = b2 = boundary; |
941 while (*b2 != '\0') { // remove any CRs and Tabs | |
942 if (*b2 != '\n' && *b2 != '\r' && *b2 != '\t') { | |
943 *b1 = *b2; | |
944 b1++; | |
945 } | |
946 b2++; | |
947 } | |
948 *b1 = '\0'; | |
31 | 949 |
950 DEBUG_EMAIL(("Found boundary of - %s\n", boundary)); | |
25 | 951 } else { |
31 | 952 DEBUG_EMAIL(("boundary not found in header\n")); |
25 | 953 } |
954 | |
955 // also possible to set 7bit encoding detection here. | |
31 | 956 if ((b2 = my_stristr(item->email->header, "Content-Transfer-Encoding:"))) { |
957 if ((b2 = strchr(b2, ':'))) { | |
25 | 958 b2++; // skip to the : at the end of the string |
31 | 959 |
25 | 960 while (*b2 == ' ' || *b2 == '\t') |
961 b2++; | |
962 if (pst_strincmp(b2, "base64", 6)==0) { | |
31 | 963 DEBUG_EMAIL(("body is base64 encoded\n")); |
25 | 964 base64_body = 1; |
965 } | |
966 } else { | |
967 DEBUG_WARN(("found a ':' during the my_stristr, but not after that..\n")); | |
968 } | |
969 } | |
970 } | |
971 | |
31 | 972 if (!boundary && (item->attach || (item->email->body && item->email->htmlbody) |
973 || item->email->rtf_compressed || item->email->encrypted_body | |
974 || item->email->encrypted_htmlbody)) { | |
975 // we need to create a boundary here. | |
976 DEBUG_EMAIL(("must create own boundary. oh dear.\n")); | |
977 boundary = malloc(50 * sizeof(char)); // allow 50 chars for boundary | |
978 boundary[0] = '\0'; | |
979 sprintf(boundary, "--boundary-LibPST-iamunique-%i_-_-", rand()); | |
980 DEBUG_EMAIL(("created boundary is %s\n", boundary)); | |
981 boundary_created = 1; | |
25 | 982 } |
983 | |
31 | 984 DEBUG_EMAIL(("About to print Header\n")); |
985 | |
986 if (item && item->email && item->email->subject && item->email->subject->subj) { | |
987 DEBUG_EMAIL(("item->email->subject->subj = %s\n", item->email->subject->subj)); | |
988 } | |
989 | |
990 if (item->email->header) { | |
991 int len; | |
992 char *soh = NULL; // real start of headers. | |
993 | |
25 | 994 // some of the headers we get from the file are not properly defined. |
995 // they can contain some email stuff too. We will cut off the header | |
996 // when we see a \n\n or \r\n\r\n | |
31 | 997 removeCR(item->email->header); |
25 | 998 temp = strstr(item->email->header, "\n\n"); |
999 | |
31 | 1000 if (temp) { |
1001 DEBUG_EMAIL(("Found body text in header\n")); | |
1002 temp[1] = '\0'; // stop after first \n | |
25 | 1003 } |
31 | 1004 |
1005 // Now, write out the header... | |
1006 soh = skip_header_prologue(item->email->header); | |
25 | 1007 if (mode != MODE_SEPERATE) { |
1008 // don't put rubbish in if we are doing seperate | |
31 | 1009 if (strncmp(soh, "X-From_: ", 9) == 0 ) { |
1010 fputs("From ", f_output); | |
1011 soh += 9; | |
1012 } else | |
1013 fprintf(f_output, "From \"%s\" %s\n", item->email->outlook_sender_name, c_time); | |
25 | 1014 } |
31 | 1015 fprintf(f_output, "%s", soh); |
1016 len = strlen(soh); | |
1017 if (!len || (soh[len-1] != '\n')) fprintf(f_output, "\n"); | |
1018 | |
25 | 1019 } else { |
1020 //make up our own header! | |
1021 if (mode != MODE_SEPERATE) { | |
1022 // don't want this first line for this mode | |
31 | 1023 if (item->email->outlook_sender_name) { |
25 | 1024 temp = item->email->outlook_sender_name; |
1025 } else { | |
1026 temp = "(readpst_null)"; | |
1027 } | |
1028 fprintf(f_output, "From \"%s\" %s\n", temp, c_time); | |
1029 } | |
31 | 1030 |
1031 temp = item->email->outlook_sender; | |
1032 if (!temp) temp = ""; | |
25 | 1033 fprintf(f_output, "From: \"%s\" <%s>\n", item->email->outlook_sender_name, temp); |
31 | 1034 |
1035 if (item->email->subject) { | |
25 | 1036 fprintf(f_output, "Subject: %s\n", item->email->subject->subj); |
1037 } else { | |
1038 fprintf(f_output, "Subject: \n"); | |
1039 } | |
31 | 1040 |
25 | 1041 fprintf(f_output, "To: %s\n", item->email->sentto_address); |
31 | 1042 if (item->email->cc_address) { |
25 | 1043 fprintf(f_output, "Cc: %s\n", item->email->cc_address); |
1044 } | |
31 | 1045 |
1046 if (item->email->sent_date) { | |
25 | 1047 c_time = (char*) xmalloc(C_TIME_SIZE); |
1048 strftime(c_time, C_TIME_SIZE, "%a, %d %b %Y %H:%M:%S %z", gmtime(&em_time)); | |
1049 fprintf(f_output, "Date: %s\n", c_time); | |
1050 free(c_time); | |
1051 } | |
1052 } | |
1053 | |
31 | 1054 fprintf(f_output, "MIME-Version: 1.0\n"); |
1055 if (boundary && boundary_created) { | |
1056 // if we created the boundary, then it has NOT already been printed | |
1057 // in the headers above. | |
1058 if (item->attach) { | |
25 | 1059 // write the boundary stuff if we have attachments |
31 | 1060 fprintf(f_output, "Content-type: multipart/mixed;\n\tboundary=\"%s\"\n", boundary); |
1061 } else if (boundary) { | |
25 | 1062 // else if we have multipart/alternative then tell it so |
31 | 1063 fprintf(f_output, "Content-type: multipart/alternative;\n\tboundary=\"%s\"\n", boundary); |
25 | 1064 } else if (item->email->htmlbody) { |
1065 fprintf(f_output, "Content-type: text/html\n"); | |
1066 } | |
1067 } | |
31 | 1068 fprintf(f_output, "\n"); // start the body |
1069 DEBUG_EMAIL(("About to print Body\n")); | |
25 | 1070 |
31 | 1071 if (item->email->body) { |
25 | 1072 if (boundary) { |
1073 fprintf(f_output, "\n--%s\n", boundary); | |
31 | 1074 fprintf(f_output, "Content-type: text/plain\n"); |
25 | 1075 if (base64_body) |
1076 fprintf(f_output, "Content-Transfer-Encoding: base64\n"); | |
31 | 1077 fprintf(f_output, "\n"); |
25 | 1078 } |
1079 removeCR(item->email->body); | |
36 | 1080 if (base64_body) { |
1081 char *enc = base64_encode(item->email->body, strlen(item->email->body)); | |
1082 if (enc) { | |
1083 write_email_body(f_output, enc); | |
1084 free(enc); | |
1085 } | |
1086 } | |
1087 else { | |
25 | 1088 write_email_body(f_output, item->email->body); |
36 | 1089 } |
25 | 1090 } |
31 | 1091 |
1092 if (item->email->htmlbody) { | |
25 | 1093 if (boundary) { |
1094 fprintf(f_output, "\n--%s\n", boundary); | |
31 | 1095 fprintf(f_output, "Content-type: text/html\n"); |
36 | 1096 if (base64_body) fprintf(f_output, "Content-Transfer-Encoding: base64\n"); |
31 | 1097 fprintf(f_output, "\n"); |
25 | 1098 } |
1099 removeCR(item->email->htmlbody); | |
36 | 1100 if (base64_body) { |
1101 char *enc = base64_encode(item->email->htmlbody, strlen(item->email->htmlbody)); | |
1102 if (enc) { | |
1103 write_email_body(f_output, enc); | |
1104 free(enc); | |
1105 } | |
1106 } | |
1107 else { | |
25 | 1108 write_email_body(f_output, item->email->htmlbody); |
36 | 1109 } |
25 | 1110 } |
1111 | |
31 | 1112 if (item->email->rtf_compressed && save_rtf) { |
37 | 1113 //int32_t tester; |
31 | 1114 DEBUG_EMAIL(("Adding RTF body as attachment\n")); |
1115 current_attach = (pst_item_attach*)xmalloc(sizeof(pst_item_attach)); | |
1116 memset(current_attach, 0, sizeof(pst_item_attach)); | |
1117 current_attach->next = item->attach; | |
1118 item->attach = current_attach; | |
41
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
39
diff
changeset
|
1119 current_attach->data = lzfu_decompress(item->email->rtf_compressed, item->email->rtf_compressed_size, ¤t_attach->size); |
31 | 1120 current_attach->filename2 = xmalloc(strlen(RTF_ATTACH_NAME)+2); |
1121 strcpy(current_attach->filename2, RTF_ATTACH_NAME); | |
1122 current_attach->mimetype = xmalloc(strlen(RTF_ATTACH_TYPE)+2); | |
1123 strcpy(current_attach->mimetype, RTF_ATTACH_TYPE); | |
37 | 1124 //memcpy(&tester, item->email->rtf_compressed+sizeof(int32_t), sizeof(int32_t)); |
1125 //LE32_CPU(tester); | |
1126 //printf("lz produced %d bytes, rtf claims %d bytes\n", current_attach->size, tester); | |
25 | 1127 } |
31 | 1128 |
25 | 1129 if (item->email->encrypted_body || item->email->encrypted_htmlbody) { |
1130 // if either the body or htmlbody is encrypted, add them as attachments | |
1131 if (item->email->encrypted_body) { | |
31 | 1132 DEBUG_EMAIL(("Adding Encrypted Body as attachment\n")); |
1133 current_attach = (pst_item_attach*) xmalloc(sizeof(pst_item_attach)); | |
1134 memset(current_attach, 0, sizeof(pst_item_attach)); | |
1135 current_attach->next = item->attach; | |
1136 item->attach = current_attach; | |
1137 current_attach->data = item->email->encrypted_body; | |
1138 current_attach->size = item->email->encrypted_body_size; | |
25 | 1139 item->email->encrypted_body = NULL; |
1140 } | |
31 | 1141 |
25 | 1142 if (item->email->encrypted_htmlbody) { |
31 | 1143 DEBUG_EMAIL(("Adding encrypted HTML body as attachment\n")); |
1144 current_attach = (pst_item_attach*) xmalloc(sizeof(pst_item_attach)); | |
1145 memset(current_attach, 0, sizeof(pst_item_attach)); | |
1146 current_attach->next = item->attach; | |
1147 item->attach = current_attach; | |
1148 current_attach->data = item->email->encrypted_htmlbody; | |
1149 current_attach->size = item->email->encrypted_htmlbody_size; | |
25 | 1150 item->email->encrypted_htmlbody = NULL; |
1151 } | |
1152 write_email_body(f_output, "The body of this email is encrypted. This isn't supported yet, but the body is now an attachment\n"); | |
1153 } | |
31 | 1154 |
25 | 1155 // attachments |
1156 attach_num = 0; | |
39 | 1157 for (current_attach = item->attach; current_attach; current_attach = current_attach->next) { |
31 | 1158 DEBUG_EMAIL(("Attempting Attachment encoding\n")); |
1159 if (!current_attach->data) { | |
1160 DEBUG_EMAIL(("Data of attachment is NULL!. Size is supposed to be %i\n", current_attach->size)); | |
25 | 1161 } |
1162 if (mode == MODE_SEPERATE && !mode_MH) | |
31 | 1163 write_separate_attachment(f_name, current_attach, ++attach_num, pst); |
25 | 1164 else |
31 | 1165 write_inline_attachment(f_output, current_attach, boundary, pst); |
25 | 1166 } |
1167 if (mode != MODE_SEPERATE) { /* do not add a boundary after the last attachment for mode_MH */ | |
31 | 1168 DEBUG_EMAIL(("Writing buffer between emails\n")); |
1169 if (boundary) fprintf(f_output, "\n--%s--\n", boundary); | |
25 | 1170 fprintf(f_output, "\n\n"); |
1171 } | |
31 | 1172 if (boundary) free (boundary); |
1173 DEBUG_RET(); | |
25 | 1174 } |
1175 | |
31 | 1176 |
25 | 1177 void write_vcard(FILE* f_output, pst_item_contact* contact, char comment[]) |
1178 { | |
39 | 1179 // We can only call rfc escape once per printf, since the second call |
1180 // may free the buffer returned by the first call. | |
1181 // I had tried to place those into a single printf - Carl. | |
1182 | |
31 | 1183 DEBUG_ENT("write_vcard"); |
25 | 1184 // the specification I am following is (hopefully) RFC2426 vCard Mime Directory Profile |
1185 fprintf(f_output, "BEGIN:VCARD\n"); | |
1186 fprintf(f_output, "FN:%s\n", rfc2426_escape(contact->fullname)); | |
39 | 1187 |
1188 //fprintf(f_output, "N:%s;%s;%s;%s;%s\n", | |
1189 fprintf(f_output, "N:%s;", (!contact->surname) ? "" : rfc2426_escape(contact->surname)); | |
1190 fprintf(f_output, "%s;", (!contact->first_name) ? "" : rfc2426_escape(contact->first_name)); | |
1191 fprintf(f_output, "%s;", (!contact->middle_name) ? "" : rfc2426_escape(contact->middle_name)); | |
1192 fprintf(f_output, "%s;", (!contact->display_name_prefix) ? "" : rfc2426_escape(contact->display_name_prefix)); | |
1193 fprintf(f_output, "%s\n", (!contact->suffix) ? "" : rfc2426_escape(contact->suffix)); | |
1194 | |
31 | 1195 if (contact->nickname) |
25 | 1196 fprintf(f_output, "NICKNAME:%s\n", rfc2426_escape(contact->nickname)); |
31 | 1197 if (contact->address1) |
25 | 1198 fprintf(f_output, "EMAIL:%s\n", rfc2426_escape(contact->address1)); |
31 | 1199 if (contact->address2) |
25 | 1200 fprintf(f_output, "EMAIL:%s\n", rfc2426_escape(contact->address2)); |
31 | 1201 if (contact->address3) |
25 | 1202 fprintf(f_output, "EMAIL:%s\n", rfc2426_escape(contact->address3)); |
31 | 1203 if (contact->birthday) |
25 | 1204 fprintf(f_output, "BDAY:%s\n", rfc2425_datetime_format(contact->birthday)); |
39 | 1205 |
31 | 1206 if (contact->home_address) { |
39 | 1207 //fprintf(f_output, "ADR;TYPE=home:%s;%s;%s;%s;%s;%s;%s\n", |
1208 fprintf(f_output, "ADR;TYPE=home:%s;", (!contact->home_po_box) ? "" : rfc2426_escape(contact->home_po_box)); | |
1209 fprintf(f_output, "%s;", ""); // extended Address | |
1210 fprintf(f_output, "%s;", (!contact->home_street) ? "" : rfc2426_escape(contact->home_street)); | |
1211 fprintf(f_output, "%s;", (!contact->home_city) ? "" : rfc2426_escape(contact->home_city)); | |
1212 fprintf(f_output, "%s;", (!contact->home_state) ? "" : rfc2426_escape(contact->home_state)); | |
1213 fprintf(f_output, "%s;", (!contact->home_postal_code) ? "" : rfc2426_escape(contact->home_postal_code)); | |
1214 fprintf(f_output, "%s\n", (!contact->home_country) ? "" : rfc2426_escape(contact->home_country)); | |
25 | 1215 fprintf(f_output, "LABEL;TYPE=home:%s\n", rfc2426_escape(contact->home_address)); |
1216 } | |
39 | 1217 |
31 | 1218 if (contact->business_address) { |
39 | 1219 //fprintf(f_output, "ADR;TYPE=work:%s;%s;%s;%s;%s;%s;%s\n", |
1220 fprintf(f_output, "ADR;TYPE=work:%s;", (!contact->business_po_box) ? "" : rfc2426_escape(contact->business_po_box)); | |
1221 fprintf(f_output, "%s;", ""); // extended Address | |
1222 fprintf(f_output, "%s;", (!contact->business_street) ? "" : rfc2426_escape(contact->business_street)); | |
1223 fprintf(f_output, "%s;", (!contact->business_city) ? "" : rfc2426_escape(contact->business_city)); | |
1224 fprintf(f_output, "%s;", (!contact->business_state) ? "" : rfc2426_escape(contact->business_state)); | |
1225 fprintf(f_output, "%s;", (!contact->business_postal_code) ? "" : rfc2426_escape(contact->business_postal_code)); | |
1226 fprintf(f_output, "%s\n", (!contact->business_country) ? "" : rfc2426_escape(contact->business_country)); | |
25 | 1227 fprintf(f_output, "LABEL;TYPE=work:%s\n", rfc2426_escape(contact->business_address)); |
1228 } | |
39 | 1229 |
31 | 1230 if (contact->other_address) { |
39 | 1231 //fprintf(f_output, "ADR;TYPE=postal:%s;%s;%s;%s;%s;%s;%s\n", |
1232 fprintf(f_output, "ADR;TYPE=postal:%s;",(!contact->other_po_box) ? "" : rfc2426_escape(contact->other_po_box)); | |
1233 fprintf(f_output, "%s;", ""); // extended Address | |
1234 fprintf(f_output, "%s;", (!contact->other_street) ? "" : rfc2426_escape(contact->other_street)); | |
1235 fprintf(f_output, "%s;", (!contact->other_city) ? "" : rfc2426_escape(contact->other_city)); | |
1236 fprintf(f_output, "%s;", (!contact->other_state) ? "" : rfc2426_escape(contact->other_state)); | |
1237 fprintf(f_output, "%s;", (!contact->other_postal_code) ? "" : rfc2426_escape(contact->other_postal_code)); | |
1238 fprintf(f_output, "%s\n", (!contact->other_country) ? "" : rfc2426_escape(contact->other_country)); | |
31 | 1239 fprintf(f_output, "LABEL;TYPE=postal:%s\n", rfc2426_escape(contact->other_address)); |
25 | 1240 } |
39 | 1241 |
1242 if (contact->business_fax) fprintf(f_output, "TEL;TYPE=work,fax:%s\n", rfc2426_escape(contact->business_fax)); | |
1243 if (contact->business_phone) fprintf(f_output, "TEL;TYPE=work,voice:%s\n", rfc2426_escape(contact->business_phone)); | |
1244 if (contact->business_phone2) fprintf(f_output, "TEL;TYPE=work,voice:%s\n", rfc2426_escape(contact->business_phone2)); | |
1245 if (contact->car_phone) fprintf(f_output, "TEL;TYPE=car,voice:%s\n", rfc2426_escape(contact->car_phone)); | |
1246 if (contact->home_fax) fprintf(f_output, "TEL;TYPE=home,fax:%s\n", rfc2426_escape(contact->home_fax)); | |
1247 if (contact->home_phone) fprintf(f_output, "TEL;TYPE=home,voice:%s\n", rfc2426_escape(contact->home_phone)); | |
1248 if (contact->home_phone2) fprintf(f_output, "TEL;TYPE=home,voice:%s\n", rfc2426_escape(contact->home_phone2)); | |
1249 if (contact->isdn_phone) fprintf(f_output, "TEL;TYPE=isdn:%s\n", rfc2426_escape(contact->isdn_phone)); | |
1250 if (contact->mobile_phone) fprintf(f_output, "TEL;TYPE=cell,voice:%s\n", rfc2426_escape(contact->mobile_phone)); | |
1251 if (contact->other_phone) fprintf(f_output, "TEL;TYPE=msg:%s\n", rfc2426_escape(contact->other_phone)); | |
1252 if (contact->pager_phone) fprintf(f_output, "TEL;TYPE=pager:%s\n", rfc2426_escape(contact->pager_phone)); | |
1253 if (contact->primary_fax) fprintf(f_output, "TEL;TYPE=fax,pref:%s\n", rfc2426_escape(contact->primary_fax)); | |
1254 if (contact->primary_phone) fprintf(f_output, "TEL;TYPE=phone,pref:%s\n", rfc2426_escape(contact->primary_phone)); | |
1255 if (contact->radio_phone) fprintf(f_output, "TEL;TYPE=pcs:%s\n", rfc2426_escape(contact->radio_phone)); | |
1256 if (contact->telex) fprintf(f_output, "TEL;TYPE=bbs:%s\n", rfc2426_escape(contact->telex)); | |
1257 if (contact->job_title) fprintf(f_output, "TITLE:%s\n", rfc2426_escape(contact->job_title)); | |
1258 if (contact->profession) fprintf(f_output, "ROLE:%s\n", rfc2426_escape(contact->profession)); | |
1259 if (contact->assistant_name || contact->assistant_phone) { | |
31 | 1260 fprintf(f_output, "AGENT:BEGIN:VCARD\n"); |
39 | 1261 if (contact->assistant_name) fprintf(f_output, "FN:%s\n", rfc2426_escape(contact->assistant_name)); |
1262 if (contact->assistant_phone) fprintf(f_output, "TEL:%s\n", rfc2426_escape(contact->assistant_phone)); | |
25 | 1263 } |
39 | 1264 if (contact->company_name) fprintf(f_output, "ORG:%s\n", rfc2426_escape(contact->company_name)); |
1265 if (comment) fprintf(f_output, "NOTE:%s\n", rfc2426_escape(comment)); | |
25 | 1266 |
1267 fprintf(f_output, "VERSION: 3.0\n"); | |
1268 fprintf(f_output, "END:VCARD\n\n"); | |
31 | 1269 DEBUG_RET(); |
25 | 1270 } |
1271 | |
31 | 1272 |
25 | 1273 void write_appointment(FILE* f_output, pst_item_appointment* appointment, |
31 | 1274 pst_item_email* email, FILETIME* create_date, FILETIME* modify_date) |
25 | 1275 { |
1276 fprintf(f_output, "BEGIN:VEVENT\n"); | |
31 | 1277 if (create_date) |
25 | 1278 fprintf(f_output, "CREATED:%s\n", |
1279 rfc2445_datetime_format(create_date)); | |
31 | 1280 if (modify_date) |
25 | 1281 fprintf(f_output, "LAST-MOD:%s\n", |
1282 rfc2445_datetime_format(modify_date)); | |
31 | 1283 if (email && email->subject) |
25 | 1284 fprintf(f_output, "SUMMARY:%s\n", |
1285 rfc2426_escape(email->subject->subj)); | |
31 | 1286 if (email && email->body) |
25 | 1287 fprintf(f_output, "DESCRIPTION:%s\n", |
1288 rfc2426_escape(email->body)); | |
31 | 1289 if (appointment && appointment->start) |
25 | 1290 fprintf(f_output, "DTSTART;VALUE=DATE-TIME:%s\n", |
1291 rfc2445_datetime_format(appointment->start)); | |
31 | 1292 if (appointment && appointment->end) |
25 | 1293 fprintf(f_output, "DTEND;VALUE=DATE-TIME:%s\n", |
1294 rfc2445_datetime_format(appointment->end)); | |
31 | 1295 if (appointment && appointment->location) |
25 | 1296 fprintf(f_output, "LOCATION:%s\n", |
1297 rfc2426_escape(appointment->location)); | |
31 | 1298 if (appointment) { |
25 | 1299 switch (appointment->showas) { |
1300 case PST_FREEBUSY_TENTATIVE: | |
1301 fprintf(f_output, "STATUS:TENTATIVE\n"); | |
1302 break; | |
1303 case PST_FREEBUSY_FREE: | |
1304 // mark as transparent and as confirmed | |
1305 fprintf(f_output, "TRANSP:TRANSPARENT\n"); | |
1306 case PST_FREEBUSY_BUSY: | |
1307 case PST_FREEBUSY_OUT_OF_OFFICE: | |
1308 fprintf(f_output, "STATUS:CONFIRMED\n"); | |
1309 break; | |
1310 } | |
1311 switch (appointment->label) { | |
1312 case PST_APP_LABEL_NONE: | |
1313 fprintf(f_output, "CATEGORIES:NONE\n"); | |
1314 break; | |
1315 case PST_APP_LABEL_IMPORTANT: | |
1316 fprintf(f_output, "CATEGORIES:IMPORTANT\n"); | |
1317 break; | |
1318 case PST_APP_LABEL_BUSINESS: | |
1319 fprintf(f_output, "CATEGORIES:BUSINESS\n"); | |
1320 break; | |
1321 case PST_APP_LABEL_PERSONAL: | |
1322 fprintf(f_output, "CATEGORIES:PERSONAL\n"); | |
1323 break; | |
1324 case PST_APP_LABEL_VACATION: | |
1325 fprintf(f_output, "CATEGORIES:VACATION\n"); | |
1326 break; | |
1327 case PST_APP_LABEL_MUST_ATTEND: | |
1328 fprintf(f_output, "CATEGORIES:MUST-ATTEND\n"); | |
1329 break; | |
1330 case PST_APP_LABEL_TRAVEL_REQ: | |
1331 fprintf(f_output, "CATEGORIES:TRAVEL-REQUIRED\n"); | |
1332 break; | |
1333 case PST_APP_LABEL_NEEDS_PREP: | |
1334 fprintf(f_output, "CATEGORIES:NEEDS-PREPARATION\n"); | |
1335 break; | |
1336 case PST_APP_LABEL_BIRTHDAY: | |
1337 fprintf(f_output, "CATEGORIES:BIRTHDAY\n"); | |
1338 break; | |
1339 case PST_APP_LABEL_ANNIVERSARY: | |
1340 fprintf(f_output, "CATEGORIES:ANNIVERSARY\n"); | |
1341 break; | |
1342 case PST_APP_LABEL_PHONE_CALL: | |
1343 fprintf(f_output, "CATEGORIES:PHONE-CALL\n"); | |
1344 break; | |
1345 } | |
1346 } | |
1347 fprintf(f_output, "END:VEVENT\n\n"); | |
1348 } | |
1349 | |
31 | 1350 |
39 | 1351 void create_enter_dir(struct file_ll* f, pst_item *item) |
25 | 1352 { |
39 | 1353 f->email_count = 0; |
1354 f->skip_count = 0; | |
1355 f->type = item->type; | |
1356 f->stored_count = (item->folder) ? item->folder->email_count : 0; | |
1357 | |
31 | 1358 DEBUG_ENT("create_enter_dir"); |
25 | 1359 if (mode == MODE_KMAIL) |
39 | 1360 f->name = mk_kmail_dir(item->file_as); //create directory and form filename |
25 | 1361 else if (mode == MODE_RECURSE) |
39 | 1362 f->name = mk_recurse_dir(item->file_as); |
25 | 1363 else if (mode == MODE_SEPERATE) { |
1364 // do similar stuff to recurse here. | |
39 | 1365 mk_seperate_dir(item->file_as); |
25 | 1366 f->name = (char*) xmalloc(10); |
1367 memset(f->name, 0, 10); | |
1368 // sprintf(f->name, SEP_MAIL_FILE_TEMPLATE, f->email_count); | |
1369 } else { | |
39 | 1370 f->name = (char*) xmalloc(strlen(item->file_as)+strlen(OUTPUT_TEMPLATE)+1); |
1371 sprintf(f->name, OUTPUT_TEMPLATE, item->file_as); | |
25 | 1372 } |
1373 | |
39 | 1374 f->dname = (char*) xmalloc(strlen(item->file_as)+1); |
1375 strcpy(f->dname, item->file_as); | |
25 | 1376 |
1377 if (overwrite != 1) { | |
1378 int x = 0; | |
1379 char *temp = (char*) xmalloc (strlen(f->name)+10); //enough room for 10 digits | |
1380 | |
1381 sprintf(temp, "%s", f->name); | |
41
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
39
diff
changeset
|
1382 check_filename(temp); |
31 | 1383 while ((f->output = fopen(temp, "r"))) { |
1384 DEBUG_MAIN(("need to increase filename because one already exists with that name\n")); | |
1385 DEBUG_MAIN(("- increasing it to %s%d\n", f->name, x)); | |
25 | 1386 x++; |
1387 sprintf(temp, "%s%08d", f->name, x); | |
31 | 1388 DEBUG_MAIN(("- trying \"%s\"\n", f->name)); |
25 | 1389 if (x == 99999999) { |
1390 DIE(("create_enter_dir: Why can I not create a folder %s? I have tried %i extensions...\n", f->name, x)); | |
1391 } | |
1392 fclose(f->output); | |
1393 } | |
1394 if (x > 0) { //then the f->name should change | |
1395 free (f->name); | |
1396 f->name = temp; | |
1397 } else { | |
1398 free(temp); | |
1399 } | |
1400 } | |
1401 | |
39 | 1402 DEBUG_MAIN(("f->name = %s\nitem->folder_name = %s\n", f->name, item->file_as)); |
25 | 1403 if (mode != MODE_SEPERATE) { |
41
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
39
diff
changeset
|
1404 check_filename(f->name); |
31 | 1405 if (!(f->output = fopen(f->name, "w"))) { |
25 | 1406 DIE(("create_enter_dir: Could not open file \"%s\" for write\n", f->name)); |
1407 } | |
1408 } | |
31 | 1409 DEBUG_RET(); |
25 | 1410 } |
1411 | |
39 | 1412 |
1413 void close_enter_dir(struct file_ll *f) | |
1414 { | |
1415 DEBUG_MAIN(("main: Email Count for folder %s is %i\n", f->dname, f->email_count)); | |
1416 if (output_mode != OUTPUT_QUIET) | |
1417 printf("\t\"%s\" - %i items done, skipped %i, should have been %i\n", | |
1418 f->dname, f->email_count, f->skip_count, f->stored_count); | |
1419 if (f->output) fclose(f->output); | |
1420 free(f->name); | |
1421 free(f->dname); | |
1422 | |
1423 if (mode == MODE_KMAIL) | |
1424 close_kmail_dir(); | |
1425 else if (mode == MODE_RECURSE) | |
1426 close_recurse_dir(); | |
1427 else if (mode == MODE_SEPERATE) | |
1428 close_seperate_dir(); | |
1429 } | |
1430 |