
/*
** Make the generale purpose filter from filter.c to be
** a filter for the UMS message base.
**
** Defines a FilterSpec with certain keywords and a bithook
** for the actual filtering.
*/

/*
** 03-Jan-94 [kmel] Corrected FIL_ACTION_LOWER at case ID_DATE,
**                  because UMS only selects _younger_ messages
**                  compared with the defined date.
**
** 02-May-94 [MS]   corrected search for constant expressions on
**                  header fields without index
**
** 23-Mar-95 [SS]   ID_LENGTH, new filter: TextLength, HeaderLength
*/


/* SMAKE */


#include "sumstl.h"

#include <stdio.h>

#include "filter.h"
#include "umsfilter.h"
#include "date.h"

extern struct Library *UMSBase;
extern struct DosLibrary *DOSBase;

#define ID_STRING  1
#define ID_UFLAG   2
#define ID_GFLAG   3
#define ID_DATE    4
#define ID_AGE     5
#define ID_MSGNUM  6
#define ID_LENGTH  7


static BOOL chktrue(char *s)
{
        if (atol(s) || !stricmp(s,"yes") || !stricmp(s,"on") || !stricmp(s,"ja") || !stricmp(s,"ein") || !stricmp(s,"an"))
                return(TRUE);
        else
                return(FALSE);
}


static VOID SetFromHelp(UMSAccount acc,ULONG help,struct FilterHookPacket *fhp)
{
        UMSSelectTags(acc,
                UMSTAG_SelReadLocal , TRUE,
                UMSTAG_SelMask      , fhp->mask  | help,
                UMSTAG_SelMatch     , fhp->match | help,
                UMSTAG_SelWriteLocal, TRUE,
                UMSTAG_SelSet       , fhp->set,
                UMSTAG_SelUnset     , fhp->clear,
                TAG_DONE);

        UMSSelectTags(acc,
                UMSTAG_SelReadLocal , TRUE,
                UMSTAG_SelMask      , help,
                UMSTAG_SelMatch     , help,
                UMSTAG_SelWriteLocal, TRUE,
                UMSTAG_SelUnset     , help,
                TAG_DONE);
}



