43 #include <curl/curl.h> 
   54 bool post(
const char* request, 
const char* url, 
const char* filename)
 
   56   CURL *curl = curl_easy_init();
 
   61   FILE* file = fopen(filename, 
"wb");
 
   64     curl_easy_cleanup(curl);
 
   68   curl_easy_setopt(curl, CURLOPT_URL, url);
 
   69   curl_easy_setopt(curl, CURLOPT_POSTFIELDS, request);
 
   71   struct curl_slist *headerlist = NULL;
 
   72   headerlist = curl_slist_append(headerlist, 
"Content-type: application/x-ofx");
 
   73   headerlist = curl_slist_append(headerlist, 
"Accept: */*, application/x-ofx");
 
   75   curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
 
   76   curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fwrite);
 
   77   curl_easy_setopt(curl, CURLOPT_WRITEDATA, (
void *)file);
 
   79   CURLcode res = curl_easy_perform(curl);
 
   81   curl_easy_cleanup(curl);
 
   82   curl_slist_free_all (headerlist);
 
   89 bool post(
const char*, 
const char*, 
const char*)
 
   91   cerr << 
"ERROR: libox must be configured with libcurl to post this request directly" << endl;
 
   96 ostream& operator<<(ostream& os, const vector<string>& strvect)
 
   98   for ( vector<string>::const_iterator it = strvect.begin(); it != strvect.end(); ++it)
 
  105 int main (
int argc, 
char *argv[])
 
  118   if ( args_info.statement_req_given || args_info.accountinfo_req_given )
 
  122       cout << 
"file " << args_info.
inputs[0] << endl;
 
  126       cerr << 
"ERROR: You must specify an output file" << endl;
 
  129   else if ( args_info.bank_fipid_given || args_info.bank_services_given )
 
  133       cout << 
"bank " << args_info.
inputs[0] << endl;
 
  137       cerr << 
"ERROR: You must specify an bank" << endl;
 
  146   if ( args_info.statement_req_given || args_info.accountinfo_req_given || args_info.payment_req_given || args_info.paymentinquiry_req_given )
 
  151     if ( args_info.fipid_given )
 
  153       cerr << 
"fipid " <<  args_info.fipid_arg << endl;
 
  154       cerr << 
"contacting partner server..." << endl;
 
  156       cout << 
"fid " << svcinfo.fid << endl;
 
  157       strncpy(fi.fid, svcinfo.fid, OFX_FID_LENGTH - 1);
 
  158       cout << 
"org " << svcinfo.org << endl;
 
  159       strncpy(fi.org, svcinfo.org, OFX_ORG_LENGTH - 1);
 
  160       cout << 
"url " << svcinfo.url << endl;
 
  163     if ( args_info.fid_given )
 
  165       cerr << 
"fid " <<  args_info.fid_arg << endl;
 
  166       strncpy(fi.fid, args_info.fid_arg, OFX_FID_LENGTH - 1);
 
  168     else if ( ! args_info.fipid_given )
 
  170       cerr << 
"ERROR: --fid is required" << endl;
 
  174     if ( args_info.org_given )
 
  176       cerr << 
"org " << args_info.org_arg << endl;
 
  177       strncpy(fi.org, args_info.org_arg, OFX_ORG_LENGTH - 1);
 
  179     else if ( ! args_info.fipid_given )
 
  181       cerr << 
"ERROR: --org is required" << endl;
 
  185     if ( args_info.user_given )
 
  187       cerr << 
"user " << args_info.user_arg << endl;
 
  188       strncpy(fi.userid, args_info.user_arg, OFX_USERID_LENGTH - 1);
 
  192       cerr << 
"ERROR: --user is required" << endl;
 
  196     if ( args_info.pass_given )
 
  198       cerr << 
"pass " << args_info.pass_arg << endl;
 
  199       strncpy(fi.userpass, args_info.pass_arg, OFX_USERPASS_LENGTH - 1);
 
  203       cerr << 
"ERROR: --pass is required" << endl;
 
  207     if ( args_info.url_given )
 
  208       url = args_info.url_arg;
 
  211   if ( args_info.statement_req_given )
 
  213     cerr << 
"Statement request" << endl;
 
  218     if ( args_info.bank_given )
 
  220       cerr << 
"bank " << args_info.bank_arg << endl;
 
  221       strncpy(account.
bank_id, args_info.bank_arg, OFX_BANKID_LENGTH - 1);
 
  225       if ( args_info.type_given && args_info.type_arg == 1 )
 
  227         cerr << 
"ERROR: --bank is required for a bank request" << endl;
 
  232     if ( args_info.broker_given )
 
  234       cerr << 
"broker " << args_info.broker_arg << endl;
 
  235       strncpy(account.broker_id, args_info.broker_arg, OFX_BROKERID_LENGTH - 1);
 
  239       if ( args_info.type_given && args_info.type_arg == 2 )
 
  241         cerr << 
"ERROR: --broker is required for an investment statement request" << endl;
 
  246     if ( args_info.acct_given )
 
  248       cerr << 
"acct " << args_info.acct_arg << endl;
 
  249       strncpy(account.
account_number, args_info.acct_arg, OFX_ACCTID_LENGTH - 1);
 
  253       cerr << 
"ERROR: --acct is required for a statement request" << endl;
 
  257     if ( args_info.type_given )
 
  259       cerr << 
"type " << args_info.type_arg << endl;
 
  260       switch (args_info.type_arg)
 
  272         cerr << 
"ERROR: --type is not valid.  Must be between 1 and 3" << endl;
 
  278       cerr << 
"ERROR: --type is required for a statement request" << endl;
 
  282     if ( args_info.past_given )
 
  284       cerr << 
"past " << args_info.past_arg << endl;
 
  288       cerr << 
