LibOFX
ofxconnect.cpp
Go to the documentation of this file.
1/***************************************************************************
2 ofx_connect.cpp
3 -------------------
4 copyright : (C) 2005 by Ace Jones
5 email : acejones@users.sourceforge.net
6***************************************************************************/
23/***************************************************************************
24 * *
25 * This program is free software; you can redistribute it and/or modify *
26 * it under the terms of the GNU General Public License as published by *
27 * the Free Software Foundation; either version 2 of the License, or *
28 * (at your option) any later version. *
29 * *
30 ***************************************************************************/
31#include <iostream>
32#include <fstream>
33#include <string>
34#include "libofx.h"
35#include <config.h> /* Include config constants, e.g., VERSION TF */
36#include <stdio.h>
37#include <stdlib.h>
38#include <unistd.h>
39#include <cstring>
40#include <cstdlib>
41#include <string.h>
42#ifdef HAVE_LIBCURL
43#include <curl/curl.h>
44#endif
45
46#include "cmdline.h" /* Gengetopt generated parser */
47
48#include "nodeparser.h"
49
50#ifdef HAVE_LIBCURL
51bool post(const char* request, const char* url, const char* filename)
52{
53 CURL *curl = curl_easy_init();
54 if (! curl)
55 return false;
56
57 remove("tmpout");
58 FILE* file = fopen(filename, "wb");
59 if (! file )
60 {
61 curl_easy_cleanup(curl);
62 return false;
63 }
64
65 curl_easy_setopt(curl, CURLOPT_URL, url);
66 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, request);
67
68 struct curl_slist *headerlist = NULL;
69 headerlist = curl_slist_append(headerlist, "Content-type: application/x-ofx");
70 headerlist = curl_slist_append(headerlist, "Accept: */*, application/x-ofx");
71
72 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
73 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fwrite);
74 curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)file);
75
76 CURLcode res = curl_easy_perform(curl);
77
78 curl_easy_cleanup(curl);
79 curl_slist_free_all (headerlist);
80
81 fclose(file);
82
83 return true;
84}
85#else
86bool post(const char*, const char*, const char*)
87{
88 std::cerr << "ERROR: libox must be configured with libcurl to post this request directly" << std::endl;
89 return false;
90}
91#endif
92
93std::ostream& operator<<(std::ostream& os, const std::vector<std::string>& strvect)
94{
95 for ( std::vector<std::string>::const_iterator it = strvect.begin(); it != strvect.end(); ++it)
96 {
97 os << (*it) << std::endl;
98 }
99 return os;
100}
101
102int main (int argc, char *argv[])
103{
104 gengetopt_args_info args_info;
105
106 if (cmdline_parser (argc, argv, &args_info) != 0)
107 exit(1) ;
108
109 if ( argc == 1 )
110 {
112 exit(1);
113 }
114
115 if ( args_info.statement_req_given || args_info.accountinfo_req_given )
116 {
117 if ( (args_info.inputs_num > 0) )
118 {
119 std::cout << "file " << args_info.inputs[0] << std::endl;
120 }
121 else
122 {
123 std::cerr << "ERROR: You must specify an output file" << std::endl;
124 exit(1);
125 }
126 }
127
128 OfxFiLogin fi;
129 memset(&fi, 0, sizeof(OfxFiLogin));
130 bool ok = true;
131 std::string url;
132
133 if ( args_info.statement_req_given || args_info.accountinfo_req_given || args_info.payment_req_given || args_info.paymentinquiry_req_given )
134 {
135 // Get the FI Login information
136 //
137
138 if ( args_info.fid_given )
139 {
140 std::cerr << "fid " << args_info.fid_arg << std::endl;
141 strncpy(fi.fid, args_info.fid_arg, OFX_FID_LENGTH - 1);
142 }
143 else
144 {
145 std::cerr << "ERROR: --fid is required" << std::endl;
146 ok = false;
147 }
148
149 if ( args_info.org_given )
150 {
151 std::cerr << "org " << args_info.org_arg << std::endl;
152 strncpy(fi.org, args_info.org_arg, OFX_ORG_LENGTH - 1);
153 }
154 else
155 {
156 std::cerr << "ERROR: --org is required" << std::endl;
157 ok = false;
158 }
159
160 if ( args_info.user_given )
161 {
162 std::cerr << "user " << args_info.user_arg << std::endl;
163 strncpy(fi.userid, args_info.user_arg, OFX_USERID_LENGTH - 1);
164 }
165 else
166 {
167 std::cerr << "ERROR: --user is required" << std::endl;
168 ok = false;
169 }
170
171 if ( args_info.pass_given )
172 {
173 std::cerr << "pass " << args_info.pass_arg << std::endl;
174 strncpy(fi.userpass, args_info.pass_arg, OFX_USERPASS_LENGTH - 1);
175 }
176 else
177 {
178 std::cerr << "ERROR: --pass is required" << std::endl;
179 ok = false;
180 }
181
182 if ( args_info.url_given )
183 url = args_info.url_arg;
184 }
185
186 if ( args_info.statement_req_given )
187 {
188 std::cerr << "Statement request" << std::endl;
189
190 OfxAccountData account;
191 memset(&account, 0, sizeof(OfxAccountData));
192
193 if ( args_info.bank_given )
194 {
195 std::cerr << "bank " << args_info.bank_arg << std::endl;
196 strncpy(account.bank_id, args_info.bank_arg, OFX_BANKID_LENGTH - 1);
197 }
198 else
199 {
200 if ( args_info.type_given && args_info.type_arg == 1 )
201 {
202 std::cerr << "ERROR: --bank is required for a bank request" << std::endl;
203 ok = false;
204 }
205 }
206
207 if ( args_info.broker_given )
208 {
209 std::cerr << "broker " << args_info.broker_arg << std::endl;
210 strncpy(account.broker_id, args_info.broker_arg, OFX_BROKERID_LENGTH - 1);
211 }
212 else
213 {
214 if ( args_info.type_given && args_info.type_arg == 2 )
215 {
216 std::cerr << "ERROR: --broker is required for an investment statement request" << std::endl;
217 ok = false;
218 }
219 }
220
221 if ( args_info.acct_given )
222 {
223 std::cerr << "acct " << args_info.acct_arg << std::endl;
224 strncpy(account.account_number, args_info.acct_arg, OFX_ACCTID_LENGTH - 1);
225 }
226 else
227 {
228 std::cerr << "ERROR: --acct is required for a statement request" << std::endl;
229 ok = false;
230 }
231
232 if ( args_info.type_given )
233 {
234 std::cerr << "type " << args_info.type_arg << std::endl;
235 switch (args_info.type_arg)
236 {
237 case 1:
238 account.account_type = account.OFX_CHECKING;
239 break;
240 case 2:
241 account.account_type = account.OFX_INVESTMENT;
242 break;
243 case 3:
244 account.account_type = account.OFX_CREDITCARD ;
245 break;
246 default:
247 std::cerr << "ERROR: --type is not valid. Must be between 1 and 3" << std::endl;
248 ok = false;
249 }
250 }
251 else
252 {
253 std::cerr << "ERROR: --type is required for a statement request" << std::endl;
254 ok = false;
255 }
256
257 if ( args_info.past_given )
258 {
259 std::cerr << "past " << args_info.past_arg << std::endl;
260 }
261 else
262 {
263 std::cerr << "ERROR: --past is required for a statement request" << std::endl;
264 ok = false;
265 }
266
267 if ( ok )
268 {
269 char* request = libofx_request_statement( &fi, &account, time(NULL) - args_info.past_arg * 86400L );
270
271 if ( url.length() && args_info.inputs_num > 0 )
272 post(request, url.c_str(), args_info.inputs[0]);
273 else
274 std::cout << request;
275
276 free(request);
277 }
278 }
279
280 if ( args_info.paymentinquiry_req_given )
281 {
282 char tridstr[33];
283 memset(tridstr, 0, 33);
284
285 bool is_trid_given = true;
286
287 if ( args_info.trid_given )
288 {
289 std::cerr << "trid " << args_info.trid_arg << std::endl;
290 snprintf(tridstr, 32, "%i", args_info.trid_arg);
291 }
292 else
293 {
294 std::cerr << "ERROR: --trid is required for a payment inquiry request" << std::endl;
295 is_trid_given = false;
296 }
297
298 if ( is_trid_given )
299 {
300 char* request = libofx_request_payment_status( &fi, tridstr );
301
302 std::filebuf fb;
303 fb.open ("query", std::ios::out);
304 std::ostream os(&fb);
305 os << request;
306 fb.close();
307
308 if ( url.length() && args_info.inputs_num > 0 )
309 post(request, url.c_str(), args_info.inputs[0]);
310 else
311 std::cout << request;
312
313 free(request);
314 }
315 }
316
317 if ( args_info.payment_req_given )
318 {
319 OfxAccountData account;
320 memset(&account, 0, sizeof(OfxAccountData));
321 OfxPayee payee;
322 memset(&payee, 0, sizeof(OfxPayee));
323 OfxPayment payment;
324 memset(&payment, 0, sizeof(OfxPayment));
325
326 strcpy(payee.name, "MARTIN PREUSS");
327 strcpy(payee.address1, "1 LAUREL ST");
328 strcpy(payee.city, "SAN CARLOS");
329 strcpy(payee.state, "CA");
330 strcpy(payee.postalcode, "94070");
331 strcpy(payee.phone, "866-555-1212");
332
333 strcpy(payment.amount, "200.00");
334 strcpy(payment.account, "1234");
335 strcpy(payment.datedue, "20060301");
336 strcpy(payment.memo, "This is a test");
337
338 bool is_payment_args_given = true;
339
340 if ( args_info.bank_given )
341 {
342 std::cerr << "bank " << args_info.bank_arg << std::endl;
343 strncpy(account.bank_id, args_info.bank_arg, OFX_BANKID_LENGTH - 1);
344 }
345 else
346 {
347 if ( args_info.type_given && args_info.type_arg == 1 )
348 {
349 std::cerr << "ERROR: --bank is required for a bank request" << std::endl;
350 is_payment_args_given = false;
351 }
352 }
353
354 if ( args_info.broker_given )
355 {
356 std::cerr << "broker " << args_info.broker_arg << std::endl;
357 strncpy(account.broker_id, args_info.broker_arg, OFX_BROKERID_LENGTH - 1);
358 }
359 else
360 {
361 if ( args_info.type_given && args_info.type_arg == 2 )
362 {
363 std::cerr << "ERROR: --broker is required for an investment statement request" << std::endl;
364 is_payment_args_given = false;
365 }
366 }
367
368 if ( args_info.acct_given )
369 {
370 std::cerr << "acct " << args_info.acct_arg << std::endl;
371 strncpy(account.account_number, args_info.acct_arg, OFX_ACCTID_LENGTH - 1);
372 }
373 else
374 {
375 std::cerr << "ERROR: --acct is required for a statement request" << std::endl;
376 is_payment_args_given = false;
377 }
378
379 if ( args_info.type_given )
380 {
381 std::cerr << "type " << args_info.type_arg << std::endl;
382 switch (args_info.type_arg)
383 {
384 case 1:
385 account.account_type = account.OFX_CHECKING;
386 break;
387 case 2:
388 account.account_type = account.OFX_INVESTMENT;
389 break;
390 case 3:
391 account.account_type = account.OFX_CREDITCARD ;
392 break;
393 default:
394 std::cerr << "ERROR: --type is not valid. Must be between 1 and 3" << std::endl;
395 ok = false;
396 }
397 }
398 else
399 {
400 std::cerr << "ERROR: --type is required for a statement request" << std::endl;
401 is_payment_args_given = false;
402 }
403
404 if ( is_payment_args_given )
405 {
406 char* request = libofx_request_payment( &fi, &account, &payee, &payment );
407
408 std::filebuf fb;
409 fb.open ("query", std::ios::out);
410 std::ostream os(&fb);
411 os << request;
412 fb.close();
413
414 if ( url.length() && args_info.inputs_num > 0 )
415 post(request, url.c_str(), args_info.inputs[0]);
416 else
417 std::cout << request;
418
419 free(request);
420 }
421
422 }
423
424 if ( args_info.accountinfo_req_given )
425 {
426 if ( ok )
427 {
428 char* request = libofx_request_accountinfo( &fi );
429
430 if ( url.length() && args_info.inputs_num > 0 )
431 post(request, url.c_str(), args_info.inputs[0]);
432 else
433 std::cout << request;
434
435 free(request);
436 }
437 }
438
439 return 0;
440}
441
442
443// vim:cin:si:ai:et:ts=2:sw=2:
444
Declaration of nodeparser object, which facilitates searching for nodes in an XML file using a notati...
The header file for the command line option parser generated by GNU Gengetopt version 2....
void cmdline_parser_print_help(void)
Where the command line options are stored.
unsigned int fid_given
Whether fid was given.
unsigned int paymentinquiry_req_given
Whether paymentinquiry-req was given.
unsigned int type_given
Whether type was given.
int type_arg
Account Type 1=checking 2=invest 3=ccard.
char * user_arg
User name.
char * pass_arg
Password.
unsigned inputs_num
unnamed options number
char * bank_arg
IBAN bank identifier.
unsigned int statement_req_given
Whether statement-req was given.
char ** inputs
unnamed options (options without names)
unsigned int user_given
Whether user was given.
char * fid_arg
FI identifier.
unsigned int acct_given
Whether acct was given.
unsigned int accountinfo_req_given
Whether accountinfo-req was given.
int trid_arg
Transaction id.
char * acct_arg
Account ID.
long past_arg
How far back to look from today (in days).
unsigned int broker_given
Whether broker was given.
char * org_arg
FI org tag.
char * broker_arg
Broker identifier.
unsigned int bank_given
Whether bank was given.
unsigned int org_given
Whether org was given.
unsigned int url_given
Whether url was given.
char * url_arg
Url to POST the data to (otherwise goes to stdout).
unsigned int past_given
Whether past was given.
unsigned int pass_given
Whether pass was given.
unsigned int payment_req_given
Whether payment-req was given.
unsigned int trid_given
Whether trid was given.