amend displaying step and task + compat project imprastorage

This commit is contained in:
a-Sansara 2014-07-17 01:32:38 +02:00
parent 23741be148
commit 14b5e9fab4
9 changed files with 700 additions and 45 deletions

View File

@ -126,19 +126,10 @@ class Cli(AbstractCli):
Sys.g.LOG_QUEUE.put(Sys.g.SIGNAL_STOP) Sys.g.LOG_QUEUE.put(Sys.g.SIGNAL_STOP)
else : else :
self.parser.error_cmd((('unknow command ',(a[0],Sys.Clz.fgb3)),)) self.parser.error_cmd((('unknow command ',(a[0],Sys.Clz.fgb3)),), True)
if not o.quiet : Sys.dprint() if not o.quiet : Sys.dprint()
#~
#~ @staticmethod
#~ def error_cmd(data):
#~ """"""
#~ Cli.print_usage('')
#~ Sys.dprint()
#~ Sys.pwarn(data, True)
#~ Cli.exit(1)
@staticmethod @staticmethod
def print_usage(data, withoutHeader=False): def print_usage(data, withoutHeader=False):

View File

@ -87,9 +87,7 @@ class CliApp:
if self.o.outputfile is None : if self.o.outputfile is None :
self.o.outputfile = Sys.basename(self.a[1]) self.o.outputfile = Sys.basename(self.a[1])
if self.o.outputfile[-len(Kirmah.EXT):] != Kirmah.EXT : if self.o.outputfile[-len(Kirmah.EXT):] != Kirmah.EXT :
print(self.o.outputfile[-len(Kirmah.EXT):])
self.o.outputfile += Kirmah.EXT self.o.outputfile += Kirmah.EXT
print(self.o.outputfile)
d = self.getDefaultOption((self.o.compress,self.o.fullcompress,self.o.nocompress)) d = self.getDefaultOption((self.o.compress,self.o.fullcompress,self.o.nocompress))
compress = (KirmahHeader.COMP_END if d == 0 or (d is None and Io.is_binary(self.a[1])) else (KirmahHeader.COMP_ALL if d==1 or d is None else KirmahHeader.COMP_NONE)) compress = (KirmahHeader.COMP_END if d == 0 or (d is None and Io.is_binary(self.a[1])) else (KirmahHeader.COMP_ALL if d==1 or d is None else KirmahHeader.COMP_NONE))

View File

@ -48,7 +48,7 @@ PRG_LICENSE = 'GNU GPL v3'
PRG_RESOURCES_PATH = '/usr/share/'+PRG_PACKAGE+sep PRG_RESOURCES_PATH = '/usr/share/'+PRG_PACKAGE+sep
if not isdir(PRG_RESOURCES_PATH): if not isdir(PRG_RESOURCES_PATH):
PRG_RESOURCES_PATH = dirname(dirname(realpath(__file__)))+sep+'resources'+sep+PRG_PACKAGE+sep PRG_RESOURCES_PATH = dirname(dirname(realpath(__file__)))+sep+'resources'+sep+PRG_PACKAGE+sep
print(PRG_RESOURCES_PATH) #~ print(PRG_RESOURCES_PATH)
PRG_GLADE_PATH = PRG_RESOURCES_PATH+'glade'+sep+PRG_PACKAGE+'.glade' PRG_GLADE_PATH = PRG_RESOURCES_PATH+'glade'+sep+PRG_PACKAGE+'.glade'
PRG_LICENSE_PATH = PRG_RESOURCES_PATH+'/LICENSE' PRG_LICENSE_PATH = PRG_RESOURCES_PATH+'/LICENSE'
PRG_LOGO_PATH = join(PRG_RESOURCES_PATH,'..'+sep,'pixmaps'+sep,PRG_PACKAGE+sep,PRG_PACKAGE+'.png') PRG_LOGO_PATH = join(PRG_RESOURCES_PATH,'..'+sep,'pixmaps'+sep,PRG_PACKAGE+sep,PRG_PACKAGE+'.png')

View File

@ -63,7 +63,7 @@ def hash_sha256_file(path):
return sha256(open(path, mode='rb').read()).hexdigest() return sha256(open(path, mode='rb').read()).hexdigest()
@Log() @Log(Const.LOG_ALL)
def hash_md5_file(path): def hash_md5_file(path):
"""Get a md5 hash of file from path """Get a md5 hash of file from path
:Returns: `str` :Returns: `str`
@ -104,7 +104,7 @@ class KeyGen :
"""""" """"""
@Log(Const.LOG_BUILD) @Log(Const.LOG_BUILD)
def __init__(self, length, salt=None): def __init__(self, length=1024, salt=None):
"""""" """"""
self.new(length, salt) self.new(length, salt)
@ -613,8 +613,7 @@ class Kirmah:
@Log() @Log()
def split(self, fromPath, hlst): def split(self, fromPath, hlst):
"""""" """"""
if not Sys.is_cli_cancel(): if not Sys.is_cli_cancel():
self.DIR_OUTBOX = ''
f = open(fromPath, 'rb+') f = open(fromPath, 'rb+')
m, p, rsz = mmap(f.fileno(), 0), 0, 0 m, p, rsz = mmap(f.fileno(), 0), 0, 0
fsize = Sys.getsize(fromPath) fsize = Sys.getsize(fromPath)
@ -766,11 +765,11 @@ class Kirmah:
d = Sys.datetime.now() d = Sys.datetime.now()
if compstart : if compstart :
if Sys.g.DEBUG : Sys.wlog(Sys.dprint()) if Sys.g.DEBUG : Sys.wlog(Sys.dprint())
Sys.ptask('Compressing data') if not Sys.g.QUIET : Sys.ptask('Compressing data')
self.compress_start(fp, tp, compstart, emit=emit) self.compress_start(fp, tp, compstart, emit=emit)
if compstart : if compstart :
if Sys.g.DEBUG : Sys.wlog(Sys.dprint()) if Sys.g.DEBUG : Sys.wlog(Sys.dprint())
Sys.pstep('Compression mode', d, True) if not Sys.g.QUIET : Sys.pstep('Compression mode', d, True)
fp, tp = tp, self.tmpPath2 if tp == self.tmpPath1 else self.tmpPath1 fp, tp = tp, self.tmpPath2 if tp == self.tmpPath1 else self.tmpPath1
if emit : Sys.cli_emit_progress(5) if emit : Sys.cli_emit_progress(5)
return fp, tp, decHeader['rmode'], decHeader['mmode'], compend return fp, tp, decHeader['rmode'], decHeader['mmode'], compend
@ -783,14 +782,14 @@ class Kirmah:
if rmode : if rmode :
#~ self.mpRandomFileContent(fp, tp, 4) #~ self.mpRandomFileContent(fp, tp, 4)
if Sys.g.DEBUG : Sys.wlog(Sys.dprint()) if Sys.g.DEBUG : Sys.wlog(Sys.dprint())
Sys.ptask('Randomizing data') if not Sys.g.QUIET : Sys.ptask('Randomizing data')
self.randomFileContent(fp, tp, emit=emit) self.randomFileContent(fp, tp, emit=emit)
fp, tp = tp, self.tmpPath2 if tp == self.tmpPath1 else self.tmpPath1 fp, tp = tp, self.tmpPath2 if tp == self.tmpPath1 else self.tmpPath1
if emit : Sys.cli_emit_progress(75) if emit : Sys.cli_emit_progress(75)
if mmode : if mmode :
if Sys.g.DEBUG : Sys.wlog(Sys.dprint()) if Sys.g.DEBUG : Sys.wlog(Sys.dprint())
Sys.ptask('Mixing data') if not Sys.g.QUIET : Sys.ptask('Mixing data')
self.mixdata(fp, tp, True, emit=emit) self.mixdata(fp, tp, True, emit=emit)
fp, tp = tp, self.tmpPath2 if tp == self.tmpPath1 else self.tmpPath1 fp, tp = tp, self.tmpPath2 if tp == self.tmpPath1 else self.tmpPath1
@ -799,17 +798,17 @@ class Kirmah:
if compend : if compend :
d = Sys.datetime.now() d = Sys.datetime.now()
if Sys.g.DEBUG : Sys.wlog(Sys.dprint()) if Sys.g.DEBUG : Sys.wlog(Sys.dprint())
Sys.ptask('Compressing data') if not Sys.g.QUIET : Sys.ptask('Compressing data')
self.compress_end(fp, toPath, compend, emit=emit) self.compress_end(fp, toPath, compend, emit=emit)
if emit : Sys.cli_emit_progress(95) if emit : Sys.cli_emit_progress(95)
if compend : if compend :
if Sys.g.DEBUG : Sys.wlog(Sys.dprint()) if Sys.g.DEBUG : Sys.wlog(Sys.dprint())
Sys.pstep('Compression mode', d, True) if not Sys.g.QUIET : Sys.pstep('Compression mode', d, True)
# clean tmp files # clean tmp files
if Sys.g.DEBUG : Sys.wlog(Sys.dprint()) if Sys.g.DEBUG : Sys.wlog(Sys.dprint())
Sys.ptask('Cleaning') if not Sys.g.QUIET : Sys.ptask('Cleaning')
try : try :
Sys.removeFile(self.tmpPath1) Sys.removeFile(self.tmpPath1)
@ -850,21 +849,21 @@ class Kirmah:
def encrypt_mproc(self, fp, tp, nproc=1, emit=True): def encrypt_mproc(self, fp, tp, nproc=1, emit=True):
"""""" """"""
if Sys.g.DEBUG : Sys.wlog(Sys.dprint()) if Sys.g.DEBUG : Sys.wlog(Sys.dprint())
Sys.ptask('Encrypting data') if not Sys.g.QUIET : Sys.ptask('Encrypting data')
d = Sys.datetime.now() d = Sys.datetime.now()
c = not Sys.is_cli_cancel() c = not Sys.is_cli_cancel()
if c: if c:
if nproc == 1 : if nproc == 1 :
self.encryptToFile(fp, tp) self.encryptToFile(fp, tp)
if Sys.g.DEBUG : Sys.wlog(Sys.dprint()) if Sys.g.DEBUG : Sys.wlog(Sys.dprint())
Sys.pstep('Encrypt data', d, c) if not Sys.g.QUIET : Sys.pstep('Encrypt data', d, c)
else : else :
hlstPaths = self.prepare_mproc_encode(fp, nproc) hlstPaths = self.prepare_mproc_encode(fp, nproc)
mg = Manager(self.mproc_encode_part, nproc, None, Sys.g.MPEVENT) mg = Manager(self.mproc_encode_part, nproc, None, Sys.g.MPEVENT)
mg.run() mg.run()
self.mpMergeFiles(hlstPaths, tp, emit=emit) self.mpMergeFiles(hlstPaths, tp, emit=emit)
if Sys.g.DEBUG : Sys.wlog(Sys.dprint()) if Sys.g.DEBUG : Sys.wlog(Sys.dprint())
Sys.pstep('Encrypt data (multiproc)', d, c) if not Sys.g.QUIET : Sys.pstep('Encrypt data (multiproc)', d, c)
if emit : Sys.cli_emit_progress(70) if emit : Sys.cli_emit_progress(70)
@ -901,9 +900,9 @@ class Kirmah:
if len(decHeader) > 0 : if len(decHeader) > 0 :
if Sys.g.DEBUG : Sys.wlog(Sys.dprint()) if Sys.g.DEBUG : Sys.wlog(Sys.dprint())
if decHeader['smode'] == self.mark[fsize%len(self.mark)] : if decHeader['smode'] == self.mark[fsize%len(self.mark)] :
Sys.pstep('Reading Header', d, True) if not Sys.g.QUIET : Sys.pstep('Reading Header', d, True)
else : else :
Sys.pstep('Reading Header', d, False, False, False) if not Sys.g.QUIET : Sys.pstep('Reading Header', d, False, False, False)
raise BadKeyException('wrong key') raise BadKeyException('wrong key')
compend, compstart = not decHeader['cmode']== KirmahHeader.COMP_NONE, decHeader['cmode']== KirmahHeader.COMP_ALL compend, compstart = not decHeader['cmode']== KirmahHeader.COMP_NONE, decHeader['cmode']== KirmahHeader.COMP_ALL
@ -913,26 +912,26 @@ class Kirmah:
if compend : if compend :
d = Sys.datetime.now() d = Sys.datetime.now()
if Sys.g.DEBUG : Sys.wlog(Sys.dprint()) if Sys.g.DEBUG : Sys.wlog(Sys.dprint())
Sys.ptask('Uncompressing data') if not Sys.g.QUIET : Sys.ptask('Uncompressing data')
self.uncompress_end(fp, tp, compend, emit=emit) self.uncompress_end(fp, tp, compend, emit=emit)
if emit : Sys.cli_emit_progress(10) if emit : Sys.cli_emit_progress(10)
if compend : if compend :
if Sys.g.DEBUG : Sys.wlog(Sys.dprint()) if Sys.g.DEBUG : Sys.wlog(Sys.dprint())
Sys.pstep('Compression mode', d, True) if not Sys.g.QUIET : Sys.pstep('Compression mode', d, True)
fp, tp = tp, self.tmpPath2 if tp == self.tmpPath1 else self.tmpPath1 fp, tp = tp, self.tmpPath2 if tp == self.tmpPath1 else self.tmpPath1
if decHeader['mmode'] : if decHeader['mmode'] :
d = Sys.datetime.now() d = Sys.datetime.now()
if Sys.g.DEBUG : Sys.wlog(Sys.dprint()) if Sys.g.DEBUG : Sys.wlog(Sys.dprint())
Sys.ptask('Sorting data') if not Sys.g.QUIET : Sys.ptask('Sorting data')
self.unmixdata(fp, tp, emit=emit) self.unmixdata(fp, tp, emit=emit)
fp, tp = tp, self.tmpPath2 if tp == self.tmpPath1 else self.tmpPath1 fp, tp = tp, self.tmpPath2 if tp == self.tmpPath1 else self.tmpPath1
if emit : Sys.cli_emit_progress(20) if emit : Sys.cli_emit_progress(20)
if decHeader['rmode'] : if decHeader['rmode'] :
d = Sys.datetime.now() d = Sys.datetime.now()
if Sys.g.DEBUG : Sys.wlog(Sys.dprint()) if Sys.g.DEBUG : Sys.wlog(Sys.dprint())
Sys.ptask('Reordering data') if not Sys.g.QUIET : Sys.ptask('Reordering data')
self.unRandomFileContent(fp, tp, emit=emit) self.unRandomFileContent(fp, tp, emit=emit)
fp, tp = tp, self.tmpPath2 if tp == self.tmpPath1 else self.tmpPath1 fp, tp = tp, self.tmpPath2 if tp == self.tmpPath1 else self.tmpPath1
if emit : Sys.cli_emit_progress(25) if emit : Sys.cli_emit_progress(25)
@ -947,15 +946,15 @@ class Kirmah:
if emit : Sys.cli_emit_progress(80) if emit : Sys.cli_emit_progress(80)
if compstart : if compstart :
if Sys.g.DEBUG : Sys.wlog(Sys.dprint()) if Sys.g.DEBUG : Sys.wlog(Sys.dprint())
Sys.ptask('Uncompressing data') if not Sys.g.QUIET : Sys.ptask('Uncompressing data')
self.uncompress_start(fromPath, toPath, compstart, emit=emit) self.uncompress_start(fromPath, toPath, compstart, emit=emit)
if emit : Sys.cli_emit_progress(90) if emit : Sys.cli_emit_progress(90)
if compstart: if compstart:
if Sys.g.DEBUG : Sys.wlog(Sys.dprint()) if Sys.g.DEBUG : Sys.wlog(Sys.dprint())
Sys.pstep('Compression mode', d, True) if not Sys.g.QUIET : Sys.pstep('Compression mode', d, True)
if Sys.g.DEBUG : Sys.wlog(Sys.dprint()) if Sys.g.DEBUG : Sys.wlog(Sys.dprint())
Sys.ptask('Cleaning') if not Sys.g.QUIET : Sys.ptask('Cleaning')
if emit : Sys.cli_emit_progress(95) if emit : Sys.cli_emit_progress(95)
try : try :
Sys.removeFile(self.tmpPath1) Sys.removeFile(self.tmpPath1)
@ -969,7 +968,7 @@ class Kirmah:
def decrypt_mproc(self, fromPath, toPath, nproc=1, emit=True): def decrypt_mproc(self, fromPath, toPath, nproc=1, emit=True):
"""""" """"""
if Sys.g.DEBUG : Sys.wlog(Sys.dprint()) if Sys.g.DEBUG : Sys.wlog(Sys.dprint())
Sys.ptask('Decrypting data') if not Sys.g.QUIET : Sys.ptask('Decrypting data')
d = Sys.datetime.now() d = Sys.datetime.now()
c = not Sys.is_cli_cancel() c = not Sys.is_cli_cancel()
if c: if c:
@ -977,14 +976,14 @@ class Kirmah:
if nproc == 1 : if nproc == 1 :
self.decryptToFile(fromPath, toPath) self.decryptToFile(fromPath, toPath)
if Sys.g.DEBUG : Sys.wlog(Sys.dprint()) if Sys.g.DEBUG : Sys.wlog(Sys.dprint())
Sys.pstep('Decrypt data', d, True) if not Sys.g.QUIET : Sys.pstep('Decrypt data', d, True)
else : else :
hlstPaths = self.prepare_mproc_decode(fromPath, nproc) hlstPaths = self.prepare_mproc_decode(fromPath, nproc)
mg = Manager(self.mproc_decode_part, nproc, None, Sys.g.MPEVENT, emit=True) mg = Manager(self.mproc_decode_part, nproc, None, Sys.g.MPEVENT, emit=True)
mg.run() mg.run()
self.mpMergeFiles(hlstPaths, toPath, emit=emit) self.mpMergeFiles(hlstPaths, toPath, emit=emit)
if Sys.g.DEBUG : Sys.wlog(Sys.dprint()) if Sys.g.DEBUG : Sys.wlog(Sys.dprint())
Sys.pstep('Decrypt data (multiproc)', d, True) if not Sys.g.QUIET : Sys.pstep('Decrypt data (multiproc)', d, True)

