00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "define.h"
00010
00011 struct file_ll {
00012 char *dname;
00013 int32_t stored_count;
00014 int32_t item_count;
00015 int32_t skip_count;
00016 int32_t type;
00017 };
00018
00019 struct options {
00020 int long_format;
00021 char *date_format;
00022 };
00023
00024 void canonicalize_filename(char *fname);
00025 void debug_print(char *fmt, ...);
00026 void usage(char *prog_name);
00027 void version();
00028
00029
00030 pst_file pstfile;
00031
00032
00033 void create_enter_dir(struct file_ll* f, pst_item *item)
00034 {
00035 pst_convert_utf8(item, &item->file_as);
00036 f->item_count = 0;
00037 f->skip_count = 0;
00038 f->type = item->type;
00039 f->stored_count = (item->folder) ? item->folder->item_count : 0;
00040 f->dname = strdup(item->file_as.str);
00041 }
00042
00043
00044 void close_enter_dir(struct file_ll *f)
00045 {
00046 free(f->dname);
00047 }
00048
00049 void process(pst_item *outeritem, pst_desc_tree *d_ptr, struct options o)
00050 {
00051 struct file_ll ff;
00052 pst_item *item = NULL;
00053 char *result = NULL;
00054 size_t resultlen = 0;
00055 size_t dateresultlen;
00056
00057 DEBUG_ENT("process");
00058 memset(&ff, 0, sizeof(ff));
00059 create_enter_dir(&ff, outeritem);
00060
00061 while (d_ptr) {
00062 if (!d_ptr->desc) {
00063 DEBUG_WARN(("ERROR item's desc record is NULL\n"));
00064 ff.skip_count++;
00065 }
00066 else {
00067 DEBUG_INFO(("Desc Email ID %"PRIx64" [d_ptr->d_id = %"PRIx64"]\n", d_ptr->desc->i_id, d_ptr->d_id));
00068
00069 item = pst_parse_item(&pstfile, d_ptr, NULL);
00070 DEBUG_INFO(("About to process item @ %p.\n", item));
00071 if (item) {
00072 if (item->message_store) {
00073
00074 DIE(("A second message_store has been found. Sorry, this must be an error.\n"));
00075 }
00076
00077 if (item->folder && d_ptr->child) {
00078
00079 pst_convert_utf8(item, &item->file_as);
00080 printf("Folder \"%s\"\n", item->file_as.str);
00081 process(item, d_ptr->child, o);
00082
00083 } else if (item->contact && (item->type == PST_TYPE_CONTACT)) {
00084 if (!ff.type) ff.type = item->type;
00085
00086 if (ff.type != PST_TYPE_CONTACT) {
00087 DEBUG_INFO(("I have a contact, but the folder isn't a contacts folder. Processing anyway\n"));
00088 }
00089 printf("Contact");
00090 if (item->contact->fullname.str)
00091 printf("\t%s", pst_rfc2426_escape(item->contact->fullname.str, &result, &resultlen));
00092 printf("\n");
00093
00094 } else if (item->email && ((item->type == PST_TYPE_NOTE) || (item->type == PST_TYPE_SCHEDULE) || (item->type == PST_TYPE_REPORT))) {
00095 if (!ff.type) ff.type = item->type;
00096
00097 if ((ff.type != PST_TYPE_NOTE) && (ff.type != PST_TYPE_SCHEDULE) && (ff.type != PST_TYPE_REPORT)) {
00098 DEBUG_INFO(("I have an email, but the folder isn't an email folder. Processing anyway\n"));
00099 }
00100 printf("Email");
00101 if (o.long_format == 1) {
00102 if (item->email->arrival_date) {
00103 char time_buffer[MAXDATEFMTLEN];
00104 dateresultlen = pst_fileTimeToString(item->email->arrival_date, o.date_format, time_buffer);
00105 if (dateresultlen < 1)
00106 DIE(("Date format error in -f option.\n"));
00107 printf("\tDate: %s", time_buffer);
00108 }
00109 else
00110 printf("\t");
00111 }
00112 if (item->email->outlook_sender_name.str)
00113 printf("\tFrom: %s", item->email->outlook_sender_name.str);
00114 else
00115 printf("\t");
00116 if (o.long_format == 1) {
00117 if (item->email->outlook_recipient_name.str)
00118 printf("\tTo: %s", item->email->outlook_recipient_name.str);
00119 else
00120 printf("\t");
00121 if (item->email->cc_address.str)
00122 printf("\tCC: %s", item->email->cc_address.str);
00123 else
00124 printf("\t");
00125 if (item->email->bcc_address.str)
00126 printf("\tBCC: %s", item->email->bcc_address.str);
00127 else
00128 printf("\t");
00129 }
00130 if (item->subject.str)
00131 printf("\tSubject: %s", item->subject.str);
00132 else
00133 printf("\t");
00134 printf("\n");
00135
00136 } else if (item->journal && (item->type == PST_TYPE_JOURNAL)) {
00137 if (!ff.type) ff.type = item->type;
00138
00139 if (ff.type != PST_TYPE_JOURNAL) {
00140 DEBUG_INFO(("I have a journal entry, but folder isn't specified as a journal type. Processing...\n"));
00141 }
00142 if (item->subject.str)
00143 printf("Journal\t%s\n", pst_rfc2426_escape(item->subject.str, &result, &resultlen));
00144
00145 } else if (item->appointment && (item->type == PST_TYPE_APPOINTMENT)) {
00146 char time_buffer[30];
00147 if (!ff.type) ff.type = item->type;
00148
00149 DEBUG_INFO(("Processing Appointment Entry\n"));
00150 if (ff.type != PST_TYPE_APPOINTMENT) {
00151 DEBUG_INFO(("I have an appointment, but folder isn't specified as an appointment type. Processing...\n"));
00152 }
00153 printf("Appointment");
00154 if (item->subject.str)
00155 printf("\tSUMMARY: %s", pst_rfc2426_escape(item->subject.str, &result, &resultlen));
00156 if (item->appointment->start)
00157 printf("\tSTART: %s", pst_rfc2445_datetime_format(item->appointment->start, sizeof(time_buffer), time_buffer));
00158 if (item->appointment->end)
00159 printf("\tEND: %s", pst_rfc2445_datetime_format(item->appointment->end, sizeof(time_buffer), time_buffer));
00160 printf("\tALL DAY: %s", (item->appointment->all_day==1 ? "Yes" : "No"));
00161 printf("\n");
00162
00163 } else {
00164 ff.skip_count++;
00165 DEBUG_INFO(("Unknown item type. %i. Ascii1=\"%s\"\n",
00166 item->type, item->ascii_type));
00167 }
00168 pst_freeItem(item);
00169 } else {
00170 ff.skip_count++;
00171 DEBUG_INFO(("A NULL item was seen\n"));
00172 }
00173 }
00174 d_ptr = d_ptr->next;
00175 }
00176 close_enter_dir(&ff);
00177 if (result) free(result);
00178 DEBUG_RET();
00179 }
00180
00181
00182 void usage(char *prog_name) {
00183 DEBUG_ENT("usage");
00184 version();
00185 printf("Usage: %s [OPTIONS] {PST FILENAME}\n", prog_name);
00186 printf("OPTIONS:\n");
00187 printf("\t-d <filename> \t- Debug to file. This is a binary log. Use readlog to print it\n");
00188 printf("\t-l\t- Print the date, CC and BCC fields of emails too (by default only the From and Subject)\n");
00189 printf("\t-f <date_format> \t- Select the date format in ctime format (by default \"%%F %%T\")\n");
00190 printf("\t-h\t- Help. This screen\n");
00191 printf("\t-V\t- Version. Display program version\n");
00192 DEBUG_RET();
00193 }
00194
00195
00196 void version() {
00197 DEBUG_ENT("version");
00198 printf("lspst / LibPST v%s\n", VERSION);
00199 #if BYTE_ORDER == BIG_ENDIAN
00200 printf("Big Endian implementation being used.\n");
00201 #elif BYTE_ORDER == LITTLE_ENDIAN
00202 printf("Little Endian implementation being used.\n");
00203 #else
00204 # error "Byte order not supported by this library"
00205 #endif
00206 DEBUG_RET();
00207 }
00208
00209
00210 int main(int argc, char* const* argv) {
00211 pst_item *item = NULL;
00212 pst_desc_tree *d_ptr;
00213 char *temp = NULL;
00214 int c;
00215 char *d_log = NULL;
00216 struct options o;
00217 o.long_format = 0;
00218 char *defaultfmtdate = "%F %T";
00219 o.date_format = defaultfmtdate;
00220
00221 while ((c = getopt(argc, argv, "d:f:lhV"))!= -1) {
00222 switch (c) {
00223 case 'd':
00224 d_log = optarg;
00225 break;
00226 case 'f':
00227 o.date_format = optarg;
00228 break;
00229 case 'l':
00230 o.long_format = 1;
00231 break;
00232 case 'h':
00233 usage(argv[0]);
00234 exit(0);
00235 break;
00236 case 'V':
00237 version();
00238 exit(0);
00239 break;
00240 default:
00241 usage(argv[0]);
00242 exit(1);
00243 break;
00244 }
00245 }
00246
00247 #ifdef DEBUG_ALL
00248
00249 if (!d_log) d_log = "lspst.log";
00250 #endif // defined DEBUG_ALL
00251 DEBUG_INIT(d_log, NULL);
00252 DEBUG_ENT("main");
00253
00254 if (argc <= optind) {
00255 usage(argv[0]);
00256 exit(2);
00257 }
00258
00259
00260 if (pst_open(&pstfile, argv[optind], NULL)) DIE(("Error opening File\n"));
00261
00262
00263 if (pst_load_index(&pstfile)) DIE(("Index Error\n"));
00264
00265 pst_load_extended_attributes(&pstfile);
00266
00267 d_ptr = pstfile.d_head;
00268 item = pst_parse_item(&pstfile, d_ptr, NULL);
00269 if (!item || !item->message_store) {
00270 DEBUG_RET();
00271 DIE(("Could not get root record\n"));
00272 }
00273
00274
00275 if (!item->file_as.str) {
00276 if (!(temp = strrchr(argv[1], '/')))
00277 if (!(temp = strrchr(argv[1], '\\')))
00278 temp = argv[1];
00279 else
00280 temp++;
00281 else
00282 temp++;
00283 item->file_as.str = strdup(temp);
00284 item->file_as.is_utf8 = 1;
00285 }
00286
00287 d_ptr = pst_getTopOfFolders(&pstfile, item);
00288 if (!d_ptr) DIE(("Top of folders record not found. Cannot continue\n"));
00289
00290 process(item, d_ptr->child, o);
00291 pst_freeItem(item);
00292 pst_close(&pstfile);
00293
00294 DEBUG_RET();
00295 return 0;
00296 }
00297
00298
00299
00300
00301 void canonicalize_filename(char *fname) {
00302 DEBUG_ENT("canonicalize_filename");
00303 if (fname == NULL) {
00304 DEBUG_RET();
00305 return;
00306 }
00307 while ((fname = strpbrk(fname, "/\\:")))
00308 *fname = '_';
00309 DEBUG_RET();
00310 }
00311
00312