1
0
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:
Adrien Bourmault 2019-08-01 16:52:36 +02:00 committed by GitHub
parent 529494784a
commit c2e1ff6c8e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 194 additions and 42 deletions

View File

@ -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'

View File

@ -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()

View File

@ -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:
@ -321,11 +337,12 @@ class mainWindow(Tk):
if not regex.fullmatch(event.char):
self.logOnTerm("Caractère non accepté !\n")
return "break"
# Adds the entry
self.mrzChar = self.termtext.get("1.0", "end")[:-1] + event.char + '\n'
# Adds the entry
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

View File

@ -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