"ERROR: --past is required for a statement request" << endl;
 
  297         post(request, url.c_str(), args_info.
inputs[0]);
 
  305   if ( args_info.paymentinquiry_req_given )
 
  308     memset(tridstr, 0, 33);
 
  312     if ( args_info.trid_given )
 
  314       cerr << 
"trid " << args_info.trid_arg << endl;
 
  315       snprintf(tridstr, 32, 
"%i", args_info.trid_arg);
 
  319       cerr << 
"ERROR: --trid is required for a payment inquiry request" << endl;
 
  325       char* request = libofx_request_payment_status( &fi, tridstr );
 
  328       fb.open (
"query", ios::out);
 
  334         post(request, url.c_str(), args_info.
inputs[0]);
 
  342   if ( args_info.payment_req_given )
 
  347     memset(&payee, 0, 
sizeof(
OfxPayee));
 
  351     strcpy(payee.name, 
"MARTIN PREUSS");
 
  352     strcpy(payee.address1, 
"1 LAUREL ST");
 
  353     strcpy(payee.city, 
"SAN CARLOS");
 
  354     strcpy(payee.state, 
"CA");
 
  355     strcpy(payee.postalcode, 
"94070");
 
  356     strcpy(payee.phone, 
"866-555-1212");
 
  358     strcpy(payment.amount, 
"200.00");
 
  359     strcpy(payment.account, 
"1234");
 
  360     strcpy(payment.datedue, 
"20060301");
 
  361     strcpy(payment.memo, 
"This is a test");
 
  365     if ( args_info.bank_given )
 
  367       cerr << 
"bank " << args_info.bank_arg << endl;
 
  368       strncpy(account.
bank_id, args_info.bank_arg, OFX_BANKID_LENGTH - 1);
 
  372       if ( args_info.type_given && args_info.type_arg == 1 )
 
  374         cerr << 
"ERROR: --bank is required for a bank request" << endl;
 
  379     if ( args_info.broker_given )
 
  381       cerr << 
"broker " << args_info.broker_arg << endl;
 
  382       strncpy(account.broker_id, args_info.broker_arg, OFX_BROKERID_LENGTH - 1);
 
  386       if ( args_info.type_given && args_info.type_arg == 2 )
 
  388         cerr << 
"ERROR: --broker is required for an investment statement request" << endl;
 
  393     if ( args_info.acct_given )
 
  395       cerr << 
"acct " << args_info.acct_arg << endl;
 
  396       strncpy(account.
account_number, args_info.acct_arg, OFX_ACCTID_LENGTH - 1);
 
  400       cerr << 
"ERROR: --acct is required for a statement request" << endl;
 
  404     if ( args_info.type_given )
 
  406       cerr << 
"type " << args_info.type_arg << endl;
 
  407       switch (args_info.type_arg)
 
  419         cerr << 
"ERROR: --type is not valid.  Must be between 1 and 3" << endl;
 
  425       cerr << 
"ERROR: --type is required for a statement request" << endl;
 
  431       char* request = libofx_request_payment( &fi, &account, &payee, &payment );
 
  434       fb.open (
"query", ios::out);
 
  440         post(request, url.c_str(), args_info.
inputs[0]);
 
  449   if ( args_info.accountinfo_req_given )
 
  456         post(request, url.c_str(), args_info.
inputs[0]);
 
  464   if ( args_info.bank_list_given )
 
  466     cout << OfxPartner::BankNames();
 
  469   if ( args_info.bank_fipid_given )
 
  471     cout << OfxPartner::FipidForBank(args_info.
inputs[0]);
 
  474   if ( args_info.bank_services_given )
 
  477     cout << 
"Account List? " << (svcinfo.
accountlist ? 
"Yes" : 
"No") << endl;
 
  478     cout << 
"Statements? " << (svcinfo.
statements ? 
"Yes" : 
"No") << endl;
 
  479     cout << 
"Billpay? " << (svcinfo.
billpay ? 
"Yes" : 
"No") << endl;
 
  480     cout << 
"Investments? " << (svcinfo.
investments ? 
"Yes" : 
"No") << endl;
 
  483   if ( args_info.allsupport_given )
 
  485     vector<string> banks = OfxPartner::BankNames();
 
  486     vector<string>::const_iterator it_bank = banks.begin();
 
  487     while ( it_bank != banks.end() )
 
  489       vector<string> fipids = OfxPartner::FipidForBank(*it_bank);
 
  490       vector<string>::const_iterator it_fipid = fipids.begin();
 
  491       while ( it_fipid != fipids.end() )
 
  493         if ( OfxPartner::ServiceInfo(*it_fipid).accountlist )
 
  494           cout << *it_bank << endl;
 
An abstraction of an account. 
Where the command line options are stored. 
char * libofx_request_statement(const struct OfxFiLogin *fi, const struct OfxAccountData *account, time_t date_from)
Creates an OFX statement request in string form. 
Methods for connecting to the OFX partner server to retrieve OFX server information. 
char * libofx_request_accountinfo(const struct OfxFiLogin *login)
Creates an OFX account info (list) request in string form. 
char bank_id[OFX_BANKID_LENGTH]
int cmdline_parser(int argc, char **argv, struct gengetopt_args_info *args_info)
void cmdline_parser_print_help(void)
unsigned inputs_num
unamed options number 
Information returned by the OFX Partner Server about a financial institution. 
int main(int argc, char *argv[])
The header file for the command line option parser generated by GNU Gengetopt version 2...
char account_number[OFX_ACCTID_LENGTH]
Declaration of nodeparser object, which facilitiates searching for nodes in an XML file using a notat...
char ** inputs
unamed options (options without names) 
Information sufficient to log into an financial institution.