#ifdef _DCC
__geta4 static LONG bitfunc(__A0 struct Hook *hook, __A2 UMSAccount acc, __A1 struct FilterHookPacket *fhp)
#else
static LONG __saveds __asm bitfunc(register __a0 struct Hook *hook, register __a2 UMSAccount acc, register __a1 struct FilterHookPacket *fhp)
#endif
{
        LONG res = FIL_ERROR_MISC;

/* printf("func: mask %08lx match %08lx set %08lx clear %08lx action %ld data %s\n",fhp->mask,fhp->match,fhp->set,fhp->clear,fhp->action,fhp->data); */

        switch (fhp->action)
        {
                case FIL_ACTION_BITS:
                {
                        UMSSelectTags(acc,
                                UMSTAG_SelReadLocal , TRUE,
                                UMSTAG_SelMask      , fhp->mask ,
                                UMSTAG_SelMatch     , fhp->match,
                                UMSTAG_SelWriteLocal, TRUE,
                                UMSTAG_SelSet       , fhp->set,
                                UMSTAG_SelUnset     , fhp->clear,
                                TAG_DONE);

                        res = FIL_ERROR_OK;
                }
                break;

                case FIL_ACTION_EQUAL:
                {
                        switch (fhp->uid)
                        {
                                case ID_LENGTH:
                                {
                                        UMSMsgNum nr=0L;

                                        while (nr = UMSSearchTags(acc,
                                                    UMSTAG_SearchLast   , nr,
                                                    UMSTAG_SearchLocal  , TRUE,
                                                    UMSTAG_SearchMask   , fhp->mask ,
                                                    UMSTAG_SearchMatch  , fhp->match,
                                                 TAG_DONE))
                                        {
                                                LONG size;

                                                if (UMSReadMsgTags(acc,
                                                    UMSTAG_RMsgNum    , nr,
                                                    UMSTAG_RNoUpdate  , TRUE,
                                                    (ULONG)fhp->udata , &size,
                                                    TAG_DONE))
                                                {
                                                        if (size==atol(fhp->data))
                                                        {
                                                                UMSSelectTags(acc,
                                                                        UMSTAG_SelWriteLocal, TRUE,
                                                                        UMSTAG_SelStart     , nr,
                                                                        UMSTAG_SelStop      , nr+1,
                                                                        UMSTAG_SelSet       , FIL_LASTBIT,
                                                                        TAG_DONE);
                                                        }
                                                }

                                                SetFromHelp(acc,FIL_LASTBIT,fhp);
                                        }

                                        res = FIL_ERROR_OK;
                                }
                                break;

                                case ID_STRING:
                                {
                                        if (strchr(fhp->data,'#') || strchr(fhp->data,'?') || strchr(fhp->data,'*'))
                                        {
                                                UMSMsgNum nr=0L;

                                                while (nr = UMSSearchTags(acc,
                                                            UMSTAG_SearchLast   , nr,
                                                            UMSTAG_SearchLocal  , TRUE,
                                                            UMSTAG_SearchMask   , fhp->mask ,
                                                            UMSTAG_SearchMatch  , fhp->match,
                                                                                (ULONG)fhp->udata   , fhp->data,
                                                                                UMSTAG_SearchPattern, 2L,
                                                         TAG_DONE))
                                                {
                                                        UMSSelectTags(acc,
                                                                UMSTAG_SelWriteLocal, TRUE,
                                                                UMSTAG_SelStart     , nr,
                                                                UMSTAG_SelStop      , nr+1,
                                                                UMSTAG_SelSet       , FIL_LASTBIT,
                                                                TAG_DONE);
                                                }
                                        }
                                        else
                                        {
                                                if (UMSSelectTags(acc,
                                                        UMSTAG_SelQuick     , TRUE,
                                                        UMSTAG_SelWriteLocal, TRUE,
                                                        UMSTAG_SelSet       , FIL_LASTBIT,
                                                        (ULONG)fhp->udata   , fhp->data,
                                                        TAG_DONE)==0L)
                                                        if (UMSErrNum(acc)==UMSERR_MissingIndex)
                                                        {
                                                                UMSMsgNum nr=0L;

                                                                while (nr = UMSSearchTags(acc,
                                                                    UMSTAG_SearchLast   , nr,
                                                                    UMSTAG_SearchLocal  , TRUE,
                                                                    UMSTAG_SearchMask   , fhp->mask ,
                                                                    UMSTAG_SearchMatch  , fhp->match,
                                                                                (ULONG)fhp->udata   , fhp->data,
                                                                                UMSTAG_SearchPattern, 2L,
                                                                 TAG_DONE))
                                                                {
                                                                        UMSSelectTags(acc,
                                                                        UMSTAG_SelWriteLocal, TRUE,
                                                                        UMSTAG_SelStart     , nr,
                                                                        UMSTAG_SelStop      , nr+1,
                                                                        UMSTAG_SelSet       , FIL_LASTBIT,
                                                                        TAG_DONE);
                                                                }
                                                        }
                                        }

                                        SetFromHelp(acc,FIL_LASTBIT,fhp);

                                        res = FIL_ERROR_OK;
                                }
                                break;

                                case ID_GFLAG:
                                case ID_UFLAG:
                                {
                                        UMSSelectTags(acc,
                                                fhp->uid==ID_GFLAG ? UMSTAG_SelReadGlobal : TAG_IGNORE, TRUE,
                                                UMSTAG_SelWriteLocal, TRUE,
                                                UMSTAG_SelMask      , (ULONG)fhp->udata,
                                                UMSTAG_SelMatch     , chktrue(fhp->data) ? (ULONG)fhp->udata : 0,
                                                UMSTAG_SelSet       , FIL_LASTBIT,
                                                TAG_DONE);

                                        SetFromHelp(acc,FIL_LASTBIT,fhp);

                                        res = FIL_ERROR_OK;
                                }
                                break;

                                case ID_AGE:
                                case ID_DATE:
                                {
                                        LONG secs = fhp->uid==ID_DATE ? DateToSeconds(fhp->data) : (CurrentSeconds()/(24*60*60) - atol(fhp->data))*(24*60*60);

                                        if (secs>0)
                                        {
                                                UMSSelectTags(acc,
                                                        UMSTAG_SelWriteLocal, TRUE,
                                                        UMSTAG_SelDate      , secs,
                                                        UMSTAG_SelSet       , FIL_LASTBIT,
                                                        TAG_DONE);

                                                UMSSelectTags(acc,
                                                        UMSTAG_SelWriteLocal, TRUE,
                                                        UMSTAG_SelDate      , secs + 24*60*60-1,
                                                        UMSTAG_SelUnset     , FIL_LASTBIT,
                                                        TAG_DONE);

                                                SetFromHelp(acc,FIL_LASTBIT,fhp);

                                                res = FIL_ERROR_OK;
                                        }
                                }
                                break;

                                case ID_MSGNUM:
                                {
                                        UMSSelectTags(acc,
                                                UMSTAG_SelWriteLocal, TRUE,
                                                UMSTAG_SelStart     , atol(fhp->data),
                                                UMSTAG_SelStop      , atol(fhp->data)+1,
                                                UMSTAG_SelSet       , FIL_LASTBIT,
                                                TAG_DONE);

                                        SetFromHelp(acc,FIL_LASTBIT,fhp);

                                        res = FIL_ERROR_OK;
                                }
                                break;
                        }
                }
                break;

                case FIL_ACTION_LOWER:
                {
                        switch (fhp->uid)
                        {
                                case ID_LENGTH:
                                {
                                        UMSMsgNum nr=0L;

                                        while (nr = UMSSearchTags(acc,
                                                    UMSTAG_SearchLast   , nr,
                                                    UMSTAG_SearchLocal  , TRUE,
                                                    UMSTAG_SearchMask   , fhp->mask ,
                                                    UMSTAG_SearchMatch  , fhp->match,
                                                 TAG_DONE))
                                        {
                                                LONG size;

                                                if (UMSReadMsgTags(acc,
                                                    UMSTAG_RMsgNum    , nr,
                                                    UMSTAG_RNoUpdate  , TRUE,
                                                    (ULONG)fhp->udata , &size,
                                                    TAG_DONE))
                                                {
                                                        if (size<atol(fhp->data))
                                                        {
                                                                UMSSelectTags(acc,
                                                                        UMSTAG_SelWriteLocal, TRUE,
                                                                        UMSTAG_SelStart     , nr,
                                                                        UMSTAG_SelStop      , nr+1,
                                                                        UMSTAG_SelSet       , FIL_LASTBIT,
                                                                        TAG_DONE);
                                                        }
                                                }
                                        }

                                        SetFromHelp(acc,FIL_LASTBIT,fhp);

                                        res = FIL_ERROR_OK;
                                }
                                break;

                                case ID_AGE:
                                {
                                        LONG secs = (CurrentSeconds()/(24*60*60) - atol(fhp->data))*(24*60*60);

                                        if (secs>0)
                                        {
                                                UMSSelectTags(acc,
                                                        UMSTAG_SelWriteLocal, TRUE,
                                                        UMSTAG_SelDate      , secs + 24*60*60,
                                                        UMSTAG_SelSet       , fhp->set,
                                                        UMSTAG_SelUnset     , fhp->clear,
                                                        TAG_DONE);

                                                res = FIL_ERROR_OK;
                                        }
                                }
                                break;

                                case ID_DATE:
                                {
                                        LONG secs = DateToSeconds(fhp->data);

                                        if (secs>0)
                                        {
                                                UMSSelectTags(acc,
                                                        UMSTAG_SelWriteLocal, TRUE,
                                                        UMSTAG_SelMask      , 0,
                                                        UMSTAG_SelMatch     , 0,
                                                        UMSTAG_SelSet       , FIL_LASTBIT,
                                                        TAG_DONE);

                                                UMSSelectTags(acc,
                                                        UMSTAG_SelWriteLocal, TRUE,
                                                        UMSTAG_SelDate      , secs,
                                                        UMSTAG_SelUnset     , FIL_LASTBIT,
                                                        TAG_DONE);

                                                SetFromHelp(acc,FIL_LASTBIT,fhp);

                                                res = FIL_ERROR_OK;
                                        }
                                }
                                break;

                                case ID_MSGNUM:
                                {
                                        UMSSelectTags(acc,
                                                UMSTAG_SelWriteLocal, TRUE,
                                                UMSTAG_SelStart     , 0,
                                                UMSTAG_SelStop      , atol(fhp->data),
                                                UMSTAG_SelSet       , FIL_LASTBIT,
                                                TAG_DONE);

                                        SetFromHelp(acc,FIL_LASTBIT,fhp);

                                        res = FIL_ERROR_OK;
                                }
                                break;

                                default:
                                {
                                        res = FIL_ERROR_INVALIDRELATION;
                                }
                                break;
                        }
                }
                break;

                default:
                {
                        res = FIL_ERROR_INVALIDRELATION;
                }
                break;
        }
        return(res);
}


