'''
libdspam, version 0.4
  
(c) 2004 Jan ONDREJ (SAL) <ondrejj(at)salstar.sk>
   
  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.
'''

DSF_CHAINED = 0x01
DSF_SIGNATURE = 0x02
DSF_COPYBACK = 0x04
DSF_NOISE = 0x08
DSF_WHITELIST = 0x10
DSF_MERGED = 0x20

DSM_PROCESS = 0x00
DSM_TOOLS = 0x01
DSM_CLASSIFY = 0x02
DSM={DSM_PROCESS:"PROCESS",DSM_TOOLS:"TOOLS",DSM_CLASSIFY:"CLASSIFY"}

DST_TEFT = 0x00
DST_TOE = 0x01
DST_TUM = 0x02
DST_NOTRAIN = 0xFF
DST={DST_TEFT:"TEFT",DST_TOE:"TOE",DST_TUM:"TUM",DST_NOTRAIN:"NOTRAIN"}

DSR_ISSPAM = 0x01
DSR_ISINNOCENT = 0x02
DSR_NONE = 0xFF
DSR={DSR_ISSPAM:'SPAM', DSR_ISINNOCENT:'INNOCENT', DSR_NONE:"NONE"}

DSS_ERROR = 0x00
DSS_CORPUS = 0x01
DSS_INOCULATION = 0x02
DSS_NONE = 0x0F
DSS={DSS_ERROR:"ERROR", DSS_CORPUS:"CORPUS", DSS_INOCULATION:"INNOCULATION",
     DSS_NONE:"NONE"}

cdef extern from "const_types.h":
     ctypedef char constchar

cdef extern from "libdspam.h":
     ctypedef unsigned int u_int32_t
     ctypedef unsigned int size_t
     struct _ds_spam_signature_t:
       void *data
       long length
     ctypedef _ds_spam_signature_t _ds_spam_signature
     struct _ds_spam_totals_t:
       long spam_learned
       long innocent_learned
       long spam_misclassified
       long innocent_misclassified
       long spam_corpusfed
       long innocent_corpusfed
       long spam_classified
       long innocent_classified
     ctypedef _ds_spam_totals_t _ds_spam_totals
     struct DSPAM_CTX_t:
       _ds_spam_totals *totals
       _ds_spam_signature *signature
       void *message
       char *username
       char *group
       int operating_mode
       int training_mode
       int training_buffer
       int classification
       int source
       u_int32_t flags
       int result
       float probability
       float confidence
     ctypedef DSPAM_CTX_t DSPAM_CTX
     struct DRIVER_CTX_t:
       DSPAM_CTX *CTX
       int status
       int flags
       int connection_cache
       void **connections
     ctypedef DRIVER_CTX_t DRIVER_CTX
     DSPAM_CTX *dspam_init(char *username, char *group, char *home, int operating_mode, u_int32_t flags)
     DSPAM_CTX *dspam_create(char *username, char *group, char *home, int operating_mode, u_int32_t flags)
     int dspam_attach (DSPAM_CTX *CTX, void *dbh)
     int dspam_detach (DSPAM_CTX *CTX)
     int dspam_process(DSPAM_CTX *CTX, char *message)
     void dspam_destroy(DSPAM_CTX *CTX)
     int dspam_getsource(DSPAM_CTX *CTX, char *buf, size_t size)
     int dspam_addattribute(DSPAM_CTX *CTX, char *name, char *value)
     int dspam_clearattributes(DSPAM_CTX *CTX)

cdef extern from "storage_driver.h":
     int dspam_init_driver(DRIVER_CTX *DTX)
     int dspam_shutdown_driver(DRIVER_CTX *DTX)
     int _ds_delete_signature(DSPAM_CTX *CTX, char *signature)
     int _ds_get_signature(DSPAM_CTX *CTX, _ds_spam_signature *SIG, char *signature)
     int _ds_set_signature(DSPAM_CTX *CTX, _ds_spam_signature *SIG, char *signature)
     int _ds_verify_signature(DSPAM_CTX *CTX, char *signature)
     int _ds_create_signature_id(DSPAM_CTX *CTX, char *buf, size_t len)

cdef extern from "stdlib.h":
     void *malloc(size_t size)
     void free(void *ptr)

class DSpamError(Exception):
      '''DSpamError'''
      pass

cdef class dspam:
  cdef DSPAM_CTX *CTX
  cdef DRIVER_CTX DTX
  cdef public int result
  cdef int ec
  def __init__(self,home,op=DSM_PROCESS,flags=DSF_CHAINED|DSF_SIGNATURE|DSF_NOISE|DSF_COPYBACK,user='root',group='root'):
      self.CTX=dspam_init(user, group, home, op, flags);
      if self.CTX==NULL:
        raise DSpamError,(0,"dspam_init failed!")
  def __del__(self):
      dspam_destroy(self.CTX)
  def check_error(self,es):
      if self.ec!=0:
        raise DSpamError,(self.ec,es+" failed ("+str(self.ec)+")!")
  def training_mode(self,mode):
      self.CTX.training_mode=mode
  def classification(self,classification):
      self.CTX.classification=classification
  def source(self,source):
      self.CTX.source=source
  def init_driver(self):
      self.ec=dspam_init_driver(&self.DTX)
      self.check_error("dspam_init_driver")
  def shutdown_driver(self):
      self.ec=dspam_shutdown_driver(&self.DTX)
      self.check_error("dspam_shutdown_driver")
  def attach(self):
      self.ec=dspam_attach(self.CTX,&self.DTX)
      self.check_error("dspam_attach")
  def detach(self):
      self.ec=dspam_detach(self.CTX)
      self.check_error("dspam_detach")
  def process(self,message):
      self.ec=dspam_process(self.CTX, message)
      self.check_error("dspam_process")
      return self.CTX.result,self.CTX.probability,self.CTX.confidence
  def getsource(self,buf,size):
      self.ec=dspam_getsource(self.CTX,buf,size)
      self.check_error("dspam_getsource")
  def addattribute(self,name,value):
      self.ec=dspam_addattribute(self.CTX,name,value)
      self.check_error("dspam_addattribute")
  def clearattributes(self):
      self.ec=dspam_clearattributes(self.CTX)
      self.check_error("dspam_clearattributes")
  def create_signature_id(self):
      cdef char buf[128]
      cdef size_t len
      while True:
        _ds_create_signature_id(self.CTX, buf, sizeof(buf))
        if _ds_verify_signature(self.CTX, buf):
          break
      return buf
  def delete_signature(self,signature):
      self.ec=_ds_delete_signature(self.CTX, signature)
      self.check_error("delete_signature('%s')" % signature)
  def get_signature(self,signature):
      cdef _ds_spam_signature_t *SIG
      SIG=<_ds_spam_signature_t *>malloc(sizeof(SIG))
      self.ec=_ds_get_signature(self.CTX, SIG, signature)
      self.check_error("get_signature('%s')" % signature)
      self.CTX.signature=SIG
  def set_signature(self,signature):
      self.ec=_ds_set_signature(self.CTX, self.CTX.signature, signature)
      self.check_error("set_signature('%s')" % signature)
  def save_signature(self):
      if self.CTX.signature!=NULL:
        sig=self.create_signature_id()
        self.set_signature(sig)
        return sig
      else:
        return ''
