Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

Internet Explorer AdBlock

, 17 Jan 2008 GPL3
Internet Explorer AdBlock Add-on
ieadblock_src.zip
IE AdBlockPS
IE AdBlockps.def
IE AdBlock
AdBlockBand.rgs
AdBlockBHO.rgs
bin
XListCtrlSSDU.lib
XListCtrlSSRU.lib
IE AdBlock.def
IE AdBlock.rgs
res
bmpToolbar.bmp
checkboxes.bmp
icoSettings.ico
XListCtrl
checkboxes.bmp
//*********************************************************************
// INCLUDES
//*********************************************************************

#include "stdafx.h"
#include "AdList.h"

//*********************************************************************
// CONSTRUCTOR & DESTRUCTOR
//*********************************************************************

CAdList::CAdList()
{
	// Initialize
	m_bKeepSorted = false;
	m_arrPatterns.SetSize(0, 32);
	m_arrRegularExpressions.SetSize(0, 32);
}

//=====================================================================

CAdList::~CAdList()
{
	// Delete all items
	DeleteAllItems();
}

//*********************************************************************
// PUBLIC FUNCTIONS
//*********************************************************************

bool CAdList::Load(CMarkup & xml, bool bResetCurrentList /* = true */)
{
	// Declare variables
	bool bSortAutomatically = true;
	CString sContent = _T(""), sType = _T(""), sElementType = _T("");
	bool bListed = false;
	int iRequestCount = 0;

	// Check if we should reset current list
	if (bResetCurrentList)
	{
		// Delete all items
		DeleteAllItems();
	}

	// Disable sorting for performance reasons
	bSortAutomatically = m_bKeepSorted;
	m_bKeepSorted = false;

	// While we can find items
	while (xml.FindElem(_T("item")))
	{
		// Get attributes
		sContent = StringLower(xml.GetAttrib(_T("content")));
		sType = StringLower(xml.GetAttrib(_T("type")));

		// Check if we have a valid content value
		if (sContent != _T(""))
		{
			// Check what type the regular expression is of
			if (sType == LISTTYPE_PATTERN)
			{
				AddPattern(sContent);
			}

			if (sType == LISTTYPE_REGULAREXPRESSION)
			{
				AddRegularExpression(sContent);
			}

			if (sType == LISTTYPE_CACHE)
			{
				// Get additional attributes
				sElementType = xml.GetAttrib(_T("elemtype"));
				bListed = (StringLower(xml.GetAttrib(_T("listed"))) == _T("true")) ? true : false;
				iRequestCount = _tstoi(StringLower(xml.GetAttrib(_T("requestcount"))));

				// Add item to cache
				AddItemToCache(sContent, sElementType, bListed, iRequestCount);
			}
		}
	}

	// Enable sorting again
	m_bKeepSorted = bSortAutomatically;

	// Should we sort automatically?
	if (m_bKeepSorted)
	{
		SortListAlphabetically();
	}

	// We successfully read the list
	return true;
}

//=====================================================================

bool CAdList::Store(CMarkup & xml)
{
	// Store patterns
	if (!StoreList(xml, &m_arrPatterns, LISTTYPE_PATTERN))
	{
		return false;
	}

	// Store regular expressions
	if (!StoreList(xml, &m_arrRegularExpressions, LISTTYPE_REGULAREXPRESSION))
	{
		return false;
	}

	// Store cache
	CacheObject object;
	int iCount = (int)m_arrCache.size();
	for (int i = 0; i < iCount; i++)
	{
		// Get object
		object = m_arrCache[i];

		// Add item element
		xml.AddElem(_T("item"));
		xml.AddAttrib(_T("content"), object.sURL);
		xml.AddAttrib(_T("type"), LISTTYPE_CACHE);
		xml.AddAttrib(_T("elemtype"), object.sElementType);
		xml.AddAttrib(_T("listed"), (object.bListed) ? _T("true") : _T("false"));
		xml.AddAttrib(_T("requestcount"), object.iRequestCount);
	}

	// If we get here, we are successful
	return true;
}

