Extension manager hang after many cycles

Sorry for italian comments.

This Extension Manager trap Router’s $Inbox AddToFolder events, and, if the note contains special flags (SpamFilter item or subject beginning by “SPAM:”), move the memo to a special folder. If the rfc821 sender is in a common whitelist, the memo go in $inbox as normal operations.

I am trying to write an extension manager (after wrote a BeforNewMail Lotusscript agent) because of problems managing a high number of users.

After some fine cycle, on the server console i can see:

19/11/2008 17.55.00 Process d:\Lotus\Domino\nRouter.EXE (5464/0x1558) has terminated abnormally

How can i find the source of the problem?

Please note that the hang occur even if

if (IsSpam(memo_note_handle))

if substituted with

if (FALSE)

//routertrap.cpp : DLL entry point.

#include “stdafx.h”

#include “routertrap.h”

#include <stdlib.h>

#include <stdio.h>

#include <addin.h>

/*

  • Domino and Notes header files

*/

#include <global.h>

#include <ixport.h>

#include <dbdrv.h>

#include <dbdrverr.h>

#include <osmem.h>

#include <nsfdata.h>

#include <names.h>

#include <osfile.h>

#include <osenv.h>

#include <nif.h>

#include <nsfdb.h>

#include <nsfnote.h>

#include <editods.h>

#include <stdnames.h>

#include <nsfsearc.h>

#include <colorid.h>

#include <misc.h>

#include <miscerr.h>

#include <actods.h>

#include <nifcoll.h>

#include <osmisc.h>

#include <viewfmt.h>

#include <foldman.h>

#include <idtable.h>

#include <mailserv.h>

#include <mail.h>

#include <dname.h>

#include <nsfnote.h>

#include <pool.h>

//===== GLOBAL VARIABLES =============================

EMHANDLER gHandlerProc;

char gTextBuffer[1024];

BOOL gHooksRegistered=FALSE;

char strSpamSubject[1024];

BOOL boolSpamFilter;

static DBHANDLE hConfDB = NULLHANDLE;

NOTEID noteidToProcess; //noteID del documento in elaborazione (solo per log)

//==========================FILE LOG

/* File Managment */

#define LOG_FILE_NAME “\nroutertrap.txt”

#define __FILE FILE

#define __OpenFile( _fn, _perm ) fopen(_fn, _perm )

#define __CloseFile( _file ) fclose( _file )

#define __WriteLine( _buf, _file ) fwrite( _buf, strlen(_buf), 1, _file )

#define __FileError(_file) ferror(_file)

#define __ReadLine( _buf, _len, _f ) fgets( _buf, _len, _f )

#define __FileSeek( _file, _offset, _whence ) fseek( _file, _offset, _whence )

FILE *gFStream = (__FILE *)0;

char DataDir[MAXPATH+1];

char FileName[MAXPATH+1];

//================ DEBUG CONTROL======================

#define DODEBUG_NONE 0

#define DODEBUG_MIN 1

#define DODEBUG_ALL 9

int DoDebug=DODEBUG_ALL;

//================ Configuration control ==============

#define NOTESINIVAR “routertrapdb” //this NOTES.INI var point to whitelist config db

#define DBCONFVIEWNAME “RFC821Addresses” //name of the whitelist view (a sorted single column

													//containing email address only, without phrase nor hiphen

NOTEID WhitelistView;

HCOLLECTION hWhitelist;

#define INBOXITEMVIEWNAME “$TITLE”

#define INBOXVIEWNAME “($Inbox)”

#define SUBJECTITEMNAME “Subject”

//#define SUBJECTCONTENT “Subject”

//#define SPAMSTRING “SPAM:”

#define SPAMFOLDERNAME “-Da siti blacklist”

//================== modalità di segnalazione SPAM di SPAMFILTER

#define SPAMITEMNAME “X_SF_SPAM”

#define CHARSPAMITEMVALUE ‘Y’

WORD gRecursionID;

/* Storage needed for synchronization under Windows NT */

CRITICAL_SECTION gCriticalSection;

TExtensionInfo ExtensionHookTable = {

{EM_NSFADDTOFOLDER, EM_REG_BEFORE, 0, FALSE, “EM_NSFADDTOFOLDER”},

{EM_NSFADDTOFOLDER, EM_REG_AFTER, 0, FALSE, “EM_NSFADDTOFOLDER”},

{0, 0, 0, 0, NULL}

};

/===== LOCAL FUNCTION PROTOTYES ======================================/

BOOL IsSpam(NOTEHANDLE );

STATUS LNPUBLIC DLL_EXPORT MainEntryPoint( void );

STATUS LNPUBLIC DLL_EXPORT EMHandlerProc( EMRECORD FAR * pExRecord);

STATUS DeregisterEntry(int x);

void LogLine(char *Line);

void LogLineAllways(char *Line);

void CleanUp( void );

BOOL FlagOkSetup(void);

BOOL ProcessIsName(char *tname);

