[Nym3-commit] r443 - in trunk/nymbaron: . Client Server

jr at conuropsis.org jr at conuropsis.org
Mon Dec 19 23:22:56 CET 2005


Author: jr
Date: 2005-12-19 23:22:55 +0100 (Mon, 19 Dec 2005)
New Revision: 443

Modified:
   trunk/nymbaron/Client/Account.py
   trunk/nymbaron/Client/Main.py
   trunk/nymbaron/Common.py
   trunk/nymbaron/Server/User.py
Log:
- change the synbox format. Beware this is not thouroughfully tested yet. It
  might break your accounts' format [client]


Modified: trunk/nymbaron/Client/Account.py
===================================================================
--- trunk/nymbaron/Client/Account.py	2005-12-15 16:02:42 UTC (rev 442)
+++ trunk/nymbaron/Client/Account.py	2005-12-19 22:22:55 UTC (rev 443)
@@ -22,30 +22,60 @@
 # IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-"""nymbaron.Client.Acount
+"""nymbaron.Client.Account
 
     This package contains user account information representation on the client
     side and ways to create, access to and modify them."""
 
 import copy
 import os
-import nymbaron.Client.Keyring as Keyring
-import nymbaron.Mail as Mail
-import mixminion.Common
-import nymbaron.Common as Common
-import mixminion.Crypto as _cr
-import nymbaron.Message as Message
-import nymbaron.Crypto as Crypto
-#import mixminion.ClientAPI as mapi
 import pickle
 import tempfile
 import time
 #TODO debugging cruft associated to seqno display
 import binascii
 
+import mixminion.Common
+import mixminion.Crypto as _cr
+#import mixminion.ClientAPI as mapi
+
+from nymbaron.Common import binsearch
+import nymbaron.Client.Keyring as Keyring
+import nymbaron.Mail as Mail
+import nymbaron.Common as Common
+import nymbaron.Message as Message
+import nymbaron.Crypto as Crypto
+
 SEQNO_LEN = 20
 SURB_LEN = 2104
 
+#TODO this helper function exists beause the necessity to convert old format
+#synbox to new format synbox. Once this conversion isn't required anymore, it
+#should be removed and its body should be placed in add_syn.
+def add_syn_to_synbox(h, l, xnymseq, mid, flag, syn, sorted = False):
+    """Adds a tuple (xnymseq, mid, flag, syn) corresponding to a syn to a synbox
+    (ie a tuple (dict, seq)."""
+    #Add to the hash
+    if h.has_key(mid):
+	#TODO what should be done here?
+	raise Exception("Bug mid not unique")
+    h[mid] = (xnymseq, flag, syn)
+    #Add to the list
+    #if sorted it is quick to insert from the end
+    if sorted:
+	i = len(l)
+	while i > 0:
+	    if l[i-1][0] <= xnymseq:
+		l[i:i] = [mid]
+		return
+	    i = i - 1
+	l[0:0] = [mid]
+    #else we use a binary search
+    else:
+	#look for the first mid whose seq number is greater than xnymseq
+	i = binsearch(l, lambda x: (h[x][0] > xnymseq))
+	l[i:i] = [mid]
+
 class NoSuchAccount(Exception): pass
 """Exception thrown when a user identified by her nym can't be found"""
 
@@ -167,11 +197,17 @@
 	- data is the hash that contains all of this
 	- datafile() is the file where we pickle from and to the data hash
 	- synbox is the synopsis box, stored in synboxfile()
-	  It is a hashtable that associates to a XNymSeq a t-uple
+	  It was a hashtable that associates to a XNymSeq a t-uple
 	  (mid, flag_is_present_on server, synopsis)
 	  it may be represented by a string : the encrypted pickled hashtable
 	  (status = 'encrypted') or a hashtable (status = decrypted).
 	  When saved, it is put in the encrypted form.
+	  Due to the meaning of the mid the previous structure is deprecated and
+	  replaced by a tuple (dic, seq) where 
+	    - dic is a hashtable mid -> (xnymseq, flag_is_present_on_server,
+	  synopsis). In the new format xnymseq is an int whereas it was a str in
+	  the old format
+	    - seq is a list of dic.keys(), sorted by ascending xnymseq
 	- mbox is the couple of a hash mid to message and a list of the keys of
 	  the hash to order these keys, stored in mboxfile()
 	- a journal which is a hash of seqno -> encrypted (message, time sent)		  and is pickled from/to journalfile()