//=====================================================================

bool CAdList::Matches(CString sURL, CString sElementType)
{
	// Make all lowercase
	sURL = StringLower(sURL);
	sElementType = StringLower(sElementType);
	int iCount = 0;
	CacheObject object;

	// First check the cache (for frequently visited websites)
	iCount = (int)m_arrCache.size();
	for (int i = 0; i < iCount; i++)
	{
		// Get object
		object = m_arrCache[i];

		// Compare object
		if ((object.sURL == sURL) && (object.sElementType == sElementType))
		{
			// Cache item used
			IncreaseCacheUsage(i);

			// Return if object is listed
			return object.bListed;
		}
	}

	// Check patterns
	if (MatchesList(&m_arrPatterns, &m_mapPatterns, sURL, sElementType))
	{
		// Add item to cache
		AddItemToCache(sURL, sElementType, true, 1);

		// Matches one of the patterns, return true
		return true;
	}

	// Check regular expressions
	if (CSettings::Instance()->GetEnableRegularExpressions())
	{
		if (MatchesList(&m_arrRegularExpressions, &m_mapRegularExpressions, sURL, sElementType))
		{
			// Add item to cache
			AddItemToCache(sURL, sElementType, true, 1);

			// Matches one of the regular expressions, return true
			return true;
		}
	}

	// Add item to cache
	AddItemToCache(sURL, sElementType, false, 1);

	// Not listed
	return false;
}

//=====================================================================

void CAdList::ClearCache()
{
	// Remove cache
	m_arrCache.clear();
}
//=====================================================================

void CAdList::SortCache()
{
	// Declare variables
	bool bStart = true;
	CacheObject object;
	int iCount = 0;

	// Check if we have valid items
	if (m_arrCache.size() <= 0)
	{
		// Exit function
		return;
	}

	// Sort by using bubble sort mechanism
	iCount = (int)m_arrCache.size();
    for (int i = 1; (i <= iCount) && bStart; i++)
	{
		bStart = false;
		for (int j = 0; j < (iCount - 1); j++)
		{
			if (m_arrCache[j + 1].iRequestCount > m_arrCache[j].iRequestCount)
			{
				object = m_arrCache[j];
				m_arrCache[j] = m_arrCache[j + 1];
				m_arrCache[j + 1] = object;
				bStart = true;
			}
		}
	}
}

//=====================================================================

int CAdList::GetCachedItemsCount()
{
	// Return the cache size
	return (int)m_arrCache.size();
}

//=====================================================================

void CAdList::DeleteAllItems()
{
	// Remove all items
	DeleteAllPatterns();
	DeleteAllRegularExpressions();
}

//=====================================================================

void CAdList::DeleteAllPatterns()
{
	// Remove all patterns
	m_arrPatterns.RemoveAll();
	m_mapPatterns.RemoveAll();
}

//=====================================================================

void CAdList::DeleteAllRegularExpressions()
{
	// Remove all regular expressions
	m_arrRegularExpressions.RemoveAll();
	m_mapRegularExpressions.RemoveAll();
}

//=====================================================================

void CAdList::AddPattern(CString sPattern)
{
	// Add
	AddItem(&m_arrPatterns, &m_mapPatterns, sPattern);
}

//=====================================================================

void CAdList::ModifyPattern(int index, CString sPattern)
{
	// Modify
	ModifyItem(&m_arrPatterns, &m_mapPatterns, index, sPattern);
}

//=====================================================================

void CAdList::RemovePattern(int index)
{
	// Remove
	RemoveItem(&m_arrPatterns, &m_mapPatterns, index);
}

//=====================================================================

void CAdList::AddRegularExpression(CString sRegularExpression)
{
	// Add
	AddItem(&m_arrRegularExpressions, &m_mapRegularExpressions, sRegularExpression);
}

