[Spambayes-checkins] spambayes/spambayes Corpus.py, 1.11, 1.12 Dibbler.py, 1.10, 1.11 ImapUI.py, 1.29, 1.30 Options.py, 1.91, 1.92 OptionsClass.py, 1.20, 1.21 ProxyUI.py, 1.33, 1.34 ServerUI.py, 1.4, 1.5 UserInterface.py, 1.37, 1.38 dbmstorage.py, 1.10, 1.11 message.py, 1.44, 1.45 oe_mailbox.py, 1.2, 1.3 smtpproxy.py, 1.4, 1.5 storage.py, 1.36, 1.37 tokenizer.py, 1.21, 1.22

Tim Peters tim_one at users.sourceforge.net
Tue Dec 16 00:06:36 EST 2003


Update of /cvsroot/spambayes/spambayes/spambayes
In directory sc8-pr-cvs1:/tmp/cvs-serv12349/spambayes

Modified Files:
	Corpus.py Dibbler.py ImapUI.py Options.py OptionsClass.py 
	ProxyUI.py ServerUI.py UserInterface.py dbmstorage.py 
	message.py oe_mailbox.py smtpproxy.py storage.py tokenizer.py 
Log Message:
Whitespace normalization.


Index: Corpus.py
===================================================================
RCS file: /cvsroot/spambayes/spambayes/spambayes/Corpus.py,v
retrieving revision 1.11
retrieving revision 1.12
diff -C2 -d -r1.11 -r1.12
*** Corpus.py	15 Dec 2003 07:06:23 -0000	1.11
--- Corpus.py	16 Dec 2003 05:06:34 -0000	1.12
***************
*** 151,155 ****
          # This method should probably not be overridden
          key = message.key()
!         
          if options["globals", "verbose"]:
              print 'placing %s in corpus cache' % (key)
--- 151,155 ----
          # This method should probably not be overridden
          key = message.key()
! 
          if options["globals", "verbose"]:
              print 'placing %s in corpus cache' % (key)

Index: Dibbler.py
===================================================================
RCS file: /cvsroot/spambayes/spambayes/spambayes/Dibbler.py,v
retrieving revision 1.10
retrieving revision 1.11
diff -C2 -d -r1.10 -r1.11
*** Dibbler.py	11 Dec 2003 18:40:54 -0000	1.10
--- Dibbler.py	16 Dec 2003 05:06:34 -0000	1.11
***************
*** 422,426 ****
                             for line in headers.split('\r\n')
                             if headersRegex.match(line)])
!         
          # HTTP Basic/Digest Authentication support.
          serverAuthMode = self._server.requestAuthenticationMode()
--- 422,426 ----
                             for line in headers.split('\r\n')
                             if headersRegex.match(line)])
! 
          # HTTP Basic/Digest Authentication support.
          serverAuthMode = self._server.requestAuthenticationMode()
***************
*** 474,478 ****
                              if isinstance(dispatcher, Listener):
                                  dispatcher.close()
!                         
                          # Let any existing connections close down first.  This
                          # has happened when all we have left are _HTTPHandlers
--- 474,478 ----
                              if isinstance(dispatcher, Listener):
                                  dispatcher.close()
! 
                          # Let any existing connections close down first.  This
                          # has happened when all we have left are _HTTPHandlers
***************
*** 482,491 ****
                          def isProtected(dispatcher):
                              return not isinstance(dispatcher, _HTTPHandler)
!                         
                          while len(filter(isProtected, contextMap.values())) > 0:
                              asyncore.poll(timeout=1, map=contextMap)
!                         
                          raise SystemExit
!                         
                      message = """<h3>500 Server error</h3><pre>%s</pre>"""
                      details = traceback.format_exception(eType, eValue, eTrace)
--- 482,491 ----
                          def isProtected(dispatcher):
                              return not isinstance(dispatcher, _HTTPHandler)
! 
                          while len(filter(isProtected, contextMap.values())) > 0:
                              asyncore.poll(timeout=1, map=contextMap)
! 
                          raise SystemExit
! 
                      message = """<h3>500 Server error</h3><pre>%s</pre>"""
                      details = traceback.format_exception(eType, eValue, eTrace)
***************
*** 560,564 ****
              self.writeError(500, "Inconsistent authentication mode.")
              return
!         
          headers = []
          headers.append('HTTP/1.0 401 Unauthorized')
--- 560,564 ----
              self.writeError(500, "Inconsistent authentication mode.")
              return
! 
          headers = []
          headers.append('HTTP/1.0 401 Unauthorized')
***************
*** 586,590 ****
  
      def _getCurrentNonce(self):
!         """Returns the current nonce value. This value is a Base64 encoding 
          of current time plus 20 minutes. This means the nonce will expire 20
          minutes from now."""
--- 586,590 ----
  
      def _getCurrentNonce(self):
!         """Returns the current nonce value. This value is a Base64 encoding
          of current time plus 20 minutes. This means the nonce will expire 20
          minutes from now."""
***************
*** 613,617 ****
          def stripQuotes(s):
              return (s[0] == '"' and s[-1] == '"') and s[1:-1] or s
!         
          options  = dict([s.split('=') for s in login.split(", ")])
          userName = stripQuotes(options["username"])
--- 613,617 ----
          def stripQuotes(s):
              return (s[0] == '"' and s[-1] == '"') and s[1:-1] or s
! 
          options  = dict([s.split('=') for s in login.split(", ")])
          userName = stripQuotes(options["username"])

Index: ImapUI.py
===================================================================
RCS file: /cvsroot/spambayes/spambayes/spambayes/ImapUI.py,v
retrieving revision 1.29
retrieving revision 1.30
diff -C2 -d -r1.29 -r1.30
*** ImapUI.py	16 Dec 2003 00:30:49 -0000	1.29
--- ImapUI.py	16 Dec 2003 05:06:34 -0000	1.30
***************
*** 255,259 ****
          UserInterface.UserInterface.onChangeopts(self, **parms)
          self.parm_ini_map = backup
!         
      def _buildFolderBox(self, section, option, available_folders):
          folderTable = self.html.configTable.clone()
--- 255,259 ----
          UserInterface.UserInterface.onChangeopts(self, **parms)
          self.parm_ini_map = backup
! 
      def _buildFolderBox(self, section, option, available_folders):
          folderTable = self.html.configTable.clone()

Index: Options.py
===================================================================
RCS file: /cvsroot/spambayes/spambayes/spambayes/Options.py,v
retrieving revision 1.91
retrieving revision 1.92
diff -C2 -d -r1.91 -r1.92
*** Options.py	16 Dec 2003 02:03:30 -0000	1.91
--- Options.py	16 Dec 2003 05:06:34 -0000	1.92
***************
*** 165,171 ****
       are generated for messages with habeas headers.  This should be fine,
       since messages with the headers should either be ham, or result in FN
!      so that we can send them to habeas so they can be sued.  However, to 
!      reduce the strength of habeas headers, we offer the ability to reduce 
!      the nine tokens to one. (This option has no effect if 
       search_for_habeas_headers is False)""",
       BOOLEAN, RESTORE),
--- 165,171 ----
       are generated for messages with habeas headers.  This should be fine,
       since messages with the headers should either be ham, or result in FN
!      so that we can send them to habeas so they can be sued.  However, to
!      reduce the strength of habeas headers, we offer the ability to reduce
!      the nine tokens to one. (This option has no effect if
       search_for_habeas_headers is False)""",
       BOOLEAN, RESTORE),
***************
*** 364,368 ****
       assigning certainty (0 or 1) to a word that has appeared in only ham
       or only spam.  This is a disaster.
!      
       As unknown_word_strength tends toward infintity, all probabilities
       tend toward unknown_word_prob.  All reports were that a value near 0.4
--- 364,368 ----
       assigning certainty (0 or 1) to a word that has appeared in only ham
       or only spam.  This is a disaster.
! 
       As unknown_word_strength tends toward infintity, all probabilities
       tend toward unknown_word_prob.  All reports were that a value near 0.4
***************
*** 975,979 ****
       PORT, RESTORE),
    ),
!  
    "globals" : (
      ("verbose", "Verbose", False,
--- 975,979 ----
       PORT, RESTORE),
    ),
