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 

Generated on Mon Feb 9 21:21:59 2009 for LibOFX by  doxygen 1.5.0