@@ -219,7 +255,7 @@
 	    self.journal_status = 'dirty'
 	    self.mbox = {}, []
 	    self.mbox_status = 'dirty'
-	    self.synbox = {}
+	    self.synbox = {}, []
 	    self.synbox_status = 'dirty'
 	    self.synbox_enc_status = 'decrypted'
 	    self['encKeys'] = []
@@ -469,7 +505,7 @@
 	    self.synbox_enc_status = 'encrypted'
 	    f.close()
 	except IOError:
-	    self.synbox = {}
+	    self.synbox = {}, []
 	    self.synbox_enc_status = 'decrypted'
 	self.synbox_status = 'ok'
 
@@ -494,6 +530,20 @@
 	key = secring.get_key(self['admKey'])
 	self.synbox = pickle.loads(Crypto.nym_decrypt(self.synbox, key))
 	self.synbox_enc_status = 'decrypted'
+	#TODO the following code converts a synbox in the old format (dictionary
+	#to a synbox in the new format. Remove once we can assume the old format
+	#isn't used anymore.
+	if type(self.synbox) == dict:
+	    synbox = {}, []
+	    xnymseqs = self.synbox.keys()
+	    xnymseqs = map(int, xnymseqs)
+	    xnymseqs.sort()
+	    for xnymseq in xnymseqs:
+		(mid, flag, syn) = self.synbox[str(xnymseq)]
+		add_syn_to_synbox(synbox[0], synbox[1], xnymseq,
+			mid, flag, syn, True)
+	    self.synbox = synbox
+	    self.synbox_status = 'dirty'
 	
     def get_synbox(self, secring):
 	"""return a copy of the synbox, trying to decrypt it if it is encrypted
@@ -512,21 +562,27 @@
 	return copy.deepcopy(self.journal)
 
     def add_syn(self, secring, xnymseq, mid, flag, syn):
-	"""add a syn to the synbox"""
+	"""add a syn to the synbox. The secring is used only if the synbox is
+	encrypted."""
 	self._decrypt_synbox(secring)
-	self.synbox[str(xnymseq)] = (mid, flag, syn)
+	add_syn_to_synbox(self.synbox[0], self.synbox[1], xnymseq, mid, flag,
+		syn)
 	self.synbox_status = "dirty"
 
     def delete_syn(self, secring, mid):
 	self._decrypt_synbox(secring)
-	l = []
-	for i, (m, flag, syn) in self.synbox.iteritems():
-	    if m == mid:
-		l.append(i)
-	if len(l) > 0:
-	    self.synbox_status = "dirty"
-	for i in l:
-	    del(self.synbox[i])
+	h, l = self.synbox
+	if h.has_key(mid):
+	    i = binsearch(l, lambda x: (x[0] >= h[mid][0]))
+	    while h[l[i]][0] == h[mid][0]:
+		if l[i] == mid:
+		    del(self.synbox[1][i])
+		    del(self.synbox[0][mid])
+		    self.synbox_status = "dirty"
+		    return
+	    raise Error("Bug : mid in the synbox hash but not sequence")
+	#TODO cruft -> output a warning here
+	print "mid %s not in the synbox, doing nothing" % binascii.hexlify(mid)
 		
     def add_msg(self, mid, msg):
 	self._load_mbox()

Modified: trunk/nymbaron/Client/Main.py
===================================================================
--- trunk/nymbaron/Client/Main.py	2005-12-15 16:02:42 UTC (rev 442)
+++ trunk/nymbaron/Client/Main.py	2005-12-19 22:22:55 UTC (rev 443)
@@ -177,12 +177,11 @@
 def build_syn_index(secring, account):
     """Builds the index of synopses of the given account. secring must be
     decrypted and contain the private admin key of account. Returns a hash
-    containing the correspondance index -> mid, where index is a XNymSeq as a
-    str"""
+    containing the correspondance index -> mid, index as a str"""
     synbox = account.get_synbox(secring)
     index = {}
-    for xnymseq, (mid, flag, syn) in synbox.iteritems():
-	index[xnymseq] = mid
+    for i, mid in enumerate(synbox[1]):
+	index[str(i)] = mid
     return index
 
 def build_mbox_index(account):
@@ -597,26 +596,20 @@
 	    "No nickname given, abort\nUse -n <nickname>")
     secring = decode_secring(config, ui)
     synbox = account.get_synbox(secring)
-    if len(synbox) == 0:
+    if len(synbox[0]) == 0:
 	ui.display("empty synbox")
 	return
+    print synbox
     mbox = account.get_mbox()[0]
-    # TODO here we need to go from str to int to str because the type of object
-    # we chose as key in the dictionnary synbox is str, but we need int order
-    # moving from int would break existing accounts. Should we add temporarily a
-    # migration function, or is breaking some accounts ok?
-    # for the time being, keep the same structure and convert data as we need
-    xnymseqs = map(int, synbox.keys())
-    xnymseqs.sort()
-    for xnymseq in xnymseqs:
-	(mid, flag, syn) = synbox[str(xnymseq)]
+    for i, mid in enumerate(synbox[1]):
+	(xnymseq, flag, syn) = synbox[0][mid]
 	if mbox.has_key(mid):
 	    avail = "email available"
 	elif flag:
 	    avail = "email available on server"
 	else:
 	    avail = "email not available"
-	ui.display("%d %s %s" % (xnymseq, binascii.hexlify(mid), avail))
+	ui.display("%d %s %s" % (i, binascii.hexlify(mid), avail))
 	if summarize:
 	    ui.display(Mail.syn_summary(syn))
 	else:

Modified: trunk/nymbaron/Common.py
===================================================================
--- trunk/nymbaron/Common.py	2005-12-15 16:02:42 UTC (rev 442)
+++ trunk/nymbaron/Common.py	2005-12-19 22:22:55 UTC (rev 443)
@@ -43,3 +43,22 @@
               "ShutdownPhrase"] 
 """The accepted strings identifying userPolicies"""
 
+#functions
+
+def binsearch(l, prop):
+    """Returns the first index i of l for which l[i] is true,
+       assuming prop is increasing over l"""
+    min = 0
+    max = len(l) - 1
+    if not prop(l[max]): return IndexError
+    if prop(l[min]): return min
+
+    current = (max + min) / 2
+    while max - min > 1:
+	if prop(l[current]):
+	    max = current
+	    current = (max + min) / 2
+	else:
+	    min = current
+	    current = (max + min) / 2
+    return max

Modified: trunk/nymbaron/Server/User.py
===================================================================
--- trunk/nymbaron/Server/User.py	2005-12-15 16:02:42 UTC (rev 442)
+++ trunk/nymbaron/Server/User.py	2005-12-19 22:22:55 UTC (rev 443)
@@ -31,20 +31,23 @@
 import re
 import os
 import sys
-import nymbaron.Server.Config as Config
-import nymbaron.Mail as Mail
-import nymbaron.Crypto as Crypto
-import nymbaron.Message as Message
 import pickle
 import string
 import time
 import calendar
+
 import mixminion.Common
-from nymbaron.Message import intToStrBE
 import mixminion.Crypto as _cr
 from mixminion.Packet import parseReplyBlocks, ParseError, compressData
 import mixminion.Fragments
 
+from nymbaron.Common import binsearch
+from nymbaron.Message import intToStrBE
+import nymbaron.Server.Config as Config
+import nymbaron.Mail as Mail
+import nymbaron.Crypto as Crypto
+import nymbaron.Message as Message
+
 maxSynPerBlob = 16
 # See nym-spec, § 4.4.3
 
@@ -81,24 +84,6 @@
 
     return p.n * p.nChunks
 
-def binsearch(l, prop):
-    """Returns the first index i of l for which l[i] is true,
-       assuming prop is increasing over l"""
-    min = 0
-    max = len(l) - 1
-    if not prop(l[max]): return IndexError
-    if prop(l[min]): return min
-
-    current = (max + min) / 2
-    while max - min > 1:
-	if prop(l[current]):
-	    max = current
-	    current = (max + min) / 2
-	else:
-	    min = current
-	    current = (max + min) / 2
-    return max
-
 def check_surb(surb):
     """Returns True if the surb is usable, False if it was already used or is
     out of date"""



More information about the Nym3-commit mailing list