! 
    "globals" : (
      ("verbose", "Verbose", False,
***************
*** 1037,1041 ****
              options.merge_files(alts)
              optionsPathname = os.path.abspath(alts[-1])
!     
      if not optionsPathname:
          optionsPathname = os.path.abspath('bayescustomize.ini')
--- 1037,1041 ----
              options.merge_files(alts)
              optionsPathname = os.path.abspath(alts[-1])
! 
      if not optionsPathname:
          optionsPathname = os.path.abspath('bayescustomize.ini')

Index: OptionsClass.py
===================================================================
RCS file: /cvsroot/spambayes/spambayes/spambayes/OptionsClass.py,v
retrieving revision 1.20
retrieving revision 1.21
diff -C2 -d -r1.20 -r1.21
*** OptionsClass.py	16 Dec 2003 04:48:28 -0000	1.20
--- OptionsClass.py	16 Dec 2003 05:06:34 -0000	1.21
***************
*** 146,150 ****
          '''Multiple values are allowed for this option.'''
          return type(self.value) in MultiContainerTypes
!     
      def is_valid(self, value):
          '''Check if this is a valid value for this option.'''
--- 146,150 ----
          '''Multiple values are allowed for this option.'''
          return type(self.value) in MultiContainerTypes
! 
      def is_valid(self, value):
          '''Check if this is a valid value for this option.'''
***************
*** 193,197 ****
                  # either no match or too many matches
                  return False
!             
      def _split_values(self, value):
          # do the regex mojo here
--- 193,197 ----
                  # either no match or too many matches
                  return False
! 
      def _split_values(self, value):
          # do the regex mojo here
***************
*** 470,474 ****
          out.close()
          f.close()
!     
      def _add_missing(self, out, written, sect, vi, label=True):
          # add any missing ones, where the value does not equal the default
--- 470,474 ----
          out.close()
          f.close()
! 
      def _add_missing(self, out, written, sect, vi, label=True):
          # add any missing ones, where the value does not equal the default
***************
*** 503,507 ****
                  except TypeError: # opt[0] not a class
                      pass
!                         
                  o = klass(*args)
                  self._options[section, o.name] = o
--- 503,507 ----
                  except TypeError: # opt[0] not a class
                      pass
! 
                  o = klass(*args)
                  self._options[section, o.name] = o
***************
*** 607,611 ****
          else:
              print >> sys.stderr, ("Attempted to set [%s] %s with invalid"
!                                   " value %s (%s)" % 
                                    (sect, opt.lower(), val, type(val)))
  
--- 607,611 ----
          else:
              print >> sys.stderr, ("Attempted to set [%s] %s with invalid"
!                                   " value %s (%s)" %
                                    (sect, opt.lower(), val, type(val)))
  
***************
*** 667,671 ****
          all.sort()
          return all
!     
      def options_in_section(self, section):
          '''Return an alphabetical list of all the options in this section.'''
--- 667,671 ----
          all.sort()
          return all
! 
      def options_in_section(self, section):
          '''Return an alphabetical list of all the options in this section.'''
***************
*** 707,730 ****
  
      def display_full(self, section=None, option=None):
!        '''Display options including all information.'''
!        # Given that the Options class is no longer as nice looking
!        # as it once was, this returns all the information, i.e.
!        # the doc, default values, and so on
!        output = StringIO.StringIO()
  
!        # when section and option are both specified, this
!        # is nothing more than a call to as_nice_string
!        if section is not None and option is not None:
!            output.write(self._options[section,
!                                       option.lower()].as_nice_string(section))
!            return output.getvalue()
!        
!        all = self._options.keys()
!        all.sort()
!        for sect, opt in all:
!            if section is not None and sect != section:
!                continue
!            output.write(self._options[sect, opt.lower()].as_nice_string(sect))
!        return output.getvalue()
  
  # These are handy references to commonly used regex/tuples defining
--- 707,730 ----
  
      def display_full(self, section=None, option=None):
!         '''Display options including all information.'''
!         # Given that the Options class is no longer as nice looking
!         # as it once was, this returns all the information, i.e.
!         # the doc, default values, and so on
!         output = StringIO.StringIO()
  
!         # when section and option are both specified, this
!         # is nothing more than a call to as_nice_string
!         if section is not None and option is not None:
!             output.write(self._options[section,
!                                        option.lower()].as_nice_string(section))
!             return output.getvalue()
! 
!         all = self._options.keys()
!         all.sort()
!         for sect, opt in all:
!             if section is not None and sect != section:
!                 continue
!             output.write(self._options[sect, opt.lower()].as_nice_string(sect))
!         return output.getvalue()
  
  # These are handy references to commonly used regex/tuples defining

Index: ProxyUI.py
===================================================================
RCS file: /cvsroot/spambayes/spambayes/spambayes/ProxyUI.py,v
retrieving revision 1.33
retrieving revision 1.34
diff -C2 -d -r1.33 -r1.34
*** ProxyUI.py	16 Dec 2003 00:30:49 -0000	1.33
--- ProxyUI.py	16 Dec 2003 05:06:34 -0000	1.34
***************
*** 700,704 ****
  
          if pmap == adv_map:
!           return errmsg
  
          # check for equal number of pop3servers and ports
--- 700,704 ----
  
          if pmap == adv_map:
!             return errmsg
  
          # check for equal number of pop3servers and ports

Index: ServerUI.py
===================================================================
RCS file: /cvsroot/spambayes/spambayes/spambayes/ServerUI.py,v
retrieving revision 1.4
retrieving revision 1.5
diff -C2 -d -r1.4 -r1.5
*** ServerUI.py	15 Dec 2003 00:16:20 -0000	1.4
--- ServerUI.py	16 Dec 2003 05:06:34 -0000	1.5
***************
*** 105,109 ****
          # we have a few extra checks
          errmsg = UserInterface.UserInterface.verifyInput(self, parms)
!         
          # check for equal number of pop3servers and ports
          slist = list(parms['pop3proxy_remote_servers'])
--- 105,109 ----
          # we have a few extra checks
          errmsg = UserInterface.UserInterface.verifyInput(self, parms)
! 
          # check for equal number of pop3servers and ports
          slist = list(parms['pop3proxy_remote_servers'])

Index: UserInterface.py
===================================================================
RCS file: /cvsroot/spambayes/spambayes/spambayes/UserInterface.py,v
retrieving revision 1.37
retrieving revision 1.38
diff -C2 -d -r1.37 -r1.38
*** UserInterface.py	16 Dec 2003 02:46:42 -0000	1.37
--- UserInterface.py	16 Dec 2003 05:06:34 -0000	1.38
***************
*** 130,139 ****
  
          if trustedIPs == "*" or remoteIP == clientSocket.getsockname()[0]:
!            return True
  
          trustedIPs = trustedIPs.replace('.', '\.').replace('*', '([01]?\d\d?|2[04]\d|25[0-5])')
          for trusted in trustedIPs.split(','):
!           if re.search("^" + trusted + "$", remoteIP):
!              return True
  
          return False
--- 130,139 ----
  
          if trustedIPs == "*" or remoteIP == clientSocket.getsockname()[0]:
!             return True
  
          trustedIPs = trustedIPs.replace('.', '\.').replace('*', '([01]?\d\d?|2[04]\d|25[0-5])')
          for trusted in trustedIPs.split(','):
!             if re.search("^" + trusted + "$", remoteIP):
!                 return True
  
          return False
***************
*** 299,303 ****
                                        nham, nspam)
          return cluesTable
!     
      def _buildCluesTable(self, message, subject=None, show_tokens=False):
          tokens = list(tokenizer.tokenize(message))
--- 299,303 ----
                                        nham, nspam)
          return cluesTable
! 
      def _buildCluesTable(self, message, subject=None, show_tokens=False):
          tokens = list(tokenizer.tokenize(message))
***************
*** 477,481 ****
          # Attempt to convert the content from a DBX file to a standard mbox
          if file:
!           content = self._convertToMbox(content)
  
          # Convert platform-specific line endings into unix-style.
--- 477,481 ----
          # Attempt to convert the content from a DBX file to a standard mbox
          if file:
!             content = self._convertToMbox(content)
  
          # Convert platform-specific line endings into unix-style.
***************
*** 513,517 ****
          """Check if the given buffer is in a non-mbox format, and convert it
          into mbox format if so.  If it's already an mbox, return it unchanged.
!         
          Currently, the only supported non-mbox format is Outlook Express DBX.
          In such a case we use the module oe_mailbox to convert the DBX
--- 513,517 ----
          """Check if the given buffer is in a non-mbox format, and convert it
          into mbox format if so.  If it's already an mbox, return it unchanged.
! 
          Currently, the only supported non-mbox format is Outlook Express DBX.
          In such a case we use the module oe_mailbox to convert the DBX
***************
*** 527,536 ****
              fh_entries = oe_mailbox.dbxFileHeader.FH_ENTRIES
              fh_ptr = oe_mailbox.dbxFileHeader.FH_TREE_ROOT_NODE_PTR
!             
              info = oe_mailbox.dbxFileInfo(dbxStream,
                                            header.getEntry(file_info_len))
              entries = header.getEntry(fh_entries)
              address = header.getEntry(fh_ptr)
!             
              if address and entries:
                  tree = oe_mailbox.dbxTree(dbxStream, address, entries)
--- 527,536 ----
              fh_entries = oe_mailbox.dbxFileHeader.FH_ENTRIES
              fh_ptr = oe_mailbox.dbxFileHeader.FH_TREE_ROOT_NODE_PTR
! 
              info = oe_mailbox.dbxFileInfo(dbxStream,
                                            header.getEntry(file_info_len))
              entries = header.getEntry(fh_entries)
              address = header.getEntry(fh_ptr)
! 
              if address and entries:
                  tree = oe_mailbox.dbxTree(dbxStream, address, entries)
***************
*** 863,867 ****
                  if options.multiple_values_allowed(sect, opt) and \
                     value == "":
!                         value = ()
                  value = options.convert(sect, opt, value)
              if not options.is_valid(sect, opt, value):
--- 863,867 ----
                  if options.multiple_values_allowed(sect, opt) and \
                     value == "":
!                     value = ()
                  value = options.convert(sect, opt, value)
              if not options.is_valid(sect, opt, value):

Index: dbmstorage.py
===================================================================
RCS file: /cvsroot/spambayes/spambayes/spambayes/dbmstorage.py,v
retrieving revision 1.10
retrieving revision 1.11
diff -C2 -d -r1.10 -r1.11
*** dbmstorage.py	26 Nov 2003 01:13:02 -0000	1.10
--- dbmstorage.py	16 Dec 2003 05:06:34 -0000	1.11
***************
*** 15,19 ****
  
  def open_dbhash(*args):
!     """Open a bsddb hash.  Don't use this on Windows, unless Python 2.3 or 
      greater is used, in which case bsddb3 is actually named bsddb."""
      import bsddb
--- 15,19 ----
  
  def open_dbhash(*args):
!     """Open a bsddb hash.  Don't use this on Windows, unless Python 2.3 or
      greater is used, in which case bsddb3 is actually named bsddb."""
      import bsddb

Index: message.py
===================================================================
RCS file: /cvsroot/spambayes/spambayes/spambayes/message.py,v
retrieving revision 1.44
retrieving revision 1.45
diff -C2 -d -r1.44 -r1.45
*** message.py	11 Dec 2003 18:45:31 -0000	1.44
--- message.py	16 Dec 2003 05:06:34 -0000	1.45
***************
*** 164,168 ****
          self.load()
  
!     def load(self):        
          try:
              self.dbm = dbmstorage.open(self.db_name, self.mode)
--- 164,168 ----
          self.load()
  
!     def load(self):
          try:
              self.dbm = dbmstorage.open(self.db_name, self.mode)
***************
*** 179,183 ****
          self.close()
  
!     def close(self):        
          # Close our underlying database.  Better not assume all databases
          # have close functions!
--- 179,183 ----
          self.close()
  
!     def close(self):
          # Close our underlying database.  Better not assume all databases
          # have close functions!

Index: oe_mailbox.py
===================================================================
RCS file: /cvsroot/spambayes/spambayes/spambayes/oe_mailbox.py,v
retrieving revision 1.2
retrieving revision 1.3
diff -C2 -d -r1.2 -r1.3
*** oe_mailbox.py	11 Dec 2003 18:45:46 -0000	1.2
--- oe_mailbox.py	16 Dec 2003 05:06:34 -0000	1.3
***************
*** 16,118 ****
  ###########################################################################
  class dbxFileHeader:
!   """
!      Each Outlook Express DBX file has a file header.
!      This header defines many properties, only a few of which interest us.
  
!      The only properties which are required are defined by indexes. The
!      indexes are static attributes of the class and their names begin with
!      "fh". You can access their values through the method getEntry().
!   """
  
!   HEADER_SIZE    = 0x24bc              # total header size
!   HEADER_ENTRIES = HEADER_SIZE >> 2    # total of entries in the header
  
!   MAGIC_NUMBER   = 0xfe12adcfL         # specific to DBX files
!   OFFLINE        = 0x26fe9d30L         # specific to offline.dbx
!   FOLDERS        = 0x6f74fdc6L         # specific to folders.dbx
!   POP3UIDL       = 0x6f74fdc7L         # specific to pop3uidl.dbx
  
!   # various entries indexes
!   FH_FILE_INFO_LENGTH       = 0x07     # file info length
!   FH_FIRST_FOLDER_LIST_NODE = 0x1b     # pointer to the first folder list node
!   FH_LAST_FOLDER_LIST_NODE  = 0x1c     # pointer to the last folder list node
!   FH_MESSAGE_CONDITIONS_PTR = 0x22     # pointer to the message conditions object
!   FH_FOLDER_CONDITIONS_PTR  = 0x23     # pointer to the folder conditions object
!   FH_ENTRIES                = 0x31     # entries in tree
!   FH_TREE_ROOT_NODE_PTR     = 0x39     # pointer to the root node of a tree
  
!   FILE_HEADER_ENTRIES = \
!   [ ( 0x07,  "file info length"                                ),
!     ( 0x09,  "pointer to the last variable segment"            ),
!     ( 0x0a,  "length of a variable segment"                    ),
!     ( 0x0b,  "used space of the last variable segment"         ),
!     ( 0x0c,  "pointer to the last tree segment"                ),
!     ( 0x0d,  "length of a tree segment"                        ),
!     ( 0x0e,  "used space of the last tree segment"             ),
!     ( 0x0f,  "pointer to the last message segment"             ),
!     ( 0x10,  "length of a message segment"                     ),
!     ( 0x11,  "used space of the last message segment"          ),
!     ( 0x12,  "root pointer to the deleted message list"        ),
!     ( 0x13,  "root pointer to the deleted tree list"           ),
!     ( 0x15,  "used space in the middle sector of the file"     ),
!     ( 0x16,  "reusable space in the middle sector of the file" ),
!     ( 0x17,  "index of the last entry in the tree"             ),
!     ( 0x1b,  "pointer to the first folder list node"           ),
!     ( 0x1c,  "pointer to the last folder list node"            ),
!     ( 0x1f,  "used space of the file"                          ),
!     ( 0x22,  "pointer to the message conditions object"        ),
!     ( 0x23,  "pointer to the folder conditions object"         ),
!     ( 0x31,  "entries in the tree"                             ),
!     ( 0x32,  "entries in the 2.nd tree"                        ),
!     ( 0x33,  "entries in the 3.rd tree"                        ),
!     ( 0x39,  "pointer to the root node of the tree"            ),
!     ( 0x3a,  "pointer to the root node of the 2.nd tree"       ),
!     ( 0x3b,  "pointer to the root node of the 3.rd tree"       ),
!     ( 0x9f,  "used space for indexed info objects"             ),
!     ( 0xa0,  "used space for conditions objects"               ),
!     ( 0xa2,  "used space for folder list objects"              ),
!     ( 0xa3,  "used space for tree objects"                     ),
!     ( 0xa4,  "used space for message objects"                  )]
  
!   def __init__(self, dbxStream):
!     """Initialize the DBX header by reading it directly from the passed
!     stream."""
!     dbxStream.seek(0)
!     self.dbxBuffer = dbxStream.read(dbxFileHeader.HEADER_SIZE)
  
!   def isMessages(self):
!     """Return true iff the DBX is a messages DBX."""
!     return not (self.isFolders() or self.isPOP3UIDL() or self.isOffline())
  
!   def isFolders(self):
!     """Return true if the DBX is the folders DBX."""
!     return self.getEntry(1) == dbxFileHeader.FOLDERS
  
!   def isPOP3UIDL(self):
!     """Return true if the DBX is the POP3UIDL DBX."""
!     return self.getEntry(1) == dbxFileHeader.POP3UIDL
  
!   def isOffline(self):
!     """Return true if the DBX is the offline DBX."""
!     return self.getEntry(1) == dbxFileHeader.OFFLINE
  
!   def isValid(self):
!     """Return true if the DBX is a valid DBX file."""
!     return self.getEntry(0) == dbxFileHeader.MAGIC_NUMBER
  
!   def getHeaderBuffer(self):
!     """Return the bytes buffer containing the whole header."""
!     return self.dbxBuffer
  
!   def getEntry(self, dbxEntry):
!     """Return the n-th entry as a long integer."""
!     return struct.unpack("L",
!                          self.dbxBuffer[dbxEntry * 4:(dbxEntry * 4) + 4])[0]
  
!   def getEntryAsHexStr(self, dbxEntry):
!     """Return the n-th entry as an hexadecimal string.
!     (Little endian encoding!)"""
!     return '0x' + \
!            binascii.hexlify(self.dbxBuffer[dbxEntry * 4:(dbxEntry * 4) + 4])
  
  ###########################################################################
--- 16,118 ----
  ###########################################################################
  class dbxFileHeader:
!     """
!        Each Outlook Express DBX file has a file header.
!        This header defines many properties, only a few of which interest us.
  
!        The only properties which are required are defined by indexes. The
!        indexes are static attributes of the class and their names begin with
!        "fh". You can access their values through the method getEntry().
!     """
  
!     HEADER_SIZE    = 0x24bc              # total header size
!     HEADER_ENTRIES = HEADER_SIZE >> 2    # total of entries in the header
  
!     MAGIC_NUMBER   = 0xfe12adcfL         # specific to DBX files
!     OFFLINE        = 0x26fe9d30L         # specific to offline.dbx
!     FOLDERS        = 0x6f74fdc6L         # specific to folders.dbx
!     POP3UIDL       = 0x6f74fdc7L         # specific to pop3uidl.dbx
  
!     # various entries indexes
!     FH_FILE_INFO_LENGTH       = 0x07     # file info length
!     FH_FIRST_FOLDER_LIST_NODE = 0x1b     # pointer to the first folder list node
!     FH_LAST_FOLDER_LIST_NODE  = 0x1c     # pointer to the last folder list node
!     FH_MESSAGE_CONDITIONS_PTR = 0x22     # pointer to the message conditions object
!     FH_FOLDER_CONDITIONS_PTR  = 0x23     # pointer to the folder conditions object
!     FH_ENTRIES                = 0x31     # entries in tree
!     FH_TREE_ROOT_NODE_PTR     = 0x39     # pointer to the root node of a tree
  
!     FILE_HEADER_ENTRIES = \
!     [ ( 0x07,  "file info length"                                ),
!       ( 0x09,  "pointer to the last variable segment"            ),
!       ( 0x0a,  "length of a variable segment"                    ),
!       ( 0x0b,  "used space of the last variable segment"         ),
!       ( 0x0c,  "pointer to the last tree segment"                ),
!       ( 0x0d,  "length of a tree segment"                        ),
!       ( 0x0e,  "used space of the last tree segment"             ),
!       ( 0x0f,  "pointer to the last message segment"             ),
!       ( 0x10,  "length of a message segment"                     ),
!       ( 0x11,  "used space of the last message segment"          ),
!       ( 0x12,  "root pointer to the deleted message list"        ),
!       ( 0x13,  "root pointer to the deleted tree list"           ),
!       ( 0x15,  "used space in the middle sector of the file"     ),
!       ( 0x16,  "reusable space in the middle sector of the file" ),
!       ( 0x17,  "index of the last entry in the tree"             ),
!       ( 0x1b,  "pointer to the first folder list node"           ),
!       ( 0x1c,  "pointer to the last folder list node"            ),
!       ( 0x1f,  "used space of the file"                          ),
!       ( 0x22,  "pointer to the message conditions object"        ),
!       ( 0x23,  "pointer to the folder conditions object"         ),
!       ( 0x31,  "entries in the tree"                             ),
!       ( 0x32,  "entries in the 2.nd tree"                        ),
!       ( 0x33,  "entries in the 3.rd tree"                        ),
!       ( 0x39,  "pointer to the root node of the tree"            ),
!       ( 0x3a,  "pointer to the root node of the 2.nd tree"       ),
!       ( 0x3b,  "pointer to the root node of the 3.rd tree"       ),
!       ( 0x9f,  "used space for indexed info objects"             ),
!       ( 0xa0,  "used space for conditions objects"               ),
!       ( 0xa2,  "used space for folder list objects"              ),
!       ( 0xa3,  "used space for tree objects"                     ),
!       ( 0xa4,  "used space for message objects"                  )]
  
!     def __init__(self, dbxStream):
!         """Initialize the DBX header by reading it directly from the passed
!         stream."""
!         dbxStream.seek(0)
!         self.dbxBuffer = dbxStream.read(dbxFileHeader.HEADER_SIZE)
  
!     def isMessages(self):
!         """Return true iff the DBX is a messages DBX."""
!         return not (self.isFolders() or self.isPOP3UIDL() or self.isOffline())
  
!     def isFolders(self):
!         """Return true if the DBX is the folders DBX."""
!         return self.getEntry(1) == dbxFileHeader.FOLDERS
  
!     def isPOP3UIDL(self):
!         """Return true if the DBX is the POP3UIDL DBX."""
!         return self.getEntry(1) == dbxFileHeader.POP3UIDL
  
!     def isOffline(self):
!         """Return true if the DBX is the offline DBX."""
!         return self.getEntry(1) == dbxFileHeader.OFFLINE
  
!     def isValid(self):
!         """Return true if the DBX is a valid DBX file."""
!         return self.getEntry(0) == dbxFileHeader.MAGIC_NUMBER
  
!     def getHeaderBuffer(self):
!         """Return the bytes buffer containing the whole header."""
!         return self.dbxBuffer
  
!     def getEntry(self, dbxEntry):
!         """Return the n-th entry as a long integer."""
!         return struct.unpack("L",
!                              self.dbxBuffer[dbxEntry * 4:(dbxEntry * 4) + 4])[0]
  
!     def getEntryAsHexStr(self, dbxEntry):
!         """Return the n-th entry as an hexadecimal string.
!         (Little endian encoding!)"""
!         return '0x' + \
!                binascii.hexlify(self.dbxBuffer[dbxEntry * 4:(dbxEntry * 4) + 4])
  
  ###########################################################################
***************
*** 121,155 ****
  
  class dbxFileInfo:
!   """
!     Following the DBX header there is DBX info. This part gives the name of
!     the folder described by the current DBX.
!   """
  
!   MESSAGE_FILE_INFO = 0x618
  
!   def __init__(self, dbxStream, dbxLength):
!     """Reads the DBX info part from a DBX stream."""
!     dbxStream.seek(dbxFileHeader.HEADER_SIZE)
!     self.dbxLength = dbxLength
!     self.dbxBuffer = dbxStream.read(dbxLength)
  
!   def isFoldersInfo(self):
!     """Return true if the info belongs to folders.dbx."""
!     return self.dbxLength != dbxFileInfo.MESSAGE_FILE_INFO
  
!   def getFolderName(self):
!     """Returns the folder name."""
!     if not self.isFoldersInfo():
!       name = [c for c in self.dbxBuffer[0x105:0x210] if ord(c) != 0]
!       return "".join(name)
!     else:
!       return None
  
!   def getCreationTime(self):
!     """Not implemented yet."""
!     if self.isFoldersInfo():
!       return "Not implemented yet"
!     else:
!       return None
  
  ###########################################################################
--- 121,155 ----
  
  class dbxFileInfo:
!     """
!       Following the DBX header there is DBX info. This part gives the name of
!       the folder described by the current DBX.
!     """
  
!     MESSAGE_FILE_INFO = 0x618
  
!     def __init__(self, dbxStream, dbxLength):
!         """Reads the DBX info part from a DBX stream."""
!         dbxStream.seek(dbxFileHeader.HEADER_SIZE)
!         self.dbxLength = dbxLength
!         self.dbxBuffer = dbxStream.read(dbxLength)
  
!     def isFoldersInfo(self):
!         """Return true if the info belongs to folders.dbx."""
!         return self.dbxLength != dbxFileInfo.MESSAGE_FILE_INFO
  
!     def getFolderName(self):
!         """Returns the folder name."""
!         if not self.isFoldersInfo():
!             name = [c for c in self.dbxBuffer[0x105:0x210] if ord(c) != 0]
!             return "".join(name)
!         else:
!             return None
  
!     def getCreationTime(self):
!         """Not implemented yet."""
!         if self.isFoldersInfo():
!             return "Not implemented yet"
!         else:
!             return None
  
  ###########################################################################
***************
*** 158,204 ****
  
  class dbxTree:
!   """Stands for the tree which stores the messages in a given folder."""
  
!   TREE_NODE_SIZE = 0x27c          # size of a tree node
  
!   def __init__(self, dbxStream, dbxAddress, dbxValues):
!     """Reads the addresses of the stored messages."""
!     self.dbxValues = [i for i in range(dbxValues)]
!     # XXX : silly fix !
!     if dbxAddress > 0:
!       self.__readValues(dbxStream, 0, dbxAddress, 0, dbxValues)
  
!   def __readValues(self, dbxStream, dbxParent, dbxAddress, dbxPosition, dbxValues):
!     dbxStream.seek(dbxAddress)
!     dbxBuffer = dbxStream.read(dbxTree.TREE_NODE_SIZE)
  
!     count = 0
!     entries = ((self.getEntry(dbxBuffer, 4) >> 8) & 0xff)
  
!     if self.getEntry(dbxBuffer, 2) != 0:
!       self.__readValues(dbxStream, dbxAddress, self.getEntry(dbxBuffer, 2),
!                                    dbxPosition, self.getEntry(dbxBuffer, 5))
!       count += self.getEntry(dbxBuffer, 5)
  
!     for i in range(entries):
!       pos = 6 + i * 3
  
!       if self.getEntry(dbxBuffer, pos) != 0:
!         count += 1
!         value = dbxPosition + count
!         self.dbxValues[value - 1] = self.getEntry(dbxBuffer, pos)
  
!       if self.getEntry(dbxBuffer, pos + 1) != 0:
!         self.__readValues(dbxStream, dbxAddress, self.getEntry(dbxBuffer, pos + 1),
!                                      dbxPosition + count, self.getEntry(dbxBuffer, pos + 2))
!         count += self.getEntry(dbxBuffer, pos + 2)
  
!   def getEntry(self, dbxBuffer, dbxEntry):
!     """Return the n-th entry as a long integer."""
!     return struct.unpack("L", dbxBuffer[dbxEntry * 4:(dbxEntry * 4) + 4])[0]
  
!   def getValue(self, dbxIndex):
!     """Return the address of the n-th message."""
!     return self.dbxValues[dbxIndex]
  
  ###########################################################################
--- 158,204 ----
  
  class dbxTree:
!     """Stands for the tree which stores the messages in a given folder."""
  
!     TREE_NODE_SIZE = 0x27c          # size of a tree node
  
!     def __init__(self, dbxStream, dbxAddress, dbxValues):
!         """Reads the addresses of the stored messages."""
!         self.dbxValues = [i for i in range(dbxValues)]
!         # XXX : silly fix !
!         if dbxAddress > 0:
!             self.__readValues(dbxStream, 0, dbxAddress, 0, dbxValues)
  
!     def __readValues(self, dbxStream, dbxParent, dbxAddress, dbxPosition, dbxValues):
!         dbxStream.seek(dbxAddress)
!         dbxBuffer = dbxStream.read(dbxTree.TREE_NODE_SIZE)
  
!         count = 0
!         entries = ((self.getEntry(dbxBuffer, 4) >> 8) & 0xff)
  
!         if self.getEntry(dbxBuffer, 2) != 0:
!             self.__readValues(dbxStream, dbxAddress, self.getEntry(dbxBuffer, 2),
!                                          dbxPosition, self.getEntry(dbxBuffer, 5))
!             count += self.getEntry(dbxBuffer, 5)
  
!         for i in range(entries):
!             pos = 6 + i * 3
  
!             if self.getEntry(dbxBuffer, pos) != 0:
!                 count += 1
!                 value = dbxPosition + count
!                 self.dbxValues[value - 1] = self.getEntry(dbxBuffer, pos)
  
!             if self.getEntry(dbxBuffer, pos + 1) != 0:
!                 self.__readValues(dbxStream, dbxAddress, self.getEntry(dbxBuffer, pos + 1),
!                                              dbxPosition + count, self.getEntry(dbxBuffer, pos + 2))
!                 count += self.getEntry(dbxBuffer, pos + 2)
  
!     def getEntry(self, dbxBuffer, dbxEntry):
!         """Return the n-th entry as a long integer."""
!         return struct.unpack("L", dbxBuffer[dbxEntry * 4:(dbxEntry * 4) + 4])[0]
  
!     def getValue(self, dbxIndex):
!         """Return the address of the n-th message."""
!         return self.dbxValues[dbxIndex]
  
  ###########################################################################
***************
*** 207,324 ****
  
  class dbxIndexedInfo:
!   """
!     Messages and folders mailboxes contain the "message info" and "folders
!     info" entities.
!     These entities are indexed info sequences. This is their base class.
!   """
  
!   MAX_INDEX = 0x20        # max index
!   DT_NONE   = 0           # data type none
  
!   def __init__(self, dbxStream, dbxAddress):
!     """Reads the indexed infos from the passed stream."""
!     self.dbxBodyLength   = 0L
!     self.dbxObjectLength = 0L
!     self.dbxEntries      = 0L
!     self.dbxCounter      = 0L
!     self.dbxBuffer       = []
!     self.dbxIndexes      = 0L
!     self.dbxBegin        = [0L for i in range(dbxIndexedInfo.MAX_INDEX)]
!     self.dbxLength       = [i  for i in self.dbxBegin]
!     self.dbxAddress       = dbxAddress
!     self.__readIndexedInfo(dbxStream)
  
!   def __readIndexedInfo(self, dbxStream):
!     dbxStream.seek(self.dbxAddress)
!     temp = dbxStream.read(12)
  
!     self.dbxBodyLength   =  self.__getEntry(temp, 1)
!     self.dbxObjectLength =  self.__getEntry(temp, 2) & 0xffff
!     self.dbxEntries      = (self.__getEntry(temp, 2) >> 16) & 0xff
!     self.dbxCounter      = (self.__getEntry(temp, 1) >> 24) & 0xff
!     self.dbxBuffer       =  dbxStream.read(self.dbxBodyLength) # bytes array
  
!     isIndirect           = bool(0)                             # boolean
!     lastIndirect         = 0
!     data                 = self.dbxEntries << 2                # index within dbxBuffer
  
!     for i in range(self.dbxEntries):
!       value      = self.__getEntry(self.dbxBuffer, i)
!       isDirect   = value & 0x80
!       index      = value & 0x7f
!       value    >>= 8
!       if isDirect:
!         self.__setIndex(index, (i << 2) + 1, 3)
!       else:
!         self.__setIndex(index, data + value)
!         if isIndirect:
!           self.__setEnd(lastIndirect, data + value)
!           isIndirect   = bool(1)
!           lastIndirect = index
!       self.dbxIndexes |= 1 << index
  
!     if isIndirect:
!       self.__setEnd(lastIndirect, self.dbxBodyLength)
  
!   def __setIndex(self, dbxIndex, dbxBegin, dbxLength = 0):
!     if dbxIndex < dbxIndexedInfo.MAX_INDEX:
!       self.dbxBegin[dbxIndex] = dbxBegin
!       self.dbxLength[dbxIndex] = dbxLength
  
!   def __setEnd(self, dbxIndex, dbxEnd):
!     if dbxIndex < dbxIndexedInfo.MAX_INDEX:
!       self.dbxLength[dbxIndex] = dbxEnd - self.dbxBegin[dbxIndex]
  
!   def __getEntry(self, dbxBuffer, dbxEntry):
!     return struct.unpack("L", dbxBuffer[dbxEntry * 4:(dbxEntry * 4) + 4])[0]
  
!   def getIndexText(self, dbxIndex):
!     """Returns the description of the given indexed field."""
!     return ""
  
!   def getIndexDataType(self, dbxIndex):
!     """Returns the data type of the given index."""
!     return DT_NONE
  
!   def getValue(self, dbxIndex):
!     """Returns a tuple : (index in buffer of the info, length of the info)."""
!     return (self.dbxBegin[dbxIndex], self.dbxLength[dbxIndex])
  
!   def getValueAsLong(self, dbxIndex):
!     """Returns the indexed info as a long value."""
!     data, length = self.getValue(dbxIndex)
!     value  = 0
!     if data:
!       value = struct.unpack("L", self.dbxBuffer[data:data + 4])[0]
!       if length < 4:
!         value &= (1 << (length << 3)) - 1
!     return value
  
!   def getString(self, dbxIndex):
!     """Returns the indexed info as a string value."""
!     index = self.dbxBegin[dbxIndex]
!     end = index
!     for c in self.dbxBuffer[index:]:
!       if ord(c) == 0: break
!       end += 1
!     return self.dbxBuffer[index:end]
  
!   def getAddress(self):
!     return self.dbxAddress
  
!   def getBodyLength(self):
!     return self.dbxBodyLength
  
!   def getEntries(self):
!     return self.dbxEntries
  
!   def getCounter(self):
!     return self.dbxCounter
  
!   def getIndexes(self):
!     return self.dbxIndexes
  
!   def isIndexed(self, dbxIndex):
!     return self.dbxIndexes & (1 << dbxIndex)
  
  ###########################################################################
--- 207,324 ----
  
  class dbxIndexedInfo:
!     """
!       Messages and folders mailboxes contain the "message info" and "folders
!       info" entities.
!       These entities are indexed info sequences. This is their base class.
!     """
  
!     MAX_INDEX = 0x20        # max index
!     DT_NONE   = 0           # data type none
  
!     def __init__(self, dbxStream, dbxAddress):
!         """Reads the indexed infos from the passed stream."""
!         self.dbxBodyLength   = 0L
!         self.dbxObjectLength = 0L
!         self.dbxEntries      = 0L
!         self.dbxCounter      = 0L
!         self.dbxBuffer       = []
!         self.dbxIndexes      = 0L
!         self.dbxBegin        = [0L for i in range(dbxIndexedInfo.MAX_INDEX)]
!         self.dbxLength       = [i  for i in self.dbxBegin]
!         self.dbxAddress       = dbxAddress
!         self.__readIndexedInfo(dbxStream)
  
!     def __readIndexedInfo(self, dbxStream):
!         dbxStream.seek(self.dbxAddress)
!         temp = dbxStream.read(12)
  
!         self.dbxBodyLength   =  self.__getEntry(temp, 1)
!         self.dbxObjectLength =  self.__getEntry(temp, 2) & 0xffff
!         self.dbxEntries      = (self.__getEntry(temp, 2) >> 16) & 0xff
!         self.dbxCounter      = (self.__getEntry(temp, 1) >> 24) & 0xff
!         self.dbxBuffer       =  dbxStream.read(self.dbxBodyLength) # bytes array
  
!         isIndirect           = bool(0)                             # boolean
!         lastIndirect         = 0
!         data                 = self.dbxEntries << 2                # index within dbxBuffer
  
!         for i in range(self.dbxEntries):
!             value      = self.__getEntry(self.dbxBuffer, i)
!             isDirect   = value & 0x80
!             index      = value & 0x7f
!             value    >>= 8
!             if isDirect:
!                 self.__setIndex(index, (i << 2) + 1, 3)
!             else:
!                 self.__setIndex(index, data + value)
!                 if isIndirect:
!                     self.__setEnd(lastIndirect, data + value)
!                     isIndirect   = bool(1)
!                     lastIndirect = index
!             self.dbxIndexes |= 1 << index
  
!         if isIndirect:
!             self.__setEnd(lastIndirect, self.dbxBodyLength)
  
!     def __setIndex(self, dbxIndex, dbxBegin, dbxLength = 0):
!         if dbxIndex < dbxIndexedInfo.MAX_INDEX:
!             self.dbxBegin[dbxIndex] = dbxBegin
!             self.dbxLength[dbxIndex] = dbxLength
  
!     def __setEnd(self, dbxIndex, dbxEnd):
!         if dbxIndex < dbxIndexedInfo.MAX_INDEX:
!             self.dbxLength[dbxIndex] = dbxEnd - self.dbxBegin[dbxIndex]
  
!     def __getEntry(self, dbxBuffer, dbxEntry):
!         return struct.unpack("L", dbxBuffer[dbxEntry * 4:(dbxEntry * 4) + 4])[0]
  
!     def getIndexText(self, dbxIndex):
!         """Returns the description of the given indexed field."""
!         return ""
  
!     def getIndexDataType(self, dbxIndex):
!         """Returns the data type of the given index."""
!         return DT_NONE
  
!     def getValue(self, dbxIndex):
!         """Returns a tuple : (index in buffer of the info, length of the info)."""
!         return (self.dbxBegin[dbxIndex], self.dbxLength[dbxIndex])
  
!     def getValueAsLong(self, dbxIndex):
!         """Returns the indexed info as a long value."""
!         data, length = self.getValue(dbxIndex)
!         value  = 0
!         if data:
!             value = struct.unpack("L", self.dbxBuffer[data:data + 4])[0]
!             if length < 4:
!                 value &= (1 << (length << 3)) - 1
!         return value
  
!     def getString(self, dbxIndex):
!         """Returns the indexed info as a string value."""
!         index = self.dbxBegin[dbxIndex]
!         end = index
!         for c in self.dbxBuffer[index:]:
!             if ord(c) == 0: break
!             end += 1
!         return self.dbxBuffer[index:end]
  
!     def getAddress(self):
!         return self.dbxAddress
  
!     def getBodyLength(self):
!         return self.dbxBodyLength
  
!     def getEntries(self):
!         return self.dbxEntries
  
!     def getCounter(self):
!         return self.dbxCounter
  
!     def getIndexes(self):
!         return self.dbxIndexes
  
!     def isIndexed(self, dbxIndex):
!         return self.dbxIndexes & (1 << dbxIndex)
  
  ###########################################################################
***************
*** 327,377 ****
  
  class dbxMessageInfo(dbxIndexedInfo):
!   """
!     The message info structure inherits from the index info one. It just
!     defines extra constants which allow to access pertinent info.
!   """
  
!   MI_INDEX           = 0x0                   # index of the message
!   MI_FLAGS           = 0x1                   # the message flags
!   MI_MESSAGE_ADDRESS = 0x4                   # the address of the message
!   MI_SUBJECT         = 0x8                   # the subject of the message
  
!   # label of each indexed info
!   INDEX_LABEL = \
!   [ "message index"                , "flags"                          ,
!     "time message created/send"    , "body lines"                     ,
!     "message address"              , "original subject"               ,
!     "time message saved"           , "message id"                     ,
!     "subject"                      , "sender eMail address and name"  ,
!     "answered to message id"       , "server/newsgroup/message number",
!     "server"                       , "sender name"                    ,
!     "sender eMail address"         , "id 0f"                          ,
!     "message priority"             , "message text length"            ,
!     "time message created/received", "receiver name"                  ,
!     "receiver eMail address"       , "id 15"                          ,
!     "id 16"                        , "id 17"                          ,
!     "id 18"                        , "id 19"                          ,
!     "OE account name"              , "OE account registry key"        ,
!     "message text structure"       , "id 1d"                          ,
!     "id 1e"                        , "id 1f"                           ]
  
!   DT_NONE      = 0                    # index is none
!   DT_INT4      = 1                    # index is a long integer (32 bits)
!   DT_STRING    = 2                    # index is a string
!   DT_DATE_TIME = 3                    # index is date/time
!   DT_DATA      = 4                    # index is data
  
!   # the data type of each index
!   INDEX_DATA_TYPE = \
!   [ DT_INT4  , DT_INT4  , DT_DATE_TIME, DT_INT4  , DT_INT4  , DT_STRING, DT_DATE_TIME, DT_STRING,
!     DT_STRING, DT_STRING, DT_STRING   , DT_STRING, DT_STRING, DT_STRING, DT_STRING   , DT_NONE  ,
!     DT_INT4  , DT_INT4  , DT_DATE_TIME, DT_STRING, DT_STRING, DT_NONE  , DT_INT4     , DT_NONE  ,
!     DT_INT4  , DT_INT4  , DT_STRING   , DT_STRING, DT_DATA  , DT_NONE  , DT_NONE     , DT_NONE   ]
  
!   def getIndexText(self, dbxIndex):
!     return dbxMessageInfo.INDEX_LABEL[dbxIndex]
  
!   def getIndexDataType(self, dbxIndex):
!     return dbxMessageInfo.INDEX_DATA_TYPE[dbxIndex]
  
  ###########################################################################
--- 327,377 ----
  
  class dbxMessageInfo(dbxIndexedInfo):
!     """
!       The message info structure inherits from the index info one. It just
!       defines extra constants which allow to access pertinent info.
!     """
  
!     MI_INDEX           = 0x0                   # index of the message
!     MI_FLAGS           = 0x1                   # the message flags
!     MI_MESSAGE_ADDRESS = 0x4                   # the address of the message
!     MI_SUBJECT         = 0x8                   # the subject of the message
  
!     # label of each indexed info
!     INDEX_LABEL = \
!     [ "message index"                , "flags"                          ,
!       "time message created/send"    , "body lines"                     ,
!       "message address"              , "original subject"               ,
!       "time message saved"           , "message id"                     ,
!       "subject"                      , "sender eMail address and name"  ,
!       "answered to message id"       , "server/newsgroup/message number",
!       "server"                       , "sender name"                    ,
!       "sender eMail address"         , "id 0f"                          ,
!       "message priority"             , "message text length"            ,
!       "time message created/received", "receiver name"                  ,
!       "receiver eMail address"       , "id 15"                          ,
!       "id 16"                        , "id 17"                          ,
!       "id 18"                        , "id 19"                          ,
!       "OE account name"              , "OE account registry key"        ,
!       "message text structure"       , "id 1d"                          ,
!       "id 1e"                        , "id 1f"                           ]
  
!     DT_NONE      = 0                    # index is none
!     DT_INT4      = 1                    # index is a long integer (32 bits)
!     DT_STRING    = 2                    # index is a string
!     DT_DATE_TIME = 3                    # index is date/time
!     DT_DATA      = 4                    # index is data
  
!     # the data type of each index
!     INDEX_DATA_TYPE = \
!     [ DT_INT4  , DT_INT4  , DT_DATE_TIME, DT_INT4  , DT_INT4  , DT_STRING, DT_DATE_TIME, DT_STRING,
!       DT_STRING, DT_STRING, DT_STRING   , DT_STRING, DT_STRING, DT_STRING, DT_STRING   , DT_NONE  ,
!       DT_INT4  , DT_INT4  , DT_DATE_TIME, DT_STRING, DT_STRING, DT_NONE  , DT_INT4     , DT_NONE  ,
!       DT_INT4  , DT_INT4  , DT_STRING   , DT_STRING, DT_DATA  , DT_NONE  , DT_NONE     , DT_NONE   ]
  