//=====================================================================

void CAdList::ModifyRegularExpression(int index, CString sRegularExpression)
{
	// Modify
	ModifyItem(&m_arrRegularExpressions, &m_mapRegularExpressions, index, sRegularExpression);
}

//=====================================================================

void CAdList::RemoveRegularExpression(int index)
{
	// Remove
	RemoveItem(&m_arrRegularExpressions, &m_mapRegularExpressions, index);
}

//=====================================================================

int CAdList::GetPatternCount()
{
	// Return count
	return (int)m_arrPatterns.GetCount();
}

//=====================================================================

CString CAdList::GetPattern(int index)
{
	// Return item
	return GetItem(&m_arrPatterns, index);
}

//=====================================================================

int CAdList::GetRegularExpressionCount()
{
	// Return count
	return (int)m_arrRegularExpressions.GetCount();
}

//=====================================================================

CString CAdList::GetRegularExpression(int index)
{
	// Return item
	return GetItem(&m_arrRegularExpressions, index);
}

//=====================================================================

void CAdList::SortListAlphabetically()
{
	// Sort patterns
	SortListAlphabeticallyInternal(&m_arrPatterns, &m_mapPatterns);

	// Sort regular expressions
	SortListAlphabeticallyInternal(&m_arrRegularExpressions, &m_mapRegularExpressions);
}

//=====================================================================

bool CAdList::GetKeepSorted()
{
	return m_bKeepSorted;
}

//=====================================================================

void CAdList::SetKeepSorted(bool bEnable)
{
	// Declare variables
	bool bWasSorted = m_bKeepSorted;

	// Now store new value
	m_bKeepSorted = bEnable;

	// Should we sort automatically?
	if (bEnable && !bWasSorted)
	{
		// Yes, sort automatically
		SortListAlphabetically();
	}
}

//*********************************************************************
// PRIVATE FUNCTIONS
//*********************************************************************

bool CAdList::StoreList(CMarkup & xml, CStringArray * pStringArray, CString sType)
{
	// Declare variables
	int iCount = 0;

	// Check if we have valid items
	if (pStringArray == NULL)
	{
		// Exit function
		return false;
	}

	// Loop all items
	iCount = (int)pStringArray->GetCount();
	for (int i = 0; i < iCount; i++)
	{
		// Add item element
		xml.AddElem(_T("ITEM"));
		xml.AddAttrib(_T("content"), (*pStringArray)[i]);
		xml.AddAttrib(_T("type"), sType);
	}

	// Succeeded
	return true;
}

//=====================================================================

bool CAdList::MatchesList(CStringArray * pStringArray, CMapStringToString * pMap,
						  CString sURL, CString sElementType)
{
	// Declare variables
	CString sPattern = _T("");
	int iCount = 0;

	// Check all items in array
	iCount = (int)pStringArray->GetCount();
	for (int i = 0; i < iCount; i++)
	{
		// Clean pattern
		sPattern = CleanPattern((*pStringArray)[i]);

		// Do we have a valid pattern?
		if (!sPattern.IsEmpty())
		{
			// Do we have a valid element type?
			if (!sElementType.IsEmpty())
			{
				// Check if the element type matches this pattern
				if (CompareElements(sElementType, sPattern))
				{
					// Listed, return true
					return true;
				}
			}

			// Check if we still have a valid url
			if (!sURL.IsEmpty())
			{
				// Compare the url's
				if (CompareElements(sURL, sPattern))
				{
					// Listed, return true
					return true;
				}
			}
		}
	}

	// Not listed
	return false;
}

//=====================================================================

