Merge pull request #14 from neox95/v3.1

V3.1.1 release
This commit is contained in:
Adrien Bourmault 2019-08-20 10:29:59 +02:00 committed by GitHub
commit 9bc808d785
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 2159 additions and 894 deletions

View File

@ -1,2 +1,2 @@
# ver|url|checksum, and | as separator, one version per || # ver|url|checksum, and | as separator, one version per ||
3.1.2|https://github.com/neox95/CNIRevelator/releases/download/3.1.1/CNIRevelator.zip|cb2f4999e7265297008074e0e2beacbb2943a004||

View File

@ -23,22 +23,26 @@
* along with CNIRevelator. If not, see <https:*www.gnu.org/licenses/>. * * along with CNIRevelator. If not, see <https:*www.gnu.org/licenses/>. *
******************************************************************************** ********************************************************************************
""" """
# Import critical files
import sys
import os import os
import subprocess
import threading import threading
import traceback
import psutil
import launcher # launcher.py" import lang # lang.py
import updater # updater.py
import globs # globs.py
import pytesseract # pytesseract.py
import logger # logger.py import logger # logger.py
import globs # globs.py
import critical # critical.py
# Import all other files and crash if necessary
try:
from main import * # main.py import launcher # launcher.py"
import updater # updater.py
import pytesseract # pytesseract.py
import ihm # ihm.py
from tkinter.messagebox import *
from tkinter import *
except:
critical.crashCNIR()
# Global handler # Global handler
logfile = logger.logCur logfile = logger.logCur
@ -59,15 +63,17 @@ def main():
text = 'Tesseract version ' + str(tesser_version) + ' Licensed Apache 2004 successfully initiated\n' text = 'Tesseract version ' + str(tesser_version) + ' Licensed Apache 2004 successfully initiated\n'
mainw.logOnTerm(text) mainw.logOnTerm(text)
mainw.logOnTerm('\n\nEntrez la première ligne de MRZ svp \n') mainw.logOnTerm('\n\n{} \n'.format(lang.all[globs.CNIRlang]["Please type a MRZ or open a scan"]))
# changelog
if globs.CNIRNewVersion: if globs.CNIRNewVersion:
showinfo('Changelog : résumé de mise à jour', ('Version du logiciel : CNIRevelator ' + globs.verstring_full + '\n\n' + globs.changelog), parent=mainw) mainw.after_idle(mainw.showChangeLog)
logfile.printdbg('main() : **** Launching App_main() ****') logfile.printdbg('main() : **** Launching App_main() ****')
try: try:
mainw.mainloop() mainw.mainloop()
except Exception as e: except Exception as e:
showerror("CNIRevelator Fatal Error", "An error has occured : {}".format(e), parent=mainw) showerror(lang.all[globs.CNIRlang]["CNIRevelator Fatal Error"], "{} : {}".format(lang.all[globs.CNIRlang]["An error has occured"],e), parent=mainw)
logfile.printdbg('main() : **** Ending App_main() ****') logfile.printdbg('main() : **** Ending App_main() ****')
logfile.printdbg('*** CNIRevelator LOGFILE. Goodbye World ! ***') logfile.printdbg('*** CNIRevelator LOGFILE. Goodbye World ! ***')
@ -75,30 +81,45 @@ def main():
## BOOTSTRAP OF CNIREVELATOR ## BOOTSTRAP OF CNIREVELATOR
try: try:
launcherThread = threading.Thread(target=updater.umain, daemon=False)
launcher.lmain(launcherThread)
except Exception:
updater.exitProcess(1)
if updater.UPDATE_IS_MADE: try:
# Launch app ! # LANGUAGE
args = updater.UPATH + '\\CNIRevelator.exe ' + globs.CNIRFolder lang.readLang()
cd = updater.UPATH except:
for i in range(0,3): critical.crashCNIR()
try: updater.exitProcess(1)
updater.spawnProcess(args, cd)
except:
time.sleep(3)
continue
break
updater.exitProcess(0)
# Here we go ! from main import * # main.py
try: # GO
main() try:
except Exception as e: launcherThread = threading.Thread(target=updater.umain, daemon=False)
traceback.print_exc(file=sys.stdout) launcher.lmain(launcherThread)
except Exception:
critical.crashCNIR()
updater.exitProcess(1)
if updater.UPDATE_IS_MADE:
# Launch app !
args = updater.UPATH + '\\CNIRevelator.exe' + " DELETE " + globs.CNIRFolder
cd = updater.UPATH
for i in range(0,3):
try:
updater.spawnProcess(args, cd)
except:
time.sleep(3)
continue
break
updater.exitProcess(0)
# Here we go !
try:
main()
except Exception as e:
critical.crashCNIR()
updater.exitProcess(1)
except:
critical.crashCNIR()
updater.exitProcess(0) updater.exitProcess(0)

66
src/critical.py Normal file
View File

@ -0,0 +1,66 @@
"""
********************************************************************************
* CNIRevelator *
* *
* Desc: Critical Stuff for CNIRevelator *
* *
* Copyright © 2018-2019 Adrien Bourmault (neox95) *
* *
* This file is part of CNIRevelator. *
* *
* CNIRevelator is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* any later version. *
* *
* CNIRevelator is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY*without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with CNIRevelator. If not, see <https:*www.gnu.org/licenses/>. *
********************************************************************************
"""
from tkinter.messagebox import *
from importlib import reload
from tkinter import *
import webbrowser
import traceback
import psutil
import os
import lang # lang.py
import logger # logger.py
import globs # globs.py
def crashCNIR(shutdown=True):
"""
very last solution
"""
try:
root = Tk()
root.withdraw()
logfile = logger.logCur
logfile.printerr("FATAL ERROR : see traceback below.\n{}".format(traceback.format_exc()))
showerror(lang.all[globs.CNIRlang]["CNIRevelator Fatal Eror"], lang.all[globs.CNIRlang]["CNIRevelator crashed because a fatal error occured. View log for more infos and please open an issue on Github"], parent=root)
res = askquestion(lang.all[globs.CNIRlang]["CNIRevelator Fatal Eror"], lang.all[globs.CNIRlang]["Would you like to open the log file ?"], parent=root)
if res == "yes":
webbrowser.open_new(globs.CNIRErrLog)
res = askquestion(lang.all[globs.CNIRlang]["CNIRevelator Fatal Eror"], lang.all[globs.CNIRlang]["Would you like to open an issue on Github to report this bug ?"], parent=root)
if res == "yes":
webbrowser.open_new("https://github.com/neox95/CNIRevelator/issues")
root.destroy()
# Quit ?
if not shutdown:
return
# Quit totally without remain in memory
for process in psutil.process_iter():
if process.pid == os.getpid():
process.terminate()
sys.exit(arg)
except:
traceback.print_exc()

View File

@ -32,9 +32,11 @@ from Crypto.Cipher import AES
from requests import Session from requests import Session
from time import time from time import time
import critical # critical.py
import logger # logger.py import logger # logger.py
import globs # globs.py import globs # globs.py
import ihm # ihm.py import ihm # ihm.py
import lang # lang.py
class AESCipher(object): class AESCipher(object):
@ -184,8 +186,8 @@ class newdownload:
reducedFilename = filename.split("\\")[-1] reducedFilename = filename.split("\\")[-1]
launcherWindow.printmsg('Downloading {}'.format(title)) launcherWindow.printmsg('{} {}'.format(lang.all[globs.CNIRlang]["Downloading"], title))
logfile.printdbg('Requesting download of {}'.format(reducedFilename)) logfile.printdbg('{} {}'.format("Downloading", reducedFilename))
try: try:
os.remove(filename) os.remove(filename)
@ -201,12 +203,12 @@ class newdownload:
launcherWindow.progressBar.stop() launcherWindow.progressBar.stop()
launcherWindow.progressBar.configure(mode='determinate', value=(int(Percent)), maximum=100) launcherWindow.progressBar.configure(mode='determinate', value=(int(Percent)), maximum=100)
launcherWindow.printmsg('Downloading {}'.format(title) + ' : {:4.2f} %'.format(Percent)) launcherWindow.printmsg('{} {}'.format(lang.all[globs.CNIRlang]["Downloading"], title) + ' : {:4.2f} %'.format(Percent))
launcherWindow.progressBar.configure(mode='indeterminate', value=0, maximum=20) launcherWindow.progressBar.configure(mode='indeterminate', value=0, maximum=20)
launcherWindow.progressBar.start() launcherWindow.progressBar.start()
logfile.printdbg('Successful retrieved {}'.format(filename)) logfile.printdbg('{} {}'.format(lang.all[globs.CNIRlang]["Successful retrieved"], filename))
return filename return filename

View File

@ -26,12 +26,9 @@ import os
# CNIRevelator version # CNIRevelator version
verType = "final release" verType = "final release"
version = [3, 1, 0] version = [3, 1, 1]
verstring_full = "{}.{}.{} {}".format(version[0], version[1], version[2], verType) verstring_full = "{}.{}.{} {}".format(version[0], version[1], version[2], verType)
verstring = "{}.{}".format(version[0], version[1]) verstring = "{}.{}".format(version[0], version[1])
debug = True
changelog = "Version 3.1.0 \nMise-à-jour majeure avec les progressions suivantes :\n- Modifications cosmétiques de l'interface utilisateur\n- Stabilisation des changements effectués sur la version mineure 3.0 : interface utilisateur, OCR, VISA A et B, logging"
CNIRTesserHash = '5b58db27f7bc08c58a2cb33d01533b034b067cf8' CNIRTesserHash = '5b58db27f7bc08c58a2cb33d01533b034b067cf8'
CNIRFolder = os.getcwd() CNIRFolder = os.getcwd()
@ -47,3 +44,28 @@ CNIRMainLog = CNIRFolder + '\\logs\\main.log'
CNIRUrlConfig = CNIRFolder + '\\config\\urlconf.ig' CNIRUrlConfig = CNIRFolder + '\\config\\urlconf.ig'
CNIRVerStock = CNIRFolder + '\\downloads\\versions.lst' CNIRVerStock = CNIRFolder + '\\downloads\\versions.lst'
CNIREnv = CNIRFolder + '\\Data\\' CNIREnv = CNIRFolder + '\\Data\\'
CNIRTesserHash = '5b58db27f7bc08c58a2cb33d01533b034b067cf8'
CNIRFolder = os.path.dirname(os.path.realpath(__file__))
CNIRLColor = "#006699"
CNIRName = "CNIRevelator {}".format(verstring)
CNIRCryptoKey = '82Xh!efX3#@P~2eG'
CNIRLangFile = CNIRFolder + '\\config\\lang.ig'
CNIRlang = "fr"
CNIRConfig = CNIRFolder + '\\config\\conf.ig'
CNIRTesser = CNIRFolder + '\\Tesseract-OCR4\\'
CNIRErrLog = CNIRFolder + '\\logs\\error.log'
CNIRMainLog = CNIRFolder + '\\logs\\main.log'
CNIRUrlConfig = CNIRFolder + '\\config\\urlconf.ig'
CNIRVerStock = CNIRFolder + '\\downloads\\versions.lst'
CNIREnv = CNIRFolder + '\\Data\\'
CNIRBetaURL = "https://raw.githubusercontent.com/neox95/CNIRevelator/v3.1/VERSIONS.LST"
CNIRDefaultURL = "https://raw.githubusercontent.com/neox95/CNIRevelator/master/VERSIONS.LST"
CNIRNewVersion = False
CNIROpenFile = False
debug = True

View File

