/*************************************************************************** ofx_partner.cpp ------------------- copyright : (C) 2005 by Ace Jones email : acejones@users.sourceforge.net ***************************************************************************/ /**@file * \brief Methods for connecting to the OFX partner server to retrieve * OFX server information */ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include #endif #include //#ifdef HAVE_LIBCURL #include //#endif #include "ofxpartner.h" #include "nodeparser.h" #include #include #include #include #include #include using std::string; using std::vector; using std::cout; using std::endl; namespace OfxPartner { bool post(const string& request, const string& url, const string& filename); const string kBankFilename = "ofx-bank-index.xml"; const string kCcFilename = "ofx-cc-index.xml"; const string kInvFilename = "ofx-inv-index.xml"; void ValidateIndexCache(void) { // TODO Check whether these files exist and are recent enough before getting them again struct stat filestats; if ( stat( kBankFilename.c_str(), &filestats ) || difftime(time(0), filestats.st_mtime) > 7.0 * 24.0 * 60.0 * 60.0 ) post("T=1&S=*&R=1&O=0&TEST=0", "http://moneycentral.msn.com/money/2005/mnynet/service/ols/filist.aspx?SKU=3&VER=6", kBankFilename); if ( stat( kCcFilename.c_str(), &filestats ) || difftime(time(0), filestats.st_mtime) > 7.0 * 24.0 * 60.0 * 60.0 ) post("T=2&S=*&R=1&O=0&TEST=0", "http://moneycentral.msn.com/money/2005/mnynet/service/ols/filist.aspx?SKU=3&VER=6", kCcFilename); if ( stat( kInvFilename.c_str(), &filestats ) || difftime(time(0), filestats.st_mtime) > 7.0 * 24.0 * 60.0 * 60.0 ) post("T=3&S=*&R=1&O=0&TEST=0", "http://moneycentral.msn.com/money/2005/mnynet/service/ols/filist.aspx?SKU=3&VER=6", kInvFilename); } vector BankNames(void) { vector result; // Make sure the index files are up to date ValidateIndexCache(); xmlpp::DomParser parser; parser.set_substitute_entities(); parser.parse_file(kBankFilename); if ( parser ) { vector names = NodeParser(parser).Path("fi/prov/name").Text(); result.insert(result.end(), names.begin(), names.end()); } parser.parse_file(kCcFilename); if ( parser ) { vector names = NodeParser(parser).Path("fi/prov/name").Text(); result.insert(result.end(), names.begin(), names.end()); } parser.parse_file(kInvFilename); if ( parser ) { vector names = NodeParser(parser).Path("fi/prov/name").Text(); result.insert(result.end(), names.begin(), names.end()); } // Add Innovision result.push_back("Innovision"); // sort the list and remove duplicates, to return one unified list of all supported banks sort(result.begin(), result.end()); result.erase(unique(result.begin(), result.end()), result.end()); return result; } vector FipidForBank(const string& bank) { vector result; xmlpp::DomParser parser; parser.set_substitute_entities(); parser.parse_file(kBankFilename); if ( parser ) { vector fipids = NodeParser(parser).Path("fi/prov").Select("name", bank).Path("guid").Text(); if ( ! fipids.back().empty() ) result.insert(result.end(), fipids.begin(), fipids.end()); } parser.parse_file(kCcFilename); if ( parser ) { vector fipids = NodeParser(parser).Path("fi/prov").Select("name", bank).Path("guid").Text(); if ( ! fipids.back().empty() ) result.insert(result.end(), fipids.begin(), fipids.end()); } parser.parse_file(kInvFilename); if ( parser ) { vector fipids = NodeParser(parser).Path("fi/prov").Select("name", bank).Path("guid").Text(); if ( ! fipids.back().empty() ) result.insert(result.end(), fipids.begin(), fipids.end()); } // the fipid for Innovision is 1. if ( bank == "Innovision" ) result.push_back("1"); sort(result.begin(), result.end()); result.erase(unique(result.begin(), result.end()), result.end()); return result; } OfxFiServiceInfo ServiceInfo(const std::string& fipid) { OfxFiServiceInfo result; memset(&result, 0, sizeof(OfxFiServiceInfo)); // Hard-coded values for Innovision test server if ( fipid == "1" ) { strncpy(result.fid, "00000", OFX_FID_LENGTH - 1); strncpy(result.org, "ReferenceFI", OFX_ORG_LENGTH - 1); strncpy(result.url, "http://ofx.innovision.com", OFX_URL_LENGTH - 1); result.accountlist = 1; result.statements = 1; result.billpay = 1; result.investments = 1; return result; } string url = "http://moneycentral.msn.com/money/2005/mnynet/service/olsvcupd/OnlSvcBrandInfo.aspx?MSNGUID=&GUID=%1&SKU=3&VER=6"; url.replace(url.find("%1"), 2, fipid); // TODO: Check whether this file exists and is recent enough before getting it again string guidfile = "fipid-%1.xml"; guidfile.replace(guidfile.find("%1"), 2, fipid); struct stat filestats; if ( stat( guidfile.c_str(), &filestats ) || difftime(time(0), filestats.st_mtime) > 7.0 * 24.0 * 60.0 * 60.0 ) post("", url.c_str(), guidfile.c_str()); // Print the FI details xmlpp::DomParser parser; parser.set_substitute_entities(); parser.parse_file(guidfile); if ( parser ) { NodeParser nodes(parser); strncpy(result.fid, nodes.Path("ProviderSettings/FID").Text().back().c_str(), OFX_FID_LENGTH - 1); strncpy(result.org, nodes.Path("ProviderSettings/Org").Text().back().c_str(), OFX_ORG_LENGTH - 1); strncpy(result.url, nodes.Path("ProviderSettings/ProviderURL").Text().back().c_str(), OFX_URL_LENGTH - 1); result.accountlist = (nodes.Path("ProviderSettings/AcctListAvail").Text().back() == "1"); result.statements = (nodes.Path("BankingCapabilities/Bank").Text().back() == "1"); result.billpay = (nodes.Path("BillPayCapabilities/Pay").Text().back() == "1"); result.investments = (nodes.Path("InvestmentCapabilities/BrkStmt").Text().back() == "1"); } return result; } bool post(const string& request, const string& url, const string& filename) { #if 1 //#ifdef HAVE_LIBCURL CURL *curl = curl_easy_init(); if (! curl) return false; remove(filename.c_str()); FILE* file = fopen(filename.c_str(), "wb"); if (! file ) { curl_easy_cleanup(curl); return false; } curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); if ( request.length() ) curl_easy_setopt(curl, CURLOPT_POSTFIELDS, request.c_str()); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fwrite); curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)file); /*CURLcode res =*/ curl_easy_perform(curl); curl_easy_cleanup(curl); fclose(file); return true; #else request; url; filename; cerr << "ERROR: libox must be configured with libcurl to post this request" << endl; return false; #endif } } // namespace OfxPartner // vim:cin:si:ai:et:ts=2:sw=2: