From 8d502134c0a470c57dda4fd114bd1140101145aa Mon Sep 17 00:00:00 2001 From: a-Sansara Date: Tue, 9 Oct 2012 22:57:01 +0200 Subject: [PATCH] multi account --- cmd.bat | 2 +- impra/cli.py | 145 +++++++++++++++++++++++------------ impra/core.py | 191 ++++++++++++++++++++++++++++++++++++---------- impra/crypt.py | 24 +++++- impra/imap.py | 3 +- impra/util.py | 13 ++-- impra/w32color.py | 2 +- imprastorage.py | 2 +- launcher.bat | 2 +- setup_build.py | 2 +- 10 files changed, 279 insertions(+), 107 deletions(-) diff --git a/cmd.bat b/cmd.bat index 53d912e..0c3c8a0 100644 --- a/cmd.bat +++ b/cmd.bat @@ -1,7 +1,7 @@ :: # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # :: # :: software : ImpraStorage # -:: version : 0.7 # +:: version : 0.8 # :: date : 2012 # :: licence : GPLv3.0 # :: author : a-Sansara # diff --git a/impra/cli.py b/impra/cli.py index 82d8067..7a93db4 100644 --- a/impra/cli.py +++ b/impra/cli.py @@ -3,7 +3,7 @@ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # software : ImpraStorage # -# version : 0.7 # +# version : 0.8 # # date : 2012 # # licence : GPLv3.0 # # author : a-Sansara # @@ -41,7 +41,7 @@ LINE_SEP_LEN = 120 LINE_SEP_CHAR = '―' if not Clz.isUnix : LINE_SEP_CHAR = '-' APP_TITLE = 'ImpraStorage' -APP_VERSION = '0.7' +APP_VERSION = '0.8' APP_AUTHOR = 'a-Sansara' APP_COPY = 'pluie.org' APP_LICENSE = 'GNU GPLv3' @@ -106,24 +106,26 @@ class Cli: parser.add_option('-q', '--quiet' , help='don\'t print status messages to stdout' , action='store_false', default=True) parser.add_option('-d', '--debug' , help='set debug mode' , action='store_true' , default=False) - gpData.add_option('-c', '--category' , help='set specified CATEGORY (crit. for opt. -l,-a or -s)' , action='store', metavar='CATG ') - gpData.add_option('-u', '--user' , help='set specified USER (crit. for opt. -l,-a or -s)' , action='store', metavar='OWNER ') - gpData.add_option('-l', '--label' , help='set specified LABEL (edit mode only)' , action='store', metavar='LABEL ') - gpData.add_option('-o', '--order' , help='set colon ORDER (crit. for opt. -l and -s)' , action='store', metavar='ORDER ' , default='ID') - gpData.add_option('-O', '--order-inv' , help='set colon ORDER_INVERSE (crit. for opt. -l and -s)' , action='store', metavar='ORDER_INVERSE') + gpData.add_option('-c', '--category' , help='set specified CATEGORY (crit. for opt. -l,-a or -s)' , action='store', metavar='CATG ') + gpData.add_option('-u', '--user' , help='set specified USER (crit. for opt. -l,-a or -s)' , action='store', metavar='OWNER ') + gpData.add_option('-l', '--label' , help='set specified LABEL (edit mode only)' , action='store', metavar='LABEL ') + gpData.add_option('-o', '--order' , help='set colon ORDER (crit. for opt. -l and -s)' , action='store', metavar='ORDER ' , default='ID') + gpData.add_option('-O', '--order-inv' , help='set colon ORDER_INVERSE (crit. for opt. -l and -s)' , action='store', metavar='ORDER_INVERSE ') #gpData.add_option('-o', '--output-dir' , help='set specified OUTPUT DIR (for opt. -l,-a,-d or -g)' , action='store', metavar='DIR ') parser.add_option_group(gpData) - gpConf.add_option('-V', '--view' , help='view configuration' , action='store' ) - gpConf.add_option('-L', '--load' , help='load configuration' , action='store' ) - gpConf.add_option('-S', '--save' , help='save configuration' , action='store' ) - gpConf.add_option('-C', '--check' , help='check configuration' , action='store' ) - gpConf.add_option('-H', '--set-host' , help='set imap host server' , action='store', metavar='HOST ') - gpConf.add_option('-U', '--set-user' , help='set imap user login' , action='store', metavar='USER ') - gpConf.add_option('-X', '--set-pass' , help='set imap user password' , action='store', metavar='PASS ') - gpConf.add_option('-P', '--set-port' , help='set imap port' , action='store', metavar='PORT ') - gpConf.add_option('-N', '--set-name' , help='set user name' , action='store', metavar='NAME ') - gpConf.add_option('-B', '--set-boxname' , help='set boxName on imap server (default:[%default])' , action='store', metavar='BOXNAME ') + gpConf.add_option('-V', '--view' , help='view configuration' , action='store' ) + gpConf.add_option('-L', '--load' , help='load configuration' , action='store' ) + gpConf.add_option('-S', '--save' , help='save configuration' , action='store' ) + gpConf.add_option('-C', '--check' , help='check configuration' , action='store' ) + gpConf.add_option('-H', '--set-host' , help='set imap host server' , action='store', metavar='HOST ') + gpConf.add_option('-U', '--set-user' , help='set imap user login' , action='store', metavar='USER ') + gpConf.add_option('-X', '--set-pass' , help='set imap user password' , action='store', metavar='PASS ') + gpConf.add_option('-P', '--set-port' , help='set imap port' , action='store', metavar='PORT ') + gpConf.add_option('-N', '--set-name' , help='set user name' , action='store', metavar='NAME ') + gpConf.add_option('-M', '--set-multi' , help='set multi account' , action='store', metavar='ACCOUNT PASSWORD', nargs=2) + gpConf.add_option('-R', '--remove-multi' , help='remove multi account' , action='store', metavar='ACCOUNT ') + gpConf.add_option('-B', '--set-boxname' , help='set boxName on imap server (default:[%default])' , action='store', metavar='BOXNAME ') gpConf.add_option('-K', '--gen-key' , help='generate new key' , action='store_true', default=False) parser.add_option_group(gpConf) @@ -170,25 +172,42 @@ class Cli: if o.view == 'all' : sections = self.ini.getSections() if len(sections) > 0: - Clz.print(' '+','.join(sections), Clz.fgB3) + ap = self.ini.get('profile') + sep = '' + for p in sections: + if p == ap : + colr = Clz.fgB1 + p = '*'+p + else : colr = Clz.fgB3 + Clz.print(sep+p, colr, False) + if sep=='':sep=',' + print() else : Clz.print(' no profiles', Clz.fgB1) else: self.ini.print(o.view) elif o.save : self.print_header() - if not o.set_host and not o.set_user and not o.set_pass and not o.set_port and not o.set_boxname and not o.set_name and not o.gen_key: + if not o.set_host and not o.set_user and not o.set_pass and not o.set_port and not o.set_boxname and not o.set_name and not o.gen_key and not o.set_multi and not o.remove_multi: parser.error(' no options specified') else : if o.set_port and not util.represents_int(o.set_port): parser.error(' port must be a number') self.exit(1) else : - if o.set_boxname: self.ini.set('box' , o.set_boxname,o.active_profile+'.imap') - if o.set_host: self.ini.set('host', o.set_host,o.active_profile+'.imap') - if o.set_user: self.ini.set('user', o.set_user,o.active_profile+'.imap') - if o.set_pass: self.ini.set('pass', o.set_pass,o.active_profile+'.imap') - if o.set_port: self.ini.set('port', o.set_port,o.active_profile+'.imap') - if o.set_name: self.ini.set('name', o.set_name,o.active_profile+'.infos') + if o.set_boxname: self.ini.set('box' , o.set_boxname,o.active_profile+'.imap') + if o.set_host : self.ini.set('host' , o.set_host,o.active_profile+'.imap') + if o.set_user : self.ini.set('user' , o.set_user,o.active_profile+'.imap') + if o.set_pass : self.ini.set('pass' , o.set_pass,o.active_profile+'.imap') + if o.set_port : self.ini.set('port' , o.set_port,o.active_profile+'.imap') + if o.set_name : self.ini.set('name' , o.set_name,o.active_profile+'.infos') + + m = self.ini.get('multi',o.active_profile+'.imap') + if m is None : m = {} + else: m = eval(m) + if o.set_multi : m[o.set_multi[0]] = o.set_multi[1] + elif o.remove_multi and m is not None and o.remove_multi in m : m.pop(o.remove_multi,None) + self.ini.set('multi', core.jdumps(m),o.active_profile+'.imap') + if o.gen_key: kg = crypt.KeyGen(256) self.ini.set('key' ,kg.key,o.active_profile+'.keys') @@ -227,19 +246,36 @@ class Cli: print() Clz.print(' it seems that your current profile `' , Clz.fgB1, False) Clz.print(o.active_profile , Clz.fgB3, False) - Clz.print('` has a wrong key to decrypt index on server.' , Clz.fgB1) - Clz.print(' you can remove index but all presents files on the box `', Clz.fgB1, False) - Clz.print(conf.get('box','imap') , Clz.fgB3, False) + Clz.print('` (account:`' , Clz.fgB1, False) + Clz.print(conf.get('user','imap') , Clz.fgB3, False) + Clz.print('`) has a wrong key to decrypt index on server.' , Clz.fgB1) + Clz.print(' you can remove index but all presents files`' , Clz.fgB1, False) Clz.print('` will be unrecoverable\n' , Clz.fgB1, True, False) - - remIndex = input(' remove index ? (yes/no) ') - if remIndex.lower()=='yes': - Clz.print(' ',Clz.OFF) + + resp = input(' backup index ? (yes/no) ') + if resp.lower()=='yes': + encData = util.get_file_content(core.dirname(conf.ini.path)+core.sep+'.index') + from time import strftime + ipath = core.dirname(conf.ini.path)+core.sep+strftime('%Y%M%d')+'-'+o.active_profile+'.index' + with open(ipath, mode='w', encoding='utf-8') as o: + o.write(encData) + Clz.print('\nindex backup in `',Clz.fgn7, False) + Clz.print(ipath,Clz.fgB3, False) + Clz.print('`',Clz.fgn7) + Clz.print('\n',Clz.fgB1, True, False) + resp = input(' remove index ? (yes/no) ') + if resp.lower()=='yes': impst = core.ImpraStorage(conf, True, self.wkpath) + print() + print(' bye') + Clz.print(' ',Clz.OFF) + print() + self.exit(1) else : print() print(' bye') + Clz.print(' ',Clz.OFF) print() self.exit(1) @@ -282,7 +318,7 @@ class Cli: order = o.order if o.order_inv is not None: order = '-'+o.order_inv - impst.index.print(order,matchIds) + impst.index.print(order,matchIds) elif a[0] == 'add': @@ -447,6 +483,8 @@ class Cli: Clz.print(a[1] , Clz.bg1+Clz.fgB3, False) Clz.print('` is not a valid id == ', Clz.bg1+Clz.fgB7) print() + else : + self.check_profile(o.active_profile, True) else : if self.ini.isEmpty() : @@ -490,7 +528,7 @@ class Cli: def check_profile(self,profile, activeCheck=False): """""" - c = self.ini.hasSection(profile+'.keys') and self.ini.has('host',profile+'.imap') and self.ini.has('user',profile+'.imap') and self.ini.has('pass',profile+'.imap') and self.ini.has('port',profile+'.imap') + c = self.ini.hasSection(profile+'.keys') and self.ini.has('host',profile+'.imap') and self.ini.has('user',profile+'.imap') and self.ini.has('pass',profile+'.imap') and self.ini.has('port',profile+'.imap') and self.ini.has('name',profile+'.infos') if activeCheck : if c : Clz.print(' '+profile+' is ok', Clz.fgB2) @@ -503,25 +541,26 @@ class Cli: except crypt.BadKeyException as e : pass else : - Clz.print(' '+profile+' incomplete', Clz.fgB1) - Clz.print(' need :', Clz.fgB1) + Clz.print(' profile `' , Clz.fgB1, False) + Clz.print(profile , Clz.fgB3, False) + Clz.print('` is incomplete\n need :', Clz.fgB1) if not self.ini.hasSection(profile+'.keys'): - Clz.print(' key (conf -S "'+profile+'" -K)', Clz.fgB1) + Clz.print(' '*4+'key'.ljust(18,' ')+' (conf -S "'+profile+'" -K)', Clz.fgB3) if not self.ini.has('host',profile+'.imap'): - Clz.print(' imap host (conf -S "'+profile+'" -H hostName)', Clz.fgB1) + Clz.print(' '*4+'imap host'.ljust(18,' ')+' (conf -S "'+profile+'" -H hostName)', Clz.fgB3) if not self.ini.has('user',profile+'.imap'): - Clz.print(' imap user (conf -S "'+profile+'" -U userName)', Clz.fgB1) + Clz.print(' '*4+'imap user'.ljust(18,' ')+' (conf -S "'+profile+'" -U accountName)', Clz.fgB3) if not self.ini.has('pass',profile+'.imap'): - Clz.print(' imap password (conf -S "'+profile+'" -X password)', Clz.fgB1) + Clz.print(' '*4+'imap password'.ljust(18,' ')+' (conf -S "'+profile+'" -X password)', Clz.fgB3) if not self.ini.has('port',profile+'.imap'): - Clz.print(' imap port (conf -S "'+profile+'" -P port)', Clz.fgB1) + Clz.print(' '*4+'imap port'.ljust(18,' ')+' (conf -S "'+profile+'" -P port)', Clz.fgB3) if not self.ini.has('name',profile+'.infos'): if c : Clz.print(' think to add your userName :',Clz.bgB3) - Clz.print(' userName (conf -S "'+profile+'" -N yourName)', Clz.fgB3) + Clz.print(' '*4+'userName'.ljust(18,' ')+' (conf -S "'+profile+'" -N yourName)', Clz.fgB3) return c - def print_header(self): + def print_header(self): printLineSep(LINE_SEP_CHAR,LINE_SEP_LEN) printHeaderTitle(APP_TITLE) printHeaderPart('version',APP_VERSION) @@ -672,6 +711,12 @@ class Cli: Clz.print('{', Clz.fgB1, False) Clz.print('name', Clz.fgB1, False) Clz.print('}', Clz.fgB1, False) + Clz.print(', -M ', Clz.fgB3, False) + Clz.print('{', Clz.fgB1, False) + Clz.print('name', Clz.fgB1, False) + Clz.print('} {', Clz.fgB1, False) + Clz.print('pass', Clz.fgB1, False) + Clz.print('}', Clz.fgB1, False) Clz.print(' ]', Clz.fgB3) def print_options(self): @@ -785,6 +830,7 @@ class Cli: Clz.print('BOXNAME'.ljust(10,' ') , Clz.fgB1, False) Clz.print(', --set-box'.ljust(18,' ') , Clz.fgB3, False) Clz.print('BOXNAME'.ljust(10,' ') , Clz.fgB1) + Clz.print(' '*50+'set imap boxname (default:__impra__)' , Clz.fgB7) print('\n') @@ -1044,13 +1090,14 @@ class Cli: def load_profile(self,o): - """""" + """""" if self.check_profile(o.active_profile): - print('profile '+o.active_profile+' loaded') + print('',end=' ') + Clz.print(' == profile `', Clz.bg2+Clz.fgb7, False) + Clz.print(o.active_profile, Clz.bg2+Clz.fgB3, False) + Clz.print('` loaded == ', Clz.bg2+Clz.fgb7) + print() self.ini.set('profile', o.active_profile) self.ini.write() else : - if not self.ini.hasSection(o.active_profile+'.imap'): - print('profile '+o.active_profile+' don\'t exist !') - else : - print('profile '+o.active_profile+' can\'t be load - incomplete\n (did you remember to generate keys ?)') + self.check_profile(o.active_profile, True) diff --git a/impra/core.py b/impra/core.py index c0944c4..bd11423 100644 --- a/impra/core.py +++ b/impra/core.py @@ -3,7 +3,7 @@ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # software : ImpraStorage # -# version : 0.7 # +# version : 0.8 # # date : 2012 # # licence : GPLv3.0 # # author : a-Sansara # @@ -47,7 +47,7 @@ from re import split as regsplit, match as regmatch, compile a from time import time, sleep from impra.imap import ImapHelper, ImapConfig from impra.util import __CALLER__, RuTime, formatBytes, randomFrom, bstr, quote_escape, stack, run, file_exists, get_file_content, DEBUG, DEBUG_ALL, DEBUG_LEVEL, DEBUG_NOTICE, DEBUG_WARN, mkdir_p, is_binary, clear, Clz -from impra.crypt import Kirmah, ConfigKey, Noiser, Randomiz, hash_sha256, hash_md5_file, BadKeyException +from impra.crypt import Kirmah, ConfigKey, Noiser, Randomiz, hash_sha256, hash_md5_file, BadKeyException, hash_sha256_file # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -140,7 +140,7 @@ class FSplitter : Clz.print('\n deploying file as :' , Clz.fgn7) Clz.print(' '+basename(filePath)+ext , Clz.fgB2, False) filePath += ext - + filePath = abspath(filePath) fp = open(filePath, 'wb+') depDir = self.DIR_INBOX if fake : depDir = self.DIR_OUTBOX @@ -256,6 +256,8 @@ class ImpraIndex: BFLAG = 7 """""" SIZE = 8 + """""" + ACCOUNT = 9 """""" FILE_BINARY = 'b' """""" @@ -287,17 +289,18 @@ class ImpraIndex: for k in dicCategory : if k == "users" : for k1 in dicCategory[k]: - if k1 not in self.dic[self.SEP_KEY_INTERN+k]: - self.dic[self.SEP_KEY_INTERN+k][k1] = dicCategory[k][k1] + if self.SEP_KEY_INTERN+k in self.dic: + if k1 not in self.dic[self.SEP_KEY_INTERN+k]: + self.dic[self.SEP_KEY_INTERN+k][k1] = dicCategory[k][k1] else : if not self.SEP_KEY_INTERN+k in self.dic: self.dic[self.SEP_KEY_INTERN+k] = dicCategory[k] - def add(self,key, label, count, ext='', usr='', cat='', md5='', bFlag='b', size=''): + def add(self,key, label, count, ext='', usr='', cat='', md5='', bFlag='b', size='', account=''): """Add an entry to the index """ if self.get(md5) == None : - self.dic[md5] = (key,label,count,ext,usr,cat,self.id,bFlag,size) + self.dic[md5] = (key,label,count,ext,usr,cat,self.id,bFlag,size,account) self.id +=1 else : print(label+' already exist') @@ -387,6 +390,33 @@ class ImpraIndex: rt.stop() return l + def fixAccount(self,account): + """""" + r = [k for i, k in enumerate(self.dic) if not k.startswith(self.SEP_KEY_INTERN)] + for k in r: + t = list(self.dic[k]) + t[self.ACCOUNT] = account + self.dic[k] = tuple(t) + + def getLightestAccount(self,l): + """""" + r = [k for i, k in enumerate(self.dic) if not k.startswith(self.SEP_KEY_INTERN)] + t = {} + for k in r: + if not self.dic[k][self.ACCOUNT] in t: t[self.dic[k][self.ACCOUNT]] = self.dic[k][self.SIZE] + else: t[self.dic[k][self.ACCOUNT]] += int(self.dic[k][self.SIZE]) + account = None + r = [] + for a in l: + if not a in t : + account = a + break + else : r.append((t[a],a)) + if account is None : + d = sorted(r, reverse=False, key=lambda lst:lst[0]) + account = d[0][1] + return account + def fixDuplicateIds(self): """Get corresponding keys of duplicate ids in the index :Returns: `str`|None key @@ -402,7 +432,7 @@ class ImpraIndex: for k in d: mxid += 1 print(self.dic[k]) - t = list(self.dic[k]) + t = list(self.dic[k]) t[self.UID] = mxid print(t) self.dic[k] = tuple(t) @@ -474,7 +504,7 @@ class ImpraIndex: """""" #~ print('decrypting index : ') try : - jdata = self.km.decrypt(data,'.index',22) + jdata = self.km.decrypt(data,'.index',22) data = jloads(jdata) except ValueError as e: raise BadKeyException(e) @@ -489,24 +519,32 @@ class ImpraIndex: orderIndex = self.COLS.index(order) if orderIndex is None : orderIndex = self.COLS.index('ID') - Clz.print(' ID'+' '*1, Clz.BG4+Clz.fgB7, False, False) + d = sorted([(self.dic.get(k),k) for i, k in enumerate(self.dic) if not k.startswith(self.SEP_KEY_INTERN)], reverse=inv, key=lambda lst:lst[0][orderIndex]) + + sizeid = 1+ceil(len(d)) + if sizeid < 3 : sizeid = 3 + sizeid = 3 + addsize = abs(3 - sizeid); + Clz.print(' ID'+' '*(1+addsize), Clz.BG4+Clz.fgB7, False, False) print('HASH' +' '*6 , end='') - print('LABEL' +' '*35, end='') + print('LABEL' +' '*(35), end='') print('SIZE' +' '*5 , end='') print('PART' +' '*2 , end='') print('TYPE' +' '*2 , end='') print('USER' +' '*11, end='') - Clz.print('CATEGORY'+' '*22, Clz.BG4+Clz.fgB7) - printLineSep(LINE_SEP_CHAR,LINE_SEP_LEN) + print('CATEGORY'+' '*(22-addsize)) + #print('CATEGORY'+' '*(22-addsize), end='') + #Clz.print('ACCOUNT'+' '*(3), Clz.BG4+Clz.fgB7) + printLineSep(LINE_SEP_CHAR,LINE_SEP_LEN) - d = sorted([(self.dic.get(k),k) for i, k in enumerate(self.dic) if not k.startswith(self.SEP_KEY_INTERN)], reverse=inv, key=lambda lst:lst[0][orderIndex]) a = '' tsize = 0 psize = 0 + #~ acc = {} #~ acc = {} for v,k in d : if matchIds==None or v[self.UID] in matchIds: a = '' - Clz.print(str(v[self.UID]).rjust(1+ceil(len(str(v[self.UID]))/10),' ')+' ', Clz.bg1+Clz.fgB7, False) + Clz.print(str(v[self.UID]).rjust(sizeid,' '), Clz.bg1+Clz.fgB7, False) Clz.print(' '+str(k)[0:6]+'... ' , Clz.fgN2, False) if len(v[self.LABEL])>36 : a = '...' Clz.print(str(v[self.LABEL][:36]+a).ljust(40,' ') , Clz.fgN7, False) @@ -514,20 +552,38 @@ class ImpraIndex: Clz.print(str(v[self.PARTS]).rjust(2 ,'0') +' '*2 , Clz.fgN1, False) Clz.print(str(v[self.EXT][:5]).ljust(7,' ') , Clz.fgn3, False) Clz.print(self.getUser(str(v[self.USER])).ljust(15 ,' ') , Clz.fgn7, False) - Clz.print(str(v[self.CATG]) +' '*2 , Clz.fgN3) + Clz.print(str(v[self.CATG]).ljust(30 ,' ') , Clz.fgN3) + #~ Clz.print(str(v[self.CATG]).ljust(30 ,' ') , Clz.fgN3, False) + #~ if len(v)-1==self.ACCOUNT: + #~ Clz.print(str(v[self.ACCOUNT]) +' '*2 , Clz.fgN3) + #~ if v[self.ACCOUNT] in acc : + #~ acc[v[self.ACCOUNT]] += int(v[self.SIZE]) + #~ else : acc[v[self.ACCOUNT]] = int(v[self.SIZE]) + #~ else: print() psize += int(v[self.SIZE]) tsize += int(v[self.SIZE]) - + if len(d)==0: + Clz.print(' empty', Clz.fgB1) printLineSep(LINE_SEP_CHAR,LINE_SEP_LEN) c = Clz.fgB2 if psize != tsize : c = Clz.fgB7 - Clz.print('size : ', Clz.fgB3, False) + Clz.print(' size : ', Clz.fgB3, False) Clz.print(formatBytes(int(psize))[:9].rjust(9,' '), c, False) if psize != tsize : Clz.print(' / ', Clz.fgB3, False) - Clz.print(formatBytes(int(tsize)), Clz.fgB2) + Clz.print(formatBytes(int(tsize)), Clz.fgB2, False) print() - + printLineSep(LINE_SEP_CHAR,LINE_SEP_LEN) + #~ Clz.print(' '*4+'[', Clz.fgB7, False) + #~ sep = '' + #~ for k in acc: + #~ if k!= '': + #~ Clz.print(sep+k,Clz.fgB3,False) + #~ Clz.print(':',Clz.fgB7,False) + #~ Clz.print(formatBytes(acc[k]),Clz.fgB2,False) + #~ if sep=='':sep = ',' + #~ Clz.print(']', Clz.fgB7, False) + #~ print() # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~ class ImpraStorage ~~ @@ -543,20 +599,29 @@ class ImpraStorage: self.wkdir = wkdir self.conf = conf self.pathInd = dirname(self.conf.ini.path)+sep+'.index' - self.rootBox = self.conf.get('box','imap') - iconf = ImapConfig(self.conf.get('host','imap'), self.conf.get('port','imap'), self.conf.get('user', 'imap'), self.conf.get('pass', 'imap')) - try : - self.ih = ImapHelper(iconf,self.rootBox) - except Exception as e: - print('Error : '+e) - print('check your connection or your imap config') + self.rootBox = self.conf.get('box','imap') self.mb = MailBuilder(self.conf.get('salt','keys')) self.fsplit = FSplitter(ConfigKey(),self.wkdir) self.delids = [] + self.ih = None + self._setIndexImap() if remIndex : self.removeIndex() self.index = self.getIndex() rt.stop() + def _setIndexImap(self): + iconf = ImapConfig(self.conf.get('host','imap'), self.conf.get('port','imap'), self.conf.get('user', 'imap'), self.conf.get('pass', 'imap')) + try : + if self.rootBox == None : + self.rootBox = '__impra__' + self.conf.set('box',self.rootBox,'imap') + if self.ih is None or self.ih.conf.user != iconf.user : + self.ih = ImapHelper(iconf,self.rootBox) + except Exception as e: + print('Error :') + print(e) + print('check your connection or your imap config') + def _getIdIndex(self): """""" mid = None @@ -624,6 +689,8 @@ class ImpraStorage: index = ImpraIndex(self.conf.get('key','keys'),self.conf.get('mark','keys'), encData, self.getIndexDefaultCatg()) defUsers = self.conf.get('users','catg') + if not ImpraIndex.SEP_KEY_INTERN+'users' in index.dic: + index.dic[ImpraIndex.SEP_KEY_INTERN+'users'] = {} for k in index.dic[ImpraIndex.SEP_KEY_INTERN+'users']: if index.dic[ImpraIndex.SEP_KEY_INTERN+'users'][k] not in [ i.strip() for i in defUsers.split(',')]: self.conf.set('users',defUsers+', '+index.dic[ImpraIndex.SEP_KEY_INTERN+'users'][k],'catg') @@ -651,7 +718,7 @@ class ImpraStorage: #~ Clz.print('\n expunge, waiting server...\n', Clz.fgB1) #~ self.srv.expunge() #~ sleep(2) - self.index.fixDuplicateIds() + self.index.fixDuplicateIds() encData = self.index.encrypt() msgIndex = self.mb.buildIndex(encData) if DEBUG and DEBUG_LEVEL <= DEBUG_NOTICE : print(msgIndex.as_string()) @@ -685,22 +752,50 @@ class ImpraStorage: lsrv = self.ih.searchBySubject(subject,True) return [ int(i) for i in set(lloc).difference(set(lsrv))] + def switchFileAccount(self,account=None): + """""" + al = self.conf.get('multi','imap') + if al is not None : + al = eval(al) + if len(al) > 0: + if not self.conf.get('user','imap') in al: + al[self.conf.get('user','imap')] = self.conf.get('pass','imap') + iconf = self.ih.conf + if iconf.user != account : + # reinit + iconf.user = None + try : + if account is None : account = self.index.getLightestAccount(al) + if account in al : + iconf.user = account + iconf.pwd = al[account] + self.ih = ImapHelper(iconf,self.rootBox) + except Exception as e: + print('Error : ') + print(e) + print('check your connection or your imap config for account '+iconf.user+' : '+iconf.password) + def addFile(self, path, label, catg=''): """""" done = False from impra.util import DEBUG, DEBUG_LEVEL, DEBUG_NOTICE, DEBUG_WARN, DEBUG_INFO rt = RuTime(eval(__CALLER__()),DEBUG_INFO) + + self.switchFileAccount() _, ext = splitext(path) try: size = getsize(path) if size > 0 : - md5 = hash_sha256(path) + md5 = hash_sha256_file(path) + account = self.ih.conf.user print() - Clz.print(' file : ' , Clz.fgn7, False) - Clz.print(path , Clz.fgN1) - Clz.print(' hash : ' , Clz.fgn7, False) - Clz.print(md5 , Clz.fgN2) + Clz.print(' account : ' , Clz.fgn7, False) + Clz.print(account , Clz.fgB7) + Clz.print(' file : ' , Clz.fgn7, False) + Clz.print(path , Clz.fgN1) + Clz.print(' hash : ' , Clz.fgn7, False) + Clz.print(md5 , Clz.fgN2) print() if not self.index.get(md5) : @@ -739,7 +834,7 @@ class ImpraStorage: Clz.print(str(mid[1]) , Clz.fgB1) else: print('\n-- error occured when sending part : %s\n-- retrying' % row[0]) - print() + if not cancel : diff = self.checkSendIds(sendIds,hlst['head'][2]) @@ -761,15 +856,17 @@ class ImpraStorage: else : print() #Clz.print(' index intall files checked\n', Clz.fgB2) + self._setIndexImap() self.index = self.getIndex(True) - self.index.add(hlst['head'][3],label,hlst['head'][1],ext,ownerHash,catg,md5,bFlag,size) + self.index.add(hlst['head'][3],label,hlst['head'][1],ext,ownerHash,catg,md5,bFlag,size,account) done = self.saveIndex() - - # clean - for mid, row in sendIds : - if cancel : self.ih.delete(mid, True) - if file_exists(self.fsplit.DIR_OUTBOX+row[1]+'.ipr') : remove(self.fsplit.DIR_OUTBOX+row[1]+'.ipr') - self.clean() + + else : + # clean + for mid, row in sendIds : + if cancel : self.ih.delete(mid, True) + if file_exists(self.fsplit.DIR_OUTBOX+row[1]+'.ipr') : remove(self.fsplit.DIR_OUTBOX+row[1]+'.ipr') + self.clean() else : print(' ',end='') @@ -787,6 +884,7 @@ class ImpraStorage: except Exception as e : print('Erroreuh') print(e) + self._setIndexImap() rt.stop() return done @@ -819,6 +917,10 @@ class ImpraStorage: print() else : rt = RuTime(eval(__CALLER__('"[%i] %s"' % (row[ImpraIndex.UID],row[ImpraIndex.LABEL]))),DEBUG_INFO) + self.switchFileAccount(row[ImpraIndex.ACCOUNT]) + account = self.ih.conf.user + Clz.print(' account : ' , Clz.fgn7, False) + Clz.print(account , Clz.fgB7) ck = ConfigKey(row[ImpraIndex.HASH]) hlst = ck.getHashList(key,row[ImpraIndex.PARTS],True) Clz.print(' get file list from server', Clz.fgn7) @@ -828,6 +930,7 @@ class ImpraStorage: Clz.print('\n expunge, waiting pls...\n', Clz.fgB1) self.ih.srv.expunge() sleep(0.5) + self._setIndexImap() self.index = self.getIndex(True) self.index.rem(key) done = self.saveIndex() @@ -848,6 +951,10 @@ class ImpraStorage: else : rt = RuTime(eval(__CALLER__('"[%i] %s"' % (row[ImpraIndex.UID],row[ImpraIndex.LABEL]))),DEBUG_INFO) + self.switchFileAccount(row[ImpraIndex.ACCOUNT]) + account = self.ih.conf.user + Clz.print(' account : ' , Clz.fgn7, False) + Clz.print(account , Clz.fgB7) ck = ConfigKey(row[ImpraIndex.HASH]) hlst = ck.getHashList(key,row[ImpraIndex.PARTS],True) ids = self.ih.searchBySubject(hlst['head'][2],True) @@ -878,7 +985,7 @@ class ImpraStorage: Clz.print(str(row[ImpraIndex.PARTS]) , Clz.BG3+Clz.fgB4, False) Clz.print(' == ' , Clz.BG3+Clz.fgB1) print() - + self._setIndexImap() rt.stop() return done diff --git a/impra/crypt.py b/impra/crypt.py index 38f5111..7e1da77 100644 --- a/impra/crypt.py +++ b/impra/crypt.py @@ -3,7 +3,7 @@ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # software : ImpraStorage # -# version : 0.7 # +# version : 0.8 # # date : 2012 # # licence : GPLv3.0 # # author : a-Sansara # @@ -49,6 +49,12 @@ def hash_sha256(data): """ return str(sha256(bytes(data,'utf-8')).hexdigest()) +def hash_sha256_file(path): + """Get a sha256 hash of str `data` + :Returns: `str` + """ + return sha256(open(path, mode='rb').read()).hexdigest() + def hash_md5_file(path): """Get a md5 hash of file from path :Returns: `str` @@ -220,6 +226,17 @@ class Kirmah: i += 1 rt.stop() return s + + def sign(self,data): + """""" + return hash_sha256(self.mark + hash_sha256(data)) + data + + def unsign(self,data): + """""" + d = data[64:] + if not data[:64] == hash_sha256(self.mark + hash_sha256(d)): + raise BadKeyException() + else: return d def encrypt(self, odata, label, cpart): """""" @@ -233,15 +250,14 @@ class Kirmah: dataEnc += self.ck.noiser.getNoise(row[2],True)+data[cp*psize:cp*psize+psize]+self.ck.noiser.getNoise(row[3],True) cp += 1 - dataEnc = str(b2a_base64(bytes(dataEnc,'utf-8')),'utf-8') - + dataEnc = self.sign(str(b2a_base64(bytes(dataEnc,'utf-8')),'utf-8')) rt.stop() return dataEnc def decrypt(self, data, label, cpart): """""" rt = RuTime(eval(__CALLER__())) - data = str(a2b_base64(bytes(data,'utf-8')),'utf-8') + data = str(a2b_base64(bytes(self.unsign(data),'utf-8')),'utf-8') dataDec = '' hlst = self.ck.getHashList(label,cpart,True) cp = ni = si = ei = rsz = 0 diff --git a/impra/imap.py b/impra/imap.py index f3c5120..6b2855c 100644 --- a/impra/imap.py +++ b/impra/imap.py @@ -3,7 +3,7 @@ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # software : ImpraStorage # -# version : 0.7 # +# version : 0.8 # # date : 2012 # # licence : GPLv3.0 # # author : a-Sansara # @@ -168,6 +168,7 @@ class ImapHelper: """""" rt = RuTime(eval(__CALLER__('conf,"'+box+'"'))) self.srv = IMAP4_SSL(conf.host,conf.port) + self.conf = conf self.srv.login(conf.user,conf.pwd) self.rootBox = box status, resp = self.srv.select(self.rootBox) diff --git a/impra/util.py b/impra/util.py index e62810f..8ab3347 100644 --- a/impra/util.py +++ b/impra/util.py @@ -3,7 +3,7 @@ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # software : ImpraStorage # -# version : 0.7 # +# version : 0.8 # # date : 2012 # # licence : GPLv3.0 # # author : a-Sansara # @@ -186,7 +186,7 @@ def __CALLER__(args=''): """ global DEBUG_LEVEL, DEBUG, DEBUG_WARN val = "self.__class__.__name__+'.%s' % stack()[1][3]+'("+quote_escape(args)+") " - if DEBUG and DEBUG_LEVEL<=DEBUG_WARN : val += "l:'+str(stack()[1][2]) " + if DEBUG and DEBUG_LEVEL<=DEBUG_WARN : val += "l:'+str(stack()[1][2])+' ' " else: val += "'" return val @@ -270,7 +270,9 @@ class IniFile: def get(self, key, section='main'): """""" - return self.dic[section][key] + v = None + if self.has(key,section) : v = self.dic[section][key] + return v def set(self, key, val, section='main'): """""" @@ -319,10 +321,9 @@ class IniFile: #~ else : content += '\n['+s[len(section)+1:]+']\n' content += '\n['+s+']\n' for k in sorted(self.dic[s]): - k = k.rstrip(' ') if s!='main' : - content += k+' = '+self.dic[s][k]+'\n' - else : main += k+' = '+self.dic[s][k]+'\n' + content += k.rstrip(' ')+' = '+str(self.dic[s][k])+'\n' + else : main += k.rstrip(' ')+' = '+str(self.dic[s][k])+'\n' return main + content def print(self,section='*', withoutSectionName=False): diff --git a/impra/w32color.py b/impra/w32color.py index 6d275d5..0d8bd80 100644 --- a/impra/w32color.py +++ b/impra/w32color.py @@ -3,7 +3,7 @@ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # software : ImpraStorage # -# version : 0.7 # +# version : 0.8 # # date : 2012 # # licence : GPLv3.0 # # author : a-Sansara # diff --git a/imprastorage.py b/imprastorage.py index 236c008..2e19638 100644 --- a/imprastorage.py +++ b/imprastorage.py @@ -3,7 +3,7 @@ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # software : ImpraStorage # -# version : 0.7 # +# version : 0.8 # # date : 2012 # # licence : GPLv3.0 # # author : a-Sansara # diff --git a/launcher.bat b/launcher.bat index 66d2e07..efead5f 100644 --- a/launcher.bat +++ b/launcher.bat @@ -1,7 +1,7 @@ :: # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # :: # :: software : ImpraStorage # -:: version : 0.7 # +:: version : 0.8 # :: date : 2012 # :: licence : GPLv3.0 # :: author : a-Sansara # diff --git a/setup_build.py b/setup_build.py index e4c211d..64d60ed 100644 --- a/setup_build.py +++ b/setup_build.py @@ -3,7 +3,7 @@ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # software : ImpraStorage # -# version : 0.7 # +# version : 0.8 # # date : 2012 # # licence : GPLv3.0 # # author : a-Sansara #