void PrintAPIError (STATUS api_error);

BOOL IsKeyPresent(char *email);

BOOL IsSenderWhitelisted( NOTEHANDLE memo_note_handle );

STATUS GetInternetAddressRFC821(char *inetaddress, char * FullAddress, int length);

#ifdef _MANAGED

#pragma managed(push, off)

#endif

BOOL APIENTRY DllMain( HINSTANCE hInstance, DWORD fdwReason, LPVOID lpReserved )

{

int x;

STATUS error=NOERROR;



x = OSGetDataDirectory(DataDir);

strcpy(FileName, DataDir);

strcat(FileName, LOG_FILE_NAME);



LogLineAllways("DllMain");



if (ProcessIsName("ROUTER") )

{

	switch(fdwReason)

	{

	case DLL_PROCESS_ATTACH:

		LogLineAllways("DllMain-DLL_PROCESS_ATTACH");			

		/*

		error = NotesInitThread ();                 

		if (error) {

			LogLineAllways("DllMain-DLL_PROCESS_ATTACH: non si attiva il thread");

			return (FALSE);

		}

		else {

			LogLineAllways("DllMain-DLL_PROCESS_ATTACH: thread avviato");

		}

		*/

		InitializeCriticalSection(&gCriticalSection);

		

		gHandlerProc = (EMHANDLER)MakeProcInstance((FARPROC)EMHandlerProc, hInstance);

	  break;



	case DLL_PROCESS_DETACH:

		LogLineAllways("DllMain-DLL_PROCESS_DETACH");

		CleanUp();



		/* Free procedure instance */

		FreeProcInstance( gHandlerProc );



		/* Deregister Extension Manager routines */

		for ( x = 0; ExtensionHookTable[x].m_Name != NULL; x += 1 ) {

			error = DeregisterEntry(x);

			if (error)

				goto Exit0;

		}



		DeleteCriticalSection(&gCriticalSection);

Exit0:

		//NotesTermThread ();

		break;

	case DLL_THREAD_ATTACH:

		LogLineAllways("DllMain-DLL_THREAD_ATTACH");

		/*

		error = NotesInitThread ();                 

		if (error) {

			LogLineAllways("DllMain-DLL_THREAD_ATTACH: non si attiva il thread");

			return (FALSE);

		}

		else {

			LogLineAllways("DllMain-DLL_THREAD_ATTACH: thread avviato");

		}

		*/

		break;

	case DLL_THREAD_DETACH:

		LogLineAllways("DllMain-DLL_THREAD_DETACH");

		//NotesTermThread ();

		break;

  }

}

return( TRUE );

}

#ifdef _MANAGED

#pragma managed(pop)

#endif

/*===========================================================================

void CleanUp(void)

===========================================================================*/

void CleanUp(void)

{

LogLine("CleanUp");

if (FlagOkSetup())

{

	//LogLine("\tCloseCollection.");

	//NIFCloseCollection(hWhitelist);	

	LogLine("\tCloseDB");

	NSFDbClose (hConfDB);

}

gHooksRegistered = FALSE;

}

void LogLine(char *Line)

{

char        TmpBuffer[1024];

//TIMEDATE far InputTime;

//WORD far retTextLength;

//char far retTextBuffer[MAXALPHATIMEDATE+1];

sprintf_s(TmpBuffer,sizeof(TmpBuffer),"ROUTERTRAP: %s",Line);



//LogEventText(Line, NULLHANDLE, NOERROR, (char far *) str))

MailLogEventText(MAIL_LOG_TO_MAILEVENTS, TmpBuffer, NULLHANDLE, NOERROR);



/*

    gFStream = __OpenFile( FileName, APPEND_PERMISSION );

    if (gFStream) {

		OSCurrentTIMEDATE(&InputTime);

		ConvertTIMEDATEToText(NULL,NULL,&InputTime,

			retTextBuffer,MAXALPHATIMEDATE,&retTextLength);

		retTextBuffer[retTextLength]='\0';

		sprintf_s(TmpBuffer,sizeof(TmpBuffer),"%s: %s\n",retTextBuffer,Line);

		__WriteLine(TmpBuffer, gFStream);

	  __CloseFile(gFStream);

	  gFStream = (__FILE *)0;

    }

*/

LogLineAllways(Line);

//printf ("PRINTF: %s\n", TmpBuffer);

}

void LogLineAllways(char *Line)

{

char        TmpBuffer[1024];

TIMEDATE far InputTime;

WORD far retTextLength;

char far retTextBuffer[MAXALPHATIMEDATE+1];



    gFStream = __OpenFile( FileName, APPEND_PERMISSION );

    if (gFStream) {

		OSCurrentTIMEDATE(&InputTime);

		ConvertTIMEDATEToText(NULL,NULL,&InputTime,

			retTextBuffer,MAXALPHATIMEDATE,&retTextLength);

		retTextBuffer[retTextLength]='\0';

		sprintf_s(TmpBuffer,sizeof(TmpBuffer),"%s: (%u) %s\n",retTextBuffer,noteidToProcess,Line);

		__WriteLine(TmpBuffer, gFStream);

	  __CloseFile(gFStream);

	  gFStream = (__FILE *)0;

    }

}

