mirror of
https://gitlab.os-k.eu/neox/CNIRevelator.git
synced 2023-08-25 14:03:10 +02:00
Finished the analyzer
This commit is contained in:
parent
529494784a
commit
c2e1ff6c8e
@ -37,7 +37,7 @@ CNIRFolder = os.getcwd()
|
||||
CNIRLColor = "#006699"
|
||||
CNIRName = "CNIRevelator {}".format(verstring)
|
||||
CNIRCryptoKey = '82Xh!efX3#@P~2eG'
|
||||
CNIRNewVersion = True
|
||||
CNIRNewVersion = False
|
||||
|
||||
CNIRConfig = CNIRFolder + '\\config\\conf.ig'
|
||||
CNIRErrLog = CNIRFolder + '\\logs\\error.log'
|
||||
|
@ -32,7 +32,7 @@ import logger # logger.py
|
||||
import globs # globs.py
|
||||
|
||||
|
||||
controlKeys = ["Right", "Left", "Up", "Down", "Home", "End", "Delete", "BackSpace", "Inser", "Shift_L", "Shift_R", "Control_R", "Control_L"]
|
||||
controlKeys = ["Right", "Left", "Up", "Down", "Home", "End", "Delete", "Inser", "Shift_L", "Shift_R", "Control_R", "Control_L"]
|
||||
|
||||
class DocumentAsk(Toplevel):
|
||||
|
||||
@ -96,6 +96,7 @@ class LoginDialog(Toplevel):
|
||||
x = ws / 2 - w / 2
|
||||
y = hs / 2 - h / 2
|
||||
self.geometry('%dx%d+%d+%d' % (w, h, x, y))
|
||||
self.bind("<Return>", self.connecti)
|
||||
|
||||
def connecti(self):
|
||||
self.login = self.entry_login.get().strip()
|
||||
|
130
src/main.py
130
src/main.py
@ -53,6 +53,7 @@ class mainWindow(Tk):
|
||||
self.mrzChar = ''
|
||||
self.mrzDecided = False
|
||||
self.Tags = []
|
||||
self.compliance = True
|
||||
|
||||
# Get the screen size
|
||||
ws = self.winfo_screenwidth()
|
||||
@ -125,6 +126,21 @@ class mainWindow(Tk):
|
||||
self.pays['text'] = 'Inconnu(e)'
|
||||
self.indic['text'] = 'Inconnu(e)'
|
||||
|
||||
|
||||
self.infoList = \
|
||||
{
|
||||
"NOM" : self.nom,
|
||||
"PRENOM" : self.prenom,
|
||||
"BDATE" : self.bdate,
|
||||
"DDATE" : self.ddate,
|
||||
"EDATE" : self.edate,
|
||||
"NO" : self.no,
|
||||
"SEX" : self.sex,
|
||||
"NAT" : self.nat,
|
||||
"PAYS" : self.pays,
|
||||
"INDIC" : self.indic,
|
||||
}
|
||||
|
||||
# The STATUS indicator
|
||||
self.STATUT = ttk.Labelframe(self, text='Statut')
|
||||
self.STATUT.grid_columnconfigure(0, weight=1)
|
||||
@ -224,11 +240,11 @@ class mainWindow(Tk):
|
||||
# Some bindings
|
||||
self.termtext.bind('<Key>', self.entryValidation)
|
||||
self.termtext.bind('<<Paste>>', self.pasteValidation)
|
||||
self.speed731text.bind('<Return>', self.speedValidation)
|
||||
self.speed731text.bind('<Control_R>', self.speedValidation)
|
||||
self.update()
|
||||
logfile.printdbg('Initialization successful')
|
||||
|
||||
def stringValidation(self):
|
||||
def stringValidation(self, char):
|
||||
# analysis
|
||||
# If we must decide the type of the document
|
||||
if not self.mrzDecided:
|
||||
@ -244,33 +260,30 @@ class mainWindow(Tk):
|
||||
|
||||
self.wait_window(invite)
|
||||
|
||||
self.logOnTerm("Document detecté : {}".format(candidates[invite.choice][2]))
|
||||
self.logOnTerm("Document detecté : {}\n".format(candidates[invite.choice][2]))
|
||||
self.mrzDecided = candidates[invite.choice]
|
||||
|
||||
elif len(candidates) == 1:
|
||||
self.logOnTerm("Document detecté : {}".format(candidates[0][2]))
|
||||
self.logOnTerm("Document detecté : {}\n".format(candidates[0][2]))
|
||||
self.mrzDecided = candidates[0]
|
||||
else:
|
||||
# break the line
|
||||
if (len(self.mrzChar) - 2 >= len(self.mrzDecided[0][0])) and ("\n" not in self.mrzChar[:-1]):
|
||||
# In case of there is no second line
|
||||
if len(self.mrzDecided[0][1]) == 0:
|
||||
self.mrzChar = self.termtext.get("1.0", "end")[:-2]
|
||||
self.mrzChar = self.termtext.get("1.0", "end")[:-1]
|
||||
self.termtext.delete("1.0","end")
|
||||
self.termtext.insert("1.0", self.mrzChar)
|
||||
self.nope = True
|
||||
self.termtext.insert("1.0", self.mrzChar[:-1])
|
||||
else:
|
||||
# In case of there is a second line
|
||||
self.mrzChar = self.termtext.get("1.0", "end")[:-1] + '\n'
|
||||
self.termtext.delete("1.0","end")
|
||||
self.termtext.insert("1.0", self.mrzChar)
|
||||
self.nope = True
|
||||
# stop when limit reached
|
||||
elif (len(self.mrzChar) - 3 >= 2 * len(self.mrzDecided[0][0])):
|
||||
self.mrzChar = self.termtext.get("1.0", "end")[:-2]
|
||||
self.mrzChar = self.termtext.get("1.0", "end")[:-1]
|
||||
self.termtext.delete("1.0","end")
|
||||
self.termtext.insert("1.0", self.mrzChar)
|
||||
|
||||
self.termtext.insert("1.0", self.mrzChar[:-1])
|
||||
# compute the control sum if needed
|
||||
self.computeSigma()
|
||||
|
||||
@ -278,10 +291,16 @@ class mainWindow(Tk):
|
||||
"""
|
||||
On the fly validation with regex
|
||||
"""
|
||||
print("go")
|
||||
|
||||
controlled = False
|
||||
|
||||
# get the cursor
|
||||
if self.mrzDecided:
|
||||
position = self.termtext.index(INSERT).split(".")
|
||||
pos = (int(position[0]) - 1) * len(self.mrzDecided[0][0]) + (int(position[1]) - 1)
|
||||
else:
|
||||
position = self.termtext.index(INSERT).split(".")
|
||||
pos = (int(position[1]) - 1)
|
||||
|
||||
# verifying that there is no Ctrl-C/Ctrl-V and others
|
||||
if event.state & 0x0004 and ( event.keysym == "c" or
|
||||
event.keysym == "v" or
|
||||
@ -298,9 +317,6 @@ class mainWindow(Tk):
|
||||
regex = re.compile("[^A-Z0-9<]")
|
||||
code = re.sub(regex, '', self.mrzChar)
|
||||
|
||||
position = self.termtext.index(INSERT).split(".")
|
||||
pos = (int(position[0]) - 1) * len(self.mrzDecided[0][0]) + (int(position[1]) - 1)
|
||||
|
||||
number = mrz.completeDocField(self.mrzDecided, code, pos) - 1
|
||||
|
||||
if number == 0:
|
||||
@ -322,10 +338,11 @@ class mainWindow(Tk):
|
||||
self.logOnTerm("Caractère non accepté !\n")
|
||||
return "break"
|
||||
# Adds the entry
|
||||
self.mrzChar = self.termtext.get("1.0", "end")[:-1] + event.char + '\n'
|
||||
tempChar = self.termtext.get("1.0", "end")[:-1]
|
||||
self.mrzChar = tempChar[:pos+1] + event.char + tempChar[pos+1:] + '\n'
|
||||
|
||||
# validation of the mrz string
|
||||
self.stringValidation()
|
||||
self.stringValidation(event.char)
|
||||
|
||||
def pasteValidation(self, event):
|
||||
"""
|
||||
@ -347,7 +364,7 @@ class mainWindow(Tk):
|
||||
for char in lines:
|
||||
self.termtext.insert("1.0", self.mrzChar)
|
||||
self.mrzChar = self.mrzChar + char
|
||||
self.stringValidation()
|
||||
self.stringValidation("")
|
||||
|
||||
return "break"
|
||||
|
||||
@ -365,6 +382,12 @@ class mainWindow(Tk):
|
||||
self.monlog['state'] = 'disabled'
|
||||
self.monlog.yview(END)
|
||||
|
||||
def clearTerm(self):
|
||||
self.monlog['state'] = 'normal'
|
||||
self.monlog.delete('1.0', 'end')
|
||||
self.monlog['state'] = 'disabled'
|
||||
self.monlog.yview(END)
|
||||
|
||||
def speedResultPrint(self, text):
|
||||
self.speedResult['state'] = 'normal'
|
||||
self.speedResult.delete("1.0", 'end')
|
||||
@ -417,24 +440,67 @@ class mainWindow(Tk):
|
||||
|
||||
parent=self)
|
||||
|
||||
# XXX
|
||||
def computeSigma(self):
|
||||
"""
|
||||
Launch the checksum computation, infos validation and display the results
|
||||
"""
|
||||
# the regex
|
||||
regex = re.compile("[^A-Z0-9<]")
|
||||
code = re.sub(regex, '', self.mrzChar)
|
||||
self.compliance = True
|
||||
|
||||
allSums = mrz.computeAllControlSum(self.mrzDecided, code)
|
||||
print("Code : {} | Sums : {}".format(code, allSums))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
allSums = mrz.computeAllControlSum(self.mrzDecided, code)["ctrlSumList"]
|
||||
#print("Code : _{}_ | Sums : {}".format(code, allSums))
|
||||
|
||||
self.termtext.tag_remove("conforme", "1.0", "end")
|
||||
self.termtext.tag_remove("nonconforme", "1.0", "end")
|
||||
|
||||
self.clearTerm()
|
||||
self.logOnTerm("Examen du document : {}\n\n".format(self.mrzDecided[2]))
|
||||
|
||||
for sum in allSums:
|
||||
x = sum[1] // len(self.mrzDecided[0][0]) +1
|
||||
y = sum[1] % len(self.mrzDecided[0][0])
|
||||
#print("index : {}.{}".format(x,y))
|
||||
#print("{} == {}".format(code[sum[1]], sum[2]))
|
||||
|
||||
self.logOnTerm("Somme de contrôle position {} : Lu {} VS Calculé {}\n".format(sum[1], code[sum[1]], sum[2]))
|
||||
|
||||
# if sum is facultative or if sum is ok
|
||||
if sum[3] or int(code[sum[1]]) == int(sum[2]):
|
||||
self.termtext.tag_add("conforme", "{}.{}".format(x,y), "{}.{}".format(x,y+1))
|
||||
self.termtext.tag_configure("conforme", background="green", foreground="white")
|
||||
else:
|
||||
self.termtext.tag_add("nonconforme", "{}.{}".format(x,y), "{}.{}".format(x,y+1))
|
||||
self.termtext.tag_configure("nonconforme", background="red", relief='raised', foreground="white")
|
||||
self.compliance = False
|
||||
|
||||
|
||||
if self.compliance == True:
|
||||
self.STATUStxt['text'] = 'CONFORME'
|
||||
self.STATUStxt['fg'] = "green"
|
||||
else:
|
||||
self.STATUStxt['text'] = 'NON CONFORME'
|
||||
self.STATUStxt['fg'] = "red"
|
||||
|
||||
# get the infos
|
||||
docInfos = mrz.getDocInfos(self.mrzDecided, code)
|
||||
#print(docInfos)
|
||||
# display the infos
|
||||
for key in [ e for e in docInfos ]:
|
||||
print(docInfos[key])
|
||||
if key in ["CODE", "CTRL"]:
|
||||
continue
|
||||
if not docInfos[key] == False:
|
||||
self.infoList[key]['text'] = docInfos[key]
|
||||
self.infoList[key]['background'] = self['background']
|
||||
self.infoList[key]['foreground'] = "black"
|
||||
else:
|
||||
self.infoList[key]['background'] = "red"
|
||||
self.infoList[key]['foreground'] = "white"
|
||||
self.infoList[key]['text'] = "NC"
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
|
99
src/mrz.py
99
src/mrz.py
@ -26,6 +26,8 @@
|
||||
|
||||
import re
|
||||
import logger # logger.py
|
||||
import re
|
||||
import datetime
|
||||
|
||||
## SEX CODES
|
||||
sexcode = {'M':'Homme', 'F':'Femme', 'X':'Non spécifié'}
|
||||
@ -717,13 +719,12 @@ I__ = [
|
||||
]
|
||||
|
||||
IDFR = [
|
||||
["11222333333333333333333333333344444E", "555566677777899999999999999AAAAAABCD"],
|
||||
["112223333333333333333333333333444444", "555566677777899999999999999AAAAAABCD"],
|
||||
{
|
||||
"1": ["2", "CODE", "ID"],
|
||||
"2": ["3", "PAYS", "FRA"],
|
||||
"3": ["25", "NOM", "([A-Z]|<)+"],
|
||||
"4": ["6", "NOINT", ".+"],
|
||||
"E": ["1", "CTRL", "[0-9]", "1234"],
|
||||
"5": ["4", "DDATE", "[0-9]+"],
|
||||
"6": ["3", "NOINT2", "[0-9]+"],
|
||||
"7": ["5", "NOINT3", "[0-9]+"],
|
||||
@ -901,8 +902,10 @@ def computeControlSum(code):
|
||||
def computeAllControlSum(doc, code):
|
||||
"""
|
||||
This function computes all the ctrl sums on a MRZ string and returns all the results
|
||||
it returns the misc infos about the document too
|
||||
"""
|
||||
ctrlSumList = []
|
||||
facult = False
|
||||
|
||||
# iteration on each char of the given MRZ
|
||||
for charPos in range(len(code)):
|
||||
@ -924,12 +927,94 @@ def computeAllControlSum(doc, code):
|
||||
ctrlSum = computeControlSum(codeChain)
|
||||
#print("SUM : {} vs {}".format(code[charPos], ctrlSum))
|
||||
|
||||
ctrlSumList += [ (field, charPos, ctrlSum) ]
|
||||
|
||||
return ctrlSumList
|
||||
|
||||
|
||||
ctrlSumList += [ (field, charPos, ctrlSum, facult) ]
|
||||
|
||||
if doc[1][field][1] == "CTRLF":
|
||||
#print("{} is CTRL field {}".format(code[charPos], field))
|
||||
|
||||
codeChain = ""
|
||||
# iteration on the fields to control
|
||||
for pos in range(len(code)):
|
||||
target = getDocString(doc)[pos]
|
||||
if target in doc[1][field][3]:
|
||||
#print("__field : {} {} {} {}".format(target, pos, field, doc[1][field][3]))
|
||||
codeChain += code[pos]
|
||||
|
||||
#print("chain to control : _{}_".format(codeChain))
|
||||
|
||||
ctrlSum = computeControlSum(codeChain)
|
||||
#print("SUM : {} vs {}".format(code[charPos], ctrlSum))
|
||||
|
||||
if code[charPos] == "<":
|
||||
facult = True
|
||||
|
||||
ctrlSumList += [ (field, charPos, ctrlSum, facult) ]
|
||||
|
||||
return {
|
||||
"ctrlSumList" : ctrlSumList
|
||||
}
|
||||
|
||||
|
||||
def getDocInfos(doc, code):
|
||||
# get all the types of infos that are in the document doc
|
||||
infoTypes = [ (doc[1][field][1], limits(doc[0][0] + doc[0][1], field)) for field in doc[1] ]
|
||||
|
||||
res = {}
|
||||
|
||||
for field in infoTypes:
|
||||
|
||||
value = code[ field[1][0] : field[1][1] ]
|
||||
|
||||
# State code
|
||||
if field[0] == 'PAYS' or field[0] == 'NAT':
|
||||
try:
|
||||
if len(value) == 3 and value[-1] != "<":
|
||||
res[field[0]] = landcode3[value]
|
||||
elif len(value) == 3 and value[-1] == "<":
|
||||
res[field[0]] = landcode2[value[:-1]]
|
||||
else:
|
||||
res[field[0]] = landcode2[value]
|
||||
except KeyError:
|
||||
res[field[0]] = False
|
||||
|
||||
# Dates
|
||||
elif field[0][1:] == 'DATE':
|
||||
# size adaptation
|
||||
if len(value) == 6:
|
||||
value = "{}/{}/{}".format(value[4:6], value[2:4], value[0:2])
|
||||
elif len(value) == 4:
|
||||
value = "{}/{}/{}".format("01", value[2:4], value[0:2])
|
||||
|
||||
# date validation
|
||||
try:
|
||||
datetime.datetime.strptime(value,"%d/%m/%y")
|
||||
except ValueError:
|
||||
print(value)
|
||||
if value != "":
|
||||
res[field[0]] = False
|
||||
else:
|
||||
res[field[0]] = value
|
||||
|
||||
# Numbers
|
||||
elif field[0][:-1] == 'NOINT':
|
||||
try:
|
||||
res["NO"] += value
|
||||
except KeyError:
|
||||
res["NO"] = value
|
||||
elif field[0] == 'NOINT':
|
||||
try:
|
||||
res["NO"] += value
|
||||
except KeyError:
|
||||
res["NO"] = value
|
||||
|
||||
elif field[0] == 'FACULT':
|
||||
res["INDIC"] += value
|
||||
# All other cases
|
||||
else:
|
||||
if value != "":
|
||||
res[field[0]] = value.replace("<", " ").strip()
|
||||
|
||||
return res
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user