[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[minion-cvs] Remove trailing space throughout.



Update of /home/minion/cvsroot/src/minion/lib/mixminion
In directory moria.mit.edu:/tmp/cvs-serv28551/lib/mixminion

Modified Files:
	BuildMessage.py ClientDirectory.py ClientMain.py 
	ClientUtils.py Common.py Config.py Crypto.py Filestore.py 
	Fragments.py MMTPClient.py Main.py NetUtils.py Packet.py 
	ServerInfo.py benchmark.py test.py testSupport.py 
Log Message:
Remove trailing space throughout.

Index: BuildMessage.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/BuildMessage.py,v
retrieving revision 1.63
retrieving revision 1.64
diff -u -d -r1.63 -r1.64
--- BuildMessage.py	24 Nov 2003 19:59:03 -0000	1.63
+++ BuildMessage.py	28 Nov 2003 04:14:03 -0000	1.64
@@ -30,7 +30,7 @@
        and add extra fields (size, hash, etc) as appropriate.  Return a list
        of strings, each of which is a message payload suitable for use in
        build*Message.
- 
+
               payload: the initial payload
               overhead: number of bytes to omit from each payload,
                         given the type ofthe message encoding.
@@ -314,8 +314,8 @@
         except MixError:
             err = 1
     # Add a dummy tag as needed to last exitinfo.
-    if (exitType != DROP_TYPE 
-        and not mixminion.Packet._TYPES_WITHOUT_TAGS.get(exitType) 
+    if (exitType != DROP_TYPE
+        and not mixminion.Packet._TYPES_WITHOUT_TAGS.get(exitType)
         and exitInfo is not None):
         exitInfo += "X"*20
     else:
@@ -330,7 +330,7 @@
     elif err:
         raise UIError("Address and %s leg of path will not fit in one header",
                       ["first", "second"][err-1])
-    
+
 #----------------------------------------------------------------------
 # MESSAGE DECODING
 def decodePayload(payload, tag, key=None, userKeys=()):
@@ -339,7 +339,7 @@
        FragmentPayload instance, or None.
 
            key: an RSA key to decode encrypted forward messages, or None
-           userKeys: a sequence of (name,key) tuples maping identity names to 
+           userKeys: a sequence of (name,key) tuples maping identity names to
                 SURB keys. For backward compatibility, 'userKeys' may also be
                 None (no SURBs known), a dict (from name to key), or a single
                 key (implied identity is "").
@@ -357,7 +357,7 @@
 
     if len(payload) != PAYLOAD_LEN:
         raise MixError("Wrong payload length")
-    
+
     if len(tag) not in (0, TAG_LEN):
         raise MixError("Wrong tag length: %s"%len(tag))
 
@@ -447,7 +447,7 @@
     # 'check' is true, we don't.
     if check or not _checkPayload(payload):
         raise MixError("Invalid checksum on reply payload")
-    
+
     return parsePayload(payload)
 
 def _decodeStatelessReplyPayload(payload, tag, userKey):

Index: ClientDirectory.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/ClientDirectory.py,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- ClientDirectory.py	26 Nov 2003 18:21:48 -0000	1.19
+++ ClientDirectory.py	28 Nov 2003 04:14:03 -0000	1.20
@@ -1,7 +1,7 @@
 # Copyright 2002-2003 Nick Mathewson.  See LICENSE for licensing information.
 # Id: ClientMain.py,v 1.89 2003/06/05 18:41:40 nickm Exp $
 
-"""mixminion.ClientDirectory: Code to handle the 'client' side of 
+"""mixminion.ClientDirectory: Code to handle the 'client' side of
    dealing with mixminion directories.  This includes:
      - downloading and caching directories
      - path generation
@@ -115,9 +115,9 @@
         try:
             try:
                 # Tell HTTP proxies and their ilk not to cache the directory.
-                # Really, the directory server should set an Expires header 
+                # Really, the directory server should set an Expires header
                 # in its response, but that's harder.
-                request = urllib2.Request(url, 
+                request = urllib2.Request(url,
                           headers={ 'Pragma' : 'no-cache',
                                     'Cache-Control' : 'no-cache', })
                 infile = urllib2.urlopen(request)
@@ -133,7 +133,7 @@
         finally:
             if timeout:
                 mixminion.NetUtils.unsetGlobalTimeout()
-        
+
         # Open a temporary output file.
         if url.endswith(".gz"):
             fname = os.path.join(self.dir, "dir_new.gz")
@@ -209,13 +209,13 @@
                 self.serverList.append((s, 'D'))
                 self.digestMap[s.getDigest()] = 'D'
                 self.goodServerNicknames[s.getNickname().lower()] = 1
-                
+
             for s in directory.getAllServers():
                 if self.goodServerNicknames.has_key(s.getNickname().lower()):
                     where = 'D'
                 else:
                     where = 'D-'
-                
+
                 self.fullServerList.append((s, where))
                 self.digestMap[s.getDigest()] = where
 
@@ -280,7 +280,7 @@
         writePickled(os.path.join(self.dir, "cache"), data)
 
     def _installAsKeyIDResolver(self):
-        """Use this ClientDirectory to identify servers in calls to 
+        """Use this ClientDirectory to identify servers in calls to
            ServerInfo.displayServer."""
         mixminion.ServerInfo._keyIDToNicknameFn = self.getNicknameByKeyID
 
@@ -288,7 +288,7 @@
         """Import a new server descriptor stored in 'filename'"""
 
         contents = readPossiblyGzippedFile(filename)
-        info = mixminion.ServerInfo.ServerInfo(string=contents, 
+        info = mixminion.ServerInfo.ServerInfo(string=contents,
                                                validatedDigests=self.digestMap)
 
         nickname = info.getNickname()
@@ -525,7 +525,7 @@
         if len(self.serverList) != len(newServers):
             self.serverList = newServers
             self.rescan()
-            
+
     def getServerInfo(self, name, startAt=None, endAt=None, strict=0):
         """Return the most-recently-published ServerInfo for a given
            'name' valid over a given time range.  If not strict, and no
@@ -554,13 +554,13 @@
                     "Couldn't find any currently live descriptor with name %s"
                     % name)
 
-            s = s[0]            
+            s = s[0]
             return s
         elif os.path.exists(os.path.expanduser(name)):
             # If it's a filename, try to read it.
             fname = os.path.expanduser(name)
             try:
-                return mixminion.ServerInfo.ServerInfo(fname=fname, 
+                return mixminion.ServerInfo.ServerInfo(fname=fname,
                                                        assumeValid=0)
             except OSError, e:
                 raise UIError("Couldn't read descriptor %r: %s" %
@@ -573,7 +573,7 @@
         else:
             return None
 
-    def generatePaths(self, nPaths, pathSpec, exitAddress, 
+    def generatePaths(self, nPaths, pathSpec, exitAddress,
                       startAt=None, endAt=None,
                       prng=None):
         """Generate a list of paths for delivering packets to a given
@@ -620,7 +620,7 @@
                     p.append(lastHop)
             elif p[-1] == None and not exitAddress.isReply:
                 p[-1] = prng.pick(plausibleExits)
- 
+
             if pathSpec.lateSplit:
                 n1 = ceilDiv(len(p),2)
             else:
@@ -638,7 +638,7 @@
                          ",".join([s.getNickname() for s in path2]))
 
         return paths
-    
+
     def getPath(self, template, startAt=None, endAt=None, prng=None):
         """Workhorse method for path selection.  Given a template, and
            a capability that must be supported by the exit node, return
@@ -706,14 +706,14 @@
                 # Avoid first hops that we can't deliver to.
                 if (not prev) and not c.canStartAt():
                     continue
-                candidates.append(c)                    
+                candidates.append(c)
             if candidates:
                 # Good.  There aresome okay servers/
                 servers[i] = prng.pick(candidates)
             else:
                 # Nope.  Can we duplicate a relay?
                 LOG.warn("Repeating a relay because of routing restrictions.")
-                if prev and next: 
+                if prev and next:
                     if prev.canRelayTo(next):
                         servers[i] = prev
                     elif next.canRelayTo(next):
@@ -794,7 +794,7 @@
                     continue
                 warned[lc_nickname] = 1
                 LOG.warn("Server %s is not recommended",fixed.getNickname())
-            
+
     def checkClientVersion(self):
         """Check the current client's version against the stated version in
            the most recently downloaded directory; print a warning if this
@@ -862,7 +862,7 @@
 
         if not terse: continue
         if not result[nickname]: continue
-        
+
         ritems = result[nickname].items()
         ritems.sort()
         minva = min([ va for (va,vu),features in ritems ])
@@ -873,7 +873,7 @@
                 if rfeatures.setdefault(f,val) != val:
                     rfeatures[f] += " / %s"%val
         result[nickname] = { (minva,maxvu) : rfeatures }
-    
+
     return result
 
 def formatFeatureMap(features, featureMap, showTime=0, cascade=0, sep=" ",
@@ -915,7 +915,7 @@
                 for k, v in fMap.items():
                     if maxFeatureLength[k] < len(v):
                         maxFeatureLength[k] = len(v)
-        formatEntries = [ "%-"+str(maxFeatureLength[f])+"s" for 
+        formatEntries = [ "%-"+str(maxFeatureLength[f])+"s" for
                           f in features ]
         format = sep.join(formatEntries)
     else:
@@ -973,14 +973,14 @@
     #     server?
     # exitSize: How large (in bytes) will the message be at the exit server?
     # headers: A map from header name to value.
-    def __init__(self,exitType=None,exitAddress=None,lastHop=None,isReply=0, 
+    def __init__(self,exitType=None,exitAddress=None,lastHop=None,isReply=0,
                  isSSFragmented=0):
         """Create a new ExitAddress.
             exitType,exitAddress -- the routing type and routing info
                for the delivery (if not a reply)
             lastHop -- the nickname of the last hop in the path, if the
                exit address is specific to a single hop.
-            isReply -- true iff this message is a reply   
+            isReply -- true iff this message is a reply
             isSSFragmented -- true iff this message is fragmented for
                server-side reassembly.
         """
@@ -1012,7 +1012,7 @@
         routingType, routingInfo, _ = self.getRouting()
         return mixminion.Packet.ServerSideFragmentedMessage(
             routingType, routingInfo, "").pack()
-        
+
     def setFragmented(self, isSSFragmented, nFragments):
         """Set the fragmentation parameters of this exit address
         """
@@ -1042,7 +1042,7 @@
         """Check whether the server described by 'desc' supports this
            exit type. Returns if yes, raises a UIError if no.  If
            'verbose' is true, give warnings for iffy cases."""
-        
+
         if self.isReply:
             return
         nickname = desc.getNickname()
@@ -1050,7 +1050,7 @@
         if self.headers:
             #XXXX007 remove this eventually.
             sware = desc['Server'].get("Software","")
-            if (sware.startswith("Mixminion 0.0.4") or 
+            if (sware.startswith("Mixminion 0.0.4") or
                 sware.startswith("Mixminion 0.0.5alpha1")):
                 raise UIError("Server %s is running old software that doesn't support exit headers.", nickname)
 
@@ -1070,7 +1070,7 @@
                 exitKB = 32
 
         needFrom = self.headers.has_key("FROM")
-        
+
         if self.exitType in ('smtp', SMTP_TYPE):
             ssec = desc['Delivery/SMTP']
             if not ssec.get("Version"):
@@ -1113,7 +1113,7 @@
         """Return true iff the exit type's addresses are specific to a
            given exit hop."""
         return self.exitType in ('mbox', MBOX_TYPE)
-            
+
     def getExitServers(self, directory, startAt=None, endAt=None):
         """Given a ClientDirectory and a time range, return a list of
            server descriptors for all servers that might work for this
@@ -1275,7 +1275,7 @@
             if n < 1: n = 1
         return [ None ] * n
     def getMinLength(self):
-        if self.n is not None: 
+        if self.n is not None:
             return self.n
         else:
             return 1
@@ -1401,7 +1401,7 @@
     while path:
         if path[0] == "'":
             m = re.match(r"'([^']+|\\')*'", path)
-            if not m: 
+            if not m:
                 raise UIError("Mismatched quotes in path.")
             p.append(m.group(1).replace("\\'", "'"))
             path = path[m.end():]
@@ -1409,7 +1409,7 @@
                 raise UIError("Invalid quotes in path.")
         elif path[0] == '"':
             m = re.match(r'"([^"]+|\\")*"', path)
-            if not m: 
+            if not m:
                 raise UIError("Mismatched quotes in path.")
             p.append(m.group(1).replace('\\"', '"'))
             path = path[m.end():]
@@ -1418,11 +1418,11 @@
         else:
             m = re.match(r"[^,:]+",path)
             if not m:
-                raise UIError("Invalid path") 
+                raise UIError("Invalid path")
             p.append(m.group(0))
             path = path[m.end():]
         if not path:
-            break 
+            break
         elif path[0] == ',':
             path = path[1:]
         elif path[0] == ':':
@@ -1491,7 +1491,7 @@
         firstLegLen = 0
         lateSplit = 1
 
-    # This is a kludge to convert paths of the form ~N to ?,~(N-1), when 
+    # This is a kludge to convert paths of the form ~N to ?,~(N-1), when
     # we're generating a two-legged path.  Otherwise, there is a possibility
     # that ~N could expand into only a single server, thus leaving one leg
     # empty.
@@ -1503,7 +1503,7 @@
         pathEntries = [ RandomServersPathElement(n=1),
                         RandomServersPathElement(approx=n_minus_1) ]
         assert lateSplit
-        
+
     path1, path2 = pathEntries[:firstLegLen], pathEntries[firstLegLen:]
 
     # Die if the path is too short, or if either leg is empty in a full path.
@@ -1519,5 +1519,5 @@
             raise UIError("The path must have at least 1 hop")
         if not halfPath and minLen < 2:
             raise UIError("The path must have at least 2 hops")
-        
+
     return PathSpecifier(path1, path2, isReply, isSURB, lateSplit=lateSplit)

Index: ClientMain.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/ClientMain.py,v
retrieving revision 1.133
retrieving revision 1.134
diff -u -d -r1.133 -r1.134
--- ClientMain.py	26 Nov 2003 18:21:49 -0000	1.133
+++ ClientMain.py	28 Nov 2003 04:14:03 -0000	1.134
@@ -71,7 +71,7 @@
     # We don't make new SURBs with any key that will expire in the next
     # month.
     MIN_KEY_LIFETIME_TO_USE = 30*24*60*60
-    
+
     def __init__(self, keyDir, passwordManager=None):
         """Create a new ClientKeyring, storing its keys in 'keyDir'"""
         if passwordManager is None:
@@ -90,7 +90,7 @@
         self.keyring = mixminion.ClientUtils.Keyring(fn, passwordManager)
 
     def getSURBKey(self, name="", create=0, password=None):
-        """Return a SURB key for a given identity, asking for passwords and 
+        """Return a SURB key for a given identity, asking for passwords and
            loading the keyring if necessary..  Return None on failure.
 
            name -- the SURB key identity
@@ -106,8 +106,8 @@
                 return None
             if not self.keyring.isLoaded():
                 return None
-        
-        
+
+
         try:
             key = self.keyring.getNewestSURBKey(
                 name,minLifetime=self.MIN_KEY_LIFETIME_TO_USE)
@@ -128,7 +128,7 @@
                 self.keyring.save()
 
         assert 0 # Unreached.
-        
+
     def getSURBKeys(self, password=None):
         """Return the keys for _all_ SURB identities as a list of
            (name,key) tuples."""
@@ -232,7 +232,7 @@
                            startAt, endAt, forceQueue=0, forceNoQueue=0,
                            forceNoServerSideFragments=0):
         """Generate and send a forward message.
-            directory -- an instance of ClientDirectory; used to generate 
+            directory -- an instance of ClientDirectory; used to generate
                paths.
             address -- an instance of ExitAddress, used to tell where to
                deliver the message.
@@ -265,7 +265,7 @@
                          startAt, endAt, forceQueue=0,
                          forceNoQueue=0):
         """Generate and send a reply message.
-            directory -- an instance of ClientDirectory; used to generate 
+            directory -- an instance of ClientDirectory; used to generate
                paths.
             address -- an instance of ExitAddress, used to tell where to
                deliver the message.
@@ -314,7 +314,7 @@
            them.  Return a list of tuples of (the packet body, a
            ServerInfo for the first hop.)
 
-            directory -- an instance of ClientDirectory; used to generate 
+            directory -- an instance of ClientDirectory; used to generate
                paths.
             address -- an instance of ExitAddress, used to tell where to
                deliver the message.
@@ -346,10 +346,10 @@
             payloads = [ mixminion.BuildMessage.buildRandomPayload() ]
             address.setFragmented(0,1)
         routingType, routingInfo, _ = address.getRouting()
-        
+
         directory.validatePath(pathSpec, address, startAt, endAt,
                                warnUnrecommended=0)
-        
+
         for p, (path1,path2) in zip(payloads, directory.generatePaths(
             len(payloads), pathSpec, address, startAt, endAt)):
 
@@ -366,7 +366,7 @@
            a tuple of (packet body, ServerInfo for the first hop.)
 
 
-            directory -- an instance of ClientDirectory; used to generate 
+            directory -- an instance of ClientDirectory; used to generate
                paths.
             address -- an instance of ExitAddress, used to tell where to
                deliver the message.
@@ -382,15 +382,15 @@
         assert address.isReply
 
         payloads = mixminion.BuildMessage.encodeMessage(message, 0, "")
-        
+
         surbLog = self.openSURBLog() # implies lock
         result = []
         try:
-            surbs = surbLog.findUnusedSURBs(surbList, len(payloads), 
+            surbs = surbLog.findUnusedSURBs(surbList, len(payloads),
                                            verbose=1, now=startAt)
             if len(surbs) < len(payloads):
                 raise UIError("Not enough usable reply blocks found; all were used or expired.")
-            
+
 
             for (surb,payload,(path1,path2)) in zip(surbs,payloads,
                   directory.generatePaths(len(payloads),pathSpec, address,
@@ -399,13 +399,13 @@
                 LOG.info("Generating packet...")
                 pkt = mixminion.BuildMessage.buildReplyPacket(
                     payload, path1, surb, self.prng)
-                
+
                 surbLog.markSURBUsed(surb)
                 result.append( (pkt, path1[0]) )
-            
+
         finally:
             surbLog.close() #implies unlock
-            
+
         return result
 
     def openSURBLog(self):
@@ -522,7 +522,7 @@
             for h in handles:
                 try:
                     routing = self.queue.getRouting(h)
-                except mixminion.Filestore.CorruptedFile: 
+                except mixminion.Filestore.CorruptedFile:
                     continue
                 packet = PacketProxy(h,self.queue)
                 packets.append((packet,routing))
@@ -1131,7 +1131,7 @@
     if parser.exitAddress.isReply:
         client.sendReplyMessage(
             parser.directory, parser.exitAddress, parser.pathSpec,
-            parser.surbList, message, 
+            parser.surbList, message,
             parser.startAt, parser.endAt, forceQueue, forceNoQueue)
     else:
         client.sendForwardMessage(
@@ -1249,7 +1249,7 @@
   -C, --cascade-features     Pretty-print results, cascading by features.
   -F <name>,--feature=<name> Select which server features to list.
   --list-features            Display a list of all recognized features.
-                               
+
 EXAMPLES:
   List all currently known servers.
       %(cmd)s
@@ -1359,7 +1359,7 @@
     for line in mixminion.ClientDirectory.formatFeatureMap(
         features,featureMap,showTime,cascade,separator,justify):
         print line
-        
+
 
 _UPDATE_SERVERS_USAGE = """\
 Usage: %(cmd)s [options]
@@ -1573,7 +1573,7 @@
 
     for path1,path2 in parser.generatePaths(count):
         assert path2 and not path1
-        surb = client.generateReplyBlock(parser.exitAddress, path2, 
+        surb = client.generateReplyBlock(parser.exitAddress, path2,
                                          name=identity,
                                          expiryTime=parser.endAt)
         if binary:

Index: ClientUtils.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/ClientUtils.py,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- ClientUtils.py	26 Nov 2003 18:21:49 -0000	1.11
+++ ClientUtils.py	28 Nov 2003 04:14:04 -0000	1.12
@@ -47,7 +47,7 @@
 
            Use the prompt 'prompt' to ask the user for the password
            'name'.  Return what the user enters.
-        """   
+        """
         raise NotImplemented()
     def _getNewPassword(self, name, prompt):
         """Abstract function; subclasses must override.
@@ -55,7 +55,7 @@
            Use the prompt 'prompt' to ask the user for a _new_
            password 'name'.  Ususally, this will involve asking for
            the password twice to confirm that the user hasn't mistyped.
-        """   
+        """
         raise NotImplemented()
     def setPassword(self, name, password):
         """Change the internally cached value for the password named
@@ -67,7 +67,7 @@
            password, we call 'confirmFn' on it.  If confirmFn returns 1,
            the password is correct.  If confirmFn returns 0, the password
            is incorrect.  Queries the user at most 'maxTries' times before
-           giving up.  Raises BadPassword on failure.""" 
+           giving up.  Raises BadPassword on failure."""
         if self.passwords.has_key(name):
             pwd = self.passwords[name]
             if confirmFn(pwd):
@@ -156,7 +156,7 @@
        If the magic is incorrect, raises ValueError.
     """
     assert list(map(len, magicList)) == [8]*len(magicList)
-    
+
     text = readFile(fname)
     r = unarmorText(text, ["TYPE III KEYRING"])
     if len(r) != 1:
@@ -166,7 +166,7 @@
     vers = [ v for k,v in headers if k == 'Version' ]
     if not vers or vers[0] != '0.1':
         raise ValueError("Unrecognized version on keyring")
-    
+
     if len(s) < MAGIC_LEN+1 or s[MAGIC_LEN] != '\x00':
         raise ValueError("Unrecognized encryption format on %s"%fname)
     if s[:MAGIC_LEN] not in magicList:
@@ -249,8 +249,8 @@
         self.bestMagic = magic
         assert len(magic) == MAGIC_LEN
         self.initFn = initFn
-        self.obsoleteMagic = [] 
-        
+        self.obsoleteMagic = []
+
     def load(self, create=0,password=None,now=None):
         """Try to load the encrypted file from disk.  If 'password' is
            not provided, query it from the password manager.  If the file
@@ -258,7 +258,7 @@
            create the file."""
         if self.loaded:
             # No need to re-load an already-loaded object.
-            return 
+            return
         elif os.path.exists(self.fname):
 ##             # Okay, the file is there. Snarf it from disk and try to give a
 ##             # good warning for its magic string.
@@ -267,7 +267,7 @@
 ##                 raise MixError("Found an obsolete keyring at %r.  Remove this file to use SURBs with this version of Mixminion."%self.fname)
 ##             if len(contents)<8 or contents[:8] not in self.okMagic:
 ##                 raise MixError("Unrecognized versioning on file %s"%self.fname)
-            
+
             # ... see if we can load it with no password ...
             if self._loadWithPassword(""):
                 return
@@ -338,7 +338,7 @@
         """Helper function for subclasses to override: convert self.object to a
            string for storage, and return the converted object."""
         return cPickle.dumps(self.object, 1)
-    
+
     def _decode(self,val,magic):
         """Helper function: given a decrypted string and magic string, sets
            self.object to the corresponding decoded value."""
@@ -509,7 +509,7 @@
             _LazyEncryptedStore.load(self, create=create, password=password)
         finally:
             del self._now
-        
+
 # ----------------------------------------------------------------------
 
 class SURBLog(mixminion.Filestore.DBBase):
@@ -547,7 +547,7 @@
             now = time.time()
         nUsed = nExpired = nShortlived = 0
         result = []
-        for surb in surbList: 
+        for surb in surbList:
             expiry = surb.timestamp
             timeLeft = expiry - now
             if self.isSURBUsed(surb):
@@ -651,7 +651,7 @@
                 fname_old = os.path.join(directory, fn)
                 fname_new = os.path.join(directory, "msg_"+handle)
                 os.rename(fname_old, fname_new)
-        
+
         self.store = mixminion.Filestore.ObjectMetadataStore(
             directory, create=1, scrub=1)
 
@@ -687,7 +687,7 @@
     def getPacket(self, handle):
         """Given a handle, return a 3-tuple of the corresponding
            32K packet, {IPV4/Host}Info, and time of first queueing.  (The time
-           is rounded down to the closest midnight GMT.)  May raise 
+           is rounded down to the closest midnight GMT.)  May raise
            CorruptedFile."""
         obj = self.store.getObject(handle)
         try:

Index: Common.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/Common.py,v
retrieving revision 1.119
retrieving revision 1.120
diff -u -d -r1.119 -r1.120
--- Common.py	25 Nov 2003 03:42:31 -0000	1.119
+++ Common.py	28 Nov 2003 04:14:04 -0000	1.120
@@ -5,11 +5,11 @@
 
    Common functionality and utility code for Mixminion"""
 
-__all__ = [ 'IntervalSet', 'Lockfile', 'LockfileLocked', 'LOG', 'LogStream', 
+__all__ = [ 'IntervalSet', 'Lockfile', 'LockfileLocked', 'LOG', 'LogStream',
             'MixError',
             'MixFatalError', 'MixProtocolError', 'UIError', 'UsageError',
             'armorText', 'ceilDiv', 'checkPrivateDir', 'checkPrivateFile',
-            'createPrivateDir', 'disp64', 
+            'createPrivateDir', 'disp64',
             'encodeBase64', 'englishSequence', 'floorDiv', 'formatBase64',
             'formatDate', 'formatFnameTime', 'formatTime',
             'installSIGCHLDHandler', 'isSMTPMailbox', 'openUnique',
@@ -207,8 +207,8 @@
 
     punc = ", "
     for item in lst:
-        if ("," in item or 
-            stringContains(item, " and ") or 
+        if ("," in item or
+            stringContains(item, " and ") or
             stringContains(item, " or ")):
             punc = "; "
             break
@@ -246,7 +246,7 @@
        list of key-value pairs for headers, generates an OpenPGP-style
        ASCII-armored message of type 'type', with contents 's' and
        headers 'header'.
-       
+
        If base64 is false, uses cleartext armor."""
     result = []
     result.append("-----BEGIN %s-----\n" %type)
@@ -280,7 +280,7 @@
           we do cleartext armor.
     """
     result = []
-    
+
     while 1:
         tp = None
         fields = []
@@ -336,7 +336,7 @@
             value = "\n".join(v)
 
         result.append((tp, fields, value))
-        
+
         s = s[mEnd.end()+1:]
 
     raise MixFatalError("Unreachable code somehow reached.")
@@ -381,7 +381,7 @@
     except (KeyError, AttributeError):
         # KeyError: no such grpent.  AttributeError: grp module not loaded.
         return "group %s"%gid
- 
+
 def checkPrivateFile(fn, fix=1):
     """Checks whether f is a file owned by this uid, set to mode 0600 or
        0700, and all its parents pass checkPrivateDir.  Raises MixFatalError
@@ -400,14 +400,14 @@
         raise MixFatalError("Nonexistent file %s" % fn)
     if not os.path.isfile(fn):
         raise MixFatalError("%s is not a regular file" % fn)
-    
+
     if _CHECK_UID:
         me = os.getuid()
         if st[stat.ST_UID] != me:
             ownerName = _uidToName(st[stat.ST_UID])
             myName = _uidToName(me)
             raise MixFilePermissionError(
-                "File %s is owned by %s, but Mixminion is running as %s" 
+                "File %s is owned by %s, but Mixminion is running as %s"
                 % (fn, ownerName, myName))
     mode = st[stat.ST_MODE] & 0777
     if _CHECK_MODE and mode not in (0700, 0600):
@@ -527,7 +527,7 @@
         # WWWW right thing, but those don't exist in Windows Me/98/95.
         if os.path.exists(f2):
             os.unlink(f2)
-        os.rename(f1, f2) 
+        os.rename(f1, f2)
 else:
     def replaceFile(f1, f2):
         """Move the file named 'f1' to a new name 'f2'.  Replace any file
@@ -1398,7 +1398,7 @@
     """Helper function. Returns a file open for writing into the file named
        'fname'.  If fname already exists, opens 'fname.1' or 'fname.2' or
        'fname.3' or so on."""
-    if 'b' in mode: 
+    if 'b' in mode:
         bin = O_BINARY
     else:
         bin = 0
@@ -1529,7 +1529,7 @@
         else:
             # There is no locking implementation.
             _warn_no_locks()
-        
+
     def _unlock(self, fd):
         """Compatibility wrapper: unlock a file for unix and windows systems.
         """
@@ -1590,14 +1590,14 @@
            functionality of Queue.Queue to support a 'timeout' argument.
            If 'block' is true and timeout is provided, wait for no more
            than 'timeout' seconds before raising QueueEmpty.
-           
+
            In Python 2.3 and later, this interface is standard.
         """
         def get(self, block=1, timeout=None):
             if timeout is None or not block:
                 return MessageQueue.get(self, block)
 
-            # This logic is adapted from 'Condition' in the Python 
+            # This logic is adapted from 'Condition' in the Python
             # threading module.
             _time = time.time
             _sleep = time.sleep

Index: Config.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/Config.py,v
retrieving revision 1.68
retrieving revision 1.69
diff -u -d -r1.68 -r1.69
--- Config.py	24 Nov 2003 19:59:04 -0000	1.68
+++ Config.py	28 Nov 2003 04:14:04 -0000	1.69
@@ -249,7 +249,7 @@
     if not mixminion.Common.isPlausibleHostname(host):
         raise ConfigError("%r doesn't look like a valid hostname",host)
     return host
-                          
+
 # Regular expression to match 'address sets' as used in Allow/Deny
 # configuration lines. General format is "<IP|*> ['/'MASK] [PORT['-'PORT]]"
 _address_set_re = re.compile(r'''^(\d+\.\d+\.\d+\.\d+|\*)
@@ -710,7 +710,7 @@
         }
 
     _syntax = None
-    _features = {} 
+    _features = {}
     _restrictFormat = 0
     _restrictKeys = 1
     _restrictSections = 1
@@ -1005,4 +1005,4 @@
     # in configure_trng and configureShredCommand, respectively.
 
     # Host is checked in setupTrustedUIDs.
-    
+

Index: Crypto.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/Crypto.py,v
retrieving revision 1.56
retrieving revision 1.57
diff -u -d -r1.56 -r1.57
--- Crypto.py	20 Nov 2003 08:47:24 -0000	1.56
+++ Crypto.py	28 Nov 2003 04:14:04 -0000	1.57
@@ -756,7 +756,7 @@
 
 
 # Global TRN instance, for use by trng().
-_theTrueRNG = None 
+_theTrueRNG = None
 
 class _TrueRNG(RNG):
     '''Random number generator that yields pieces of entropy from

Index: Filestore.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/Filestore.py,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- Filestore.py	7 Nov 2003 06:59:35 -0000	1.13
+++ Filestore.py	28 Nov 2003 04:14:04 -0000	1.14
@@ -29,7 +29,7 @@
 from mixminion.Crypto import getCommonPRNG
 
 __all__ = [ "StringStore", "StringMetadataStore",
-            "ObjectStore", "ObjectMetadataStore", 
+            "ObjectStore", "ObjectMetadataStore",
             "MixedStore", "MixedMetadataStore",
             "DBBase", "JournaledDBBase", "BooleanJournaledDBBase",
             "CorruptedFile",
@@ -58,12 +58,12 @@
 
        This class is not for direct use; combine it with one of the
        mixin classes below.
-       
+
        Abstractly, a BaseStore is a consistent collection of 'things'
        with (optional) persistant metadata.  The 'things' support
        insert, move, and delete operations.  The metadata supports
        modification.
-       
+
        Implementation: a BaseStore is a directory of 'message' files.
        Each filename in the directory has a name in one of the
        following formats:
@@ -80,7 +80,7 @@
              meta_HANDLE
              inpm_HANDLE
              crpm_HANDLE
- 
+
        Threading notes:  Although BaseStore itself is threadsafe, you'll want
        to synchronize around any multistep operations that you want to
        run atomically.  Use BaseStore.lock() and BaseStore.unlock() for this.
@@ -170,7 +170,7 @@
 
     def _doRemove(self, handle, newState):
         self._changeState(handle, "msg", newState)
-        
+
     def _preserveCorrupted(self, handle):
         """Given a handle, change the message state to 'crp'."""
         self._doRemove(handle, "crp")
@@ -284,7 +284,7 @@
                 LOG.error("Directory %s contains: %s", self.dir, contents)
                 self.count(1)
                 return
-            
+
             if self.n_entries < 0:
                 return
             if s1 == 'msg' and s2 != 'msg':
@@ -513,7 +513,7 @@
     def __init__(self, location, create=0, scrub=0):
         BaseMetadataStore.__init__(self, location, create, scrub)
         ObjectMetadataStoreMixin.__init__(self)
-        
+
 class MixedStore(BaseStore, StringStoreMixin, ObjectStoreMixin):
     def __init__(self, location, create=0, scrub=0):
         BaseStore.__init__(self, location, create, scrub)
@@ -579,11 +579,11 @@
             dbtype = whichdb.whichdb(filename)
             raise MixFatalError("Unsupported type for %s database: %s"
                                 %(purpose, dbtype))
-        
+
         if hasattr(self.log, 'sync'):
             self._syncLog = self.log.sync
         elif hasattr(self.log, '_commit'):
-            # Workaround for dumbdbm to allow syncing. (Standard in 
+            # Workaround for dumbdbm to allow syncing. (Standard in
             # Python 2.3.)
             self._syncLog = self.log._commit
         else:
@@ -654,7 +654,7 @@
             del self.log[self._encodeKey(k)]
         finally:
             self._lock.release()
-        
+
     def sync(self):
         """Flush all pending changes to disk"""
         self._lock.acquire()
@@ -691,7 +691,7 @@
     # journal -- map from journal-encoded key to journal-encoded value.
     # journalFileName -- filename to use for journal file.
     # journalFile -- fd for the journal file
-    
+
     def __init__(self, location, purpose, klen, vlen, vdflt):
         """Create a new JournaledDBBase that stores its files to match the
            pattern 'location*', whose journal-encoded keys are all of length
@@ -791,7 +791,7 @@
             self.journal = {}
         finally:
             self._lock.release()
-    
+
     def close(self):
         try:
             self._lock.acquire()

Index: Fragments.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/Fragments.py,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- Fragments.py	31 Aug 2003 19:29:29 -0000	1.9
+++ Fragments.py	28 Nov 2003 04:14:04 -0000	1.10
@@ -93,7 +93,7 @@
         s = whiten(s)
         s += paddingPRNG.getBytes(self.paddingLen)
         assert len(s) == self.paddedLen
-        
+
         chunks = []
         for i in xrange(self.nChunks):
             chunks.append( s[i*self.chunkSize:(i+1)*self.chunkSize] )
@@ -211,7 +211,7 @@
         hs = s.getChunkHandles()
         msg = "".join([self.store.messageContents(h) for h in hs])
         msg = unwhiten(msg[:s.params.length])
-        return msg                      
+        return msg
 
     def markMessageCompleted(self, msgid, rejected=0):
         """Release all resources associated with the messageid 'msgid', and
@@ -241,7 +241,7 @@
             if not state.hasReadyChunks():
                 continue
             state.reconstruct(self.store)
-            
+
     def expireMessages(self, cutoff):
         """Remove all pending messages that were first inserted before
            'cutoff'. """
@@ -250,7 +250,7 @@
             if s.inserted < cutoff:
                 expiredMessageIDs[s.messageid] = 1
         self._deleteMessageIDs(expiredMessageIDs, "REJECTED")
-        
+
     def rescan(self):
         """Check all fragment metadata objects on disk, and reconstruct our
            internal view of message states.
@@ -308,7 +308,7 @@
         """Helper function. Remove all the fragments and chunks associated
            with a given message, and mark the message as delivered or
            undeliverable.
-           
+
               messageIDSet -- a map from 20-byte messageID to 1.
               why -- 'REJECTED' or 'COMPLETED'.
         """
@@ -424,14 +424,14 @@
     #     are ready for reconstruction, but haven't been reconstructed
     #     yet.
     def __init__(self, messageid, length, overhead, inserted, nym):
-        """Create a new MessageState. 
+        """Create a new MessageState.
         """
         self.messageid = messageid
         self.overhead = overhead
         self.inserted = inserted
         self.nym = nym
         # chunkno -> handle,fragmentmeta
-        self.chunks = {} 
+        self.chunks = {}
         # chunkno -> idxwithinchunk -> (handle,fragmentmeta)
         self.fragmentsByChunk = []
         self.params = FragmentationParams(length, overhead)
@@ -439,7 +439,7 @@
             self.fragmentsByChunk.append({})
         # chunkset: ready chunk num -> 1
         self.readyChunks = {}
-        
+
     def isDone(self):
         """Return true iff we have reconstructed all the chunks for this
            message."""
@@ -475,7 +475,7 @@
 
         if self.readyChunks.get(fm.chunkNum):
             del self.readyChunks[fm.chunkNum]
-            
+
     def addFragment(self, h, fm, noop=0):
         """Register a fragment with handle h and FragmentMetadata fm.  If the
            fragment is inconsistent with the other fragments of this message,
@@ -488,7 +488,7 @@
         if (fm.size != self.params.length or
             fm.overhead != self.overhead):
             raise MismatchedFragment
-        
+
         chunkNum, pos = self.params.getPosition(fm.idx)
         if chunkNum >= self.params.nChunks:
             raise MismatchedFragment
@@ -496,7 +496,7 @@
         if (self.chunks.has_key(chunkNum) or
             len(self.fragmentsByChunk[chunkNum]) >= self.params.k):
             raise UnneededFragment
-        
+
         if self.fragmentsByChunk[chunkNum].has_key(pos):
             raise MismatchedFragment
 
@@ -504,7 +504,7 @@
             return
         assert h
         if self.inserted > fm.insertedDate:
-            self.inserted = fm.insertedDate        
+            self.inserted = fm.insertedDate
         self.fragmentsByChunk[chunkNum][pos] = (h, fm)
 
         if len(self.fragmentsByChunk[chunkNum]) >= self.params.k:
@@ -586,7 +586,7 @@
         status = {"C":"COMPLETED", "R":"REJECTED"}[v[0]]
         tm = int(v[2:])
         return status, tm
-            
+
 # ======================================================================
 # Internal lazy-generated cache from (k,n) to _minionlib.FEC object.
 # Note that we only use k,n for a limited set of k,n.

Index: MMTPClient.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/MMTPClient.py,v
retrieving revision 1.43
retrieving revision 1.44
diff -u -d -r1.43 -r1.44
--- MMTPClient.py	24 Nov 2003 19:59:04 -0000	1.43
+++ MMTPClient.py	28 Nov 2003 04:14:04 -0000	1.44
@@ -113,7 +113,7 @@
         # Do the TLS handshaking
         mixminion.NetUtils.connectWithTimeout(
             self.sock, (self.targetAddr, self.targetPort), connectTimeout)
-        
+
         LOG.debug("Handshaking with %s:", self.serverName)
         self.tls = self.context.sock(self.sock.fileno())
         self.tls.connect()
@@ -289,7 +289,7 @@
            return.  If not, raise MixProtocolBadAuth.  Display all messages
            using the server 'serverName'.
         """
-        
+
         # First, make sure the certificate is neither premature nor expired.
         try:
             tls.check_cert_alive()

Index: Main.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/Main.py,v
retrieving revision 1.63
retrieving revision 1.64
diff -u -d -r1.63 -r1.64
--- Main.py	26 Nov 2003 18:21:49 -0000	1.63
+++ Main.py	28 Nov 2003 04:14:04 -0000	1.64
@@ -206,7 +206,7 @@
 
 def commandShell(cmd,args):
     # Used to implement a 'mixminion shell' on systems (like windows) with
-    # somewhat bogus CLI support. 
+    # somewhat bogus CLI support.
     import mixminion
     import shlex
 

Index: NetUtils.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/NetUtils.py,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- NetUtils.py	19 Nov 2003 09:48:09 -0000	1.4
+++ NetUtils.py	28 Nov 2003 04:14:04 -0000	1.5
@@ -20,7 +20,7 @@
 # Global vars
 
 # When we get IPv4 and IPv6 addresses for the same host, which do we use?
-PREFER_INET4 = 1
+PREFER_INET4 = 1  # For now, _always_ prefer IPv4
 
 # Local copies of socket.AF_INET4 and socket.AF_INET6.  (AF_INET6 may be
 #  unsupported.)
@@ -32,7 +32,7 @@
 
 # For windows -- list of errno values that we can expect when blocking IO
 # blocks on a connect.
-IN_PROGRESS_ERRNOS = [ getattr(errno, ename) 
+IN_PROGRESS_ERRNOS = [ getattr(errno, ename)
    for ename in [ "EINPROGRESS", "WSAEWOULDBLOCK"]
    if hasattr(errno,ename) ]
 del ename
@@ -88,7 +88,7 @@
         if len(e.args) == 2:
             return ("NOENT", str(e[1]), time.time())
         else:
-            return ("NOENT", str(e), time.time())            
+            return ("NOENT", str(e), time.time())
 #----------------------------------------------------------------------
 
 _SOCKETS_SUPPORT_TIMEOUT = hasattr(socket.SocketType, "settimeout")
@@ -204,7 +204,7 @@
             pass
         if s is not None:
             s.close()
-            
+
     _PROTOCOL_SUPPORT = tuple(res)
     return res
 
@@ -216,7 +216,7 @@
 def normalizeIP4(ip):
     """If IP is an IPv4 address, return it in canonical form.  Raise
        ValueError if it isn't."""
-    
+
     i = ip.strip()
 
     # inet_aton is a bit more permissive about spaces and incomplete
@@ -242,7 +242,7 @@
         raise ValueError("Invalid characters %r in address %r"%(bad,ip))
     if len(ip) < 2:
         raise ValueError("IPv6 address %r is too short"%ip)
-        
+
     items = ip.split(":")
     if not items:
         raise ValueError("Empty IPv6 address")
@@ -269,14 +269,14 @@
             if not (0 <= val <= 0xFFFF):
                 raise ValueError("IPv6 word %r out of range"%item)
             foundWords += 1
-            
+
     if foundNils > 1:
         raise ValueError("Too many ::'s in IPv6 address %r"%ip)
     elif foundNils == 0 and foundWords < 8:
         raise ValueError("IPv6 address %r is too short"%ip)
     elif foundWords > 8:
         raise ValueError("IPv6 address %r is too long"%ip)
-            
+
     return ip
 
 def nameIsStaticIP(name):
@@ -297,4 +297,4 @@
             return None
     else:
         return None
-            
+

Index: Packet.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/Packet.py,v
retrieving revision 1.67
retrieving revision 1.68
diff -u -d -r1.67 -r1.68
--- Packet.py	26 Nov 2003 18:21:49 -0000	1.67
+++ Packet.py	28 Nov 2003 04:14:04 -0000	1.68
@@ -14,7 +14,7 @@
             'encodeMailHeaders', 'encodeMessageHeaders',
             'FRAGMENT_PAYLOAD_OVERHEAD', 'FWD_HOST_TYPE', 'FWD_IPV4_TYPE',
             'FragmentPayload',
-            'FRAGMENT_MESSAGEID_LEN', 'FRAGMENT_TYPE', 
+            'FRAGMENT_MESSAGEID_LEN', 'FRAGMENT_TYPE',
             'HEADER_LEN', 'IPV4Info', 'MAJOR_NO', 'MBOXInfo',
             'MBOX_TYPE', 'MINOR_NO', 'MIN_EXIT_TYPE',
             'MIN_SUBHEADER_LEN', 'MMTPHostInfo', 'Packet',
@@ -27,8 +27,8 @@
             'parseMBOXInfo', 'parsePacket', 'parseMessageAndHeaders',
             'parsePayload', 'parseRelayInfoByType', 'parseReplyBlock',
             'parseReplyBlocks', 'parseSMTPInfo', 'parseSubheader',
-            'parseTextEncodedMessages', 'parseTextReplyBlocks', 
-            'uncompressData'            
+            'parseTextEncodedMessages', 'parseTextReplyBlocks',
+            'uncompressData'
             ]
 
 import binascii
@@ -93,10 +93,10 @@
 FRAGMENT_TYPE  = 0x0103  # Find the actual delivery info in the message payload
 MAX_EXIT_TYPE  = 0xFFFF
 
-# Set of exit types that don't get tag fields. 
-# XXXX007 This interface is really brittle; it needs to change.  I added it 
+# Set of exit types that don't get tag fields.
+# XXXX007 This interface is really brittle; it needs to change.  I added it
 # XXXX007 in order to allow 'fragment' to be an exit type without adding a
-# XXXX007 needless tag field to every fragment routing info.  
+# XXXX007 needless tag field to every fragment routing info.
 _TYPES_WITHOUT_TAGS = { FRAGMENT_TYPE : 1 }
 
 def typeIsSwap(tp):
@@ -209,7 +209,7 @@
         if _TYPES_WITHOUT_TAGS.get(self.routingtype):
             return self.routinginfo
         else:
-            assert len(self.routinginfo) >= TAG_LEN            
+            assert len(self.routinginfo) >= TAG_LEN
             return self.routinginfo[TAG_LEN:]
 
     def getTag(self):
@@ -413,7 +413,7 @@
 def parseServerSideFragmentedMessage(s):
     if len(s) < SSF_PREFIX_LEN:
         raise ParseError("Server-side fragmented message too short")
-    
+
     rt, rl = struct.unpack(SSF_UNPACK_PATTERN, s[:SSF_PREFIX_LEN])
     if len(s) < SSF_PREFIX_LEN + rl:
         raise ParseError("Server-side fragmented message too short")
@@ -729,21 +729,21 @@
 # the body is base64-encoded.
 
 MESSAGE_ARMOR_NAME = "TYPE III ANONYMOUS MESSAGE"
- 
+
 def parseTextEncodedMessages(msg,force=0):
     """Given a text-encoded Type III packet, return a list of
        TextEncodedMessage objects or raise ParseError.
-       
+
           force -- uncompress the message even if it's overcompressed.
     """
-    
+
     def isBase64(t,f):
         for k,v in f:
             if k == "Message-type":
                 if v != 'plaintext':
                     return 1
         return 0
-    
+
     unarmored = unarmorText(msg, (MESSAGE_ARMOR_NAME,), base64fn=isBase64)
     res = []
     for tp,fields,val in unarmored:
@@ -769,7 +769,7 @@
 
         if msgType == 'LONG' and force:
             msg = uncompressData(msg)
-            
+
         if msgType in ('TXT','BIN','LONG','FRAG'):
             res.append(TextEncodedMessage(val, msgType))
         else:

Index: ServerInfo.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/ServerInfo.py,v
retrieving revision 1.64
retrieving revision 1.65
diff -u -d -r1.64 -r1.65
--- ServerInfo.py	24 Nov 2003 19:59:04 -0000	1.64
+++ ServerInfo.py	28 Nov 2003 04:14:04 -0000	1.65
@@ -77,7 +77,7 @@
     """Given a 20-byte keyid, look up the nickname of the corresponding
        server.  Return the nickname on success and None if we don't recognize
        the server.
-    
+
        FFFF Right now, this is not supported for servers, since they don't
        FFFF download directories.
     """
@@ -200,13 +200,13 @@
                     if k == 'Descriptor-Version' and v.strip() != '0.2':
                         raise ConfigError("Unrecognized descriptor version: %s"
                                           % v.strip())
-        
-        
+
+
         # Remove any sections with unrecognized versions.
         revisedContents = []
         for name, ents in contents:
             v = self.expected_versions.get(name)
-            if not v: 
+            if not v:
                 revisedContents.append((name, ents))
                 continue
             versionkey, versionval = v
@@ -346,7 +346,7 @@
         host = self.getHostname()
         if host is None: return None
         return MMTPHostInfo(host, self.getPort(), self.getKeyDigest())
-    
+
     def getRoutingInfo(self):
         """Return whichever of MMTPHostInfo or IPV4 info is best for
            delivering to this server (assuming that the sending host
@@ -414,7 +414,7 @@
                   mixminion.Packet.SWAP_FWD_IPV4_TYPE][swap]
 
         return rt, ri
-        
+
     def getCaps(self):
         """Return a list of strings to describe this servers abilities in
            a concise human-readable format."""

Index: benchmark.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/benchmark.py,v
retrieving revision 1.48
retrieving revision 1.49
diff -u -d -r1.48 -r1.49
--- benchmark.py	10 Nov 2003 04:04:35 -0000	1.48
+++ benchmark.py	28 Nov 2003 04:14:04 -0000	1.49
@@ -287,7 +287,7 @@
 
     print "RSA generate (1024 bit,e=100073471)", timeit(
         lambda: pk_generate(1024, 100073471), 10)
-                             
+
     rsa = pk_generate(1024, 100073471)
     print "Pad+RSA public encrypt",
     print timeit((lambda rsa=rsa: pk_encrypt(s70b, rsa)),1000)
@@ -490,7 +490,7 @@
     d2 = mix_mktemp()
     os.mkdir(d2,0700)
     getCommonPRNG().getBytes(1)
-    
+
     #for ln,it in (32*1024,100),(128,400),(1024,400), (32*1024,100):
     for ln,it in ():
         msg = "z"*ln
@@ -919,10 +919,10 @@
         #tls.get_peer_cert_pk()
         certcache.check(tls, keyid, ("127.0.0.1", TEST_PORT))
         #print certcache.cache
-        
+
         tls.shutdown()
         sock.close()
-            
+
 
 
     while 1:
@@ -1005,14 +1005,14 @@
         fec = _ml.FEC_generate(3,5)
         chunks = [ fec.encode(i, inp) for i in xrange(5) ]
         fec.decode([(i, chunks[i]) for i in xrange(2,5) ])
-        
+
 #----------------------------------------------------------------------
 def timeAll(name, args):
     if 0:
         timeEfficiency()
         return
 
-    fecTiming()    
+    fecTiming()
     cryptoTiming()
     rsaTiming()
     buildMessageTiming()

Index: test.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/test.py,v
retrieving revision 1.168
retrieving revision 1.169
diff -u -d -r1.168 -r1.169
--- test.py	25 Nov 2003 02:15:14 -0000	1.168
+++ test.py	28 Nov 2003 04:14:04 -0000	1.169
@@ -203,7 +203,7 @@
         if not floatEq(f1, f2, tolerance):
             self.fail("%s != %s" % (f1, f2))
     def assertLongStringEq(self, s1, s2):
-        """Fail unless the string s1 equals the string s2.  If they aren't 
+        """Fail unless the string s1 equals the string s2.  If they aren't
            equal, give a failure message that highlights the first point at
            which they differ."""
         if s1 != s2:
@@ -279,7 +279,7 @@
             self.assertEquals(parse(s), t)
             if not last:
                 continue
-            
+
             if c == 'EX':
                 self.assertRaises(ValueError, cmp, last, t)
             elif c == '<':
@@ -566,7 +566,7 @@
         LF1.replaceContents("shorter")
         if not ON_WINDOWS:
             self.assertEquals("shorter", readFile(fn))
-        
+
         self.assertRaises(LockfileLocked, LF2.acquire, blocking=0)
         LF1.release()
         LF2.acquire("LF2",1)
@@ -727,7 +727,7 @@
         self.assertEquals("fred", es(["fred"]))
         self.assertEquals("fred and joe", es(["fred", "joe"]))
         self.assertEquals("fred, joe, and bob", es(["fred", "joe", "bob"]))
-        self.assertEquals("fred, jr; joe; and bob", 
+        self.assertEquals("fred, jr; joe; and bob",
                           es(["fred, jr", "joe", "bob"]))
         self.assertEquals("fred, jr; and bob",
                           es(["fred, jr", "bob"]))
@@ -738,9 +738,9 @@
                              compound="or"))
         self.assertEquals("fred", es(["fred"], compound="or"))
         self.assertEquals("fred or joe", es(["fred", "joe"], compound="or"))
-        self.assertEquals("fred, joe, or bob", 
+        self.assertEquals("fred, joe, or bob",
                           es(["fred", "joe", "bob"], compound="or"))
-        
+
 #----------------------------------------------------------------------
 
 class MinionlibCryptoTests(TestCase):
@@ -989,7 +989,7 @@
             out = fec.decode(chk)
             eq(out, inpChunks)
             eq("".join(out), inp)
-          
+
     def test_good_fec(self):
         self.do_fec_test(3,5,10)
         self.do_fec_test(10,20,1024)
@@ -999,7 +999,7 @@
         self.do_fec_test(3,3,2048)
 
     def test_bad_fec(self):
-        
+
         self.assertRaises(_ml.FECError,_ml.FEC_generate,5,3)
         self.assertRaises(_ml.FECError,_ml.FEC_generate,0,10)
         self.assertRaises(_ml.FECError,_ml.FEC_generate,10,300)
@@ -1204,7 +1204,7 @@
         for i in xrange(1,10000,17):
             self.failUnless(0 <= PRNG.getInt(10) < 10)
             self.failUnless(0 <= PRNG.getInt(i) < i)
-        
+
         # Check getNormal
         tot = 0
         for i in xrange(1,1000):
@@ -1384,7 +1384,7 @@
         self.failUnlessRaises(ParseError, parseMMTPHostInfo, "\x30\x55"+keyid)
         self.failUnlessRaises(ParseError, parseMMTPHostInfo,
                               "\x30\x55"+keyid+"_.com")
-                          
+
 
     def test_replyblock(self):
         # Try parsing an example 'reply block' object
@@ -1791,7 +1791,7 @@
     def getRoutingFor(self,other,swap):
         tp = [FWD_IPV4_TYPE,SWAP_FWD_IPV4_TYPE][swap]
         return (tp, other.getRoutingInfo().pack())
-                
+
 
 class BuildMessageTests(TestCase):
     def setUp(self):
@@ -1828,7 +1828,7 @@
 
     def test_payload_helpers(self):
         "test helpers for payload encoding"
-        
+
         p = AESCounterPRNG()
         for _ in xrange(10):
             t = BuildMessage._getRandomTag(p)
@@ -2124,7 +2124,7 @@
         self.assertEquals(payload, p[:len(payload)])
 
     def test_build_fwd_message(self):
-        
+
         bfm = BuildMessage.buildForwardPacket
         befm = BuildMessage.buildEncryptedForwardPacket
         payloadF = BuildMessage.encodeMessage("Hello!!!!",0)[0]
@@ -2144,7 +2144,7 @@
                                 "Goodbye") ),
                              "Hello!!!!")
         m = bfm(payloadF, 500, "Goodbye", [self.server1], [self.server3])
-        
+
         messages = {}
 
         def decoder0(p,t,messages=messages):
@@ -2160,7 +2160,7 @@
                                ("Goodbye",) ),
                              "Hello!!!!",
                              decoder=decoder0)
-        
+
         # Drop message gets no tag, random payload
         m = bfm(BuildMessage.buildRandomPayload(),
                 DROP_TYPE, "", [self.server1], [self.server3])
@@ -2204,7 +2204,7 @@
                                     "Phello") ),
                                  "<<<<Hello>>>>"*100,
                                  decoder=decoder)
-            
+
         # Now do more tests on final messages: is the format as expected?
         p,t = messages['fwd']
         self.assertEquals(20, len(t))
@@ -2339,7 +2339,7 @@
             payload = BuildMessage._decodeStatelessReplyPayload(p,t,
                                                          "Tyrone Slothrop")
             return payload.getUncompressedContents()
-        
+
         self.do_message_test(m,
                              ((self.pk3, self.pk1), None,
                               (FWD_IPV4_TYPE,SWAP_FWD_IPV4_TYPE),
@@ -2702,7 +2702,7 @@
         p = encodeMessageHeaders(h) + "This is the message.\n"
         m = bfm(BuildMessage.encodeMessage(p,0)[0],
                 SMTP_TYPE, "nobody@invalid",[self.server1], [self.server3])
-        pkt = self.do_test_chain(m, 
+        pkt = self.do_test_chain(m,
                                  [self.sp1, self.sp3],
                                  [FWD_IPV4_TYPE, SMTP_TYPE],
                                  [self.server3.getRoutingInfo().pack(),
@@ -2712,13 +2712,13 @@
         self.assert_(not pkt.isEncrypted())
         self.assertEquals(pkt.getContents(), "This is the message.\n")
         self.assertEquals(pkt.getHeaders(), h)
-        
+
         #    (binary msg with headers.)
         body = "\x01\x02\x03\x04"*10
         p = encodeMessageHeaders(h) + body
         m = bfm(BuildMessage.encodeMessage(p,0)[0],
                 SMTP_TYPE, "nobody@invalid",[self.server1], [self.server3])
-        pkt = self.do_test_chain(m, 
+        pkt = self.do_test_chain(m,
                                  [self.sp1, self.sp3],
                                  [FWD_IPV4_TYPE, SMTP_TYPE],
                                  [self.server3.getRoutingInfo().pack(),
@@ -2869,7 +2869,7 @@
         self.d3 = mix_mktemp("q3")
     def testCreateStore(self):
         Store = mixminion.Filestore.MixedStore
-        
+
         # Nonexistent dir.
         self.failUnlessRaises(MixFatalError, Store, self.d1)
         # File in place of dir
@@ -2903,7 +2903,7 @@
 
     def testStoreOps(self):
         Store = mixminion.Filestore.MixedStore
-        
+
         queue1 = Store(self.d2, create=1)
         queue2 = Store(self.d3, create=1)
 
@@ -3080,7 +3080,7 @@
         for fn in os.listdir(d_parent):
             self.assertStartsWith(fn, "db0")
             os.unlink(os.path.join(d_parent,fn))
-        
+
         # Test journaled DB.
         loc = os.path.join(d_parent, "db1")
         jloc = loc+"_jrnl"
@@ -3333,7 +3333,7 @@
         self.assertEndsWith(buf.getvalue(), "[WARN] Hello, world\n")
         self.failUnless(buf.getvalue().index('\n') == len(buf.getvalue())-1)
         log.error("All your anonymity are belong to us")
-        self.assertEndsWith(buf.getvalue(), 
+        self.assertEndsWith(buf.getvalue(),
             "[ERROR] All your anonymity are belong to us\n")
 
         buf.truncate(0)
@@ -3357,7 +3357,7 @@
         if ON_WIN32: #WWWW
             log.close()
             return
-        
+
         os.rename(t,t1)
         log.info("Ghi")
         log.reset()
@@ -3438,7 +3438,7 @@
             return st[stat.ST_MODE]&0777, st[stat.ST_UID], os.path.isdir(f)
 
         # Now we test a directory we don't own...
-        if not ON_WIN32 and os.getuid() == 0: 
+        if not ON_WIN32 and os.getuid() == 0:
             # If we're root, we can play with chown!
             # We don't own the directory
             os.chown(subdir, 1, 1)
@@ -3994,7 +3994,7 @@
 
 class ConfigFileTests(TestCase):
     def testValidFiles(self):
-        
+
         TCF = TestConfigFile
         # Try a minimal file.
         shorterString = """[Sec1]\nFoo a\n"""
@@ -4101,13 +4101,13 @@
         try:
             TestConfigFile(None,"[Sec1]\nFoo: 1\nBap:1\n")
         except ConfigError, e:
-            self.assertEndsWith(str(e), 
+            self.assertEndsWith(str(e),
                                 "Unrecognized key Bap on line 3. This "
                                 "key belongs in Sec2, but appears in Sec1.")
         try:
             TestConfigFile(None,"[Sec1]\nFoo: 1\nQuz:1\n")
         except ConfigError, e:
-            self.assertEndsWith(str(e), 
+            self.assertEndsWith(str(e),
                                "Unrecognized key Quz on line 3. This key "
                                "belongs in Sec2 or Sec3, but appears in Sec1.")
 
@@ -4249,7 +4249,7 @@
         self.assertEquals(SC._parseMixRule("binomialCottrell"),
                           "BinomialCottrellMixPool")
         self.assertEquals(SC._parseMixRule("TIMED"), "TimedMixPool")
-        
+
 
         ##
         # Now, try the failing cases.
@@ -5967,22 +5967,22 @@
             self.assertEquals(receiveDict['bar'][:2],
                               (mixminion.NetUtils.AF_INET6, '18:0FFF::4:1'))
             # We allow a little wiggle on DELAY, since many OS's don't
-            # stricly guarantee that 
+            # stricly guarantee that
             #     t1=time();sleep(x);t2=time();assert t2>=t1+x
             # will pass.
-            self.assert_(DELAY*.8 <= receiveDict['foo'][2]-start 
+            self.assert_(DELAY*.8 <= receiveDict['foo'][2]-start
                                   <= DELAY+LATENCY)
-            self.assert_(DELAY*.8 <= receiveDict['bar'][2]-start 
+            self.assert_(DELAY*.8 <= receiveDict['bar'][2]-start
                                   <= DELAY+LATENCY)
             self.assertEquals(receiveDict['nowhere.noplace'][0], "NOENT")
             self.assertEquals(cache.getNonblocking("foo"),
                               receiveDict['foo'])
             self.assertEquals(cache.getNonblocking("baz.com")[:2],
                               (socket.AF_INET, '10.99.22.8'))
-            self.assert_(DELAY*1.20 <= receiveDict['baz.com'][2]-start 
+            self.assert_(DELAY*1.20 <= receiveDict['baz.com'][2]-start
                                     <= DELAY*1.25 + LATENCY)
 
-            # Change foo's expiration time to be well before nowhere's, 
+            # Change foo's expiration time to be well before nowhere's,
             # then expire foo but not nowhere.
             t2 = receiveDict['nowhere.noplace'][2]
             cache.cache['foo'] = cache.cache['foo'][:2]+((t2-5),)
@@ -6000,7 +6000,7 @@
             self.assertEquals(5, len(receiveDict))
         finally:
             undoReplacedAttributes()
-            
+
 #----------------------------------------------------------------------
 
 class ServerMainTests(TestCase):
@@ -6201,7 +6201,7 @@
         idx1 = contents.index("\n\n")+2
         idx2 = contents.rindex("\n-----END TYPE")
         contents = base64.decodestring(contents[idx1:idx2])
-        
+
         self.assertEquals(contents[:8], magic1)
         self.assertEquals(contents[8], '\x00')
         salt = contents[9:17]
@@ -6212,10 +6212,10 @@
         self.assertEquals(decrypted[4:14], "xyzzyxyzzy")
         self.assertEquals(decrypted[-20:],
                           mixminion.Crypto.sha1(decrypted[:-20]+salt+magic1))
-        
+
         self.assertEquals((magic1,"xyzzyxyzzy"),
                           CU._readEncryptedFile(f1, "x", [magic1, "BLIZNERT"]))
-        
+
         # Try reading with wrong password.
         self.assertRaises(CU.BadPassword, CU._readEncryptedFile,
                           f1, "nobodaddy", [magic1])
@@ -6227,7 +6227,7 @@
         # Try empty data.
         CU._writeEncryptedFile(f1, password="x", magic=magic1, data="")
         self.assertEquals((magic1,""),CU._readEncryptedFile(f1, "x", [magic1]))
-        
+
         # Test LazyEncryptedStore
         class DummyPasswordManager(CU.PasswordManager):
             def __init__(self,d):
@@ -6348,7 +6348,7 @@
                  for _ in range(3)]
 
         #FFFF check for skipping expired and shortlived SURBs.
-        
+
         s = SURBLog(fname)
         try:
             self.assert_(not s.isSURBUsed(surbs[0]))
@@ -6403,7 +6403,7 @@
         self.assertEquals((ipv4,previousMidnight(now)), v[1:])
         self.assertLongStringEq(v[0], p1)
         cq.removePacket(h1)
-        
+
 class ClientDirectoryTests(TestCase):
     def testClientDirectory(self):
         """Check out ClientMain's directory implementation"""
@@ -6657,7 +6657,7 @@
 
         #XXXX007 remove
         mixminion.ClientDirectory.WARN_STAR = 0
-        
+
         paddr = mixminion.ClientDirectory.parseAddress
         email = paddr("smtp:lloyd@dobler.com")
         mboxWithServer = paddr("mbox:Granola@Lola")
@@ -6825,7 +6825,7 @@
         self.assertEquals(map(len,[p1,p2,p3,p4,p5,p6]),[1,3,1,3,1,3])
         self.assertEquals(p2[-1].getNickname(), p4[-1].getNickname())
         self.assertEquals(p2[-1].getNickname(), p6[-1].getNickname())
-        
+
         # 2. Failing cases
         raises = self.assertRaises
         # Nonexistent server
@@ -6908,7 +6908,7 @@
           [ "Alice:xxx yy", "Bob:zz ww / kk" ])
         self.assertEquals(formatFeatureMap(["A","B"],fm4,showTime=0,cascade=0,
                                            just=1,sep="!"),
-          [ "Alice:xxx!yy     ", 
+          [ "Alice:xxx!yy     ",
             "Bob  :zz !ww / kk" ])
         self.assertEquals(formatFeatureMap(["A","B"],fm3,showTime=1,cascade=0),
           [ "Alice:1970-01-01 to 1970-01-01:xxx yy",
@@ -6926,7 +6926,7 @@
             "Bob:",
             "  [1970-01-02 to 1970-01-03] a1##b1",
             "  [1970-01-03 to 1970-01-04] a2##b2" ])
-        
+
         self.assertEquals(formatFeatureMap(["A","B"],fmx,showTime=1,cascade=2),
           [ "Alice:", "  [1970-01-02 to 1970-01-04]", "    A:aa", "    B:bb",
             "Bob:",
@@ -7066,7 +7066,7 @@
         # Create a directory...
         dirname = mix_mktemp()
         directory = mixminion.ClientDirectory.ClientDirectory(dirname)
-        
+
         edesc = getExampleServerDescriptors()
         fname = mix_mktemp()
         for server, descriptors in edesc.items():
@@ -7083,7 +7083,7 @@
         Lola = ServerInfo(string=edesc["Lola"][1], assumeValid=1)
         Joe = ServerInfo(string=edesc["Joe"][0], assumeValid=1)
         Alice = ServerInfo(string=edesc["Alice"][1], assumeValid=1)
-        
+
         # ... and for now, we need to restart the client.
         client = mixminion.ClientMain.MixminionClient(usercfg)
 
@@ -7224,7 +7224,7 @@
                           (K28*20, K28 - 47, 16, 22,
                            2, 16*(K28-47), 32*(K28-47),
                            fp1.paddedLen-(K28*20)))
-        
+
 
         # 3 chunks.
         fp1 = FP(K28 * 32 + 101, 0)
@@ -7234,11 +7234,11 @@
                           (K28*32+101, K28 - 47, 16, 22,
                            3, 16*(K28-47), 48*(K28-47),
                            fp1.paddedLen-(K28*32+101)))
-        
+
 
     def testFragmentation(self):
         FP = mixminion.Fragments.FragmentationParams
-        
+
         # One chunk.
         msg = Crypto.getCommonPRNG().getBytes(150*1024)
         fp1 = FP(len(msg), 38)
@@ -7249,7 +7249,7 @@
             self.assertEquals(len(b), 28*1024 - 47 - 38)
         m2 = "".join(fec.decode(zip(range(3,11),blocks[3:])))
         self.assertLongStringEq(msg, unwhiten(m2[:150*1024]))
-        
+
         # Three chunks.
         msg = Crypto.getCommonPRNG().getBytes(28*32*1024 + 101)
         fp1 = FP(len(msg), 0)
@@ -7264,7 +7264,7 @@
             self.assertEquals(16, len(receivedBlocks))
             chunks.append("".join(fec.decode(receivedBlocks)))
         self.assertLongStringEq(msg, unwhiten(("".join(chunks))[:len(msg)]))
-        
+
     def testFragmentPool(self):
         em = mixminion.BuildMessage.encodeMessage
         pp = mixminion.Packet.parsePayload
@@ -7274,7 +7274,7 @@
         pkts2 = [ pp(x) for x in em(M2,0) ]
         self.assertEquals(map(len, [pkts1,pkts2]),
                           [3, 66])
-        
+
         loc = mix_mktemp()
         pool = mixminion.Fragments.FragmentPool(loc)
         self.assertEquals([], pool.listReadyMessages())
@@ -7333,7 +7333,7 @@
         # Provoke an error in the big one part way through.
         ####
         M1 = Crypto.getCommonPRNG().getBytes(1024*150)
-        M2 = Crypto.getCommonPRNG().getBytes(1024*200) 
+        M2 = Crypto.getCommonPRNG().getBytes(1024*200)
         M3 = Crypto.getCommonPRNG().getBytes(1024*900)
         pkts1 = [ pp(x) for x in em(M1,38) ]
         pkts2 = [ pp(x) for x in em(M2,0) ]
@@ -7376,7 +7376,7 @@
         pool.expireMessages(time.time()+48*60*60)
         self.assertEquals(pool.listReadyMessages(), [])
         pool.close()
-        
+
 #----------------------------------------------------------------------
 
 def initializeGlobals():
@@ -7431,7 +7431,7 @@
                    NetUtilTests,
                    DNSFarmTests,
                    ClientUtilTests,
-           
+
                    ModuleTests,
                    ClientDirectoryTests,
                    ClientMainTests,
@@ -7457,7 +7457,7 @@
     # under the mixminion package.
     if os.environ.get("MM_COVERAGE"):
         allmods = [ mod for name, mod in sys.modules.items()
-                    if (mod is not None and 
+                    if (mod is not None and
                         name.startswith("mixminion") and
                         name != 'mixminion._minionlib') ]
         coverage.report(allmods)

Index: testSupport.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/testSupport.py,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -d -r1.22 -r1.23
--- testSupport.py	7 Nov 2003 07:03:28 -0000	1.22
+++ testSupport.py	28 Nov 2003 04:14:04 -0000	1.23
@@ -369,7 +369,7 @@
 def tvRSA():
     print "======================================== RSA"
     pk1 = TEST_KEYS_2048[0]
-    print "Example 2048-bit Key K" 
+    print "Example 2048-bit Key K"
     n,e = pk1.get_public_key()
     n2,e2,d,p,q = pk1.get_private_key()
     print "   exponent =",hexNum(e)
@@ -377,7 +377,7 @@
     print "   Private key (P)=",hexNum(p)
     print "   Private key (Q)=",hexNum(q)
     print "   Private key (D)=",hexNum(d)
-    
+
     print "   PK_Encode(K) =",hexStr(pk1.encode_key(1))
     print "   Fingerprint =",mixminion.Crypto.pk_fingerprint(pk1)
 
@@ -391,11 +391,11 @@
                 mixminion.Crypto.OAEP_PARAMETER,256,CyclicRNG())
     print "   Padded string (2048 bits):",hexStr(enc)
     pkenc = pk1.crypt(enc,1,1)
-    
+
     print
     print "   PK_Encrypt(K,M):",hexStr(pkenc)
     assert mixminion.Crypto.pk_decrypt(pkenc,pk1) == s
-    
+
 def tvAES():
     import mixminion._minionlib as _ml
     print "======================================== AES"
@@ -408,8 +408,8 @@
     db = _ml.aes128_block_crypt(_ml.aes_key(k),b,0)
     print "   Encrypted block:",hexStr(eb)
     print "   Decrypted block:",hexStr(db)
-    
-    print 
+
+    print
     print "Counter mode encryption:"
     k = unHexStr("[02 13 24 35 46 57 68 79 8A 9B AC BD CE DF E0 F1]")
     print "   Key:",hexStr(k)
@@ -448,7 +448,7 @@
     assert unHexNum(hexNum(10000))  in (10000, 10000L)
     assert unHexNum(hexNum(100000)) in (100000,100000L)
     assert unHexNum(hexNum(1000000000L)) == 1000000000L
-    
+
     tvRSA()
     tvAES()
     tvLIONESS()