/*

  • RegisterEntry: Attempts to Register one entry.

  • in: x = Offset into table

  • out: 0 if ok, returned error otherwise

*/

STATUS RegisterEntry(int x)

{

STATUS error = NOERROR;



if (ExtensionHookTable[x].m_Name == NULL) return(error);



//LogLine("RegisterEntry-------------------------------------------------\n");



//LogLine( gTextBuffer );



error = EMRegister( ExtensionHookTable[x].m_Identifier,

    ExtensionHookTable[x].m_Notification,

    (EMHANDLER)gHandlerProc,

    gRecursionID,

    &ExtensionHookTable[x].m_RegistrationHandle);



if (error) {

	LogLine("EMRegister Failed----------------------------!!\n");

	return(error);

}



return(error);

}

/*

  • DeregisterEntry: Attempts to Deregister one entry.

  • in: x = Offset into table

  • out: 0 if ok, returned error otherwise

*/

STATUS DeregisterEntry(int x)

{

STATUS error = NOERROR;

//LogLine("DeregisterEntry");

if (ExtensionHookTable[x].m_Name == NULL) 

	return(error);



//LogLine("-------------------------------------------------\n");



//if (DoDebug>=DODEBUG_ALL) LogLine( gTextBuffer );



error = EMDeregister(ExtensionHookTable[x].m_RegistrationHandle);



if (error) {

	LogLine("EMDregister Failed---------------!!!!!!!!");

	return(error);

}



return(error);

}

STATUS LNPUBLIC DLL_EXPORT MainEntryPoint( void )

{

STATUS    error;

WORD      x;



error = NOERROR;



LogLineAllways("in MainEntryPoint");



if (ProcessIsName("ROUTER") ) 

{

	LogLineAllways("in MainEntryPoint, processo ROUTER");



	/*

	*    When run on a server the dll is called multiple times. the flag

	*    keeps the main code from being executed more than once.

	*/

	FlagOkSetup();

	if ( gHooksRegistered )

		return(NOERROR);

	LogLine("MainEntryPoint-HookRegister");			

	gHooksRegistered = TRUE;



	/* Get proc instance for the handler callback. */

	#if defined (NT)

	/* Done in the DllMain function at startup. */

	#else

	gHandlerProc = EMHandlerProc;

	#endif



	/*  Next get a recursion ID  for the run */



    

	//LogLine("Calling EMCreateRecursionID\n");



	error = EMCreateRecursionID( &gRecursionID );



	if (error)

	  LogLine("EMCreateRecursionID Failed  -----------------!!!!!!\n");



	/*Loop through the table testing each entry */



	else 

	{

		//LogLine("EMCreateRecursionID Returned Success\n");



		for ( x = 0; ExtensionHookTable[x].m_Name != NULL; x += 1 ) {

			error = RegisterEntry(x);

			if (error)

				break;

	}

}

}

else

	LogLineAllways("in MainEntryPoint, processo NON ROUTER");

return( error );

}

BOOL ProcessIsName(char *tname)

{

HMODULE hModule=NULLHANDLE;

HANDLE hDesc;

char far ProcessName[256];

char far szProcessName[256];

AddInQueryDefaults(&hModule, &hDesc);

if (OSLoadString(hModule, PKG_ADDIN+0, ProcessName, sizeof(ProcessName)-1)==0)

	return false;

OSTranslate(OS_TRANSLATE_LMBCS_TO_ASCII, ProcessName, 

	strlen(ProcessName), szProcessName, sizeof(szProcessName)-1);

/*

sprintf_s(gTextBuffer,sizeof gTextBuffer, "ProcessIsName: %s", szProcessName);

LogLineAllways(gTextBuffer);

*/

if (_strnicmp(szProcessName, tname , sizeof(szProcessName))!=0) {

	sprintf_s(gTextBuffer,sizeof gTextBuffer, "Processo: -%s- diverso da -%s-", szProcessName,tname);

	LogLineAllways(gTextBuffer);

	return false;

}

sprintf_s(gTextBuffer,sizeof gTextBuffer, "Processo: -%s- uguale a -%s-", szProcessName,tname);

LogLineAllways(gTextBuffer);



return true;

}

void LogFileName(DBHANDLE hDB)

{

//stampa il nome del file

char szDBCanonicalPathName[MAXPATH];

#define PATHMSG		"Path of SRC= %s"

char TempStr[MAXPATH + 50];

STATUS error = 0;

if (error = NSFDbPathGet(hDB, szDBCanonicalPathName, NULL))

{}

else {

	if (DoDebug>=DODEBUG_MIN) {

		sprintf_s(TempStr,sizeof(TempStr),PATHMSG, szDBCanonicalPathName);

		LogLine(TempStr);

	}

}

}

