imap uid + cli getById

This commit is contained in:
a-Sansara 2012-09-13 20:23:29 +02:00
parent 800ce9f013
commit bc7a1a2876
5 changed files with 225 additions and 104 deletions

View File

@ -243,13 +243,19 @@ you can remove index but all presents files on the box %s will be unrecoverable
sys.exit(1)
if o.list :
impst.index.print(True,'-'*120+'\n -- INDEX '+impst.rootBox+'\n'+'-'*120)
if impst.index != None:
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)
impst.addFile(o.add[0],o.add[1],o.user,o.category)
elif o.get :
print(o.get)
impst.getFile(o.get)
elif o.get_by_id :
print(o.get_by_id)
label = impst.index.searchById(o.get_by_id)
if label !=None :
impst.getFile(label)
else: print(o.get_by_id+' a is not valid id')
elif o.search :
print(o.search)
elif o.remove :

View File

@ -42,7 +42,7 @@ from os import remove, urandom, sep
from os.path import abspath, dirname, join, realpath, basename, getsize, splitext
from re import split as regsplit
from impra.imap import ImapHelper, ImapConfig
from impra.util import __CALLER__, Rsa, RuTime, Noiser, Randomiz, RuTime, hash_sha256, formatBytes, randomFrom, bstr, quote_escape, stack, run
from impra.util import __CALLER__, Rsa, RuTime, Noiser, Randomiz, RuTime, hash_sha256, formatBytes, randomFrom, bstr, quote_escape, stack, run, file_exists, get_file_content
DEBUG = True
@ -205,12 +205,17 @@ class ImpraConf:
def get(self, key, section='main', profile=None):
""""""
if profile == None : profile = self.profile
return self.ini.get(key, profile+self.SEP_SECTION+section)
v = None
if self.ini.has(key,profile+self.SEP_SECTION+section):
v = self.ini.get(key, profile+self.SEP_SECTION+section)
return v
def set(self, key, value, section='main', profile=None):
""""""
if profile == None : profile = self.profile
return self.ini.set(key, value, profile+self.SEP_SECTION+section)
v = self.ini.set(key, value, profile+self.SEP_SECTION+section)
self.ini.write()
return v
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -235,7 +240,7 @@ class ImpraIndex:
"""Separator used for internal key such categories"""
def __init__(self, rsa, encdata='', dicCategory={}):
def __init__(self, rsa, encdata='', dicCategory={}, id=0):
"""Initialize the index with rsa and encoded data
:Parameters:
@ -247,7 +252,7 @@ class ImpraIndex:
"""
self.rsa = rsa
self.dic = {}
self.id = 0
self.id = id
if encdata =='' : data = encdata
else : data = self.rsa.decrypt(encdata)
data = data.replace(self.QUOTE_REPL, '\'')
@ -255,11 +260,10 @@ class ImpraIndex:
l = regsplit(self.SEP_ITEM,ld[0])
for row in l:
d = regsplit(self.SEP_TOKEN,row)
del d[7:]
# key : count, hash, ext, usr, cat
if len(d)>4 and d!='':
d.append(self.id)
if len(d)>5 and d!='':
self.dic[d[1]] = d
self.id += 1
if len(ld)>1:
l = regsplit(self.SEP_ITEM,ld[1].lstrip('\n'))
for row in l:
@ -287,16 +291,29 @@ class ImpraIndex:
def search(self,label):
"""Search the corresponding label in the index"""
return self.dic.get(label)
def searchById(self,sid):
"""Search the corresponding label in the index"""
rt = RuTime(eval(__CALLER__()))
l = None
r = [v for i, v in enumerate(self.dic) if self.dic[v][6] == str(sid)]
if len(r)>0: l = r[0]
rt.stop()
return l
def toString(self, withoutCatg=False):
def toString(self, withoutCatg=False, idFirst=False):
"""Make a string representation of the index as it was store on the server"""
data = cdata = ''
for k in sorted(self.dic):
v = self.dic.get(k)
if k[0]==self.SEP_KEY_INTERN and len(k)>1:
cdata += k+'='+v+self.SEP_ITEM
else :
for i in v: data += str(i)+self.SEP_TOKEN
else :
if not idFirst :
for i in v: data += str(i)+self.SEP_TOKEN
else :
data += str(v[6]).rjust(1+ceil(len(str(v[6]))/10),' ')+' '
for i in v[:-1]: data += str(i)+self.SEP_TOKEN
data = data.rstrip(self.SEP_TOKEN)+self.SEP_ITEM
if not withoutCatg :
data += self.SEP_CATEGORY+'\n'+cdata
@ -308,13 +325,10 @@ class ImpraIndex:
def print(self,withoutCatg=False, header=''):
"""Print index content as formated bloc"""
data = self.toString(withoutCatg).split(';')
i = 0
data = self.toString(withoutCatg,True).split(';')
print(header)
for row in data:
if row.rstrip('\n') != '':
print(str(i).rjust(1+ceil(len(data)/10),' ')+' - '+row)
i += 1
for row in data:
if row.rstrip('\n') != '': print(row)
@ -329,6 +343,7 @@ class ImpraStorage:
if wkdir == None : wkdir = abspath(join(dirname( __file__ ), '..', 'wk'))
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'))
self.ih = ImapHelper(iconf,self.rootBox)
@ -342,8 +357,7 @@ class ImpraStorage:
def _getIdIndex(self):
""""""
mid = None
status, resp = self.ih.srv.search(None, '(SUBJECT "%s")' % self.mb.getHashName('index'))
ids = [m for m in resp[0].split()]
ids = self.ih.searchBySubject(self.mb.getHashName('index'),True)
if len(ids) > 0 and int(ids[0]) >= 0 :
mid = ids[len(ids)-1]
for i in ids:
@ -357,20 +371,40 @@ class ImpraStorage:
ids = [m for m in resp[0].split()]
return ids
def _getCryptIndex(self):
""""""
encData = ''
if not self.idx : self._getIdIndex()
if self.idx :
msgIndex = self.ih.email(self.idx, True)
if msgIndex != None :
for part in msgIndex.walk():
ms = part.get_payload(decode=True)
encData = str(ms,'utf-8')
return encData
def getIndex(self):
""""""
index = None
rt = RuTime(eval(__CALLER__()))
index = None
encData = ''
uid = self.conf.get('uid' ,'index')
date = self.conf.get('date','index')
nid = self.conf.get('nid' ,'index')
if nid==None : nid = 0
if uid !=None : print(uid+' - '+date+' - ['+(str(nid))+']')
self._getIdIndex()
if self.idx :
msgIndex = self.ih.email(self.idx)
for i in self.delids : self.ih.delete(i)
for part in msgIndex.walk():
ms = part.get_payload(decode=True)
encData = str(ms,'utf-8')
else :
encData = ''
self.ih.deleteBin()
index = ImpraIndex(self.rsa, encData, {'catg':self.conf.get('types','catg')})
# getFromFile
if int(self.idx) == int(uid) and file_exists(self.pathInd):
encData = get_file_content(self.pathInd)
print('cache')
else:
encData = self._getCryptIndex()
with open(self.pathInd, mode='w', encoding='utf-8') as o:
o.write(encData)
index = ImpraIndex(self.rsa, encData, {'catg':self.conf.get('types','catg')}, int(nid))
rt.stop()
return index
def removeIndex(self):
@ -384,11 +418,18 @@ class ImpraStorage:
global DEBUG
rt = RuTime(eval(__CALLER__()))
if self.idx != None :
self.ih.delete(self.idx)
self.ih.delete(self.idx, True)
for i in self.delids : self.ih.delete(i, True)
encData = self.index.encrypt()
msgIndex = self.mb.buildIndex(encData)
if DEBUG: print(msgIndex.as_string())
self.ih.send(msgIndex.as_string(), self.rootBox)
ids = self.ih.send(msgIndex.as_string(), self.rootBox)
date = self.ih.headerField('date', ids[1], True)
self.conf.set('uid',ids[1],'index')
self.conf.set('date',date,'index')
with open(self.pathInd, mode='w', encoding='utf-8') as o:
o.write(encData)
self.ih.deleteBin()
#self.index = self.getIndex()
rt.stop()
@ -414,6 +455,7 @@ class ImpraStorage:
remove(self.fsplit.DIR_OUTBOX+row[1]+'.ipr')
self.index.add(hlst['head'][3],hlst['head'][0],hlst['head'][1],ext,self.mb.getHashName(usr),catg)
self.saveIndex()
self.conf.set('nid', str(self.index.id),'index')
else :
raise Exception(label + ' already exist on server')
except Exception as e :
@ -424,29 +466,35 @@ class ImpraStorage:
""""""
global DEBUG
rt = RuTime(eval(__CALLER__('"%s"' % label)))
key = self.index.search(label)
if key!=None :
ck = ConfigKey(key[0])
count = int(key[2])
hlst = ck.getHashList(label,count,True)
ids = self._getIdsBySubject(hlst['head'][2])
if len(ids) >= count:
status, resp = self.ih.srv.fetch(ids[0],'(BODY[HEADER.FIELDS (TO)])')
to = bstr(resp[0][1][4:-4])
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 :
self.ih.downloadAttachment(mid,self.fsplit.DIR_INBOX)
if DEBUG :
print(hlst['head'])
for v in hlst['data']:
print(v)
self.fsplit.deployFile(hlst, key[3])
if label==None :
print(str(label)+' unexist')
else :
key = self.index.search(label)
if label!=None and key!=None:
ck = ConfigKey(key[0])
count = int(key[2])
hlst = ck.getHashList(label,count,True)
ids = self._getIdsBySubject(hlst['head'][2])
if len(ids) >= count:
status, resp = self.ih.srv.fetch(ids[0],'(BODY[HEADER.FIELDS (TO)])')
to = bstr(resp[0][1][4:-4])
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 :
self.ih.downloadAttachment(mid,self.fsplit.DIR_INBOX)
if DEBUG :
print(hlst['head'])
for v in hlst['data']:
print(v)
self.fsplit.deployFile(hlst, key[3])
else :
#raise Exception(label+' is private')
print(label+' is private')
else :
raise Exception(label+' is private')
else :
raise Exception(label+' : invalid count parts '+str(len(ids))+'/'+str(count))
else:
raise Exception(label+' not on the server')
#raise Exception(label+' : invalid count parts '+str(len(ids))+'/'+str(count))
print(label+' : invalid count parts '+str(len(ids))+'/'+str(count))
else:
#raise Exception(str(label)+' not on the server')
print(str(label)+' not on the server')
rt.stop()
def clean(self):

View File

@ -188,19 +188,23 @@ class ImapHelper:
def countSeen(self, box='INBOX'):
""""""
s = self.status()
s = self.status(box)
return s['MESSAGES']-s['UNSEEN']
def countUnseen(self, box='INBOX'):
""""""
return self.status()['UNSEEN']
return self.status(box)['UNSEEN']
def countMsg(self, box='INBOX'):
""""""
return self.status()['MESSAGES']
return self.status(box)['MESSAGES']
def _ids(self, box='INBOX', search='ALL', charset=None):
def _ids(self, box='INBOX', search='ALL', charset=None, byUid=False):
""""""
status, resp = self.srv.select(box)
if status == self.KO :
self.createBox(box)
self.srv.select(box)
status, resp = self.srv.search(charset, '(%s)' % search)
return split(' ',bstr(resp[self.K_HEAD]))
@ -239,19 +243,54 @@ class ImapHelper:
rt.stop()
return status==self.OK
def subject(self, mid):
def subject(self, mid, byUid=False):
""""""
status, resp = self.srv.fetch(mid, '(body[header.fields (subject)])')
status, resp = self.fetch(mid, '(UID BODY[HEADER.FIELDS (SUBJECT)])', byUid)
subject = decode_header(str(resp[self.K_HEAD][1][9:-4], 'utf-8'))[0]
s = subject[0]
if subject[1] :
s = str(s,subject[1])
return s
def email(self, mid):
def search(self, query, byUid=False):
if byUid :
status, resp = self.srv.uid('search', None, query)
else :
status, resp = self.srv.search(None, query)
ids = [m for m in resp[0].split()]
return ids
def searchBySubject(self, subject, byUid=False):
return self.search('(SUBJECT "%s")' % subject, byUid)
def getUid(self, mid):
""""""
status, resp = self.srv.fetch(mid,'(UID RFC822)')
if status == self.OK :
value = ''
status, resp = self.srv.fetch(mid, '(UID)')
if status==self.OK :
value = resp[0][len(str(mid))+3:-1]
return value
def fetch(self, mid, query, byUid=False):
""""""
if not byUid :
status, resp = self.srv.fetch(mid, query)
else:
status, resp = self.srv.uid('fetch', mid, query)
return status, resp
def headerField(self, field, mid, byUid=False):
""""""
value = ''
status, resp = self.fetch(mid, '(UID BODY[HEADER.FIELDS (%s)])' % field.upper(), byUid)
if status==self.OK and resp[0]!=None:
value = str(resp[0][1][len(field)+2:-4],'utf-8')
return value
def email(self, mid, byUid=False):
""""""
status, resp = self.fetch(mid,'(UID RFC822)', byUid)
if status == self.OK and resp[0]!=None:
msg = message_from_bytes(resp[0][1])
else :
msg = None
@ -261,21 +300,31 @@ class ImapHelper:
""""""
rt = RuTime(eval(__CALLER__()))
self.srv.select(self.BOX_BIN)
ids = self._ids(self.BOX_BIN)
if len(ids) > 0 and ids[0]!='':
for mid in ids :
print('deleting msg '+mid)
status, resp = self.srv.store(mid, '+FLAGS', '\\Deleted')
ids = self.search('ALL',True)
if len(ids) > 0 and ids[0]!='' and ids[0]!=None:
#print(str(ids[0],'utf-8').split())
for mid in ids:
print('deleting msg '+str(mid))
#~ uid = bytes(mid)
#~ print(type(mid))
#~ print(mid)
#status, resp = self.srv.store(mid, '+FLAGS', '\\Deleted')
status, resp = self.srv.uid('store', mid, '+FLAGS', '\\Deleted' )
print(status)
print(resp)
self.srv.expunge()
self.srv.select(self.rootBox)
rt.stop()
def delete(self, mid):
def delete(self, mid, byUid=False):
""""""
rt = RuTime(eval(__CALLER__('%i' % int(mid))))
status = None
if int(mid) > 0 :
status, resp = self.srv.store(mid, '+FLAGS', '\\Deleted')
if byUid:
status, resp = self.srv.uid( 'store', mid, '+FLAGS', '\\Deleted' )
else :
status, resp = self.srv.store(mid, '+FLAGS', '\\Deleted')
self.srv.expunge()
rt.stop()
return status == self.OK
@ -297,9 +346,14 @@ class ImapHelper:
def send(self, msg, box='INBOX'):
""""""
rt = RuTime(eval(__CALLER__()))
self.srv.append(box, '\Draft', Time2Internaldate(time()), bytes(msg,'utf-8'))
rt = RuTime(eval(__CALLER__()))
mid = None
date = Time2Internaldate(time())
status, resp = self.srv.append(box, '\Draft', date, bytes(msg,'utf-8'))
if status==self.OK:
mid = str(resp[0],'utf-8')[11:-11].split(' ')
rt.stop()
return mid
if __name__ == '__main__':
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -85,6 +85,15 @@ def get_file_path(val):
""""""
return abspath(dirname(val))+sep
def file_exists(path):
""""""
try:
with open(path) as f:
exist = True
except IOError as e:
exist = False
return exist
def formatBytes(b, p=2):
"""Give a human representation of bytes size `b`
:Returns: `str`

View File

@ -27,40 +27,44 @@
# along with ImpraStorage. If not, see <http://www.gnu.org/licenses/>.
from impra.core import ImpraConf, ImpraStorage
from impra.util import IniFile, Rsa, RuTime
from impra.util import IniFile, Rsa, RuTime, get_file_path
from impra.cli import Cli
if __name__ == '__main__':
rt = RuTime(__name__+'()')
conf = ImpraConf(IniFile('./impra.ini'))
rsa = Rsa(conf.ini.get('prvKey',conf.profile+'.keys'),conf.ini.get('pubKey',conf.profile+'.keys'))
impst = ImpraStorage(rsa, conf)
print('\n -- INDEX DATA -- ')
impst.index.print()
Cli(get_file_path(__file__ ))
#~ rt = RuTime(__name__+'()')
#~ conf = ImpraConf(IniFile('./impra.ini'))
#~ rsa = Rsa(conf.ini.get('prvKey',conf.profile+'.keys'),conf.ini.get('pubKey',conf.profile+'.keys'))
#~ impst = ImpraStorage(rsa, conf)
#~
#~ print('\n -- INDEX DATA -- ')
#~ impst.index.print()
#~ print('-- LIST BOX --')
#~ lb = impst.ih.listBox('/')
#~ print(lb)
#print('-- DELETE BIN --')
#impst.ih.deleteBin()
filePath = '/media/Data/dev/big_toph3.jpg'
lab = 'Meuf\'bonne aussi4'
print('\n -- ADD FILE -- ')
impst.addFile(filePath,lab,conf.ini.get('name',conf.profile+'.infos'),'images')
print('\n -- GET FILE -- ')
impst.getFile(lab)
print('\n -- INDEX DATA -- ')
impst.index.print()
print('\n -- CLEAN -- ')
impst.clean()
rt.stop()
#~
#~ #print('-- DELETE BIN --')
#~ #impst.ih.deleteBin()
#~
#~ filePath = '/media/Data/dev/big_toph3.jpg'
#~
#~ lab = 'Meuf\'bonne aussi4'
#~
#~ print('\n -- ADD FILE -- ')
#~ impst.addFile(filePath,lab,conf.ini.get('name',conf.profile+'.infos'),'images')
#~
#~ print('\n -- GET FILE -- ')
#~ impst.getFile(lab)
#~
#~ print('\n -- INDEX DATA -- ')
#~ impst.index.print()
#~
#~ print('\n -- CLEAN -- ')
#~ impst.clean()
#~
#~ rt.stop()
#python -O -m compileall impra/*.py