#ifdef WIN32
# define _CRT_NONSTDC_NO_DEPRECATE 1
# define _CRT_SECURE_NO_DEPRECATE 1
+# define NOMINMAX
# define SHIBODBC_EXPORTS __declspec(dllexport)
#else
# define SHIBODBC_EXPORTS
#endif
-#include <shib/shib-threads.h>
#include <shib-target/shib-target.h>
#include <log4cpp/Category.hh>
+#include <xmltooling/util/NDC.h>
+#include <ctime>
+#include <algorithm>
#include <sstream>
#include <sql.h>
#include <dmalloc.h>
#endif
-using namespace std;
-using namespace saml;
-using namespace shibboleth;
using namespace shibtarget;
+using namespace shibboleth;
+using namespace saml;
+using namespace xmltooling;
using namespace log4cpp;
+using namespace std;
#define PLUGIN_VER_MAJOR 3
#define PLUGIN_VER_MINOR 0
#define COLSIZE_APPLICATION_ID 256
#define COLSIZE_ADDRESS 128
#define COLSIZE_PROVIDER_ID 256
-#define LONGDATA_BUFLEN 2048
+#define LONGDATA_BUFLEN 32768
/*
CREATE TABLE state (
SQLHDBC getHDBC();
- log4cpp::Category* log;
+ Category* log;
protected:
- //ThreadKey* m_mysql;
const DOMElement* m_root; // can only use this during initialization
string m_connstring;
static SQLHENV m_henv; // single handle for both plugins
bool m_bInitializedODBC; // tracks which class handled the process
+ static const char* p_connstring;
pair<int,int> getVersion(SQLHDBC);
void log_error(SQLHANDLE handle, SQLSMALLINT htype);
};
SQLHENV ODBCBase::m_henv = SQL_NULL_HANDLE;
-
-/*
-extern "C" void shib_mysql_destroy_handle(void* data)
-{
- MYSQL* mysql = (MYSQL*) data;
- if (mysql) mysql_close(mysql);
-}
-*/
+const char* ODBCBase::p_connstring = NULL;
ODBCBase::ODBCBase(const DOMElement* e) : m_root(e), m_bInitializedODBC(false)
{
#ifdef _DEBUG
- saml::NDC ndc("ODBCBase");
+ xmltooling::NDC ndc("ODBCBase");
#endif
- log = &(Category::getInstance("shibtarget.SessionCache.ODBC"));
- //m_mysql = ThreadKey::create(&shib_mysql_destroy_handle);
-
- if (m_henv != SQL_NULL_HANDLE) {
- log->info("ODBC already initialized");
- return;
- }
+ log = &(Category::getInstance("shibtarget.ODBC"));
- // Enable connection pooling.
- SQLSetEnvAttr(SQL_NULL_HANDLE, SQL_ATTR_CONNECTION_POOLING, (void*)SQL_CP_ONE_PER_HENV, 0);
+ if (m_henv == SQL_NULL_HANDLE) {
+ // Enable connection pooling.
+ SQLSetEnvAttr(SQL_NULL_HANDLE, SQL_ATTR_CONNECTION_POOLING, (void*)SQL_CP_ONE_PER_HENV, 0);
- // Allocate the environment.
- if (!SQL_SUCCEEDED(SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &m_henv)))
- throw ConfigurationException("ODBC failed to initialize.");
+ // Allocate the environment.
+ if (!SQL_SUCCEEDED(SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &m_henv)))
+ throw ConfigurationException("ODBC failed to initialize.");
- // Specify ODBC 3.x
- SQLSetEnvAttr(m_henv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
+ // Specify ODBC 3.x
+ SQLSetEnvAttr(m_henv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
- log->info("ODBC initialized");
- m_bInitializedODBC = true;
+ log->info("ODBC initialized");
+ m_bInitializedODBC = true;
+ }
// Grab connection string from the configuration.
e=saml::XML::getFirstChildElement(e,shibtarget::XML::SHIBTARGET_NS,ConnectionString);
if (!e || !e->hasChildNodes()) {
- this->~ODBCBase();
- throw ConfigurationException("ODBC cache requires ConnectionString element in configuration.");
+ if (!p_connstring) {
+ this->~ODBCBase();
+ throw ConfigurationException("ODBC cache requires ConnectionString element in configuration.");
+ }
+ m_connstring=p_connstring;
+ }
+ else {
+ xmltooling::auto_ptr_char arg(e->getFirstChild()->getNodeValue());
+ m_connstring=arg.get();
+ p_connstring=m_connstring.c_str();
}
- auto_ptr_char arg(e->getFirstChild()->getNodeValue());
- m_connstring=arg.get();
// Connect and check version.
SQLHDBC conn=getHDBC();
//delete m_mysql;
if (m_bInitializedODBC)
SQLFreeHandle(SQL_HANDLE_ENV,m_henv);
+ m_bInitializedODBC=false;
m_henv = SQL_NULL_HANDLE;
+ p_connstring=NULL;
}
void ODBCBase::log_error(SQLHANDLE handle, SQLSMALLINT htype)
SQLHDBC ODBCBase::getHDBC()
{
#ifdef _DEBUG
- saml::NDC ndc("getMYSQL");
+ xmltooling::NDC ndc("getMYSQL");
#endif
// Get a handle.
SQLBindCol(hstmt,2,SQL_C_SLONG,&minor,0,NULL);
if ((sr=SQLFetch(hstmt)) != SQL_NO_DATA) {
- SQLCloseCursor(hstmt);
SQLFreeHandle(SQL_HANDLE_STMT,hstmt);
return pair<int,int>(major,minor);
}
- SQLCloseCursor(hstmt);
SQLFreeHandle(SQL_HANDLE_STMT,hstmt);
log->error("no rows returned in version query");
throw SAMLException("ODBCBase::getVersion failed to read version from database");
private:
bool m_storeAttributes;
ISessionCache* m_cache;
- CondWait* shutdown_wait;
+ xmltooling::CondWait* shutdown_wait;
bool shutdown;
- Thread* cleanup_thread;
+ xmltooling::Thread* cleanup_thread;
static void* cleanup_fcn(void*); // XXX Assumed an ODBCCCache
};
ODBCCCache::ODBCCCache(const DOMElement* e) : ODBCBase(e), m_storeAttributes(false)
{
#ifdef _DEBUG
- saml::NDC ndc("ODBCCCache");
+ xmltooling::NDC ndc("ODBCCCache");
#endif
+ log = &(Category::getInstance("shibtarget.SessionCache.ODBC"));
m_cache = dynamic_cast<ISessionCache*>(
SAMLConfig::getConfig().getPlugMgr().newPlugin(shibtarget::XML::MemorySessionCacheType, m_root)
delete m_cache;
}
+void appendXML(ostream& os, const char* str)
+{
+ const char* pos=strchr(str,'\'');
+ while (pos) {
+ os.write(str,pos-str);
+ os << "''";
+ str=pos+1;
+ pos=strchr(str,'\'');
+ }
+ os << str;
+}
+
HRESULT ODBCCCache::onCreate(
const char* key,
const IApplication* application,
)
{
#ifdef _DEBUG
- saml::NDC ndc("onCreate");
+ xmltooling::NDC ndc("onCreate");
#endif
// Get XML data from entry. Default is not to return SAML objects.
ostringstream q;
q << "INSERT state VALUES ('" << key << "','" << application->getId() << "'," << timebuf << "," << timebuf
<< ",'" << entry->getClientAddress() << "'," << majorVersion << "," << minorVersion << ",'" << entry->getProviderId()
- << "',?,?,?)";
-
+ << "','";
+ appendXML(q,subject.first);
+ q << "','";
+ appendXML(q,context);
+ q << "',";
+ if (m_storeAttributes && tokens.first) {
+ q << "'";
+ appendXML(q,tokens.first);
+ q << "')";
+ }
+ else
+ q << "null)";
if (log->isDebugEnabled())
log->debug("SQL insert: %s", q.str().c_str());
ODBCConn conn(getHDBC());
SQLAllocHandle(SQL_HANDLE_STMT,conn,&hstmt);
- // Bind text parameters to statement.
- SQLINTEGER cbSubject=SQL_LEN_DATA_AT_EXEC(0),cbContext=SQL_LEN_DATA_AT_EXEC(0),cbTokens;
- if (!m_storeAttributes || !tokens.first)
- cbTokens=SQL_NULL_DATA;
- else
- cbTokens=SQL_LEN_DATA_AT_EXEC(0);
- SQLRETURN sr=SQLBindParameter(hstmt,1,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_LONGVARCHAR,LONGDATA_BUFLEN,0,(SQLPOINTER)subject.first,0,&cbSubject);
- if (!SQL_SUCCEEDED(sr))
- log_error(hstmt, SQL_HANDLE_STMT);
- sr=SQLBindParameter(hstmt,2,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_LONGVARCHAR,LONGDATA_BUFLEN,0,(SQLPOINTER)context,0,&cbContext);
- if (!SQL_SUCCEEDED(sr))
- log_error(hstmt, SQL_HANDLE_STMT);
- sr=SQLBindParameter(hstmt,3,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_LONGVARCHAR,LONGDATA_BUFLEN,0,(SQLPOINTER)tokens.first,0,&cbTokens);
- if (!SQL_SUCCEEDED(sr))
- log_error(hstmt, SQL_HANDLE_STMT);
-
// Execute statement.
- sr=SQLExecDirect(hstmt, (SQLCHAR*)q.str().c_str(), SQL_NTS);
- if (sr==SQL_NEED_DATA) {
- // Loop to send text data into driver.
- // pData is set each round by the driver to the pointers we bound above.
- char* pData;
- sr=SQLParamData(hstmt,(SQLPOINTER*)&pData);
- while (sr==SQL_NEED_DATA) {
- size_t len=strlen(pData);
- while (len>0) {
- size_t amt = min(LONGDATA_BUFLEN,len);
- SQLPutData(hstmt, pData, amt);
- pData += amt;
- len = len - amt;
- }
- sr=SQLParamData(hstmt,(SQLPOINTER*)&pData);
- }
- }
-
HRESULT hr=NOERROR;
+ SQLRETURN sr=SQLExecDirect(hstmt, (SQLCHAR*)q.str().c_str(), SQL_NTS);
if (!SQL_SUCCEEDED(sr)) {
log->error("failed to insert record into database");
log_error(hstmt, SQL_HANDLE_STMT);
hr=E_FAIL;
}
- SQLCloseCursor(hstmt);
SQLFreeHandle(SQL_HANDLE_STMT,hstmt);
return hr;
}
)
{
#ifdef _DEBUG
- saml::NDC ndc("onRead");
+ xmltooling::NDC ndc("onRead");
#endif
log->debug("searching database...");
if (!SQL_SUCCEEDED(sr)) {
log->error("error searching for (%s)",key);
log_error(hstmt, SQL_HANDLE_STMT);
- SQLCloseCursor(hstmt);
SQLFreeHandle(SQL_HANDLE_STMT,hstmt);
return E_FAIL;
}
SQLBindCol(hstmt,7,SQL_C_CHAR,provider_id,sizeof(provider_id),NULL);
if ((sr=SQLFetch(hstmt)) == SQL_NO_DATA) {
- SQLCloseCursor(hstmt);
SQLFreeHandle(SQL_HANDLE_STMT,hstmt);
return S_FALSE;
}
}
}
- SQLCloseCursor(hstmt);
SQLFreeHandle(SQL_HANDLE_STMT,hstmt);
return hr;
}
HRESULT ODBCCCache::onRead(const char* key, time_t& accessed)
{
#ifdef _DEBUG
- saml::NDC ndc("onRead");
+ xmltooling::NDC ndc("onRead");
#endif
log->debug("reading last access time from database");
if (!SQL_SUCCEEDED(sr)) {
log->error("error searching for (%s)",key);
log_error(hstmt, SQL_HANDLE_STMT);
- SQLCloseCursor(hstmt);
SQLFreeHandle(SQL_HANDLE_STMT,hstmt);
return E_FAIL;
}
if ((sr=SQLFetch(hstmt)) == SQL_NO_DATA) {
log->warn("session expected, but not found in database");
- SQLCloseCursor(hstmt);
SQLFreeHandle(SQL_HANDLE_STMT,hstmt);
return S_FALSE;
}
- SQLCloseCursor(hstmt);
SQLFreeHandle(SQL_HANDLE_STMT,hstmt);
struct tm t;
HRESULT ODBCCCache::onRead(const char* key, string& tokens)
{
#ifdef _DEBUG
- saml::NDC ndc("onRead");
+ xmltooling::NDC ndc("onRead");
#endif
if (!m_storeAttributes)
if (!SQL_SUCCEEDED(sr)) {
log->error("error searching for (%s)",key);
log_error(hstmt, SQL_HANDLE_STMT);
- SQLCloseCursor(hstmt);
SQLFreeHandle(SQL_HANDLE_STMT,hstmt);
return E_FAIL;
}
if ((sr=SQLFetch(hstmt)) == SQL_NO_DATA) {
log->warn("session expected, but not found in database");
- SQLCloseCursor(hstmt);
SQLFreeHandle(SQL_HANDLE_STMT,hstmt);
return S_FALSE;
}
tokens += (char*)buf;
}
- SQLCloseCursor(hstmt);
SQLFreeHandle(SQL_HANDLE_STMT,hstmt);
return hr;
}
HRESULT ODBCCCache::onUpdate(const char* key, const char* tokens, time_t lastAccess)
{
#ifdef _DEBUG
- saml::NDC ndc("onUpdate");
+ xmltooling::NDC ndc("onUpdate");
#endif
- SQLRETURN sr;
- SQLHSTMT hstmt;
- ODBCConn conn(getHDBC());
+ ostringstream q;
if (lastAccess>0) {
#ifndef HAVE_GMTIME_R
char timebuf[32];
strftime(timebuf,32,"{ts '%Y-%m-%d %H:%M:%S'}",ptime);
- ostringstream q;
q << "UPDATE state SET atime=" << timebuf << " WHERE cookie='" << key << "'";
-
- SQLAllocHandle(SQL_HANDLE_STMT,conn,&hstmt);
- sr=SQLExecDirect(hstmt, (SQLCHAR*)q.str().c_str(), SQL_NTS);
}
else if (tokens) {
if (!m_storeAttributes)
return S_FALSE;
- string q = string("UPDATE state SET tokens=? WHERE cookie='") + key + "'";
-
- SQLAllocHandle(SQL_HANDLE_STMT,conn,&hstmt);
-
- // Bind text parameters to statement.
- SQLINTEGER cbTokens = tokens ? SQL_LEN_DATA_AT_EXEC(0) : SQL_NULL_DATA;
- sr=SQLBindParameter(hstmt,1,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_LONGVARCHAR,LONGDATA_BUFLEN,0,(SQLPOINTER)tokens,0,&cbTokens);
-
- // Execute statement.
- sr=SQLExecDirect(hstmt, (SQLCHAR*)q.c_str(), SQL_NTS);
- if (sr==SQL_NEED_DATA) {
- // Loop to send text data into driver.
- // pData is set each round by the driver to the pointers we bound above.
- char* pData;
- sr=SQLParamData(hstmt,(SQLPOINTER*)&pData);
- while (sr==SQL_NEED_DATA) {
- size_t len=strlen(pData);
- while (len>0) {
- size_t amt=min(LONGDATA_BUFLEN,len);
- SQLPutData(hstmt, pData, amt);
- pData += amt;
- len = len - amt;
- }
- sr=SQLParamData(hstmt,(SQLPOINTER*)&pData);
- }
- }
+ q << "UPDATE state SET tokens=";
+ if (*tokens) {
+ q << "'";
+ appendXML(q,tokens);
+ q << "' ";
+ }
+ else
+ q << "null ";
+ q << "WHERE cookie='" << key << "'";
}
else {
log->warn("onUpdate called with nothing to do!");
return S_FALSE;
}
- HRESULT hr;
+ HRESULT hr=NOERROR;
+ SQLHSTMT hstmt;
+ ODBCConn conn(getHDBC());
+ SQLAllocHandle(SQL_HANDLE_STMT,conn,&hstmt);
+ SQLRETURN sr=SQLExecDirect(hstmt, (SQLCHAR*)q.str().c_str(), SQL_NTS);
if (sr==SQL_NO_DATA)
hr=S_FALSE;
else if (!SQL_SUCCEEDED(sr)) {
log_error(hstmt, SQL_HANDLE_STMT);
hr=E_FAIL;
}
- else
- hr=NOERROR;
- SQLCloseCursor(hstmt);
SQLFreeHandle(SQL_HANDLE_STMT,hstmt);
return hr;
}
HRESULT ODBCCCache::onDelete(const char* key)
{
#ifdef _DEBUG
- saml::NDC ndc("onDelete");
+ xmltooling::NDC ndc("onDelete");
#endif
SQLHSTMT hstmt;
string q = string("DELETE FROM state WHERE cookie='") + key + "'";
SQLRETURN sr=SQLExecDirect(hstmt, (SQLCHAR*)q.c_str(), SQL_NTS);
- HRESULT hr;
+ HRESULT hr=NOERROR;
if (sr==SQL_NO_DATA)
hr=S_FALSE;
else if (!SQL_SUCCEEDED(sr)) {
log_error(hstmt, SQL_HANDLE_STMT);
hr=E_FAIL;
}
- else
- hr=NOERROR;
- SQLCloseCursor(hstmt);
SQLFreeHandle(SQL_HANDLE_STMT,hstmt);
return hr;
}
void ODBCCCache::cleanup()
{
#ifdef _DEBUG
- saml::NDC ndc("cleanup");
+ xmltooling::NDC ndc("cleanup");
#endif
- Mutex* mutex = Mutex::create();
+ Mutex* mutex = xmltooling::Mutex::create();
int rerun_timer = 0;
int timeout_life = 0;
if (SQL_SUCCEEDED(sr) && rowcount > 0)
log->info("purging %d old sessions",rowcount);
- SQLCloseCursor(hstmt);
SQLFreeHandle(SQL_HANDLE_STMT,hstmt);
}
mutex->unlock();
delete mutex;
- Thread::exit(NULL);
+ xmltooling::Thread::exit(NULL);
}
void* ODBCCCache::cleanup_fcn(void* cache_p)
{
ODBCCCache* cache = (ODBCCCache*)cache_p;
+#ifndef WIN32
// First, let's block all signals
Thread::mask_all_signals();
+#endif
// Now run the cleanup process.
cache->cleanup();
return NULL;
}
-/*
-class MySQLReplayCache : public MySQLBase, virtual public IReplayCache
+
+class ODBCReplayCache : public ODBCBase, virtual public IReplayCache
{
public:
- MySQLReplayCache(const DOMElement* e);
- virtual ~MySQLReplayCache() {}
+ ODBCReplayCache(const DOMElement* e);
+ virtual ~ODBCReplayCache() {}
- bool check(const XMLCh* str, time_t expires) {auto_ptr_XMLCh temp(str); return check(temp.get(),expires);}
+ bool check(const XMLCh* str, time_t expires) {xmltooling::auto_ptr_XMLCh temp(str); return check(temp.get(),expires);}
bool check(const char* str, time_t expires);
};
-MySQLReplayCache::MySQLReplayCache(const DOMElement* e) : MySQLBase(e)
+ODBCReplayCache::ODBCReplayCache(const DOMElement* e) : ODBCBase(e)
{
#ifdef _DEBUG
- saml::NDC ndc("MySQLReplayCache");
+ saml::NDC ndc("ODBCReplayCache");
#endif
-
- log = &(Category::getInstance("shibmysql.ReplayCache"));
+ log = &(Category::getInstance("shibtarget.ReplayCache.ODBC"));
}
-bool MySQLReplayCache::check(const char* str, time_t expires)
+bool ODBCReplayCache::check(const char* str, time_t expires)
{
#ifdef _DEBUG
saml::NDC ndc("check");
#endif
- // Remove expired entries
- string q = string("DELETE FROM replay WHERE expires < NOW()");
- MYSQL* mysql = getMYSQL();
- if (mysql_query(mysql, q.c_str())) {
- const char* err=mysql_error(mysql);
- log->error("Error deleting expired entries: %s", err);
- if (isCorrupt(err) && repairTable(mysql,"replay")) {
- // Try again...
- if (mysql_query(mysql, q.c_str()))
- log->error("Error deleting expired entries: %s", mysql_error(mysql));
- }
+ time_t now=time(NULL);
+#ifndef HAVE_GMTIME_R
+ struct tm* ptime=gmtime(&now);
+#else
+ struct tm res;
+ struct tm* ptime=gmtime_r(&now,&res);
+#endif
+ char timebuf[32];
+ strftime(timebuf,32,"{ts '%Y-%m-%d %H:%M:%S'}",ptime);
+
+ // Remove expired entries.
+ SQLHSTMT hstmt;
+ ODBCConn conn(getHDBC());
+ SQLAllocHandle(SQL_HANDLE_STMT,conn,&hstmt);
+ string q = string("DELETE FROM replay WHERE expires < ") + timebuf;
+ SQLRETURN sr=SQLExecDirect(hstmt, (SQLCHAR*)q.c_str(), SQL_NTS);
+ if (sr!=SQL_NO_DATA && !SQL_SUCCEEDED(sr)) {
+ log->error("error purging old replay cache entries");
+ log_error(hstmt, SQL_HANDLE_STMT);
}
+ SQLCloseCursor(hstmt);
- string q2 = string("SELECT id FROM replay WHERE id='") + str + "'";
- if (mysql_query(mysql, q2.c_str())) {
- const char* err=mysql_error(mysql);
- log->error("Error searching for %s: %s", str, err);
- if (isCorrupt(err) && repairTable(mysql,"replay")) {
- if (mysql_query(mysql, q2.c_str())) {
- log->error("Error retrying search for %s: %s", str, mysql_error(mysql));
- throw SAMLException("Replay cache failed, please inform application support staff.");
- }
- }
- else
- throw SAMLException("Replay cache failed, please inform application support staff.");
+ // Look for a replay.
+ q = string("SELECT id FROM replay WHERE id='") + str + "'";
+ sr=SQLExecDirect(hstmt, (SQLCHAR*)q.c_str(), SQL_NTS);
+ if (!SQL_SUCCEEDED(sr)) {
+ log->error("error searching replay cache");
+ log_error(hstmt, SQL_HANDLE_STMT);
+ SQLFreeHandle(SQL_HANDLE_STMT,hstmt);
+ throw SAMLException("Replay cache failed, please inform application support staff.");
}
- // Did we find it?
- MYSQL_RES* rows = mysql_store_result(mysql);
- if (rows && mysql_num_rows(rows)>0) {
- mysql_free_result(rows);
- return false;
+ // If we got a record, we return false.
+ if ((sr=SQLFetch(hstmt)) != SQL_NO_DATA) {
+ SQLFreeHandle(SQL_HANDLE_STMT,hstmt);
+ return false;
}
+ SQLCloseCursor(hstmt);
+
+#ifndef HAVE_GMTIME_R
+ ptime=gmtime(&expires);
+#else
+ ptime=gmtime_r(&expires,&res);
+#endif
+ strftime(timebuf,32,"{ts '%Y-%m-%d %H:%M:%S'}",ptime);
- ostringstream q3;
- q3 << "INSERT INTO replay VALUES('" << str << "'," << "FROM_UNIXTIME(" << expires << "))";
-
- // then add it to the database
- if (mysql_query(mysql, q3.str().c_str())) {
- const char* err=mysql_error(mysql);
- log->error("Error inserting %s: %s", str, err);
- if (isCorrupt(err) && repairTable(mysql,"state")) {
- // Try again...
- if (mysql_query(mysql, q3.str().c_str())) {
- log->error("Error inserting %s: %s", str, mysql_error(mysql));
- throw SAMLException("Replay cache failed, please inform application support staff.");
- }
- }
- else
- throw SAMLException("Replay cache failed, please inform application support staff.");
+ // Add it to the database.
+ q = string("INSERT replay VALUES('") + str + "'," + timebuf + ")";
+ sr=SQLExecDirect(hstmt, (SQLCHAR*)q.c_str(), SQL_NTS);
+ if (!SQL_SUCCEEDED(sr)) {
+ log->error("error inserting replay cache entry", str);
+ log_error(hstmt, SQL_HANDLE_STMT);
+ SQLFreeHandle(SQL_HANDLE_STMT,hstmt);
+ throw SAMLException("Replay cache failed, please inform application support staff.");
}
-
+
+ SQLFreeHandle(SQL_HANDLE_STMT,hstmt);
return true;
}
-IPlugIn* new_mysql_replay(const DOMElement* e)
-{
- return new MySQLReplayCache(e);
-}
-*/
-/*************************************************************************
- * The registration functions here...
- */
+// Factories
IPlugIn* new_odbc_ccache(const DOMElement* e)
{
return new ODBCCCache(e);
}
+IPlugIn* new_odbc_replay(const DOMElement* e)
+{
+ return new ODBCReplayCache(e);
+}
+
extern "C" int SHIBODBC_EXPORTS saml_extension_init(void*)
{
// register this ccache type
-// SAMLConfig::getConfig().getPlugMgr().regFactory(shibtarget::XML::ODBCReplayCacheType, &new_odbc_replay);
+ SAMLConfig::getConfig().getPlugMgr().regFactory(shibtarget::XML::ODBCReplayCacheType, &new_odbc_replay);
SAMLConfig::getConfig().getPlugMgr().regFactory(shibtarget::XML::ODBCSessionCacheType, &new_odbc_ccache);
return 0;
}
extern "C" void SHIBODBC_EXPORTS saml_extension_term()
{
SAMLConfig::getConfig().getPlugMgr().unregFactory(shibtarget::XML::ODBCSessionCacheType);
-// SAMLConfig::getConfig().getPlugMgr().unregFactory(shibtarget::XML::ODBCReplayCacheType);
+ SAMLConfig::getConfig().getPlugMgr().unregFactory(shibtarget::XML::ODBCReplayCacheType);
}