!     def getIndexText(self, dbxIndex):
!         return dbxMessageInfo.INDEX_LABEL[dbxIndex]
  
!     def getIndexDataType(self, dbxIndex):
!         return dbxMessageInfo.INDEX_DATA_TYPE[dbxIndex]
  
  ###########################################################################
***************
*** 380,418 ****
  
  class dbxMessage:
!   def __init__(self, dbxStream, dbxAddress):
!     self.dbxAddress = dbxAddress
!     self.dbxText   = ""
!     self.dbxLength = 0L
!     self.__readMessageText(dbxStream)
  
!   def __getEntry(self, dbxBuffer, dbxEntry):
!     if len(dbxBuffer) < (dbxEntry * 4) + 4:
!       return None
!     return struct.unpack("L", dbxBuffer[dbxEntry * 4:(dbxEntry * 4) + 4])[0]
  
!   def __readMessageText(self, dbxStream):
!     address = self.dbxAddress
!     header = ""
  
!     while (address):
!       dbxStream.seek(address)
!       header = dbxStream.read(16)
  
!       self.dbxLength += self.__getEntry(header, 2)
!       address          = self.__getEntry(header, 3)
  
!     pos = ""
!     address = self.dbxAddress
  
!     while (address):
!       dbxStream.seek(address)
!       header  = dbxStream.read(16)
!       pos    += dbxStream.read(self.__getEntry(header, 2))
!       address  = self.__getEntry(header, 3)
  
!     self.dbxText = pos
  
!   def getText(self):
!     return self.dbxText
  
  ###########################################################################
--- 380,418 ----
  
  class dbxMessage:
!     def __init__(self, dbxStream, dbxAddress):
!         self.dbxAddress = dbxAddress
!         self.dbxText   = ""
!         self.dbxLength = 0L
!         self.__readMessageText(dbxStream)
  
!     def __getEntry(self, dbxBuffer, dbxEntry):
!         if len(dbxBuffer) < (dbxEntry * 4) + 4:
!             return None
!         return struct.unpack("L", dbxBuffer[dbxEntry * 4:(dbxEntry * 4) + 4])[0]
  
!     def __readMessageText(self, dbxStream):
!         address = self.dbxAddress
!         header = ""
  
!         while (address):
!             dbxStream.seek(address)
!             header = dbxStream.read(16)
  
!             self.dbxLength += self.__getEntry(header, 2)
!             address          = self.__getEntry(header, 3)
  
!         pos = ""
!         address = self.dbxAddress
  
!         while (address):
!             dbxStream.seek(address)
!             header  = dbxStream.read(16)
!             pos    += dbxStream.read(self.__getEntry(header, 2))
!             address  = self.__getEntry(header, 3)
  
!         self.dbxText = pos
  
!     def getText(self):
!         return self.dbxText
  
  ###########################################################################
***************
*** 421,488 ****
  
  if __name__ == '__main__':
!   import sys
!   import getopt
  
!   try:
!     opts, args = getopt.getopt(sys.argv[1:], 'hp')
!   except getopt.error, msg:
!     print >>sys.stderr, str(msg) + '\n\n' + __doc__
!     sys.exit()
  
!   print_message = False
!   for opt, arg in opts:
!     if opt == '-h':
!       print >>sys.stderr, __doc__
!       sys.exit()
!     elif opt == '-p':
!       print_message = True
  
!   if not args:
!     print "Please enter a directory with dbx files."
!     sys.exit()
  
!   MAILBOX_DIR = args[0]  
  
!   files = [os.path.join(MAILBOX_DIR, file) for file in \
!            os.listdir(MAILBOX_DIR) if os.path.splitext(file)[1] == '.dbx']
  
!   for file in files:
!     try:
!       print
!       print file
  
!       dbx = open(file, "rb", 0)
!       header = dbxFileHeader(dbx)
  
!       print "IS VALID DBX  :", header.isValid()
  
!       if header.isMessages():
!         info = dbxFileInfo(dbx, header.getEntry(dbxFileHeader.FH_FILE_INFO_LENGTH))
!         print "MAILBOX NAME  :", info.getFolderName()
!         print "CREATION TIME :", info.getCreationTime()
  
!         entries = header.getEntry(dbxFileHeader.FH_ENTRIES)
!         address  = header.getEntry(dbxFileHeader.FH_TREE_ROOT_NODE_PTR)
  
!         if address and entries:
!           tree = dbxTree(dbx, address, entries)
  
!           for i in range(entries):
!             address = tree.getValue(i)
!             messageInfo = dbxMessageInfo(dbx, address)
  
!             if messageInfo.isIndexed(dbxMessageInfo.MI_MESSAGE_ADDRESS):
!               messageAddress = messageInfo.getValueAsLong(dbxMessageInfo.MI_MESSAGE_ADDRESS)
!               message        = dbxMessage(dbx, messageAddress)
  
!               if print_message:
!                 print
!                 print "Message :", messageInfo.getString(dbxMessageInfo.MI_SUBJECT)
!                 print "=" * (len(messageInfo.getString(dbxMessageInfo.MI_SUBJECT)) + 9)
!                 print
!                 print message.getText()
  
!     except Exception, (strerror):
!       print strerror
  
!     dbx.close()
--- 421,488 ----
  
  if __name__ == '__main__':
!     import sys
!     import getopt
  
!     try:
!         opts, args = getopt.getopt(sys.argv[1:], 'hp')
!     except getopt.error, msg:
!         print >>sys.stderr, str(msg) + '\n\n' + __doc__
!         sys.exit()
  
!     print_message = False
!     for opt, arg in opts:
!         if opt == '-h':
!             print >>sys.stderr, __doc__
!             sys.exit()
!         elif opt == '-p':
!             print_message = True
  
!     if not args:
!         print "Please enter a directory with dbx files."
!         sys.exit()
  
!     MAILBOX_DIR = args[0]
  
!     files = [os.path.join(MAILBOX_DIR, file) for file in \
!              os.listdir(MAILBOX_DIR) if os.path.splitext(file)[1] == '.dbx']
  
!     for file in files:
!         try:
!             print
!             print file
  
!             dbx = open(file, "rb", 0)
!             header = dbxFileHeader(dbx)
  
!             print "IS VALID DBX  :", header.isValid()
  
!             if header.isMessages():
!                 info = dbxFileInfo(dbx, header.getEntry(dbxFileHeader.FH_FILE_INFO_LENGTH))
!                 print "MAILBOX NAME  :", info.getFolderName()
!                 print "CREATION TIME :", info.getCreationTime()
  
!                 entries = header.getEntry(dbxFileHeader.FH_ENTRIES)
!                 address  = header.getEntry(dbxFileHeader.FH_TREE_ROOT_NODE_PTR)
  
!                 if address and entries:
!                     tree = dbxTree(dbx, address, entries)
  
!                     for i in range(entries):
!                         address = tree.getValue(i)
!                         messageInfo = dbxMessageInfo(dbx, address)
  
!                         if messageInfo.isIndexed(dbxMessageInfo.MI_MESSAGE_ADDRESS):
!                             messageAddress = messageInfo.getValueAsLong(dbxMessageInfo.MI_MESSAGE_ADDRESS)
!                             message        = dbxMessage(dbx, messageAddress)
  
!                             if print_message:
!                                 print
!                                 print "Message :", messageInfo.getString(dbxMessageInfo.MI_SUBJECT)
!                                 print "=" * (len(messageInfo.getString(dbxMessageInfo.MI_SUBJECT)) + 9)
!                                 print
!                                 print message.getText()
  
!         except Exception, (strerror):
!             print strerror
  
!         dbx.close()

Index: smtpproxy.py
===================================================================
RCS file: /cvsroot/spambayes/spambayes/spambayes/smtpproxy.py,v
retrieving revision 1.4
retrieving revision 1.5
diff -C2 -d -r1.4 -r1.5
*** smtpproxy.py	3 Oct 2003 05:17:43 -0000	1.4
--- smtpproxy.py	16 Dec 2003 05:06:34 -0000	1.5
***************
*** 61,65 ****
     work, but I don't really know.  Richie Hindle suggested something along
     these lines back in September '02.
!    
   o Suggestions?
  
--- 61,65 ----
     work, but I don't really know.  Richie Hindle suggested something along
     these lines back in September '02.
! 
   o Suggestions?
  
***************
*** 74,88 ****
  the smtpproxy can extract the id from the body of the message, if it
  is there.