@ -1,4 +1,4 @@
""" """
******************************************************************************** ********************************************************************************
* CNIRevelator * * CNIRevelator *
* * * *
@ -23,19 +23,22 @@
******************************************************************************** ********************************************************************************
""" """
from tkinter import *
import webbrowser
from tkinter.messagebox import * from tkinter.messagebox import *
from tkinter import *
from tkinter import filedialog from tkinter import filedialog
from tkinter import ttk from tkinter import ttk
import cv2
import PIL.Image, PIL.ImageTk import PIL.Image, PIL.ImageTk
import traceback import traceback
import webbrowser
import cv2
import critical # critical.py
import logger # logger.py import logger # logger.py
import globs # globs.py import globs # globs.py
import lang # lang.py import lang # lang.py
import updater # updater.py
import critical # critical.py
controlKeys = ["Escape", "Right", "Left", "Up", "Down", "Home", "End", "BackSpace", "Delete", "Inser", "Shift_L", "Shift_R", "Control_R", "Control_L"] controlKeys = ["Escape", "Right", "Left", "Up", "Down", "Home", "End", "BackSpace", "Delete", "Inser", "Shift_L", "Shift_R", "Control_R", "Control_L"]
@ -117,21 +120,22 @@ class LoginDialog(Toplevel):
self.login = '' self.login = ''
super().__init__(parent) super().__init__(parent)
self.title(lang.all[globs.CNIRlang]["Connection"]) self.title(lang.all[globs.CNIRlang]["Connection"])
Label(self, text='IPN : ').pack() self["background"] = "white"
self.entry_login = Entry(self) Label(self, text='IPN : ', bg="white").pack(fill=Y)
self.entry_login = ttk.Entry(self)
self.entry_login.insert(0, '') self.entry_login.insert(0, '')
self.entry_login.pack() self.entry_login.pack()
Label(self, text='{} : '.format(lang.all[globs.CNIRlang]["Password"])).pack() Label(self, text='{} : '.format(lang.all[globs.CNIRlang]["Password"]), bg="white").pack(fill=Y)
self.entry_pass = Entry(self, show='*') self.entry_pass = ttk.Entry(self, show='*')
self.entry_pass.insert(0, '') self.entry_pass.insert(0, '')
self.entry_pass.pack() self.entry_pass.pack(fill=Y)
Button(self, text=lang.all[globs.CNIRlang]["Connection"], command=(self.connecti)).pack() ttk.Button(self, text=lang.all[globs.CNIRlang]["Connection"], command=(self.connecti)).pack(fill=Y, pady=10)
self.update()
self.resizable(width=False, height=False) self.resizable(width=False, height=False)
ws = self.winfo_screenwidth() ws = self.winfo_screenwidth()
hs = self.winfo_screenheight() hs = self.winfo_screenheight()
w = hs / 10 w = self.winfo_reqwidth() + 5
h = ws / 18 h = self.winfo_reqheight()
self.update()
if getattr(sys, 'frozen', False): if getattr(sys, 'frozen', False):
self.iconbitmap(sys._MEIPASS + '\\id-card.ico\\id-card.ico') self.iconbitmap(sys._MEIPASS + '\\id-card.ico\\id-card.ico')
else: else:
@ -146,6 +150,124 @@ class LoginDialog(Toplevel):
self.key = self.entry_pass.get().strip() self.key = self.entry_pass.get().strip()
self.destroy() self.destroy()
class ChangelogDialog(Toplevel):
def __init__(self, parent, text):
super().__init__(parent)
self.title(lang.all[globs.CNIRlang]["Show Changelog"])
self["background"] = "white"
self.grid_columnconfigure(0, weight=1)
self.grid_rowconfigure(0, weight=1)
self.text = Text(self, wrap='word', width=55, height=15, borderwidth=0, font="TkDefaultFont", bg="white")
self.text.grid(column=0, row=0, sticky='EWNS', padx=5, pady=5)
ttk.Button(self, text="OK", command=(self.oki)).grid(column=0, row=1, pady=5)
self.scrollb = ttk.Scrollbar(self, command=(self.text.yview))
self.scrollb.grid(column=1, row=0, sticky='EWNS', padx=5, pady=5)
self.text['yscrollcommand'] = self.scrollb.set
self.text.insert('end', text)
self.text['state'] = 'disabled'
self.update()
self.resizable(width=False, height=False)
ws = self.winfo_screenwidth()
hs = self.winfo_screenheight()
w = self.winfo_reqwidth() + 5
h = self.winfo_reqheight()
if getattr(sys, 'frozen', False):
self.iconbitmap(sys._MEIPASS + '\\id-card.ico\\id-card.ico')
else:
self.iconbitmap('id-card.ico')
x = ws / 2 - w / 2
y = hs / 2 - h / 2
self.geometry('%dx%d+%d+%d' % (w, h, x, y))
self.bind("<Return>", self.oki)
def oki(self, event=None):
self.destroy()
class langDialog(Toplevel):
def __init__(self, parent):
super().__init__(parent)
self.title(lang.all[globs.CNIRlang]["Language"])
Label(self, text=lang.all[globs.CNIRlang]["Please choose your language : "]).pack(fill=Y)
vals = [i for i in lang.all]
for i in range(len(lang.all)):
ttk.Radiobutton(self, text=vals[i], command=self.createRegister(i), value=vals[i]).pack(fill=Y)
ttk.Button(self, text="OK", command=(self.oki)).pack(fill=Y, pady=5)
self.update()
self.resizable(width=False, height=False)
ws = self.winfo_screenwidth()
hs = self.winfo_screenheight()
w = self.winfo_reqwidth() + 5
h = self.winfo_reqheight()
if getattr(sys, 'frozen', False):
self.iconbitmap(sys._MEIPASS + '\\id-card.ico\\id-card.ico')
else:
self.iconbitmap('id-card.ico')
x = ws / 2 - w / 2
y = hs / 2 - h / 2
self.geometry('%dx%d+%d+%d' % (w, h, x, y))
self.bind("<Return>", self.oki)
def oki(self, event=None):
self.destroy()
def createRegister(self, i):
def register():
lang.updateLang([j for j in lang.all][i])
return register
class updateSetDialog(Toplevel):
def __init__(self, parent):
super().__init__(parent)
self.title(lang.all[globs.CNIRlang]["Update options"])
Label(self, text=lang.all[globs.CNIRlang]["Please choose your update channel : "]).pack(fill=Y)
self.vals = ["Stable", "Beta"]
vals = self.vals
for i in range(len(vals)):
ttk.Radiobutton(self, text=vals[i], command=self.createRegister(i), value=vals[i]).pack(fill=Y)
ttk.Button(self, text="OK", command=(self.oki)).pack(fill=Y, pady=5)
self.update()
self.resizable(width=False, height=False)
ws = self.winfo_screenwidth()
hs = self.winfo_screenheight()
w = self.winfo_reqwidth() + 5
h = self.winfo_reqheight()
if getattr(sys, 'frozen', False):
self.iconbitmap(sys._MEIPASS + '\\id-card.ico\\id-card.ico')
else:
self.iconbitmap('id-card.ico')
x = ws / 2 - w / 2
y = hs / 2 - h / 2
self.geometry('%dx%d+%d+%d' % (w, h, x, y))
self.bind("<Return>", self.oki)
def oki(self, event=None):
self.destroy()
def createRegister(self, i):
def register():
updater.updateChannel(self.vals[i])
return register
class LauncherWindow(Tk): class LauncherWindow(Tk):
def __init__(self): def __init__(self):
@ -153,6 +275,12 @@ class LauncherWindow(Tk):
Tk.__init__(self) Tk.__init__(self)
self.resizable(width=False, height=False) self.resizable(width=False, height=False)
# icon
if getattr(sys, 'frozen', False):
self.iconbitmap(sys._MEIPASS + '\\id-card.ico\\id-card.ico')
else:
self.iconbitmap('id-card.ico')
# Setting up the geometry # Setting up the geometry
ws = self.winfo_screenwidth() ws = self.winfo_screenwidth()
hs = self.winfo_screenheight() hs = self.winfo_screenheight()
@ -201,11 +329,6 @@ class LauncherWindow(Tk):
self.update() self.update()
self.progressBar.grid(row=1, sticky='S') self.progressBar.grid(row=1, sticky='S')
if getattr(sys, 'frozen', False):
self.iconbitmap(sys._MEIPASS + '\\id-card.ico\\id-card.ico')
else:
self.iconbitmap('id-card.ico')
logfile = logger.logCur logfile = logger.logCur
logfile.printdbg('Launcher IHM successful') logfile.printdbg('Launcher IHM successful')
self.protocol('WM_DELETE_WINDOW', lambda : 0) self.protocol('WM_DELETE_WINDOW', lambda : 0)
@ -233,22 +356,20 @@ class ResizeableCanvas(Canvas):
# rescale all the objects tagged with the "all" tag # rescale all the objects tagged with the "all" tag
self.scale("all",0,0,wscale,hscale) self.scale("all",0,0,wscale,hscale)
def crashCNIR(): class StatusBar(Frame):
"""
last solution
"""
# Global handler
logfile = logger.logCur
# hide main window
root = Tk()
root.withdraw()
logfile.printerr("FATAL ERROR : see traceback below.\n{}".format(traceback.format_exc()))
showerror(lang.all[globs.CNIRlang]["CNIRevelator Fatal Eror"], lang.all[globs.CNIRlang]["CNIRevelator crashed because a fatal error occured. View log for more infos and please open an issue on Github"])
res = askquestion(lang.all[globs.CNIRlang]["CNIRevelator Fatal Eror"], lang.all[globs.CNIRlang]["Would you like to open an issue on Github to report this bug ?"])
if res == "yes":
webbrowser.open_new("https://github.com/neox95/CNIRevelator/issues")
root.destroy()
def __init__(self, master):
Frame.__init__(self, master)
self.label = Label(self, bd=1, relief=SUNKEN, anchor=W)
self.label.pack(fill=X)
def set(self, text):
self.label.config(text="Document : " + text.lower())
self.label.update_idletasks()
def clear(self):
self.label.config(text="")
self.label.update_idletasks()
## Global Handler ## Global Handler
launcherWindowCur = LauncherWindow() launcherWindowCur = LauncherWindow()

1465
src/lang.py Normal file

File diff suppressed because it is too large Load Diff

View File

@ -26,12 +26,13 @@
import sys import sys
import os import os
import threading import threading
import traceback
import critical # critical.py
import updater # updater.py import updater # updater.py
import ihm # ihm.py import ihm # ihm.py
import globs # globs.py import globs # globs.py
import logger # logger.py import logger # logger.py
import lang # lang.py
## Main function ## Main function
def lmain(mainThread): def lmain(mainThread):
@ -44,7 +45,7 @@ def lmain(mainThread):
# Hello user # Hello user
launcherWindow.progressBar.configure(mode='indeterminate', value=0, maximum=20) launcherWindow.progressBar.configure(mode='indeterminate', value=0, maximum=20)
launcherWindow.printmsg('Starting...') launcherWindow.printmsg(lang.all[globs.CNIRlang]["Starting..."])
launcherWindow.progressBar.start() launcherWindow.progressBar.start()
# Starting the main update thread # Starting the main update thread

View File

@ -26,6 +26,7 @@
import logging import logging
import os import os
import critical # critical.py
import globs # globs.py import globs # globs.py
## The logging class ## The logging class

View File

@ -31,29 +31,37 @@ from tkinter import filedialog
from tkinter import ttk from tkinter import ttk
import threading import threading
from datetime import datetime from datetime import datetime
from importlib import reload
import re import re
import traceback
import cv2 import cv2
import PIL.Image, PIL.ImageTk import PIL.Image, PIL.ImageTk
import os, shutil import os, shutil
import webbrowser import webbrowser
import sys, os
import critical # critical.py
import ihm # ihm.py import ihm # ihm.py
import logger # logger.py import logger # logger.py
import mrz # mrz.py import mrz # mrz.py
import globs # globs.py import globs # globs.py
import pytesseract # pytesseract.py import pytesseract # pytesseract.py
import lang # lang.py
# Global handler # Global handler
logfile = logger.logCur logfile = logger.logCur
class mainWindow(Tk): class mainWindow(Tk):
## App Pattern
def __init__(self): def __init__(self):
Tk.__init__(self) Tk.__init__(self)
self.initialize() self.initialize()
def initialize(self): def initialize(self):
"""
Initializes the main window
"""
self.mrzChar = "" self.mrzChar = ""
self.mrzDecided = False self.mrzDecided = False
self.Tags = [] self.Tags = []
@ -61,6 +69,12 @@ class mainWindow(Tk):
self.corners = [] self.corners = []
self.validatedtext = "" self.validatedtext = ""
# The icon
if getattr(sys, 'frozen', False):
self.iconbitmap(sys._MEIPASS + '\\id-card.ico\\id-card.ico')
else:
self.iconbitmap('id-card.ico')
# Hide during construction # Hide during construction
self.withdraw() self.withdraw()
@ -70,15 +84,16 @@ class mainWindow(Tk):
logfile.printdbg('Launching main window with resolution' + str(ws) + 'x' + str(hs)) logfile.printdbg('Launching main window with resolution' + str(ws) + 'x' + str(hs))
# Configuring the size of each part of the window # Configuring the size of each part of the window
self.grid_columnconfigure(0, weight=1, minsize=(ws / 2 * 0.3333333333333333)) self.grid_columnconfigure(0, minsize=(ws / 2 * 0.3333333333333333))
self.grid_columnconfigure(1, weight=1, minsize=(ws / 2 * 0.3333333333333333)) self.grid_columnconfigure(1, minsize=(ws / 2 * 0.3333333333333333))
self.grid_columnconfigure(2, weight=1, minsize=(ws / 2 * 0.3333333333333333)) self.grid_columnconfigure(2, weight=1, minsize=(ws / 2 * 0.3333333333333333))
self.grid_rowconfigure(0, weight=1, minsize=(hs / 2 * 0.5)) self.grid_rowconfigure(0, minsize=(hs / 2 * 0.5))
self.grid_rowconfigure(1, weight=1, minsize=(hs / 2 * 0.10)) self.grid_rowconfigure(1, minsize=(hs / 2 * 0.10))
self.grid_rowconfigure(2, weight=1, minsize=(hs / 2 * 0.35)) self.grid_rowconfigure(2, minsize=(hs / 2 * 0.35))
self.grid_rowconfigure(3, minsize=10)
# Prepare the data sections # Prepare the data sections
self.lecteur_ci = ttk.Labelframe(self, text="Informations sur la pièce d'identité") self.lecteur_ci = ttk.Labelframe(self, text=lang.all[globs.CNIRlang]["Informations about the current document"])
self.lecteur_ci.grid_columnconfigure(0, weight=1) self.lecteur_ci.grid_columnconfigure(0, weight=1)
self.lecteur_ci.grid_columnconfigure(1, weight=1) self.lecteur_ci.grid_columnconfigure(1, weight=1)
self.lecteur_ci.grid_columnconfigure(2, weight=1) self.lecteur_ci.grid_columnconfigure(2, weight=1)
@ -90,52 +105,57 @@ class mainWindow(Tk):
self.lecteur_ci.grid_rowconfigure(3, weight=1) self.lecteur_ci.grid_rowconfigure(3, weight=1)
self.lecteur_ci.grid_rowconfigure(4, weight=1) self.lecteur_ci.grid_rowconfigure(4, weight=1)
self.lecteur_ci.grid_rowconfigure(5, weight=1) self.lecteur_ci.grid_rowconfigure(5, weight=1)
# And what about the status bar ?
self.statusbar = ihm.StatusBar(self)
self.statusbar.grid(row=3, columnspan=3, sticky="NSEW")
# Fill the data sections # Fill the data sections
ttk.Label((self.lecteur_ci), text='Statut : ').grid(column=0, row=0, padx=5, pady=5) ttk.Label((self.lecteur_ci), text='{} : '.format(lang.all[globs.CNIRlang]["Status"])).grid(column=0, row=0, padx=5, pady=5)
self.STATUStxt = ttk.Label((self.lecteur_ci), text='EN ATTENTE', font=("TkDefaultFont", 13, "bold"), foreground="orange", anchor=CENTER) self.statusbar.set(lang.all[globs.CNIRlang]["IDLE"])
self.STATUStxt = ttk.Label((self.lecteur_ci), text=lang.all[globs.CNIRlang]["IDLE"], font=("TkDefaultFont", 13, "bold"), foreground="orange", anchor=CENTER)
self.STATUStxt.grid(column=1, row=0, padx=5, pady=5) self.STATUStxt.grid(column=1, row=0, padx=5, pady=5)
ttk.Label((self.lecteur_ci), text='Nom : ').grid(column=0, row=1, padx=5, pady=5) ttk.Label((self.lecteur_ci), text='{} : '.format(lang.all[globs.CNIRlang]["Name"])).grid(column=0, row=1, padx=5, pady=5)
self.nom = ttk.Label((self.lecteur_ci), text=' ') self.nom = ttk.Label((self.lecteur_ci), text=' ')
self.nom.grid(column=1, row=1, padx=5, pady=5) self.nom.grid(column=1, row=1, padx=5, pady=5)
ttk.Label((self.lecteur_ci), text='Nom (2) : ').grid(column=0, row=2, padx=5, pady=5) ttk.Label((self.lecteur_ci), text='{} (2) : '.format(lang.all[globs.CNIRlang]["Name"])).grid(column=0, row=2, padx=5, pady=5)
self.prenom = ttk.Label((self.lecteur_ci), text=' ') self.prenom = ttk.Label((self.lecteur_ci), text=' ')
self.prenom.grid(column=1, row=2, padx=5, pady=5) self.prenom.grid(column=1, row=2, padx=5, pady=5)
ttk.Label((self.lecteur_ci), text='Date de naissance : ').grid(column=0, row=3, padx=5, pady=5) ttk.Label((self.lecteur_ci), text='{} : '.format(lang.all[globs.CNIRlang]["Birth date"])).grid(column=0, row=3, padx=5, pady=5)
self.bdate = ttk.Label((self.lecteur_ci), text=' ') self.bdate = ttk.Label((self.lecteur_ci), text=' ')
self.bdate.grid(column=1, row=3, padx=5, pady=5) self.bdate.grid(column=1, row=3, padx=5, pady=5)
ttk.Label((self.lecteur_ci), text='Date de délivrance : ').grid(column=0, row=4, padx=5, pady=5) ttk.Label((self.lecteur_ci), text='{} : '.format(lang.all[globs.CNIRlang]["Issue date"])).grid(column=0, row=4, padx=5, pady=5)
self.ddate = ttk.Label((self.lecteur_ci), text=' ') self.ddate = ttk.Label((self.lecteur_ci), text=' ')
self.ddate.grid(column=1, row=4, padx=5, pady=5) self.ddate.grid(column=1, row=4, padx=5, pady=5)
ttk.Label((self.lecteur_ci), text="Date d'expiration : ").grid(column=0, row=5, padx=5, pady=5) ttk.Label((self.lecteur_ci), text="{} : ".format(lang.all[globs.CNIRlang]["Expiration date"])).grid(column=0, row=5, padx=5, pady=5)
self.edate = ttk.Label((self.lecteur_ci), text=' ') self.edate = ttk.Label((self.lecteur_ci), text=' ')
self.edate.grid(column=1, row=5, padx=5, pady=5) self.edate.grid(column=1, row=5, padx=5, pady=5)
ttk.Label((self.lecteur_ci), text='Sexe du porteur : ').grid(column=4, row=1, padx=5, pady=5) ttk.Label((self.lecteur_ci), text='{} : '.format(lang.all[globs.CNIRlang]["Sex"])).grid(column=4, row=1, padx=5, pady=5)
self.sex = ttk.Label((self.lecteur_ci), text=' ') self.sex = ttk.Label((self.lecteur_ci), text=' ')
self.sex.grid(column=5, row=1, padx=5, pady=5) self.sex.grid(column=5, row=1, padx=5, pady=5)
ttk.Label((self.lecteur_ci), text='Pays de délivrance : ').grid(column=4, row=2, padx=5, pady=5) ttk.Label((self.lecteur_ci), text='{} : '.format(lang.all[globs.CNIRlang]["Issuing country"])).grid(column=4, row=2, padx=5, pady=5)
self.pays = ttk.Label((self.lecteur_ci), text=' ') self.pays = ttk.Label((self.lecteur_ci), text=' ')
self.pays.grid(column=5, row=2, padx=5, pady=5) self.pays.grid(column=5, row=2, padx=5, pady=5)
ttk.Label((self.lecteur_ci), text='Nationalité du porteur : ').grid(column=4, row=3, padx=5, pady=5) ttk.Label((self.lecteur_ci), text='{} : '.format(lang.all[globs.CNIRlang]["Nationality"])).grid(column=4, row=3, padx=5, pady=5)
self.nat = ttk.Label((self.lecteur_ci), text=' ') self.nat = ttk.Label((self.lecteur_ci), text=' ')
self.nat.grid(column=5, row=3, padx=5, pady=5) self.nat.grid(column=5, row=3, padx=5, pady=5)
ttk.Label((self.lecteur_ci), text='Immatriculation : ').grid(column=4, row=4, padx=5, pady=5) ttk.Label((self.lecteur_ci), text='{} : '.format(lang.all[globs.CNIRlang]["Registration"])).grid(column=4, row=4, padx=5, pady=5)
self.indic = ttk.Label((self.lecteur_ci), text=' ') self.indic = ttk.Label((self.lecteur_ci), text=' ')
self.indic.grid(column=5, row=4, padx=5, pady=5) self.indic.grid(column=5, row=4, padx=5, pady=5)
ttk.Label((self.lecteur_ci), text='Numéro de document : ').grid(column=4, row=5, padx=5, pady=5) ttk.Label((self.lecteur_ci), text='{} : '.format(lang.all[globs.CNIRlang]["Document number"])).grid(column=4, row=5, padx=5, pady=5)
self.no = ttk.Label((self.lecteur_ci), text=' ') self.no = ttk.Label((self.lecteur_ci), text=' ')
self.no.grid(column=5, row=5, padx=5, pady=5) self.no.grid(column=5, row=5, padx=5, pady=5)
self.nom['text'] = 'Inconnu(e)' self.nom['text'] = lang.all[globs.CNIRlang]["Unknown"]
self.prenom['text'] = 'Inconnu(e)' self.prenom['text'] = lang.all[globs.CNIRlang]["Unknown"]
self.bdate['text'] = 'Inconnu(e)' self.bdate['text'] = lang.all[globs.CNIRlang]["Unknown"]
self.ddate['text'] = 'Inconnu(e)' self.ddate['text'] = lang.all[globs.CNIRlang]["Unknown"]
self.edate['text'] = 'Inconnu(e)' self.edate['text'] = lang.all[globs.CNIRlang]["Unknown"]
self.no['text'] = 'Inconnu(e)' self.no['text'] = lang.all[globs.CNIRlang]["Unknown"]
self.sex['text'] = 'Inconnu(e)' self.sex['text'] = lang.all[globs.CNIRlang]["Unknown"]
self.nat['text'] = 'Inconnu(e)' self.nat['text'] = lang.all[globs.CNIRlang]["Unknown"]
self.pays['text'] = 'Inconnu(e)' self.pays['text'] = lang.all[globs.CNIRlang]["Unknown"]
self.indic['text'] = 'Inconnu(e)' self.indic['text'] = lang.all[globs.CNIRlang]["Unknown"]
self.infoList = \ self.infoList = \
@ -153,7 +173,7 @@ class mainWindow(Tk):
} }
# The the image viewer # The the image viewer
self.imageViewer = ttk.Labelframe(self, text='Affichage et traitement de documents') self.imageViewer = ttk.Labelframe(self, text=lang.all[globs.CNIRlang]["Display and processing of documents"])
self.imageViewer.grid_columnconfigure(0, weight=1) self.imageViewer.grid_columnconfigure(0, weight=1)
self.imageViewer.grid_columnconfigure(1, weight=0) self.imageViewer.grid_columnconfigure(1, weight=0)
self.imageViewer.grid_rowconfigure(0, weight=1) self.imageViewer.grid_rowconfigure(0, weight=1)
@ -258,7 +278,7 @@ class mainWindow(Tk):
# The terminal to enter the MRZ # The terminal to enter the MRZ
self.terminal = ttk.Labelframe(self, text='Terminal de saisie de MRZ complète') self.terminal = ttk.Labelframe(self, text=lang.all[globs.CNIRlang]["Complete MRZ capture terminal"])
self.terminal.grid_columnconfigure(0, weight=1) self.terminal.grid_columnconfigure(0, weight=1)
self.terminal.grid_rowconfigure(0, weight=1) self.terminal.grid_rowconfigure(0, weight=1)
self.termframe = Frame(self.terminal) self.termframe = Frame(self.terminal)
@ -272,7 +292,7 @@ class mainWindow(Tk):
self.termtext.grid(column=0, row=0, sticky='SW', padx=5, pady=25) self.termtext.grid(column=0, row=0, sticky='SW', padx=5, pady=25)
# Speed Entry Zone for 731 # Speed Entry Zone for 731
self.terminal2 = ttk.Labelframe(self, text='Terminal de saisie rapide (731)') self.terminal2 = ttk.Labelframe(self, text=lang.all[globs.CNIRlang]["Quick entry terminal (731)"])
self.terminal2.grid_columnconfigure(0, weight=1) self.terminal2.grid_columnconfigure(0, weight=1)
self.terminal2.grid_rowconfigure(0, weight=1) self.terminal2.grid_rowconfigure(0, weight=1)
self.speed731 = Frame(self.terminal2) self.speed731 = Frame(self.terminal2)
@ -294,7 +314,7 @@ class mainWindow(Tk):
self.speedResult.grid(column=2, row=0, sticky='NEW', padx=5, pady=5) self.speedResult.grid(column=2, row=0, sticky='NEW', padx=5, pady=5)
# The monitor that indicates some useful infos # The monitor that indicates some useful infos
self.monitor = ttk.Labelframe(self, text='Moniteur') self.monitor = ttk.Labelframe(self, text=lang.all[globs.CNIRlang]["Monitor"])
self.monlog = Text((self.monitor), state='disabled', width=60, height=10, wrap='word') self.monlog = Text((self.monitor), state='disabled', width=60, height=10, wrap='word')
self.monlog.grid(column=0, row=0, sticky='EWNS', padx=5, pady=5) self.monlog.grid(column=0, row=0, sticky='EWNS', padx=5, pady=5)
self.scrollb = ttk.Scrollbar((self.monitor), command=(self.monlog.yview)) self.scrollb = ttk.Scrollbar((self.monitor), command=(self.monlog.yview))
@ -313,41 +333,45 @@ class mainWindow(Tk):
# What is a window without a menu bar ? # What is a window without a menu bar ?
menubar = Menu(self) menubar = Menu(self)
menu1 = Menu(menubar, tearoff=0) menu1 = Menu(menubar, tearoff=0)
menu1.add_command(label='Nouveau', command=(self.newEntry)) menu1.add_command(label=lang.all[globs.CNIRlang]["New"], command=(self.newEntry))
menu1.add_command(label='Ouvrir scan...', command=(self.openingScan)) menu1.add_command(label=lang.all[globs.CNIRlang]["Open scan..."], command=(self.openingScan))
menu1.add_separator() menu1.add_separator()
menu1.add_command(label='Quitter', command=(self.destroy)) menu1.add_command(label=lang.all[globs.CNIRlang]["Quit"], command=(self.destroy))
menubar.add_cascade(label='Fichier', menu=menu1) menubar.add_cascade(label=lang.all[globs.CNIRlang]["File"], menu=menu1)
menu2 = Menu(menubar, tearoff=0)
menu2.add_command(label=lang.all[globs.CNIRlang]["Update options"], command=(self.updateSet))
menu2.add_command(label=lang.all[globs.CNIRlang]["Show Changelog"], command=(self.showChangeLog))
menu2.add_separator()
menu2.add_command(label=lang.all[globs.CNIRlang]["Language"], command=(self.languageSet))
menubar.add_cascade(label=lang.all[globs.CNIRlang]["Settings"], menu=menu2)
menu3 = Menu(menubar, tearoff=0) menu3 = Menu(menubar, tearoff=0)
menu3.add_command(label='Commandes au clavier', command=(self.helpbox)) menu3.add_command(label=lang.all[globs.CNIRlang]["Keyboard commands"], command=(self.helpbox))
menu3.add_command(label='Signaler un problème', command=(self.openIssuePage)) menu3.add_command(label=lang.all[globs.CNIRlang]["Report a bug"], command=(self.openIssuePage))
menu3.add_separator() menu3.add_separator()
menu3.add_command(label='A propos de CNIRevelator', command=(self.infobox)) menu3.add_command(label=lang.all[globs.CNIRlang]["About CNIRevelator"], command=(self.infobox))
menubar.add_cascade(label='Aide', menu=menu3) menubar.add_cascade(label=lang.all[globs.CNIRlang]["Help"], menu=menu3)
menubar.add_command(label="<|>", command=(self.panelResize))
self.config(menu=menubar) self.config(menu=menubar)
# The title # The title
self.wm_title(globs.CNIRName) self.wm_title(globs.CNIRName)
# The icon
if getattr(sys, 'frozen', False):
self.iconbitmap(sys._MEIPASS + '\\id-card.ico\\id-card.ico')
else:
self.iconbitmap('id-card.ico')
# Make this window resizable and set her size # Make this window resizable and set her size
self.resizable(width=True, height=True) self.resizable(0, 0)
self.update() self.update()
w = int(self.winfo_reqwidth()) self.w = int(self.winfo_reqwidth())
h = int(self.winfo_reqheight()) self.h = int(self.winfo_reqheight())
ws = self.winfo_screenwidth() self.ws = self.winfo_screenwidth()
hs = self.winfo_screenheight() self.hs = self.winfo_screenheight()
x = (ws - w)/2 self.x = (self.ws - self.w)/2
y = (hs - h)/2 self.y = (self.hs - self.h)/2
self.geometry('%dx%d+%d+%d' % (w, h, x, y)) self.geometry('%dx%d+%d+%d' % (self.w, self.h, self.x, self.y))
self.update() self.update()
self.deiconify() self.deiconify()
self.minsize(self.winfo_width(), self.winfo_height()) self.attributes("-topmost", 1)
self.maxsize(self.w, self.h)
self.minsize(int(2.15 * (self.ws / 2 * 0.3333333333333333)), self.h)
self.currentw = self.w
# Set image # Set image
self.imageViewer.image = None self.imageViewer.image = None
@ -364,27 +388,33 @@ class mainWindow(Tk):
self.imageViewer.ZONE.bind("<Button-1>", self.rectangleSelectScan) self.imageViewer.ZONE.bind("<Button-1>", self.rectangleSelectScan)
logfile.printdbg('Initialization successful') logfile.printdbg('Initialization successful')
def statusUpdate(self, image=None, setplace=False):
if image:
self.imageViewer.image = image
self.imageViewer.ZONE.itemconfigure(self.STATUSimg, image=(self.imageViewer.image))
self.imageViewer.ZONE.configure(scrollregion=self.imageViewer.ZONE.bbox("all"))
if globs.CNIROpenFile:
self.after_idle(lambda : self.openScanFile(sys.argv[1]))
## OCR related functions
def rectangleSelectScan(self, event): def rectangleSelectScan(self, event):
"""
Realises the selection of the MRZ to make OCR possible
"""
if self.imageViewer.image: if self.imageViewer.image:
canvas = event.widget canvas = event.widget
print("Get coordinates : [{}, {}], for [{}, {}]".format(canvas.canvasx(event.x), canvas.canvasy(event.y), event.x, event.y)) #print("Get coordinates : [{}, {}], for [{}, {}]".format(canvas.canvasx(event.x), canvas.canvasy(event.y), event.x, event.y))
self.corners.append([canvas.canvasx(event.x), canvas.canvasy(event.y)]) self.corners.append([canvas.canvasx(event.x), canvas.canvasy(event.y)])
if len(self.corners) == 2: if len(self.corners) == 2:
self.select = self.imageViewer.ZONE.create_rectangle(self.corners[0][0], self.corners[0][1], self.corners[1][0], self.corners[1][1], outline ='cyan', width = 2) self.select = self.imageViewer.ZONE.create_rectangle(self.corners[0][0], self.corners[0][1], self.corners[1][0], self.corners[1][1], outline ='cyan', width = 2)
print("Get rectangle : [{}, {}], for [{}, {}]".format(self.corners[0][0], self.corners[0][1], self.corners[1][0], self.corners[1][1])) #print("Get rectangle : [{}, {}], for [{}, {}]".format(self.corners[0][0], self.corners[0][1], self.corners[1][0], self.corners[1][1]))
if len(self.corners) > 2: if len(self.corners) > 2:
self.corners = [] self.corners = []
self.imageViewer.ZONE.delete(self.select) self.imageViewer.ZONE.delete(self.select)
def goOCRDetection(self): def goOCRDetection(self):
"""
Realises the OCR detection and get the text in self.mrzChar (and prints it)
"""
if self.imageViewer.image: if self.imageViewer.image:
cv_img = cv2.imreadmulti(self.imageViewer.imagePath)[1][self.imageViewer.pagenumber] cv_img = cv2.imreadmulti(self.imageViewer.imagePath)[1][self.imageViewer.pagenumber]
cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB) cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB)
@ -434,7 +464,7 @@ class mainWindow(Tk):
invite.focus_force() invite.focus_force()
self.wait_window(invite) self.wait_window(invite)
print("text : {}".format(self.validatedtext)) #print("text : {}".format(self.validatedtext))
self.mrzChar = "" self.mrzChar = ""
@ -445,7 +475,7 @@ class mainWindow(Tk):
self.mrzChar = self.mrzChar + char self.mrzChar = self.mrzChar + char
self.stringValidation("") self.stringValidation("")
print(self.mrzChar) #print(self.mrzChar)
# Reinstall tesseract # Reinstall tesseract
except pytesseract.TesseractNotFoundError as e: except pytesseract.TesseractNotFoundError as e:
@ -453,16 +483,20 @@ class mainWindow(Tk):
shutil.rmtree(globs.CNIRTesser) shutil.rmtree(globs.CNIRTesser)
except Exception: except Exception:
pass pass
showerror('Erreur de module OCR', ('Le module OCR localisé en ' + str(os.environ['PATH']) + 'est introuvable ou corrompu. Il sera réinstallé à la prochaine exécution'), parent=self) showerror(lang.all[globs.CNIRlang]["OCR module error"], (lang.all[globs.CNIRlang]["The OCR module located at {} can not be found or corrupted. It will be reinstalled at the next run"].format(os.environ['PATH'])), parent=self)
logfile.printerr("Tesseract error : {}. Will be reinstallated".format(e)) logfile.printerr(lang.all[globs.CNIRlang]["Tesseract error : {}. Will be reinstallated"].format(e))
# Tesseract error # Tesseract error
except pytesseract.TesseractError as e: except pytesseract.TesseractError as e:
logfile.printerr("Tesseract error : {}".format(e)) logfile.printerr("Tesseract error : {}".format(e))
showerror('Erreur de module OCR', ("Le module Tesseract a rencontré un problème : {}".format(e)), parent=self) showerror(lang.all[globs.CNIRlang]["OCR module error"], (lang.all[globs.CNIRlang]["The Tesseract module encountered a problem: {}"].format(e)), parent=self)
## Regex and document detection + control related functions
def stringValidation(self, keysym): def stringValidation(self, keysym):
"""
Analysis of the already typed document
"""
# analysis # analysis
# If we must decide the type of the document # If we must decide the type of the document
if not self.mrzDecided: if not self.mrzDecided:
@ -478,11 +512,13 @@ class mainWindow(Tk):
self.wait_window(invite) self.wait_window(invite)
self.logOnTerm("Document detecté : {}\n".format(candidates[invite.choice][2])) self.logOnTerm(lang.all[globs.CNIRlang]["Document detected: {}\n"].format(candidates[invite.choice][2]))
self.statusbar.set(candidates[invite.choice][2])
self.mrzDecided = candidates[invite.choice] self.mrzDecided = candidates[invite.choice]
elif len(candidates) == 1: elif len(candidates) == 1:
self.logOnTerm("Document detecté : {}\n".format(candidates[0][2])) self.logOnTerm(lang.all[globs.CNIRlang]["Document detected: {}\n"].format(candidates[0][2]))
self.statusbar.set(candidates[0][2])
self.mrzDecided = candidates[0] self.mrzDecided = candidates[0]
else: else:
# corrects some problems # corrects some problems
@ -569,11 +605,13 @@ class mainWindow(Tk):
self.wait_window(invite) self.wait_window(invite)
self.logOnTerm("Document re-detecté : {}\n".format(candidates[invite.choice][2])) self.logOnTerm(lang.all[globs.CNIRlang]["Document detected again: {}\n"].format(candidates[invite.choice][2]))
self.statusbar.set(candidates[invite.choice][2])
self.mrzDecided = candidates[invite.choice] self.mrzDecided = candidates[invite.choice]
elif len(candidates) == 1: elif len(candidates) == 1:
self.logOnTerm("Document re-detecté : {}\n".format(candidates[0][2])) self.logOnTerm(lang.all[globs.CNIRlang]["Document detected again: {}\n"].format(candidates[0][2]))
self.statusbar.set(candidates[0][2])
self.mrzDecided = candidates[0] self.mrzDecided = candidates[0]
return "break" return "break"
@ -583,7 +621,7 @@ class mainWindow(Tk):
regex = re.compile("[A-Z]|<|[0-9]") regex = re.compile("[A-Z]|<|[0-9]")
# match ! # match !
if not regex.fullmatch(event.char): if not regex.fullmatch(event.char):
self.logOnTerm("Caractère non accepté !\n") self.logOnTerm(lang.all[globs.CNIRlang]["Character not accepted !\n"])
return "break" return "break"
# Adds the entry # Adds the entry
tempChar = self.termtext.get("1.0", "end")[:-1] tempChar = self.termtext.get("1.0", "end")[:-1]
@ -625,35 +663,147 @@ class mainWindow(Tk):
char = self.speed731text.get() char = self.speed731text.get()
self.speedResultPrint(str(mrz.computeControlSum(char))) self.speedResultPrint(str(mrz.computeControlSum(char)))
return "break" return "break"
def computeSigma(self):
"""
Launch the checksum computation, infos validation and print/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)["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(lang.all[globs.CNIRlang]["Document Review: {}\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]))
if sum[3]:
self.logOnTerm(lang.all[globs.CNIRlang]["Checksum position {}: Lu {} VS Calculated {} [facultative]\n"].format(sum[1], code[sum[1]], sum[2]))
else:
self.logOnTerm(lang.all[globs.CNIRlang]["Checksum position {}: Lu {} VS Calculated {}\n"].format(sum[1], code[sum[1]], sum[2]))
# if sum is facultative or if sum is ok
try:
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
except ValueError:
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
# 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", "CTRLF"]:
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"
self.compliance = False
if self.compliance == True:
self.STATUStxt["text"] = lang.all[globs.CNIRlang]["COMPLIANT"]
self.STATUStxt["foreground"] = "green"
self.statusbar.set(lang.all[globs.CNIRlang]["COMPLIANT"])
else:
self.STATUStxt["text"] = lang.all[globs.CNIRlang]["IMPROPER"]
self.STATUStxt["foreground"] = "red"
self.statusbar.set(lang.all[globs.CNIRlang]["IMPROPER"])
## Print functions
def logOnTerm(self, text): def logOnTerm(self, text):
"""
Writes on the monitor
"""
self.monlog['state'] = 'normal' self.monlog['state'] = 'normal'
self.monlog.insert('end', text) self.monlog.insert('end', text)
self.monlog['state'] = 'disabled' self.monlog['state'] = 'disabled'
self.monlog.yview(END) self.monlog.yview(END)
def clearTerm(self): def clearTerm(self):
"""
Clears the monitor
"""
self.monlog['state'] = 'normal' self.monlog['state'] = 'normal'
self.monlog.delete('1.0', 'end') self.monlog.delete('1.0', 'end')
self.monlog['state'] = 'disabled' self.monlog['state'] = 'disabled'
self.monlog.yview(END) self.monlog.yview(END)
def speedResultPrint(self, text): def speedResultPrint(self, text):
"""
Prints a result in the quick entry terminal
"""
self.speedResult['state'] = 'normal' self.speedResult['state'] = 'normal'
self.speedResult.delete("1.0", 'end') self.speedResult.delete("1.0", 'end')
self.speedResult.insert('end', text) self.speedResult.insert('end', text)
self.speedResult['state'] = 'disabled' self.speedResult['state'] = 'disabled'
## Document display related functions
def DisplayUpdate(self, image=None, setplace=False):
"""
Reload the displayer to display the image or not
"""
if image:
self.imageViewer.image = image
self.imageViewer.ZONE.itemconfigure(self.STATUSimg, image=(self.imageViewer.image))
self.imageViewer.ZONE.configure(scrollregion=self.imageViewer.ZONE.bbox("all"))
def goPageChoice(self, event): def goPageChoice(self, event):
"""
Change the current viewed page of the multipage tiff if needed
"""
self.imageViewer.pagenumber = int(self.toolbar.pageChooser.get()) - 1 self.imageViewer.pagenumber = int(self.toolbar.pageChooser.get()) - 1
self.resizeScan() self.resizeScan()
def openingScan(self): def openingScan(self):
"""
Open the scan, ask its path and displays it
"""
path = '' path = ''
path = filedialog.askopenfilename(parent=self, title='Ouvrir un scan de CNI...', filetypes=(('TIF files', '*.tif'), path = filedialog.askopenfilename(parent=self, title=lang.all[globs.CNIRlang]["Open a scan of document..."], filetypes=(('TIF files', '*.tif'),
('TIF files', '*.tiff'), ('TIF files', '*.tiff'),
('JPEG files', '*.jpg'), ('JPEG files', '*.jpg'),
('JPEG files', '*.jpeg'))) ('JPEG files', '*.jpeg')))
self.openScanFile(path)
def openScanFile(self, path):
"""
Open an image file at path to display it on the displayer
"""
# Check if the file is valid
if ( path[-3:] != 'jpg'
and path[-3:] != 'tif'
and path[-4:] != 'jpeg'
and path[-4:] != 'tiff' ) or not os.path.isfile(path):
showerror(lang.all[globs.CNIRlang]["Open a scan of document..."], lang.all[globs.CNIRlang]["The file you provided is not valid : {}"].format(path))
return
# Load an image using OpenCV # Load an image using OpenCV
self.imageViewer.imagePath = path self.imageViewer.imagePath = path
self.imageViewer.imgZoom = 1 self.imageViewer.imgZoom = 1
@ -685,7 +835,7 @@ class mainWindow(Tk):
# Use PIL (Pillow) to convert the NumPy ndarray to a PhotoImage # Use PIL (Pillow) to convert the NumPy ndarray to a PhotoImage
photo = PIL.ImageTk.PhotoImage(image = PIL.Image.fromarray(cv_img)) photo = PIL.ImageTk.PhotoImage(image = PIL.Image.fromarray(cv_img))
self.statusUpdate(photo) self.DisplayUpdate(photo)
def zoomInScan50(self, quantity = 50): def zoomInScan50(self, quantity = 50):
if self.imageViewer.image: if self.imageViewer.image:
@ -746,6 +896,9 @@ class mainWindow(Tk):
self.resizeScan() self.resizeScan()
def negativeScan(self): def negativeScan(self):
"""
Invert the bits to make a negative of the scan (and highlight the contrasts)
"""
if self.imageViewer.image: if self.imageViewer.image:
# Load an image using OpenCV # Load an image using OpenCV
cv_img = cv2.imreadmulti(self.imageViewer.imagePath)[1][self.imageViewer.pagenumber] cv_img = cv2.imreadmulti(self.imageViewer.imagePath)[1][self.imageViewer.pagenumber]
@ -760,6 +913,9 @@ class mainWindow(Tk):
self.resizeScan(cv_img) self.resizeScan(cv_img)
def resizeScan(self, cv_img = None): def resizeScan(self, cv_img = None):
"""
Reloads the image according to settings
"""
if self.imageViewer.image: if self.imageViewer.image:
try: try:
if not hasattr(cv_img, 'shape'): if not hasattr(cv_img, 'shape'):
@ -789,10 +945,10 @@ class mainWindow(Tk):
cv_img = cv2.resize(cv_img, dim, interpolation = cv2.INTER_AREA) cv_img = cv2.resize(cv_img, dim, interpolation = cv2.INTER_AREA)
# Use PIL (Pillow) to convert the NumPy ndarray to a PhotoImage # Use PIL (Pillow) to convert the NumPy ndarray to a PhotoImage
photo = PIL.ImageTk.PhotoImage(image = PIL.Image.fromarray(cv_img)) photo = PIL.ImageTk.PhotoImage(image = PIL.Image.fromarray(cv_img))
self.statusUpdate( photo) self.DisplayUpdate( photo)
except Exception as e: except Exception as e:
logfile.printerr("Error with opencv : {}".format(e)) logfile.printerr("Error with opencv : {}".format(e))
traceback.print_exc(file=sys.stdout) critical.crashCNIR()
try: try:
# Reload an image using OpenCV # Reload an image using OpenCV
path = self.imageViewer.imagePath path = self.imageViewer.imagePath
@ -807,144 +963,97 @@ class mainWindow(Tk):
height, width, channels_no = cv_img.shape height, width, channels_no = cv_img.shape
# Use PIL (Pillow) to convert the NumPy ndarray to a PhotoImage # Use PIL (Pillow) to convert the NumPy ndarray to a PhotoImage
photo = PIL.ImageTk.PhotoImage(image = PIL.Image.fromarray(cv_img)) photo = PIL.ImageTk.PhotoImage(image = PIL.Image.fromarray(cv_img))
self.statusUpdate(photo) self.DisplayUpdate(photo)
except Exception as e: except Exception as e:
logfile.printerr("Critical error with opencv : ".format(e)) logfile.printerr("Critical error with opencv : ".format(e))
traceback.print_exc(file=sys.stdout) critical.crashCNIR()
showerror("Erreur OpenCV (traitement d'images)", "Une erreur critique s'est produite dans le gestionnaire de traitement d'images OpenCV utilisé par CNIRevelator. L'application va se réinitialiser") showerror(lang.all[globs.CNIRlang]["OpenCV error (image processing)"], lang.all[globs.CNIRlang]["A critical error has occurred in the OpenCV image processing manager used by CNIRevelator, the application will reset itself"])
self.initialize() self.initialize()
## IHM and user interface related functions
def newEntry(self): def newEntry(self):
"""
Reinits the IHM and invite
"""
self.initialize() self.initialize()
self.logOnTerm('\n\nEntrez la première ligne de MRZ svp \n') self.logOnTerm('\n\n{}\n'.format(lang.all[globs.CNIRlang]["Please type a MRZ or open a scan"]))
def infobox(self): def infobox(self):
"""
Shows the About dialog
"""
Tk().withdraw() Tk().withdraw()
showinfo('A propos de CNIRevelator', showinfo( lang.all[globs.CNIRlang]["About CNIRevelator"],
( 'Version du logiciel : CNIRevelator ' + globs.verstring_full + '\n\n' (
"Copyright © 2018-2019 Adrien Bourmault (neox95)" + "\n\n" lang.all[globs.CNIRlang]["ABOUT"]
"CNIRevelator est un logiciel libre : vous avez le droit de le modifier et/ou le distribuer "
"dans les termes de la GNU General Public License telle que publiée par "
"la Free Software Foundation, dans sa version 3 ou "
"ultérieure. " + "\n\n"
"CNIRevelator est distribué dans l'espoir d'être utile, sans toutefois "
"impliquer une quelconque garantie de "
"QUALITÉ MARCHANDE ou APTITUDE À UN USAGE PARTICULIER. Référez vous à la "
"GNU General Public License pour plus de détails à ce sujet. "
"\n\n"
"Vous devriez avoir reçu une copie de la GNU General Public License "
"avec CNIRevelator. Si cela n'est pas le cas, jetez un oeil à <https://www.gnu.org/licenses/>. "
"\n\n"
"Le module d'OCR Tesseract 4.0 est soumis à l'Apache License 2004."
"\n\n"
"Les bibliothèques python et l'environnement Anaconda 3 sont soumis à la licence BSD 2018-2019."
"\n\n"
"Le code source de ce programme est disponible sur Github à l'adresse <https://github.com/neox95/CNIRevelator>.\n"
"Son fonctionnement est conforme aux normes et directives du document 9303 de l'OACI régissant les documents de voyages et d'identité." + '\n\n'
" En cas de problèmes ou demande particulière, ouvrez-y une issue ou bien envoyez un mail à neox@os-k.eu !\n\n"
), ),
parent=self) parent=self)
def helpbox(self): def helpbox(self):
"""
Shows the keyboard help summary
"""
Tk().withdraw() Tk().withdraw()
showinfo('Aide sur les contrôles au clavier', showinfo( lang.all[globs.CNIRlang]["Keyboard commands"],
( "Terminal de saisie rapide (731) : \n\n" (
" Caractères autorisés : Alphanumériques en majuscule et le caractère '<'. Pas de minuscules ni caractères spéciaux, autrement la somme est mise à zéro \n\n" lang.all[globs.CNIRlang]["KEYBHELP"]
" Calculer résultat :\t\t\tTouche Ctrl droite \n"
" Copier :\t\t\t\tCtrl-C \n"
" Coller :\t\t\t\tCtrl-V \n"
"\n\n"
"Terminal de saisie MRZ complète : \n\n"
" Caractères autorisés : Alphanumériques en majuscule et le caractère '<'. Pas de minuscules ni caractères spéciaux, autrement la somme est mise à zéro \n\n"
" Calculer résultat :\t\t\tTouche Ctrl droite \n"
" Compléter champ :\t\t\tTouche Tab \n"
" Copier :\t\t\t\tCtrl-C \n"
" Coller :\t\t\t\tCtrl-V \n"
" Forcer une nouvelle détection du document :\tEchap\n"
), ),
parent=self) parent=self)
def openIssuePage(self): def openIssuePage(self):
self.openBrowser("https://github.com/neox95/CNIRevelator/issues") """
Opens the Github Issue Repository page
"""
webbrowser.open_new("https://github.com/neox95/CNIRevelator/issues")
def openBrowser(self, url): def showChangeLog(self):
webbrowser.open_new(url) changelogWin = ihm.ChangelogDialog(self, ('{} : CNIRevelator {}\n\n{}'.format(lang.all[globs.CNIRlang]["Program version"], globs.verstring_full, lang.all[globs.CNIRlang]["CHANGELOG"])))
changelogWin.transient(self)
changelogWin.grab_set()
changelogWin.focus_force()
self.wait_window(changelogWin)
def computeSigma(self): def updateSet(self):
""" """
Launch the checksum computation, infos validation and display the results Update Settings
""" """
# the regex changeupdateWin = ihm.updateSetDialog(self)
regex = re.compile("[^A-Z0-9<]") changeupdateWin.transient(self)
code = re.sub(regex, '', self.mrzChar) changeupdateWin.grab_set()
self.compliance = True changeupdateWin.focus_force()
self.wait_window(changeupdateWin)
allSums = mrz.computeAllControlSum(self.mrzDecided, code)["ctrlSumList"]
#print("Code : _{}_ | Sums : {}".format(code, allSums)) def languageSet(self):
"""
self.termtext.tag_remove("conforme", "1.0", "end") Lang Settings
self.termtext.tag_remove("nonconforme", "1.0", "end") """
changelangWin = ihm.langDialog(self)
self.clearTerm() changelangWin.transient(self)
self.logOnTerm("Examen du document : {}\n\n".format(self.mrzDecided[2])) changelangWin.grab_set()
changelangWin.focus_force()
for sum in allSums: self.wait_window(changelangWin)
x = sum[1] // len(self.mrzDecided[0][0]) +1
y = sum[1] % len(self.mrzDecided[0][0]) global mrz
#print("index : {}.{}".format(x,y)) mrz = reload(mrz)
#print("{} == {}".format(code[sum[1]], sum[2]))
self.initialize()
self.logOnTerm("Somme de contrôle position {} : Lu {} VS Calculé {}\n".format(sum[1], code[sum[1]], sum[2]))
def panelResize(self):
# if sum is facultative or if sum is ok """
try: Shows or hides the panel
if sum[3] or int(code[sum[1]]) == int(sum[2]): """
self.termtext.tag_add("conforme", "{}.{}".format(x,y), "{}.{}".format(x,y+1)) if self.currentw > int(2.15 * (self.ws / 2 * 0.3333333333333333)):
self.termtext.tag_configure("conforme", background="green", foreground="white") self.currentw = int(2.15 * (self.ws / 2 * 0.3333333333333333))
else: self.geometry('%dx%d+%d+%d' % (self.currentw, self.h, self.x, self.y))
self.termtext.tag_add("nonconforme", "{}.{}".format(x,y), "{}.{}".format(x,y+1)) self.update()
self.termtext.tag_configure("nonconforme", background="red", relief='raised', foreground="white")
self.compliance = False
except ValueError:
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
# 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"
self.compliance = False
if self.compliance == True:
self.STATUStxt["text"] = "CONFORME"
self.STATUStxt["foreground"] = "green"
else: else:
self.STATUStxt["text"] = "NON CONFORME" self.currentw = self.w
self.STATUStxt["foreground"] = "red" self.geometry('%dx%d+%d+%d' % (self.currentw, self.h, self.x, self.y))
self.update()
return

View File

@ -24,537 +24,22 @@
******************************************************************************** ********************************************************************************
""" """
import re
import logger # logger.py
import re import re
import datetime import datetime
import logger # logger.py
import globs # globs.py
import lang # lang.py
import critical # critical.py
## SEX CODES ## SEX CODES
sexcode = {'M':'Homme', 'F':'Femme', 'X':'Non spécifié'} sexcode = {'M':'Homme', 'F':'Femme', 'X':'Non spécifié'}
## COUNTRY CODES ## COUNTRY CODES
landcode2 = { landcode2 = lang.all[globs.CNIRlang]["LANDCODE2"]
'AW': 'Aruba',
'AF': 'Afghanistan',
'AO': 'Angola',
'AI': 'Anguilla',
'AL': 'Albanie',
'AD': 'Andorre',
'AE': 'Emirats arabes unis',
'AR': 'Argentine',
'AM': 'Arménie',
'AS': 'Samoa américaines',
'AQ': 'Antarctique',
'TF': 'Terres australes et antarctiques françaises',
'AG': 'Antigua-et-Barbuda',
'AU': 'Australie',
'AT': 'Autriche',
'AZ': 'Azerbaidjan',
'BI': 'Burundi',
'BE': 'Belgique',
'BJ': 'Benin',
'BQ': 'Pays-Bas caribéens',
'BF': 'Burkina Faso',
'BD': 'Bangladesh',
'BG': 'Bulgarie',
'BH': 'Bahrein',
'BS': 'Bahamas',
'BA': 'Bosnie-Herzegovine',
'BL': 'Saint-Barthélemy',
'BY': 'Bielorussie',
'BZ': 'Belize',
'BM': 'Bermudes',
'BO': 'Bolivie',
'BR': 'Brésil',
'BB': 'Barbade',
'BN': 'Brunei',
'BT': 'Bhoutan',
'BW': 'Botswana',
'CF': 'République Centrafricaine',
'CA': 'Canada',
'CC': 'Îles Cocos',
'CH': 'Suisse',
'CL': 'Chili',
'CN': 'Chine',
'CI': "Côte d'Ivoire",
'CM': 'Cameroun',
'CD': 'Congo (République démocratique)',
'CG': 'Congo (République)',
'CK': 'Îles Cook',
'CO': 'Colombie',
'KM': 'Comores',
'CV': 'Cap-Vert',
'CR': 'Costa Rica',
'CU': 'Cuba',
'CW': 'Curaçao',
'CX': 'Île Christmas',
'KY': 'Caimans',
'CY': 'Chypre',
'CZ': 'Tchéquie',
'DE': 'Allemagne',
'DJ': 'Djibouti',
'DM': 'Dominique',
'DK': 'Danemark',
'DO': 'République dominicaine',
'DZ': 'Algérie',
'EC': 'Equateur',
'EG': 'Egypte',
'ER': 'Erythrée',
'EH': 'Sahara occidental',
'ES': 'Espagne',
'EE': 'Estonie',
'ET': 'Ethiopie',
'FI': 'Finlande',
'FJ': 'Fidji',
'FK': 'Îles Malouines',
'FR': 'France',
'FO': 'Féroé',
'FM': 'Micronésie',
'GA': 'Gabon',
'GB': 'Royaume-Uni',
'GE': 'Géorgie',
'GG': 'Guernesey',
'GH': 'Ghana',
'GI': 'Gibraltar',
'GN': 'Guinée',
'GP': 'Guadeloupe',
'GM': 'Gambie',
'GW': 'Guinée-Bissau',
'GQ': 'Guinée équatoriale',
'GR': 'Grèce',
'GD': 'Grenade',
'GL': 'Groenland',
'GT': 'Guatemala',
'GF': 'Guyane',
'GU': 'Guam',
'GY': 'Guyana',
'HK': 'Hong Kong',
'HN': 'Honduras',
'HR': 'Croatie',
'HT': 'Haïti',
'HU': 'Hongrie',
'ID': 'Indonésie',
'IM': 'Île de Man',
'IN': 'Inde',
'IO': "Territoire britannique de l'océan Indien",
'IE': 'Irlande',
'IR': 'Irak',
'IQ': 'Iran',
'IS': 'Islande',
'IL': 'Israël',
'IT': 'Italie',
'JM': 'Jamaïque',
'JE': 'Jersey',
'JO': 'Jordanie',
'JP': 'Japon',
'KZ': 'Kazakhstan',
'KE': 'Kenya',
'KG': 'Kirghizistan',
'KH': 'Cambodge',
'KI': 'Kiribati',
'KN': 'Saint-Christophe-et-Niévès',
'KR': 'Corée du Sud',
'KW': 'Koweït',
'LA': 'Laos',
'LB': 'Liban',
'LR': 'Liberia',
'LY': 'Libye',
'LC': 'Sainte-Lucie',
'LI': 'Liechtenstein',
'LK': 'Sri Lanka',
'LS': 'Lesotho',
'LT': 'Lituanie',
'LU': 'Luxembourg',
'LV': 'Lettonie',
'MO': 'Macao',
'MF': 'Sint-Maarten',
'MA': 'Maroc',
'MC': 'Monaco',
'MD': 'Moldavie',
'MG': 'Madagascar',
'MV': 'Maldives',
'MX': 'Mexique',
'MH': 'Marshall',
'MK': 'Macedoine',
'ML': 'Mali',
'MT': 'Malte',
'MM': 'Birmanie',
'ME': 'Monténégro',
'MN': 'Mongolie',
'MP': 'Îles Mariannes du Nord',
'MZ': 'Mozambique',
'MR': 'Mauritanie',
'MS': 'Montserrat',
'MQ': 'Martinique',
'MU': 'Maurice',
'MW': 'Malawi',
'MY': 'Malaisie',
'YT': 'Mayotte',
'NA': 'Namibie',
'NC': 'Nouvelle-Calédonie',
'NE': 'Niger',
'NF': 'Île Norfolk',
'NG': 'Nigeria',
'NI': 'Nicaragua',
'NU': 'Niue',
'NL': 'Pays-Bas',
'NO': 'Norvège',
'NP': 'Nepal',
'NR': 'Nauru',
'NZ': 'Nouvelle-Zélande',
'OM': 'Oman',
'PK': 'Pakistan',
'PA': 'Panama',
'PN': 'Îles Pitcairn',
'PE': 'Pérou',
'PH': 'Philippines',
'PW': 'Palaos',
'PG': 'Papouasie-Nouvelle-Guinée',
'PL': 'Pologne',
'PR': 'Porto Rico',
'KP': 'Corée du Nord',
'PT': 'Portugal',
'PY': 'Paraguay',
'PS': 'Palestine',
'PF': 'Polynésie française',
'QA': 'Qatar',
'RE': 'Réunion',
'RO': 'Roumanie',
'RU': 'Russie',
'RW': 'Rwanda',
'SA': 'Arabie saoudite',
'SD': 'Soudan',
'SN': 'Sénégal',
'SG': 'Singapour',
'GS': 'Georgie du Sud-et-les iles Sandwich du Sud',
'SH': 'Sainte-Hélène, Ascension et Tristan da Cunha',
'SJ': 'Svalbard et île Jan Mayen',
'SB': 'Salomon',
'SL': 'Sierra Leone',
'SV': 'Salvador',
'SM': 'Saint-Marin',
'SO': 'Somalie',
'PM': 'Saint-Pierre-et-Miquelon',
'RS': 'Serbie',
'SS': 'Soudan du Sud',
'ST': 'Sao Tomé-et-Principe',
'SR': 'Suriname',
'SK': 'Slovaquie',
'SI': 'Slovénie',
'SE': 'Suède',
'SZ': 'eSwatani',
'SX': 'Saint-Martin ',
'SC': 'Seychelles',
'SY': 'Syrie',
'TC': 'Îles Turques-et-Caïques',
'TD': 'Tchad',
'TG': 'Togo',
'TH': 'Thaïlande',
'TJ': 'Tadjikistan',
'TK': 'Tokelau',
'TM': 'Turkmenistan',
'TL': 'Timor oriental',
'TO': 'Tonga',
'TT': 'Trinité-et-Tobago',
'TN': 'Tunisie',
'TR': 'Turquie',
'TV': 'Tuvalu',
'TW': 'Taiwan',
'TZ': 'Tanzanie',
'UG': 'Ouganda',
'UA': 'Ukraine',
'UY': 'Uruguay',
'US': 'Etats-Unis',
'UZ': 'Ouzbékistan',
'VA': 'Saint-Siège (État de la Cité du Vatican)',
'VC': 'Saint-Vincent-et-les-Grenadines',
'VE': 'Venezuela',
'VG': 'Îles Vierges britanniques',
'VI': 'Îles Vierges des États-Unis',
'VN': 'Viêt Nam',
'VU': 'Vanuatu',
'WF': 'Wallis-et-Futuna',
'WS': 'Samoa',
'XK': 'Kosovo',
'YE': 'Yémen',
'ZA': 'Afrique du Sud',
'ZM': 'Zambie',
'ZW': 'Zimbabwe'
}
landcode3 = { landcode3 = lang.all[globs.CNIRlang]["LANDCODE3"]
'ABW': 'Aruba',
'AFG': 'Afghanistan',
'AGO': 'Angola',
'AIA': 'Anguilla',
'ALB': 'Albanie',
'AND': 'Andorre',
'ARE': 'Emirats arabes unis',
'ARG': 'Argentine',
'ARM': 'Arménie',
'ASM': 'Samoa américaines',
'ATA': 'Antarctique',
'ATF': 'Terres australes et antarctiques françaises',
'ATG': 'Antigua-et-Barbuda',
'AUS': 'Australie',
'AUT': 'Autriche',
'AZE': 'Azerbaidjan',
'BDI': 'Burundi',
'BEL': 'Belgique',
'BEN': 'Benin',
'BES': 'Pays-Bas caribéens',
'BFA': 'Burkina Faso',
'BGD': 'Bangladesh',
'BGR': 'Bulgarie',
'BHR': 'Bahrein',
'BHS': 'Bahamas',
'BIH': 'Bosnie-Herzegovine',
'BLM': 'Saint-Barthélemy',
'BLR': 'Bielorussie',
'BLZ': 'Belize',
'BMU': 'Bermudes',
'BOL': 'Bolivie',
'BRA': 'Brésil',
'BRB': 'Barbade',
'BRN': 'Brunei',
'BTN': 'Bhoutan',
'BWA': 'Botswana',
'CAF': 'République Centrafricaine',
'CAN': 'Canada',
'CCK': 'Îles Cocos',
'CHE': 'Suisse',
'CHL': 'Chili',
'CHN': 'Chine',
'CIV': "Côte d'Ivoire",
'CMR': 'Cameroun',
'COD': 'Congo (République démocratique)',
'COG': 'Congo (République)',
'COK': 'Îles Cook',
'COL': 'Colombie',
'COM': 'Comores',
'CPV': 'Cap-Vert',
'CRI': 'Costa Rica',
'CUB': 'Cuba',
'CUW': 'Curaçao',
'CXR': 'Île Christmas',
'CYM': 'Caimans',
'CYP': 'Chypre',
'CZE': 'Tchéquie',
'DEU': 'Allemagne',
'DJI': 'Djibouti',
'DMA': 'Dominique',
'DNK': 'Danemark',
'DOM': 'République dominicaine',
'DZA': 'Algérie',
'ECU': 'Equateur',
'EGY': 'Egypte',
'ERI': 'Erythrée',
'ESH': 'Sahara occidental',
'ESP': 'Espagne',
'EST': 'Estonie',
'ETH': 'Ethiopie',
'FIN': 'Finlande',
'FJI': 'Fidji',
'FLK': 'Îles Malouines',
'FRA': 'France',
'FRO': 'Féroé',
'FSM': 'Micronésie',
'GAB': 'Gabon',
'GBR': 'Royaume-Uni',
'GEO': 'Géorgie',
'GGY': 'Guernesey',
'GHA': 'Ghana',
'GIB': 'Gibraltar',
'GIN': 'Guinée',
'GLP': 'Guadeloupe',
'GMB': 'Gambie',
'GNB': 'Guinée-Bissau',
'GNQ': 'Guinée équatoriale',
'GRC': 'Grèce',
'GRD': 'Grenade',
'GRL': 'Groenland',
'GTM': 'Guatemala',
'GUF': 'Guyane',
'GUM': 'Guam',
'GUY': 'Guyana',
'HKG': 'Hong Kong',
'HND': 'Honduras',
'HRV': 'Croatie',
'HTI': 'Haïti',
'HUN': 'Hongrie',
'IDN': 'Indonésie',
'IMN': 'Île de Man',
'IND': 'Inde',
'IOT': "Territoire britannique de l'océan Indien",
'IRL': 'Irlande',
'IRN': 'Irak',
'IRQ': 'Iran',
'ISL': 'Islande',
'ISR': 'Israël',
'ITA': 'Italie',
'JAM': 'Jamaïque',
'JEY': 'Jersey',
'JOR': 'Jordanie',
'JPN': 'Japon',
'KAZ': 'Kazakhstan',
'KEN': 'Kenya',
'KGZ': 'Kirghizistan',
'KHM': 'Cambodge',
'KIR': 'Kiribati',
'KNA': 'Saint-Christophe-et-Niévès',
'KOR': 'Corée du Sud',
'KWT': 'Koweït',
'LAO': 'Laos',
'LBN': 'Liban',
'LBR': 'Liberia',
'LBY': 'Libye',
'LCA': 'Sainte-Lucie',
'LIE': 'Liechtenstein',
'LKA': 'Sri Lanka',
'LSO': 'Lesotho',
'LTU': 'Lituanie',
'LUX': 'Luxembourg',
'LVA': 'Lettonie',
'MAC': 'Macao',
'MAF': 'Sint-Maarten',
'MAR': 'Maroc',
'MCO': 'Monaco',
'MDA': 'Moldavie',
'MDG': 'Madagascar',
'MDV': 'Maldives',
'MEX': 'Mexique',
'MHL': 'Marshall',
'MKD': 'Macedoine',
'MLI': 'Mali',
'MLT': 'Malte',
'MMR': 'Birmanie',
'MNE': 'Monténégro',
'MNG': 'Mongolie',
'MNP': 'Îles Mariannes du Nord',
'MOZ': 'Mozambique',
'MRT': 'Mauritanie',
'MSR': 'Montserrat',
'MTQ': 'Martinique',
'MUS': 'Maurice',
'MWI': 'Malawi',
'MYS': 'Malaisie',
'MYT': 'Mayotte',
'NAM': 'Namibie',
'NCL': 'Nouvelle-Calédonie',
'NER': 'Niger',
'NFK': 'Île Norfolk',
'NGA': 'Nigeria',
'NIC': 'Nicaragua',
'NIU': 'Niue',
'NLD': 'Pays-Bas',
'NOR': 'Norvège',
'NPL': 'Nepal',
'NRU': 'Nauru',
'NZL': 'Nouvelle-Zélande',
'OMN': 'Oman',
'PAK': 'Pakistan',
'PAN': 'Panama',
'PCN': 'Îles Pitcairn',
'PER': 'Pérou',
'PHL': 'Philippines',
'PLW': 'Palaos',
'PNG': 'Papouasie-Nouvelle-Guinée',
'POL': 'Pologne',
'PRI': 'Porto Rico',
'PRK': 'Corée du Nord',
'PRT': 'Portugal',
'PRY': 'Paraguay',
'PSE': 'Palestine',
'PYF': 'Polynésie française',
'QAT': 'Qatar',
'REU': 'Réunion',
'ROU': 'Roumanie',
'RUS': 'Russie',
'RWA': 'Rwanda',
'SAU': 'Arabie saoudite',
'SDN': 'Soudan',
'SEN': 'Sénégal',
'SGP': 'Singapour',
'SGS': 'Georgie du Sud-et-les iles Sandwich du Sud',
'SHN': 'Sainte-Hélène, Ascension et Tristan da Cunha',
'SJM': 'Svalbard et île Jan Mayen',
'SLB': 'Salomon',
'SLE': 'Sierra Leone',
'SLV': 'Salvador',
'SMR': 'Saint-Marin',
'SOM': 'Somalie',
'SPM': 'Saint-Pierre-et-Miquelon',
'SRB': 'Serbie',
'SSD': 'Soudan du Sud',
'STP': 'Sao Tomé-et-Principe',
'SUR': 'Suriname',
'SVK': 'Slovaquie',
'SVN': 'Slovénie',
'SWE': 'Suède',
'SWZ': 'eSwatani',
'SXM': 'Saint-Martin ',
'SYC': 'Seychelles',
'SYR': 'Syrie',
'TCA': 'Îles Turques-et-Caïques',
'TCD': 'Tchad',
'TGO': 'Togo',
'THA': 'Thaïlande',
'TJK': 'Tadjikistan',
'TKL': 'Tokelau',
'TKM': 'Turkmenistan',
'TLS': 'Timor oriental',
'TON': 'Tonga',
'TTO': 'Trinité-et-Tobago',
'TUN': 'Tunisie',
'TUR': 'Turquie',
'TUV': 'Tuvalu',
'TWN': 'Taiwan',
'TZA': 'Tanzanie',
'UGA': 'Ouganda',
'UKR': 'Ukraine',
'URY': 'Uruguay',
'USA': 'Etats-Unis',
'UZB': 'Ouzbékistan',
'VAT': 'Saint-Siège (État de la Cité du Vatican)',
'VCT': 'Saint-Vincent-et-les-Grenadines',
'VEN': 'Venezuela',
'VGB': 'Îles Vierges britanniques',
'VIR': 'Îles Vierges des États-Unis',
'VNM': 'Viêt Nam',
'VUT': 'Vanuatu',
'WLF': 'Wallis-et-Futuna',
'WSM': 'Samoa',
'XKX': 'Kosovo',
'YEM': 'Yémen',
'ZAF': 'Afrique du Sud',
'ZMB': 'Zambie',
'ZWE': 'Zimbabwe',
'NTZ': 'Zone neutre',
'UNO': 'Fonctionnaire des Nations Unies',
'UNA': "Fonctionnaire d'une organisation affiliée aux Nations Unies",
'UNK': 'Représentant des Nations Unies au Kosovo',
'XXA': 'Apatride Convention 1954',
'XXB': 'Réfugié Convention 1954',
'XXC': 'Réfugié autre',
'XXX': 'Résident Légal de Nationalité Inconnue',
'D': 'Allemagne',
'EUE': 'Union Européenne',
'GBD': "Citoyen Britannique d'Outre-mer (BOTC)",
'GBN': 'British National (Overseas)',
'GBO': 'British Overseas Citizen',
'GBP': 'British Protected Person',
'GBS': 'British Subject',
'XBA': 'Banque Africaine de Développement',
'XIM': "Banque Africaine d'ExportImport",
'XCC': 'Caribbean Community or one of its emissaries',
'XCO': 'Common Market for Eastern and Southern Africa',
'XEC': 'Economic Community of West African States',
'XPO': 'International Criminal Police Organization',
'XOM': 'Sovereign Military Order of Malta',
'RKS': 'Kosovo',
'WSA': 'World Service Authority World Passport'
}
## DOCUMENTS TYPES ## DOCUMENTS TYPES
@ -576,7 +61,7 @@ P = [
"D": ["1", "CTRLF", "[0-9]", "C"], "D": ["1", "CTRLF", "[0-9]", "C"],
"E": ["1", "CTRL", "[0-9]", "4578ABCD"] "E": ["1", "CTRL", "[0-9]", "4578ABCD"]
}, },
"Passeport" lang.all[globs.CNIRlang]["Passeport"]
] ]
IP = [ IP = [
@ -596,7 +81,7 @@ IP = [
"C": ["11", "FACULT", ".+"], "C": ["11", "FACULT", ".+"],
"D": ["1", "CTRL", "[0-9]", "345679AC"] "D": ["1", "CTRL", "[0-9]", "345679AC"]
}, },
"Carte-passeport" lang.all[globs.CNIRlang]["Carte-passeport"]
] ]
I_ = [ I_ = [
@ -616,7 +101,7 @@ I_ = [
"C": ["11", "FACULT", ".+"], "C": ["11", "FACULT", ".+"],
"D": ["1", "CTRL", "[0-9]", "345679AC"] "D": ["1", "CTRL", "[0-9]", "345679AC"]
}, },
"Titre d'identité/de voyage" lang.all[globs.CNIRlang]["Titre d'identité/de voyage"]
] ]
AC = [ AC = [
@ -637,7 +122,7 @@ AC = [
"C": ["11", "FACULT", ".+"], "C": ["11", "FACULT", ".+"],
"D": ["1", "CTRL", "[0-9]","345679AC"] "D": ["1", "CTRL", "[0-9]","345679AC"]
}, },
"Certificat de membre d'équipage" lang.all[globs.CNIRlang]["Certificat de membre d'équipage"]
] ]
VA = [ VA = [
@ -656,7 +141,7 @@ VA = [
"B": ["1", "CTRL", "[0-9]", "A"], "B": ["1", "CTRL", "[0-9]", "A"],
"C": ["16", "FACULT", ".+"] "C": ["16", "FACULT", ".+"]
}, },
"Visa de type A" lang.all[globs.CNIRlang]["Visa de type A"]
] ]
VB = [ VB = [
@ -675,7 +160,7 @@ VB = [
"B": ["1", "CTRL", "[0-9]", "A"], "B": ["1", "CTRL", "[0-9]", "A"],
"C": ["8", "FACULT", ".+"] "C": ["8", "FACULT", ".+"]
}, },
"Visa de type B" lang.all[globs.CNIRlang]["Visa de type B"]
] ]
TSF = [ TSF = [
@ -694,7 +179,7 @@ TSF = [
"B": ["1", "CTRL", "[0-9]", "A"], "B": ["1", "CTRL", "[0-9]", "A"],
"C": ["8", "FACULT", ".+"] "C": ["8", "FACULT", ".+"]
}, },
"Carte de séjour" lang.all[globs.CNIRlang]["Carte de séjour"]
] ]
I__ = [ I__ = [
@ -714,7 +199,7 @@ I__ = [
"C": ["7", "FACULT", ".+"], "C": ["7", "FACULT", ".+"],
"D": ["1", "CTRL", "[0-9]", "4578ABC"] "D": ["1", "CTRL", "[0-9]", "4578ABC"]
}, },
"Pièce d'identité/de voyage" lang.all[globs.CNIRlang]["Pièce d'identité/de voyage"]
] ]
IDFR = [ IDFR = [
@ -734,7 +219,7 @@ IDFR = [
"C": ["1", "SEX", "[A-Z]"], "C": ["1", "SEX", "[A-Z]"],
"D": ["1", "CTRL", "[0-9]", "123456789ABCE"] "D": ["1", "CTRL", "[0-9]", "123456789ABCE"]
}, },
"Pièce d'identité FR" lang.all[globs.CNIRlang]["Pièce d'identité FR"]
] ]
DL = [ DL = [
@ -748,7 +233,7 @@ DL = [
"6": ["8", "NOM", "([A-Z]|<)+"], "6": ["8", "NOM", "([A-Z]|<)+"],
"7": ["1", "CTRL", "[0-9]", "123456"] "7": ["1", "CTRL", "[0-9]", "123456"]
}, },
"Permis de conduire" lang.all[globs.CNIRlang]["Permis de conduire"]
] ]
TYPES = [IDFR, I__, VB, VA, AC, I_, IP, P, DL, TSF] TYPES = [IDFR, I__, VB, VA, AC, I_, IP, P, DL, TSF]
@ -1010,6 +495,14 @@ def getDocInfos(doc, code):
res["INDIC"] += value res["INDIC"] += value
except KeyError: except KeyError:
res["INDIC"] = value res["INDIC"] = value
# Sex
elif field[0] == 'SEX':
if not value in "MF":
res[field[0]] = False
else:
res[field[0]] = value
# All other cases # All other cases
else: else:
if value != "": if value != "":

View File

@ -24,7 +24,9 @@
""" """
from win32com.client import Dispatch from win32com.client import Dispatch
import traceback from tkinter.messagebox import *
from tkinter import *
import pythoncom
import sys import sys
import time import time
import os import os
@ -34,10 +36,12 @@ import hashlib
import subprocess import subprocess
import psutil import psutil
import critical # critical.py
import ihm # ihm.py import ihm # ihm.py
import logger # logger.py import logger # logger.py
import globs # globs.py import globs # globs.py
import downloader # downloader.py import downloader # downloader.py
import lang # lang.py
UPDATE_IS_MADE = False UPDATE_IS_MADE = False
UPATH = ' ' UPATH = ' '
@ -80,52 +84,21 @@ def exitProcess(arg):
if process.pid == os.getpid(): if process.pid == os.getpid():
process.terminate() process.terminate()
sys.exit(arg) sys.exit(arg)
def runPowershell(scriptblock, cwd=os.getcwd()): def updateChannel(choice):
""" if choice == "Beta":
Executes a powershell command with open(globs.CNIRUrlConfig, 'w') as (configFile):
""" configFile.write("{}\n0\n0".format(globs.CNIRBetaURL))
log.debug("Running PowerShell Block:\r\n%s", scriptblock) else:
log.debug("Current Directory: %s\r\n" % cwd) with open(globs.CNIRUrlConfig, 'w') as (configFile):
psProc = subprocess.Popen([r'C:\WINDOWS\system32\WindowsPowerShell\v1.0\powershell.exe', configFile.write("{}\n0\n0".format(globs.CNIRDefaultURL))
'-ExecutionPolicy', 'Bypass',
'-noprofile',
'-c', '-',],
cwd=cwd,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
stdoutdata, stderrdata = psProc.communicate(scriptblock)
if stdoutdata:
log.debug("Script Output:\r\n%s" % stdoutdata)
elif not stderrdata:
log.debug("Script completed succssfully (no stdout/stderr).")
if stderrdata:
log.error("Script Error:\r\n%s" % stderrdata)
return stdoutdata, stderrdata
def getCertificates(server_list, location="LocalMachine", store="My"):
"""
Returns the json data of all installed certificates
"""
cmd = '''
$sb = { ls Cert:\%s\%s | Select Subject,ThumbPrint }
$Servers = '%s' | ConvertFrom-Json
Invoke-Command -ComputerName $Servers -ScriptBlock $sb -Authentication Negotiate | ConvertTo-Json -Depth 999
''' % (location, store, json.dumps(server_list))
stdoutdata, stderrdata = runPowershell(cmd)
return json.loads(stdoutdata)
def getLatestVersion(credentials): def getLatestVersion(credentials):
""" """
Returns the latest version of the software Returns the latest version of the software
""" """
finalver, finalurl, finalchecksum = [None]*3
# Global Handlers # Global Handlers
logfile = logger.logCur logfile = logger.logCur
@ -155,7 +128,7 @@ def getLatestVersion(credentials):
except: except:
pass pass
with open(globs.CNIRUrlConfig, 'w') as (configFile): with open(globs.CNIRUrlConfig, 'w') as (configFile):
configFile.write("https://raw.githubusercontent.com/neox95/CNIRevelator/master/VERSIONS.LST\n0\n0") configFile.write("{}\n0\n0".format(globs.CNIRDefaultURL))
# Getting the list of versions of the software # Getting the list of versions of the software
logfile.printdbg('Retrieving the software versions') logfile.printdbg('Retrieving the software versions')
@ -188,7 +161,7 @@ def getLatestVersion(credentials):
else: else:
finalurl = url finalurl = url
finalchecksum = None finalchecksum = None
return (finalver, finalurl, finalchecksum) return (finalver, finalurl, finalchecksum)
@ -200,6 +173,11 @@ def tessInstall(PATH, credentials):
# Verifying that Tesseract is installed # Verifying that Tesseract is installed
if not os.path.exists(PATH + '\\Tesseract-OCR4\\'): if not os.path.exists(PATH + '\\Tesseract-OCR4\\'):
finalver, finalurl, finalchecksum = getLatestVersion(credentials) finalver, finalurl, finalchecksum = getLatestVersion(credentials)
if finalurl == None:
logfile.printerr('Unable to get the Tesseract url')
return False
tesseracturl = finalurl.replace("CNIRevelator.zip", "tesseract_4.zip") tesseracturl = finalurl.replace("CNIRevelator.zip", "tesseract_4.zip")
# WE ASSUME THAT THE MAIN FILE IS CNIRevelator.zip AND THAT THE TESSERACT PACKAGE IS tesseract_4.zip # WE ASSUME THAT THE MAIN FILE IS CNIRevelator.zip AND THAT THE TESSERACT PACKAGE IS tesseract_4.zip
@ -228,7 +206,7 @@ def tessInstall(PATH, credentials):
# Unzip Tesseract # Unzip Tesseract
logfile.printdbg("Unzipping the package") logfile.printdbg("Unzipping the package")
launcherWindow.printmsg('Installing the updates') launcherWindow.printmsg(lang.all[globs.CNIRlang]["Installing the updates"])
zip_ref = zipfile.ZipFile(PATH + '\\downloads\\TsrtPackage.zip', 'r') zip_ref = zipfile.ZipFile(PATH + '\\downloads\\TsrtPackage.zip', 'r')
zip_ref.extractall(PATH) zip_ref.extractall(PATH)
zip_ref.close() zip_ref.close()
@ -261,7 +239,7 @@ def batch(credentials):
getTheUpdate = downloader.newdownload(credentials, finalurl, globs.CNIRFolder + '\\downloads\\CNIPackage.zip', "CNIRevelator {}.{}.{}".format(finalver[0], finalver[1], finalver[2])).download() getTheUpdate = downloader.newdownload(credentials, finalurl, globs.CNIRFolder + '\\downloads\\CNIPackage.zip', "CNIRevelator {}.{}.{}".format(finalver[0], finalver[1], finalver[2])).download()
launcherWindow.printmsg('Verifying download...') launcherWindow.printmsg(lang.all[globs.CNIRlang]["Verifying download..."])
# CHECKSUM # CHECKSUM
BUF_SIZE = 65536 # lets read stuff in 64kb chunks! BUF_SIZE = 65536 # lets read stuff in 64kb chunks!
@ -286,7 +264,7 @@ def batch(credentials):
global UPATH global UPATH
UPATH = globs.CNIRFolder + '\\..\\CNIRevelator' + "{}.{}.{}".format(finalver[0], finalver[1], finalver[2]) UPATH = globs.CNIRFolder + '\\..\\CNIRevelator' + "{}.{}.{}".format(finalver[0], finalver[1], finalver[2])
logfile.printdbg("Make place") logfile.printdbg("Make place")
launcherWindow.printmsg('Preparing installation...') launcherWindow.printmsg(lang.all[globs.CNIRlang]["Preparing installation..."])
# Cleanup # Cleanup
try: try:
shutil.rmtree(UPATH + 'temp') shutil.rmtree(UPATH + 'temp')
@ -298,7 +276,7 @@ def batch(credentials):
logfile.printdbg('Unable to cleanup : ' +str(e)) logfile.printdbg('Unable to cleanup : ' +str(e))
# Unzip # Unzip
logfile.printdbg("Unzipping the package") logfile.printdbg("Unzipping the package")
launcherWindow.printmsg('Installing the updates') launcherWindow.printmsg(lang.all[globs.CNIRlang]["Installing the updates"])
zip_ref = zipfile.ZipFile(globs.CNIRFolder + '\\downloads\\CNIPackage.zip', 'r') zip_ref = zipfile.ZipFile(globs.CNIRFolder + '\\downloads\\CNIPackage.zip', 'r')
zip_ref.extractall(UPATH + "temp") zip_ref.extractall(UPATH + "temp")
zip_ref.close() zip_ref.close()
@ -309,9 +287,16 @@ def batch(credentials):
logfile.printdbg('Extracted :' + UPATH + '\\CNIRevelator.exe') logfile.printdbg('Extracted :' + UPATH + '\\CNIRevelator.exe')
# Make a shortcut # Make a shortcut
createShortcut("CNIRevelator.lnk", UPATH + '\\CNIRevelator.exe', UPATH) # hide main window
pythoncom.CoInitialize()
root = Tk()
root.withdraw()
res = askquestion(lang.all[globs.CNIRlang]["Shortcut creation"], lang.all[globs.CNIRlang]["Would you like to create/update the shortcut for CNIRevelator on your desktop ?"])
if res == "yes":
createShortcut("CNIRevelator.lnk", UPATH + '\\CNIRevelator.exe', UPATH)
root.destroy()
launcherWindow.printmsg('Success !') launcherWindow.printmsg(lang.all[globs.CNIRlang]["Success !"])
# Cleanup # Cleanup
try: try:
@ -319,7 +304,7 @@ def batch(credentials):
except: except:
pass pass
# Time to quit # Time to quit
launcherWindow.printmsg('Launched the new process.') launcherWindow.printmsg(lang.all[globs.CNIRlang]["Launching the new version..."])
global UPDATE_IS_MADE global UPDATE_IS_MADE
UPDATE_IS_MADE = True UPDATE_IS_MADE = True
return True return True
@ -335,19 +320,19 @@ def umain():
if not credentials.valid: if not credentials.valid:
logfile.printerr("Credentials Error. No effective update !") logfile.printerr("Credentials Error. No effective update !")
launcherWindow.printmsg('Credentials Error. No effective update !') launcherWindow.printmsg(lang.all[globs.CNIRlang]["Credentials Error. No effective update !"])
time.sleep(2) time.sleep(2)
launcherWindow.exit() launcherWindow.exit()
return 0 return 0
# Cleaner for the old version if detected # Cleaner for the old version if detected
if len(sys.argv) > 2: if len(sys.argv) > 2 and str(sys.argv[1]) == "DELETE":
globs.CNIRNewVersion = True globs.CNIRNewVersion = True
launcherWindow.printmsg('Deleting old version !') launcherWindow.printmsg(lang.all[globs.CNIRlang]["Deleting old version"])
logfile.printdbg("Old install detected : {}".format(sys.argv[1])) logfile.printdbg("Old install detected : {}".format(sys.argv[1]))
while os.path.exists(str(sys.argv[2])): while os.path.exists(str(sys.argv[2])):
try: try:
os.remove(str(sys.argv[2])) shutil.rmtree(str(sys.argv[2]))
except Exception as e: except Exception as e:
logfile.printerr(str(e)) logfile.printerr(str(e))
logfile.printdbg('Trying stop the process !') logfile.printdbg('Trying stop the process !')
@ -361,45 +346,24 @@ def umain():
else: else:
logfile.printdbg('Terminating process !') logfile.printdbg('Terminating process !')
process.terminate() process.terminate()
os.remove(str(sys.argv[2])) shutil.rmtree(str(sys.argv[2]))
break break
except Exception as e: except Exception as e:
logfile.printerr(str(e)) logfile.printerr(str(e))
launcherWindow.printmsg('Fail :{}'.format(e)) launcherWindow.printmsg('Fail :{}'.format(e))
launcherWindow.printmsg('Starting...') launcherWindow.printmsg(lang.all[globs.CNIRlang]['Starting...'])
elif len(sys.argv) > 1:
globs.CNIRNewVersion = True # check we want open a file
launcherWindow.printmsg('Deleting old version !') elif len(sys.argv) > 1 and str(sys.argv[1]) != "DELETE":
logfile.printdbg("Old install detected : {}".format(sys.argv[1])) globs.CNIROpenFile = True
while os.path.exists(str(sys.argv[1])): print(sys.argv)
try:
shutil.rmtree(str(sys.argv[1]))
except Exception as e:
logfile.printerr(str(e))
logfile.printdbg('Trying stop the process !')
launcherWindow.printmsg('Fail :{}'.format(e))
try:
for process in psutil.process_iter():
if process.name() == 'CNIRevelator.exe':
logfile.printdbg('Process found. Command line: {}'.format(process.cmdline()))
if process.pid == os.getpid():
logfile.printdbg("Don't touch us ! {} = {}".format(process.pid, os.getpid()))
else:
logfile.printdbg('Terminating process !')
process.terminate()
shutil.rmtree(str(sys.argv[1]))
break
except Exception as e:
logfile.printerr(str(e))
launcherWindow.printmsg('Fail :{}'.format(e))
launcherWindow.printmsg('Starting...')
try: try:
try: try:
# EXECUTING THE UPDATE BATCH # EXECUTING THE UPDATE BATCH
success = batch(credentials) success = batch(credentials)
except Exception as e: except Exception as e:
logfile.printerr("An error occured on the thread : " + str(traceback.format_exc())) critical.crashCNIR()
launcherWindow.printmsg('ERROR : ' + str(e)) launcherWindow.printmsg('ERROR : ' + str(e))
time.sleep(3) time.sleep(3)
launcherWindow.exit() launcherWindow.exit()
@ -410,7 +374,7 @@ def umain():
launcherWindow.printmsg('Software is up-to-date !') launcherWindow.printmsg('Software is up-to-date !')
else: else:
logfile.printerr("An error occured. No effective update !") logfile.printerr("An error occured. No effective update !")
launcherWindow.printmsg('An error occured. No effective update !') launcherWindow.printmsg(lang.all[globs.CNIRlang]['An error occured. No effective update !'])
time.sleep(2) time.sleep(2)
launcherWindow.exit() launcherWindow.exit()
return 0 return 0
@ -419,7 +383,7 @@ def umain():
launcherWindow.exit() launcherWindow.exit()
return 0 return 0
except: except:
logfile.printerr("A FATAL ERROR OCCURED : " + str(traceback.format_exc())) critical.crashCNIR()
launcherWindow.exit() launcherWindow.exit()
sys.exit(2) sys.exit(2)
return 2 return 2
@ -429,7 +393,7 @@ def umain():
# INSTALLING TESSERACT OCR # INSTALLING TESSERACT OCR
success = tessInstall(globs.CNIRFolder, credentials) success = tessInstall(globs.CNIRFolder, credentials)
except Exception as e: except Exception as e:
logfile.printerr("An error occured on the thread : " + str(traceback.format_exc())) critical.crashCNIR()
launcherWindow.printmsg('ERROR : ' + str(e)) launcherWindow.printmsg('ERROR : ' + str(e))
time.sleep(3) time.sleep(3)
launcherWindow.exit() launcherWindow.exit()
@ -437,16 +401,16 @@ def umain():
if success: if success:
logfile.printdbg("Software is up-to-date !") logfile.printdbg("Software is up-to-date !")
launcherWindow.printmsg('Software is up-to-date !') launcherWindow.printmsg(lang.all[globs.CNIRlang]['Software is up-to-date !'])
else: else:
logfile.printerr("An error occured. No effective update !") logfile.printerr("An error occured. No effective update !")
launcherWindow.printmsg('An error occured. No effective update !') launcherWindow.printmsg(lang.all[globs.CNIRlang]['An error occured. No effective update !'])
time.sleep(2) time.sleep(2)
launcherWindow.exit() launcherWindow.exit()
return 0 return 0
except: except:
logfile.printerr("A FATAL ERROR OCCURED : " + str(traceback.format_exc())) critical.crashCNIR()
launcherWindow.exit() launcherWindow.exit()
sys.exit(2) sys.exit(2)
return 2 return 2