- Main Page
- Namespaces
- Data Structures
- Files

# 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     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 // vim:cin:si:ai:et:ts=2:sw=2:
    00496