static const struct Hook bithook = { { NULL,NULL },(VOID *)bitfunc,NULL,NULL };


struct FilterSpec UmsFilterSpec[] =
{
        { "MsgText"      , ID_STRING , (APTR)UMSTAG_WMsgText       },
        { "FromName"     , ID_STRING , (APTR)UMSTAG_WFromName      },
        { "FromAddr"     , ID_STRING , (APTR)UMSTAG_WFromAddr      },
        { "ToName"       , ID_STRING , (APTR)UMSTAG_WToName        },
        { "ToAddr"       , ID_STRING , (APTR)UMSTAG_WToAddr        },
        { "MsgID"        , ID_STRING , (APTR)UMSTAG_WMsgID         },
        { "CreationDate" , ID_STRING , (APTR)UMSTAG_WCreationDate  },
        { "ReceiveDate"  , ID_STRING , (APTR)UMSTAG_WReceiveDate   },
        { "ReferID"      , ID_STRING , (APTR)UMSTAG_WReferID       },
        { "Group"        , ID_STRING , (APTR)UMSTAG_WGroup         },
        { "Subject"      , ID_STRING , (APTR)UMSTAG_WSubject       },
        { "Attributes"   , ID_STRING , (APTR)UMSTAG_WAttributes    },
        { "Comments"     , ID_STRING , (APTR)UMSTAG_WComments      },
        { "Organization" , ID_STRING , (APTR)UMSTAG_WOrganization  },
        { "Distribution" , ID_STRING , (APTR)UMSTAG_WDistribution  },
        { "Folder"       , ID_STRING , (APTR)UMSTAG_WFolder        },
        { "FidoID"       , ID_STRING , (APTR)UMSTAG_WFidoID        },
        { "MausID"       , ID_STRING , (APTR)UMSTAG_WMausID        },
        { "ReplyGroup"   , ID_STRING , (APTR)UMSTAG_WReplyGroup    },
        { "ReplyName"    , ID_STRING , (APTR)UMSTAG_WReplyName     },
        { "ReplyAddr"    , ID_STRING , (APTR)UMSTAG_WReplyAddr     },
        { "LogicalToName", ID_STRING , (APTR)UMSTAG_WLogicalToName },
        { "LogicalToAddr", ID_STRING , (APTR)UMSTAG_WLogicalToAddr },
        { "FileName"     , ID_STRING , (APTR)UMSTAG_WFileName      },
        { "RFCMsgNum"    , ID_STRING , (APTR)UMSTAG_WRFCMsgNum     },
        { "FidoText"     , ID_STRING , (APTR)UMSTAG_WFidoText      },
        { "ErrorText"    , ID_STRING , (APTR)UMSTAG_WErrorText     },
        { "Newsreader"   , ID_STRING , (APTR)UMSTAG_WNewsreader    },
        { "RFCAttr"      , ID_STRING , (APTR)UMSTAG_WRfcAttr       },
        { "FTNAttr"      , ID_STRING , (APTR)UMSTAG_WFtnAttr       },
        { "ZerAttr"      , ID_STRING , (APTR)UMSTAG_WZerAttr       },
        { "MausAttr"     , ID_STRING , (APTR)UMSTAG_WMausAttr      },
        { "TempFileName" , ID_STRING , (APTR)UMSTAG_WTempFileName  },

        { "Archive"      , ID_UFLAG  , (APTR)UMSUSTATF_Archive     },
        { "Junk"         , ID_UFLAG  , (APTR)UMSUSTATF_Junk        },
        { "PostPoned"    , ID_UFLAG  , (APTR)UMSUSTATF_PostPoned   },
        { "Selected"     , ID_UFLAG  , (APTR)UMSUSTATF_Selected    },
        { "Old"          , ID_UFLAG  , (APTR)UMSUSTATF_Old         },
        { "WriteAccess"  , ID_UFLAG  , (APTR)UMSUSTATF_WriteAccess },
        { "ReadAccess"   , ID_UFLAG  , (APTR)UMSUSTATF_ReadAccess  },
        { "ViewAccess"   , ID_UFLAG  , (APTR)UMSUSTATF_ViewAccess  },
        { "Owner"        , ID_UFLAG  , (APTR)UMSUSTATF_Owner       },

        { "UFlag0"       , ID_UFLAG  , (APTR)(1<<0 )               },
        { "UFlag1"       , ID_UFLAG  , (APTR)(1<<1 )               },
        { "UFlag2"       , ID_UFLAG  , (APTR)(1<<2 )               },
        { "UFlag3"       , ID_UFLAG  , (APTR)(1<<3 )               },
        { "UFlag4"       , ID_UFLAG  , (APTR)(1<<4 )               },
        { "UFlag5"       , ID_UFLAG  , (APTR)(1<<5 )               },
        { "UFlag6"       , ID_UFLAG  , (APTR)(1<<6 )               },
        { "UFlag7"       , ID_UFLAG  , (APTR)(1<<7 )               },
        { "UFlag8"       , ID_UFLAG  , (APTR)(1<<8 )               },
        { "UFlag9"       , ID_UFLAG  , (APTR)(1<<9 )               },
        { "UFlagA"       , ID_UFLAG  , (APTR)(1<<10)               },
        { "UFlagB"       , ID_UFLAG  , (APTR)(1<<11)               },
        { "UFlagC"       , ID_UFLAG  , (APTR)(1<<12)               },
        { "UFlagD"       , ID_UFLAG  , (APTR)(1<<13)               },
        { "UFlagE"       , ID_UFLAG  , (APTR)(1<<14)               },
        { "UFlagF"       , ID_UFLAG  , (APTR)(1<<15)               },

        { "Deleted"      , ID_GFLAG  , (APTR)UMSGSTATF_Deleted     },
        { "Expired"      , ID_GFLAG  , (APTR)UMSGSTATF_Expired     },
        { "Exported"     , ID_GFLAG  , (APTR)UMSGSTATF_Exported    },
        { "Orphan"       , ID_GFLAG  , (APTR)UMSGSTATF_Orphan      },
        { "Link"         , ID_GFLAG  , (APTR)UMSGSTATF_Link        },
        { "Hardlink"     , ID_GFLAG  , (APTR)UMSGSTATF_HardLink    },
        { "Parked"       , ID_GFLAG  , (APTR)UMSGSTATF_Parked      },
        { "HasFile"      , ID_GFLAG  , (APTR)UMSGSTATF_HasFile     },

        { "Age"          , ID_AGE    , 0                           },
        { "Date"         , ID_DATE   , 0                           },
        { "MsgNum"       , ID_MSGNUM , NULL                        },

        { "TextLength"   , ID_LENGTH , (APTR)UMSTAG_RTextLength    },
        { "HeaderLength" , ID_LENGTH , (APTR)UMSTAG_RHeaderLength  },

        { NULL          , NULL      , NULL                        }
};


LONG UmsFilterExpression(char *str,UMSAccount acc,ULONG mask,ULONG match,ULONG setbit)
{
        return(FilterExpression((struct Hook *)&bithook,UmsFilterSpec,str,acc,mask,match,setbit));
}
