#include "PacketFilterExpression.h"
#include "Logger/Logger.h"

string& trim(const string& sOriginal) {
  
  string::const_iterator leftIt = sOriginal.begin();
  string::const_iterator rightIt = sOriginal.end();
  
  while(leftIt != sOriginal.end() && (*leftIt) == ' ')
    leftIt++;

  rightIt--;
  while(rightIt != sOriginal.begin() && (*rightIt) == ' ')
    rightIt--;
  
  string *result = new string(sOriginal.substr(leftIt - sOriginal.begin(), rightIt - leftIt + 1));
  
  return *result;
}

PacketFilterExpression::PacketFilterExpression(const string& sExpression)
  :m_operator(EO_NONE),
   m_headerId(e_NoHeader),
   m_fieldId(e_NoField),
   m_value(""),
   m_leftPart("") {
  
  int pos;
  string sHeaderName, sFieldName;
  
  if((pos = sExpression.find("==")) != string::npos) 
    m_operator = EO_EQUAL;
  else if((pos = sExpression.find("!=")) != string::npos) 
    m_operator = EO_DIFFERENT;

  if(m_operator != EO_NONE) {
    m_value = trim(sExpression.substr(pos + 2, string::npos));
    m_leftPart = sExpression.substr(0, pos);
    if((pos = m_leftPart.find(".")) != string::npos) {
      sHeaderName = m_leftPart.substr(0, pos);
      if(trim(sHeaderName) == "ip") {
	m_headerId = e_Ip;
      }
      else if(trim(sHeaderName) == "tcp") {
	m_headerId = e_Tcp;
      }
      else if(trim(sHeaderName) == "udp") {
	m_headerId = e_Udp;
      }
      else {
	Logger::Instance().LogError("Bad filter: unsupported protocol for IP header");
      }
    
      sFieldName = m_leftPart.substr(pos + 1, string::npos);
      if(trim(sFieldName) == "addr") {
	m_fieldId = e_Addr;
      }
      else if(trim(sFieldName) == "src") {
	m_fieldId = e_Src;
      }
      else if(trim(sFieldName) == "dst") {
	m_fieldId = e_Dst;
      }
      else if(trim(sFieldName) == "port") {
	m_fieldId = e_Port;
      }
      else if(trim(sFieldName) == "srcport") {
	m_fieldId = e_SrcPort;
      }
      else if(trim(sFieldName) == "dstport") {
	m_fieldId = e_DstPort;
      }
      else if(trim(sFieldName) == "proto") {
	m_fieldId = e_Proto;
      }
      else {
	Logger::Instance().LogError("Bad filter: unsupported field name");
      }
    }
    else {
      	Logger::Instance().LogError("Bad filter: left part should be header.field");
    }
  }
  else {
    m_value = trim(sExpression);
  }
}

PacketFilterExpression::~PacketFilterExpression() {

}

const string& PacketFilterExpression::GetExpression() const {
  string *s = new string("");
  
  if(m_operator != EO_NONE)
    *s += m_leftPart;
  
  if(m_operator == EO_EQUAL) 
    *s += "==";
  
  if(m_operator == EO_DIFFERENT) 
    *s += "!=";
  
  *s += m_value;
  
  return *s;
}

bool PacketFilterExpression::Match(const PacketDissector& packet) const {
  
  return packet.Match(m_headerId, m_fieldId, m_value);
  
}