View File

@ -87,6 +87,7 @@ class AbstractCli():
"""""" """"""
if not Sys.isUnix : Const.LINE_SEP_CHAR = '-' if not Sys.isUnix : Const.LINE_SEP_CHAR = '-'
AbstractCli.conf = prgconf AbstractCli.conf = prgconf
self.CHQ = "'"
self.parser = TinyParser() self.parser = TinyParser()
self.parser.print_help = self.print_help self.parser.print_help = self.print_help
self.parser.print_usage = self.print_usage self.parser.print_usage = self.print_usage
@ -98,7 +99,7 @@ class AbstractCli():
self.parser.add_option('-q', '--quiet' , action='store_true', default=False) self.parser.add_option('-q', '--quiet' , action='store_true', default=False)
self.parser.add_option('--no-color' , action='store_true' , default=False) self.parser.add_option('--no-color' , action='store_true' , default=False)
def error_cmd(self, data, pusage=False): def error_cmd(self, data, pusage=False):
"""""" """"""
@ -127,7 +128,7 @@ class AbstractCli():
Sys.wlog(a) Sys.wlog(a)
Sys.wlog(b + c + d + e + f ) Sys.wlog(b + c + d + e + f )
Sys.wlog(a) Sys.wlog(a)
Sys.wlog(Sys.dprint()) #~ Sys.wlog(Sys.dprint())
@staticmethod @staticmethod

488
psr/imap.py Normal file
View File

@ -0,0 +1,488 @@
from imaplib import Commands, IMAP4_SSL, Time2Internaldate
from binascii import b2a_base64, a2b_base64
from codecs import register, StreamReader, StreamWriter
from email import message_from_bytes
from email.header import decode_header
from email.message import Message
from re import search as research, split as resplit
from psr.sys import Io, Sys, Const
from psr.log import Log
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~ ImapUtf7 decoding/encoding ~~
def _seq_encode(seq,l):
""""""
if len(seq) > 0 :
l.append('&%s-' % str(b2a_base64(bytes(''.join(seq),'utf-16be')),'utf-8').rstrip('\n=').replace('/', ','))
elif l:
l.append('-')
def _seq_decode(seq,l):
""""""
d = ''.join(seq[1:])
pad = 4-(len(d)%4)
l.append(str(a2b_base64(bytes(d.replace(',', '/')+pad*'=','utf-16be')),'utf-16be'))
def encode(s):
""""""
l, e, = [], []
for c in s :
if ord(c) in range(0x20,0x7e):
if e : _seq_encode(e,l)
e = []
l.append(c)
if c == '&' : l.append('-')
else :
e.append(c)
if e : _seq_encode(e,l)
return ''.join(l)
def decode(s):
""""""
l, d = [], []
for c in s:
if c == '&' and not d : d.append('&')
elif c == '-' and d:
if len(d) == 1: l.append('&')
else : _seq_decode(d,l)
d = []
elif d: d.append(c)
else: l.append(c)
if d: _seq_decode(d,l)
return ''.join(l)
def _encoder(s):
""""""
e = bytes(encode(s),'utf-8')
return e, len(e)
def _decoder(s):
""""""
d = decode(str(s,'utf-8'))
return d, len(d)
def _codec_imap4utf7(name):
""""""
if name == 'imap4-utf-7':
return (_encoder, _decoder, Imap4Utf7StreamReader, Imap4Utf7StreamWriter)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~ StreamReader & StreamWriter ~~
class Imap4Utf7StreamReader(StreamReader):
def decode(self, s, errors='strict'): return _decoder(s)
class Imap4Utf7StreamWriter(StreamWriter):
def decode(self, s, errors='strict'): return _encoder(s)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~ registering codec ~~
register(_codec_imap4utf7)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~ Imap utilities ~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~ class ImapConfig ~~
class ImapConfig:
""""""
def __init__(self, host, user, pwd, port=993):
""""""
self.host = host
self.user = user
self.pwd = pwd
self.port = port
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~ class ImapClient ~~
class ImapClient(IMAP4_SSL):
""""""
Commands['XLIST'] = ('AUTH', 'SELECTED')
@Log(Const.LOG_DEBUG)
def xlist(self, directory='""', pattern='*'):
"""(X)List mailbox names in directory matching pattern. Using Google's XLIST extension
(status, [data]) = <instance>.xlist(directory='""', pattern='*')
'data' is list of XLIST responses.
thks to barduck : http://stackoverflow.com/users/602242/barduck
"""
try :
name = 'XLIST'
status, data = self._simple_command(name, directory, pattern)
return self._untagged_response(status, data, name)
except :
return 'NO', ''
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~ class ImapHelper ~~
class ImapHelper:
""""""
K_HEAD, K_DATA = 0, 1
""""""
OK = 'OK'
""""""
KO = 'NO'
""""""
ENCODING = 'utf-8'
""""""
REG_SATUS = r'^"?(.*)"? \(([^\(]*)\)'
""""""
NO_SELECT = '\\Noselect'
""""""
CHILDREN = '\\HasChildren'
""""""
NO_CHILDREN = '\\HasNoChildren'
""""""
INBOX = '\\Inbox'
""""""
DRAFTS = '\\Drafts'
""""""
TRASH = '\\Trash'
""""""
SENT = '\\Sent'
""""""
DELETED = '\\Deleted'
""""""
FLAGS = '+FLAGS'
""""""
@Log(Const.LOG_BUILD)
def __init__(self, conf, box='INBOX'):
""""""
if research('yahoo.com', conf.host) is not None :
self.DRAFTS = self.DRAFTS[:-1]
self.conf = conf
self.rootBox = box
self.BOXS = {}
self.cnx = None
self.cnxusr = None
self.switchAccount(self.conf, self.rootBox, True)
@Log()
def switchAccount(self, conf, box='INBOX', force=False):
if force or self.cnx is None or self.cnxusr is not conf.user :
try :
Sys.print(' Attempt to login... ' , Sys.Clz.fgB7, False)
Sys.print('(' , Sys.Clz.fgn7, False)
Sys.print(conf.user , Sys.Clz.fgB2, False)
Sys.print('@' , Sys.Clz.fgn7, False)
Sys.print(conf.host , Sys.Clz.fgB4, False)
Sys.print(':' , Sys.Clz.fgn7, False)
Sys.print(conf.port , Sys.Clz.fgB3, False)
Sys.print(')' , Sys.Clz.fgn7)
self.cnx = ImapClient(conf.host,conf.port)
except Exception as e :
raise BadHostException()
try :
status, resp = self.cnx.login(conf.user,conf.pwd)
except Exception as e :
status = self.KO
pass
finally :
if status == self.KO :
self.cnxusr = None
raise BadLoginException(' Cannot login with '+conf.user+':'+conf.pwd)
else :
Sys.print(' connected' , Sys.Clz.fgB2)
self.cnxusr = conf.user
try :
status, resp = self.cnx.select(self.rootBox)
if status == self.KO :
self.createBox(self.rootBox)
status, resp = self.cnx.select(self.rootBox)
self.initBoxNames()
except Exception as e :
print(e)
@Log()
def createBox(self, box):
""""""
status, resp = self.cnx.create(encode(box))
return status==self.OK
@Log()
def deleteBox(self, box):
""""""
status, resp = self.cnx.delete(encode(box))
return status==self.OK
@Log(Const.LOG_DEBUG)
def initBoxNames(self):
""""""
status, resp = self.cnx.xlist()
if status == self.OK :
bdef, bname, c = None, None, None
for c in resp :
bdef, bname = c[1:-1].split(b') "/" "')
if bdef == Io.bytes(self.NO_SELECT+' '+self.CHILDREN) :
self.BOXS['/'] = Io.str(bname)
elif bdef == Io.bytes(self.NO_CHILDREN+' '+self.INBOX) :
self.BOXS[self.INBOX] = self.INBOX[1:].upper()
elif bdef == Io.bytes(self.NO_CHILDREN+' '+self.DRAFTS) :
self.BOXS[self.DRAFTS] = Io.str(bname)
elif bdef == Io.bytes(self.NO_CHILDREN+' '+self.TRASH) :
self.BOXS[self.TRASH] = Io.str(bname)
elif bdef == Io.bytes(self.NO_CHILDREN+' '+self.SENT) :
self.BOXS[self.SENT] = Io.str(bname)
else :
self.BOXS = { '/' : '/', self.INBOX : self.INBOX[1:].upper(), self.DRAFTS : self.DRAFTS[1:], self.TRASH : self.TRASH[1:], self.SENT : self.SENT[1:] }
@Log(Const.LOG_DEBUG)
def listBox(self, box='INBOX', pattern='*'):
""""""
status, resp = self.cnx.list(box,pattern)
l = []
for r in resp :
if r is not None :
name = Io.str(r).split(' "/" ')
l.append((name[0][1:-1].split(' '),name[1][1:-1]))
return l
@Log(Const.LOG_DEBUG)
def status(self, box='INBOX'):
""""""
status, resp = self.cnx.status(box, '(MESSAGES RECENT UIDNEXT UIDVALIDITY UNSEEN)')
if status == self.OK :
data = research(self.REG_SATUS, Io.str(resp[self.K_HEAD]))
l = resplit(' ',data.group(2))
dic = {'BOX' : box}
for i in range(len(l)):
if i%2 == 0 : dic[l[i]] = int(l[i+1])
else : dic = {}
return dic
@Log()
def countSeen(self, box='INBOX'):
""""""
s = self.status(box)
return s['MESSAGES']-s['UNSEEN']
@Log()
def countUnseen(self, box='INBOX'):
""""""
return self.status(box)['UNSEEN']
@Log()
def countMsg(self, box='INBOX'):
""""""
return self.status(box)['MESSAGES']
@Log(Const.LOG_DEBUG)
def _ids(self, box='INBOX', search='ALL', charset=None, byUid=False):
""""""
status, resp = self.cnx.select(box)
if status == self.KO :
self.createBox(box)
self.cnx.select(box)
status, resp = self.cnx.search(charset, '(%s)' % search)
return resplit(' ',Io.str(resp[self.K_HEAD]))
@Log()
def idsUnseen(self, box='INBOX', charset=None):
""""""
return self._ids(box,'UNSEEN', charset)
@Log()
def idsMsg(self, box='INBOX', charset=None):
""""""
return self._ids(box,'ALL', charset)
@Log()
def idsSeen(self, box='INBOX', charset=None):
""""""
return self._ids(box,'NOT UNSEEN', charset)
@Log(Const.LOG_DEBUG)
def search(self, query, byUid=False):
""""""
if byUid :
status, resp = self.cnx.uid('search', None, query)
else :
status, resp = self.cnx.search(None, query)
ids = [m for m in resp[0].split()]
return ids
@Log()
def searchBySubject(self, subject, byUid=False):
""""""
return self.search('(SUBJECT "%s")' % subject, byUid)
@Log()
def getUid(self, mid):
""""""
value = ''
status, resp = self.cnx.fetch(mid, '(UID)')
if status==self.OK :
# '$mid (UID $uid)'
value = resp[0][len(str(mid))+6:-1]
return value
@Log(Const.LOG_DEBUG)
def fetch(self, mid, query, byUid=False):
""""""
if not byUid :
status, resp = self.cnx.fetch(mid, query)
else:
status, resp = self.cnx.uid('fetch', mid, query)
return status, resp
@Log()
def headerField(self, mid, field, byUid=False):
""""""
value = ''
field = field.upper()
query = '(UID BODY[HEADER' + ('])' if field=='*' or field=='ALL' else '.FIELDS (%s)])' % field)
status, resp = self.fetch(mid, query, byUid)
if status==self.OK and resp[0]!=None:
value = Io.str(resp[0][1][len(field)+2:-4])
return value
@Log()
def getSubject(self, mid, byUid=False):
""""""
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
@staticmethod
def _getIdsList(ids):
idslist = None
if isinstance(ids,list):
if len(ids) > 0 and ids[0]!='' and ids[0]!=None:
li = len(ids)-1
if int(ids[0])+li == int(ids[li]):
idslist = Io.str(ids[0]+b':'+ids[li]) if isinstance(ids[0],bytes) else str(ids[0])+':'+str(ids[li])
else :
idslist = Io.str(b','.join(ids)) if isinstance(ids[0],bytes) else ','.join(ids)
elif isinstance(ids, int) and ids > 0:
idslist = Io.str(ids)
return idslist
@Log()
def delete(self, ids, byUid=False, expunge=True):
""""""
status, delids = None, ImapHelper._getIdsList(ids)
#~ print(delids)
if delids is not None :
if byUid:
status, resp = self.cnx.uid( 'store', delids, self.FLAGS, self.DELETED )
else :
status, resp = self.cnx.store(delids, self.FLAGS, self.DELETED)
if expunge :
self.cnx.expunge()
return status == self.OK
@Log()
def clearTrash(self):
""""""
self.cnx.select(self.BOXS[self.TRASH])
ids = self.search('ALL',True)
if len(ids) > 0 and ids[0]!='' and ids[0]!=None:
delids = ImapHelper._getIdsList(ids)
status, resp = self.cnx.uid('store', delids, self.FLAGS, self.DELETED )
Sys.print(' Deleting msg ', Sys.Clz.fgn7, False, False)
Sys.print(delids , Sys.Clz.fgB1, False, False)
Sys.print(' '+status , Sys.Clz.fgB7)
self.cnx.expunge()
self.cnx.select(self.rootBox)
@Log()
def getEmail(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
return msg
@Log(Const.LOG_APP)
def getAttachment(self, msg, toDir='./', byUid=False):
""""""
if not isinstance(msg, Message) :
msg = self.getEmail(msg, byUid)
for part in msg.walk():
filename = part.get_filename()
if part.get_content_maintype() == 'multipart' or not filename : continue
with Io.wfile(Sys.join(toDir, filename)) as fo :
fo.write(part.get_payload(decode=True))
@Log()
def send(self, msg, box='INBOX'):
""""""
mid = None
date = Time2Internaldate(Sys.time())
status, resp = self.cnx.append(box, '\Draft', date, bytes(msg,'utf-8'))
if status==self.OK:
mid = str(resp[0],'utf-8')[11:-11].split(' ')
return mid
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~ class BadLoginException ~~
class BadLoginException(BaseException):
pass
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~ class BadLoginException ~~
class BadHostException(BaseException):
pass

170
psr/ini.py Normal file
View File

@ -0,0 +1,170 @@
from re import split as regsplit
from psr.sys import Sys, Io, Const
from psr.log import Log
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~ class IniFile ~~
class IniFile:
"""Read and write inifile"""
@Log(Const.LOG_BUILD)
def __init__(self, path):
""""""
self.path = path
self.dic = {}
self.read()
@Log(Const.LOG_DEBUG)
def isEmpty(self):
""""""
return len(self.dic)==0
@Log(Const.LOG_DEBUG)
def has(self, key, section='main'):
""""""
d = self.hasSection(section) and (key in self.dic[section])
return d
@Log(Const.LOG_DEBUG)
def hasSection(self, section):
""""""
d = (section in self.dic)
return d
@Log(Const.LOG_DEBUG)
def get(self, key, section='main'):
""""""
return self.dic[section][key]
@Log(Const.LOG_DEBUG)
def set(self, key, val, section='main'):
""""""
v = None
if not section in self.dic:
self.dic[section] = {}
if key in self.dic[section]:
v = self.dic[section].pop(key)
self.dic[section][key] = str(val)
return v
@Log()
def rem(self, key, section):
""""""
v = None
if section in self.dic :
if key == '*' :
v = self.dic.pop(section)
elif key in self.dic[section]:
v = self.dic[section].pop(key)
return v
@Log()
def save(self,path=None):
""""""
Io.set_data(path if path is not None else self.path, '# last updated : '+str(Sys.datetime.now())+Const.LF+self.toString())
@Log(Const.LOG_DEBUG)
def getSection(self, section):
""""""
data = {}
for s in self.dic :
if s.startswith(section, 0) : data[s[len(section)+1:]] = self.dic[s]
return data
@Log(Const.LOG_DEBUG)
def getSections(self):
""""""
l = {}
for s in self.dic:
section = s.split('.')
if len(section)> 1 and not section[0] in l :
l[section[0]] = 1
return [k for i,k in enumerate(l)]
@Log(Const.LOG_DEBUG)
def toString(self, section='*'):
""""""
content = ''
main = ''
for s in self.dic:
if section=='*' or section+'.'==s[:len(section)+1]:
if s!='main':
content += Const.LF+'['+s+']'+Const.LF
for k in sorted(self.dic[s]):
k = k.rstrip(' ')
v = self.dic[s][k] if self.dic[s][k] is not None else ''
if s!='main' :
content += k+' = '+str(v)+Const.LF
else : main += k+' = '+str(v)+Const.LF
return main + content
@Log(Const.LOG_DEBUG)
def print(self, section='*', withoutSectionName=False):
""""""
if section=='main' or section=='*' :
self.printSection('main', withoutSectionName)
for s in self.dic:
if section=='*' or section+'.'==s[:len(section)+1]:
if s!='main':
self.printSection(s, withoutSectionName)
@Log(Const.LOG_DEBUG)
def printSection(self, sectionName, withoutSectionName=False):
""""""
if sectionName!='main':
Sys.dprint()
if not withoutSectionName :
Sys.print('['+sectionName+']', Sys.Clz.fgB3)
else:
Sys.print('['+sectionName.split('.')[1]+']', Sys.Clz.fgB3)
if sectionName in self.dic :
for k in sorted(self.dic[sectionName]):
k = k.rstrip(' ')
a = ''
Sys.print(k.ljust(10,' ')+' = ' , Sys.Clz.fgn7, False)
if self.dic[sectionName][k] is not None :
if len(self.dic[sectionName][k]) > 98: a = ''
if Sys.isUnix() or k is not 'key' :
Sys.print(self.dic[sectionName][k][:98]+a, Sys.Clz.fgN2)
else:
Sys.print('key is masked', Sys.Clz.fgb1)
@Log()
def read(self):
""""""
try:
with Io.rfile(self.path, False) as fi:
csection = 'main'
self.dic[csection] = {}
for l in fi:
l = l.rstrip().lstrip()
if len(l) > 0 and not l[0]=='#' :
d = regsplit(' *= *', l , 1)
if len(d)> 1:
self.dic[csection][d[0]] = d[1] if d[1] is not None else ''
elif len(l)>0 and l[0]=='[':
csection = l.strip('[]')
self.dic[csection] = {}
except IOError :
pass
@Log()
def delete(self):
Io.removeFile(self.path)
self.dic = {}

View File

@ -86,7 +86,7 @@ class Log:
if not (isinstance(a, str) or isinstance(a, bytes)): if not (isinstance(a, str) or isinstance(a, bytes)):
a = str(a) a = str(a)
if len(a) > Sys.g.LOG_LIM_ARG_LENGTH : if len(a) > Sys.g.LOG_LIM_ARG_LENGTH :
args[i] = a[:Sys.g.LOG_LIM_ARG_LENGTH]+'...' if isinstance(a, str) else b'...' args[i] = a[:Sys.g.LOG_LIM_ARG_LENGTH]+'' if isinstance(a, str) else bytes('','utf-8')
args = str(args)[1:-1] args = str(args)[1:-1]
if args[-1:] == ',' : args = args[:-1] if args[-1:] == ',' : args = args[:-1]
return args return args

View File

@ -48,10 +48,10 @@ class Sys:
"""""" """"""
from platform import system as getSysName from platform import system as getSysName
from os import system as sysCall, remove as removeFile, makedirs, sep, getpid from os import system as sysCall, remove as removeFile, makedirs, sep, getpid, listdir
from getpass import getuser as getUserLogin from getpass import getuser as getUserLogin
from time import strftime, mktime, time, localtime, sleep from time import strftime, mktime, time, localtime, sleep
from datetime import datetime from datetime import datetime, timedelta
from sys import exit from sys import exit
from os.path import abspath, dirname, join, realpath, basename, getsize, isdir, splitext from os.path import abspath, dirname, join, realpath, basename, getsize, isdir, splitext
from math import log, floor, ceil from math import log, floor, ceil
@ -164,6 +164,8 @@ class Sys:
"""Give a human representation of bytes size `b` """Give a human representation of bytes size `b`
:Returns: `str` :Returns: `str`
""" """
if b is None or b=='': return '0'
else :b = int(b)
units = [Const.UNIT_SHORT_B, Const.UNIT_SHORT_KIB, Const.UNIT_SHORT_MIB, Const.UNIT_SHORT_GIB, Const.UNIT_SHORT_TIB]; units = [Const.UNIT_SHORT_B, Const.UNIT_SHORT_KIB, Const.UNIT_SHORT_MIB, Const.UNIT_SHORT_GIB, Const.UNIT_SHORT_TIB];
b = max(b,0); b = max(b,0);
if b == 0 : lb= 0 if b == 0 : lb= 0
@ -261,6 +263,7 @@ class Sys:
@staticmethod @staticmethod
def dprint(d='',end=Const.LF, dbcall=False): def dprint(d='',end=Const.LF, dbcall=False):
"""""" """"""
dbcall = Sys.g.QUIET
if not dbcall : if not dbcall :
if not Sys.g.GUI or Sys.g.GUI_PRINT_STDOUT : if not Sys.g.GUI or Sys.g.GUI_PRINT_STDOUT :
if Sys.g.RLOCK is not None : if Sys.g.RLOCK is not None :
@ -309,11 +312,16 @@ class Sys:
return bdata return bdata
@staticmethod
def getDelta(t):
v = ''.join(['{:.5f}'.format(Sys.time()-(Sys.mktime(t.timetuple())+1e-6*t.microsecond)),' s'])
return v
@staticmethod @staticmethod
def pdelta(t, label='', dbcall= False): def pdelta(t, label='', dbcall= False):
"""""" """"""
if len(label)>0 and not dbcall : Sys.print(label+' ', Sys.CLZ_IO, False) if len(label)>0 and not dbcall : Sys.print(label+' ', Sys.CLZ_IO, False)
v = ''.join(['{:.5f}'.format(Sys.time()-(Sys.mktime(t.timetuple())+1e-6*t.microsecond)),' s']) v = Sys.getDelta(t)
if not dbcall : if not dbcall :
Sys.print(v, Sys.CLZ_DELTA) Sys.print(v, Sys.CLZ_DELTA)