diff --git a/Makefile b/Makefile index cde2166..becd262 100644 --- a/Makefile +++ b/Makefile @@ -1,88 +1,89 @@ #!/usr/bin/make -f CFLAGS ?= -g -Wall PREFIX ?= /usr/local INSTALL ?= install #---------------- Do not modify below this point ------------------ INSTALL_DIR := $(INSTALL) -p -d -o root -g root -m 0755 INSTALL_FILE := $(INSTALL) -p -o root -g root -m 0644 INSTALL_PROGRAM := $(INSTALL) -p -o root -g root -m 0755 # -s INSTALL_SCRIPT := $(INSTALL) -p -o root -g root -m 0755 VERSION = $(shell cat VERSION) CFLAGS += -DVERSION=\"$(VERSION)\" +CPPFLAGS += -DVERSION=\"$(VERSION)\" DOCS := AUTHORS ChangeLog CREDITS FILE-FORMAT FILE-FORMAT.html LICENSE TODO \ VERSION DISTFILES := $(DOCS) Makefile setup1.vdproj XGetopt.c XGetopt.h common.h \ debug.c define.h dumpblocks.c getidblock.c libpst.c libpst.h \ libstrfunc.c libstrfunc.h lspst.c lzfu.c lzfu.h moz-script \ readlog.vcproj readpst.1 readpst.c readpstlog.1 readpstlog.c \ testdebug.c timeconv.c timeconv.h w32pst.sln w32pst.vcproj \ nick2ldif.cpp pst2ldif.cpp PROGS := lspst readpst readpstlog pst2ldif nick2ldif ALL_PROGS := $(PROGS) dumpblocks getidblock testdebug all: $(PROGS) XGetopt.o: XGetopt.h debug.o: define.h dumpblocks.o: define.h getidblock.o: XGetopt.h define.h libpst.h libpst.o: define.h libstrfunc.h libpst.h timeconv.h libstrfunc.o: libstrfunc.h lspst.o: libpst.h timeconv.h lzfu.o: define.h libpst.h lzfu.h readpst.o: XGetopt.h libstrfunc.h define.h libpst.h common.h timeconv.h lzfu.h pst2ldif.o: XGetopt.h libstrfunc.h define.h libpst.h common.h timeconv.h lzfu.h nick2ldif.o: XGetopt.h libstrfunc.h define.h libpst.h common.h timeconv.h lzfu.h readpstlog.o: XGetopt.h define.h testdebug.o: define.h timeconv.o: timeconv.h common.h readpst: readpst.o libpst.o timeconv.o libstrfunc.o debug.o lzfu.o lspst: debug.o libpst.o libstrfunc.o lspst.o timeconv.o getidblock: getidblock.o libpst.o debug.o libstrfunc.o testdebug: testdebug.o debug.o readpstlog: readpstlog.o debug.o dumpblocks: dumpblocks.o libpst.o debug.o libstrfunc.o pst2ldif: pst2ldif.o libpst.o timeconv.o libstrfunc.o debug.o lzfu.o g++ ${CFLAGS} pst2ldif.cpp -o pst2ldif libpst.o timeconv.o libstrfunc.o debug.o lzfu.o nick2ldif: nick2ldif.o libpst.o timeconv.o libstrfunc.o debug.o lzfu.o g++ ${CFLAGS} nick2ldif.cpp -o nick2ldif libpst.o timeconv.o libstrfunc.o debug.o lzfu.o clean: rm -f core *.o readpst.log $(ALL_PROGS) *~ MANIFEST distclean: clean rm -f libpst-*.tar.gz install: all $(INSTALL_DIR) $(DESTDIR)$(PREFIX)/bin $(INSTALL_PROGRAM) readpst{,log} $(DESTDIR)$(PREFIX)/bin $(INSTALL_DIR) $(DESTDIR)$(PREFIX)/share/man/man1 $(INSTALL_FILE) readpst{,log}.1 $(DESTDIR)$(PREFIX)/share/man/man1/ $(INSTALL_DIR) $(DESTDIR)$(PREFIX)/share/doc/libpst $(INSTALL_FILE) $(DOCS) $(DESTDIR)$(PREFIX)/share/doc/libpst/ uninstall: -rm -f $(DESTDIR)$(PREFIX)/bin/readpst{,log} -rm -f $(DESTDIR)$(PREFIX)/share/man/man1/readpst{,log}.1 # stolen from ESR's Software Release Practices HOWTO available at: # http://en.tldp.org/HOWTO/Software-Release-Practice-HOWTO/distpractice.html MANIFEST: Makefile @ls $(DISTFILES) | sed s:^:libpst-$(VERSION)/: >MANIFEST tarball libpst-$(VERSION).tar.gz: MANIFEST $(DISTFILES) @(cd ..; ln -s libpst libpst-$(VERSION)) (cd ..; tar -czvf libpst/libpst-$(VERSION).tar.gz `cat libpst/MANIFEST`) @(cd ..; rm libpst-$(VERSION)) @rm -f MANIFEST .PHONY: clean distclean uninstall install tarball diff --git a/VERSION b/VERSION index cb0c939..be14282 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.5.2 +0.5.3 diff --git a/libpst.h b/libpst.h index f15c0ec..c0ff393 100644 --- a/libpst.h +++ b/libpst.h @@ -1,510 +1,507 @@ /*** * libpst.h * Part of LibPST project * Written by David Smith * dave.s@earthcorp.com */ // LibPST - Library for Accessing Outlook .pst files // Dave Smith - davesmith@users.sourceforge.net #ifndef LIBPST_H #define LIBPST_H #ifndef _MSC_VER #ifndef FILETIME_DEFINED #define FILETIME_DEFINED //Win32 Filetime struct - copied from WINE typedef struct { u_int32_t dwLowDateTime; u_int32_t dwHighDateTime; } FILETIME; #endif //ifndef FILETIME_DEFINED #endif //ifndef _MSC_VER // define the INT32_MAX here cause it isn't normally defined #ifndef INT32_MAX # define INT32_MAX INT_MAX #endif // According to Jan Wolter, sys/param.h is the most portable source of endian // information on UNIX systems. see http://www.unixpapa.com/incnote/byteorder.html #ifdef _MSC_VER #define BYTE_ORDER LITTLE_ENDIAN #else #include #endif // defined _MSC_VER #if BYTE_ORDER == BIG_ENDIAN # define LE64_CPU(x) \ x = ((((x) & 0xff00000000000000) >> 56) | \ (((x) & 0x00ff000000000000) >> 40) | \ (((x) & 0x0000ff0000000000) >> 24) | \ (((x) & 0x000000ff00000000) >> 8 ) | \ (((x) & 0x00000000ff000000) << 8 ) | \ (((x) & 0x0000000000ff0000) << 24) | \ (((x) & 0x000000000000ff00) << 40) | \ (((x) & 0x00000000000000ff) << 56)); # define LE32_CPU(x) \ x = ((((x) & 0xff000000) >> 24) | \ (((x) & 0x00ff0000) >> 8 ) | \ (((x) & 0x0000ff00) << 8 ) | \ (((x) & 0x000000ff) << 24)); # define LE16_CPU(x) \ x = ((((x) & 0xff00) >> 8) | \ (((x) & 0x00ff) << 8)); #elif BYTE_ORDER == LITTLE_ENDIAN # define LE64_CPU(x) {} # define LE32_CPU(x) {} # define LE16_CPU(x) {} #else # error "Byte order not supported by this library" #endif // BYTE_ORDER #ifdef _MSC_VER #include "windows.h" #define int32_t int #define u_int32_t unsigned int #define int16_t short int #define u_int16_t unsigned short int #endif // _MSC_VER - -#define PST_VERSION "0.5.1" - #define PST_TYPE_NOTE 1 #define PST_TYPE_APPOINTMENT 8 #define PST_TYPE_CONTACT 9 #define PST_TYPE_JOURNAL 10 #define PST_TYPE_STICKYNOTE 11 #define PST_TYPE_TASK 12 #define PST_TYPE_OTHER 13 #define PST_TYPE_REPORT 14 // defines whether decryption is done on this bit of data #define PST_NO_ENC 0 #define PST_ENC 1 // defines types of possible encryption #define PST_NO_ENCRYPT 0 #define PST_COMP_ENCRYPT 1 #define PST_ENCRYPT 2 // defines different types of mappings #define PST_MAP_ATTRIB 1 #define PST_MAP_HEADER 2 // define my custom email attributes. #define PST_ATTRIB_HEADER -1 // defines types of free/busy values for appointment->showas #define PST_FREEBUSY_FREE 0 #define PST_FREEBUSY_TENTATIVE 1 #define PST_FREEBUSY_BUSY 2 #define PST_FREEBUSY_OUT_OF_OFFICE 3 // defines labels for appointment->label #define PST_APP_LABEL_NONE 0 // None #define PST_APP_LABEL_IMPORTANT 1 // Important #define PST_APP_LABEL_BUSINESS 2 // Business #define PST_APP_LABEL_PERSONAL 3 // Personal #define PST_APP_LABEL_VACATION 4 // Vacation #define PST_APP_LABEL_MUST_ATTEND 5 // Must Attend #define PST_APP_LABEL_TRAVEL_REQ 6 // Travel Required #define PST_APP_LABEL_NEEDS_PREP 7 // Needs Preparation #define PST_APP_LABEL_BIRTHDAY 8 // Birthday #define PST_APP_LABEL_ANNIVERSARY 9 // Anniversary #define PST_APP_LABEL_PHONE_CALL 10// Phone Call typedef struct _pst_misc_6_struct { int32_t i1; int32_t i2; int32_t i3; int32_t i4; int32_t i5; int32_t i6; } pst_misc_6; typedef struct _pst_entryid_struct { int32_t u1; char entryid[16]; int32_t id; } pst_entryid; typedef struct _pst_desc_struct { u_int32_t d_id; u_int32_t desc_id; u_int32_t list_id; u_int32_t parent_id; } pst_desc; typedef struct _pst_index_struct{ u_int32_t id; int32_t offset; u_int16_t size; int16_t u1; } pst_index; typedef struct _pst_index_tree { u_int32_t id; int32_t offset; size_t size; int32_t u1; struct _pst_index_tree * next; } pst_index_ll; typedef struct _pst_index2_tree { int32_t id2; pst_index_ll *id; struct _pst_index2_tree * next; } pst_index2_ll; typedef struct _pst_desc_tree { u_int32_t id; pst_index_ll * list_index; pst_index_ll * desc; int32_t no_child; struct _pst_desc_tree * prev; struct _pst_desc_tree * next; struct _pst_desc_tree * parent; struct _pst_desc_tree * child; struct _pst_desc_tree * child_tail; } pst_desc_ll; typedef struct _pst_item_email_subject { int32_t off1; int32_t off2; char *subj; } pst_item_email_subject; typedef struct _pst_item_email { FILETIME *arrival_date; int32_t autoforward; // 1 = true, 0 = not set, -1 = false char *body; char *cc_address; char *common_name; int32_t conv_index; int32_t conversion_prohib; int32_t delete_after_submit; // 1 = true, 0 = false int32_t delivery_report; // 1 = true, 0 = false char *encrypted_body; int32_t encrypted_body_size; char *encrypted_htmlbody; int32_t encrypted_htmlbody_size; int32_t flag; char *header; char *htmlbody; int32_t importance; char *in_reply_to; int32_t message_cc_me; // 1 = true, 0 = false int32_t message_recip_me; // 1 = true, 0 = false int32_t message_to_me; // 1 = true, 0 = false char *messageid; int32_t orig_sensitivity; char *outlook_recipient; char *outlook_recipient2; char *outlook_sender; char *outlook_sender_name; char *outlook_sender2; int32_t priority; char *proc_subject; int32_t read_receipt; char *recip_access; char *recip_address; char *recip2_access; char *recip2_address; int32_t reply_requested; char *reply_to; char *return_path_address; int32_t rtf_body_char_count; int32_t rtf_body_crc; char *rtf_body_tag; char *rtf_compressed; int32_t rtf_in_sync; // 1 = true, 0 = doesn't exist, -1 = false int32_t rtf_ws_prefix_count; int32_t rtf_ws_trailing_count; char *sender_access; char *sender_address; char *sender2_access; char *sender2_address; int32_t sensitivity; FILETIME *sent_date; pst_entryid *sentmail_folder; char *sentto_address; pst_item_email_subject *subject; } pst_item_email; typedef struct _pst_item_folder { int32_t email_count; int32_t unseen_email_count; int32_t assoc_count; char subfolder; } pst_item_folder; typedef struct _pst_item_message_store { pst_entryid *deleted_items_folder; pst_entryid *search_root_folder; pst_entryid *top_of_personal_folder; pst_entryid *top_of_folder; int32_t valid_mask; // what folders the message store contains int32_t pwd_chksum; } pst_item_message_store; typedef struct _pst_item_contact { char *access_method; char *account_name; char *address1; char *address1a; char *address1_desc; char *address1_transport; char *address2; char *address2a; char *address2_desc; char *address2_transport; char *address3; char *address3a; char *address3_desc; char *address3_transport; char *assistant_name; char *assistant_phone; char *billing_information; FILETIME *birthday; char *business_address; char *business_city; char *business_country; char *business_fax; char *business_homepage; char *business_phone; char *business_phone2; char *business_po_box; char *business_postal_code; char *business_state; char *business_street; char *callback_phone; char *car_phone; char *company_main_phone; char *company_name; char *computer_name; char *customer_id; char *def_postal_address; char *department; char *display_name_prefix; char *first_name; char *followup; char *free_busy_address; char *ftp_site; char *fullname; int32_t gender; char *gov_id; char *hobbies; char *home_address; char *home_city; char *home_country; char *home_fax; char *home_phone; char *home_phone2; char *home_po_box; char *home_postal_code; char *home_state; char *home_street; char *initials; char *isdn_phone; char *job_title; char *keyword; char *language; char *location; int32_t mail_permission; char *manager_name; char *middle_name; char *mileage; char *mobile_phone; char *nickname; char *office_loc; char *org_id; char *other_address; char *other_city; char *other_country; char *other_phone; char *other_po_box; char *other_postal_code; char *other_state; char *other_street; char *pager_phone; char *personal_homepage; char *pref_name; char *primary_fax; char *primary_phone; char *profession; char *radio_phone; int32_t rich_text; char *spouse_name; char *suffix; char *surname; char *telex; char *transmittable_display_name; char *ttytdd_phone; FILETIME *wedding_anniversary; } pst_item_contact; typedef struct _pst_item_attach { char *filename1; char *filename2; char *mimetype; char *data; size_t size; int32_t id2_val; int32_t id_val; // calculated from id2_val during creation of record int32_t method; int32_t position; int32_t sequence; struct _pst_item_attach *next; } pst_item_attach; typedef struct _pst_item_extra_field { char *field_name; char *value; struct _pst_item_extra_field *next; } pst_item_extra_field; typedef struct _pst_item_journal { FILETIME *end; FILETIME *start; char *type; } pst_item_journal; typedef struct _pst_item_appointment { FILETIME *end; char *location; FILETIME *reminder; FILETIME *start; char *timezonestring; int32_t showas; int32_t label; } pst_item_appointment; typedef struct _pst_item { struct _pst_item_email *email; // data reffering to email struct _pst_item_folder *folder; // data reffering to folder struct _pst_item_contact *contact; // data reffering to contact struct _pst_item_attach *attach; // linked list of attachments struct _pst_item_attach *current_attach; // pointer to current attachment struct _pst_item_message_store * message_store; // data referring to the message store struct _pst_item_extra_field *extra_fields; // linked list of extra headers and such struct _pst_item_journal *journal; // data reffering to a journal entry struct _pst_item_appointment *appointment; // data reffering to a calendar entry int32_t type; char *ascii_type; char *file_as; char *comment; int32_t message_size; char *outlook_version; char *record_key; // probably 16 bytes long. size_t record_key_size; int32_t response_requested; FILETIME *create_date; FILETIME *modify_date; int32_t private_member; } pst_item; typedef struct _pst_x_attrib_ll { int32_t type; int32_t mytype; int32_t map; void *data; struct _pst_x_attrib_ll *next; } pst_x_attrib_ll; typedef struct _pst_file { pst_index_ll *i_head, *i_tail; pst_index2_ll *i2_head; pst_desc_ll *d_head, *d_tail; pst_x_attrib_ll *x_head; int32_t index1; int32_t index1_count; int32_t index2; int32_t index2_count; FILE * fp; size_t size; unsigned char encryption; unsigned char ind_type; } pst_file; typedef struct _pst_block_offset { int16_t from; int16_t to; } pst_block_offset; struct _pst_num_item { int32_t id; unsigned char *data; int32_t type; size_t size; char *extra; }; typedef struct _pst_num_array { int32_t count_item; int32_t count_array; struct _pst_num_item ** items; struct _pst_num_array *next; } pst_num_array; struct holder { unsigned char **buf; FILE * fp; int32_t base64; char base64_extra_chars[3]; int32_t base64_extra; }; // prototypes int32_t pst_open(pst_file *pf, char *name, char *mode); int32_t pst_close(pst_file *pf); pst_desc_ll * pst_getTopOfFolders(pst_file *pf, pst_item *root); int32_t pst_attach_to_mem(pst_file *pf, pst_item_attach *attach, unsigned char **b); int32_t pst_attach_to_file(pst_file *pf, pst_item_attach *attach, FILE* fp); int32_t pst_attach_to_file_base64(pst_file *pf, pst_item_attach *attach, FILE* fp); int32_t pst_load_index (pst_file *pf); pst_desc_ll* pst_getNextDptr(pst_desc_ll* d); int32_t pst_load_extended_attributes(pst_file *pf); int32_t _pst_build_id_ptr(pst_file *pf, int32_t offset, int32_t depth, int32_t linku1, int32_t start_val, int32_t end_val); int32_t _pst_build_desc_ptr (pst_file *pf, int32_t offset, int32_t depth, int32_t linku1, u_int32_t *high_id, int32_t start_id, int32_t end_val); pst_item* _pst_getItem(pst_file *pf, pst_desc_ll *d_ptr); void * _pst_parse_item (pst_file *pf, pst_desc_ll *d_ptr); pst_num_array * _pst_parse_block(pst_file *pf, u_int32_t block_id, pst_index2_ll *i2_head); int32_t _pst_process(pst_num_array *list, pst_item *item); int32_t _pst_free_list(pst_num_array *list); void _pst_freeItem(pst_item *item); int32_t _pst_free_id2(pst_index2_ll * head); int32_t _pst_free_id (pst_index_ll *head); int32_t _pst_free_desc (pst_desc_ll *head); int32_t _pst_free_xattrib(pst_x_attrib_ll *x); int32_t _pst_getBlockOffset(char *buf, int32_t read_size, int32_t i_offset, int32_t offset, pst_block_offset *p); pst_index2_ll * _pst_build_id2(pst_file *pf, pst_index_ll* list, pst_index2_ll* head_ptr); pst_index_ll * _pst_getID(pst_file* pf, u_int32_t id); pst_index_ll * _pst_getID2(pst_index2_ll * ptr, u_int32_t id); pst_desc_ll * _pst_getDptr(pst_file *pf, u_int32_t id); size_t _pst_read_block_size(pst_file *pf, int32_t offset, size_t size, char ** buf, int32_t do_enc, unsigned char is_index); int32_t _pst_decrypt(unsigned char *buf, size_t size, int32_t type); int32_t _pst_getAtPos(FILE *fp, int32_t pos, void* buf, u_int32_t size); int32_t _pst_get (FILE *fp, void *buf, u_int32_t size); size_t _pst_ff_getIDblock_dec(pst_file *pf, u_int32_t id, unsigned char **b); size_t _pst_ff_getIDblock(pst_file *pf, u_int32_t id, unsigned char** b); size_t _pst_ff_getID2block(pst_file *pf, u_int32_t id2, pst_index2_ll *id2_head, unsigned char** buf); size_t _pst_ff_getID2data(pst_file *pf, pst_index_ll *ptr, struct holder *h); size_t _pst_ff_compile_ID(pst_file *pf, u_int32_t id, struct holder *h, int32_t size); int32_t pst_strincmp(char *a, char *b, int32_t x); int32_t pst_stricmp(char *a, char *b); size_t pst_fwrite(const void*ptr, size_t size, size_t nmemb, FILE*stream); char * _pst_wide_to_single(char *wt, int32_t size); // DEBUG functions int32_t _pst_printDptr(pst_file *pf); int32_t _pst_printIDptr(pst_file* pf); int32_t _pst_printID2ptr(pst_index2_ll *ptr); void * xmalloc(size_t size); #endif // defined LIBPST_H diff --git a/pst2ldif.cpp b/pst2ldif.cpp index 1430a08..a07fad2 100644 --- a/pst2ldif.cpp +++ b/pst2ldif.cpp @@ -1,595 +1,593 @@ /* Copyright (c) 2004 Carl Byington - 510 Software Group, released under the GPL version 2 or any later version at your choice available at http://www.fsf.org/licenses/gpl.txt Based on readpst.c by David Smith */ using namespace std; #include #include #include #include #include #include #include #ifndef _WIN32 # include # include //mkdir // for reading of directory and clearing in function mk_separate_dir # include # include #else # include # define chdir _chdir # define int32_t __int32 #endif #ifndef __GNUC__ # include "XGetopt.h" #endif // needed for std c++ collections #include extern "C" { #include "libstrfunc.h" // for base64_encoding #include "define.h" #include "libpst.h" #include "common.h" #include "timeconv.h" #include "lzfu.h" } -#define VERSION "0.2" - int32_t usage(); int32_t version(); char *my_stristr(char *haystack, char *needle); char *check_filename(char *fname); char *single(char *str); char *folded(char *str); void multi(char *fmt, char *str); char *rfc2426_escape(char *str); int32_t chr_count(char *str, char x); char *prog_name; pst_file pstfile; char *ldap_base = NULL; // 'o=some.domain.tld, c=US' char *ldap_class = NULL; // 'newPerson' char *ldap_org = NULL; // 'o=some.domain.tld', computed from ldap_base //////////////////////////////////////////////// // define our ordering struct ltstr { bool operator()(char* s1, char* s2) const { return strcasecmp(s1, s2) < 0; } }; // define our set typedef set string_set; // make a static set to hold the cn values static string_set all_strings; //////////////////////////////////////////////// // helper to register a string in a string set // static char* register_string(string_set &s, char *name); static char* register_string(string_set &s, char *name) { string_set::iterator i = s.find(name); if (i != s.end()) return *i; char *x = strdup(name); s.insert(x); return x; } //////////////////////////////////////////////// // register a global string // static char* register_string(char *name); static char* register_string(char *name) { return register_string(all_strings, name); } //////////////////////////////////////////////// // make a unique string // static char* unique_string(char *name); static char* unique_string(char *name) { int unique = 2; string_set::iterator i = all_strings.find(name); if (i == all_strings.end()) return register_string(name); while (true) { char n[strlen(name)+10]; snprintf(n, sizeof(n), "%s %d", name, unique++); string_set::iterator i = all_strings.find(n); if (i == all_strings.end()) return register_string(n); } } //////////////////////////////////////////////// // remove leading and trailing blanks // static char *trim(char *name); static char *trim(char *name) { char *p; while (*name == ' ') name++; p = name + strlen(name) - 1; while ((p >= name) && (*p == ' ')) *p-- = '\0'; return name; } static void process(pst_desc_ll *d_ptr); static void process(pst_desc_ll *d_ptr) { pst_item *item = NULL; while (d_ptr) { if (d_ptr->desc) { item = (pst_item*)_pst_parse_item(&pstfile, d_ptr); DEBUG_INFO(("item pointer is %p\n", item)); if (item) { if (item->message_store) { // there should only be one message_store, and we have already done it DIE(("main: A second message_store has been found. Sorry, this must be an error.\n")); } if (item->folder && d_ptr->child && strcasecmp(item->file_as, "Deleted Items")) { //if this is a non-empty folder other than deleted items, we want to recurse into it fprintf(stderr, "entering folder %s\n", item->file_as); process(d_ptr->child); } else if (item->contact) { // deal with a contact if (item->type != PST_TYPE_CONTACT) { DIE(("type should be contact\n")); } else if (item->contact == NULL) { // this is an incorrect situation. Inform user DIE(("null item contact\n")); } else { char cn[1000]; snprintf(cn, sizeof(cn), "%s %s %s %s", single(item->contact->display_name_prefix), single(item->contact->first_name), single(item->contact->surname), single(item->contact->suffix)); if (strcmp(cn, " ")) { // fprintf(stderr, "\n\n\n"); // fprintf(stderr, "access_method %s\n", item->contact->access_method); // fprintf(stderr, "account_name %s\n", item->contact->account_name); // fprintf(stderr, "address1 %s\n", item->contact->address1); // fprintf(stderr, "address1_desc %s\n", item->contact->address1_desc); // fprintf(stderr, "address1_transport %s\n", item->contact->address1_transport); // fprintf(stderr, "address2 %s\n", item->contact->address2); // fprintf(stderr, "address2_desc %s\n", item->contact->address2_desc); // fprintf(stderr, "address2_transport %s\n", item->contact->address2_transport); // fprintf(stderr, "address3 %s\n", item->contact->address3); // fprintf(stderr, "address3_desc %s\n", item->contact->address3_desc); // fprintf(stderr, "address3_transport %s\n", item->contact->address3_transport); // fprintf(stderr, "assistant_name %s\n", item->contact->assistant_name); // fprintf(stderr, "assistant_phone %s\n", item->contact->assistant_phone); // fprintf(stderr, "billing_information %s\n", item->contact->billing_information); // fprintf(stderr, "business_address %s\n", item->contact->business_address); // fprintf(stderr, "business_city %s\n", item->contact->business_city); // fprintf(stderr, "business_country %s\n", item->contact->business_country); // fprintf(stderr, "business_fax %s\n", item->contact->business_fax); // fprintf(stderr, "business_homepage %s\n", item->contact->business_homepage); // fprintf(stderr, "business_phone %s\n", item->contact->business_phone); // fprintf(stderr, "business_phone2 %s\n", item->contact->business_phone2); // fprintf(stderr, "business_po_box %s\n", item->contact->business_po_box); // fprintf(stderr, "business_postal_code %s\n", item->contact->business_postal_code); // fprintf(stderr, "business_state %s\n", item->contact->business_state); // fprintf(stderr, "business_street %s\n", item->contact->business_street); // fprintf(stderr, "callback_phone %s\n", item->contact->callback_phone); // fprintf(stderr, "car_phone %s\n", item->contact->car_phone); // fprintf(stderr, "company_main_phone %s\n", item->contact->company_main_phone); // fprintf(stderr, "company_name %s\n", item->contact->company_name); // fprintf(stderr, "computer_name %s\n", item->contact->computer_name); // fprintf(stderr, "customer_id %s\n", item->contact->customer_id); // fprintf(stderr, "def_postal_address %s\n", item->contact->def_postal_address); // fprintf(stderr, "department %s\n", item->contact->department); // fprintf(stderr, "display_name_prefix %s\n", item->contact->display_name_prefix); // fprintf(stderr, "first_name %s\n", item->contact->first_name); // fprintf(stderr, "followup %s\n", item->contact->followup); // fprintf(stderr, "free_busy_address %s\n", item->contact->free_busy_address); // fprintf(stderr, "ftp_site %s\n", item->contact->ftp_site); // fprintf(stderr, "fullname %s\n", item->contact->fullname); // fprintf(stderr, "gov_id %s\n", item->contact->gov_id); // fprintf(stderr, "hobbies %s\n", item->contact->hobbies); // fprintf(stderr, "home_address %s\n", item->contact->home_address); // fprintf(stderr, "home_city %s\n", item->contact->home_city); // fprintf(stderr, "home_country %s\n", item->contact->home_country); // fprintf(stderr, "home_fax %s\n", item->contact->home_fax); // fprintf(stderr, "home_phone %s\n", item->contact->home_phone); // fprintf(stderr, "home_phone2 %s\n", item->contact->home_phone2); // fprintf(stderr, "home_po_box %s\n", item->contact->home_po_box); // fprintf(stderr, "home_postal_code %s\n", item->contact->home_postal_code); // fprintf(stderr, "home_state %s\n", item->contact->home_state); // fprintf(stderr, "home_street %s\n", item->contact->home_street); // fprintf(stderr, "initials %s\n", item->contact->initials); // fprintf(stderr, "isdn_phone %s\n", item->contact->isdn_phone); // fprintf(stderr, "job_title %s\n", item->contact->job_title); // fprintf(stderr, "keyword %s\n", item->contact->keyword); // fprintf(stderr, "language %s\n", item->contact->language); // fprintf(stderr, "location %s\n", item->contact->location); // fprintf(stderr, "manager_name %s\n", item->contact->manager_name); // fprintf(stderr, "middle_name %s\n", item->contact->middle_name); // fprintf(stderr, "mileage %s\n", item->contact->mileage); // fprintf(stderr, "mobile_phone %s\n", item->contact->mobile_phone); // fprintf(stderr, "nickname %s\n", item->contact->nickname); // fprintf(stderr, "office_loc %s\n", item->contact->office_loc); // fprintf(stderr, "org_id %s\n", item->contact->org_id); // fprintf(stderr, "other_address %s\n", item->contact->other_address); // fprintf(stderr, "other_city %s\n", item->contact->other_city); // fprintf(stderr, "other_country %s\n", item->contact->other_country); // fprintf(stderr, "other_phone %s\n", item->contact->other_phone); // fprintf(stderr, "other_po_box %s\n", item->contact->other_po_box); // fprintf(stderr, "other_postal_code %s\n", item->contact->other_postal_code); // fprintf(stderr, "other_state %s\n", item->contact->other_state); // fprintf(stderr, "other_street %s\n", item->contact->other_street); // fprintf(stderr, "pager_phone %s\n", item->contact->pager_phone); // fprintf(stderr, "personal_homepage %s\n", item->contact->personal_homepage); // fprintf(stderr, "pref_name %s\n", item->contact->pref_name); // fprintf(stderr, "primary_fax %s\n", item->contact->primary_fax); // fprintf(stderr, "primary_phone %s\n", item->contact->primary_phone); // fprintf(stderr, "profession %s\n", item->contact->profession); // fprintf(stderr, "radio_phone %s\n", item->contact->radio_phone); // fprintf(stderr, "spouse_name %s\n", item->contact->spouse_name); // fprintf(stderr, "suffix %s\n", item->contact->suffix); // fprintf(stderr, "surname %s\n", item->contact->surname); // fprintf(stderr, "telex %s\n", item->contact->telex); // fprintf(stderr, "transmittable_display_name %s\n", item->contact->transmittable_display_name); // fprintf(stderr, "ttytdd_phone %s\n", item->contact->ttytdd_phone); // have a valid cn char *ucn = unique_string(folded(trim(cn))); printf("dn: cn=%s, %s\n", ucn, ldap_base); printf("cn: %s\n", ucn); if (item->contact->first_name) { snprintf(cn, sizeof(cn), "%s %s", single(item->contact->display_name_prefix), single(item->contact->first_name)); printf("givenName: %s\n", trim(cn)); } if (item->contact->surname) { snprintf(cn, sizeof(cn), "%s %s", single(item->contact->surname), single(item->contact->suffix)); printf("sn: %s\n", trim(cn)); } else if (item->contact->company_name) { printf("sn: %s\n", single(item->contact->company_name)); } else printf("sn: %s\n", ucn); // use cn as sn if we cannot find something better if (item->contact->job_title) printf("personalTitle: %s\n", single(item->contact->job_title)); if (item->contact->company_name) printf("company: %s\n", single(item->contact->company_name)); if (item->contact->address1 && *item->contact->address1) printf("mail: %s\n", single(item->contact->address1)); if (item->contact->address2 && *item->contact->address2) printf("mail: %s\n", single(item->contact->address2)); if (item->contact->address3 && *item->contact->address3) printf("mail: %s\n", single(item->contact->address3)); if (item->contact->address1a && *item->contact->address1a) printf("mail: %s\n", single(item->contact->address1a)); if (item->contact->address2a && *item->contact->address2a) printf("mail: %s\n", single(item->contact->address2a)); if (item->contact->address3a && *item->contact->address3a) printf("mail: %s\n", single(item->contact->address3a)); if (item->contact->business_address) { if (item->contact->business_po_box) printf("postalAddress: %s\n", single(item->contact->business_po_box)); if (item->contact->business_street) multi("postalAddress: %s\n", item->contact->business_street); if (item->contact->business_city) printf("l: %s\n", single(item->contact->business_city)); if (item->contact->business_state) printf("st: %s\n", single(item->contact->business_state)); if (item->contact->business_postal_code) printf("postalCode: %s\n", single(item->contact->business_postal_code)); } else if (item->contact->home_address) { if (item->contact->home_po_box) printf("postalAddress: %s\n", single(item->contact->home_po_box)); if (item->contact->home_street) multi("postalAddress: %s\n", item->contact->home_street); if (item->contact->home_city) printf("l: %s\n", single(item->contact->home_city)); if (item->contact->home_state) printf("st: %s\n", single(item->contact->home_state)); if (item->contact->home_postal_code) printf("postalCode: %s\n", single(item->contact->home_postal_code)); } else if (item->contact->other_address) { if (item->contact->other_po_box) printf("postalAddress: %s\n", single(item->contact->other_po_box)); if (item->contact->other_street) multi("postalAddress: %s\n", item->contact->other_street); if (item->contact->other_city) printf("l: %s\n", single(item->contact->other_city)); if (item->contact->other_state) printf("st: %s\n", single(item->contact->other_state)); if (item->contact->other_postal_code) printf("postalCode: %s\n", single(item->contact->other_postal_code)); } if (item->contact->business_fax) printf("facsimileTelephoneNumber: %s\n", single(item->contact->business_fax)); else if (item->contact->home_fax) printf("facsimileTelephoneNumber: %s\n", single(item->contact->home_fax)); if (item->contact->business_phone) printf("telephoneNumber: %s\n", single(item->contact->business_phone)); if (item->contact->home_phone) printf("homePhone: %s\n", single(item->contact->home_phone)); if (item->contact->car_phone) printf("mobile: %s\n", single(item->contact->car_phone)); else if (item->contact->mobile_phone) printf("mobile: %s\n", single(item->contact->mobile_phone)); else if (item->contact->other_phone) printf("mobile: %s\n", single(item->contact->other_phone)); if (item->comment) printf("description: %s\n", single(item->comment)); printf("objectClass: %s\n\n", ldap_class); } } } else { DEBUG_INFO(("item is not a contact\n")); } } _pst_freeItem(item); } d_ptr = d_ptr->next; } } int main(int argc, char** argv) { pst_desc_ll *d_ptr; char *fname = NULL; char *temp = NULL; //temporary char pointer char c; prog_name = argv[0]; pst_item *item = NULL; while ((c = getopt(argc, argv, "b:c:Vh"))!= -1) { switch (c) { case 'b': ldap_base = optarg; temp = strchr(ldap_base, ','); if (temp) { *temp = '\0'; ldap_org = strdup(ldap_base+2); // assume first 2 chars are o= *temp = ','; } break; case 'c': ldap_class = optarg; break; case 'h': usage(); exit(0); break; case 'V': version(); exit(0); break; default: usage(); exit(1); break; } } if ((argc > optind) && (ldap_base) && (ldap_class) && (ldap_org)) { fname = argv[optind]; } else { usage(); exit(2); } DEBUG_INIT("pst2ldif.log"); DEBUG_REGISTER_CLOSE(); DEBUG_ENT("main"); RET_DERROR(pst_open(&pstfile, fname, "r"), 1, ("Error opening File\n")); RET_DERROR(pst_load_index(&pstfile), 2, ("Index Error\n")); pst_load_extended_attributes(&pstfile); d_ptr = pstfile.d_head; // first record is main record item = (pst_item*)_pst_parse_item(&pstfile, d_ptr); if (!item || !item->message_store) { DEBUG_RET(); DIE(("main: Could not get root record\n")); } d_ptr = pst_getTopOfFolders(&pstfile, item); if (!d_ptr) { DEBUG_RET(); DIE(("Top of folders record not found. Cannot continue\n")); } _pst_freeItem(item); // write the ldap header printf("dn: %s\n", ldap_base); printf("o: %s\n", ldap_org); printf("objectClass: organization\n\n"); printf("dn: cn=root, %s\n", ldap_base); printf("cn: root\n"); printf("objectClass: %s\n\n", ldap_class); process(d_ptr->child); // do the children of TOPF pst_close(&pstfile); DEBUG_RET(); return 0; } int usage() { version(); printf("Usage: %s [OPTIONS] {PST FILENAME}\n", prog_name); printf("OPTIONS:\n"); printf("\t-h\t- Help. This screen\n"); printf("\t-V\t- Version. Display program version\n"); printf("\t-b ldapbase\t- set the ldap base value\n"); printf("\t-c class \t- set the class of the ldap objects\n"); return 0; } int version() { printf("pst2ldif v%s\n", VERSION); #if BYTE_ORDER == BIG_ENDIAN printf("Big Endian implementation being used.\n"); #elif BYTE_ORDER == LITTLE_ENDIAN printf("Little Endian implementation being used.\n"); #else # error "Byte order not supported by this library" #endif #ifdef __GNUC__ printf("GCC %d.%d : %s %s\n", __GNUC__, __GNUC_MINOR__, __DATE__, __TIME__); #endif return 0; } // my_stristr varies from strstr in that its searches are case-insensitive char * my_stristr(char *haystack, char *needle) { char *x=haystack, *y=needle, *z = NULL; if (haystack == NULL || needle == NULL) return NULL; while (*y != '\0' && *x != '\0') { if (tolower(*y) == tolower(*x)) { // move y on one y++; if (z == NULL) { z = x; // store first position in haystack where a match is made } } else { y = needle; // reset y to the beginning of the needle z = NULL; // reset the haystack storage point } x++; // advance the search in the haystack } return z; } char *check_filename(char *fname) { char *t = fname; if (t == NULL) { return fname; } while ((t = strpbrk(t, "/\\:"))) { // while there are characters in the second string that we don't want *t = '_'; //replace them with an underscore } return fname; } char *single(char *str) { if (!str) return ""; char *ret = rfc2426_escape(str); char *n = strchr(ret, '\n'); if (n) *n = '\0'; return ret; } char *folded(char *str) { if (!str) return ""; char *ret = rfc2426_escape(str); char *n = ret; while (n = strchr(n, '\n')) { *n = ' '; } n = ret; while (n = strchr(n, ',')) { *n = ' '; } return ret; } void multi(char *fmt, char *str) { if (!str) return; char *ret = rfc2426_escape(str); char *n = ret; while (n = strchr(ret, '\n')) { *n = '\0'; printf(fmt, ret); ret = n+1; } if (*ret) printf(fmt, ret); } char *rfc2426_escape(char *str) { static char* buf = NULL; char *ret, *a, *b; int x = 0, y, z; if (str == NULL) ret = str; else { // calculate space required to escape all the following characters x = strlen(str) +(y=(chr_count(str, ',')*2) + (chr_count(str, '\\')*2) + (chr_count(str, ';')*2) + (chr_count(str, '\n')*2)); z = chr_count(str, '\r'); if (y == 0 && z == 0) // there isn't any extra space required ret = str; else { buf = (char*) realloc(buf, x+1); a = str; b = buf; while (*a != '\0') { switch(*a) { // case ',' : case '\\': case ';' : // case '\n': *(b++)='\\'; *b=*a; break; case '\r': break; default: *b=*a; } b++; a++; } *b = '\0'; ret = buf; } } return ret; } int chr_count(char *str, char x) { int r = 0; while (*str != '\0') { if (*str == x) r++; str++; } return r; } diff --git a/readpst.1 b/readpst.1 index d6d3922..2286c34 100644 --- a/readpst.1 +++ b/readpst.1 @@ -1,82 +1,87 @@ .\" Hey, EMACS: -*- nroff -*- .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) -.TH READPST 1 "February 24, 2004" +.TH READPST 1 "15 January 2005" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: .\" .nh disable hyphenation .\" .hy enable hyphenation .\" .ad l left justify .\" .ad b justify to both left and right margins .\" .nf disable filling .\" .fi enable filling .\" .br insert line break .\" .sp insert n+1 empty lines .\" for manpage-specific macros, see man(7) .SH NAME readpst \- convert PST (MS Outlook Personal Folders) files to mbox format .SH SYNOPSIS .B readpst .RI [ options ] " files" ... .SH DESCRIPTION This manual page documents briefly the .B readpst command. .PP .\" TeX users may be more comfortable with the \fB\fP and .\" \fI\fP escape sequences to invode bold face and italics, .\" respectively. \fBreadpst\fP is a program that can read an Outlook PST (Personal Folders) file and convert it into an mbox file, a format suitable for KMail, a recursive mbox structure, or seperate emails. .SH OPTIONS A summary of options is included below. .TP +.B \-c +Set the Contact output mode. Use -cv for vcard format or -cl for +an email list +.TP .B \-d Specify name of debug log file. Defaults to "readpst.log". The log file isn\'t an ascii file, it is a binary file readable by \fBreadpstlog\fP. .TP .B \-h -Show summary of options. +Show summary of options. Subsequent options are then ignored. .TP .B \-k Changes the output format to KMail. .TP .B \-o Specifies the output directory. The directory must already exist, and is entered after the PST file is opened, but before any processing of files commences. .TP .B \-q Changes to silent mode. No feedback is printed to the screen, except for error messages. .TP .B \-r Changes the output format to Recursive. This will create folders as named in the PST file, and will put all emails in a file called "mbox" inside each folder. These files are then compatible with all mbox\-compatible email clients. .TP .B \-S Output messages into seperate files. This will create folders as named in the PST file, and will put each email in its own file. These files will be numbered from 000000000 increasing in intervals of 1 (ie 000000000, 000000001, 0000000002). Any attachments are saved alongside each email as 000000000\-attach0, or with the name of the attachment if one is present. .TP .B \-V -Show version of program. +Show version of program. Subsequent options are then ignored. .TP .B \-w Overwrite any previous output files. \fBBeware\fP: When used with the \-S switch, this will remove all files from the target folder before writing. This is to keep the count of emails and attachments correct. .SH SEE ALSO .BR readpstlog (1) -.SH AUTHOR -This manual page was written by Dave Smith , and updated -by Joe Nahmias for the Debian GNU/Linux system (but may be -used by others). +.SH AUTHORS +This manual page was originally written by Dave Smith +, and updated by Joe Nahmias +for the Debian GNU/Linux system (but may be used by others). It was +subsequently updated by Brad Hards . diff --git a/readpst.c b/readpst.c index 946a135..1591717 100644 --- a/readpst.c +++ b/readpst.c @@ -1,1505 +1,1442 @@ /*** * readpst.c * Part of the LibPST project * Written by David Smith - * dave.s@earthcorp.com + * dave.s@earthcorp.com */ -// Includes {{{1 #include #include #include #include #include #include #include #ifndef _WIN32 # include # include //mkdir // for reading of directory and clearing in function mk_seperate_dir # include # include #else # include # define chdir _chdir # define int32_t __int32 #endif #ifndef __GNUC__ # include "XGetopt.h" #endif #include "libstrfunc.h" // for base64_encoding #include "define.h" #include "libpst.h" #include "common.h" #include "timeconv.h" #include "lzfu.h" -// }}}1 -// Defines {{{1 #define OUTPUT_TEMPLATE "%s" #define OUTPUT_KMAIL_DIR_TEMPLATE ".%s.directory" #define KMAIL_INDEX ".%s.index" -#define VERSION "0.5.1" // max size of the c_time char*. It will store the date of the email #define C_TIME_SIZE 500 #define PERM_DIRS 0777 // macro used for creating directories #ifndef WIN32 #define D_MKDIR(x) mkdir(x, PERM_DIRS) #else #define D_MKDIR(x) mkdir(x) #endif -// }}}1 -// struct file_ll {{{1 struct file_ll { char *name; char *dname; FILE * output; int32_t stored_count; int32_t email_count; int32_t skip_count; int32_t type; struct file_ll *next; }; -// }}}1 -// Function Declarations {{{1 void write_email_body(FILE *f, char *body); char *removeCR (char *c); int32_t usage(); int32_t version(); char *mk_kmail_dir(char*); int32_t close_kmail_dir(); char *mk_recurse_dir(char*); int32_t close_recurse_dir(); char *mk_seperate_dir(char *dir, int overwrite); int32_t close_seperate_dir(); int32_t mk_seperate_file(struct file_ll *f); char *my_stristr(char *haystack, char *needle); char *check_filename(char *fname); char *rfc2426_escape(char *str); int32_t chr_count(char *str, char x); char *rfc2425_datetime_format(FILETIME *ft); char *rfc2445_datetime_format(FILETIME *ft); char *skip_header_prologue(char *headers); -// }}}1 -// Global Variables {{{1 char *prog_name; char *output_dir = "."; char *kmail_chdir = NULL; -// }}}1 -// More Defines {{{1 // Normal mode just creates mbox format files in the current directory. Each file is named // the same as the folder's name that it represents #define MODE_NORMAL 0 // KMail mode creates a directory structure suitable for being used directly // by the KMail application #define MODE_KMAIL 1 // recurse mode creates a directory structure like the PST file. Each directory // contains only one file which stores the emails in mbox format. #define MODE_RECURSE 2 // seperate mode is similar directory structure to RECURSE. The emails are stored in // seperate files, numbering from 1 upward. Attachments belonging to the emails are // saved as email_no-filename (e.g. 1-samplefile.doc or 000001-Attachment2.zip) #define MODE_SEPERATE 3 // Output Normal just prints the standard information about what is going on #define OUTPUT_NORMAL 0 // Output Quiet is provided so that only errors are printed #define OUTPUT_QUIET 1 // default mime-type for attachments that have a null mime-type #define MIME_TYPE_DEFAULT "application/octet-stream" // output mode for contacts #define CMODE_VCARD 0 -#define CMODE_LIST 1 +#define CMODE_LIST 1 // output settings for RTF bodies // filename for the attachment #define RTF_ATTACH_NAME "rtf-body.rtf" // mime type for the attachment #define RTF_ATTACH_TYPE "application/rtf" -// }}}1 -// int main(int argc, char** argv) {{{1 int main(int argc, char** argv) { - // declarations {{{2 pst_item *item = NULL; pst_file pstfile; pst_desc_ll *d_ptr; char * fname = NULL; time_t em_time; char * c_time, *d_log=NULL; int c,x; int mode = MODE_NORMAL; int output_mode = OUTPUT_NORMAL; int contact_mode = CMODE_VCARD; int overwrite = 0; int base64_body = 0; // int encrypt = 0; FILE *fp; char *enc; // base64 encoded attachment char *boundary = NULL, *b1, *b2; // the boundary marker between multipart sections char *temp = NULL; //temporary char pointer int attach_num = 0; int skip_child = 0; struct file_ll *f, *head; prog_name = argv[0]; - // }}}2 while ((c = getopt(argc, argv, "d:hko:qrSVwc:"))!= -1) { - switch (c) { - case 'c': - if (optarg!=NULL && optarg[0]=='v') - contact_mode=CMODE_VCARD; - else if (optarg!=NULL && optarg[0]=='l') - contact_mode=CMODE_LIST; - else { - usage(); - exit(0); - } - break; - case 'd': - d_log = optarg; - break; - case 'h': - usage(); - exit(0); - break; - case 'V': - version(); - exit(0); - break; - case 'k': - mode = MODE_KMAIL; - break; - case 'o': - output_dir = optarg; - break; - case 'q': - output_mode = OUTPUT_QUIET; - break; - case 'r': - mode = MODE_RECURSE; - break; - case 'S': - mode = MODE_SEPERATE; - break; - case 'w': - overwrite = 1; - break; - default: - usage(); - exit(1); - break; - } + switch (c) { + case 'c': + if (optarg!=NULL && optarg[0]=='v') + contact_mode=CMODE_VCARD; + else if (optarg!=NULL && optarg[0]=='l') + contact_mode=CMODE_LIST; + else { + usage(); + exit(0); + } + break; + case 'd': + d_log = optarg; + break; + case 'h': + usage(); + exit(0); + break; + case 'V': + version(); + exit(0); + break; + case 'k': + mode = MODE_KMAIL; + break; + case 'o': + output_dir = optarg; + break; + case 'q': + output_mode = OUTPUT_QUIET; + break; + case 'r': + mode = MODE_RECURSE; + break; + case 'S': + mode = MODE_SEPERATE; + break; + case 'w': + overwrite = 1; + break; + default: + usage(); + exit(1); + break; + } } #ifdef DEBUG_ALL // initialize log file if (d_log == NULL) - d_log = "readpst.log"; + d_log = "readpst.log"; DEBUG_INIT(d_log); DEBUG_REGISTER_CLOSE(); #endif // defined DEBUG_ALL DEBUG_ENT("main"); if (argc > optind) { - fname = argv[optind]; + fname = argv[optind]; } else { - usage(); - exit(2); + usage(); + exit(2); } if (output_mode != OUTPUT_QUIET) printf("Opening PST file and indexes...\n"); DEBUG_MAIN(("main: Opening PST file '%s'\n", fname)); RET_DERROR(pst_open(&pstfile, fname, "r"), 1, ("Error opening File\n")); DEBUG_MAIN(("main: Loading Indexes\n")); RET_DERROR(pst_load_index(&pstfile), 2, ("Index Error\n")); DEBUG_MAIN(("processing file items\n")); pst_load_extended_attributes(&pstfile); if (chdir(output_dir)) { - x = errno; - pst_close(&pstfile); - DIE(("main: Cannot change to output dir %s: %s\n", output_dir, strerror(x))); + x = errno; + pst_close(&pstfile); + DIE(("main: Cannot change to output dir %s: %s\n", output_dir, strerror(x))); } if (output_mode != OUTPUT_QUIET) printf("About to start processing first record...\n"); d_ptr = pstfile.d_head; // first record is main record if ((item = _pst_parse_item(&pstfile, d_ptr)) == NULL || item->message_store == NULL) { - DIE(("main: Could not get root record\n")); + DIE(("main: Could not get root record\n")); } // default the file_as to the same as the main filename if it doesn't exist if (item->file_as == NULL) { - if ((temp = strrchr(fname, '/')) == NULL) - if ((temp = strrchr(fname, '\\')) == NULL) - temp = fname; - else - temp++; // get past the "\\" - else - temp++; // get past the "/" - item->file_as = (char*)xmalloc(strlen(temp)+1); - strcpy(item->file_as, temp); - DEBUG_MAIN(("file_as was blank, so am using %s\n", item->file_as)); + if ((temp = strrchr(fname, '/')) == NULL) + if ((temp = strrchr(fname, '\\')) == NULL) + temp = fname; + else + temp++; // get past the "\\" + else + temp++; // get past the "/" + item->file_as = (char*)xmalloc(strlen(temp)+1); + strcpy(item->file_as, temp); + DEBUG_MAIN(("file_as was blank, so am using %s\n", item->file_as)); } DEBUG_MAIN(("main: Root Folder Name: %s\n", item->file_as)); f = (struct file_ll*) malloc(sizeof(struct file_ll)); memset(f, 0, sizeof(struct file_ll)); f->email_count = 0; f->skip_count = 0; f->next = NULL; head = f; if (mode == MODE_KMAIL) - f->name = mk_kmail_dir(item->file_as); + f->name = mk_kmail_dir(item->file_as); else if (mode == MODE_RECURSE) - f->name = mk_recurse_dir(item->file_as); + f->name = mk_recurse_dir(item->file_as); else if (mode == MODE_SEPERATE) { - // do similar stuff to recurse here. - mk_seperate_dir(item->file_as, overwrite); - f->name = (char*) xmalloc(10); - sprintf(f->name, "%09i", f->email_count); + // do similar stuff to recurse here. + mk_seperate_dir(item->file_as, overwrite); + f->name = (char*) xmalloc(10); + sprintf(f->name, "%09i", f->email_count); } else { - f->name = (char*) malloc(strlen(item->file_as)+strlen(OUTPUT_TEMPLATE)+1); - sprintf(f->name, OUTPUT_TEMPLATE, item->file_as); + f->name = (char*) malloc(strlen(item->file_as)+strlen(OUTPUT_TEMPLATE)+1); + sprintf(f->name, OUTPUT_TEMPLATE, item->file_as); } f->dname = (char*) malloc(strlen(item->file_as)+1); strcpy(f->dname, item->file_as); if (overwrite != 1 && mode != MODE_SEPERATE) { - // if overwrite is set to 1 we keep the existing name and don't modify anything - // we don't want to go changing the file name of the SEPERATE items - temp = (char*) malloc (strlen(f->name)+10); //enough room for 10 digits - sprintf(temp, "%s", f->name); - temp = check_filename(temp); - x = 0; - while ((f->output = fopen(temp, "r")) != NULL) { - DEBUG_MAIN(("main: need to increase filename cause one already exists with that name\n")); - DEBUG_MAIN(("main: - increasing it to %s%d\n", f->name, x)); - x++; - sprintf(temp, "%s%08d", f->name, x); - DEBUG_MAIN(("main: - trying \"%s\"\n", temp)); - if (x == 99999999) { - DIE(("main: Why can I not create a folder %s? I have tried %i extensions...\n", f->name, x)); - } - fclose(f->output); - } - if (x > 0) { //then the f->name should change - free (f->name); - f->name = temp; - } else { - free (temp); - } + // if overwrite is set to 1 we keep the existing name and don't modify anything + // we don't want to go changing the file name of the SEPERATE items + temp = (char*) malloc (strlen(f->name)+10); //enough room for 10 digits + sprintf(temp, "%s", f->name); + temp = check_filename(temp); + x = 0; + while ((f->output = fopen(temp, "r")) != NULL) { + DEBUG_MAIN(("main: need to increase filename cause one already exists with that name\n")); + DEBUG_MAIN(("main: - increasing it to %s%d\n", f->name, x)); + x++; + sprintf(temp, "%s%08d", f->name, x); + DEBUG_MAIN(("main: - trying \"%s\"\n", temp)); + if (x == 99999999) { + DIE(("main: Why can I not create a folder %s? I have tried %i extensions...\n", f->name, x)); + } + fclose(f->output); + } + if (x > 0) { //then the f->name should change + free (f->name); + f->name = temp; + } else { + free (temp); + } } if (mode != MODE_SEPERATE) { - f->name = check_filename(f->name); - if ((f->output = fopen(f->name, "w")) == NULL) { - DIE(("main: Could not open file \"%s\" for write\n", f->name)); - } + f->name = check_filename(f->name); + if ((f->output = fopen(f->name, "w")) == NULL) { + DIE(("main: Could not open file \"%s\" for write\n", f->name)); + } } f->type = item->type; if ((d_ptr = pst_getTopOfFolders(&pstfile, item)) == NULL) { - DIE(("Top of folders record not found. Cannot continue\n")); + DIE(("Top of folders record not found. Cannot continue\n")); } if (item){ - _pst_freeItem(item); - item = NULL; + _pst_freeItem(item); + item = NULL; } /* if ((item = _pst_parse_item(&pstfile, d_ptr)) == NULL || item->folder == NULL) { - DEBUG_MAIN(("main: Could not get \"Top Of Personal Folder\" record\n")); - return -2; - }*/ + DEBUG_MAIN(("main: Could not get \"Top Of Personal Folder\" record\n")); + return -2; + }*/ d_ptr = d_ptr->child; // do the children of TOPF if (output_mode != OUTPUT_QUIET) printf("Processing items...\n"); DEBUG_MAIN(("main: About to do email stuff\n")); while (d_ptr != NULL) { - DEBUG_MAIN(("main: New item record\n")); - if (d_ptr->desc == NULL) { - DEBUG_WARN(("main: ERROR ?? item's desc record is NULL\n")); - f->skip_count++; - goto check_parent; - } - DEBUG_MAIN(("main: Desc Email ID %#x [d_ptr->id = %#x]\n", d_ptr->desc->id, d_ptr->id)); - - item = _pst_parse_item(&pstfile, d_ptr); - DEBUG_MAIN(("main: About to process item\n")); - if (item != NULL && item->email != NULL && item->email->subject != NULL && - item->email->subject->subj != NULL) { - // DEBUG_EMAIL(("item->email->subject = %p\n", item->email->subject)); - // DEBUG_EMAIL(("item->email->subject->subj = %p\n", item->email->subject->subj)); - } - if (item != NULL) { - if (item->message_store != NULL) { - // there should only be one message_store, and we have already done it - DIE(("main: A second message_store has been found. Sorry, this must be an error.\n")); - } - - - if (item->folder != NULL) { - // Process Folder item {{{2 - // if this is a folder, we want to recurse into it - if (output_mode != OUTPUT_QUIET) printf("Processing Folder \"%s\"\n", item->file_as); - // f->email_count++; - DEBUG_MAIN(("main: I think I may try to go into folder \"%s\"\n", item->file_as)); - f = (struct file_ll*) malloc(sizeof(struct file_ll)); - memset(f, 0, sizeof(struct file_ll)); - - f->next = head; - f->email_count = 0; - f->type = item->type; - f->stored_count = item->folder->email_count; - head = f; - - temp = item->file_as; - temp = check_filename(temp); - - if (mode == MODE_KMAIL) - f->name = mk_kmail_dir(item->file_as); //create directory and form filename - else if (mode == MODE_RECURSE) - f->name = mk_recurse_dir(item->file_as); - else if (mode == MODE_SEPERATE) { - // do similar stuff to recurse here. - mk_seperate_dir(item->file_as, overwrite); - f->name = (char*) xmalloc(10); - memset(f->name, 0, 10); - // sprintf(f->name, "%09i", f->email_count); - } else { - f->name = (char*) xmalloc(strlen(item->file_as)+strlen(OUTPUT_TEMPLATE+1)); - sprintf(f->name, OUTPUT_TEMPLATE, item->file_as); - } - - f->dname = (char*) xmalloc(strlen(item->file_as)+1); - strcpy(f->dname, item->file_as); - - if (overwrite != 1) { - temp = (char*) xmalloc (strlen(f->name)+10); //enough room for 10 digits - sprintf(temp, "%s", f->name); - x = 0; - temp = check_filename(temp); - while ((f->output = fopen(temp, "r")) != NULL) { - DEBUG_MAIN(("main: need to increase filename cause one already exists with that name\n")); - DEBUG_MAIN(("main: - increasing it to %s%d\n", f->name, x)); - x++; - sprintf(temp, "%s%08d", f->name, x); - DEBUG_MAIN(("main: - trying \"%s\"\n", f->name)); - if (x == 99999999) { - DIE(("main: Why can I not create a folder %s? I have tried %i extensions...\n", f->name, x)); - } - fclose(f->output); - } - if (x > 0) { //then the f->name should change - free (f->name); - f->name = temp; - } else { - free(temp); - } - } - - DEBUG_MAIN(("main: f->name = %s\nitem->folder_name = %s\n", f->name, item->file_as)); - if (mode != MODE_SEPERATE) { - f->name = check_filename(f->name); - if ((f->output = fopen(f->name, "w")) == NULL) { - DIE(("main: Could not open file \"%s\" for write\n", f->name)); - } - } - if (d_ptr->child != NULL) { - d_ptr = d_ptr->child; - skip_child = 1; - } else { - DEBUG_MAIN(("main: Folder has NO children. Creating directory, and closing again\n")); - if (output_mode != OUTPUT_QUIET) - printf("\tNo items to process in folder \"%s\", should have been %i\n", f->dname, f->stored_count); - head = f->next; - if (f->output != NULL) - fclose(f->output); - if (mode == MODE_KMAIL) - close_kmail_dir(); - else if (mode == MODE_RECURSE) - close_recurse_dir(); - else if (mode == MODE_SEPERATE) - close_seperate_dir(); - free(f->dname); - free(f->name); - free(f); - - f = head; - } - _pst_freeItem(item); - item = NULL; // just for the odd situations! - goto check_parent; - // }}}2 - } else if (item->contact != NULL) { - // Process Contact item {{{2 - // deal with a contact - // write them to the file, one per line in this format - // Desc Name \n - if (mode == MODE_SEPERATE) { - mk_seperate_file(f); - } - f->email_count++; - - DEBUG_MAIN(("main: Processing Contact\n")); - if (f->type != PST_TYPE_CONTACT) { - DEBUG_MAIN(("main: I have a contact, but the folder isn't a contacts folder. " - "Will process anyway\n")); - } - if (item->type != PST_TYPE_CONTACT) { - DEBUG_MAIN(("main: I have an item that has contact info, but doesn't say that" - " it is a contact. Type is \"%s\"\n", item->ascii_type)); - DEBUG_MAIN(("main: Processing anyway\n")); - } - if (item->contact == NULL) { // this is an incorrect situation. Inform user - DEBUG_MAIN(("main: ERROR. This contact has not been fully parsed. one of the pre-requisties is NULL\n")); - } else { - if (contact_mode == CMODE_VCARD) { - // the specification I am following is (hopefully) RFC2426 vCard Mime Directory Profile - fprintf(f->output, "BEGIN:VCARD\n"); - fprintf(f->output, "FN:%s\n", rfc2426_escape(item->contact->fullname)); - fprintf(f->output, "N:%s;%s;%s;%s;%s\n", - rfc2426_escape((item->contact->surname==NULL?"":item->contact->surname)), - rfc2426_escape((item->contact->first_name==NULL?"":item->contact->first_name)), - rfc2426_escape((item->contact->middle_name==NULL?"":item->contact->middle_name)), - rfc2426_escape((item->contact->display_name_prefix==NULL?"":item->contact->display_name_prefix)), - rfc2426_escape((item->contact->suffix==NULL?"":item->contact->suffix))); - if (item->contact->nickname != NULL) - fprintf(f->output, "NICKNAME:%s\n", rfc2426_escape(item->contact->nickname)); - if (item->contact->address1 != NULL) - fprintf(f->output, "EMAIL:%s\n", rfc2426_escape(item->contact->address1)); - if (item->contact->address2 != NULL) - fprintf(f->output, "EMAIL:%s\n", rfc2426_escape(item->contact->address2)); - if (item->contact->address3 != NULL) - fprintf(f->output, "EMAIL:%s\n", rfc2426_escape(item->contact->address3)); - if (item->contact->birthday != NULL) - fprintf(f->output, "BDAY:%s\n", rfc2425_datetime_format(item->contact->birthday)); - if (item->contact->home_address != NULL) { - fprintf(f->output, "ADR;TYPE=home:%s;%s;%s;%s;%s;%s;%s\n", - rfc2426_escape((item->contact->home_po_box!=NULL?item->contact->home_po_box:"")), - "", // extended Address - rfc2426_escape((item->contact->home_street!=NULL?item->contact->home_street:"")), - rfc2426_escape((item->contact->home_city!=NULL?item->contact->home_city:"")), - rfc2426_escape((item->contact->home_state!=NULL?item->contact->home_state:"")), - rfc2426_escape((item->contact->home_postal_code!=NULL?item->contact->home_postal_code:"")), - rfc2426_escape((item->contact->home_country!=NULL?item->contact->home_country:""))); - fprintf(f->output, "LABEL;TYPE=home:%s\n", rfc2426_escape(item->contact->home_address)); - } - if (item->contact->business_address != NULL) { - fprintf(f->output, "ADR;TYPE=work:%s;%s;%s;%s;%s;%s;%s\n", - rfc2426_escape((item->contact->business_po_box!=NULL?item->contact->business_po_box:"")), - "", // extended Address - rfc2426_escape((item->contact->business_street!=NULL?item->contact->business_street:"")), - rfc2426_escape((item->contact->business_city!=NULL?item->contact->business_city:"")), - rfc2426_escape((item->contact->business_state!=NULL?item->contact->business_state:"")), - rfc2426_escape((item->contact->business_postal_code!=NULL?item->contact->business_postal_code:"")), - rfc2426_escape((item->contact->business_country!=NULL?item->contact->business_country:""))); - fprintf(f->output, "LABEL;TYPE=work:%s\n", rfc2426_escape(item->contact->business_address)); - } - if (item->contact->other_address != NULL) { - fprintf(f->output, "ADR;TYPE=postal:%s;%s;%s;%s;%s;%s;%s\n", - rfc2426_escape((item->contact->other_po_box!=NULL?item->contact->business_po_box:"")), - "", // extended Address - rfc2426_escape((item->contact->other_street!=NULL?item->contact->other_street:"")), - rfc2426_escape((item->contact->other_city!=NULL?item->contact->other_city:"")), - rfc2426_escape((item->contact->other_state!=NULL?item->contact->other_state:"")), - rfc2426_escape((item->contact->other_postal_code!=NULL?item->contact->other_postal_code:"")), - rfc2426_escape((item->contact->other_country!=NULL?item->contact->other_country:""))); - fprintf(f->output, "ADR;TYPE=postal:%s\n", rfc2426_escape(item->contact->other_address)); - } - if (item->contact->business_fax != NULL) - fprintf(f->output, "TEL;TYPE=work,fax:%s\n", rfc2426_escape(item->contact->business_fax)); - if (item->contact->business_phone != NULL) - fprintf(f->output, "TEL;TYPE=work,voice:%s\n", rfc2426_escape(item->contact->business_phone)); - if (item->contact->business_phone2 != NULL) - fprintf(f->output, "TEL;TYPE=work,voice:%s\n", rfc2426_escape(item->contact->business_phone2)); - if (item->contact->car_phone != NULL) - fprintf(f->output, "TEL;TYPE=car,voice:%s\n", rfc2426_escape(item->contact->car_phone)); - if (item->contact->home_fax != NULL) - fprintf(f->output, "TEL;TYPE=home,fax:%s\n", rfc2426_escape(item->contact->home_fax)); - if (item->contact->home_phone != NULL) - fprintf(f->output, "TEL;TYPE=home,voice:%s\n", rfc2426_escape(item->contact->home_phone)); - if (item->contact->home_phone2 != NULL) - fprintf(f->output, "TEL;TYPE=home,voice:%s\n", rfc2426_escape(item->contact->home_phone2)); - if (item->contact->isdn_phone != NULL) - fprintf(f->output, "TEL;TYPE=isdn:%s\n", rfc2426_escape(item->contact->isdn_phone)); - if (item->contact->mobile_phone != NULL) - fprintf(f->output, "TEL;TYPE=cell,voice:%s\n", rfc2426_escape(item->contact->mobile_phone)); - if (item->contact->other_phone != NULL) - fprintf(f->output, "TEL;TYPE=msg:%s\n", rfc2426_escape(item->contact->other_phone)); - if (item->contact->pager_phone != NULL) - fprintf(f->output, "TEL;TYPE=pager:%s\n", rfc2426_escape(item->contact->pager_phone)); - if (item->contact->primary_fax != NULL) - fprintf(f->output, "TEL;TYPE=fax,pref:%s\n", rfc2426_escape(item->contact->primary_fax)); - if (item->contact->primary_phone != NULL) - fprintf(f->output, "TEL;TYPE=phone,pref:%s\n", rfc2426_escape(item->contact->primary_phone)); - if (item->contact->radio_phone != NULL) - fprintf(f->output, "TEL;TYPE=pcs:%s\n", rfc2426_escape(item->contact->radio_phone)); - if (item->contact->telex != NULL) - fprintf(f->output, "TEL;TYPE=bbs:%s\n", rfc2426_escape(item->contact->telex)); - if (item->contact->job_title != NULL) - fprintf(f->output, "TITLE:%s\n", rfc2426_escape(item->contact->job_title)); - if (item->contact->profession != NULL) - fprintf(f->output, "ROLE:%s\n", rfc2426_escape(item->contact->profession)); - if (item->contact->assistant_name != NULL || item->contact->assistant_phone != NULL) { - fprintf(f->output, "AGENT:BEGIN:VCARD\\n"); - if (item->contact->assistant_name != NULL) - fprintf(f->output, "FN:%s\\n", rfc2426_escape(item->contact->assistant_name)); - if (item->contact->assistant_phone != NULL) - fprintf(f->output, "TEL:%s\\n", rfc2426_escape(item->contact->assistant_phone)); - fprintf(f->output, "END:VCARD\\n\n"); - } - if (item->contact->company_name != NULL) - fprintf(f->output, "ORG:%s\n", rfc2426_escape(item->contact->company_name)); - if (item->comment != NULL) - fprintf(f->output, "NOTE:%s\n", rfc2426_escape(item->comment)); - - fprintf(f->output, "VERSION: 3.0\n"); - fprintf(f->output, "END:VCARD\n\n"); - } else { - fprintf(f->output, "%s <%s>\n", item->contact->fullname, item->contact->address1); - } - } - // }}}2 - } else if (item->email != NULL && - (item->type == PST_TYPE_NOTE || item->type == PST_TYPE_REPORT)) { - // Process Email item {{{2 - if (mode == MODE_SEPERATE) { - mk_seperate_file(f); - } - - f->email_count++; - - DEBUG_MAIN(("main: seen an email\n")); - - // convert the sent date if it exists, or set it to a fixed date - if (item->email->sent_date != NULL) { - em_time = fileTimeToUnixTime(item->email->sent_date, 0); - c_time = ctime(&em_time); - if (c_time != NULL) - c_time[strlen(c_time)-1] = '\0'; //remove end \n - else - c_time = "Fri Dec 28 12:06:21 2001"; - } else - c_time= "Fri Dec 28 12:06:21 2001"; - - // if the boundary is still set from the previous run, then free it - if (boundary != NULL) { - free (boundary); - boundary = NULL; - } - - // we will always look at the header to discover some stuff - if (item->email->header != NULL ) { - // see if there is a boundary variable there - // this search MUST be made case insensitive (DONE). - // Also, some check to find out if we - // are looking at the boundary associated with content-type, and that the content - // type really is "multipart" - if ((b2 = my_stristr(item->email->header, "boundary=")) != NULL) { - b2 += strlen("boundary="); // move boundary to first char of marker - - if (*b2 == '"') { - b2++; - b1 = strchr(b2, '"'); // find terminating quote - } else { - b1 = b2; - while (isgraph(*b1)) // find first char that isn't part of boundary - b1++; - } - - boundary = malloc ((b1-b2)+1); //malloc that length - memset (boundary, 0, (b1-b2)+1); // blank it - strncpy(boundary, b2, b1-b2); // copy boundary to another variable - b1 = b2 = boundary; - while (*b2 != '\0') { // remove any CRs and Tabs - if (*b2 != '\n' && *b2 != '\r' && *b2 != '\t') { - *b1 = *b2; - b1++; - } - b2++; - } - *b1 = '\0'; - - DEBUG_MAIN(("main: Found boundary of - %s\n", boundary)); - } else { - - DEBUG_MAIN(("main: boundary not found in header\n")); - } - - // also possible to set 7bit encoding detection here. - if ((b2 = my_stristr(item->email->header, "Content-Transfer-Encoding:")) != NULL) { - if ((b2 = strchr(b2, ':')) != NULL) { - b2++; // skip to the : at the end of the string - - while (*b2 == ' ' || *b2 == '\t') - b2++; - if (pst_strincmp(b2, "base64", 6)==0) { - DEBUG_MAIN(("body is base64 encoded\n")); - base64_body = 1; - } - } else { - DEBUG_WARN(("found a ':' during the my_stristr, but not after that..\n")); - } - } - - } - if (boundary == NULL && (item->attach ||(item->email->body && item->email->htmlbody) - || item->email->rtf_compressed || item->email->encrypted_body - || item->email->encrypted_htmlbody)) { - // we need to create a boundary here. - DEBUG_EMAIL(("main: must create own boundary. oh dear.\n")); - boundary = malloc(50 * sizeof(char)); // allow 50 chars for boundary - boundary[0] = '\0'; - sprintf(boundary, "--boundary-LibPST-iamunique-%i_-_-", rand()); - DEBUG_EMAIL(("main: created boundary is %s\n", boundary)); - } - - DEBUG_MAIN(("main: About to print Header\n")); - - if (item != NULL && item->email != NULL && item->email->subject != NULL && - item->email->subject->subj != NULL) { - DEBUG_EMAIL(("item->email->subject->subj = %p\n", item->email->subject->subj)); - } - if (item->email->header != NULL) { - // some of the headers we get from the file are not properly defined. - // they can contain some email stuff too. We will cut off the header - // when we see a \n\n or \r\n\r\n - - removeCR(item->email->header); - - temp = strstr(item->email->header, "\n\n"); - - if (temp != NULL) { - DEBUG_MAIN(("main: Found body text in header\n")); - temp += 2; // get past the \n\n - *temp = '\0'; - } - - if (mode != MODE_SEPERATE) { - char *soh = NULL; // real start of headers. - // don't put rubbish in if we are doing seperate - fprintf(f->output, "From \"%s\" %s\n", item->email->outlook_sender_name, c_time); - soh = skip_header_prologue(item->email->header); - fprintf(f->output, "%s\n\n", soh); - } else { - fprintf(f->output, "%s\n", item->email->header); - } - } else { - //make up our own header! - if (mode != MODE_SEPERATE) { - // don't want this first line for this mode - if (item->email->outlook_sender_name != NULL) { - temp = item->email->outlook_sender_name; - } else { - temp = "(readpst_null)"; - } - fprintf(f->output, "From \"%s\" %s\n", temp, c_time); - } - if ((temp = item->email->outlook_sender) == NULL) - temp = ""; - fprintf(f->output, "From: \"%s\" <%s>\n", item->email->outlook_sender_name, temp); - if (item->email->subject != NULL) { - fprintf(f->output, "Subject: %s\n", item->email->subject->subj); - } else { - fprintf(f->output, "Subject: \n"); - } - fprintf(f->output, "To: %s\n", item->email->sentto_address); - if (item->email->cc_address != NULL) { - fprintf(f->output, "CC: %s\n", item->email->cc_address); - } - if (item->email->sent_date != NULL) { - c_time = (char*) xmalloc(C_TIME_SIZE); - strftime(c_time, C_TIME_SIZE, "%a, %d %b %Y %H:%M:%S %z", gmtime(&em_time)); - fprintf(f->output, "Date: %s\n", c_time); - free(c_time); - } - - fprintf(f->output, "MIME-Version: 1.0\n"); - if (item->attach != NULL) { - // write the boundary stuff if we have attachments - fprintf(f->output, "Content-type: multipart/mixed;\n\tboundary=\"%s\"\n", - boundary); - } else if (item->email->htmlbody && item->email->body) { - // else if we have an html and text body then tell it so - fprintf(f->output, "Content-type: multipart/alternate;\n\tboundary=\"%s\"\n", - boundary); - } else if (item->email->htmlbody) { - fprintf(f->output, "Content-type: text/html\n"); - } - fprintf(f->output, "\n"); - } - - - DEBUG_MAIN(("main: About to print Body\n")); - - if (item->email->body != NULL) { - if (boundary) { - fprintf(f->output, "\n--%s\n", boundary); - fprintf(f->output, "Content-type: text/plain\n\n"); - if (base64_body) - fprintf(f->output, "Content-Transfer-Encoding: base64\n"); - } - removeCR(item->email->body); - if (base64_body) - write_email_body(f->output, base64_encode(item->email->body, - strlen(item->email->body))); - else - write_email_body(f->output, item->email->body); - } - - if (item->email->htmlbody != NULL) { - if (boundary) { - fprintf(f->output, "\n--%s\n", boundary); - fprintf(f->output, "Content-type: text/html\n\n"); - if (base64_body) - fprintf(f->output, "Content-Transfer-Encoding: base64\n"); - } - removeCR(item->email->htmlbody); - if (base64_body) - write_email_body(f->output, base64_encode(item->email->htmlbody, - strlen(item->email->htmlbody))); - else - write_email_body(f->output, item->email->htmlbody); - } - - attach_num = 0; - - if (item->email->rtf_compressed != NULL) { - DEBUG_MAIN(("Adding RTF body as attachment\n")); - item->current_attach = (pst_item_attach*)xmalloc(sizeof(pst_item_attach)); - memset(item->current_attach, 0, sizeof(pst_item_attach)); - item->current_attach->next = item->attach; - item->attach = item->current_attach; - item->current_attach->data = lzfu_decompress(item->email->rtf_compressed); - item->current_attach->filename2 = xmalloc(strlen(RTF_ATTACH_NAME)+2); - strcpy(item->current_attach->filename2, RTF_ATTACH_NAME); - item->current_attach->mimetype = xmalloc(strlen(RTF_ATTACH_TYPE)+2); - strcpy(item->current_attach->mimetype, RTF_ATTACH_TYPE); - memcpy(&(item->current_attach->size), item->email->rtf_compressed+sizeof(int32_t), sizeof(int32_t)); - LE32_CPU(item->current_attach->size); - // item->email->rtf_compressed = ; - // attach_num++; - } - if (item->email->encrypted_body || item->email->encrypted_htmlbody) { - // if either the body or htmlbody is encrypted, add them as attachments - if (item->email->encrypted_body) { - DEBUG_MAIN(("Adding Encrypted Body as attachment\n")); - item->current_attach = (pst_item_attach*) xmalloc(sizeof(pst_item_attach)); - memset(item->current_attach, 0, sizeof(pst_item_attach)); - item->current_attach->next = item->attach; - item->attach = item->current_attach; - - item->current_attach->data = item->email->encrypted_body; - item->current_attach->size = item->email->encrypted_body_size; - item->email->encrypted_body = NULL; - } - if (item->email->encrypted_htmlbody) { - DEBUG_MAIN(("Adding encrypted HTML body as attachment\n")); - item->current_attach = (pst_item_attach*) xmalloc(sizeof(pst_item_attach)); - memset(item->current_attach, 0, sizeof(pst_item_attach)); - item->current_attach->next = item->attach; - item->attach = item->current_attach; - - item->current_attach->data = item->email->encrypted_htmlbody; - item->current_attach->size = item->email->encrypted_htmlbody_size; - item->email->encrypted_htmlbody = NULL; - } - 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"); - } - base64_body = 0; - // attachments - item->current_attach = item->attach; - while (item->current_attach != NULL) { - DEBUG_MAIN(("main: Attempting Attachment encoding\n")); - if (item->current_attach->data == NULL) { - DEBUG_MAIN(("main: Data of attachment is NULL!. Size is supposed to be %i\n", item->current_attach->size)); - } - if (mode == MODE_SEPERATE) { - f->name = check_filename(f->name); - if (item->current_attach->filename2 == NULL) { - temp = xmalloc(strlen(f->name)+15); - sprintf(temp, "%s-attach%i", f->name, attach_num); - } else { - temp = xmalloc(strlen(f->name)+strlen(item->current_attach->filename2)+15); - fp = NULL; x=0; - do { - if (fp != NULL) fclose(fp); - if (x == 0) - sprintf(temp, "%s-%s", f->name, item->current_attach->filename2); - else - sprintf(temp, "%s-%s-%i", f->name, item->current_attach->filename2, x); - } while ((fp = fopen(temp, "r"))!=NULL && ++x < 99999999); - if (x > 99999999) { - DIE(("error finding attachment name. exhausted possibilities to %s\n", temp)); - } - } - DEBUG_MAIN(("main: Saving attachment to %s\n", temp)); - if ((fp = fopen(temp, "w")) == NULL) { - WARN(("main: Cannot open attachment save file \"%s\"\n", temp)); - } else { - if (item->current_attach->data != NULL) - fwrite(item->current_attach->data, 1, item->current_attach->size, fp); - else { - pst_attach_to_file(&pstfile, item->current_attach, fp); - } - fclose(fp); - } - } else { - DEBUG_MAIN(("main: Attachment Size is %i\n", item->current_attach->size)); - DEBUG_MAIN(("main: Attachment Pointer is %p\n", item->current_attach->data)); - if (item->current_attach->data != NULL) { - if ((enc = base64_encode (item->current_attach->data, item->current_attach->size)) == NULL) { - DEBUG_MAIN(("main: ERROR base64_encode returned NULL. Must have failed\n")); - item->current_attach = item->current_attach->next; - continue; - } - } - if (boundary) { - fprintf(f->output, "\n--%s\n", boundary); - if (item->current_attach->mimetype == NULL) { - fprintf(f->output, "Content-type: %s\n", MIME_TYPE_DEFAULT); - } else { - fprintf(f->output, "Content-type: %s\n", item->current_attach->mimetype); - } - fprintf(f->output, "Content-transfer-encoding: base64\n"); - if (item->current_attach->filename2 == NULL) { - fprintf(f->output, "Content-Disposition: inline\n\n"); - } else { - fprintf(f->output, "Content-Disposition: attachment; filename=\"%s\"\n\n", - item->current_attach->filename2); - } - } - if (item->current_attach->data != NULL) { - fwrite(enc, 1, strlen(enc), f->output); - DEBUG_MAIN(("Attachment Size after encoding is %i\n", strlen(enc))); - } else { - pst_attach_to_file_base64(&pstfile, item->current_attach, f->output); - } - fprintf(f->output, "\n\n"); - } - item->current_attach = item->current_attach->next; - attach_num++; - } - if (mode != MODE_SEPERATE) { - DEBUG_MAIN(("main: Writing buffer between emails\n")); - if (boundary) - fprintf(f->output, "\n--%s--\n", boundary); - fprintf(f->output, "\n\n"); - } - // }}}2 - } else if (item->type == PST_TYPE_JOURNAL) { - // Process Journal item {{{2 - // deal with journal items - if (mode == MODE_SEPERATE) { - mk_seperate_file(f); - } - f->email_count++; - - DEBUG_MAIN(("main: Processing Journal Entry\n")); - if (f->type != PST_TYPE_JOURNAL) { - DEBUG_MAIN(("main: I have a journal entry, but folder isn't specified as a journal type. Processing...\n")); - } - - /* if (item->type != PST_TYPE_JOURNAL) { - DEBUG_MAIN(("main: I have an item with journal info, but it's type is \"%s\" \n. Processing...\n", - item->ascii_type)); - }*/ - fprintf(f->output, "BEGIN:VJOURNAL\n"); - if (item->email->subject != NULL) - fprintf(f->output, "SUMMARY:%s\n", rfc2426_escape(item->email->subject->subj)); - if (item->email->body != NULL) - fprintf(f->output, "DESCRIPTION:%s\n", rfc2426_escape(item->email->body)); - if (item->journal->start != NULL) - fprintf(f->output, "DTSTART;VALUE=DATE-TIME:%s\n", rfc2445_datetime_format(item->journal->start)); - fprintf(f->output, "END:VJOURNAL\n\n"); - // }}}2 - } else if (item->type == PST_TYPE_APPOINTMENT) { - // Process Calendar Appointment item {{{2 - // deal with Calendar appointments - if (mode == MODE_SEPERATE) { - mk_seperate_file(f); - } - f->email_count++; - - DEBUG_MAIN(("main: Processing Appointment Entry\n")); - if (f->type != PST_TYPE_APPOINTMENT) { - DEBUG_MAIN(("main: I have an appointment, but folder isn't specified as an appointment type. Processing...\n")); - } - fprintf(f->output, "BEGIN:VEVENT\n"); - if (item->create_date != NULL) - fprintf(f->output, "CREATED:%s\n", rfc2445_datetime_format(item->create_date)); - if (item->modify_date != NULL) - fprintf(f->output, "LAST-MOD:%s\n", rfc2445_datetime_format(item->modify_date)); - if (item->email != NULL && item->email->subject != NULL) - fprintf(f->output, "SUMMARY:%s\n", rfc2426_escape(item->email->subject->subj)); - if (item->email != NULL && item->email->body != NULL) - fprintf(f->output, "DESCRIPTION:%s\n", rfc2426_escape(item->email->body)); - if (item->appointment != NULL && item->appointment->start != NULL) - fprintf(f->output, "DTSTART;VALUE=DATE-TIME:%s\n", rfc2445_datetime_format(item->appointment->start)); - if (item->appointment != NULL && item->appointment->end != NULL) - fprintf(f->output, "DTEND;VALUE=DATE-TIME:%s\n", rfc2445_datetime_format(item->appointment->end)); - if (item->appointment != NULL && item->appointment->location != NULL) - fprintf(f->output, "LOCATION:%s\n", rfc2426_escape(item->appointment->location)); - if (item->appointment != NULL) { - switch (item->appointment->showas) { - case PST_FREEBUSY_TENTATIVE: - fprintf(f->output, "STATUS:TENTATIVE\n"); - break; - case PST_FREEBUSY_FREE: - // mark as transparent and as confirmed - fprintf(f->output, "TRANSP:TRANSPARENT\n"); - case PST_FREEBUSY_BUSY: - case PST_FREEBUSY_OUT_OF_OFFICE: - fprintf(f->output, "STATUS:CONFIRMED\n"); - break; - } - switch (item->appointment->label) { - case PST_APP_LABEL_NONE: - fprintf(f->output, "CATEGORIES:NONE\n"); break; - case PST_APP_LABEL_IMPORTANT: - fprintf(f->output, "CATEGORIES:IMPORTANT\n"); break; - case PST_APP_LABEL_BUSINESS: - fprintf(f->output, "CATEGORIES:BUSINESS\n"); break; - case PST_APP_LABEL_PERSONAL: - fprintf(f->output, "CATEGORIES:PERSONAL\n"); break; - case PST_APP_LABEL_VACATION: - fprintf(f->output, "CATEGORIES:VACATION\n"); break; - case PST_APP_LABEL_MUST_ATTEND: - fprintf(f->output, "CATEGORIES:MUST-ATTEND\n"); break; - case PST_APP_LABEL_TRAVEL_REQ: - fprintf(f->output, "CATEGORIES:TRAVEL-REQUIRED\n"); break; - case PST_APP_LABEL_NEEDS_PREP: - fprintf(f->output, "CATEGORIES:NEEDS-PREPARATION\n"); break; - case PST_APP_LABEL_BIRTHDAY: - fprintf(f->output, "CATEGORIES:BIRTHDAY\n"); break; - case PST_APP_LABEL_ANNIVERSARY: - fprintf(f->output, "CATEGORIES:ANNIVERSARY\n"); break; - case PST_APP_LABEL_PHONE_CALL: - fprintf(f->output, "CATEGORIES:PHONE-CALL\n"); break; - } - } - fprintf(f->output, "END:VEVENT\n\n"); - // }}}2 - } else { - f->skip_count++; - DEBUG_MAIN(("main: Unknown item type. %i. Ascii1=\"%s\"\n", - item->type, item->ascii_type)); - } - } else { - f->skip_count++; - DEBUG_MAIN(("main: A NULL item was seen\n")); - } - - DEBUG_MAIN(("main: Going to next d_ptr\n")); - if (boundary) { - free(boundary); - boundary = NULL; - } + DEBUG_MAIN(("main: New item record\n")); + if (d_ptr->desc == NULL) { + DEBUG_WARN(("main: ERROR ?? item's desc record is NULL\n")); + f->skip_count++; + goto check_parent; + } + DEBUG_MAIN(("main: Desc Email ID %#x [d_ptr->id = %#x]\n", d_ptr->desc->id, d_ptr->id)); + + item = _pst_parse_item(&pstfile, d_ptr); + DEBUG_MAIN(("main: About to process item\n")); + if (item != NULL && item->email != NULL && item->email->subject != NULL && + item->email->subject->subj != NULL) { + // DEBUG_EMAIL(("item->email->subject = %p\n", item->email->subject)); + // DEBUG_EMAIL(("item->email->subject->subj = %p\n", item->email->subject->subj)); + } + if (item != NULL) { + if (item->message_store != NULL) { + // there should only be one message_store, and we have already done it + DIE(("main: A second message_store has been found. Sorry, this must be an error.\n")); + } + + + if (item->folder != NULL) { + // if this is a folder, we want to recurse into it + if (output_mode != OUTPUT_QUIET) printf("Processing Folder \"%s\"\n", item->file_as); + // f->email_count++; + DEBUG_MAIN(("main: I think I may try to go into folder \"%s\"\n", item->file_as)); + f = (struct file_ll*) malloc(sizeof(struct file_ll)); + memset(f, 0, sizeof(struct file_ll)); + + f->next = head; + f->email_count = 0; + f->type = item->type; + f->stored_count = item->folder->email_count; + head = f; + + temp = item->file_as; + temp = check_filename(temp); + + if (mode == MODE_KMAIL) + f->name = mk_kmail_dir(item->file_as); //create directory and form filename + else if (mode == MODE_RECURSE) + f->name = mk_recurse_dir(item->file_as); + else if (mode == MODE_SEPERATE) { + // do similar stuff to recurse here. + mk_seperate_dir(item->file_as, overwrite); + f->name = (char*) xmalloc(10); + memset(f->name, 0, 10); + // sprintf(f->name, "%09i", f->email_count); + } else { + f->name = (char*) xmalloc(strlen(item->file_as)+strlen(OUTPUT_TEMPLATE+1)); + sprintf(f->name, OUTPUT_TEMPLATE, item->file_as); + } + + f->dname = (char*) xmalloc(strlen(item->file_as)+1); + strcpy(f->dname, item->file_as); + + if (overwrite != 1) { + temp = (char*) xmalloc (strlen(f->name)+10); //enough room for 10 digits + sprintf(temp, "%s", f->name); + x = 0; + temp = check_filename(temp); + while ((f->output = fopen(temp, "r")) != NULL) { + DEBUG_MAIN(("main: need to increase filename cause one already exists with that name\n")); + DEBUG_MAIN(("main: - increasing it to %s%d\n", f->name, x)); + x++; + sprintf(temp, "%s%08d", f->name, x); + DEBUG_MAIN(("main: - trying \"%s\"\n", f->name)); + if (x == 99999999) { + DIE(("main: Why can I not create a folder %s? I have tried %i extensions...\n", f->name, x)); + } + fclose(f->output); + } + if (x > 0) { //then the f->name should change + free (f->name); + f->name = temp; + } else { + free(temp); + } + } + + DEBUG_MAIN(("main: f->name = %s\nitem->folder_name = %s\n", f->name, item->file_as)); + if (mode != MODE_SEPERATE) { + f->name = check_filename(f->name); + if ((f->output = fopen(f->name, "w")) == NULL) { + DIE(("main: Could not open file \"%s\" for write\n", f->name)); + } + } + if (d_ptr->child != NULL) { + d_ptr = d_ptr->child; + skip_child = 1; + } else { + DEBUG_MAIN(("main: Folder has NO children. Creating directory, and closing again\n")); + if (output_mode != OUTPUT_QUIET) + printf("\tNo items to process in folder \"%s\", should have been %i\n", f->dname, f->stored_count); + head = f->next; + if (f->output != NULL) + fclose(f->output); + if (mode == MODE_KMAIL) + close_kmail_dir(); + else if (mode == MODE_RECURSE) + close_recurse_dir(); + else if (mode == MODE_SEPERATE) + close_seperate_dir(); + free(f->dname); + free(f->name); + free(f); + + f = head; + } + _pst_freeItem(item); + item = NULL; // just for the odd situations! + goto check_parent; + } else if (item->contact != NULL) { + // deal with a contact + // write them to the file, one per line in this format + // Desc Name \n + if (mode == MODE_SEPERATE) { + mk_seperate_file(f); + } + f->email_count++; + + DEBUG_MAIN(("main: Processing Contact\n")); + if (f->type != PST_TYPE_CONTACT) { + DEBUG_MAIN(("main: I have a contact, but the folder isn't a contacts folder. " + "Will process anyway\n")); + } + if (item->type != PST_TYPE_CONTACT) { + DEBUG_MAIN(("main: I have an item that has contact info, but doesn't say that" + " it is a contact. Type is \"%s\"\n", item->ascii_type)); + DEBUG_MAIN(("main: Processing anyway\n")); + } + if (item->contact == NULL) { // this is an incorrect situation. Inform user + DEBUG_MAIN(("main: ERROR. This contact has not been fully parsed. one of the pre-requisties is NULL\n")); + } else { + if (contact_mode == CMODE_VCARD) { + // the specification I am following is (hopefully) RFC2426 vCard Mime Directory Profile + fprintf(f->output, "BEGIN:VCARD\n"); + fprintf(f->output, "FN:%s\n", rfc2426_escape(item->contact->fullname)); + fprintf(f->output, "N:%s;%s;%s;%s;%s\n", + rfc2426_escape((item->contact->surname==NULL?"":item->contact->surname)), + rfc2426_escape((item->contact->first_name==NULL?"":item->contact->first_name)), + rfc2426_escape((item->contact->middle_name==NULL?"":item->contact->middle_name)), + rfc2426_escape((item->contact->display_name_prefix==NULL?"":item->contact->display_name_prefix)), + rfc2426_escape((item->contact->suffix==NULL?"":item->contact->suffix))); + if (item->contact->nickname != NULL) + fprintf(f->output, "NICKNAME:%s\n", rfc2426_escape(item->contact->nickname)); + if (item->contact->address1 != NULL) + fprintf(f->output, "EMAIL:%s\n", rfc2426_escape(item->contact->address1)); + if (item->contact->address2 != NULL) + fprintf(f->output, "EMAIL:%s\n", rfc2426_escape(item->contact->address2)); + if (item->contact->address3 != NULL) + fprintf(f->output, "EMAIL:%s\n", rfc2426_escape(item->contact->address3)); + if (item->contact->birthday != NULL) + fprintf(f->output, "BDAY:%s\n", rfc2425_datetime_format(item->contact->birthday)); + if (item->contact->home_address != NULL) { + fprintf(f->output, "ADR;TYPE=home:%s;%s;%s;%s;%s;%s;%s\n", + rfc2426_escape((item->contact->home_po_box!=NULL?item->contact->home_po_box:"")), + "", // extended Address + rfc2426_escape((item->contact->home_street!=NULL?item->contact->home_street:"")), + rfc2426_escape((item->contact->home_city!=NULL?item->contact->home_city:"")), + rfc2426_escape((item->contact->home_state!=NULL?item->contact->home_state:"")), + rfc2426_escape((item->contact->home_postal_code!=NULL?item->contact->home_postal_code:"")), + rfc2426_escape((item->contact->home_country!=NULL?item->contact->home_country:""))); + fprintf(f->output, "LABEL;TYPE=home:%s\n", rfc2426_escape(item->contact->home_address)); + } + if (item->contact->business_address != NULL) { + fprintf(f->output, "ADR;TYPE=work:%s;%s;%s;%s;%s;%s;%s\n", + rfc2426_escape((item->contact->business_po_box!=NULL?item->contact->business_po_box:"")), + "", // extended Address + rfc2426_escape((item->contact->business_street!=NULL?item->contact->business_street:"")), + rfc2426_escape((item->contact->business_city!=NULL?item->contact->business_city:"")), + rfc2426_escape((item->contact->business_state!=NULL?item->contact->business_state:"")), + rfc2426_escape((item->contact->business_postal_code!=NULL?item->contact->business_postal_code:"")), + rfc2426_escape((item->contact->business_country!=NULL?item->contact->business_country:""))); + fprintf(f->output, "LABEL;TYPE=work:%s\n", rfc2426_escape(item->contact->business_address)); + } + if (item->contact->other_address != NULL) { + fprintf(f->output, "ADR;TYPE=postal:%s;%s;%s;%s;%s;%s;%s\n", + rfc2426_escape((item->contact->other_po_box!=NULL?item->contact->business_po_box:"")), + "", // extended Address + rfc2426_escape((item->contact->other_street!=NULL?item->contact->other_street:"")), + rfc2426_escape((item->contact->other_city!=NULL?item->contact->other_city:"")), + rfc2426_escape((item->contact->other_state!=NULL?item->contact->other_state:"")), + rfc2426_escape((item->contact->other_postal_code!=NULL?item->contact->other_postal_code:"")), + rfc2426_escape((item->contact->other_country!=NULL?item->contact->other_country:""))); + fprintf(f->output, "ADR;TYPE=postal:%s\n", rfc2426_escape(item->contact->other_address)); + } + if (item->contact->business_fax != NULL) + fprintf(f->output, "TEL;TYPE=work,fax:%s\n", rfc2426_escape(item->contact->business_fax)); + if (item->contact->business_phone != NULL) + fprintf(f->output, "TEL;TYPE=work,voice:%s\n", rfc2426_escape(item->contact->business_phone)); + if (item->contact->business_phone2 != NULL) + fprintf(f->output, "TEL;TYPE=work,voice:%s\n", rfc2426_escape(item->contact->business_phone2)); + if (item->contact->car_phone != NULL) + fprintf(f->output, "TEL;TYPE=car,voice:%s\n", rfc2426_escape(item->contact->car_phone)); + if (item->contact->home_fax != NULL) + fprintf(f->output, "TEL;TYPE=home,fax:%s\n", rfc2426_escape(item->contact->home_fax)); + if (item->contact->home_phone != NULL) + fprintf(f->output, "TEL;TYPE=home,voice:%s\n", rfc2426_escape(item->contact->home_phone)); + if (item->contact->home_phone2 != NULL) + fprintf(f->output, "TEL;TYPE=home,voice:%s\n", rfc2426_escape(item->contact->home_phone2)); + if (item->contact->isdn_phone != NULL) + fprintf(f->output, "TEL;TYPE=isdn:%s\n", rfc2426_escape(item->contact->isdn_phone)); + if (item->contact->mobile_phone != NULL) + fprintf(f->output, "TEL;TYPE=cell,voice:%s\n", rfc2426_escape(item->contact->mobile_phone)); + if (item->contact->other_phone != NULL) + fprintf(f->output, "TEL;TYPE=msg:%s\n", rfc2426_escape(item->contact->other_phone)); + if (item->contact->pager_phone != NULL) + fprintf(f->output, "TEL;TYPE=pager:%s\n", rfc2426_escape(item->contact->pager_phone)); + if (item->contact->primary_fax != NULL) + fprintf(f->output, "TEL;TYPE=fax,pref:%s\n", rfc2426_escape(item->contact->primary_fax)); + if (item->contact->primary_phone != NULL) + fprintf(f->output, "TEL;TYPE=phone,pref:%s\n", rfc2426_escape(item->contact->primary_phone)); + if (item->contact->radio_phone != NULL) + fprintf(f->output, "TEL;TYPE=pcs:%s\n", rfc2426_escape(item->contact->radio_phone)); + if (item->contact->telex != NULL) + fprintf(f->output, "TEL;TYPE=bbs:%s\n", rfc2426_escape(item->contact->telex)); + if (item->contact->job_title != NULL) + fprintf(f->output, "TITLE:%s\n", rfc2426_escape(item->contact->job_title)); + if (item->contact->profession != NULL) + fprintf(f->output, "ROLE:%s\n", rfc2426_escape(item->contact->profession)); + if (item->contact->assistant_name != NULL || item->contact->assistant_phone != NULL) { + fprintf(f->output, "AGENT:BEGIN:VCARD\\n"); + if (item->contact->assistant_name != NULL) + fprintf(f->output, "FN:%s\\n", rfc2426_escape(item->contact->assistant_name)); + if (item->contact->assistant_phone != NULL) + fprintf(f->output, "TEL:%s\\n", rfc2426_escape(item->contact->assistant_phone)); + fprintf(f->output, "END:VCARD\\n\n"); + } + if (item->contact->company_name != NULL) + fprintf(f->output, "ORG:%s\n", rfc2426_escape(item->contact->company_name)); + if (item->comment != NULL) + fprintf(f->output, "NOTE:%s\n", rfc2426_escape(item->comment)); + + fprintf(f->output, "VERSION: 3.0\n"); + fprintf(f->output, "END:VCARD\n\n"); + } else { + fprintf(f->output, "%s <%s>\n", item->contact->fullname, item->contact->address1); + } + } + } else if (item->email != NULL && + (item->type == PST_TYPE_NOTE || item->type == PST_TYPE_REPORT)) { + if (mode == MODE_SEPERATE) { + mk_seperate_file(f); + } + + f->email_count++; + + DEBUG_MAIN(("main: seen an email\n")); + + // convert the sent date if it exists, or set it to a fixed date + if (item->email->sent_date != NULL) { + em_time = fileTimeToUnixTime(item->email->sent_date, 0); + c_time = ctime(&em_time); + if (c_time != NULL) + c_time[strlen(c_time)-1] = '\0'; //remove end \n + else + c_time = "Fri Dec 28 12:06:21 2001"; + } else + c_time= "Fri Dec 28 12:06:21 2001"; + + // if the boundary is still set from the previous run, then free it + if (boundary != NULL) { + free (boundary); + boundary = NULL; + } + + // we will always look at the header to discover some stuff + if (item->email->header != NULL ) { + // see if there is a boundary variable there + // this search MUST be made case insensitive (DONE). + // Also, some check to find out if we + // are looking at the boundary associated with content-type, and that the content + // type really is "multipart" + if ((b2 = my_stristr(item->email->header, "boundary=")) != NULL) { + b2 += strlen("boundary="); // move boundary to first char of marker + + if (*b2 == '"') { + b2++; + b1 = strchr(b2, '"'); // find terminating quote + } else { + b1 = b2; + while (isgraph(*b1)) // find first char that isn't part of boundary + b1++; + } + + boundary = malloc ((b1-b2)+1); //malloc that length + memset (boundary, 0, (b1-b2)+1); // blank it + strncpy(boundary, b2, b1-b2); // copy boundary to another variable + b1 = b2 = boundary; + while (*b2 != '\0') { // remove any CRs and Tabs + if (*b2 != '\n' && *b2 != '\r' && *b2 != '\t') { + *b1 = *b2; + b1++; + } + b2++; + } + *b1 = '\0'; + + DEBUG_MAIN(("main: Found boundary of - %s\n", boundary)); + } else { + + DEBUG_MAIN(("main: boundary not found in header\n")); + } + + // also possible to set 7bit encoding detection here. + if ((b2 = my_stristr(item->email->header, "Content-Transfer-Encoding:")) != NULL) { + if ((b2 = strchr(b2, ':')) != NULL) { + b2++; // skip to the : at the end of the string + + while (*b2 == ' ' || *b2 == '\t') + b2++; + if (pst_strincmp(b2, "base64", 6)==0) { + DEBUG_MAIN(("body is base64 encoded\n")); + base64_body = 1; + } + } else { + DEBUG_WARN(("found a ':' during the my_stristr, but not after that..\n")); + } + } + + } + + DEBUG_MAIN(("main: About to print Header\n")); + + if (item != NULL && item->email != NULL && item->email->subject != NULL && + item->email->subject->subj != NULL) { + DEBUG_EMAIL(("item->email->subject->subj = %p\n", item->email->subject->subj)); + } + if (item->email->header != NULL) { + // some of the headers we get from the file are not properly defined. + // they can contain some email stuff too. We will cut off the header + // when we see a \n\n or \r\n\r\n + + removeCR(item->email->header); + + temp = strstr(item->email->header, "\n\n"); + + if (temp != NULL) { + DEBUG_MAIN(("main: Found body text in header\n")); + *temp = '\0'; + } + + if (mode != MODE_SEPERATE) { + char *soh = NULL; // real start of headers. + // don't put rubbish in if we are doing seperate + fprintf(f->output, "From \"%s\" %s\n", item->email->outlook_sender_name, c_time); + soh = skip_header_prologue(item->email->header); + fprintf(f->output, "%s\n", soh); + } else { + fprintf(f->output, "%s", item->email->header); + } + } else { + //make up our own header! + if (mode != MODE_SEPERATE) { + // don't want this first line for this mode + if (item->email->outlook_sender_name != NULL) { + temp = item->email->outlook_sender_name; + } else { + temp = "(readpst_null)"; + } + fprintf(f->output, "From \"%s\" %s\n", temp, c_time); + } + if ((temp = item->email->outlook_sender) == NULL) + temp = ""; + fprintf(f->output, "From: \"%s\" <%s>\n", item->email->outlook_sender_name, temp); + if (item->email->subject != NULL) { + fprintf(f->output, "Subject: %s\n", item->email->subject->subj); + } else { + fprintf(f->output, "Subject: \n"); + } + fprintf(f->output, "To: %s\n", item->email->sentto_address); + if (item->email->cc_address != NULL) { + fprintf(f->output, "Cc: %s\n", item->email->cc_address); + } + if (item->email->sent_date != NULL) { + c_time = (char*) xmalloc(C_TIME_SIZE); + strftime(c_time, C_TIME_SIZE, "%a, %d %b %Y %H:%M:%S %z", gmtime(&em_time)); + fprintf(f->output, "Date: %s\n", c_time); + free(c_time); + } + + fprintf(f->output, "MIME-Version: 1.0\n"); + } + if (boundary == NULL && (item->attach ||(item->email->body && item->email->htmlbody) + || item->email->rtf_compressed || item->email->encrypted_body + || item->email->encrypted_htmlbody)) { + // we need to create a boundary here. + DEBUG_EMAIL(("main: must create own boundary. oh dear.\n")); + boundary = malloc(50 * sizeof(char)); // allow 50 chars for boundary + boundary[0] = '\0'; + sprintf(boundary, "--boundary-LibPST-iamunique-%i_-_-", rand()); + DEBUG_EMAIL(("main: created boundary is %s\n", boundary)); + + /* If boundary != NULL, then it'll already be printed with existing + * headers. Otherwise, we generate it here, and print it. + */ + if (item->attach != NULL) { + // write the boundary stuff if we have attachments + fprintf(f->output, "Content-type: multipart/mixed;\n\tboundary=\"%s\"\n", + boundary); + } else if (boundary != NULL) { + // else if we have multipart/alternative then tell it so + fprintf(f->output, "Content-type: multipart/alternative;\n\tboundary=\"%s\"\n", + boundary); + } else if (item->email->htmlbody) { + fprintf(f->output, "Content-type: text/html\n"); + } + } + fprintf(f->output, "\n"); + + DEBUG_MAIN(("main: About to print Body\n")); + + if (item->email->body != NULL) { + if (boundary) { + fprintf(f->output, "\n--%s\n", boundary); + fprintf(f->output, "Content-type: text/plain\n"); + if (base64_body) fprintf(f->output, "Content-Transfer-Encoding: base64\n"); + fprintf(f->output, "\n"); + } + removeCR(item->email->body); + if (base64_body) + write_email_body(f->output, base64_encode(item->email->body, + strlen(item->email->body))); + else + write_email_body(f->output, item->email->body); + } + + if (item->email->htmlbody != NULL) { + if (boundary) { + fprintf(f->output, "\n--%s\n", boundary); + fprintf(f->output, "Content-type: text/html\n"); + if (base64_body) fprintf(f->output, "Content-Transfer-Encoding: base64\n"); + fprintf(f->output, "\n"); + } + removeCR(item->email->htmlbody); + if (base64_body) + write_email_body(f->output, base64_encode(item->email->htmlbody, + strlen(item->email->htmlbody))); + else + write_email_body(f->output, item->email->htmlbody); + } + + attach_num = 0; + + if (item->email->rtf_compressed != NULL) { + DEBUG_MAIN(("Adding RTF body as attachment\n")); + item->current_attach = (pst_item_attach*)xmalloc(sizeof(pst_item_attach)); + memset(item->current_attach, 0, sizeof(pst_item_attach)); + item->current_attach->next = item->attach; + item->attach = item->current_attach; + item->current_attach->data = lzfu_decompress(item->email->rtf_compressed); + item->current_attach->filename2 = xmalloc(strlen(RTF_ATTACH_NAME)+2); + strcpy(item->current_attach->filename2, RTF_ATTACH_NAME); + item->current_attach->mimetype = xmalloc(strlen(RTF_ATTACH_TYPE)+2); + strcpy(item->current_attach->mimetype, RTF_ATTACH_TYPE); + memcpy(&(item->current_attach->size), item->email->rtf_compressed+sizeof(int32_t), sizeof(int32_t)); + LE32_CPU(item->current_attach->size); + // item->email->rtf_compressed = ; + // attach_num++; + } + if (item->email->encrypted_body || item->email->encrypted_htmlbody) { + // if either the body or htmlbody is encrypted, add them as attachments + if (item->email->encrypted_body) { + DEBUG_MAIN(("Adding Encrypted Body as attachment\n")); + item->current_attach = (pst_item_attach*) xmalloc(sizeof(pst_item_attach)); + memset(item->current_attach, 0, sizeof(pst_item_attach)); + item->current_attach->next = item->attach; + item->attach = item->current_attach; + + item->current_attach->data = item->email->encrypted_body; + item->current_attach->size = item->email->encrypted_body_size; + item->email->encrypted_body = NULL; + } + if (item->email->encrypted_htmlbody) { + DEBUG_MAIN(("Adding encrypted HTML body as attachment\n")); + item->current_attach = (pst_item_attach*) xmalloc(sizeof(pst_item_attach)); + memset(item->current_attach, 0, sizeof(pst_item_attach)); + item->current_attach->next = item->attach; + item->attach = item->current_attach; + + item->current_attach->data = item->email->encrypted_htmlbody; + item->current_attach->size = item->email->encrypted_htmlbody_size; + item->email->encrypted_htmlbody = NULL; + } + 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"); + } + base64_body = 0; + // attachments + item->current_attach = item->attach; + while (item->current_attach != NULL) { + DEBUG_MAIN(("main: Attempting Attachment encoding\n")); + if (item->current_attach->data == NULL) { + DEBUG_MAIN(("main: Data of attachment is NULL!. Size is supposed to be %i\n", item->current_attach->size)); + } + if (mode == MODE_SEPERATE) { + f->name = check_filename(f->name); + if (item->current_attach->filename2 == NULL) { + temp = xmalloc(strlen(f->name)+15); + sprintf(temp, "%s-attach%i", f->name, attach_num); + } else { + temp = xmalloc(strlen(f->name)+strlen(item->current_attach->filename2)+15); + fp = NULL; x=0; + do { + if (fp != NULL) fclose(fp); + if (x == 0) + sprintf(temp, "%s-%s", f->name, item->current_attach->filename2); + else + sprintf(temp, "%s-%s-%i", f->name, item->current_attach->filename2, x); + } while ((fp = fopen(temp, "r"))!=NULL && ++x < 99999999); + if (x > 99999999) { + DIE(("error finding attachment name. exhausted possibilities to %s\n", temp)); + } + } + DEBUG_MAIN(("main: Saving attachment to %s\n", temp)); + if ((fp = fopen(temp, "w")) == NULL) { + WARN(("main: Cannot open attachment save file \"%s\"\n", temp)); + } else { + if (item->current_attach->data != NULL) + fwrite(item->current_attach->data, 1, item->current_attach->size, fp); + else { + pst_attach_to_file(&pstfile, item->current_attach, fp); + } + fclose(fp); + } + } else { + DEBUG_MAIN(("main: Attachment Size is %i\n", item->current_attach->size)); + DEBUG_MAIN(("main: Attachment Pointer is %p\n", item->current_attach->data)); + if (item->current_attach->data != NULL) { + if ((enc = base64_encode (item->current_attach->data, item->current_attach->size)) == NULL) { + DEBUG_MAIN(("main: ERROR base64_encode returned NULL. Must have failed\n")); + item->current_attach = item->current_attach->next; + continue; + } + } + if (boundary) { + fprintf(f->output, "\n--%s\n", boundary); + if (item->current_attach->mimetype == NULL) { + fprintf(f->output, "Content-type: %s\n", MIME_TYPE_DEFAULT); + } else { + fprintf(f->output, "Content-type: %s\n", item->current_attach->mimetype); + } + fprintf(f->output, "Content-transfer-encoding: base64\n"); + if (item->current_attach->filename2 == NULL) { + fprintf(f->output, "Content-Disposition: inline\n\n"); + } else { + fprintf(f->output, "Content-Disposition: attachment; filename=\"%s\"\n\n", + item->current_attach->filename2); + } + } + if (item->current_attach->data != NULL) { + fwrite(enc, 1, strlen(enc), f->output); + DEBUG_MAIN(("Attachment Size after encoding is %i\n", strlen(enc))); + } else { + pst_attach_to_file_base64(&pstfile, item->current_attach, f->output); + } + fprintf(f->output, "\n\n"); + } + item->current_attach = item->current_attach->next; + attach_num++; + } + if (mode != MODE_SEPERATE) { + DEBUG_MAIN(("main: Writing buffer between emails\n")); + if (boundary) + fprintf(f->output, "\n--%s--\n", boundary); + fprintf(f->output, "\n\n"); + } + } else if (item->type == PST_TYPE_JOURNAL) { + // deal with journal items + if (mode == MODE_SEPERATE) { + mk_seperate_file(f); + } + f->email_count++; + + DEBUG_MAIN(("main: Processing Journal Entry\n")); + if (f->type != PST_TYPE_JOURNAL) { + DEBUG_MAIN(("main: I have a journal entry, but folder isn't specified as a journal type. Processing...\n")); + } + + /* if (item->type != PST_TYPE_JOURNAL) { + DEBUG_MAIN(("main: I have an item with journal info, but it's type is \"%s\" \n. Processing...\n", + item->ascii_type)); + }*/ + fprintf(f->output, "BEGIN:VJOURNAL\n"); + if (item->email->subject != NULL) + fprintf(f->output, "SUMMARY:%s\n", rfc2426_escape(item->email->subject->subj)); + if (item->email->body != NULL) + fprintf(f->output, "DESCRIPTION:%s\n", rfc2426_escape(item->email->body)); + if (item->journal->start != NULL) + fprintf(f->output, "DTSTART;VALUE=DATE-TIME:%s\n", rfc2445_datetime_format(item->journal->start)); + fprintf(f->output, "END:VJOURNAL\n\n"); + } else if (item->type == PST_TYPE_APPOINTMENT) { + // deal with Calendar appointments + if (mode == MODE_SEPERATE) { + mk_seperate_file(f); + } + f->email_count++; + + DEBUG_MAIN(("main: Processing Appointment Entry\n")); + if (f->type != PST_TYPE_APPOINTMENT) { + DEBUG_MAIN(("main: I have an appointment, but folder isn't specified as an appointment type. Processing...\n")); + } + fprintf(f->output, "BEGIN:VEVENT\n"); + if (item->create_date != NULL) + fprintf(f->output, "CREATED:%s\n", rfc2445_datetime_format(item->create_date)); + if (item->modify_date != NULL) + fprintf(f->output, "LAST-MOD:%s\n", rfc2445_datetime_format(item->modify_date)); + if (item->email != NULL && item->email->subject != NULL) + fprintf(f->output, "SUMMARY:%s\n", rfc2426_escape(item->email->subject->subj)); + if (item->email != NULL && item->email->body != NULL) + fprintf(f->output, "DESCRIPTION:%s\n", rfc2426_escape(item->email->body)); + if (item->appointment != NULL && item->appointment->start != NULL) + fprintf(f->output, "DTSTART;VALUE=DATE-TIME:%s\n", rfc2445_datetime_format(item->appointment->start)); + if (item->appointment != NULL && item->appointment->end != NULL) + fprintf(f->output, "DTEND;VALUE=DATE-TIME:%s\n", rfc2445_datetime_format(item->appointment->end)); + if (item->appointment != NULL && item->appointment->location != NULL) + fprintf(f->output, "LOCATION:%s\n", rfc2426_escape(item->appointment->location)); + if (item->appointment != NULL) { + switch (item->appointment->showas) { + case PST_FREEBUSY_TENTATIVE: + fprintf(f->output, "STATUS:TENTATIVE\n"); + break; + case PST_FREEBUSY_FREE: + // mark as transparent and as confirmed + fprintf(f->output, "TRANSP:TRANSPARENT\n"); + case PST_FREEBUSY_BUSY: + case PST_FREEBUSY_OUT_OF_OFFICE: + fprintf(f->output, "STATUS:CONFIRMED\n"); + break; + } + switch (item->appointment->label) { + case PST_APP_LABEL_NONE: + fprintf(f->output, "CATEGORIES:NONE\n"); break; + case PST_APP_LABEL_IMPORTANT: + fprintf(f->output, "CATEGORIES:IMPORTANT\n"); break; + case PST_APP_LABEL_BUSINESS: + fprintf(f->output, "CATEGORIES:BUSINESS\n"); break; + case PST_APP_LABEL_PERSONAL: + fprintf(f->output, "CATEGORIES:PERSONAL\n"); break; + case PST_APP_LABEL_VACATION: + fprintf(f->output, "CATEGORIES:VACATION\n"); break; + case PST_APP_LABEL_MUST_ATTEND: + fprintf(f->output, "CATEGORIES:MUST-ATTEND\n"); break; + case PST_APP_LABEL_TRAVEL_REQ: + fprintf(f->output, "CATEGORIES:TRAVEL-REQUIRED\n"); break; + case PST_APP_LABEL_NEEDS_PREP: + fprintf(f->output, "CATEGORIES:NEEDS-PREPARATION\n"); break; + case PST_APP_LABEL_BIRTHDAY: + fprintf(f->output, "CATEGORIES:BIRTHDAY\n"); break; + case PST_APP_LABEL_ANNIVERSARY: + fprintf(f->output, "CATEGORIES:ANNIVERSARY\n"); break; + case PST_APP_LABEL_PHONE_CALL: + fprintf(f->output, "CATEGORIES:PHONE-CALL\n"); break; + } + } + fprintf(f->output, "END:VEVENT\n\n"); + } else { + f->skip_count++; + DEBUG_MAIN(("main: Unknown item type. %i. Ascii1=\"%s\"\n", + item->type, item->ascii_type)); + } + } else { + f->skip_count++; + DEBUG_MAIN(("main: A NULL item was seen\n")); + } + + DEBUG_MAIN(("main: Going to next d_ptr\n")); + if (boundary) { + free(boundary); + boundary = NULL; + } check_parent: - // _pst_freeItem(item); - while (!skip_child && d_ptr->next == NULL && d_ptr->parent != NULL) { - DEBUG_MAIN(("main: Going to Parent\n")); - head = f->next; - if (f->output != NULL) - fclose(f->output); - DEBUG_MAIN(("main: Email Count for folder %s is %i\n", f->dname, f->email_count)); - if (output_mode != OUTPUT_QUIET) - printf("\t\"%s\" - %i items done, skipped %i, should have been %i\n", - f->dname, f->email_count, f->skip_count, f->stored_count); - if (mode == MODE_KMAIL) - close_kmail_dir(); - else if (mode == MODE_RECURSE) - close_recurse_dir(); - else if (mode == MODE_SEPERATE) - close_seperate_dir(); - free(f->name); - free(f->dname); - free(f); - f = head; - if (head == NULL) { //we can't go higher. Must be at start? - DEBUG_MAIN(("main: We are now trying to go above the highest level. We must be finished\n")); - break; //from main while loop - } - d_ptr = d_ptr->parent; - skip_child = 0; - } - - if (item != NULL) { - DEBUG_MAIN(("main: Freeing memory used by item\n")); - _pst_freeItem(item); - item = NULL; - } - - if (!skip_child) - d_ptr = d_ptr->next; - else - skip_child = 0; - - if (d_ptr == NULL) { - DEBUG_MAIN(("main: d_ptr is now NULL\n")); - } + // _pst_freeItem(item); + while (!skip_child && d_ptr->next == NULL && d_ptr->parent != NULL) { + DEBUG_MAIN(("main: Going to Parent\n")); + head = f->next; + if (f->output != NULL) + fclose(f->output); + DEBUG_MAIN(("main: Email Count for folder %s is %i\n", f->dname, f->email_count)); + if (output_mode != OUTPUT_QUIET) + printf("\t\"%s\" - %i items done, skipped %i, should have been %i\n", + f->dname, f->email_count, f->skip_count, f->stored_count); + if (mode == MODE_KMAIL) + close_kmail_dir(); + else if (mode == MODE_RECURSE) + close_recurse_dir(); + else if (mode == MODE_SEPERATE) + close_seperate_dir(); + free(f->name); + free(f->dname); + free(f); + f = head; + if (head == NULL) { //we can't go higher. Must be at start? + DEBUG_MAIN(("main: We are now trying to go above the highest level. We must be finished\n")); + break; //from main while loop + } + d_ptr = d_ptr->parent; + skip_child = 0; + } + + if (item != NULL) { + DEBUG_MAIN(("main: Freeing memory used by item\n")); + _pst_freeItem(item); + item = NULL; + } + + if (!skip_child) + d_ptr = d_ptr->next; + else + skip_child = 0; + + if (d_ptr == NULL) { + DEBUG_MAIN(("main: d_ptr is now NULL\n")); + } } if (output_mode != OUTPUT_QUIET) printf("Finished.\n"); DEBUG_MAIN(("main: Finished.\n")); - // Cleanup {{{2 pst_close(&pstfile); // fclose(pstfile.fp); while (f != NULL) { - if (f->output != NULL) - fclose(f->output); - free(f->name); - free(f->dname); - - if (mode == MODE_KMAIL) - close_kmail_dir(); - else if (mode == MODE_RECURSE) - close_recurse_dir(); - else if (mode == MODE_SEPERATE) - // DO SOMETHING HERE - ; - head = f->next; - free (f); - f = head; + if (f->output != NULL) + fclose(f->output); + free(f->name); + free(f->dname); + + if (mode == MODE_KMAIL) + close_kmail_dir(); + else if (mode == MODE_RECURSE) + close_recurse_dir(); + else if (mode == MODE_SEPERATE) + // DO SOMETHING HERE + ; + head = f->next; + free (f); + f = head; } DEBUG_RET(); - // }}}2 return 0; } -// }}}1 -// void write_email_body(FILE *f, char *body) {{{1 void write_email_body(FILE *f, char *body) { char *n = body; // DEBUG_MAIN(("write_email_body(): \"%s\"\n", body)); DEBUG_ENT("write_email_body"); while (n != NULL) { - if (strncmp(body, "From ", 5) == 0) - fprintf(f, ">"); - if ((n = strchr(body, '\n'))) { - n++; - fwrite(body, n-body, 1, f); //write just a line - - body = n; - } + if (strncmp(body, "From ", 5) == 0) + fprintf(f, ">"); + if ((n = strchr(body, '\n'))) { + n++; + fwrite(body, n-body, 1, f); //write just a line + + body = n; + } } fwrite(body, strlen(body), 1, f); DEBUG_RET(); } -// }}}1 -// char *removeCR (char *c) {{{1 char *removeCR (char *c) { // converts /r/n to /n char *a, *b; DEBUG_ENT("removeCR"); a = b = c; while (*a != '\0') { - *b = *a; - if (*a != '\r') - b++; - a++; + *b = *a; + if (*a != '\r') + b++; + a++; } *b = '\0'; DEBUG_RET(); return c; } -// }}}1 -// int usage() {{{1 int usage() { DEBUG_ENT("usage"); version(); printf("Usage: %s [OPTIONS] {PST FILENAME}\n", prog_name); printf("OPTIONS:\n"); printf("\t-c[v|l]\t- Set the Contact output mode. -cv = VCard, -cl = EMail list\n"); printf("\t-d\t- Debug to file. This is a binary log. Use readlog to print it\n"); printf("\t-h\t- Help. This screen\n"); printf("\t-k\t- KMail. Output in kmail format\n"); printf("\t-o\t- Output Dir. Directory to write files to. CWD is changed *after* opening pst file\n"); printf("\t-q\t- Quiet. Only print error messages\n"); printf("\t-r\t- Recursive. Output in a recursive format\n"); printf("\t-S\t- Seperate. Write emails in the seperate format\n"); printf("\t-V\t- Version. Display program version\n"); printf("\t-w\t- Overwrite any output mbox files\n"); DEBUG_RET(); return 0; } -// }}}1 -// int version() {{{1 int version() { DEBUG_ENT("version"); - printf("ReadPST v%s implementing LibPST v%s\n", VERSION, PST_VERSION); + printf("ReadPST v%s\n", VERSION); #if BYTE_ORDER == BIG_ENDIAN printf("Big Endian implementation being used.\n"); #elif BYTE_ORDER == LITTLE_ENDIAN printf("Little Endian implementation being used.\n"); #else # error "Byte order not supported by this library" #endif #ifdef __GNUC__ printf("GCC %d.%d : %s %s\n", __GNUC__, __GNUC_MINOR__, __DATE__, __TIME__); #endif DEBUG_RET(); return 0; } -// }}}1 -// char *mk_kmail_dir(char *fname) {{{1 char *mk_kmail_dir(char *fname) { //change to that directory //make a directory based on OUTPUT_KMAIL_DIR_TEMPLATE //allocate space for OUTPUT_TEMPLATE and form a char* with fname //return that value char *dir, *out_name, *index; int x; DEBUG_ENT("mk_kmail_dir"); if (kmail_chdir != NULL && chdir(kmail_chdir)) { - x = errno; - DIE(("mk_kmail_dir: Cannot change to directory %s: %s\n", kmail_chdir, strerror(x))); + x = errno; + DIE(("mk_kmail_dir: Cannot change to directory %s: %s\n", kmail_chdir, strerror(x))); } dir = malloc(strlen(fname)+strlen(OUTPUT_KMAIL_DIR_TEMPLATE)+1); sprintf(dir, OUTPUT_KMAIL_DIR_TEMPLATE, fname); dir = check_filename(dir); if (D_MKDIR(dir)) { - //error occured - if (errno != EEXIST) { - x = errno; - DIE(("mk_kmail_dir: Cannot create directory %s: %s\n", dir, strerror(x))); - } + //error occured + if (errno != EEXIST) { + x = errno; + DIE(("mk_kmail_dir: Cannot create directory %s: %s\n", dir, strerror(x))); + } } kmail_chdir = realloc(kmail_chdir, strlen(dir)+1); strcpy(kmail_chdir, dir); free (dir); //we should remove any existing indexes created by KMail, cause they might be different now index = malloc(strlen(fname)+strlen(KMAIL_INDEX)+1); sprintf(index, KMAIL_INDEX, fname); unlink(index); free(index); out_name = malloc(strlen(fname)+strlen(OUTPUT_TEMPLATE)+1); sprintf(out_name, OUTPUT_TEMPLATE, fname); DEBUG_RET(); return out_name; } -// }}}1 -// int close_kmail_dir() {{{1 int close_kmail_dir() { // change .. int x; DEBUG_ENT("close_kmail_dir"); if (kmail_chdir != NULL) { //only free kmail_chdir if not NULL. do not change directory - free(kmail_chdir); - kmail_chdir = NULL; + free(kmail_chdir); + kmail_chdir = NULL; } else { - if (chdir("..")) { - x = errno; - DIE(("close_kmail_dir: Cannot move up dir (..): %s\n", strerror(x))); - } + if (chdir("..")) { + x = errno; + DIE(("close_kmail_dir: Cannot move up dir (..): %s\n", strerror(x))); + } } DEBUG_RET(); return 0; } -// }}}1 -// char *mk_recurse_dir(char *dir) {{{1 // this will create a directory by that name, then make an mbox file inside // that dir. any subsequent dirs will be created by name, and they will // contain mbox files char *mk_recurse_dir(char *dir) { int x; char *out_name; DEBUG_ENT("mk_recurse_dir"); dir = check_filename(dir); if (D_MKDIR (dir)) { - if (errno != EEXIST) { // not an error because it exists - x = errno; - DIE(("mk_recurse_dir: Cannot create directory %s: %s\n", dir, strerror(x))); - } + if (errno != EEXIST) { // not an error because it exists + x = errno; + DIE(("mk_recurse_dir: Cannot create directory %s: %s\n", dir, strerror(x))); + } } if (chdir (dir)) { - x = errno; - DIE(("mk_recurse_dir: Cannot change to directory %s: %s\n", dir, strerror(x))); + x = errno; + DIE(("mk_recurse_dir: Cannot change to directory %s: %s\n", dir, strerror(x))); } out_name = malloc(strlen("mbox")+1); strcpy(out_name, "mbox"); DEBUG_RET(); return out_name; } -// }}}1 -// int close_recurse_dir() {{{1 int close_recurse_dir() { int x; DEBUG_ENT("close_recurse_dir"); if (chdir("..")) { - x = errno; - DIE(("close_recurse_dir: Cannot go up dir (..): %s\n", strerror(x))); + x = errno; + DIE(("close_recurse_dir: Cannot go up dir (..): %s\n", strerror(x))); } DEBUG_RET(); return 0; } -// }}}1 -// char *mk_seperate_dir(char *dir, int overwrite) {{{1 char *mk_seperate_dir(char *dir, int overwrite) { #if !defined(WIN32) && !defined(__CYGWIN__) DIR * sdir = NULL; struct dirent *dirent = NULL; struct stat *filestat = xmalloc(sizeof(struct stat)); #endif char *dir_name = NULL; int x = 0, y = 0; DEBUG_ENT("mk_seperate_dir"); /*#if defined(WIN32) || defined(__CYGWIN__) DIE(("mk_seperate_dir: Win32 applications cannot use this function yet.\n")); #endif*/ dir_name = xmalloc(strlen(dir)+10); do { - if (y == 0) - sprintf(dir_name, "%s", dir); - else - sprintf(dir_name, "%s%09i", dir, y); // enough for 9 digits allocated above - - dir_name = check_filename(dir_name); - DEBUG_MAIN(("mk_seperate_dir: about to try creating %s\n", dir_name)); - if (D_MKDIR(dir_name)) { - if (errno != EEXIST) { // if there is an error, and it doesn't already exist - x = errno; - DIE(("mk_seperate_dir: Cannot create directory %s: %s\n", dir, strerror(x))); - } - } else { - break; - } - y++; + if (y == 0) + sprintf(dir_name, "%s", dir); + else + sprintf(dir_name, "%s%09i", dir, y); // enough for 9 digits allocated above + + dir_name = check_filename(dir_name); + DEBUG_MAIN(("mk_seperate_dir: about to try creating %s\n", dir_name)); + if (D_MKDIR(dir_name)) { + if (errno != EEXIST) { // if there is an error, and it doesn't already exist + x = errno; + DIE(("mk_seperate_dir: Cannot create directory %s: %s\n", dir, strerror(x))); + } + } else { + break; + } + y++; } while (overwrite == 0); if (chdir (dir_name)) { - x = errno; - DIE(("mk_recurse_dir: Cannot change to directory %s: %s\n", dir, strerror(x))); + x = errno; + DIE(("mk_recurse_dir: Cannot change to directory %s: %s\n", dir, strerror(x))); } if (overwrite) { - // we should probably delete all files from this directory + // we should probably delete all files from this directory #if !defined(WIN32) && !defined(__CYGWIN__) - if ((sdir = opendir("./")) == NULL) { - WARN(("mk_seperate_dir: Cannot open dir \"%s\" for deletion of old contents\n", "./")); - } else { - while ((dirent = readdir(sdir)) != NULL) { - if (lstat(dirent->d_name, filestat) != -1) - if (S_ISREG(filestat->st_mode)) { - if (unlink(dirent->d_name)) { - y = errno; - DIE(("mk_seperate_dir: unlink returned error on file %s: %s\n", dirent->d_name, strerror(y))); - } - } - } - } + if ((sdir = opendir("./")) == NULL) { + WARN(("mk_seperate_dir: Cannot open dir \"%s\" for deletion of old contents\n", "./")); + } else { + while ((dirent = readdir(sdir)) != NULL) { + if (lstat(dirent->d_name, filestat) != -1) + if (S_ISREG(filestat->st_mode)) { + if (unlink(dirent->d_name)) { + y = errno; + DIE(("mk_seperate_dir: unlink returned error on file %s: %s\n", dirent->d_name, strerror(y))); + } + } + } + } #endif } // overwrite will never change during this function, it is just there so that // if overwrite is set, we only go through this loop once. // we don't return a filename here cause it isn't necessary. DEBUG_RET(); return NULL; } -// }}}1 -// int close_seperate_dir() {{{1 int close_seperate_dir() { int x; DEBUG_ENT("close_seperate_dir"); if (chdir("..")) { - x = errno; - DIE(("close_seperate_dir: Cannot go up dir (..): %s\n", strerror(x))); + x = errno; + DIE(("close_seperate_dir: Cannot go up dir (..): %s\n", strerror(x))); } DEBUG_RET(); return 0; } -// }}}1 -// int mk_seperate_file(struct file_ll *f) {{{1 int mk_seperate_file(struct file_ll *f) { DEBUG_ENT("mk_seperate_file"); DEBUG_MAIN(("mk_seperate_file: opening next file to save email\n")); if (f->email_count > 999999999) { // bigger than nine 9's - DIE(("mk_seperate_file: The number of emails in this folder has become too high to handle")); + DIE(("mk_seperate_file: The number of emails in this folder has become too high to handle")); } sprintf(f->name, "%09i", f->email_count); if (f->output != NULL) - fclose(f->output); + fclose(f->output); f->output = NULL; f->name = check_filename(f->name); if ((f->output = fopen(f->name, "w")) == NULL) { - DIE(("mk_seperate_file: Cannot open file to save email \"%s\"\n", f->name)); + DIE(("mk_seperate_file: Cannot open file to save email \"%s\"\n", f->name)); } DEBUG_RET(); return 0; } -// }}}1 -// char *my_stristr(char *haystack, char *needle) {{{1 char *my_stristr(char *haystack, char *needle) { // my_stristr varies from strstr in that its searches are case-insensitive char *x=haystack, *y=needle, *z = NULL; DEBUG_ENT("my_stristr"); if (haystack == NULL || needle == NULL) - return NULL; + return NULL; while (*y != '\0' && *x != '\0') { - if (tolower(*y) == tolower(*x)) { - // move y on one - y++; - if (z == NULL) { - z = x; // store first position in haystack where a match is made - } - } else { - y = needle; // reset y to the beginning of the needle - z = NULL; // reset the haystack storage point - } - x++; // advance the search in the haystack + if (tolower(*y) == tolower(*x)) { + // move y on one + y++; + if (z == NULL) { + z = x; // store first position in haystack where a match is made + } + } else { + y = needle; // reset y to the beginning of the needle + z = NULL; // reset the haystack storage point + } + x++; // advance the search in the haystack } DEBUG_RET(); return z; } -// }}}1 -// char *check_filename(char *fname) {{{1 char *check_filename(char *fname) { char *t = fname; DEBUG_ENT("check_filename"); if (t == NULL) { - DEBUG_RET(); - return fname; + DEBUG_RET(); + return fname; } while ((t = strpbrk(t, "/\\:")) != NULL) { - // while there are characters in the second string that we don't want - *t = '_'; //replace them with an underscore + // while there are characters in the second string that we don't want + *t = '_'; //replace them with an underscore } DEBUG_RET(); return fname; } -// }}}1 -// char *rfc2426_escape(char *str) {{{1 char *rfc2426_escape(char *str) { static char* buf = NULL; char *ret, *a, *b; int x = 0, y, z; DEBUG_ENT("rfc2426_escape"); if (str == NULL) - ret = str; + ret = str; else { - // calculate space required to escape all the following characters - x = strlen(str) +(y=(chr_count(str, ',')*2) + (chr_count(str, '\\')*2) + (chr_count(str, ';')*2) + (chr_count(str, '\n')*2)); - z = chr_count(str, '\r'); - if (y == 0 && z == 0) - // there isn't any extra space required - ret = str; - else { - buf = (char*) realloc(buf, x+1); - a = str; - b = buf; - while (*a != '\0') { - switch(*a) { - case ',' : - case '\\': - case ';' : - case '\n': - *(b++)='\\'; - *b=*a; - break; - case '\r': - break; - default: - *b=*a; - } - b++; - a++; - } - *b = '\0'; - ret = buf; - } + // calculate space required to escape all the following characters + x = strlen(str) +(y=(chr_count(str, ',')*2) + (chr_count(str, '\\')*2) + (chr_count(str, ';')*2) + (chr_count(str, '\n')*2)); + z = chr_count(str, '\r'); + if (y == 0 && z == 0) + // there isn't any extra space required + ret = str; + else { + buf = (char*) realloc(buf, x+1); + a = str; + b = buf; + while (*a != '\0') { + switch(*a) { + case ',' : + case '\\': + case ';' : + case '\n': + *(b++)='\\'; + *b=*a; + break; + case '\r': + break; + default: + *b=*a; + } + b++; + a++; + } + *b = '\0'; + ret = buf; + } } DEBUG_RET(); return ret; } -// }}}1 -// int chr_count(char *str, char x) {{{1 int chr_count(char *str, char x) { int r = 0; while (*str != '\0') { - if (*str == x) - r++; - str++; + if (*str == x) + r++; + str++; } return r; } -// }}}1 -// char *rfc2425_datetime_format(FILETIME *ft) {{{1 char *rfc2425_datetime_format(FILETIME *ft) { static char * buffer = NULL; struct tm *stm = NULL; DEBUG_ENT("rfc2425_datetime_format"); if (buffer == NULL) - buffer = malloc(30); // should be enough for the date as defined below + buffer = malloc(30); // should be enough for the date as defined below stm = fileTimeToStructTM(ft); //Year[4]-Month[2]-Day[2] Hour[2]:Min[2]:Sec[2] if (strftime(buffer, 30, "%Y-%m-%dT%H:%M:%SZ", stm)==0) { - DEBUG_INFO(("Problem occured formatting date\n")); + DEBUG_INFO(("Problem occured formatting date\n")); } DEBUG_RET(); return buffer; } -// }}}1 -// char *rfc2445_datetime_format(FILETIME *ft) {{{1 char *rfc2445_datetime_format(FILETIME *ft) { static char* buffer = NULL; struct tm *stm = NULL; DEBUG_ENT("rfc2445_datetime_format"); if (buffer == NULL) - buffer = malloc(30); // should be enough + buffer = malloc(30); // should be enough stm = fileTimeToStructTM(ft); if (strftime(buffer, 30, "%Y%m%dT%H%M%SZ", stm)==0) { - DEBUG_INFO(("Problem occured formatting date\n")); + DEBUG_INFO(("Problem occured formatting date\n")); } DEBUG_RET(); return buffer; } -// }}}1 -// char *skip_header_prologue(char *headers) {{{1 // The sole purpose of this function is to bypass the pseudo-header prologue // that Microsoft Outlook inserts at the beginning of the internet email // headers for emails stored in their "Personal Folders" files. char *skip_header_prologue(char *headers) { - const char *bad = "Microsoft Mail Internet Headers"; + const char *bad = "Microsoft Mail Internet Headers"; - if ( strncmp(headers, bad, strlen(bad)) == 0 ) { - // Found the offensive header prologue - char *pc; + if ( strncmp(headers, bad, strlen(bad)) == 0 ) { + // Found the offensive header prologue + char *pc; - pc = strchr(headers, '\n'); - return pc + 1; - } + pc = strchr(headers, '\n'); + return pc + 1; + } - return headers; + return headers; } -// }}}1 // vim:sw=4 ts=4: // vim600: set foldlevel=0 foldmethod=marker: