LibOFX
|
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 { 00374 extern int ofx_PARSER_msg; 00375 extern int ofx_DEBUG_msg; 00376 extern int ofx_WARNING_msg; 00377 extern int ofx_ERROR_msg; 00378 extern int ofx_INFO_msg; 00379 extern int ofx_STATUS_msg; 00380 00381 gengetopt_args_info args_info; 00382 00383 /* let's call our cmdline parser */ 00384 if (cmdline_parser (argc, argv, &args_info) != 0) 00385 exit(1) ; 00386 00387 // if (args_info.msg_parser_given) 00388 // cout << "The msg_parser option was given!" << endl; 00389 00390 // cout << "The flag is " << ( args_info.msg_parser_flag ? "on" : "off" ) << 00391 // "." << endl ; 00392 args_info.msg_parser_flag ? ofx_PARSER_msg = true : ofx_PARSER_msg = false; 00393 args_info.msg_debug_flag ? ofx_DEBUG_msg = true : ofx_DEBUG_msg = false; 00394 args_info.msg_warning_flag ? ofx_WARNING_msg = true : ofx_WARNING_msg = false; 00395 args_info.msg_error_flag ? ofx_ERROR_msg = true : ofx_ERROR_msg = false; 00396 args_info.msg_info_flag ? ofx_INFO_msg = true : ofx_INFO_msg = false; 00397 args_info.msg_status_flag ? ofx_STATUS_msg = true : ofx_STATUS_msg; 00398 00399 bool skiphelp = false; 00400 00401 if(args_info.list_import_formats_given) 00402 { 00403 skiphelp = true; 00404 cout <<"The supported file formats for the 'input-file-format' argument are:"<<endl; 00405 for(int i=0; LibofxImportFormatList[i].format!=LAST; i++) 00406 { 00407 cout <<" "<<LibofxImportFormatList[i].description<<endl; 00408 } 00409 } 00410 00411 LibofxContextPtr libofx_context = libofx_get_new_context(); 00412 00413 //char **inputs ; /* unamed options */ 00414 //unsigned inputs_num ; /* unamed options number */ 00415 if (args_info.inputs_num > 0) 00416 { 00417 const char* filename = args_info.inputs[0]; 00418 00419 00420 ofx_set_statement_cb(libofx_context, ofx_proc_statement_cb, 0); 00421 ofx_set_account_cb(libofx_context, ofx_proc_account_cb, 0); 00422 ofx_set_transaction_cb(libofx_context, ofx_proc_transaction_cb, 0); 00423 ofx_set_security_cb(libofx_context, ofx_proc_security_cb, 0); 00424 ofx_set_status_cb(libofx_context, ofx_proc_status_cb, 0); 00425 00426 enum LibofxFileFormat file_format = libofx_get_file_format_from_str(LibofxImportFormatList, args_info.import_format_arg); 00428 if(args_info.inputs_num > 1) 00429 { 00430 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; 00431 for ( unsigned i = 1 ; i < args_info.inputs_num ; ++i ) 00432 { 00433 cout << "file: " << args_info.inputs[i] << endl ; 00434 } 00435 } 00436 libofx_proc_file(libofx_context, args_info.inputs[0], file_format); 00437 } 00438 else 00439 { 00440 if ( !skiphelp ) 00441 cmdline_parser_print_help(); 00442 } 00443 return 0; 00444 }