ofxconnect.cpp
Go to the documentation of this file.

    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