# 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
    00040 #ifdef HAVE_LIBCURL
    00041 #include <curl/curl.h>
    00042 #endif
    00043
    00044 #include "cmdline.h" /* Gengetopt generated parser */
    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   // Get the FI Login information
    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     OfxAccountInfo account;
    00214     memset(&account,0,sizeof(OfxAccountInfo));
    00215
    00216     if ( args_info.bank_given )
    00217     {
    00218       cerr << "bank " << args_info.bank_arg << endl;
    00219       strncpy(account.bankid,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.brokerid,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.accountid,args_info.acct_arg,OFX_ACCOUNT_ID_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       account.type = static_cast<AccountType>(args_info.type_arg);
    00259     }
    00260     else
    00261     {
    00262       cerr << "ERROR: --type is required for a statement request" << endl;
    00263       ok = false;
    00264     }
    00265
    00266     if ( args_info.past_given )
    00267     {
    00268       cerr << "past " << args_info.past_arg << endl;
    00269     }
    00270     else
    00271     {
    00272       cerr << "ERROR: --past is required for a statement request" << endl;
    00273       ok = false;
    00274     }
    00275
    00276     if ( ok )
    00277     {
    00278       char* request = libofx_request_statement( &fi, &account, time(NULL) - args_info.past_arg * 86400L );
    00279
    00280       if ( url.length() )
    00281         post(request,url.c_str(),args_info.inputs[0]);
    00282       else
    00283         cout << request;
    00284
    00285       free(request);
    00286     }
    00287   }
    00288
    00289   if ( args_info.paymentinquiry_req_given )
    00290   {
    00291     char tridstr[33];
    00292     memset(tridstr,0,33);
    00293
    00294     bool ok = true;
    00295
    00296     if ( args_info.trid_given )
    00297     {
    00298       cerr << "trid " << args_info.trid_arg << endl;
    00299       snprintf(tridstr,32,"%i",args_info.trid_arg);
    00300     }
    00301     else
    00302     {
    00303       cerr << "ERROR: --trid is required for a payment inquiry request" << endl;
    00304       ok = false;
    00305     }
    00306
    00307     if ( ok )
    00308     {
    00309       char* request = libofx_request_payment_status( &fi, tridstr );
    00310
    00311       filebuf fb;
    00312       fb.open ("query",ios::out);
    00313       ostream os(&fb);
    00314       os << request;
    00315       fb.close();
    00316
    00317       if ( url.length() )
    00318         post(request,url.c_str(),args_info.inputs[0]);
    00319       else
    00320         cout << request;
    00321
    00322       free(request);
    00323     }
    00324   }
    00325
    00326   if ( args_info.payment_req_given )
    00327   {
    00328     OfxAccountInfo account;
    00329     memset(&account,0,sizeof(OfxAccountInfo));
    00330     OfxPayee payee;
    00331     memset(&payee,0,sizeof(OfxPayee));
    00332     OfxPayment payment;
    00333     memset(&payment,0,sizeof(OfxPayment));
    00334
    00335     strcpy(payee.name,"MARTIN PREUSS");
    00336     strcpy(payee.address1,"1 LAUREL ST");
    00337     strcpy(payee.city,"SAN CARLOS");
    00338     strcpy(payee.state,"CA");
    00339     strcpy(payee.postalcode,"94070");
    00340     strcpy(payee.phone,"866-555-1212");
    00341
    00342     strcpy(payment.amount,"200.00");
    00343     strcpy(payment.account,"1234");
    00344     strcpy(payment.datedue,"20060301");
    00345     strcpy(payment.memo,"This is a test");
    00346
    00347     bool ok = true;
    00348
    00349     if ( args_info.bank_given )
    00350     {
    00351       cerr << "bank " << args_info.bank_arg << endl;
    00352       strncpy(account.bankid,args_info.bank_arg,OFX_BANKID_LENGTH-1);
    00353     }
    00354     else
    00355     {
    00356       if ( args_info.type_given && args_info.type_arg == 1 )
    00357       {
    00358         cerr << "ERROR: --bank is required for a bank request" << endl;
    00359         ok = false;
    00360       }
    00361     }
    00362
    00363     if ( args_info.broker_given )
    00364     {
    00365       cerr << "broker " << args_info.broker_arg << endl;
    00366       strncpy(account.brokerid,args_info.broker_arg,OFX_BROKERID_LENGTH-1);
    00367     }
    00368     else
    00369     {
    00370       if ( args_info.type_given && args_info.type_arg == 2 )
    00371       {
    00372         cerr << "ERROR: --broker is required for an investment statement request" << endl;
    00373         ok = false;
    00374       }
    00375     }
    00376
    00377     if ( args_info.acct_given )
    00378     {
    00379       cerr << "acct " << args_info.acct_arg << endl;
    00380       strncpy(account.accountid,args_info.acct_arg,OFX_ACCOUNT_ID_LENGTH-1);
    00381     }
    00382     else
    00383     {
    00384       cerr << "ERROR: --acct is required for a statement request" << endl;
    00385       ok = false;
    00386     }
    00387
    00388     if ( args_info.type_given )
    00389     {
    00390       cerr << "type " << args_info.type_arg << endl;
    00391       account.type = static_cast<AccountType>(args_info.type_arg);
    00392     }
    00393     else
    00394     {
    00395       cerr << "ERROR: --type is required for a statement request" << endl;
    00396       ok = false;
    00397     }
    00398
    00399     if ( ok )
    00400     {
    00401       char* request = libofx_request_payment( &fi, &account, &payee, &payment );
    00402
    00403       filebuf fb;
    00404       fb.open ("query",ios::out);
    00405       ostream os(&fb);
    00406       os << request;
    00407       fb.close();
    00408
    00409       if ( url.length() )
    00410         post(request,url.c_str(),args_info.inputs[0]);
    00411       else
    00412         cout << request;
    00413
    00414       free(request);
    00415     }
    00416
    00417   }
    00418
    00419   if ( args_info.accountinfo_req_given )
    00420   {
    00421     if ( ok )
    00422     {
    00423       char* request = libofx_request_accountinfo( &fi );
    00424
    00425       if ( url.length() )
    00426         post(request,url.c_str(),args_info.inputs[0]);
    00427       else
    00428         cout << request;
    00429
    00430       free(request);
    00431     }
    00432   }
    00433
    00434   if ( args_info.bank_list_given )
    00435   {
    00436     cout << OfxPartner::BankNames();
    00437   }
    00438
    00439   if ( args_info.bank_fipid_given )
    00440   {
    00441     cout << OfxPartner::FipidForBank(args_info.inputs[0]);
    00442   }
    00443
    00444   if ( args_info.bank_services_given )
    00445   {
    00446     OfxFiServiceInfo svcinfo = OfxPartner::ServiceInfo(args_info.inputs[0]);
    00447     cout << "Account List? " << (svcinfo.accountlist?"Yes":"No") << endl;
    00448     cout << "Statements? " << (svcinfo.statements?"Yes":"No") << endl;
    00449     cout << "Billpay? " << (svcinfo.billpay?"Yes":"No") << endl;
    00450     cout << "Investments? " << (svcinfo.investments?"Yes":"No") << endl;
    00451   }
    00452
    00453   if ( args_info.allsupport_given )
    00454   {
    00455     vector<string> banks = OfxPartner::BankNames();
    00456     vector<string>::const_iterator it_bank = banks.begin();
    00457     while ( it_bank != banks.end() )
    00458     {
    00459       vector<string> fipids = OfxPartner::FipidForBank(*it_bank);
    00460       vector<string>::const_iterator it_fipid = fipids.begin();
    00461       while ( it_fipid != fipids.end() )
    00462       {
    00463         if ( OfxPartner::ServiceInfo(*it_fipid).accountlist )
    00464           cout << *it_bank << endl;
    00465         ++it_fipid;
    00466       }
    00467       ++it_bank;
    00468     }
    00469   }
    00470
    00471   return 0;
    00472 }
    00473
    00474
    00475 // vim:cin:si:ai:et:ts=2:sw=2:
    00476