void CAdList::AddItemToCache(CString sURL, CString sElementType, bool bListed,
							 int iRequestCount)
{
	// Declare variables
	CacheObject object;
	int iCount = 0, iRequestCountToDelete = 5;

	// Is the url empty?
	if (sURL.IsEmpty())
	{
		// Yes, exit function
		return;
	}

	// Prepare new object
	object.sURL = sURL;
	object.sElementType = sElementType;
	object.bListed = bListed;
	object.iRequestCount = iRequestCount;

	// No, are we allowed to add?
	if ((int)m_arrCache.size() >= CSettings::Instance()->GetCacheSize())
	{
		// No, remove all items with a requestion count lower than 5
		while ((int)m_arrCache.size() >= CSettings::Instance()->GetCacheSize() - 50)
		{
			// Increase count to delete
			iRequestCountToDelete++;

			// Remove all last items
			while ((int)m_arrCache.size() > 0)
			{
				// Get iterator
				vector<CacheObject>::iterator i = m_arrCache.end() - 1;

				// Check if we can remove current last item
				if (i->iRequestCount < iRequestCountToDelete)
				{
					// Remove cache object
					m_arrCache.erase(i);
				}
				else
				{
					// Quit current loop
					break;
				}
			}
		}
	}

	// Add to cache
	m_arrCache.push_back(object);
}

//=====================================================================

void CAdList::IncreaseCacheUsage(int iExistingCacheLocation)
{
	// Declare variables
	CacheObject object;

	// Get object from index
	object = m_arrCache[iExistingCacheLocation];

	// Increase the request counter
	object.iRequestCount++;

	// Add item again
	m_arrCache[iExistingCacheLocation] = object;
}

//=====================================================================

void CAdList::AddItem(CStringArray * pStringArray, CMapStringToString * pMap,
					  CString sContent)
{
	// Declare variables
	CString sTemp = _T("");
	int index = 0;

	// Check if we have valid items
	if ((pStringArray == NULL) || (pMap == NULL))
	{
		// Exit function
		return;
	}

	// Make lowercase
	sContent = StringLower(sContent);

	// Check if item is not empty
	if (sContent.IsEmpty())
	{
		// Exit function
		return;
	}

	// Look up value in the map
	if (pMap->Lookup(sContent, sTemp))
	{
		// Item already exists, exit function
		return;		
	}

	// Add item
	index = (int)pStringArray->Add(sContent);
	sTemp.Format(_T("%d"), index);
	(*pMap)[sContent] = sTemp;

	// Should we sort automatically?
	if (m_bKeepSorted)
	{
		SortListAlphabeticallyInternal(pStringArray, pMap);
	}
}

//=====================================================================

void CAdList::ModifyItem(CStringArray * pStringArray, CMapStringToString * pMap,
						 int index, CString sContent)
{
	// Declare variables
	CString sTemp = _T("");

	// Check if we have valid items
	if ((pStringArray == NULL) || (pMap == NULL))
	{
		// Exit function
		return;
	}

	// Check if value is between boundaries
	if ((index >= 0) && (index < pStringArray->GetCount()))
	{
		// Modify item
		pMap->RemoveKey((*pStringArray)[index]);
		pStringArray->SetAt(index, sContent);
		sTemp.Format(_T("%d"), index);
		(*pMap)[sContent] = sTemp;
	}

	// Should we sort automatically?
	if (m_bKeepSorted)
	{
		SortListAlphabeticallyInternal(pStringArray, pMap);
	}
}

//=====================================================================

void CAdList::RemoveItem(CStringArray * pStringArray, CMapStringToString * pMap, int index)
{
	// Check if we have valid items
	if ((pStringArray == NULL) || (pMap == NULL))
	{
		// Exit function
		return;
	}

	// Check if value is between boundaries
	if ((index >= 0) && (index < pStringArray->GetCount()))
	{
		// Remove item
		pMap->RemoveKey((*pStringArray)[index]);
		pStringArray->RemoveAt(index);
	}
}

//=====================================================================

CString CAdList::GetItem(CStringArray * pStringArray, int index)
{
	// Check if we have valid items
	if (pStringArray == NULL)
	{
		// Exit function
		return _T("");
	}

	// Check if value is between boundaries
	if ((index >= 0) && (index < pStringArray->GetCount()))
	{
		return (*pStringArray)[index];
	}

	// Return empty element
	return _T("");
}