BOOL AddToFolder(DBHANDLE hDB, NOTEID DocNoteID, char *FolderName)

{

/* To add documents to this folder, create an id table of docs */

STATUS error;

HANDLE      hNotesIDTable;   /* table of Note IDs to modify */

NOTEID		FolderNoteID;

char FilePath[MAXPATH];



//Occorre trovare il NoteID della cartella SPAM

if (error = NIFFindView(hDB, FolderName, &FolderNoteID))

{

	if (DoDebug>=DODEBUG_MIN) {

		 NSFDbPathGet(hDB,FilePath,NULL);

		sprintf_s(gTextBuffer,sizeof(gTextBuffer), 

			"%s: Attenzione: NON TROVATA CARTELLA SPAM************************",FilePath);

		LogLine(gTextBuffer);

	}

    return (FALSE);

}

//if (DoDebug>=DODEBUG_ALL) 	LogLine("Trovata cartella SPAM, ");



if (error = IDCreateTable(sizeof(NOTEID), &hNotesIDTable))

{

	LogLine("IDCreateTable non riuscito");

	return (FALSE);

}

if (error = IDInsert (hNotesIDTable, DocNoteID, NULL))

{

	LogLine("IDInsert non riuscito");

	IDDestroyTable (hNotesIDTable);

	//API_RETURN (ERR(error));

	return (FALSE);

}

if (error = FolderDocAdd (hDB, NULLHANDLE, FolderNoteID, hNotesIDTable, 0L)) {

	LogLine("FolderDocAdd non riuscito");

	return (FALSE);

}

IDDestroyTable (hNotesIDTable);

return (TRUE);

}

/* non seguiamo questo sistema perchè dovremmo registrarne due differenti per BEFORE e AFTER

STATUS LNPUBLIC NSFAddToFolderEMCallback(

DBHANDLE  hViewDB,

DBHANDLE  hDataDB,

NOTEID  FolderNoteID,

NOTEID  NoteID,

UNID *NoteUNID,

BOOL  IsAddOperation,

TIMEDATE *RevisionTime)

{

return (ERR_EM_CONTINUE);

}

*/

STATUS LNPUBLIC DLL_EXPORT EMHandlerProc( EMRECORD FAR * pExRecord )

