lspst.c

Go to the documentation of this file.
00001 /***
00002  * lspst.c
00003  * Part of the LibPST project
00004  * Author: Joe Nahmias <joe@nahmias.net>
00005  * Based on readpst.c by David Smith <dave.s@earthcorp.com>
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 // global settings
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                     // there should only be one message_store, and we have already done it
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                     // if this is a folder, we want to recurse into it
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                     // Process Contact item
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                     // Process Email item
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                     // Process Journal item
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                     // Process Calendar Appointment item
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; //temporary char pointer
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         // force a log file
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     // Open PST file
00260     if (pst_open(&pstfile, argv[optind], NULL)) DIE(("Error opening File\n"));
00261 
00262     // Load PST index
00263     if (pst_load_index(&pstfile)) DIE(("Index Error\n"));
00264 
00265     pst_load_extended_attributes(&pstfile);
00266 
00267     d_ptr = pstfile.d_head; // first record is main record
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     // default the file_as to the same as the main filename if it doesn't exist
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++; // get past the "\\"
00281         else
00282             temp++; // get past the "/"
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);    // do the childred of TOPF
00291     pst_freeItem(item);
00292     pst_close(&pstfile);
00293 
00294     DEBUG_RET();
00295     return 0;
00296 }
00297 
00298 
00299 // This function will make sure that a filename is in canonical form.  That
00300 // is, it will replace any slashes, backslashes, or colons with underscores.
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 

Generated on 12 Jan 2020 for 'LibPst' by  doxygen 1.6.1