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