{

STATUS error = 0;

//NOTEHANDLE  view_note_handle;

NOTEHANDLE  memo_note_handle;



/* do nothing if there is an error. */

if (pExRecord->Status != NOERROR) {

	goto Exit0;

} 

if (ProcessIsName("ROUTER")) LogLineAllways("in EMHandlerProc: processo ROUTER");

else LogLineAllways("in EMHandlerProc: processo NON ROUTER!!!!!!!!!!!!!!!!!!!!!!!!");



if (ProcessIsName("ROUTER") )

	if (FlagOkSetup())

	{

		switch (pExRecord->EId)

		{

		case EM_NSFADDTOFOLDER:

			{

				VARARG_PTR ap;

				WORD NotificationType;

				DBHANDLE  hViewDB;

				DBHANDLE  hDataDB;

				NOTEID  FolderNoteID, InboxNoteID;

				NOTEID  NoteID;

				UNID *NoteUNID;

				BOOL  IsAddOperation;

				TIMEDATE *RevisionTime;

				char szDBCanonicalPathName[MAXPATH];

				/* get arguments */

				ap = pExRecord->Ap;

				hViewDB=VARARG_GET(ap, DBHANDLE);

				hDataDB=VARARG_GET(ap, DBHANDLE);

				FolderNoteID=VARARG_GET(ap, NOTEID);

				NoteID=VARARG_GET(ap,NOTEID);

				NoteUNID=VARARG_GET(ap,UNID *);

				IsAddOperation=VARARG_GET(ap,BOOL );

				RevisionTime=VARARG_GET(ap,TIMEDATE *);

				NSFDbPathGet(hViewDB, szDBCanonicalPathName, NULL);

				if (DoDebug>=DODEBUG_ALL) {

					sprintf_s(gTextBuffer,sizeof(gTextBuffer), "%s: EM_NSFADDTOFOLDER, ", szDBCanonicalPathName);

					LogLine(gTextBuffer);

				}

				

				NotificationType=pExRecord->NotificationType;

				if (NotificationType==EM_BEFORE)

				{

					if (DoDebug>=DODEBUG_ALL)	LogLine("(EM_BEFORE) *****************");

					noteidToProcess=NoteID;			//NOTEID to log thread interactions

					if (IsAddOperation)		//only for addtofolder

					{		

							// check for ($Inbox)

						   if (error = NIFFindView (hViewDB, "($Inbox)", &InboxNoteID))

						   {

								if (DoDebug>=DODEBUG_ALL) LogLine("Cannot open ($Inbox)");

								goto Exit0;

						   }



						   if (InboxNoteID == FolderNoteID)

							{

								//in Inbox, open the memo document:

								if (DoDebug>=DODEBUG_ALL) LogLine("Siamo in ($Inbox)");

								if (error = NSFNoteOpen (hDataDB, // database handle 

									NoteID,                 // note ID 

									0,                      // open flags 

									&memo_note_handle))          // note handle (return) 

									{

										LogLine("Il messaggio di posta non e' esaminabile, non sarà considerato SPAM");

										break;

									}

								else	//memo aperto

								{

									if (DoDebug>=DODEBUG_ALL) 		LogLine("Siamo sul documento");

									if (IsSpam(memo_note_handle))		

									//sostituendo con if (FALSE) invece che if (ISSPAM...) si pianta ugualmente

									{

										//	if (FALSE) invece che "if (!IsSenderWhitelisted( memo_note_handle))" si pianta

										if (!IsSenderWhitelisted( memo_note_handle))

										{

											if ( ! AddToFolder(hDataDB, NoteID, SPAMFOLDERNAME))

											{

												if (DoDebug>=DODEBUG_ALL) 

													LogLine("NON SI SPOSTA IN CARTELLA SPAM-------------!");

												//lasciare i normali eventi in modo che in assenza 

												//...della cartella vada in Inbox

												NSFNoteClose (memo_note_handle);	

												break;

											}

											if (DoDebug>=DODEBUG_MIN) 

												LogLine("SPAM spostato in cartella");



											NSFNoteClose (memo_note_handle);	

											//tornando diverso da ERR_EM_CONTINUE 

											//non completa l'operazione (inserimento in Inbox)

											noteidToProcess=0;			//NOTEID to log thread interactions

											return(NOERROR);	

										}

										else

										{

											if (DoDebug>=DODEBUG_MIN) 

												LogLine("Trovato SPAM da Whitelist");

										}

									}

									else		//non è spam

									{

										LogLine("Non e' SPAM");

									}

								}

								NSFNoteClose(memo_note_handle);		//chiusura del memo

								//NSFNoteClose (view_note_handle);	//chiusura della cartella

							}

							else 	//LA CARTELLA NON E' INBOX, tralascia

							{

								if (DoDebug>=DODEBUG_ALL) {

									sprintf_s(gTextBuffer,sizeof(gTextBuffer), "Il messaggio non e' stato recapitato in $Inbox");

									LogLine(gTextBuffer);

								}

								//NSFNoteClose (view_note_handle);		//chiusura della cartella

							}

						

						}

					else {

						LogLine("Non e' IsAddOperation: cos'e'?");

					}



					}

				else if (NotificationType==EM_AFTER) {			//EM_AFTER

					LogLineAllways("(EM_AFTER)");

					noteidToProcess=0;			//annulla per loggare Noteid del documento 

				}

				else LogLine("NotificationType not AFTER nor BEFORE");

			}	

			

			break;		

			}		

		}

Exit0:

/*

The status code generated inside of the callback function has a direct effect on the execution 

of Domino or Notes core.  If the callback returns the special status code ERR_EM_CONTINUE, 

Domino or Notes will continue execution (as if this hook had never been called).  

If the callback returns any other status code to Domino or Notes (including NOERROR), 

no other DLLs or Addins that are registered for the same NSF function will get called by 

the Extension Manager. Also if the callback registered with EM_REG_BEFORE returns a status code , 

the Domino or Notes core function will not be executed.*/

return( ERR_EM_CONTINUE );

}

/*************************************************************************

FUNCTION:   PrintAPIError

PURPOSE:    This function prints the Lotus C API for Domino and Notes 

	error message associated with an error code.

**************************************************************************/

void PrintAPIError (STATUS api_error)

{

STATUS  string_id = ERR(api_error);

char    error_text[200];

WORD    text_len;



// Get the message for this Lotus C API for Domino and Notes error code

//from the resource string table.



text_len = OSLoadString (NULLHANDLE, string_id, error_text, sizeof(error_text));



/* Print it. */



fprintf (stderr, "\n%s\n", error_text);

}

BOOL ViewIsKeyPresent(char far * email)

