Added Files:
knnewdelete.cpp knrcommon.cpp knregistration.cpp
knrfiltermanager.cpp knrproceduremanager.cpp
knrredirectmanager.cpp kntclapi.cpp
Log Message:
knregistration adds the ability to register procedures, filters, and indirects based on patterns in URIs. Matched portions of these URIs are added to the ns_conn "form" before delivery to the procedure, filter, or indirect request. Requires the knutil library.
--- NEW FILE: knnewdelete.cpp ---
/**
* (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#define KNMODULE knregistration
#include "knutil/knnewdelete.h"
--- NEW FILE: knrcommon.cpp ---
/**
* (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#include "knexportlibraryknregistrationmodule.h"
#include "knrcommon.h"
bool addQueryToConn(KnSet& toAdd, Ns_Conn* conn)
{
if(toAdd.size() == 0)
return false;
Ns_Set* query;
query = Ns_ConnGetQuery(conn);
if (query != NULL)
{
for(int i = 0; i < toAdd.size(); i++)
{
Ns_SetUpdate(query, (char*)toAdd[i].m_key.c_str(), (char*)toAdd[i].m_value.c_str());
}
return true;
}
return false;
}
bool removeQueryFromConn(KnSet& toRemove, Ns_Conn* conn)
{
if(toRemove.size() == 0)
return false;
Ns_Set* query;
query = Ns_ConnGetQuery(conn);
if (query != NULL)
{
for(int i = 0; i < toRemove.size(); i++)
{
Ns_SetDeleteKey(query, (char*)toRemove[i].m_key.c_str());
}
return true;
}
return false;
}
--- NEW FILE: knregistration.cpp ---
/**
* (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#include <vector>
#include <list>
#include <map>
#include "knutil/knlog.h"
#include "knutil/knset.h"
#include "knutil/kntemplateuri.h"
#include "knexportlibraryknregistrationmodule.h"
#include "knregistration.h"
#include "knrfiltermanager.h"
#include "knrproceduremanager.h"
#include "knrredirectmanager.h"
#include "kntclapi.h"
static KnRFilterManager g_filterManager;
static KnRProcedureManager g_procManager;
static KnRRedirectManager g_redirectManager;
static const char* HttpMethods[] = { "GET", "HEAD", "PUT", "DELETE", "POST", "SUBSCRIBE"};
static const int HttpMethodsCount = 6;
int KnFilterRegistered(void* context, Ns_Conn* conn, int why)
{
// redirect
if(why == NS_FILTER_PRE_AUTH)
{
int result = g_redirectManager.redirect(context, conn);
if(result != NS_OK)
return result;
}
// filters
int result = g_filterManager.runFilters(context, conn, why);
if(result == NS_FILTER_RETURN)
return result;
// procedures
if(why == NS_FILTER_POST_AUTH)
{
return g_procManager.runProcedures(context, conn);
}
return result;
}
void KnRegisterProc(const char* server, const char* method, bool inheritable, const char* urlTemplate, KnRegisteredProc* proc, void* context)
{
if(strcmp(method,"*") != 0)
g_procManager.registerProc(new KnCRProcedureHandler(server,method,urlTemplate,inheritable,proc,context));
else
{
for(int i = 0; i < HttpMethodsCount; i++)
g_procManager.registerProc(new KnCRProcedureHandler(server,HttpMethods[i],urlTemplate,inheritable,proc,context));
}
}
void KnRegisterTclProc(const char* server, const char* method, bool inheritable, const char* urlTemplate, const char* proc ,const char* args)
{
if(strcmp(method,"*") != 0)
g_procManager.registerProc(new KnTclRProcedureHandler(server,method,urlTemplate,inheritable,proc,args));
else
{
for(int i = 0; i < HttpMethodsCount; i++)
g_procManager.registerProc(new KnTclRProcedureHandler(server,HttpMethods[i],urlTemplate,inheritable,proc,args));
}
}
void KnRegisterFilter(const char* server, const char* method, int why, const char* urlTemplate, KnRegisteredFilter* proc, void* context)
{
if(strcmp(method,"*") != 0)
g_filterManager.registerFilter(new KnCRFilterHandler(server,method,why,urlTemplate,proc,context));
else
{
for(int i = 0; i < HttpMethodsCount; i++)
g_filterManager.registerFilter(new KnCRFilterHandler(server,HttpMethods[i],why,urlTemplate,proc,context));
}
}
void KnRegisterTclFilter(const char* server, const char* method, int why, const char* urlTemplate, const char* proc, const char* args)
{
if(strcmp(method,"*") != 0)
g_filterManager.registerFilter(new KnTclRFilterHandler(server,method,why,urlTemplate,proc,args));
else
{
for(int i = 0; i < HttpMethodsCount; i++)
g_filterManager.registerFilter(new KnTclRFilterHandler(server,HttpMethods[i],why,urlTemplate,proc,args));
}
}
void KnRegisterRedirect(bool internal, const char* method, const char* urlTemplateFrom, const char* urlTemplateTo)
{
if(strcmp(method,"*") != 0)
g_redirectManager.addRedirect(new KnRRedirectInfo(internal, method, urlTemplateFrom, urlTemplateTo));
else
{
for(int i = 0; i < HttpMethodsCount; i++)
g_redirectManager.addRedirect(new KnRRedirectInfo(internal, HttpMethods[i], urlTemplateFrom, urlTemplateTo));
}
}
bool KnUnregisterProc(const char* server, const char* method, bool inheritable, const char* urlTemplate)
{
if(strcmp(method,"*") != 0)
return g_procManager.removeProcedure(server,method,inheritable,urlTemplate);
for(int i = 0; i < HttpMethodsCount; i++)
g_procManager.removeProcedure(server,HttpMethods[i],inheritable,urlTemplate);
return true;
}
bool KnUnregisterFilter(const char* server, const char* method, int why, const char* urlTemplate)
{
if(strcmp(method,"*") != 0)
return g_filterManager.removeFilter(server,method,why,urlTemplate);
for(int i = 0; i < HttpMethodsCount; i++)
return g_filterManager.removeFilter(server,HttpMethods[i],why,urlTemplate);
return true;
}
bool KnUnregisterRedirect(const char* method, const char* urlTemplateFrom)
{
if(strcmp(method,"*") != 0)
return g_redirectManager.removeRedirect(method, urlTemplateFrom);
for(int i = 0; i < HttpMethodsCount; i++)
return g_redirectManager.removeRedirect(HttpMethods[i], urlTemplateFrom);
return true;
}
extern "C"
{
EXPORT_LIBRARY_KNREGISTRATION int NsRegistration_ModuleInit(char *hServer, char *hModule)
{
KnLog(KnLogNotice, "knregistration: starting");
KnLog(KnLogNotice, "knregistration: build date: %s %s", __DATE__, __TIME__);
char filter_path[1024];
Ns_Set* config = NULL;
const char* nsp;
if ((nsp = Ns_ConfigGetPath(hServer, hModule, NULL)) == 0
|| (config = Ns_ConfigGetSection(const_cast<CONST char*>(nsp))) == 0)
{
KnLog(KnLogError, "knregistration: could not parse configuration");
return NS_ERROR;
}
KnString urlfilter;
urlfilter += "/*";
Ns_RegisterFilter(
hServer,
"*",
const_cast<char*>(urlfilter.c_str()),
KnFilterRegistered,
NS_FILTER_POST_AUTH | NS_FILTER_PRE_AUTH | NS_FILTER_TRACE
,NULL
);
// Export TCL commands
if (NS_OK != Ns_TclInitInterps(hServer, KnRegister_TclCommands::AddCmds, NULL))
{
KnLog( KnLogError, "knregistration: Couldn't add kn_ TCL commands to server '%s'", hServer);
return NS_ERROR;
}
KnLog(KnLogNotice, "knregistration: ready");
return NS_OK;
}
}
--- NEW FILE: knrfiltermanager.cpp ---
/**
* (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#include "knexportlibraryknregistrationmodule.h"
#include "knrcommon.h"
#include "knrfiltermanager.h"
/* ------------------------------------------------------------------------- */
/* IKnRFilterHandler */
/* ------------------------------------------------------------------------- */
IKnRFilterHandler::IKnRFilterHandler(const char* server, const char* method, int why, const char* urlTemplate)
: m_server(server),m_method(method),m_why(why),m_urlTemplate(urlTemplate)
{
}
IKnRFilterHandler::~IKnRFilterHandler()
{
}
std::string IKnRFilterHandler::getID()
{
return m_server+':'+m_method+':'+(char)('a'+m_why);
}
std::string IKnRFilterHandler::getID(const char* server, const char* method, int why)
{
std::string result = server;
result += ":";
result += method;
result += ":";
result += (char)('a'+why);
return result;
}
/* ------------------------------------------------------------------------- */
/* KnCRFilterHandler */
/* ------------------------------------------------------------------------- */
KnCRFilterHandler::KnCRFilterHandler(const char* server, const char* method, int why, const char* urlTemplate, KnRegisteredFilter* proc, void* context)
: IKnRFilterHandler(server,method,why,urlTemplate),m_proc(proc),m_context(context)
{
}
int KnCRFilterHandler::handle(void *context, Ns_Conn *conn, int why)
{
return (*m_proc)(context,conn,why);
}
/* ------------------------------------------------------------------------- */
/* KnTclRFilterHandler */
/* ------------------------------------------------------------------------- */
KnTclRFilterHandler::KnTclRFilterHandler(const char* server, const char* method, int why, const char* urlTemplate, const char* proc, const char* args)
: IKnRFilterHandler(server,method,why,urlTemplate),m_proc(proc),m_args(args)
{
}
int KnTclRFilterHandler::handle(void *context, Ns_Conn *conn, int why)
{
std::string& command = m_proc;
command += " ";
command += m_args;
Tcl_Interp* interp = Ns_GetConnInterp(conn);
int status = Tcl_EvalEx(interp, const_cast<char*>(command.c_str()),command.length(),TCL_EVAL_DIRECT);
if (status != TCL_OK)
{
KnLog(KnLogError,"knregistration: Couldn't evaluate '%s': %s",command.c_str(), Tcl_GetStringResult(interp));
Ns_TclLogError(interp);
return NS_ERROR;
}
Tcl_Obj* result = Tcl_GetObjResult(interp);
if(result == TCL_OK)
{
int filterresult = NS_OK;
Tcl_GetIntFromObj(interp,result,&filterresult);
return filterresult;
}
return NS_ERROR;
}
/* ------------------------------------------------------------------------- */
/* KnRFilterManager */
/* ------------------------------------------------------------------------- */
void KnRFilterManager::registerFilter(IKnRFilterHandler* fh)
{
FinderType::ScopedWriteable sw(m_filterFinder);
KnString name(fh->m_urlTemplate.c_str());
m_filterFinder.put(
fh->getID(),
new KnTemplateURI(name, KnString(fh->m_urlTemplate.c_str())),
fh);
}
bool KnRFilterManager::removeFilter(const char* server, const char* method, int why, const char* urlTemplate)
{
FinderType::ScopedWriteable sw(m_filterFinder);
std::string id = IKnRFilterHandler::getID(server,method,why);
KnString name(urlTemplate);
return m_filterFinder.removeByName(id, name);
}
int KnRFilterManager::runFilters(void *context, Ns_Conn *conn, int why)
{
if(!m_filterFinder.size())
return NS_OK;
int ret = NS_OK;
std::string method = conn->request->method;
std::string url = conn->request->url;
std::string server = Ns_ConnServer(conn);
std::string id = IKnRFilterHandler::getID(server.c_str(),method.c_str(),why);
KNREGDBG(KnLog(KnLogDev,"ReC: knregistration: Looking for filter for url '%s' in set '%s'", url.c_str(), id.c_str()));
ResultType result;
{
FinderType::ScopedReadable sr(m_filterFinder);
if(! m_filterFinder.findAllMatchesSubs(id, url.c_str(), result))
return NS_OK;
}
KNREGDBG(KnLog(KnLogDev,"ReC: knregistration: Found %d filters that matched '%s'",
result.size(), url.c_str()));
bool added;
KnSet* matched;
int i;
for(i = 0; i < result.size(); i++)
{
matched = result[i].first;
if (KNREGDBG(KnLog(KnLogDev,"ReC: knregistration: Calling filter with set:")))
{
matched->dump(KnString("ReC: knregistration: "));
}
added = addQueryToConn(*matched, conn);
int filterresult = result[i].second->handle(context, conn, why);
if(added)
removeQueryFromConn(*matched, conn);
if((filterresult == NS_FILTER_BREAK)||(filterresult == NS_FILTER_RETURN))
{
ret = filterresult;
break;
}
}
for(i = 0 ; i < result.size() ; i++)
{
matched = result[i].first;
SAFE_DELETE(matched);
}
return ret;
}
--- NEW FILE: knrproceduremanager.cpp ---
/**
* (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#include "knexportlibraryknregistrationmodule.h"
#include "knrcommon.h"
#include "knrproceduremanager.h"
/* ------------------------------------------------------------------------- */
/* IKnRProcedureHandler */
/* ------------------------------------------------------------------------- */
IKnRProcedureHandler::IKnRProcedureHandler(const char* server, const char* method, const char* urlTemplate, bool inheritable)
: m_server(server),m_method(method),m_urlTemplate(urlTemplate),m_inheritable(inheritable)
{
}
IKnRProcedureHandler::~IKnRProcedureHandler()
{
}
bool IKnRProcedureHandler::isInheritable()
{
return m_inheritable;
}
std::string IKnRProcedureHandler::getID()
{
return m_server+':'+m_method;
}
std::string IKnRProcedureHandler::getID(const char* server, const char* method)
{
std::string result = server;
result += ":";
result += method;
return result;
}
/* ------------------------------------------------------------------------- */
/* KnRProcedureInfo */
/* ------------------------------------------------------------------------- */
KnRProcedureInfo::KnRProcedureInfo()
{
m_inheritable = NULL;
m_exact = NULL;
}
KnRProcedureInfo::KnRProcedureInfo(IKnRProcedureHandler* ph)
{
m_inheritable = NULL;
m_exact = NULL;
set(ph);
}
KnRProcedureInfo::~KnRProcedureInfo()
{
SAFE_DELETE(m_inheritable);
SAFE_DELETE(m_exact);
}
bool KnRProcedureInfo::hasInheritable()
{
return m_inheritable != NULL;
}
bool KnRProcedureInfo::hasExact()
{
return m_exact != NULL;
}
bool KnRProcedureInfo::removeHandler(bool inheritable)
{
if(inheritable && hasInheritable())
{
SAFE_DELETE(m_inheritable);
return true;
}
if(!inheritable && hasExact())
{
SAFE_DELETE(m_exact);
return true;
}
return false;
}
int KnRProcedureInfo::handle(void* context, Ns_Conn* conn)
{
return m_exact->handle(context,conn);
}
int KnRProcedureInfo::handleInheritable(void* context, Ns_Conn* conn)
{
return m_inheritable->handle(context,conn);
}
void KnRProcedureInfo::set(IKnRProcedureHandler* ph)
{
if(ph->isInheritable())
{
SAFE_DELETE(m_inheritable);
m_inheritable = ph;
}else
{
SAFE_DELETE(m_exact);
m_exact = ph;
}
}
/* ------------------------------------------------------------------------- */
/* KnCRProcedureHandler */
/* ------------------------------------------------------------------------- */
KnCRProcedureHandler::KnCRProcedureHandler(const char* server, const char* method, const char* urlTemplate, bool inheritable, KnRegisteredProc* proc, void* context)
: IKnRProcedureHandler( server, method, urlTemplate,inheritable)
{
m_proc = proc;
m_context = context;
}
int KnCRProcedureHandler::handle(void* context, Ns_Conn* conn)
{
return (*m_proc)(context,conn);
}
/* ------------------------------------------------------------------------- */
/* KnTclRProcedureHandler */
/* ------------------------------------------------------------------------- */
KnTclRProcedureHandler::KnTclRProcedureHandler(const char* server, const char* method, const char* urlTemplate, bool inheritable, const char* proc, const char* args)
: IKnRProcedureHandler(server,method,urlTemplate,inheritable)
{
m_proc = proc;
m_args = args;
}
int KnTclRProcedureHandler::handle(void* context, Ns_Conn* conn)
{
Tcl_Interp *interp = Ns_GetConnInterp(conn);
int result;
std::string command;
command += m_proc;
int id = Ns_ConnId(conn);
char buffer[30];
sprintf(buffer,"cns%d",id);
command += ' ';
command += buffer;
command += m_args;
result = Tcl_EvalEx(interp, (char*)command.c_str(), command.size(), 0);
if (result != TCL_OK)
{
Ns_TclLogError(interp);
if (Ns_ConnResetReturn(conn) == NS_OK)
return Ns_ConnReturnInternalError(conn);
return NS_OK;
}
return NS_OK;
}
/* ------------------------------------------------------------------------- */
/* KnRProcedureManager */
/* ------------------------------------------------------------------------- */
void KnRProcedureManager::registerProc(IKnRProcedureHandler* ph)
{
FinderType::ScopedWriteable sw(m_procFinder);
std::string id = ph->getID();
KnString name(ph->m_urlTemplate.c_str());
KnSmartRef<KnTemplateURI> temp;
KnSmartRef<KnRProcedureInfo> info;
if(m_procFinder.findByName(id, name, temp, info))
info->set(ph);
else
{
m_procFinder.put(
id,
new KnTemplateURI(name, KnString(ph->m_urlTemplate.c_str())),
new KnRProcedureInfo(ph)
);
}
}
bool KnRProcedureManager::removeProcedure(const char* server, const char* method, bool inheritable, const char* urlTemplate)
{
FinderType::ScopedWriteable sw(m_procFinder);
std::string id = IKnRProcedureHandler::getID(server,method);
KnString name(urlTemplate);
KnSmartRef<KnTemplateURI> temp;
KnSmartRef<KnRProcedureInfo> info;
if(m_procFinder.findByName(id, name, temp, info))
{
if(info->removeHandler(inheritable))
{
if(!(info->hasExact() || info->hasInheritable()))
return m_procFinder.removeByName(id, name);
return true;
}
}
return false;
}
int KnRProcedureManager::runProcedures(void* context, Ns_Conn* conn)
{
if(!m_procFinder.size())
return NS_OK;
int ret = NS_OK; // respond as a filter
std::string method = conn->request->method;
std::string url = conn->request->url;
std::string server = Ns_ConnServer(conn);
std::string id = IKnRProcedureHandler::getID(server.c_str(),method.c_str());
KNREGDBG(KnLog(KnLogDev,"ReC: knregistration: Looking for procedure for url '%s' in set '%s'", url.c_str(), id.c_str()));
ResultType result;
{
FinderType::ScopedReadable sr(m_procFinder);
if(! m_procFinder.findAllMatchesSubs(id, url.c_str(), result))
return ret;
}
KNREGDBG(KnLog(KnLogDev,"ReC: knregistration: %d candidates for url '%s'", result.size(), url.c_str()));
KnSet* matched;
int exactPos;
bool hasExact = false;
for(exactPos = 0; exactPos < result.size(); exactPos++)
{
if(result[exactPos].second->hasExact())
{
hasExact = true;
break;
}
}
bool added;
int i;
if(hasExact)
{
for(i = result.size()-1 ; i > exactPos; i--)
{
if(!result[i].second->hasInheritable())
continue;
matched = result[i].first;
if (KNREGDBG(KnLog(KnLogDev,"ReC: knregistration: calling inherited procedure using set:")))
{
matched->dump(KnString("ReC: knregistration: "));
}
added = addQueryToConn(*matched, conn);
result[i].second->handleInheritable(context, conn);
if(added)
removeQueryFromConn(*matched, conn);
}
matched = result[exactPos].first;
if (KNREGDBG(KnLog(KnLogDev,"ReC: knregistration: calling exact-match procedure using set:")))
{
matched->dump(KnString("ReC: knregistration: "));
}
added = addQueryToConn(*matched, conn);
result[exactPos].second->handle(context, conn);
ret = NS_FILTER_RETURN;
if(added)
removeQueryFromConn(*matched, conn);
}else
{
for(i = result.size()-1 ; i >= 0; i--)
{
if(!result[i].second->hasInheritable())
continue;
matched = result[i].first;
if (KNREGDBG(KnLog(KnLogDev,"ReC: knregistration: calling inherited procedure using set:")))
{
matched->dump(KnString("ReC: knregistration: "));
}
added = addQueryToConn(*matched, conn);
result[i].second->handleInheritable(context, conn);
if(added)
removeQueryFromConn(*matched, conn);
}
}
for(i = 0 ; i < result.size() ; i++)
{
matched = result[i].first;
SAFE_DELETE(matched);
}
return ret;
}
--- NEW FILE: knrredirectmanager.cpp ---
/**
* (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#include "knexportlibraryknregistrationmodule.h"
#include "knrcommon.h"
#include "knrredirectmanager.h"
/* ------------------------------------------------------------------------- */
/* Utility */
/* ------------------------------------------------------------------------- */
void createExternalRedirectUrl(Ns_Conn* conn, const std::string& toUrl, std::string& url)
{
url = "";
if(toUrl[0] == '/')
{
Ns_DString ds;
Ns_DStringInit(&ds);
char* location = Ns_ConnLocation(conn, &ds);
if(location)
url += location;
Ns_DStringFree(&ds);
}
url += toUrl;
}
/* ------------------------------------------------------------------------- */
/* KnRRedirectInfo */
/* ------------------------------------------------------------------------- */
KnRRedirectInfo::KnRRedirectInfo(bool internal, const char* method, const char* urlTemplateFrom, const char* urlTemplateTo)
:m_internal(internal),m_method(method),m_urlTemplateFrom(urlTemplateFrom),m_urlTemplateTo(urlTemplateTo)
{
}
/* ------------------------------------------------------------------------- */
/* KnRRedirectManager */
/* ------------------------------------------------------------------------- */
KnRRedirectManager::KnRRedirectManager()
{
}
KnRRedirectManager::~KnRRedirectManager()
{
}
void KnRRedirectManager::addRedirect(KnRRedirectInfo* ri)
{
FinderType::ScopedWriteable sw(m_redirectFinder);
KnString name;
name.printf("%s%s",ri->m_method.c_str(), ri->m_urlTemplateFrom.c_str());
KnTemplateURI* tempuri = new KnTemplateURI(name, KnString(ri->m_urlTemplateFrom.c_str()));
m_redirectFinder.put(ri->m_method, tempuri, ri);
}
bool KnRRedirectManager::removeRedirect(const char* method, const char* urlTemplateFrom)
{
FinderType::ScopedWriteable sw(m_redirectFinder);
KnString name;
std::string m = method;
name.printf("%s%s",method, urlTemplateFrom);
return m_redirectFinder.removeByName(m, name);
}
int KnRRedirectManager::redirect(void* context, Ns_Conn* conn)
{
if(!m_redirectFinder.size())
return NS_OK;
KnSet matched;
std::string url = (conn->request->url? conn->request->url : "");
std::string method = conn->request->method;
KnSmartRef<KnTemplateURI> pattern;
KnSmartRef<KnRRedirectInfo> ri;
std::string newUrl;
{
FinderType::ScopedReadable sr(m_redirectFinder);
bool found = m_redirectFinder.findBestMatchSubs(method, url.c_str(), matched, pattern, ri);
if(!found)
return NS_OK;
}
//KnLog(KnLogDebug,"Chose pattern [%s] for redirecting url [%s] from pattern list:",ri->m_urlTemplateFrom.c_str(), url.c_str());
//m_redirectFinder.dump(method, KnLogDebug);
std::string redirectTo;
bool valid = KnTemplateURI::replaceInto(matched, ri->m_urlTemplateTo.c_str(), redirectTo, true);
if(!valid)
{
KnLog(KnLogNotice, "Invalid redirect translation from [%s] to [%s]", ri->m_urlTemplateFrom.c_str(), ri->m_urlTemplateTo.c_str());
return NS_OK;
}
newUrl = redirectTo;
if(ri->m_internal)
{
addQueryToConn(matched, conn);
// Url rewrite
Ns_ConnRedirect(conn, (char*)newUrl.c_str());
}else
{
createExternalRedirectUrl(conn, redirectTo, newUrl);
addQueryToConn(matched, conn);
// External redirect
Ns_ConnReturnRedirect(conn, (char*)newUrl.c_str());
}
return NS_FILTER_RETURN;
}
--- NEW FILE: kntclapi.cpp ---
/**
* (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA
*
* @KNOWNOW_LICENSE_START@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not
* be used to endorse or promote any product without prior written
* permission from KnowNow, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @KNOWNOW_LICENSE_END@
**/
#include "knutil/knstring.h"
#include "knutil/knset.h"
#include "knutil/knstringtokenizer.h"
#include "knutil/kntclinterp.h"
#include "knutil/kntclerrors.h"
#include "knexportlibraryknregistrationmodule.h"
#include "knregistration.h"
namespace KnRegister_TclCommands
{
extern "C"
{
int
kn_registerproc (
void * context,
Tcl_Interp* interp,
int objc,
Tcl_Obj * objv[])
{
if (objc < 4)
{
KnTcl_WrongNumArgs(interp,3,objv,"string");
return TCL_ERROR;
}
bool inheritable = false;
int index = 1;
char* elem = (Tcl_GetString(objv[index]));
if(strcasecmp(elem,"-noinherit") == 0)
{
index++;
inheritable = false;
}else
if(strcasecmp(elem,"-inherit") == 0)
{
index++;
inheritable = true;
}
char* method(Tcl_GetString(objv[index++]));
char* url(Tcl_GetString(objv[index++]));
char* proc(Tcl_GetString(objv[index++]));
std::string args;
for(int i = index; i < objc; i++)
{
args += " {";
args += Tcl_GetString(objv[i]);
args += "}";
}
KnRegisterTclProc(Ns_TclInterpServer(interp), method, inheritable, url, proc, args.c_str());
return TCL_OK;
}
int
kn_registerfilter (
void * context,
Tcl_Interp* interp,
int objc,
Tcl_Obj * objv[])
{
if (objc < 5)
{
KnTcl_WrongNumArgs(interp,4,objv,"string");
return TCL_ERROR;
}
int index = 1;
char* server = Ns_TclInterpServer(interp);
char* type(Tcl_GetString(objv[index++]));
char* method(Tcl_GetString(objv[index++]));
char* url(Tcl_GetString(objv[index++]));
char* proc(Tcl_GetString(objv[index++]));
std::string args;
for(int i = 5; i < objc; i++)
{
args += " {";
args += Tcl_GetString(objv[i]);
args += "}";
}
int filterType;
if(strcasecmp(type,"-preauth") == 0)
filterType = NS_FILTER_PRE_AUTH;
else
if(strcasecmp(type,"-postauth") == 0)
filterType = NS_FILTER_POST_AUTH;
else
if(strcasecmp(type,"-trace") == 0)
filterType = NS_FILTER_TRACE;
else
{
Tcl_AppendResult(interp,"500 Unknown type for filter: '",type,"'",0);
return TCL_ERROR;
}
KnRegisterTclFilter(server, method, filterType, url, proc, args.c_str());
return TCL_OK;
}
int
kn_registerredirect (
void * context,
Tcl_Interp* interp,
int objc,
Tcl_Obj * objv[])
{
if (objc < 5)
{
KnTcl_WrongNumArgs(interp,4,objv,"string");
return TCL_ERROR;
}
int index = 1;
char* type(Tcl_GetString(objv[index++]));
char* method(Tcl_GetString(objv[index++]));
char* template1(Tcl_GetString(objv[index++]));
char* template2(Tcl_GetString(objv[index++]));
if(strcasecmp(type,"-internal") == 0)
KnRegisterRedirect(true, method, template1, template2);
else
if(strcasecmp(type,"-external") == 0)
KnRegisterRedirect(false, method, template1, template2);
else
{
Tcl_AppendResult(interp,"500 Unknown type of redirect: '",type,"'",0);
return TCL_ERROR;
}
return TCL_OK;
}
int
kn_unregister (
void * context,
Tcl_Interp* interp,
int objc,
Tcl_Obj * objv[])
{
if (objc < 4)
{
KnTcl_WrongNumArgs(interp,1,objv,"string");
return TCL_ERROR;
}
char* type(Tcl_GetString(objv[1]));
bool success;
if(strcasecmp(type,"-redirect") == 0)
{
char* method(Tcl_GetString(objv[2]));
char* from(Tcl_GetString(objv[3]));
success = KnUnregisterRedirect(method,from);
}
else
if(strcasecmp(type,"-filter") == 0)
{
char* why(Tcl_GetString(objv[4]));
char* method(Tcl_GetString(objv[2]));
char* temp(Tcl_GetString(objv[3]));
success = KnUnregisterFilter(Ns_TclInterpServer(interp),method,atoi(why),temp);
}
else
if(strcasecmp(type,"-proc") == 0)
{
char* what(Tcl_GetString(objv[4]));
char* method(Tcl_GetString(objv[2]));
char* temp(Tcl_GetString(objv[3]));
bool inheritable = true;
if(strcasecmp(what,"-noinherit"))
inheritable = false;
success = KnUnregisterProc(Ns_TclInterpServer(interp),method,inheritable,temp);
}
else
{
Tcl_AppendResult(interp,"500 Unknown type of unregister: '",type,"'",0);
return TCL_ERROR;
}
Tcl_Obj *result = Tcl_NewBooleanObj(success);
Tcl_SetObjResult(interp,result);
return TCL_OK ;
}
} // extern "C"
int AddCmds(Tcl_Interp *nsInterp, void *context)
{
Tcl_CreateObjCommand(nsInterp,
"kn_registerproc", kn_registerproc, context, NULL);
Tcl_CreateObjCommand(nsInterp,
"kn_registerfilter", kn_registerfilter, context, NULL);
Tcl_CreateObjCommand(nsInterp,
"kn_registerredirect", kn_registerredirect, context, NULL);
Tcl_CreateObjCommand(nsInterp,
"kn_unregister", kn_unregister, context, NULL);
return 0;
}
}
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
aolserver-commits mailing list
aolserve...@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/aolserver-commits