ofxdump.cpp
Go to the documentation of this file.

    00001 /***************************************************************************
    00002                           ofxdump.cpp
    00003                              -------------------
    00004     copyright            : (C) 2002 by Benoit Grégoire
    00005     email                : benoitg@coeus.ca
    00006 ***************************************************************************/
    00022 /***************************************************************************
    00023  *                                                                         *
    00024  *   This program is free software; you can redistribute it and/or modify  *
    00025  *   it under the terms of the GNU General Public License as published by  *
    00026  *   the Free Software Foundation; either version 2 of the License, or     *
    00027  *   (at your option) any later version.                                   *
    00028  *                                                                         *
    00029  ***************************************************************************/
    00030 #include <iostream>
    00031 #include <iomanip>
    00032 #include <cstdlib>
    00033 #include <cstring>
    00034 #include <string>
    00035 #include "libofx.h"
    00036 #include <stdio.h>              /* for printf() */
    00037 #include <config.h>             /* Include config constants, e.g., VERSION TF */
    00038 #include <errno.h>
    00039
    00040 #include "cmdline.h" /* Gengetopt generated parser */
    00041
    00042 using namespace std;
    00043
    00044
    00045 int ofx_proc_security_cb(struct OfxSecurityData data, void * security_data)
    00046 {
    00047   char dest_string[255];
    00048   cout<<"ofx_proc_security():\n";
    00049   if(data.unique_id_valid==true){
    00050     cout<<"    Unique ID of the security being traded: "<<data.unique_id<<"\n";
    00051   }
    00052   if(data.unique_id_type_valid==true){
    00053     cout<<"    Format of the Unique ID: "<<data.unique_id_type<<"\n";
    00054   }
    00055   if(data.secname_valid==true){
    00056     cout<<"    Name of the security: "<<data.secname<<"\n";
    00057   }
    00058   if(data.ticker_valid==true){
    00059     cout<<"    Ticker symbol: "<<data.ticker<<"\n";
    00060   }
    00061   if(data.unitprice_valid==true){
    00062     cout<<"    Price of each unit of the security: "<<data.unitprice<<"\n";
    00063   }
    00064   if(data.date_unitprice_valid==true){
    00065     strftime(dest_string,sizeof(dest_string),"%c %Z",localtime(&(data.date_unitprice)));
    00066     cout<<"    Date as of which the unitprice is valid: "<<dest_string<<"\n";
    00067   }
    00068   if(data.currency_valid==true){
    00069     cout<<"    Currency of the unitprice: "<<data.currency<<"\n";
    00070   }
    00071   if(data.memo_valid==true){
    00072     cout<<"    Extra transaction information (memo): "<<data.memo<<"\n";
    00073   }
    00074   cout<<"\n";
    00075   return 0;
    00076 }
    00077
    00078 int ofx_proc_transaction_cb(struct OfxTransactionData data, void * transaction_data)
    00079 {
    00080   char dest_string[255];
    00081   cout<<"ofx_proc_transaction():\n";
    00082
    00083   if(data.account_id_valid==true){
    00084     cout<<"    Account ID : "<<data.account_id<<"\n";
    00085   }
    00086
    00087   if(data.transactiontype_valid==true)
    00088     {
    00089       if(data.transactiontype==OFX_CREDIT)
    00090         strncpy(dest_string, "CREDIT: Generic credit", sizeof(dest_string));
    00091       else if (data.transactiontype==OFX_DEBIT)
    00092         strncpy(dest_string, "DEBIT: Generic debit", sizeof(dest_string));
    00093       else if (data.transactiontype==OFX_INT)
    00094         strncpy(dest_string, "INT: Interest earned or paid (Note: Depends on signage of amount)", sizeof(dest_string));
    00095       else if (data.transactiontype==OFX_DIV)
    00096         strncpy(dest_string, "DIV: Dividend", sizeof(dest_string));
    00097       else if (data.transactiontype==OFX_FEE)
    00098         strncpy(dest_string, "FEE: FI fee", sizeof(dest_string));
    00099       else if (data.transactiontype==OFX_SRVCHG)
    00100         strncpy(dest_string, "SRVCHG: Service charge", sizeof(dest_string));
    00101       else if (data.transactiontype==OFX_DEP)
    00102         strncpy(dest_string, "DEP: Deposit", sizeof(dest_string));
    00103       else if (data.transactiontype==OFX_ATM)
    00104         strncpy(dest_string, "ATM: ATM debit or credit (Note: Depends on signage of amount)", sizeof(dest_string));
    00105       else if (data.transactiontype==OFX_POS)
    00106         strncpy(dest_string, "POS: Point of sale debit or credit (Note: Depends on signage of amount)", sizeof(dest_string));
    00107       else if (data.transactiontype==OFX_XFER)
    00108         strncpy(dest_string, "XFER: Transfer", sizeof(dest_string));
    00109       else if (data.transactiontype==OFX_CHECK)
    00110         strncpy(dest_string, "CHECK: Check", sizeof(dest_string));
    00111       else if (data.transactiontype==OFX_PAYMENT)
    00112         strncpy(dest_string, "PAYMENT: Electronic payment", sizeof(dest_string));
    00113       else if (data.transactiontype==OFX_CASH)
    00114         strncpy(dest_string, "CASH: Cash withdrawal", sizeof(dest_string));
    00115       else if (data.transactiontype==OFX_DIRECTDEP)
    00116         strncpy(dest_string, "DIRECTDEP: Direct deposit", sizeof(dest_string));
    00117       else if (data.transactiontype==OFX_DIRECTDEBIT)
    00118         strncpy(dest_string, "DIRECTDEBIT: Merchant initiated debit", sizeof(dest_string));
    00119       else if (data.transactiontype==OFX_REPEATPMT)
    00120         strncpy(dest_string, "REPEATPMT: Repeating payment/standing order", sizeof(dest_string));
    00121       else if (data.transactiontype==OFX_OTHER)
    00122         strncpy(dest_string, "OTHER: Other", sizeof(dest_string));
    00123       else
    00124         strncpy(dest_string, "Unknown transaction type", sizeof(dest_string));
    00125       cout<<"    Transaction type: "<<dest_string<<"\n";
    00126     }
    00127
    00128
    00129   if(data.date_initiated_valid==true){
    00130     strftime(dest_string,sizeof(dest_string),"%c %Z",localtime(&(data.date_initiated)));
    00131     cout<<"    Date initiated: "<<dest_string<<"\n";
    00132   }
    00133   if(data.date_posted_valid==true){
    00134     strftime(dest_string,sizeof(dest_string),"%c %Z",localtime(&(data.date_posted)));
    00135     cout<<"    Date posted: "<<dest_string<<"\n";
    00136   }
    00137   if(data.date_funds_available_valid==true){
    00138     strftime(dest_string,sizeof(dest_string),"%c %Z",localtime(&(data.date_funds_available)));
    00139     cout<<"    Date funds are available: "<<dest_string<<"\n";
    00140   }
    00141   if(data.amount_valid==true){
    00142     cout<<"    Total money amount: "<<setiosflags(ios::fixed)<<setiosflags(ios::showpoint)<<setprecision(2)<<data.amount<<"\n";
    00143   }
    00144   if(data.units_valid==true){
    00145     cout<<"    # of units: "<<setiosflags(ios::fixed)<<setiosflags(ios::showpoint)<<setprecision(2)<<data.units<<"\n";
    00146   }
    00147   if(data.oldunits_valid==true){
    00148     cout<<"    # of units before split: "<<setiosflags(ios::fixed)<<setiosflags(ios::showpoint)<<setprecision(2)<<data.oldunits<<"\n";
    00149   }
    00150   if(data.newunits_valid==true){
    00151     cout<<"    # of units after split: "<<setiosflags(ios::fixed)<<setiosflags(ios::showpoint)<<setprecision(2)<<data.newunits<<"\n";
    00152   }
    00153   if(data.unitprice_valid==true){
    00154     cout<<"    Unit price: "<<setiosflags(ios::fixed)<<setiosflags(ios::showpoint)<<setprecision(2)<<data.unitprice<<"\n";
    00155   }
    00156   if(data.fees_valid==true){
    00157     cout<<"    Fees: "<<setiosflags(ios::fixed)<<setiosflags(ios::showpoint)<<setprecision(2)<<data.fees<<"\n";
    00158   }
    00159   if(data.commission_valid==true){
    00160     cout<<"    Commission: "<<setiosflags(ios::fixed)<<setiosflags(ios::showpoint)<<setprecision(2)<<data.commission<<"\n";
    00161   }
    00162   if(data.fi_id_valid==true){
    00163     cout<<"    Financial institution's ID for this transaction: "<<data.fi_id<<"\n";
    00164   }
    00165   if(data.fi_id_corrected_valid==true){
    00166     cout<<"    Financial institution ID replaced or corrected by this transaction: "<<data.fi_id_corrected<<"\n";
    00167   }
    00168   if(data.fi_id_correction_action_valid==true){
    00169     cout<<"    Action to take on the corrected transaction: ";
    00170     if (data.fi_id_correction_action==DELETE)
    00171       cout<<"DELETE\n";
    00172     else if (data.fi_id_correction_action==REPLACE)
    00173       cout<<"REPLACE\n";
    00174     else
    00175       cout<<"ofx_proc_transaction(): This should not happen!\n";
    00176     }
    00177   if(data.invtransactiontype_valid==true){
    00178     cout<<"    Investment transaction type: ";
    00179     if (data.invtransactiontype==OFX_BUYDEBT)
    00180       strncpy(dest_string, "BUYDEBT (Buy debt security)", sizeof(dest_string));
    00181     else if (data.invtransactiontype==OFX_BUYMF)
    00182       strncpy(dest_string, "BUYMF (Buy mutual fund)", sizeof(dest_string));
    00183     else if (data.invtransactiontype==OFX_BUYOPT)
    00184       strncpy(dest_string, "BUYOPT (Buy option)", sizeof(dest_string));
    00185     else if (data.invtransactiontype==OFX_BUYOTHER)
    00186       strncpy(dest_string, "BUYOTHER (Buy other security type)", sizeof(dest_string));
    00187     else if (data.invtransactiontype==OFX_BUYSTOCK)
    00188       strncpy(dest_string, "BUYSTOCK (Buy stock))", sizeof(dest_string));
    00189     else if (data.invtransactiontype==OFX_CLOSUREOPT)
    00190       strncpy(dest_string, "CLOSUREOPT (Close a position for an option)", sizeof(dest_string));
    00191     else if (data.invtransactiontype==OFX_INCOME)
    00192       strncpy(dest_string, "INCOME (Investment income is realized as cash into the investment account)", sizeof(dest_string));
    00193     else if (data.invtransactiontype==OFX_INVEXPENSE)
    00194       strncpy(dest_string, "INVEXPENSE (Misc investment expense that is associated with a specific security)", sizeof(dest_string));
    00195     else if (data.invtransactiontype==OFX_JRNLFUND)
    00196       strncpy(dest_string, "JRNLFUND (Journaling cash holdings between subaccounts within the same investment account)", sizeof(dest_string));
    00197     else if (data.invtransactiontype==OFX_MARGININTEREST)
    00198       strncpy(dest_string, "MARGININTEREST (Margin interest expense)", sizeof(dest_string));
    00199     else if (data.invtransactiontype==OFX_REINVEST)
    00200       strncpy(dest_string, "REINVEST (Reinvestment of income)", sizeof(dest_string));
    00201     else if (data.invtransactiontype==OFX_RETOFCAP)
    00202       strncpy(dest_string, "RETOFCAP (Return of capital)", sizeof(dest_string));
    00203     else if (data.invtransactiontype==OFX_SELLDEBT)
    00204       strncpy(dest_string, "SELLDEBT (Sell debt security.  Used when debt is sold, called, or reached maturity)", sizeof(dest_string));
    00205     else if (data.invtransactiontype==OFX_SELLMF)
    00206       strncpy(dest_string, "SELLMF (Sell mutual fund)", sizeof(dest_string));
    00207     else if (data.invtransactiontype==OFX_SELLOPT)
    00208       strncpy(dest_string, "SELLOPT (Sell option)", sizeof(dest_string));
    00209     else if (data.invtransactiontype==OFX_SELLOTHER)
    00210       strncpy(dest_string, "SELLOTHER (Sell other type of security)", sizeof(dest_string));
    00211     else if (data.invtransactiontype==OFX_SELLSTOCK)
    00212       strncpy(dest_string, "SELLSTOCK (Sell stock)", sizeof(dest_string));
    00213     else if (data.invtransactiontype==OFX_SPLIT)
    00214       strncpy(dest_string, "SPLIT (Stock or mutial fund split)", sizeof(dest_string));
    00215     else if (data.invtransactiontype==OFX_TRANSFER)
    00216       strncpy(dest_string, "TRANSFER (Transfer holdings in and out of the investment account)", sizeof(dest_string));
    00217     else
    00218       strncpy(dest_string, "ERROR, this investment transaction type is unknown.  This is a bug in ofxdump", sizeof(dest_string));
    00219
    00220     cout<<dest_string<<"\n";
    00221   }
    00222   if(data.unique_id_valid==true){
    00223     cout<<"    Unique ID of the security being traded: "<<data.unique_id<<"\n";
    00224   }
    00225   if(data.unique_id_type_valid==true){
    00226     cout<<"    Format of the Unique ID: "<<data.unique_id_type<<"\n";
    00227   }
    00228   if(data.security_data_valid==true){
    00229     ofx_proc_security_cb(*(data.security_data_ptr), NULL );
    00230   }
    00231
    00232   if(data.server_transaction_id_valid==true){
    00233     cout<<"    Server's transaction ID (confirmation number): "<<data.server_transaction_id<<"\n";
    00234   }
    00235   if(data.check_number_valid==true){
    00236     cout<<"    Check number: "<<data.check_number<<"\n";
    00237   }
    00238   if(data.reference_number_valid==true){
    00239     cout<<"    Reference number: "<<data.reference_number<<"\n";
    00240   }
    00241   if(data.standard_industrial_code_valid==true){
    00242     cout<<"    Standard Industrial Code: "<<data.standard_industrial_code<<"\n";
    00243   }
    00244   if(data.payee_id_valid==true){
    00245     cout<<"    Payee_id: "<<data.payee_id<<"\n";
    00246   }
    00247   if(data.name_valid==true){
    00248     cout<<"    Name of payee or transaction description: "<<data.name<<"\n";
    00249   }
    00250   if(data.memo_valid==true){
    00251     cout<<"    Extra transaction information (memo): "<<data.memo<<"\n";
    00252   }
    00253   cout<<"\n";
    00254   return 0;
    00255 }//end ofx_proc_transaction()
    00256
    00257 int ofx_proc_statement_cb(struct OfxStatementData data, void * statement_data)
    00258 {
    00259   char dest_string[255];
    00260   cout<<"ofx_proc_statement():\n";
    00261   if(data.currency_valid==true){
    00262     cout<<"    Currency: "<<data.currency<<"\n";
    00263   }
    00264   if(data.account_id_valid==true){
    00265     cout<<"    Account ID: "<<data.account_id<<"\n";
    00266   }
    00267   if(data.date_start_valid==true){
    00268     strftime(dest_string,sizeof(dest_string),"%c %Z",localtime(&(data.date_start)));
    00269     cout<<"    Start date of this statement: "<<dest_string<<"\n";
    00270   }
    00271   if(data.date_end_valid==true){
    00272     strftime(dest_string,sizeof(dest_string),"%c %Z",localtime(&(data.date_end)));
    00273     cout<<"    End date of this statement: "<<dest_string<<"\n";
    00274   }
    00275   if(data.ledger_balance_valid==true){
    00276     cout<<"    Ledger balance: "<<setiosflags(ios::fixed)<<setiosflags(ios::showpoint)<<setprecision(2)<<data.ledger_balance<<"\n";
    00277   }
    00278   if(data.ledger_balance_date_valid==true){
    00279     strftime(dest_string,sizeof(dest_string),"%c %Z",localtime(&(data.ledger_balance_date)));
    00280     cout<<"    Ledger balance date: "<<dest_string<<"\n";
    00281   }
    00282   if(data.available_balance_valid==true){
    00283     cout<<"    Available balance: "<<setiosflags(ios::fixed)<<setiosflags(ios::showpoint)<<setprecision(2)<<data.available_balance<<"\n";
    00284   }
    00285   if(data.available_balance_date_valid==true){
    00286     strftime(dest_string,sizeof(dest_string),"%c %Z",localtime(&(data.available_balance_date)));
    00287     cout<<"    Ledger balance date: "<<dest_string<<"\n";
    00288   }
    00289   if(data.marketing_info_valid==true){
    00290     cout<<"    Marketing information: "<<data.marketing_info<<"\n";
    00291   }
    00292   cout<<"\n";
    00293   return 0;
    00294 }//end ofx_proc_statement()
    00295
    00296 int ofx_proc_account_cb(struct OfxAccountData data, void * account_data)
    00297 {
    00298   cout<<"ofx_proc_account():\n";
    00299   if(data.account_id_valid==true){
    00300     cout<<"    Account ID: "<<data.account_id<<"\n";
    00301     cout<<"    Account name: "<<data.account_name<<"\n";
    00302   }
    00303   if(data.account_type_valid==true){
    00304     cout<<"    Account type: ";
    00305     switch(data.account_type){
    00306     case OfxAccountData::OFX_CHECKING : cout<<"CHECKING\n";
    00307       break;
    00308     case OfxAccountData::OFX_SAVINGS : cout<<"SAVINGS\n";
    00309       break;
    00310     case OfxAccountData::OFX_MONEYMRKT : cout<<"MONEYMRKT\n";
    00311       break;
    00312     case OfxAccountData::OFX_CREDITLINE : cout<<"CREDITLINE\n";
    00313       break;
    00314     case OfxAccountData::OFX_CMA : cout<<"CMA\n";
    00315       break;
    00316     case OfxAccountData::OFX_CREDITCARD : cout<<"CREDITCARD\n";
    00317       break;
    00318     case OfxAccountData::OFX_INVESTMENT : cout<<"INVESTMENT\n";
    00319       break;
    00320     default: cout<<"ofx_proc_account() WRITEME: This is an unknown account type!";
    00321     }
    00322   }
    00323   if(data.currency_valid==true){
    00324     cout<<"    Currency: "<<data.currency<<"\n";
    00325   }
    00326
    00327   if (data.bank_id_valid)
    00328     cout<<"    Bank ID: "<<data.bank_id << endl;;
    00329
    00330   if (data.branch_id_valid)
    00331     cout<<"    Branch ID: "<<data.branch_id << endl;
    00332
    00333   if (data.account_number_valid)
    00334     cout<<"    Account #: "<<data.account_number << endl;
    00335
    00336   cout<<"\n";
    00337   return 0;
    00338 }//end ofx_proc_account()
    00339
    00340
    00341
    00342 int ofx_proc_status_cb(struct OfxStatusData data, void * status_data)
    00343 {
    00344   cout<<"ofx_proc_status():\n";
    00345   if(data.ofx_element_name_valid==true){
    00346     cout<<"    Ofx entity this status is relevent to: "<< data.ofx_element_name<<" \n";
    00347   }
    00348   if(data.severity_valid==true){
    00349     cout<<"    Severity: ";
    00350     switch(data.severity){
    00351     case OfxStatusData::INFO : cout<<"INFO\n";
    00352       break;
    00353     case OfxStatusData::WARN : cout<<"WARN\n";
    00354       break;
    00355     case OfxStatusData::ERROR : cout<<"ERROR\n";
    00356       break;
    00357     default: cout<<"WRITEME: Unknown status severity!\n";
    00358     }
    00359   }
    00360   if(data.code_valid==true){
    00361     cout<<"    Code: "<<data.code<<", name: "<<data.name<<"\n    Description: "<<data.description<<"\n";
    00362   }
    00363   if(data.server_message_valid==true){
    00364     cout<<"    Server Message: "<<data.server_message<<"\n";
    00365   }
    00366   cout<<"\n";
    00367   return 0;
    00368 }
    00369
    00370
    00371 int main (int argc, char *argv[])
    00372 {
    00373   gengetopt_args_info args_info;
    00374
    00375   /* let's call our cmdline parser */
    00376   if (cmdline_parser (argc, argv, &args_info) != 0)
    00377     exit(1) ;
    00378
    00379   //  if (args_info.msg_parser_given)
    00380   //    cout << "The msg_parser option was given!" << endl;
    00381
    00382   //  cout << "The flag is " << ( args_info.msg_parser_flag ? "on" : "off" ) <<
    00383   //    "." << endl ;
    00384   args_info.msg_parser_flag ? ofx_PARSER_msg = true : ofx_PARSER_msg = false;
    00385   args_info.msg_debug_flag ? ofx_DEBUG_msg = true : ofx_DEBUG_msg = false;
    00386   args_info.msg_warning_flag ? ofx_WARNING_msg = true : ofx_WARNING_msg = false;
    00387   args_info.msg_error_flag ? ofx_ERROR_msg = true : ofx_ERROR_msg = false;
    00388   args_info.msg_info_flag ? ofx_INFO_msg = true : ofx_INFO_msg = false;
    00389   args_info.msg_status_flag ? ofx_STATUS_msg = true : ofx_STATUS_msg;
    00390
    00391   bool skiphelp = false;
    00392
    00393   if(args_info.list_import_formats_given)
    00394     {
    00395       skiphelp = true;
    00396       cout <<"The supported file formats for the 'input-file-format' argument are:"<<endl;
    00397       for(int i=0; LibofxImportFormatList[i].format!=LAST; i++)
    00398         {
    00399           cout <<"     "<<LibofxImportFormatList[i].description<<endl;
    00400         }
    00401     }
    00402
    00403   LibofxContextPtr libofx_context = libofx_get_new_context();
    00404
    00405   //char **inputs ; /* unamed options */
    00406   //unsigned inputs_num ; /* unamed options number */
    00407   if (args_info.inputs_num  > 0)
    00408     {
    00409       const char* filename = args_info.inputs[0];
    00410
    00411
    00412       ofx_set_statement_cb(libofx_context, ofx_proc_statement_cb, 0);
    00413       ofx_set_account_cb(libofx_context, ofx_proc_account_cb, 0);
    00414       ofx_set_transaction_cb(libofx_context, ofx_proc_transaction_cb, 0);
    00415       ofx_set_security_cb(libofx_context, ofx_proc_security_cb, 0);
    00416       ofx_set_status_cb(libofx_context, ofx_proc_status_cb, 0);
    00417
    00418       enum LibofxFileFormat file_format = libofx_get_file_format_from_str(LibofxImportFormatList, args_info.import_format_arg);
    00420       if(args_info.inputs_num  > 1)
    00421         {
    00422           cout << "Sorry, currently, only the first file is processed as the library can't deal with more right now.  The following files were ignored:"<<endl;
    00423           for ( unsigned i = 1 ; i < args_info.inputs_num ; ++i )
    00424             {
    00425               cout << "file: " << args_info.inputs[i] << endl ;
    00426               }
    00427         }
    00428       libofx_proc_file(libofx_context, args_info.inputs[0], file_format);
    00429     }
    00430   else
    00431     {
    00432       if ( !skiphelp )
    00433         cmdline_parser_print_help();
    00434     }
    00435   return 0;
    00436 }