{

STATUS error = 0;

COLLECTIONPOSITION coll_pos;                /* position within collection */

DWORD     match_size;                       /* number of notes matching key */

	//Apre la vista per le ricerche

if (error = NIFOpenCollection(

     hConfDB,      //handle of db with view 

     hConfDB,      //handle of db with data

     WhitelistView,        // note id of the view 

     0,              // collection open flags 

     NULLHANDLE,     // handle to unread ID list (input and return) 

     &hWhitelist,   // collection handle (return) 

     NULLHANDLE,     // handle to open view note (return) 

     NULL,           // universal note id of view (return)

     NULLHANDLE,     // handle to collapsed list (return) 

     NULLHANDLE))    // handle to selected list (return) 

  {

	//NSFDbClose (hConfDB);

	sprintf_s(gTextBuffer, sizeof(gTextBuffer),"Non riesco ad aprire la vista \"%s\"", DBCONFVIEWNAME);

	LogLine(gTextBuffer);

	PrintAPIError(error);

	return false;

  }



error = NIFFindByName (

      hWhitelist,       // collection to look in 

      email,          // string to match on 

      FIND_CASE_INSENSITIVE, //match rules 

      &coll_pos,         //where match begins (return) 

      &match_size);      // how many match (return) 



if (ERR(error) == ERR_NOT_FOUND) {

	NIFCloseCollection(hWhitelist);	

	if (DoDebug>=DODEBUG_ALL)  LogLine("ViewIsKeyPresent: Non trovato nella vista");

	return false; 

}

NIFCloseCollection(hWhitelist);	

if (DoDebug>=DODEBUG_ALL)  LogLine("ViewIsKeyPresent: Trovato nella vista whitelist");

return true;

}

BOOL IsSenderWhitelisted( NOTEHANDLE memo_note_handle )

{

//this function check to see if the memo originator is in whitelist

STATUS error = 0;



char        FromAddress[MAXSPRINTF+1];

char		far InternetAddress821[MAXSPRINTF+1];

//WORD        StringLength;

long field_len;



/* FROM */

/*

MailGetMessageItem (memo_note_handle, MAIL_FROM_ITEM_NUM, FromAddress, MAXSPRINTF, &StringLength);

FromAddress[StringLength] = '\0';*/

field_len = NSFItemGetText (memo_note_handle, "FROM", FromAddress, (WORD) sizeof (FromAddress));

sprintf_s(gTextBuffer,sizeof(gTextBuffer), "%s contiene: -%s-", "FROM", FromAddress);

if (DoDebug>=DODEBUG_ALL) LogLine(gTextBuffer);

if (DoDebug>=DODEBUG_ALL){

	sprintf_s(gTextBuffer,sizeof(gTextBuffer),"MAIL_FROM field:\"%s\"",FromAddress);

	LogLine(gTextBuffer);

}

if (error=GetInternetAddressRFC821(InternetAddress821, FromAddress, sizeof(InternetAddress821)))

{

	if (DoDebug>=DODEBUG_ALL){

		LogLine("GetInternetAddressRFC821 returned error");

		return false;

	}

}

if (strlen(InternetAddress821)==0) {

	if (DoDebug>=DODEBUG_ALL){

		LogLine("GetInternetAddressRFC821 ritornato Null, tengo il contenuto di FROM");

		strncpy_s(InternetAddress821, sizeof(InternetAddress821)-1, FromAddress, strlen(FromAddress));

		InternetAddress821[strlen(FromAddress)] = '\0';	

	}

}

if (DoDebug>=DODEBUG_ALL){

	sprintf_s(gTextBuffer,sizeof(gTextBuffer),"InternetAddress821:\"%s\"",InternetAddress821);

	LogLine(gTextBuffer);

}

if(ViewIsKeyPresent(InternetAddress821)) {

	if (DoDebug>=DODEBUG_ALL)	LogLine("Sender in whitelist");

	return true;

}

if (DoDebug>=DODEBUG_ALL)	LogLine("Sender NOT in whitelist");



return false;

}

STATUS GetInternetAddressRFC821(char *inetaddress, char * FullAddress, int length)

{

//return the address is not a internet RFC821 like address

//error if cannot convert

STATUS      error = NOERROR;

DN_COMPONENTS DNComp;

char        tmpStr[MAXSPRINTF+1];



error = DNParse(0L, NULL, FullAddress, &DNComp, sizeof(DNComp));

if (error)

{

	LogLine("DNParse return Error");

	return error;

}



if (DoDebug>=DODEBUG_ALL) {

	sprintf_s(gTextBuffer,sizeof(gTextBuffer),

		"DNComp.Address821:\"%s\", lunghezza: %d, lunghezza disponibile di inetaddress:%d",

		DNComp.Address821,DNComp.Address821Length,length);

	LogLine(gTextBuffer);

}

//strncpy_s(inetaddress, sizeof(inetaddress)-1, (char *) DNComp.Address821, DNComp.Address821Length);

//se usi strncpy_s va in crash

//strncpy(inetaddress, (char *) DNComp.Address821, DNComp.Address821Length);

memmove(inetaddress,DNComp.Address821, DNComp.Address821Length);

inetaddress[DNComp.Address821Length] = '\0';	

if (DoDebug>=DODEBUG_ALL){

	sprintf_s(tmpStr,sizeof(tmpStr),"Indirizzo da convertire: '%s', convertito: '%s'", FullAddress, 	inetaddress);

	LogLine(tmpStr);

}

return error;

}

STATUS GetProfileFieldStr(char * FieldName, char * ProfileName, char * Username, char * retStr)

