/*
 * YAMN plugin export functions for filtering
 *
 * (c) majvan 2002-2004
 */

#include "stdafx.h"

 //--------------------------------------------------------------------------------------------------
 //--------------------------------------------------------------------------------------------------

PYAMN_FILTERPLUGINQUEUE FirstFilterPlugin = nullptr;

INT_PTR RegisterFilterPluginSvc(WPARAM, LPARAM);

//Removes plugin from queue and deletes its structures
INT_PTR UnregisterFilterPlugin(HYAMNFILTERPLUGIN Plugin);

INT_PTR UnregisterFilterPluginSvc(WPARAM wParam, LPARAM lParam);

//Removes all filter plugins
INT_PTR UnregisterFilterPlugins();

INT_PTR FilterMailSvc(WPARAM, LPARAM);

//Sets imported functions for an plugin and therefore it starts plugin to be registered and running
// Plugin- plugin, which wants to set its functions
// Importance- importance of plugin (see m_filterplugin.h)
// YAMNFilterFcn- pointer to imported functions
// YAMNfilterFcnVer- version of YAMN_FILTERIMPORTFCN, use YAMN_FILTERIMPORTFCNVERSION
// returns nonzero if success
int WINAPI SetFilterPluginFcnImportFcn(HYAMNFILTERPLUGIN Plugin, uint32_t Importance, PYAMN_FILTERIMPORTFCN YAMNFilterFcn, uint32_t YAMNFilterFcnVer);

struct CExportedFunctions FilterPluginExportedFcn[] =
{
	{YAMN_SETFILTERPLUGINFCNIMPORTID, (void *)SetFilterPluginFcnImportFcn},
};

struct CExportedServices FilterPluginExportedSvc[] =
{
	{MS_YAMN_REGISTERFILTERPLUGIN, RegisterFilterPluginSvc},
	{MS_YAMN_UNREGISTERFILTERPLUGIN, UnregisterFilterPluginSvc},
};

//--------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------

INT_PTR RegisterFilterPluginSvc(WPARAM wParam, LPARAM lParam)
{
	PYAMN_FILTERREGISTRATION Registration = (PYAMN_FILTERREGISTRATION)wParam;
	HYAMNFILTERPLUGIN Plugin;

	if (lParam != YAMN_FILTERREGISTRATIONVERSION)
		return 0;
	if ((Registration->Name == nullptr) || (Registration->Ver == nullptr))
		return NULL;
	if (nullptr == (Plugin = new YAMN_FILTERPLUGIN))
		return NULL;

	Plugin->PluginInfo = Registration;
	Plugin->FilterFcn = nullptr;
	return (INT_PTR)Plugin;
}

INT_PTR UnregisterFilterPlugin(HYAMNFILTERPLUGIN Plugin)
{
	PYAMN_FILTERPLUGINQUEUE Parser, Found;

	if (FirstFilterPlugin->Plugin == Plugin) {
		Found = FirstFilterPlugin;
		FirstFilterPlugin = FirstFilterPlugin->Next;
	}
	else {
		for (Parser = FirstFilterPlugin; (Parser->Next != nullptr) && (Plugin != Parser->Next->Plugin); Parser = Parser->Next);
		if (Parser->Next != nullptr) {
			Found = Parser->Next;
			Parser->Next = Parser->Next->Next;
		}
		else
			Found = nullptr;
	}
	if (Found != nullptr) {
		if (Plugin->FilterFcn->UnLoadFcn != nullptr)
			Plugin->FilterFcn->UnLoadFcn((void *)nullptr);

		delete Found->Plugin;
		delete Found;
		return 1;
	}

	return 0;
}

INT_PTR UnregisterFilterPluginSvc(WPARAM wParam, LPARAM)
{
	HYAMNFILTERPLUGIN Plugin = (HYAMNFILTERPLUGIN)wParam;

	mir_cslock lck(PluginRegCS);
	UnregisterFilterPlugin(Plugin);
	return 1;
}