!                                                         Header	Body
  *** Windows 2000 MUAs ***
  Eudora 5.2 Forward                                         *     *
  Eudora 5.2 Redirect                                              *
  Netscape Messenger (4.7) Forward (inline)                  *     *
! Netscape Messenger (4.7) Forward (quoted) Plain      	         *
! Netscape Messenger (4.7) Forward (quoted) HTML      	         *
! Netscape Messenger (4.7) Forward (quoted) Plain & HTML       	 *       
! Netscape Messenger (4.7) Forward (attachment) Plain 	   *     *	 
! Netscape Messenger (4.7) Forward (attachment) HTML  	   *	 *
! Netscape Messenger (4.7) Forward (attachment) Plain & HTML *  	 *
  Outlook Express 6 Forward HTML (Base64)                          *
  Outlook Express 6 Forward HTML (None)                            *
--- 74,88 ----
  the smtpproxy can extract the id from the body of the message, if it
  is there.
!                                                         Header  Body
  *** Windows 2000 MUAs ***
  Eudora 5.2 Forward                                         *     *
  Eudora 5.2 Redirect                                              *
  Netscape Messenger (4.7) Forward (inline)                  *     *
! Netscape Messenger (4.7) Forward (quoted) Plain                  *
! Netscape Messenger (4.7) Forward (quoted) HTML                   *
! Netscape Messenger (4.7) Forward (quoted) Plain & HTML           *
! Netscape Messenger (4.7) Forward (attachment) Plain        *     *
! Netscape Messenger (4.7) Forward (attachment) HTML         *     *
! Netscape Messenger (4.7) Forward (attachment) Plain & HTML *     *
  Outlook Express 6 Forward HTML (Base64)                          *
  Outlook Express 6 Forward HTML (None)                            *
***************
*** 92,96 ****
  Outlook Express 6 Forward Plain (QP)                             *
  Outlook Express 6 Forward Plain (uuencoded)                      *
! http://www.endymion.com/products/mailman Forward	             *
  M2 (Opera Mailer 7.01) Forward                                   *
  M2 (Opera Mailer 7.01) Redirect                            *     *
--- 92,96 ----
  Outlook Express 6 Forward Plain (QP)                             *
  Outlook Express 6 Forward Plain (uuencoded)                      *
! http://www.endymion.com/products/mailman Forward                     *
  M2 (Opera Mailer 7.01) Forward                                   *
  M2 (Opera Mailer 7.01) Redirect                            *     *
***************
*** 263,267 ****
            then do not forward the command on.  Otherwise forward verbatim.
  
!     Any other commands are merely passed on verbatim to the server.          
      """
  
--- 263,267 ----
            then do not forward the command on.  Otherwise forward verbatim.
  
!     Any other commands are merely passed on verbatim to the server.
      """
  
***************
*** 334,338 ****
              self.blockData = False
          return "%s:%s" % (command, ' '.join(args))
!         
      def onData(self, command, args):
          self.inData = True
--- 334,338 ----
              self.blockData = False
          return "%s:%s" % (command, ' '.join(args))
! 
      def onData(self, command, args):
          self.inData = True
***************
*** 357,361 ****
          self.state = state
          self.imap = imap
!     
      def extractSpambayesID(self, data):
          msg = message_from_string(data)
--- 357,361 ----
          self.state = state
          self.imap = imap
! 
      def extractSpambayesID(self, data):
          msg = message_from_string(data)
***************
*** 493,497 ****
                "different lengths!"
          sys.exit()
!     return servers, proxyPorts    
  
  def CreateProxies(servers, proxyPorts, trainer):
--- 493,497 ----
                "different lengths!"
          sys.exit()
!     return servers, proxyPorts
  
  def CreateProxies(servers, proxyPorts, trainer):

Index: storage.py
===================================================================
RCS file: /cvsroot/spambayes/spambayes/spambayes/storage.py,v
retrieving revision 1.36
retrieving revision 1.37
diff -C2 -d -r1.36 -r1.37
*** storage.py	8 Oct 2003 04:04:35 -0000	1.36
--- storage.py	16 Dec 2003 05:06:34 -0000	1.37
***************
*** 238,242 ****
          self._write_state_key()
          self.db.sync()
!         
      def _write_state_key(self):
          self.db[self.statekey] = (classifier.PICKLE_VERSION,
--- 238,242 ----
          self._write_state_key()
          self.db.sync()
! 
      def _write_state_key(self):
          self.db[self.statekey] = (classifier.PICKLE_VERSION,
***************
*** 248,252 ****
          key."""
          self._write_state_key()
!     
      def _wordinfoget(self, word):
          if isinstance(word, unicode):
--- 248,252 ----
          key."""
          self._write_state_key()
! 
      def _wordinfoget(self, word):
          if isinstance(word, unicode):
***************
*** 340,344 ****
          '''Commit the current transaction - may commit at db or cursor'''
          raise NotImplementedError, "must be implemented in subclass"
!         
      def create_bayes(self):
          '''Create a new bayes table'''
--- 340,344 ----
          '''Commit the current transaction - may commit at db or cursor'''
          raise NotImplementedError, "must be implemented in subclass"
! 
      def create_bayes(self):
          '''Create a new bayes table'''
***************
*** 451,455 ****
  
          import psycopg
!         
          if options["globals", "verbose"]:
              print >> sys.stderr, 'Loading state from',self.db_name,'database'
--- 451,455 ----
  
          import psycopg
! 
          if options["globals", "verbose"]:
              print >> sys.stderr, 'Loading state from',self.db_name,'database'
***************
*** 463,467 ****
              self.db.rollback()
              self.create_bayes()
!         
          if self._has_key(self.statekey):
              row = self._get_row(self.statekey)
--- 463,467 ----
              self.db.rollback()
              self.create_bayes()
! 
          if self._has_key(self.statekey):
              row = self._get_row(self.statekey)
***************
*** 485,489 ****
      It is assumed that the database already exists, and that the mySQL
      server is currently running.'''
!  
      def __init__(self, data_source_name):
          self.table_definition = ("create table bayes ("
--- 485,489 ----
      It is assumed that the database already exists, and that the mySQL
      server is currently running.'''
! 
      def __init__(self, data_source_name):
          self.table_definition = ("create table bayes ("
***************
*** 522,526 ****
  
          import MySQLdb
!         
          if options["globals", "verbose"]:
              print >> sys.stderr, 'Loading state from',self.db_name,'database'
--- 522,526 ----
  
          import MySQLdb
! 
          if options["globals", "verbose"]:
              print >> sys.stderr, 'Loading state from',self.db_name,'database'
***************
*** 535,539 ****
              self.db.rollback()
              self.create_bayes()
!         
          if self._has_key(self.statekey):
              row = self._get_row(self.statekey)
--- 535,539 ----
              self.db.rollback()
              self.create_bayes()
! 
          if self._has_key(self.statekey):
              row = self._get_row(self.statekey)

Index: tokenizer.py
===================================================================
RCS file: /cvsroot/spambayes/spambayes/spambayes/tokenizer.py,v
retrieving revision 1.21
retrieving revision 1.22
diff -C2 -d -r1.21 -r1.22
*** tokenizer.py	15 Dec 2003 09:20:33 -0000	1.21
--- tokenizer.py	16 Dec 2003 05:06:34 -0000	1.22
***************
*** 663,670 ****
      if 3 <= n <= maxword:
          yield word
!         
      elif n >= 3:
          # A long word.
!         
          # Don't want to skip embedded email addresses.
          # An earlier scheme also split up the y in x at y on '.'.  Not splitting
--- 663,670 ----
      if 3 <= n <= maxword:
          yield word
! 
      elif n >= 3:
          # A long word.
! 
          # Don't want to skip embedded email addresses.
          # An earlier scheme also split up the y in x at y on '.'.  Not splitting
***************
*** 816,820 ****
          # http://mail.python.org/pipermail/spambayes-dev/2003-September/001177.html
          yield "filename:<bogus>"
!         
      if 0:   # disabled; see comment before function
          x = msg.get('content-transfer-encoding')
--- 816,820 ----
          # http://mail.python.org/pipermail/spambayes-dev/2003-September/001177.html
          yield "filename:<bogus>"
! 
      if 0:   # disabled; see comment before function
          x = msg.get('content-transfer-encoding')
***************
*** 1174,1178 ****
                  elif valid_habeas == 9:
                      yield "x-habeas-swe:valid"
!                     
          # Subject:
          # Don't ignore case in Subject lines; e.g., 'free' versus 'FREE' is
--- 1174,1178 ----
                  elif valid_habeas == 9:
                      yield "x-habeas-swe:valid"
! 
          # Subject:
          # Don't ignore case in Subject lines; e.g., 'free' versus 'FREE' is





More information about the Spambayes-checkins mailing list