{

STATUS error=NOERROR;

WORD retDataType;

BLOCKID retbhValue;

DWORD retValueLength;

char *pData;

char FieldBuffer[128];

char gTextBuffer[1024];

FieldBuffer[0]='\0';

gTextBuffer[0]='\0';

if( error = NSFProfileGetField( hConfDB, ProfileName,

				  (WORD) strlen(ProfileName),

				  Username, (WORD) strlen(Username), 

				  FieldName,	(WORD) strlen(FieldName),		

				  &retDataType,				

				  &retbhValue,

				  &retValueLength))

{

	sprintf_s(gTextBuffer, sizeof(gTextBuffer),"Non riesco a leggere il campo %s del profilo %s", FieldName, ProfileName);

	LogLine(gTextBuffer);

	PrintAPIError(error);

	return error;

}

if( retDataType != TYPE_TEXT )

{

   sprintf_s(gTextBuffer, sizeof(gTextBuffer),"Il campo %s del profilo %s non e' di tipo testo", FieldName, ProfileName);

	LogLine(gTextBuffer);

	//non essendo del tipo richiesto, azzeriamo la stringa

	retStr[0]='\0';

   	return error;

}

pData = OSLockBlock( char, retbhValue );

if ( ISNULLBLOCKID(retbhValue ))

{

	LogLine("OSLockBlock  ==NULL, profilo non letto.");

	retStr[0]='\0';

   	return error;

}

else

{

pData += sizeof(WORD); 				// step over data type word 

memmove( FieldBuffer, pData, (int) (retValueLength - sizeof(WORD)));

FieldBuffer[retValueLength - sizeof(WORD)] = '\0';

sprintf_s(gTextBuffer, sizeof(gTextBuffer),"FieldBuffer da profilo:-%s- lunghezza:%d", FieldBuffer, strlen(FieldBuffer));

LogLine(gTextBuffer);

OSUnlockBlock( retbhValue);

memmove(retStr,FieldBuffer,strlen(FieldBuffer)+1);

}

return error;

}

BOOL FlagOkSetup(void)

{

//esegue il setup delle variabili di lavoro

static	bool OKSetup=false;

char	near		confDBPath[20];

	

STATUS error = 0;

char FieldBuffer[128];



if (OKSetup)			//se gia inizializzato ritorna vero

	return (OKSetup);



//Prova ad inizializzare il sistema

if (!OSGetEnvironmentString(NOTESINIVAR, confDBPath, sizeof(confDBPath)-1))

{

	sprintf_s(gTextBuffer, sizeof(gTextBuffer),"Variabile in NOTES.INI non presente: %s", NOTESINIVAR);

	LogLine(gTextBuffer);

	return false;

}

if (error= NSFDbOpen (confDBPath, &hConfDB))

{

	sprintf_s(gTextBuffer,sizeof(gTextBuffer), 

		"Non riesco ad aprire il file %s specificato nella variabile notes.ini %s", confDBPath,NOTESINIVAR);

	LogLine(gTextBuffer);

	PrintAPIError(error);

	return false;

}

if (error = NIFFindView (hConfDB, DBCONFVIEWNAME, &WhitelistView))

{

	NSFDbClose (hConfDB);

	sprintf_s(gTextBuffer,sizeof(gTextBuffer), "Non riesco a trovare la vista %s del file %s specificato nella variabile notes.ini %s", DBCONFVIEWNAME, confDBPath, NOTESINIVAR);

	LogLine(gTextBuffer);

	PrintAPIError(error);

	return false;

}



//Apre la vista per le ricerche per controllare che esista

if (error = NIFOpenCollection(

     hConfDB,      //handle of db with view 

     hConfDB,      //handle of db with data

     WhitelistView,        // note id of the view 

     0,              // collection open flags 

     NULLHANDLE,     // handle to unread ID list (input and return) 

     &hWhitelist,   // collection handle (return) 

     NULLHANDLE,     // handle to open view note (return) 

     NULL,           // universal note id of view (return)

     NULLHANDLE,     // handle to collapsed list (return) 

     NULLHANDLE))    // handle to selected list (return) 

  {

	NSFDbClose (hConfDB);

	sprintf_s(gTextBuffer, sizeof(gTextBuffer),"Non riesco ad aprire la vista \"%s\" del file %s specificato nella variabile notes.ini %s", DBCONFVIEWNAME, confDBPath, NOTESINIVAR);

	LogLine(gTextBuffer);

	PrintAPIError(error);

	return false;

  }



NIFCloseCollection(hWhitelist);		// chiudi collection, la riaprirà all'uso

//lettura livello di log dal profilo

if (error=GetProfileFieldStr(“LogLevel”, “Profilo”, “”,FieldBuffer))

{

	//NIFCloseCollection(hWhitelist);	

	NSFDbClose (hConfDB);

	LogLine("Non riesco a leggere il profilo");

	PrintAPIError(error);

	return false;

}

DoDebug=atoi(FieldBuffer);

sprintf_s(gTextBuffer, sizeof(gTextBuffer),"Livello di log impostato: %d", DoDebug);

LogLine(gTextBuffer);



 //lettura livello di log dal profilo

if (error=GetProfileFieldStr(“SpamSubject”, “Profilo”, “”,FieldBuffer))

{

	//NIFCloseCollection(hWhitelist);	

	NSFDbClose (hConfDB);

	LogLine("Non riesco a leggere il profilo");

	PrintAPIError(error);

	return false;

}

memmove(strSpamSubject,FieldBuffer,strlen(FieldBuffer)+1);	//copia anche '\0'

sprintf_s(gTextBuffer, sizeof(gTextBuffer), "Contenuto subject richiesto:%s lunghezza %d", 

  strSpamSubject,strlen(strSpamSubject));

LogLine(gTextBuffer);

//lettura dal profilo

if (error=GetProfileFieldStr(“SFItem”, “Profilo”, “”,FieldBuffer))

{

	NSFDbClose (hConfDB);

	LogLine("Non riesco a leggere il profilo");

	PrintAPIError(error);

	return false;

}

if(FieldBuffer[0]='Y')

	boolSpamFilter=TRUE;

else

	boolSpamFilter=FALSE;

sprintf_s(gTextBuffer, sizeof(gTextBuffer),"SFitem: %d", boolSpamFilter);

LogLine(gTextBuffer);



OKSetup=true;

if (DoDebug>=DODEBUG_MIN) 	LogLine("Setup OK");

return true;

}

