Microsoft Chat Server Development Guide |
---|
// MessageFilter.cpp : Implementation of CMessageFilter
#include "stdafx.h"
#include "MsgFilter.h"
#include "MessageFilter.h"
// CHATSDK: Include the definition for the chat interface GUID
#include "..\inc\chatsvc_i.h"
/////////////////////////////////////////////////////////////////////////////
// CMessageFilter::IChatMsgFilter
//
// Retrieve a word from our list of filtered words
STDMETHODIMP CMessageFilter::get_Item(int index, BSTR * pVal)
{
if( index < m_FilteredWords.size() ) {
*pVal = SysAllocString(m_FilteredWords[index]) ;
return S_OK;
} else {
return E_INVALIDARG;
}
}
// Retrieve a count of our filtered words
STDMETHODIMP CMessageFilter::get_Count(int * pVal)
{
*pVal = m_FilteredWords.size();
return S_OK;
}
// Add a new word to our list of filtered words
STDMETHODIMP CMessageFilter::Add(BSTR Message)
{
// Store all words as lower case
for(wchar_t *p = Message; *p; p++)
*p = towlower(*p);
// Add the Message filter text to our list of filtered words
m_FilteredWords.push_back(Message);
return S_OK;
}
/////////////////////////////////////////////////////////////////////////////
// CMessageFilter::IChatExtensionCallBack Implementations
//
// All extensions need a short-name, as used by /extmsg and administration
STDMETHODIMP CMessageFilter::get_Name(BSTR *pbstrName)
{
*pbstrName = SysAllocString(L"MsgFilter");
return S_OK;
}
// Init is called to allow us to initialize and to receive a reference to the ChatRegistrar
STDMETHODIMP CMessageFilter::Init(IChatServer *pServer, IChatRegistrar* pRegistrar, long *Result)
{
// Maintain a reference to the chat registrar
m_pRegistrar = pRegistrar; // 'smart' pointer doesn't need to addref()
// Bind to the OnNewUser message, return Init() as OK if we bind OK
m_pRegistrar->AddServerEvent( (_bstr_t)L"OnNewChannel", Result);
// Add some default 4 letter words
Add((_bstr_t)L"CHAT");
Add((_bstr_t)L"WORK");
Add((_bstr_t)L"MAIL");
return S_OK;
}
// Allows the administration program (MMC) to query for the CLSID of any property pages we have
STDMETHODIMP CMessageFilter::OnGetPropertyPageClass(PPAGE Class, BSTR *pbstrCLSID)
{
// return the PROGID for our a component (in this case the extension object)
// that supports the ISpecifyPropertyPages that names our property pages
if( Class == PPAGE_SERVER ) {
*pbstrCLSID = SysAllocString(L"MessageFilter.MessageFilter.1");
}
return S_OK;
}
////////////////////////////////////////////////////////////////////////////
// CMessageFilter::IChatServerCallBack Implementations
//
// Notification that a new channel is/has been created
STDMETHODIMP CMessageFilter::OnNewChannel(IChatChannel *pChannel, VARIANT_BOOL varbPostUpdate, long *pCancel)
{
if( varbPostUpdate == VARIANT_TRUE ) {
// if we have a post-update to a new channel, bind to its OnChannelText events
m_pRegistrar->AddChannelEvent( (_bstr_t)L"OnChannelText", pChannel, pCancel);
}
*pCancel = 0; // don't cancel the event
return S_OK;
}
/////////////////////////////////////////////////////////////////////////////
// CMessageFilter::IChatChannelCallBack Implementations
//
// Notification that some text is/has been sent to a channel
STDMETHODIMP CMessageFilter::OnChannelText(IChatChannel *pChannel, IChatUser *pUser, IRCCMDTYPE Type, BSTR *Message, VARIANT_BOOL varbPostUpdate, long *pCancel)
{
if( varbPostUpdate == VARIANT_FALSE ) { // Pre-Update message, allows us to modify its intent
WORDLIST::iterator it;
bool badUser = false;
// Iterate though each word, checking for a substring match, change to *'s
for(it = m_FilteredWords.begin(); it != m_FilteredWords.end(); it++) {
wchar_t *p = *Message;
while( p && (p = wcsstr(p, it->m_str)) != NULL ) {
badUser = true;
for(wchar_t *q = it->m_str; *q; q++, p++)
*p = '*';
}
}
// Send a message to the user if we filtered any of their text
if( badUser )
{
WCHAR wszReply[128];
BSTR Nick;
BSTR Ident;
pUser->get_Nick(&Nick);
pUser->get_Identity(&Ident);
swprintf(wszReply, L"%s!%s PRIVMSG %s : You really should not use that language\r\n", Nick, Ident, Nick);
pUser->ProtocolMessageOut( (_bstr_t)wszReply);
SysFreeString(Nick);
SysFreeString(Ident);
}
}
*pCancel = 0;
return S_OK;
}
/////////////////////////////////////////////////////////////////////////////
// CMessageFilter::ISpecifyPropertyPages Implementation
// - you can copy this routine as-is for your pages
// Override the ISpecifyPropertyPages::GetPages with some 'cut-paste' code that returns
// the list of property pages as defined by the PROPERTY_MAP in the class .H
HRESULT CMessageFilter::ISpecifyPropertyPages_GetPages(CAUUID* pPages, ATL_PROPMAP_ENTRY* pMap)
{
int nCnt = 0;
// Get count of unique pages
for(int i = 0; pMap[i].pclsidPropPage != NULL; i++)
{
if (!InlineIsEqualGUID(*pMap[i].pclsidPropPage, CLSID_NULL))
nCnt++;
}
pPages->pElems = NULL;
pPages->pElems = (GUID*) CoTaskMemAlloc(sizeof(CLSID)*nCnt);
if (pPages->pElems == NULL)
return E_OUTOFMEMORY;
nCnt = 0;
for(i = 0; pMap[i].pclsidPropPage != NULL; i++) {
if (!InlineIsEqualGUID(*pMap[i].pclsidPropPage, CLSID_NULL)) {
BOOL bMatch = FALSE;
for (int j=0;j<nCnt;j++) {
if (InlineIsEqualGUID(*(pMap[i].pclsidPropPage), pPages->pElems[j])) {
bMatch = TRUE;
break;
}
}
if (!bMatch)
pPages->pElems[nCnt++] = *pMap[i].pclsidPropPage;
}
}
pPages->cElems = nCnt;
return S_OK;
}
© 1998 Microsoft Corporation. All rights reserved.