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.