cli adventures
This commit is contained in:
parent
ef8cf429e5
commit
800ce9f013
226
impra/cli.py
226
impra/cli.py
|
@ -30,9 +30,11 @@
|
||||||
# ~~ package cli ~~
|
# ~~ package cli ~~
|
||||||
|
|
||||||
from optparse import OptionParser, OptionGroup
|
from optparse import OptionParser, OptionGroup
|
||||||
desc="""version : 0.41 copyright : pluie.org
|
import sys
|
||||||
author : a-Sansara license : GNU GPLv3
|
import impra.util as util
|
||||||
|
import impra.core as core
|
||||||
|
|
||||||
|
desc="""
|
||||||
ImpraStorage provided a private imap access to store large files.
|
ImpraStorage provided a private imap access to store large files.
|
||||||
Each file stored on the server is split in severals random parts.
|
Each file stored on the server is split in severals random parts.
|
||||||
Each part also contains random noise data (lenght depends on a crypt key)
|
Each part also contains random noise data (lenght depends on a crypt key)
|
||||||
|
@ -52,7 +54,7 @@ ImpraStorage randomly upload each parts then update the index.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
class _SimplerOptionParser(OptionParser):
|
class _OptionParser(OptionParser):
|
||||||
"""A simplified OptionParser"""
|
"""A simplified OptionParser"""
|
||||||
|
|
||||||
def format_description(self, formatter):
|
def format_description(self, formatter):
|
||||||
|
@ -61,7 +63,28 @@ class _SimplerOptionParser(OptionParser):
|
||||||
def format_epilog(self, formatter):
|
def format_epilog(self, formatter):
|
||||||
return self.epilog
|
return self.epilog
|
||||||
|
|
||||||
parser = _SimplerOptionParser(prog='imprastorage', usage='\n\n %prog COMMAND [OPTION]...',epilog="""
|
|
||||||
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
# ~~ class Cli ~~
|
||||||
|
|
||||||
|
class Cli:
|
||||||
|
|
||||||
|
def __init__(self,path):
|
||||||
|
|
||||||
|
self.ini = util.IniFile(path+'impra.ini')
|
||||||
|
parser = _OptionParser(prog='imprastorage', usage='\n\n\
|
||||||
|
------------------------------------------------------------------------------\n\
|
||||||
|
-- ImpraStorage --\n\
|
||||||
|
------------------------------------------------------------------------------\n\
|
||||||
|
-- version : 0.41 copyright : pluie.org --\n\
|
||||||
|
-- author : a-Sansara license : GNU GPLv3 --\n\
|
||||||
|
------------------------------------------------------------------------------\n\
|
||||||
|
\n\
|
||||||
|
%prog conf [-D|-L| -K,-H {host},-U {user},-X {password},-P {port},\n\
|
||||||
|
-B {boxname}] [-A profileName]\n\
|
||||||
|
%prog data [-l |-a {file, label} |-g {label} |-G {id} |-s {pattern} |\n\
|
||||||
|
-r {label} |-R {id}] [-c {catg}, -u {owner}, -b {boxname},\n\
|
||||||
|
-o {outputdir}]',epilog="""
|
||||||
|
|
||||||
conf command Examples:
|
conf command Examples:
|
||||||
|
|
||||||
|
@ -69,8 +92,7 @@ conf command Examples:
|
||||||
imprastorage conf -K -H imap.gmail.com -P 993 -U login -X password
|
imprastorage conf -K -H imap.gmail.com -P 993 -U login -X password
|
||||||
|
|
||||||
Set config on a new profile with same keys from previous active profile:
|
Set config on a new profile with same keys from previous active profile:
|
||||||
imprastorage conf -A profile1 -H myimapserver.net -P 993 -U login \\
|
imprastorage conf -H myimapserver.net -P 993 -U login -X password -B boxname -A profile1
|
||||||
-X password -B boxname
|
|
||||||
|
|
||||||
Load config from a profile (wich become active) :
|
Load config from a profile (wich become active) :
|
||||||
imprastorage conf -DA profile2
|
imprastorage conf -DA profile2
|
||||||
|
@ -108,49 +130,161 @@ data command Examples:
|
||||||
|
|
||||||
""",description=desc)
|
""",description=desc)
|
||||||
|
|
||||||
gpData = OptionGroup(parser, '\ndata related Options (command data)\n-----------------------------------')
|
gpData = OptionGroup(parser, '\n------------------------------------\ndata related Options (command data)')
|
||||||
gpConf = OptionGroup(parser, '\nconf related Options (command conf)\n-----------------------------------')
|
gpConf = OptionGroup(parser, '\n------------------------------------\nconf related Options (command conf)')
|
||||||
|
|
||||||
# metavar='<ARG1> <ARG2>', nargs=2
|
# metavar='<ARG1> <ARG2>', nargs=2
|
||||||
parser.add_option('-v', '--version' , help='show program\'s version number and exit' , dest='version' , action='store_true' , default=False)
|
parser.add_option('-v', '--version' , help='show program\'s version number and exit' , action='store_true' , default=False)
|
||||||
parser.add_option('-q', '--quiet' , help='don\'t print status messages to stdout' , dest='verbose' , action='store_false', default=True)
|
parser.add_option('-q', '--quiet' , help='don\'t print status messages to stdout' , action='store_false', default=True)
|
||||||
parser.add_option('-f', '--force' , help='dont confirm and force action' , dest='force' , action='store_true' , default=False)
|
parser.add_option('-f', '--force' , help='dont confirm and force action' , action='store_true' , default=False)
|
||||||
parser.add_option('-d', '--debug' , help='set debug mode' , dest='debug' , action='store_true' , default=False)
|
parser.add_option('-d', '--debug' , help='set debug mode' , action='store_true' , default=False)
|
||||||
|
|
||||||
gpData.add_option('-l', '--list' , help='list index on imap server' , dest='list_index' , action='store_true' , default=False)
|
gpData.add_option('-l', '--list' , help='list index on imap server' , action='store_true' )
|
||||||
gpData.add_option('-b', '--boxname' , help='switch boxname on imap server' , dest='switch_boxname' , action='store', metavar='BOXN')
|
gpData.add_option('-a', '--add' , help='add file FILE with specified LABEL on server' , action='store', metavar='FILE LABEL ', nargs=2)
|
||||||
gpData.add_option('-a', '--add' , help='add file FILE with specified LABEL on server' , dest='add' , action='store', metavar='FILE LABEL', nargs=2)
|
gpData.add_option('-g', '--get' , help='get file with specified LABEL from server' , action='store', metavar='LABEL ')
|
||||||
gpData.add_option('-g', '--get' , help='get file with specified LABEL from server' , dest='get' , action='store', metavar='LABEL')
|
gpData.add_option('-G', '--get-by-id' , help='get file with specified ID from server' , action='store', metavar='ID ')
|
||||||
gpData.add_option('-G', '--get-by-id' , help='get file with specified ID from server' , dest='get_by_id' , action='store', metavar='ID')
|
gpData.add_option('-s', '--search' , help='search file with specified PATTERN' , action='store', metavar='PATTERN ')
|
||||||
gpData.add_option('-s', '--search' , help='search file with specified PATTERN' , dest='search' , action='store', metavar='PATTERN')
|
gpData.add_option('-r', '--remove' , help='remove FILE with specified LABEL from server' , action='store', metavar='LABEL ')
|
||||||
gpData.add_option('-c', '--category' , help='set specified CATEGORY (crit. for opt. -l,-a or -s)' , dest='category' , action='store', metavar='CATG' , default='none')
|
gpData.add_option('-R', '--remove-by-id' , help='remove FILE with specified ID from server' , action='store', metavar='ID ')
|
||||||
gpData.add_option('-u', '--user' , help='set specified USER (crit. for opt. -l,-a or -s)' , dest='owner' , action='store', metavar='OWNER' , default='all')
|
gpData.add_option('-b', '--boxname' , help='switch boxname on imap server' , action='store', metavar='BOXN ')
|
||||||
gpData.add_option('-o', '--output-dir' , help='set specified OUTPUT DIR (for opt. -l,-a,-d or -g)' , dest='output' , action='store', metavar='DIR')
|
gpData.add_option('-c', '--category' , help='set specified CATEGORY (crit. for opt. -l,-a or -s)' , action='store', metavar='CATG ' , default='none')
|
||||||
gpData.add_option('-r', '--remove' , help='remove FILE with specified LABEL from server' , dest='remove' , action='store', metavar='LABEL')
|
gpData.add_option('-u', '--user' , help='set specified USER (crit. for opt. -l,-a or -s)' , action='store', metavar='OWNER ' , default='all')
|
||||||
gpData.add_option('-R', '--remove-by-id' , help='remove FILE with specified ID from server' , dest='remove_by_id' , action='store', metavar='ID')
|
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)
|
parser.add_option_group(gpData)
|
||||||
|
|
||||||
gpConf.add_option('-L', '--list-conf' , help='list configuration' , dest='list_conf' , action='store')
|
gpConf.add_option('-L', '--list-conf' , help='list configuration' , action='store_true', default=False)
|
||||||
gpConf.add_option('-A', '--active-profile', help='set active profile' , dest='profile' , action='store', metavar='PROFILE', default='default')
|
gpConf.add_option('-D', '--load-conf' , help='load configuration' , action='store_true', default=False)
|
||||||
gpConf.add_option('-H', '--set-host' , help='set imap host server' , dest='host' , action='store', metavar='HOST')
|
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' , dest='user' , action='store', metavar='USER')
|
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' , dest='password' , action='store', metavar='PASS')
|
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 (default:[%default])' , dest='port' , action='store', metavar='PORT' , default=993)
|
gpConf.add_option('-P', '--set-port' , help='set imap port' , action='store', metavar='PORT ')
|
||||||
gpConf.add_option('-B', '--set-boxname' , help='set boxName on imap server (default:[%default])' , dest='boxname' , action='store', metavar='BOXN' , default='__IMPRA')
|
gpConf.add_option('-N', '--set-name' , help='set user name' , action='store', metavar='NAME ')
|
||||||
gpConf.add_option('-K', '--gen-keys' , help='generate new pub/private keys' , dest='generate_keys' , action='store_true', default=False)
|
gpConf.add_option('-B', '--set-boxn' , help='set boxName on imap server (default:[%default])' , action='store', metavar='BOXNAME ')
|
||||||
gpConf.add_option('-D', '--load-conf' , help='load configuration' , dest='load_conf' , action='store_true', default=False)
|
gpConf.add_option('-K', '--gen-keys' , help='generate new pub/private keys' , action='store_true', default=False)
|
||||||
parser.add_option_group(gpConf)
|
gpConf.add_option('-A', '--active-profile', help='set active profile' , action='store', metavar='PROFILE ')
|
||||||
|
|
||||||
def show_index():
|
parser.add_option_group(gpConf)
|
||||||
print('show_index')
|
|
||||||
|
|
||||||
(opts, args) = parser.parse_args()
|
(o, a) = parser.parse_args()
|
||||||
#~ if not 'toto' in opts.__dict__ :
|
|
||||||
#~ print("mandatory option is missing\n")
|
|
||||||
#~ parser.print_help()
|
|
||||||
#~ exit(-1)*/
|
|
||||||
#~ print('--------')
|
|
||||||
#~ print(opts)
|
|
||||||
#~ print('--------')
|
|
||||||
#~ print(args)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if not a:
|
||||||
|
parser.print_help()
|
||||||
|
print()
|
||||||
|
parser.error(' no commando specified')
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
# ~~ conf CMD ~~
|
||||||
|
if a[0] == 'conf' :
|
||||||
|
|
||||||
|
if o.active_profile==None:
|
||||||
|
if self.ini.has('profile') : o.active_profile = self.ini.get('profile')
|
||||||
|
else : o.active_profile = 'default'
|
||||||
|
|
||||||
|
if o.load_conf : self.load_profile(o)
|
||||||
|
|
||||||
|
elif o.list_conf : print(self.ini.toString(o.active_profile))
|
||||||
|
|
||||||
|
else :
|
||||||
|
if not o.set_host and not o.set_user and not o.set_pass and not o.set_port and not o.set_boxn and not o.set_name and not o.gen_keys:
|
||||||
|
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')
|
||||||
|
sys.exit(1)
|
||||||
|
if o.set_boxn: ini.set('box' , o.set_boxn,o.active_profile+'.imap')
|
||||||
|
if o.set_host: ini.set('host', o.set_host,o.active_profile+'.imap')
|
||||||
|
if o.set_user: ini.set('user', o.set_user,o.active_profile+'.imap')
|
||||||
|
if o.set_pass: ini.set('pass', o.set_pass,o.active_profile+'.imap')
|
||||||
|
if o.set_port: ini.set('port', o.set_port,o.active_profile+'.imap')
|
||||||
|
if o.set_name: ini.set('name', o.set_name,o.active_profile+'.infos')
|
||||||
|
if o.gen_keys:
|
||||||
|
rsa = util.Rsa(None,None,path,True)
|
||||||
|
self.ini.set('prvKey',rsa.prvKey,o.active_profile+'.keys')
|
||||||
|
self.ini.set('pubKey',rsa.pubKey,o.active_profile+'.keys')
|
||||||
|
self.ini.set('salt' ,'-¤-ImpraStorage-¤-',o.active_profile+'.keys')
|
||||||
|
if self.check_profile(o.active_profile):
|
||||||
|
self.ini.set('profile', o.active_profile)
|
||||||
|
self.ini.write()
|
||||||
|
print(self.ini.toString(o.active_profile))
|
||||||
|
|
||||||
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
# ~~ data CMD ~~
|
||||||
|
elif a[0] == 'data' :
|
||||||
|
|
||||||
|
o.active_profile = self.ini.get('profile')
|
||||||
|
|
||||||
|
if not o.list and not o.add and not o.get and not o.get_by_id and not o.search and not o.remove and not o.remove_by_id :
|
||||||
|
parser.error(' no options specified')
|
||||||
|
else :
|
||||||
|
|
||||||
|
if self.check_profile(o.active_profile):
|
||||||
|
conf = core.ImpraConf(self.ini,o.active_profile)
|
||||||
|
rsa = util.Rsa(conf.get('prvKey','keys'),conf.get('pubKey','keys'))
|
||||||
|
impst = None
|
||||||
|
try:
|
||||||
|
impst = core.ImpraStorage(rsa, conf)
|
||||||
|
except util.BadKeysException as e :
|
||||||
|
print('Error : ')
|
||||||
|
print(e)
|
||||||
|
print("""
|
||||||
|
it seems that your current profile %s has bad keys to decrypt index on server.
|
||||||
|
you can remove index but all presents files on the box %s will be unrecoverable
|
||||||
|
""" % (o.active_profile, conf.get('box','imap')))
|
||||||
|
remIndex = input('remove index ? (yes/no)')
|
||||||
|
if remIndex.lower()=='yes':
|
||||||
|
impst = core.ImpraStorage(rsa, conf, True)
|
||||||
|
else :
|
||||||
|
print('bye')
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if o.list :
|
||||||
|
impst.index.print(True,'-'*120+'\n -- INDEX '+impst.rootBox+'\n'+'-'*120)
|
||||||
|
elif o.add :
|
||||||
|
impst.addFile(o.add[0],o.add[1],o.user,o.category)
|
||||||
|
elif o.get :
|
||||||
|
print(o.get)
|
||||||
|
elif o.get_by_id :
|
||||||
|
print(o.get_by_id)
|
||||||
|
elif o.search :
|
||||||
|
print(o.search)
|
||||||
|
elif o.remove :
|
||||||
|
print(o.remove)
|
||||||
|
elif o.remove_by_id :
|
||||||
|
print(o.remove_by_id)
|
||||||
|
|
||||||
|
#~ filePath = '/media/Data/dev/big_toph3.jpg'
|
||||||
|
#~ lab = 'Meuf\'bonne aussi4'
|
||||||
|
#~ print('\n -- ADD FILE -- ')
|
||||||
|
#~ impst.addFile(filePath,lab,conf.get('name','infos'),'images')
|
||||||
|
|
||||||
|
#~ else :
|
||||||
|
#~ self.load_profile(o)
|
||||||
|
#~ print('data cmd')
|
||||||
|
#~ print(o)
|
||||||
|
|
||||||
|
else : parser.print_help()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def check_profile(self,profile):
|
||||||
|
""""""
|
||||||
|
return 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')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def load_profile(self,o):
|
||||||
|
""""""
|
||||||
|
if self.check_profile(o.active_profile):
|
||||||
|
print('profile '+o.active_profile+' loaded')
|
||||||
|
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 ?)')
|
||||||
|
|
|
@ -29,7 +29,6 @@
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
# ~~ package core ~~
|
# ~~ package core ~~
|
||||||
|
|
||||||
import inspect
|
|
||||||
from base64 import urlsafe_b64encode
|
from base64 import urlsafe_b64encode
|
||||||
from email.encoders import encode_base64
|
from email.encoders import encode_base64
|
||||||
from email.header import Header
|
from email.header import Header
|
||||||
|
@ -43,8 +42,9 @@ from os import remove, urandom, sep
|
||||||
from os.path import abspath, dirname, join, realpath, basename, getsize, splitext
|
from os.path import abspath, dirname, join, realpath, basename, getsize, splitext
|
||||||
from re import split as regsplit
|
from re import split as regsplit
|
||||||
from impra.imap import ImapHelper, ImapConfig
|
from impra.imap import ImapHelper, ImapConfig
|
||||||
from impra.util import __CALLER__, Rsa, RuTime, Noiser, Randomiz, RuTime, hash_sha256, formatBytes, randomFrom, bstr, quote_escape, stack
|
from impra.util import __CALLER__, Rsa, RuTime, Noiser, Randomiz, RuTime, hash_sha256, formatBytes, randomFrom, bstr, quote_escape, stack, run
|
||||||
|
|
||||||
|
DEBUG = True
|
||||||
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
# ~~ class ConfigKey ~~
|
# ~~ class ConfigKey ~~
|
||||||
|
@ -63,7 +63,6 @@ class ConfigKey:
|
||||||
|
|
||||||
def getHashList(self,name,count,noSorted=False):
|
def getHashList(self,name,count,noSorted=False):
|
||||||
""""""
|
""""""
|
||||||
rt = RuTime('getHashList')
|
|
||||||
rt = RuTime(eval(__CALLER__('"%s",%s,%i' % (name,count,noSorted))))
|
rt = RuTime(eval(__CALLER__('"%s",%s,%i' % (name,count,noSorted))))
|
||||||
self.rdmz.new(count)
|
self.rdmz.new(count)
|
||||||
dic, lst, hroot = {}, [], hash_sha256(self.salt+name)
|
dic, lst, hroot = {}, [], hash_sha256(self.salt+name)
|
||||||
|
@ -185,21 +184,23 @@ class ImpraConf:
|
||||||
if self.ini.isEmpty():
|
if self.ini.isEmpty():
|
||||||
save = True
|
save = True
|
||||||
rsa = Rsa()
|
rsa = Rsa()
|
||||||
self.set('host','imap.gmail.com','imap')
|
self.set('host','host','imap')
|
||||||
self.set('port','993','imap')
|
self.set('port','993','imap')
|
||||||
self.set('user','login','imap')
|
self.set('user','login','imap')
|
||||||
self.set('pass','**********','imap')
|
self.set('pass','password','imap')
|
||||||
self.set('box' ,'__SMILF','imap')
|
self.set('box' ,'__IMPRA','imap')
|
||||||
self.set('pubKey',rsa.pubKey,'keys')
|
self.set('pubKey',rsa.pubKey,'keys')
|
||||||
self.set('prvKey',rsa.prvKey,'keys')
|
self.set('prvKey',rsa.prvKey,'keys')
|
||||||
self.set('salt' ,'-¤-ImpraStorage-¤-','keys')
|
self.set('salt' ,'-¤-ImpraStorage-¤-','keys')
|
||||||
if not self.ini.hasSection(self.profile+self.SEP_SECTION+'catg'):
|
if not self.ini.hasSection(self.profile+self.SEP_SECTION+'catg'):
|
||||||
save = True
|
save = True
|
||||||
|
try:
|
||||||
self.set('users', self.get('name','infos'),'catg')
|
self.set('users', self.get('name','infos'),'catg')
|
||||||
|
except Exception : pass
|
||||||
self.set('types', 'music,films,doc,images,archives,games','catg')
|
self.set('types', 'music,films,doc,images,archives,games','catg')
|
||||||
if save :
|
if save :
|
||||||
self.ini.write()
|
self.ini.write()
|
||||||
print(self.ini.toString())
|
#print(self.ini.toString())
|
||||||
|
|
||||||
def get(self, key, section='main', profile=None):
|
def get(self, key, section='main', profile=None):
|
||||||
""""""
|
""""""
|
||||||
|
@ -227,7 +228,7 @@ class ImpraIndex:
|
||||||
SEP_CATEGORY = '¤'
|
SEP_CATEGORY = '¤'
|
||||||
"""Separator used for category section"""
|
"""Separator used for category section"""
|
||||||
|
|
||||||
QUOTE_REPL = '-§'
|
QUOTE_REPL = '§'
|
||||||
"""Char replacement of simple quote String"""
|
"""Char replacement of simple quote String"""
|
||||||
|
|
||||||
SEP_KEY_INTERN = '@'
|
SEP_KEY_INTERN = '@'
|
||||||
|
@ -246,6 +247,7 @@ class ImpraIndex:
|
||||||
"""
|
"""
|
||||||
self.rsa = rsa
|
self.rsa = rsa
|
||||||
self.dic = {}
|
self.dic = {}
|
||||||
|
self.id = 0
|
||||||
if encdata =='' : data = encdata
|
if encdata =='' : data = encdata
|
||||||
else : data = self.rsa.decrypt(encdata)
|
else : data = self.rsa.decrypt(encdata)
|
||||||
data = data.replace(self.QUOTE_REPL, '\'')
|
data = data.replace(self.QUOTE_REPL, '\'')
|
||||||
|
@ -254,7 +256,10 @@ class ImpraIndex:
|
||||||
for row in l:
|
for row in l:
|
||||||
d = regsplit(self.SEP_TOKEN,row)
|
d = regsplit(self.SEP_TOKEN,row)
|
||||||
# key : count, hash, ext, usr, cat
|
# key : count, hash, ext, usr, cat
|
||||||
if len(d)>4 and d!='': self.dic[d[1]] = d
|
if len(d)>4 and d!='':
|
||||||
|
d.append(self.id)
|
||||||
|
self.dic[d[1]] = d
|
||||||
|
self.id += 1
|
||||||
if len(ld)>1:
|
if len(ld)>1:
|
||||||
l = regsplit(self.SEP_ITEM,ld[1].lstrip('\n'))
|
l = regsplit(self.SEP_ITEM,ld[1].lstrip('\n'))
|
||||||
for row in l:
|
for row in l:
|
||||||
|
@ -270,7 +275,8 @@ class ImpraIndex:
|
||||||
to decode data, and parts count
|
to decode data, and parts count
|
||||||
"""
|
"""
|
||||||
if self.search(label) == None :
|
if self.search(label) == None :
|
||||||
self.dic[label] = (key,label,count,ext,usr,cat)
|
self.dic[label] = (key,label,count,ext,usr,cat, self.id)
|
||||||
|
self.id +=1
|
||||||
else :
|
else :
|
||||||
print(label+' already exist')
|
print(label+' already exist')
|
||||||
|
|
||||||
|
@ -282,7 +288,7 @@ class ImpraIndex:
|
||||||
"""Search the corresponding label in the index"""
|
"""Search the corresponding label in the index"""
|
||||||
return self.dic.get(label)
|
return self.dic.get(label)
|
||||||
|
|
||||||
def toString(self):
|
def toString(self, withoutCatg=False):
|
||||||
"""Make a string representation of the index as it was store on the server"""
|
"""Make a string representation of the index as it was store on the server"""
|
||||||
data = cdata = ''
|
data = cdata = ''
|
||||||
for k in sorted(self.dic):
|
for k in sorted(self.dic):
|
||||||
|
@ -292,17 +298,24 @@ class ImpraIndex:
|
||||||
else :
|
else :
|
||||||
for i in v: data += str(i)+self.SEP_TOKEN
|
for i in v: data += str(i)+self.SEP_TOKEN
|
||||||
data = data.rstrip(self.SEP_TOKEN)+self.SEP_ITEM
|
data = data.rstrip(self.SEP_TOKEN)+self.SEP_ITEM
|
||||||
return data+self.SEP_CATEGORY+'\n'+cdata;
|
if not withoutCatg :
|
||||||
|
data += self.SEP_CATEGORY+'\n'+cdata
|
||||||
|
return data;
|
||||||
|
|
||||||
def encrypt(self):
|
def encrypt(self):
|
||||||
""""""
|
""""""
|
||||||
return self.rsa.encrypt(self.toString().replace('\'', self.QUOTE_REPL))
|
return self.rsa.encrypt(self.toString().replace('\'', self.QUOTE_REPL))
|
||||||
|
|
||||||
def print(self):
|
def print(self,withoutCatg=False, header=''):
|
||||||
"""Print index content as formated bloc"""
|
"""Print index content as formated bloc"""
|
||||||
data = self.toString().split(';')
|
data = self.toString(withoutCatg).split(';')
|
||||||
|
i = 0
|
||||||
|
print(header)
|
||||||
for row in data:
|
for row in data:
|
||||||
if row.rstrip('\n') != '': print(row)
|
if row.rstrip('\n') != '':
|
||||||
|
print(str(i).rjust(1+ceil(len(data)/10),' ')+' - '+row)
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
@ -311,7 +324,7 @@ class ImpraIndex:
|
||||||
class ImpraStorage:
|
class ImpraStorage:
|
||||||
""""""
|
""""""
|
||||||
|
|
||||||
def __init__(self, rsa, conf, wkdir=None):
|
def __init__(self, rsa, conf, remIndex=False, wkdir=None):
|
||||||
""""""
|
""""""
|
||||||
if wkdir == None : wkdir = abspath(join(dirname( __file__ ), '..', 'wk'))
|
if wkdir == None : wkdir = abspath(join(dirname( __file__ ), '..', 'wk'))
|
||||||
self.wkdir = wkdir
|
self.wkdir = wkdir
|
||||||
|
@ -323,6 +336,7 @@ class ImpraStorage:
|
||||||
self.rsa = rsa
|
self.rsa = rsa
|
||||||
self.fsplit = FSplitter(ConfigKey(),self.wkdir)
|
self.fsplit = FSplitter(ConfigKey(),self.wkdir)
|
||||||
self.delids = []
|
self.delids = []
|
||||||
|
if remIndex : self.removeIndex()
|
||||||
self.index = self.getIndex()
|
self.index = self.getIndex()
|
||||||
|
|
||||||
def _getIdIndex(self):
|
def _getIdIndex(self):
|
||||||
|
@ -345,6 +359,7 @@ class ImpraStorage:
|
||||||
|
|
||||||
def getIndex(self):
|
def getIndex(self):
|
||||||
""""""
|
""""""
|
||||||
|
index = None
|
||||||
self._getIdIndex()
|
self._getIdIndex()
|
||||||
if self.idx :
|
if self.idx :
|
||||||
msgIndex = self.ih.email(self.idx)
|
msgIndex = self.ih.email(self.idx)
|
||||||
|
@ -355,22 +370,31 @@ class ImpraStorage:
|
||||||
else :
|
else :
|
||||||
encData = ''
|
encData = ''
|
||||||
self.ih.deleteBin()
|
self.ih.deleteBin()
|
||||||
return ImpraIndex(self.rsa,encData, {'catg':self.conf.get('types','catg')})
|
index = ImpraIndex(self.rsa, encData, {'catg':self.conf.get('types','catg')})
|
||||||
|
return index
|
||||||
|
|
||||||
|
def removeIndex(self):
|
||||||
|
""""""
|
||||||
|
self._getIdIndex()
|
||||||
|
if self.idx :
|
||||||
|
self.ih.delete(self.idx)
|
||||||
|
|
||||||
def saveIndex(self):
|
def saveIndex(self):
|
||||||
""""""
|
""""""
|
||||||
|
global DEBUG
|
||||||
rt = RuTime(eval(__CALLER__()))
|
rt = RuTime(eval(__CALLER__()))
|
||||||
if self.idx != None :
|
if self.idx != None :
|
||||||
self.ih.delete(self.idx)
|
self.ih.delete(self.idx)
|
||||||
encData = self.index.encrypt()
|
encData = self.index.encrypt()
|
||||||
msgIndex = self.mb.buildIndex(encData)
|
msgIndex = self.mb.buildIndex(encData)
|
||||||
print(msgIndex.as_string())
|
if DEBUG: print(msgIndex.as_string())
|
||||||
self.ih.send(msgIndex.as_string(), self.rootBox)
|
self.ih.send(msgIndex.as_string(), self.rootBox)
|
||||||
#self.index = self.getIndex()
|
#self.index = self.getIndex()
|
||||||
rt.stop()
|
rt.stop()
|
||||||
|
|
||||||
def addFile(self, path, label, usr='all', catg=''):
|
def addFile(self, path, label, usr='all', catg=''):
|
||||||
""""""
|
""""""
|
||||||
|
global DEBUG
|
||||||
rt = RuTime(eval(__CALLER__('"%s","%s","%s"' % (path[:13]+'...',label,usr))))
|
rt = RuTime(eval(__CALLER__('"%s","%s","%s"' % (path[:13]+'...',label,usr))))
|
||||||
|
|
||||||
#~ hlst = self.fsplit.addFile(path,label)
|
#~ hlst = self.fsplit.addFile(path,label)
|
||||||
|
@ -379,6 +403,7 @@ class ImpraStorage:
|
||||||
try:
|
try:
|
||||||
if self.index.search(label)==None :
|
if self.index.search(label)==None :
|
||||||
hlst = self.fsplit.addFile(path,label)
|
hlst = self.fsplit.addFile(path,label)
|
||||||
|
if DEBUG :
|
||||||
print(hlst['head'])
|
print(hlst['head'])
|
||||||
for v in hlst['data']:
|
for v in hlst['data']:
|
||||||
print(v)
|
print(v)
|
||||||
|
@ -397,6 +422,7 @@ class ImpraStorage:
|
||||||
|
|
||||||
def getFile(self,label):
|
def getFile(self,label):
|
||||||
""""""
|
""""""
|
||||||
|
global DEBUG
|
||||||
rt = RuTime(eval(__CALLER__('"%s"' % label)))
|
rt = RuTime(eval(__CALLER__('"%s"' % label)))
|
||||||
key = self.index.search(label)
|
key = self.index.search(label)
|
||||||
if key!=None :
|
if key!=None :
|
||||||
|
@ -410,6 +436,7 @@ class ImpraStorage:
|
||||||
if to == self.mb.getHashName('all')+'@'+self.mb.DOMAIN_NAME or to == self.mb.getHashName(self.conf.ini.get('name',self.conf.profile+'.infos'))+'@'+self.mb.DOMAIN_NAME :
|
if to == self.mb.getHashName('all')+'@'+self.mb.DOMAIN_NAME or to == self.mb.getHashName(self.conf.ini.get('name',self.conf.profile+'.infos'))+'@'+self.mb.DOMAIN_NAME :
|
||||||
for mid in ids :
|
for mid in ids :
|
||||||
self.ih.downloadAttachment(mid,self.fsplit.DIR_INBOX)
|
self.ih.downloadAttachment(mid,self.fsplit.DIR_INBOX)
|
||||||
|
if DEBUG :
|
||||||
print(hlst['head'])
|
print(hlst['head'])
|
||||||
for v in hlst['data']:
|
for v in hlst['data']:
|
||||||
print(v)
|
print(v)
|
||||||
|
|
|
@ -29,7 +29,6 @@
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
# ~~ package imap ~~
|
# ~~ package imap ~~
|
||||||
|
|
||||||
import inspect
|
|
||||||
from email import message_from_bytes
|
from email import message_from_bytes
|
||||||
from email.header import decode_header
|
from email.header import decode_header
|
||||||
from email.message import Message
|
from email.message import Message
|
||||||
|
|
|
@ -32,16 +32,27 @@
|
||||||
from hashlib import sha256
|
from hashlib import sha256
|
||||||
from math import log, floor, ceil
|
from math import log, floor, ceil
|
||||||
from random import choice
|
from random import choice
|
||||||
from os import urandom, popen
|
from os import urandom, popen, sep
|
||||||
from os.path import dirname, realpath
|
from os.path import dirname, realpath, abspath
|
||||||
from time import time
|
from time import time
|
||||||
from re import split as regsplit
|
from re import split as regsplit
|
||||||
from base64 import urlsafe_b64encode
|
from base64 import urlsafe_b64encode
|
||||||
from inspect import stack
|
from inspect import stack
|
||||||
|
from subprocess import PIPE, Popen
|
||||||
|
from sys import stderr
|
||||||
|
|
||||||
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
# ~~ methods ~~
|
# ~~ methods ~~
|
||||||
|
|
||||||
|
def represents_int(s):
|
||||||
|
""""""
|
||||||
|
try:
|
||||||
|
int(s)
|
||||||
|
return True
|
||||||
|
except ValueError:
|
||||||
|
return False
|
||||||
|
|
||||||
def quote_escape(data):
|
def quote_escape(data):
|
||||||
"""Escape simple quote
|
"""Escape simple quote
|
||||||
:Returns: `str`
|
:Returns: `str`
|
||||||
|
@ -70,6 +81,10 @@ def randomFrom(val, sval=0):
|
||||||
lst = list(range(sval,val))
|
lst = list(range(sval,val))
|
||||||
return choice(lst)
|
return choice(lst)
|
||||||
|
|
||||||
|
def get_file_path(val):
|
||||||
|
""""""
|
||||||
|
return abspath(dirname(val))+sep
|
||||||
|
|
||||||
def formatBytes(b, p=2):
|
def formatBytes(b, p=2):
|
||||||
"""Give a human representation of bytes size `b`
|
"""Give a human representation of bytes size `b`
|
||||||
:Returns: `str`
|
:Returns: `str`
|
||||||
|
@ -89,6 +104,19 @@ def bstr(b,enc='utf-8'):
|
||||||
""""""
|
""""""
|
||||||
return str(b, encoding=enc)
|
return str(b, encoding=enc)
|
||||||
|
|
||||||
|
def run(cmdline):
|
||||||
|
""""""
|
||||||
|
try:
|
||||||
|
p = Popen(cmdline, shell=True,stdout=PIPE, stderr=PIPE)
|
||||||
|
cmdout, cmderr = p.communicate()
|
||||||
|
rcode = p.wait()
|
||||||
|
if rcode < 0:
|
||||||
|
print((stderr,"Child was terminated by signal",rcode))
|
||||||
|
else:
|
||||||
|
return (rcode,cmdout,cmderr)
|
||||||
|
except OSError as e :
|
||||||
|
return (e,cmdout,cmderr)
|
||||||
|
|
||||||
def __CALLER__(args=''):
|
def __CALLER__(args=''):
|
||||||
"""Give basic information of caller method
|
"""Give basic information of caller method
|
||||||
usage ::
|
usage ::
|
||||||
|
@ -174,13 +202,15 @@ class RuTime:
|
||||||
self._start()
|
self._start()
|
||||||
|
|
||||||
def _start(self):
|
def _start(self):
|
||||||
print(' ==> '+self.label)
|
from impra.core import DEBUG
|
||||||
|
if DEBUG :print(' ==> '+self.label)
|
||||||
self.sc = time()
|
self.sc = time()
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
"""Stop duration and print basics stats duration on console"""
|
"""Stop duration and print basics stats duration on console"""
|
||||||
|
from impra.core import DEBUG
|
||||||
self.ec = time()
|
self.ec = time()
|
||||||
self._stats()
|
if DEBUG:self._stats()
|
||||||
|
|
||||||
def _stats(self):
|
def _stats(self):
|
||||||
print(' <== '+self.label+(' [%.9f s]' % (self.ec - self.sc))+' <¤¤ ')
|
print(' <== '+self.label+(' [%.9f s]' % (self.ec - self.sc))+' <¤¤ ')
|
||||||
|
@ -204,7 +234,7 @@ class IniFile:
|
||||||
|
|
||||||
def has(self, key, section='main'):
|
def has(self, key, section='main'):
|
||||||
""""""
|
""""""
|
||||||
d = (key in self.dic[section])
|
d = self.hasSection(section) and (key in self.dic[section])
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def hasSection(self, section):
|
def hasSection(self, section):
|
||||||
|
@ -243,17 +273,19 @@ class IniFile:
|
||||||
with open(path, mode='w', encoding='utf-8') as o:
|
with open(path, mode='w', encoding='utf-8') as o:
|
||||||
o.write(content)
|
o.write(content)
|
||||||
|
|
||||||
def toString(self,path=None):
|
def toString(self,section='*'):
|
||||||
""""""
|
""""""
|
||||||
if path == None : path = self.path
|
|
||||||
content = ''
|
content = ''
|
||||||
main = ''
|
main = ''
|
||||||
for s in self.dic:
|
for s in self.dic:
|
||||||
|
if section=='*' or section+'.'==s[:len(section)+1]:
|
||||||
if s!='main':
|
if s!='main':
|
||||||
|
#~ if section=='*': content += '\n['+s+']\n'
|
||||||
|
#~ else : content += '\n['+s[len(section)+1:]+']\n'
|
||||||
content += '\n['+s+']\n'
|
content += '\n['+s+']\n'
|
||||||
for k in sorted(self.dic[s]):
|
for k in sorted(self.dic[s]):
|
||||||
k = k.rstrip(' ')
|
k = k.rstrip(' ')
|
||||||
if s!='main':
|
if s!='main' :
|
||||||
content += k+' = '+self.dic[s][k]+'\n'
|
content += k+' = '+self.dic[s][k]+'\n'
|
||||||
else : main += k+' = '+self.dic[s][k]+'\n'
|
else : main += k+' = '+self.dic[s][k]+'\n'
|
||||||
return main + content
|
return main + content
|
||||||
|
@ -275,33 +307,43 @@ class IniFile:
|
||||||
except IOError : pass
|
except IOError : pass
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
# ~~ class ImpraStorage ~~
|
||||||
|
|
||||||
|
class BadKeysException(BaseException):
|
||||||
|
pass
|
||||||
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
# ~~ class Rsa ~~
|
# ~~ class Rsa ~~
|
||||||
|
|
||||||
class Rsa:
|
class Rsa:
|
||||||
""""""
|
""""""
|
||||||
|
|
||||||
def __init__(self, prvKey=None, pubKey=None, dpath='./'):
|
def __init__(self, prvKey=None, pubKey=None, dpath='./', forceKeyGen=False):
|
||||||
""""""
|
""""""
|
||||||
self.cpath = dirname(realpath(__file__))+'/../desurveil/scripts/'
|
self.cpath = dirname(realpath(__file__))+'/../desurveil/scripts/'
|
||||||
self.prvKey = prvKey
|
self.prvKey = prvKey
|
||||||
self.pubKey = pubKey
|
self.pubKey = pubKey
|
||||||
self.dpath = dpath
|
self.dpath = dpath
|
||||||
if prvKey == None or pubKey==None : self.key()
|
if prvKey == None or pubKey==None : self.key(forceKeyGen)
|
||||||
|
|
||||||
def key(self):
|
def key(self,force=False):
|
||||||
""""""
|
""""""
|
||||||
cmd = self.cpath+"desurveil key -a "+self.dpath+".impra_id_rsa -l "+self.dpath+".impra_id_rsa.pub"
|
cmd = self.cpath+"desurveil key -a "+self.dpath+".impra_id_rsa -l "+self.dpath+".impra_id_rsa.pub"
|
||||||
#print(cmd)
|
#print(cmd)
|
||||||
|
|
||||||
try :
|
try :
|
||||||
with open(self.dpath+'.impra_id_rsa','rt') as f: pass
|
with open(self.dpath+'.impra_id_rsa','rt') as f: pass
|
||||||
|
if force:d = popen(cmd).read()
|
||||||
except IOError as e:
|
except IOError as e:
|
||||||
d = popen(cmd).read()
|
d = popen(cmd).read()
|
||||||
#print(d)
|
#print(d)
|
||||||
self.prvKey = get_file_content(self.dpath+'.impra_id_rsa')
|
self.prvKey = get_file_content(self.dpath+'.impra_id_rsa')
|
||||||
self.pubKey = get_file_content(self.dpath+'.impra_id_rsa.pub')
|
self.pubKey = get_file_content(self.dpath+'.impra_id_rsa.pub')
|
||||||
#print('pubKey : \n'+self.pubKey)
|
#~ print('pubKey : \n'+self.pubKey)
|
||||||
#print('prvKey : \n'+self.prvKey)
|
#~ print('prvKey : \n'+self.prvKey)
|
||||||
|
|
||||||
def encrypt(self,data):
|
def encrypt(self,data):
|
||||||
""""""
|
""""""
|
||||||
|
@ -318,5 +360,10 @@ class Rsa:
|
||||||
if self.prvKey != None : key = " -CI '"+self.prvKey+"'"
|
if self.prvKey != None : key = " -CI '"+self.prvKey+"'"
|
||||||
#if self.prvKey != None : key = " -C '"+self.dpath+".impra_id_rsa'"
|
#if self.prvKey != None : key = " -C '"+self.dpath+".impra_id_rsa'"
|
||||||
cmd = self.cpath+"desurveil decrypt -i '"+data+"'"+key
|
cmd = self.cpath+"desurveil decrypt -i '"+data+"'"+key
|
||||||
#print(cmd)
|
|
||||||
return popen(cmd).read()
|
rs = run(cmd)
|
||||||
|
if rs[0]==1:
|
||||||
|
raise BadKeysException('bad key to decrypt')
|
||||||
|
else :
|
||||||
|
encData = str(rs[1],'utf-8')
|
||||||
|
return encData
|
||||||
|
|
Loading…
Reference in New Issue
Block a user