LibOFX
|
00001 /*************************************************************************** 00002 ofx_connect.cpp 00003 ------------------- 00004 copyright : (C) 2005 by Ace Jones 00005 email : acejones@users.sourceforge.net 00006 ***************************************************************************/ 00023 /*************************************************************************** 00024 * * 00025 * This program is free software; you can redistribute it and/or modify * 00026 * it under the terms of the GNU General Public License as published by * 00027 * the Free Software Foundation; either version 2 of the License, or * 00028 * (at your option) any later version. * 00029 * * 00030 ***************************************************************************/ 00031 #include <iostream> 00032 #include <fstream> 00033 #include <string> 00034 #include "libofx.h" 00035 #include <config.h> /* Include config constants, e.g., VERSION TF */ 00036 #include <stdio.h> 00037 #include <stdlib.h> 00038 #include <unistd.h> 00039 #include <cstring> 00040 #include <cstdlib> 00041 #include <string.h> 00042 #ifdef HAVE_LIBCURL 00043 #include <curl/curl.h> 00044 #endif 00045 00046 #include "cmdline.h" /* Gengetopt generated parser */ 00047 00048 #include "nodeparser.h" 00049 #include "ofxpartner.h" 00050 00051 using namespace std; 00052 00053 #ifdef HAVE_LIBCURL 00054 bool post(const char* request, const char* url, const char* filename) 00055 { 00056 CURL *curl = curl_easy_init(); 00057 if(! curl) 00058 return false; 00059 00060 unlink("tmpout"); 00061 FILE* file = fopen(filename,"wb"); 00062 if (! file ) 00063 { 00064 curl_easy_cleanup(curl); 00065 return false; 00066 } 00067 00068 curl_easy_setopt(curl, CURLOPT_URL, url); 00069 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, request); 00070 00071 struct curl_slist *headerlist=NULL; 00072 headerlist=curl_slist_append(headerlist, "Content-type: application/x-ofx"); 00073 headerlist=curl_slist_append(headerlist, "Accept: */*, application/x-ofx"); 00074 00075 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist); 00076 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fwrite); 00077 curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)file); 00078 00079 CURLcode res = curl_easy_perform(curl); 00080 00081 curl_easy_cleanup(curl); 00082 curl_slist_free_all (headerlist); 00083 00084 fclose(file); 00085 00086 return true; 00087 } 00088 #else 00089 bool post(const char*, const char*, const char*) 00090 { 00091 cerr << "ERROR: libox must be configured with libcurl to post this request directly" << endl; 00092 return false; 00093 } 00094 #endif 00095 00096 ostream& operator<<(ostream& os,const vector<string>& strvect) 00097 { 00098 for( vector<string>::const_iterator it=strvect.begin(); it!=strvect.end(); ++it) 00099 { 00100 os << (*it) << endl; 00101 } 00102 return os; 00103 } 00104 00105 int main (int argc, char *argv[]) 00106 { 00107 gengetopt_args_info args_info; 00108 00109 if (cmdline_parser (argc, argv, &args_info) != 0) 00110 exit(1) ; 00111 00112 if ( argc == 1 ) 00113 { 00114 cmdline_parser_print_help(); 00115 exit(1); 00116 } 00117 00118 if ( args_info.statement_req_given || args_info.accountinfo_req_given ) 00119 { 00120 if ( (args_info.inputs_num > 0) ) 00121 { 00122 cout << "file " << args_info.inputs[0] << endl; 00123 } 00124 else 00125 { 00126 cerr << "ERROR: You must specify an output file" << endl; 00127 } 00128 } 00129 else if ( args_info.bank_fipid_given || args_info.bank_services_given ) 00130 { 00131 if ( (args_info.inputs_num > 0) ) 00132 { 00133 cout << "bank " << args_info.inputs[0] << endl; 00134 } 00135 else 00136 { 00137 cerr << "ERROR: You must specify an bank" << endl; 00138 } 00139 } 00140 00141 OfxFiLogin fi; 00142 memset(&fi,0,sizeof(OfxFiLogin)); 00143 bool ok = true; 00144 string url; 00145 00146 if ( args_info.statement_req_given || args_info.accountinfo_req_given || args_info.payment_req_given || args_info.paymentinquiry_req_given ) 00147 { 00148 // Get the FI Login information 00149 // 00150 00151 if ( args_info.fipid_given ) 00152 { 00153 cerr << "fipid " << args_info.fipid_arg << endl; 00154 cerr << "contacting partner server..." << endl; 00155 OfxFiServiceInfo svcinfo = OfxPartner::ServiceInfo(args_info.fipid_arg); 00156 cout << "fid " << svcinfo.fid << endl; 00157 strncpy(fi.fid,svcinfo.fid,OFX_FID_LENGTH-1); 00158 cout << "org " << svcinfo.org << endl; 00159 strncpy(fi.org,svcinfo.org,OFX_ORG_LENGTH-1); 00160 cout << "url " << svcinfo.url << endl; 00161 url = svcinfo.url; 00162 } 00163 if ( args_info.fid_given ) 00164 { 00165 cerr << "fid " << args_info.fid_arg << endl; 00166 strncpy(fi.fid,args_info.fid_arg,OFX_FID_LENGTH-1); 00167 } 00168 else if ( ! args_info.fipid_given ) 00169 { 00170 cerr << "ERROR: --fid is required" << endl; 00171 ok = false; 00172 } 00173 00174 if ( args_info.org_given ) 00175 { 00176 cerr << "org " << args_info.org_arg << endl; 00177 strncpy(fi.org,args_info.org_arg,OFX_ORG_LENGTH-1); 00178 } 00179 else if ( ! args_info.fipid_given ) 00180 { 00181 cerr << "ERROR: --org is required" << endl; 00182 ok = false; 00183 } 00184 00185 if ( args_info.user_given ) 00186 { 00187 cerr << "user " << args_info.user_arg << endl; 00188 strncpy(fi.userid,args_info.user_arg,OFX_USERID_LENGTH-1); 00189 } 00190 else 00191 { 00192 cerr << "ERROR: --user is required" << endl; 00193 ok = false; 00194 } 00195 00196 if ( args_info.pass_given ) 00197 { 00198 cerr << "pass " << args_info.pass_arg << endl; 00199 strncpy(fi.userpass,args_info.pass_arg,OFX_USERPASS_LENGTH-1); 00200 } 00201 else 00202 { 00203 cerr << "ERROR: --pass is required" << endl; 00204 ok = false; 00205 } 00206 00207 if ( args_info.url_given ) 00208 url = args_info.url_arg; 00209 } 00210 00211 if ( args_info.statement_req_given ) 00212 { 00213 cerr << "Statement request" << endl; 00214 00215 OfxAccountData account; 00216 memset(&account,0,sizeof(OfxAccountData)); 00217 00218 if ( args_info.bank_given ) 00219 { 00220 cerr << "bank " << args_info.bank_arg << endl; 00221 strncpy(account.bank_id,args_info.bank_arg,OFX_BANKID_LENGTH-1); 00222 } 00223 else 00224 { 00225 if ( args_info.type_given && args_info.type_arg == 1 ) 00226 { 00227 cerr << "ERROR: --bank is required for a bank request" << endl; 00228 ok = false; 00229 } 00230 } 00231 00232 if ( args_info.broker_given ) 00233 { 00234 cerr << "broker " << args_info.broker_arg << endl; 00235 strncpy(account.broker_id,args_info.broker_arg,OFX_BROKERID_LENGTH-1); 00236 } 00237 else 00238 { 00239 if ( args_info.type_given && args_info.type_arg == 2 ) 00240 { 00241 cerr << "ERROR: --broker is required for an investment statement request" << endl; 00242 ok = false; 00243 } 00244 } 00245 00246 if ( args_info.acct_given ) 00247 { 00248 cerr << "acct " << args_info.acct_arg << endl; 00249 strncpy(account.account_number,args_info.acct_arg,OFX_ACCTID_LENGTH-1); 00250 } 00251 else 00252 { 00253 cerr << "ERROR: --acct is required for a statement request" << endl; 00254 ok = false; 00255 } 00256 00257 if ( args_info.type_given ) 00258 { 00259 cerr << "type " << args_info.type_arg << endl; 00260 switch (args_info.type_arg) { 00261 case 1: account.account_type = account.OFX_CHECKING; 00262 break; 00263 case 2: account.account_type = account.OFX_INVESTMENT; 00264 break; 00265 case 3: account.account_type = account.OFX_CREDITCARD ; 00266 break; 00267 default: 00268 cerr << "ERROR: --type is not valid. Must be between 1 and 3" << endl; 00269 ok = false; 00270 } 00271 } 00272 else 00273 { 00274 cerr << "ERROR: --type is required for a statement request" << endl; 00275 ok = false; 00276 } 00277 00278 if ( args_info.past_given ) 00279 { 00280 cerr << "past " << args_info.past_arg << endl; 00281 } 00282 else 00283 { 00284 cerr << "ERROR: --past is required for a statement request" << endl; 00285 ok = false; 00286 } 00287 00288 if ( ok ) 00289 { 00290 char* request = libofx_request_statement( &fi, &account, time(NULL) - args_info.past_arg * 86400L ); 00291 00292 if ( url.length() ) 00293 post(request,url.c_str(),args_info.inputs[0]); 00294 else 00295 cout << request; 00296 00297 free(request); 00298 } 00299 } 00300 00301 if ( args_info.paymentinquiry_req_given ) 00302 { 00303 char tridstr[33]; 00304 memset(tridstr,0,33); 00305 00306 bool ok = true; 00307 00308 if ( args_info.trid_given ) 00309 { 00310 cerr << "trid " << args_info.trid_arg << endl; 00311 snprintf(tridstr,32,"%i",args_info.trid_arg); 00312 } 00313 else 00314 { 00315 cerr << "ERROR: --trid is required for a payment inquiry request" << endl; 00316 ok = false; 00317 } 00318 00319 if ( ok ) 00320 { 00321 char* request = libofx_request_payment_status( &fi, tridstr ); 00322 00323 filebuf fb; 00324 fb.open ("query",ios::out); 00325 ostream os(&fb); 00326 os << request; 00327 fb.close(); 00328 00329 if ( url.length() ) 00330 post(request,url.c_str(),args_info.inputs[0]); 00331 else 00332 cout << request; 00333 00334 free(request); 00335 } 00336 } 00337 00338 if ( args_info.payment_req_given ) 00339 { 00340 OfxAccountData account; 00341 memset(&account,0,sizeof(OfxAccountData)); 00342 OfxPayee payee; 00343 memset(&payee,0,sizeof(OfxPayee)); 00344 OfxPayment payment; 00345 memset(&payment,0,sizeof(OfxPayment)); 00346 00347 strcpy(payee.name,"MARTIN PREUSS"); 00348 strcpy(payee.address1,"1 LAUREL ST"); 00349 strcpy(payee.city,"SAN CARLOS"); 00350 strcpy(payee.state,"CA"); 00351 strcpy(payee.postalcode,"94070"); 00352 strcpy(payee.phone,"866-555-1212"); 00353 00354 strcpy(payment.amount,"200.00"); 00355 strcpy(payment.account,"1234"); 00356 strcpy(payment.datedue,"20060301"); 00357 strcpy(payment.memo,"This is a test"); 00358 00359 bool ok = true; 00360 00361 if ( args_info.bank_given ) 00362 { 00363 cerr << "bank " << args_info.bank_arg << endl; 00364 strncpy(account.bank_id,args_info.bank_arg,OFX_BANKID_LENGTH-1); 00365 } 00366 else 00367 { 00368 if ( args_info.type_given && args_info.type_arg == 1 ) 00369 { 00370 cerr << "ERROR: --bank is required for a bank request" << endl; 00371 ok = false; 00372 } 00373 } 00374 00375 if ( args_info.broker_given ) 00376 { 00377 cerr << "broker " << args_info.broker_arg << endl; 00378 strncpy(account.broker_id,args_info.broker_arg,OFX_BROKERID_LENGTH-1); 00379 } 00380 else 00381 { 00382 if ( args_info.type_given && args_info.type_arg == 2 ) 00383 { 00384 cerr << "ERROR: --broker is required for an investment statement request" << endl; 00385 ok = false; 00386 } 00387 } 00388 00389 if ( args_info.acct_given ) 00390 { 00391 cerr << "acct " << args_info.acct_arg << endl; 00392 strncpy(account.account_number,args_info.acct_arg,OFX_ACCTID_LENGTH-1); 00393 } 00394 else 00395 { 00396 cerr << "ERROR: --acct is required for a statement request" << endl; 00397 ok = false; 00398 } 00399 00400 if ( args_info.type_given ) 00401 { 00402 cerr << "type " << args_info.type_arg << endl; 00403 switch (args_info.type_arg) { 00404 case 1: account.account_type = account.OFX_CHECKING; 00405 break; 00406 case 2: account.account_type = account.OFX_INVESTMENT; 00407 break; 00408 case 3: account.account_type = account.OFX_CREDITCARD ; 00409 break; 00410 default: 00411 cerr << "ERROR: --type is not valid. Must be between 1 and 3" << endl; 00412 ok = false; 00413 } 00414 } 00415 else 00416 { 00417 cerr << "ERROR: --type is required for a statement request" << endl; 00418 ok = false; 00419 } 00420 00421 if ( ok ) 00422 { 00423 char* request = libofx_request_payment( &fi, &account, &payee, &payment ); 00424 00425 filebuf fb; 00426 fb.open ("query",ios::out); 00427 ostream os(&fb); 00428 os << request; 00429 fb.close(); 00430 00431 if ( url.length() ) 00432 post(request,url.c_str(),args_info.inputs[0]); 00433 else 00434 cout << request; 00435 00436 free(request); 00437 } 00438 00439 } 00440 00441 if ( args_info.accountinfo_req_given ) 00442 { 00443 if ( ok ) 00444 { 00445 char* request = libofx_request_accountinfo( &fi ); 00446 00447 if ( url.length() ) 00448 post(request,url.c_str(),args_info.inputs[0]); 00449 else 00450 cout << request; 00451 00452 free(request); 00453 } 00454 } 00455 00456 if ( args_info.bank_list_given ) 00457 { 00458 cout << OfxPartner::BankNames(); 00459 } 00460 00461 if ( args_info.bank_fipid_given ) 00462 { 00463 cout << OfxPartner::FipidForBank(args_info.inputs[0]); 00464 } 00465 00466 if ( args_info.bank_services_given ) 00467 { 00468 OfxFiServiceInfo svcinfo = OfxPartner::ServiceInfo(args_info.inputs[0]); 00469 cout << "Account List? " << (svcinfo.accountlist?"Yes":"No") << endl; 00470 cout << "Statements? " << (svcinfo.statements?"Yes":"No") << endl; 00471 cout << "Billpay? " << (svcinfo.billpay?"Yes":"No") << endl; 00472 cout << "Investments? " << (svcinfo.investments?"Yes":"No") << endl; 00473 } 00474 00475 if ( args_info.allsupport_given ) 00476 { 00477 vector<string> banks = OfxPartner::BankNames(); 00478 vector<string>::const_iterator it_bank = banks.begin(); 00479 while ( it_bank != banks.end() ) 00480 { 00481 vector<string> fipids = OfxPartner::FipidForBank(*it_bank); 00482 vector<string>::const_iterator it_fipid = fipids.begin(); 00483 while ( it_fipid != fipids.end() ) 00484 { 00485 if ( OfxPartner::ServiceInfo(*it_fipid).accountlist ) 00486 cout << *it_bank << endl; 00487 ++it_fipid; 00488 } 00489 ++it_bank; 00490 } 00491 } 00492 00493 return 0; 00494 } 00495 00496 00497 // vim:cin:si:ai:et:ts=2:sw=2: 00498