BOOL IsSpam(NOTEHANDLE memo_note_handle )

{

BOOL         field_found;	

WORD         field_len;	

char         itemvalue[500];

char		TextBuffer[1024];

if (boolSpamFilter==TRUE)

{

	LogLineAllways("1");

	field_found = NSFItemIsPresent (memo_note_handle, SPAMITEMNAME, (WORD) strlen (SPAMITEMNAME));

	if (field_found )   

	{ 

		field_len = NSFItemGetText (memo_note_handle, SPAMITEMNAME, itemvalue, (WORD) sizeof (itemvalue));

		LogLineAllways("1.1");

		if (DoDebug>=DODEBUG_ALL) 

		{

			sprintf_s(TextBuffer,sizeof(gTextBuffer), "%s contiene: %s",SPAMITEMNAME, itemvalue);

			LogLine(TextBuffer);

		}

		//vediamo se contiene SPAMITEMVALUE:



		//vediamo se questo ha problema: if (_strnicmp(itemvalue, SPAMITEMVALUE , strlen(SPAMITEMVALUE))==0) 

		if (itemvalue[0]==CHARSPAMITEMVALUE)

		{

			//contiene SPAMITEMVALUE

			return true;

		}

		LogLineAllways("1.2");

	}

	else

	{

			LogLine ("SPAMITEMNAME non trovato.");

	}

	LogLineAllways("1.3");

}

LogLineAllways("2");

if(strlen(strSpamSubject)!=0)

{

	LogLineAllways("2.1");

	field_found = NSFItemIsPresent (memo_note_handle, SUBJECTITEMNAME, (WORD) strlen (SUBJECTITEMNAME));

	if (!field_found )   { 

		LogLine ("SUBJECTITEMNAME non trovato.");

		return false;

	} 

	LogLineAllways("2.2");

	field_len = NSFItemGetText (memo_note_handle, SUBJECTITEMNAME, itemvalue, (WORD) sizeof (itemvalue));



	if (DoDebug>=DODEBUG_ALL) 

	{

		sprintf_s(TextBuffer,sizeof(gTextBuffer), "%s contiene: %s",SUBJECTITEMNAME, itemvalue);

		LogLine(TextBuffer);

	}

	LogLineAllways("2.3");

	//vediamo se contiene strSpamSubject:

	// era così: if (_strnicmp(itemvalue, strSpamSubject, strlen(strSpamSubject))==0) 

	if (strnicmp(itemvalue, strSpamSubject, min(field_len,strlen(strSpamSubject)))==0) 

	{

		LogLineAllways("2.3.1");

		//contiene strSpamSubject

		if (DoDebug>=DODEBUG_ALL) 

			{

				sprintf_s(TextBuffer,sizeof(gTextBuffer), "%s contiene la stringa cercata: %s",SUBJECTITEMNAME, strSpamSubject);

				LogLine(TextBuffer);

			}

		LogLineAllways("2.3.2");

		return true;

	}

	LogLineAllways("2.4");

}

else		//non è stato richiesto SPAM tramite stringa in Subject

{

	LogLineAllways("3");

	if (DoDebug>=DODEBUG_ALL) 

		{

			LogLineAllways("3.1");

			sprintf_s(TextBuffer,sizeof(gTextBuffer), "Non e' stato richiesto di riconoscere il campo %s. La stringa  %s e' lunga %d",SUBJECTITEMNAME, strSpamSubject, strlen(strSpamSubject));

			LogLine(TextBuffer);

		}

LogLineAllways("3.2");	

}

LogLineAllways("4");

return false;

}