INT_PTR UnregisterFilterPlugins()
{
	mir_cslock lck(PluginRegCS);

	// We remove protocols from the protocol list
	while (FirstFilterPlugin != nullptr)
		UnregisterFilterPlugin(FirstFilterPlugin->Plugin);
	return 1;
}

int WINAPI SetFilterPluginFcnImportFcn(HYAMNFILTERPLUGIN Plugin, uint32_t Importance, PYAMN_FILTERIMPORTFCN YAMNFilterFcn, uint32_t YAMNFilterFcnVer)
{
	PYAMN_FILTERPLUGINQUEUE Parser, Previous;

	if (YAMNFilterFcnVer != YAMN_FILTERIMPORTFCNVERSION)
		return 0;
	if (YAMNFilterFcn == nullptr)
		return 0;

	Plugin->Importance = Importance;
	Plugin->FilterFcn = YAMNFilterFcn;

	mir_cslock lck(PluginRegCS);

	// We add protocol to the protocol list
	for (Previous = nullptr, Parser = FirstFilterPlugin; Parser != nullptr && Parser->Next != nullptr && Parser->Plugin->Importance <= Importance; Previous = Parser, Parser = Parser->Next);

	if (Previous == nullptr) { //insert to the beginnig of queue
		FirstFilterPlugin = new YAMN_FILTERPLUGINQUEUE;
		FirstFilterPlugin->Plugin = Plugin;
		FirstFilterPlugin->Next = Parser;
	}
	else {
		Previous->Next = new YAMN_FILTERPLUGINQUEUE;
		Previous = Previous->Next;			//leave previous, go to actual plugin
		Previous->Plugin = Plugin;
		Previous->Next = Parser;				//and in actual plugin set, that next plugin is the one we insert in front of
	}
	return 1;
}

INT_PTR FilterMailSvc(WPARAM wParam, LPARAM lParam)
{
	CAccount *Account = (CAccount *)wParam;
	HYAMNMAIL Mail = (HYAMNMAIL)lParam;
	PYAMN_FILTERPLUGINQUEUE ActualPlugin;

	mir_cslock lck(PluginRegCS);
	WaitToWriteFcn(Account->MessagesAccessSO);

	for (ActualPlugin = FirstFilterPlugin; ActualPlugin != nullptr; ActualPlugin = ActualPlugin->Next)
		if (ActualPlugin->Plugin->FilterFcn->FilterMailFcnPtr != nullptr)
			ActualPlugin->Plugin->FilterFcn->FilterMailFcnPtr(Account, YAMN_ACCOUNTVERSION, Mail, YAMN_MAILVERSION);

	Mail->Flags |= YAMN_MSG_FILTERED;

	//Set mail flags according to spamlevel settings
	if ((Mail->Flags & YAMN_MSG_SPAMMASK) > YAMN_MSG_SPAML1)
		Mail->Flags = Mail->Flags & ~(YAMN_MSG_BROWSER | YAMN_MSG_POPUP | YAMN_MSG_SYSTRAY | YAMN_MSG_SOUND | YAMN_MSG_APP | YAMN_MSG_NEVENT);
	if (YAMN_MSG_SPAML(Mail->Flags, YAMN_MSG_SPAML3) || YAMN_MSG_SPAML(Mail->Flags, YAMN_MSG_SPAML4))
		Mail->Flags = Mail->Flags | (YAMN_MSG_AUTODELETE | YAMN_MSG_DELETEOK);	//set message to delete
	if (YAMN_MSG_SPAML(Mail->Flags, YAMN_MSG_SPAML3))
		Mail->Flags = Mail->Flags & ~(YAMN_MSG_MEMDELETE);	//set message not to delete it immidiatelly from memory

	WriteDoneFcn(Account->MessagesAccessSO);
	return 1;
}