//=====================================================================

void CAdList::SortListAlphabeticallyInternal(CStringArray * pStringArray, 
											 CMapStringToString * pMap)
{
	// Declare variables
	bool bStart = true;
	CString sTemp = _T("");
	int iCount = 0;

	// Check if we have valid items
	if ((pStringArray == NULL) || (pMap == NULL))
	{
		// Exit function
		return;
	}

	// Sort by using bubble sort mechanism
	iCount = (int)pStringArray->GetCount();
    for (int i = 1; (i <= iCount) && bStart; i++)
	{
		bStart = false;
		for (int j = 0; j < (iCount - 1); j++)
		{
			if ((*pStringArray)[j + 1].CompareNoCase((*pStringArray)[j]) < 0)
			{ 
				sTemp = (*pStringArray)[j];
				(*pStringArray)[j] = (*pStringArray)[j+1];
				(*pStringArray)[j + 1] = sTemp;
				bStart = true;
			}
		}
	}

	// Now create a full map
	pMap->RemoveAll();

	// Loop all items
	for (int i = 0; i < iCount; i++)
	{
		sTemp.Format(_T("%d"), i);
		(*pMap)[(*pStringArray)[i]] = sTemp;
	}
}

//=====================================================================

bool CAdList::CompareElements(CString sElement, CString sElementWithMask)
{	
	// Add * if no | is used
	if (sElementWithMask.GetAt(0) != _T('|'))
	{
		// Check if a * is added before url
		if (sElementWithMask.GetAt(0) != _T('*'))
		{
			// Add * before url
			sElementWithMask.Insert(0, _T("*"));
		}		
	}
	else
	{
		// Remove | for comparision
		sElementWithMask.Delete(0);
	}

	// Add * if no | is used
	if (sElementWithMask.GetAt(sElementWithMask.GetLength() - 1) != _T('|'))
	{
		// Check if a * is added after url
		if (sElementWithMask.GetAt(sElementWithMask.GetLength() - 1) != _T('*'))
		{
			// Add * after url
			sElementWithMask.Insert(sElementWithMask.GetLength(), _T("*"));
		}
	}
	else
	{
		// Remove | for comparision
		sElementWithMask.Delete(sElementWithMask.GetLength() - 1);
	}

	// Compare urls
	return CompareWildCards(sElement, sElementWithMask, _T(""));
}

//=====================================================================

CString CAdList::CleanPattern(CString sPattern)
{
	// Declare variables
	int iPos = -1;

	// Strip all specific elements
	/*iPos = sPattern.Find(_T('#'));
	if (iPos != -1)
	{
		// Remove all from pos
		sPattern.Delete(iPos, sPattern.GetLength() - iPos);
	}*/

	// Strip all options
	iPos = sPattern.Find(_T('$'));
	if (iPos != -1)
	{
		// Remove all from pos
		sPattern.Delete(iPos, sPattern.GetLength() - iPos);
	}

	// Return the pattern
	return sPattern;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)

Share

About the Author

Geert van Horrik
Software Developer CatenaLogic
Netherlands Netherlands
I am Geert van Horrik, and I have studied Computer Science in the Netherlands.
 
I love to write software using .NET (especially the combination of WPF and C#). I am also the lead developer of Catel, an open-source application development framework for WPF, Silverlight, WP7 and WinRT with the focus on MVVM.
 
I have my own company since January 1st 2007, called CatenaLogic. This company develops commercial and non-commercial software.
 
To download (or buy) applications I have written, visit my website: http://www.catenalogic.com
Follow on   Twitter

| Advertise | Privacy | Mobile
Web02 | 2.8.141022.2 | Last Updated 17 Jan 2008
Article Copyright 2008 by Geert van Horrik
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid