// scanner.hpp
//
// (C) 2002-2009 MicroNeil Research Corporation

// 20040113 _M - Added Reset() to the scanner object to more completely handle
// cleanup after processing a message. Where previously the calling code would
// need to be sure it deleted the evaulation matrix when it was done, now it
// should call Reset. Reset is also included now in the destructor for this
// object.

// 20030928 _M - Moving toward the peer-server architecture and V3. The message
// scanning component has been moved into it's own object called "scanner". From
// now on, a message, or text will be passed to the scanner and the scanner will
// return an evaulation matrix. As always, if something goes wrong it will throw.
// This allows us to separate the creation of a scanner, and it's use, from any
// other nifty logic. So, if I'm in a server mode, I can take my scanner and throw
// messages at it as often as I like. Each message I pump in one side comes out the
// other side as an evaluation matrix. This will work well for SMTP based engines
// as well as peer-server, or any other "service pipeline".
//
// Note that the scanner object has two ways it will accept data. One way is as a
// message via .ScanMessage(c_str). This method employs the filter chain system and
// expects to see an SMTP message. The second way is as plain text via .ScanText(c_str).
// This method is useful for "internal" purposes such as secondary scans used to
// locate compound rules or parameter scans used to pick up tuning data from the
// rulebase.

#ifndef _MN_Scanner
#define _MN_Scanner

#include "FilterChain.hpp"
#include "snf_engine.hpp"

const int ScanHorizon = 32768;      // Maximum length of message to check.

class Scanner {

  private:

    TokenMatrix RuleBase;                                      // The RuleBase for this scanner.

    EvaluationMatrix* myEvaluationMatrix;                      // Evaluation Matrix for current scan.

  public:

    class BadMatrixAllocation {};                              // Exception for failed allocation.

    Scanner() {myEvaluationMatrix=NULL;}                       // Construct with empty matrix.
    
    ~Scanner() {Reset();}                                      // Destructor now cleans up.

    void Reset() {                                             // Reset safely deletes the eval
      if(myEvaluationMatrix!=NULL){                            // matrix and nulls it's pointer.
        delete myEvaluationMatrix;
        myEvaluationMatrix=NULL;
      }
    }

    void LoadRuleBase(string& RuleFileName, string& SecurityKey);  // Load & Validate RuleBase.

    EvaluationMatrix* ScanMessage(unsigned char* MessageBuffer);   // Scan with filter chain.

    EvaluationMatrix* ScanText(unsigned char* TextBuffer);         // Scan without filter chain.

    inline EvaluationMatrix* GetMatrix(){return myEvaluationMatrix;}  // Return the latest matrix.
    
};

#endif
