diff --git a/impra/cli.py b/impra/cli.py index 01aaf59..ad4dad2 100644 --- a/impra/cli.py +++ b/impra/cli.py @@ -35,7 +35,7 @@ import impra.crypt as crypt import impra.util as util import impra.core as core from impra.util import Clz, mprint - +from time import strftime LINE_SEP_LEN = 120 LINE_SEP_CHAR = '―' @@ -243,7 +243,7 @@ class Cli: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~ data CMD ~~ - elif not self.ini.isEmpty() and (a[0] == 'list' or a[0] == 'add' or a[0] == 'get' or a[0] == 'remove' or a[0] == 'search' or a[0] == 'edit'): + elif not self.ini.isEmpty() and (a[0] == 'list' or a[0] == 'add' or a[0] == 'get' or a[0] == 'remove' or a[0] == 'search' or a[0] == 'edit' or a[0] == 'export' or a[0] == 'import'): o.active_profile = self.ini.get('profile') @@ -268,8 +268,7 @@ class Cli: 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' + ipath = core.dirname(conf.ini.path)+core.sep+strftime('%Y%m%d%H%M%S')+'-'+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) @@ -293,7 +292,40 @@ class Cli: self.exit(1) - if a[0]=='list': + if a[0]=='export': + if not impst.irefresh: impst.getIndex(True) + encData = impst.index.encrypt() + ipath = core.dirname(conf.ini.path)+core.sep+strftime('%Y%m%d%H%M%S')+'_'+o.active_profile+'.index' + with open(ipath, mode='w', encoding='utf-8') as o: + o.write(encData) + mprint() + Clz.print(' index saved as ', Clz.fgn7) + Clz.print(' '+ipath, Clz.fgB2) + mprint() + + if a[0]=='import': + if not len(a)>1 : self.error_cmd('`'+a[0]+' need one argument',parser) + else : + vfile = a[1] + if util.file_exists(vfile) : + encData = util.get_file_content(vfile) + try : + impst.importIndex(encData) + impst.saveIndex() + mprint('\n ',end='') + Clz.print(' == OK == ', Clz.bg2+Clz.fgb7) + mprint() + except crypt.BadKeyException as e: + mprint() + Clz.print(' Error : BadKeyException', Clz.fgB1) + Clz.print(' Your profile key don\'t match the index', Clz.fgB1) + mprint() + else : + mprint() + Clz.print(' file not found', Clz.fgB1) + mprint() + + elif a[0]=='list': uid = conf.get('uid' ,'index') date = conf.get('date','index') @@ -338,7 +370,19 @@ class Cli: if not len(a)>1 : self.error_cmd('`'+a[0]+' need at least one argument',parser) else: vfile = a[1] - if util.file_exists(vfile) : + if not util.file_exists(vfile) : + if os.path.isdir(vfile): + for f in os.listdir(vfile): + if not os.path.isdir(f): + label, ext = core.splitext(core.basename(f)) + if o.category is None : o.category = '' + done = impst.addFile(vfile+core.sep+f,label,o.category) + if done : + mprint('\n ',end='') + Clz.print(' == OK == ', Clz.bg2+Clz.fgb7) + mprint() + else : self.error_cmd('`'+a[1]+' is not a file or dir',parser) + else: if not len(a)>2 : label, ext = core.splitext(core.basename(vfile)) else: label = a[2] @@ -348,8 +392,7 @@ class Cli: mprint('\n ',end='') Clz.print(' == OK == ', Clz.bg2+Clz.fgb7) mprint() - - else : self.error_cmd('`'+a[1]+' is not a file',parser) + elif a[0] == 'edit': if not len(a)>1 : self.error_cmd('`'+a[0]+' need an id',parser) @@ -592,13 +635,10 @@ class Cli: Clz.print(' USAGE :\n', Clz.fgB3) Clz.print(' imprastorage ', Clz.fgb7, False) - if Clz.isUnix: - Clz.print('--help ', Clz.fgB3) - else: - Clz.print('help ', Clz.fgB3) + Clz.print('help ', Clz.fgB3) Clz.print(' imprastorage ', Clz.fgb7, False) - Clz.print('add ', Clz.fgB3, False) + Clz.print('add '.ljust(8,' '), Clz.fgB3, False) Clz.print('{', Clz.fgB1, False) Clz.print('filePath', Clz.fgB1, False) Clz.print('} ', Clz.fgB1, False) @@ -613,7 +653,7 @@ class Cli: Clz.print(']', Clz.fgB3) Clz.print(' imprastorage ', Clz.fgb7, False) - Clz.print('edit ', Clz.fgB3, False) + Clz.print('edit '.ljust(8,' '), Clz.fgB3, False) Clz.print('{', Clz.fgB1, False) Clz.print('id', Clz.fgB1, False) Clz.print('} ', Clz.fgB1, False) @@ -629,13 +669,13 @@ class Cli: Clz.print(']', Clz.fgB3) Clz.print(' imprastorage ', Clz.fgb7, False) - Clz.print('get ', Clz.fgB3, False) + Clz.print('get '.ljust(8,' '), Clz.fgB3, False) Clz.print('{', Clz.fgB1, False) Clz.print('id|ids', Clz.fgB1, False) Clz.print('}', Clz.fgB1) Clz.print(' imprastorage ', Clz.fgb7, False) - Clz.print('list ', Clz.fgB3, False) + Clz.print('list '.ljust(8,' '), Clz.fgB3, False) Clz.print('[', Clz.fgB3, False) Clz.print(' -c ', Clz.fgB3, False) Clz.print('{', Clz.fgB1, False) @@ -654,13 +694,13 @@ class Cli: Clz.print(']', Clz.fgB3) Clz.print(' imprastorage ', Clz.fgb7, False) - Clz.print('remove ', Clz.fgB3, False) + Clz.print('remove '.ljust(8,' '), Clz.fgB3, False) Clz.print('{', Clz.fgB1, False) Clz.print('id', Clz.fgB1, False) Clz.print('}', Clz.fgB1) Clz.print(' imprastorage ', Clz.fgb7, False) - Clz.print('search ', Clz.fgB3, False) + Clz.print('search '.ljust(8,' '), Clz.fgB3, False) Clz.print('{', Clz.fgB1, False) Clz.print('pattern', Clz.fgB1, False) Clz.print('} ', Clz.fgB1, False) @@ -680,10 +720,19 @@ class Cli: Clz.print('colon', Clz.fgB1, False) Clz.print('}', Clz.fgB1, False) Clz.print(']', Clz.fgB3) + + Clz.print(' imprastorage ', Clz.fgb7, False) + Clz.print('export '.ljust(8,' '), Clz.fgB3) + + Clz.print(' imprastorage ', Clz.fgb7, False) + Clz.print('import '.ljust(8,' '), Clz.fgB3, False) + Clz.print('{', Clz.fgB1, False) + Clz.print('filePath', Clz.fgB1, False) + Clz.print('} ', Clz.fgB1) Clz.print(' imprastorage ', Clz.fgb7, False) - Clz.print('conf', Clz.fgB3, False) - Clz.print(' -L', Clz.fgB3, False) + Clz.print('conf '.ljust(8,' '), Clz.fgB3, False) + Clz.print('-L', Clz.fgB3, False) Clz.print('|', Clz.fgB1, False) Clz.print('-V', Clz.fgB3, False) Clz.print('|', Clz.fgB1, False) @@ -693,47 +742,47 @@ class Cli: Clz.print('}', Clz.fgB1) Clz.print(' imprastorage ', Clz.fgb7, False) - Clz.print('conf', Clz.fgB3, False) - Clz.print(' -S ', Clz.fgB3, False) + Clz.print('conf '.ljust(8,' '), Clz.fgB3, False) + Clz.print('-S ', Clz.fgB3, False) Clz.print('{', Clz.fgB1, False) Clz.print('profile', Clz.fgB1, False) Clz.print('} ', Clz.fgB1, False) Clz.print('[', Clz.fgB3, False) Clz.print(' -K', Clz.fgB3, False) - Clz.print(', -H ', Clz.fgB3, False) + Clz.print(' -H ', Clz.fgB3, False) Clz.print('{', Clz.fgB1, False) Clz.print('host', Clz.fgB1, False) Clz.print('}', Clz.fgB1, False) - Clz.print(', -U ', Clz.fgB3, False) + Clz.print(' -U ', Clz.fgB3, False) Clz.print('{', Clz.fgB1, False) Clz.print('user', Clz.fgB1, False) Clz.print('}', Clz.fgB1, False) - Clz.print(', -X ', Clz.fgB3, False) + Clz.print(' -X ', Clz.fgB3, False) Clz.print('{', Clz.fgB1, False) Clz.print('password', Clz.fgB1, False) Clz.print('}', Clz.fgB1, False) - Clz.print(', -P ', Clz.fgB3, False) + Clz.print(' -P ', Clz.fgB3, False) Clz.print('{', Clz.fgB1, False) Clz.print('port', Clz.fgB1, False) Clz.print('}', Clz.fgB1, False) - Clz.print(', -B ', Clz.fgB3, False) + Clz.print(' -B ', Clz.fgB3, False) Clz.print('{', Clz.fgB1, False) Clz.print('box', Clz.fgB1, False) Clz.print('}', Clz.fgB1, False) - Clz.print(', -N ', Clz.fgB3, False) + Clz.print(' -N ', Clz.fgB3, False) Clz.print('{', Clz.fgB1, False) Clz.print('name', Clz.fgB1, False) Clz.print('}', Clz.fgB1, False) - Clz.print(', \\', Clz.fgB3) + Clz.print(' \\', Clz.fgB3) - Clz.print(' '*37, Clz.fgb7, False) + Clz.print(' '*40, Clz.fgb7, False) Clz.print('-M ', Clz.fgB3, False) Clz.print('{', Clz.fgB1, False) Clz.print('user', Clz.fgB1, False) Clz.print('} {', Clz.fgB1, False) Clz.print('pass', Clz.fgB1, False) Clz.print('}', Clz.fgB1, False) - Clz.print(', -R ', Clz.fgB3, False) + Clz.print(' -R ', Clz.fgB3, False) Clz.print('{', Clz.fgB1, False) Clz.print('user', Clz.fgB1, False) Clz.print('}', Clz.fgB1, False) @@ -749,6 +798,8 @@ class Cli: Clz.print(' '*50+'don\'t print status messages to stdout' , Clz.fgB7) Clz.print(' '*4+'-d, --debug' , Clz.fgB3) Clz.print(' '*50+'set debug mode' , Clz.fgB7) + Clz.print(' '*4+' --no-color' , Clz.fgB3) + Clz.print(' '*50+'disable color mode' , Clz.fgB7) mprint('\n') Clz.print(' COMMANDS OPTIONS :\n' , Clz.fgB3) @@ -1056,7 +1107,24 @@ class Cli: Clz.print(' '*8+'imprastorage ', Clz.fgB7, False) Clz.print('search ', Clz.fgB3, False) Clz.print(CHQ+'old mountain$'+CHQ, Clz.fgB1) - + + + printLineSep(LINE_SEP_CHAR,LINE_SEP_LEN) + Clz.print('\n'+' '*4+'command export :', Clz.fgB3) + + Clz.print(' '*8+'# export the current index (as an encrypt file)',Clz.fgn7) + Clz.print(' '*8+'imprastorage ', Clz.fgB7, False) + Clz.print('export ', Clz.fgB3) + + + printLineSep(LINE_SEP_CHAR,LINE_SEP_LEN) + Clz.print('\n'+' '*4+'command import :', Clz.fgB3) + + Clz.print(' '*8+'# import an index (build by export command)',Clz.fgn7) + Clz.print(' '*8+'# carreful with this command, current index will be unrecoverable',Clz.fgn7) + Clz.print(' '*8+'imprastorage ', Clz.fgB7, False) + Clz.print('import ', Clz.fgB3, False) + Clz.print(' 20121010222244_gmail.index', Clz.fgB1) printLineSep(LINE_SEP_CHAR,LINE_SEP_LEN) Clz.print('\n'+' '*4+'command conf :', Clz.fgB3) diff --git a/impra/core.py b/impra/core.py index 2a8f1d5..7d99598 100644 --- a/impra/core.py +++ b/impra/core.py @@ -45,10 +45,10 @@ from os import remove, urandom, sep from os.path import abspath, dirname, join, realpath, basename, getsize, splitext from re import split as regsplit, match as regmatch, compile as regcompile, search as regsearch from time import time, sleep -from impra.imap import ImapHelper, ImapConfig +from impra.imap import ImapHelper, ImapConfig, BadLoginException from impra.util import __CALLER__, RuTime, formatBytes, randomFrom, bstr, quote_escape, stack, run, file_exists, get_file_content, DEBUG, mkdir_p, is_binary, clear, Clz, mprint from impra.crypt import Kirmah, ConfigKey, Noiser, Randomiz, hash_sha256, hash_md5_file, BadKeyException, hash_sha256_file - +from sys import exit as sysexit # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~ class FSplitter ~~ @@ -406,7 +406,10 @@ class ImpraIndex: 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 + if len(t)-1 < self.ACCOUNT: + t.append(account) + else: + t[self.ACCOUNT] = account self.dic[k] = tuple(t) rt.stop() @@ -627,7 +630,7 @@ class ImpraStorage: self.ih = None self._setIndexImap() if remIndex : self.removeIndex() - self.index = self.getIndex() + self.getIndex() rt.stop() def _setIndexImap(self): @@ -637,11 +640,19 @@ class ImpraStorage: 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) + try : + self.ih = ImapHelper(iconf,self.rootBox) + except BadLoginException as e1: + Clz.print('Error :', Clz.fgB1, True, False) + mprint(e1) + Clz.print('', Clz.OFF) + sysexit(1) + except Exception as e: - mprint('Error :') + Clz.print('Error :', Clz.fgB1, True, False) mprint(e) - mprint('check your connection or your imap config') + Clz.print('check your connection or your imap config', Clz.fgB1) + sysexit(1) def _getIdIndex(self): """""" @@ -698,6 +709,7 @@ class ImpraStorage: Clz.print(' get index from cache', Clz.fgn7) else: refresh = True else: refresh = True + self.irefresh = refresh if refresh : Clz.print(' refreshing index', Clz.fgn7) self._getIdIndex() @@ -706,16 +718,17 @@ class ImpraStorage: with open(self.pathInd, mode='w', encoding='utf-8') as o: o.write(encData) self.conf.set('time',str(datetime.now()),'index') - - 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') + self.importIndex(encData) rt.stop() - return index + + def importIndex(self, encData): + self.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 self.index.dic: + self.index.dic[ImpraIndex.SEP_KEY_INTERN+'users'] = {} + for k in self.index.dic[ImpraIndex.SEP_KEY_INTERN+'users']: + if self.index.dic[ImpraIndex.SEP_KEY_INTERN+'users'][k] not in [ i.strip() for i in defUsers.split(',')]: + self.conf.set('users',defUsers+', '+self.index.dic[ImpraIndex.SEP_KEY_INTERN+'users'][k],'catg') def removeIndex(self): """""" @@ -893,7 +906,7 @@ class ImpraStorage: mprint() #Clz.print(' index intall files checked\n', Clz.fgB2) self._setIndexImap() - self.index = self.getIndex(True) + self.getIndex(True) self.index.add(hlst['head'][3],label,hlst['head'][1],ext,ownerHash,catg,md5,bFlag,size,account) done = self.saveIndex() @@ -968,7 +981,7 @@ class ImpraStorage: self.ih.srv.expunge() sleep(0.5) self._setIndexImap() - self.index = self.getIndex(True) + self.getIndex(True) self.index.rem(key) done = self.saveIndex() rt.stop() @@ -994,6 +1007,7 @@ class ImpraStorage: ck = ConfigKey(row[ImpraIndex.HASH]) hlst = ck.getHashList(key,row[ImpraIndex.PARTS],True) ids = self.ih.searchBySubject(hlst['head'][2],True) + if len(ids) >= row[ImpraIndex.PARTS]: for mid in ids : diff --git a/impra/imap.py b/impra/imap.py index 658c41e..b6a583f 100644 --- a/impra/imap.py +++ b/impra/imap.py @@ -173,15 +173,18 @@ class ImapHelper: if DEBUG.level <= DEBUG.ALL : mprint(status) mprint(resp) - self.rootBox = box - if boxBin is None : - if search('yahoo.com',conf.host) is not None : - self.BOX_BIN = 'Trash' - if box != None : - status, resp = self.srv.select(self.rootBox) - if status == self.KO : - self.createBox(self.rootBox) - self.srv.select(self.rootBox) + if status == self.OK: + self.rootBox = box + if boxBin is None : + if search('yahoo.com',conf.host) is not None : + self.BOX_BIN = 'Trash' + if box != None : + status, resp = self.srv.select(self.rootBox) + if status == self.KO : + self.createBox(self.rootBox) + self.srv.select(self.rootBox) + else : + raise BadLoginException('cannot login with '+conf.user) rt.stop() def status(self,box='INBOX'): @@ -383,6 +386,13 @@ class ImapHelper: rt.stop() return mid + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# ~~ class BadLoginException ~~ + +class BadLoginException(BaseException): + pass + if __name__ == '__main__': # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ iconf = ImapConfig("imap.gmail.com", 993, 'gpslot.001', '__gpslot#22')