mirror of
https://gitlab.os-k.eu/neox/CNIRevelator.git
synced 2023-08-25 14:03:10 +02:00
Compare commits
116 Commits
Author | SHA1 | Date | |
---|---|---|---|
e52c34319f | |||
fba076d245 | |||
9ca31bd744 | |||
3ab1ed9570 | |||
db84dbd13c | |||
88c41b2a48 | |||
17acb12992 | |||
bbb2e43f61 | |||
01b4a6ea4b | |||
f744c6fedd | |||
e230d65cd4 | |||
d1bf646118 | |||
4f36d5904e | |||
102b1d1e67 | |||
de31c9d79c | |||
535583e010 | |||
c880645949 | |||
83a6e110f6 | |||
624b78d9d1 | |||
1fe97b425a | |||
6a7d8ea5fb | |||
5e616e5283 | |||
072f1a2510 | |||
a7a22be152 | |||
7aed2c6623 | |||
b78d2842bf | |||
f44fd1add7 | |||
9972359ac1 | |||
b69e312cf7 | |||
30e1b15dd1 | |||
6d4104e6fa | |||
98cae9b951 | |||
1cce5184fd | |||
bf508555da | |||
9e57123850 | |||
685f7aab5a | |||
43fca39314 | |||
3110872310 | |||
46b7eb8c26 | |||
c7fb8d4c4b | |||
fe940585ac | |||
2dee9b79cf | |||
e037bba76e | |||
e7d164d355 | |||
19684df1c1 | |||
c2503d411b | |||
d5620bdd30 | |||
1f19344896 | |||
085cb2f571 | |||
e45af9d903 | |||
4062d68b2b | |||
cb46844fec | |||
1c38f1c8b4 | |||
a277295374 | |||
0897452d06 | |||
20c0b44d7b | |||
d45a0a9e9c | |||
17ad747e50 | |||
086d98fa3d | |||
840d70d9a3 | |||
cff6c44c91 | |||
f58e964e78 | |||
31672ec6f6 | |||
dfd0b9c988 | |||
0b0661bfa9 | |||
1483797828 | |||
a59b9cfff1 | |||
ff5c480929 | |||
20532650eb | |||
2be7a7568e | |||
31a3518213 | |||
2bc2c9c13b | |||
a9b7056114 | |||
eabb676c28 | |||
e065642f8b | |||
a13ca281ba | |||
f1dd2129ca | |||
659d47f47f | |||
942f6dd9da | |||
bcf0fde819 | |||
14f98e8493 | |||
afed0fe6ec | |||
d55146b532 | |||
ea40cf5938 | |||
99ce7d59f7 | |||
5eb98d2004 | |||
06d50121c7 | |||
017329257e | |||
81313007b0 | |||
ad813c0b14 | |||
ea93e4a7dd | |||
45d8734f7d | |||
9d7e866807 | |||
fd7c68e4a1 | |||
26b2c7c564 | |||
4bf8fad661 | |||
16f1d00e35 | |||
d399c4d7ca | |||
1054884b51 | |||
5547305794 | |||
822b206280 | |||
6d514b1ada | |||
2db1c28e24 | |||
6c480d49b9 | |||
73f0c1b583 | |||
9423e316eb | |||
9bc808d785 | |||
49ee60e58a | |||
f117fb8658 | |||
fcf8949c6b | |||
dda773cd75 | |||
b0d4fbf2fc | |||
73e06d37df | |||
ec7cd0e11d | |||
c34a88abc5 | |||
8e389ddf25 |
38
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
38
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Create a report to help us improve
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Describe the bug**
|
||||||
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
**To Reproduce**
|
||||||
|
Steps to reproduce the behavior:
|
||||||
|
1. Go to '...'
|
||||||
|
2. Click on '....'
|
||||||
|
3. Scroll down to '....'
|
||||||
|
4. See error
|
||||||
|
|
||||||
|
**Expected behavior**
|
||||||
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
|
**Screenshots**
|
||||||
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
|
**Desktop (please complete the following information):**
|
||||||
|
- OS: [e.g. iOS]
|
||||||
|
- Browser [e.g. chrome, safari]
|
||||||
|
- Version [e.g. 22]
|
||||||
|
|
||||||
|
**Smartphone (please complete the following information):**
|
||||||
|
- Device: [e.g. iPhone6]
|
||||||
|
- OS: [e.g. iOS8.1]
|
||||||
|
- Browser [e.g. stock browser, safari]
|
||||||
|
- Version [e.g. 22]
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context about the problem here.
|
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
about: Suggest an idea for this project
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Is your feature request related to a problem? Please describe.**
|
||||||
|
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||||
|
|
||||||
|
**Describe the solution you'd like**
|
||||||
|
A clear and concise description of what you want to happen.
|
||||||
|
|
||||||
|
**Describe alternatives you've considered**
|
||||||
|
A clear and concise description of any alternative solutions or features you've considered.
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context or screenshots about the feature request here.
|
BIN
CNIRevelator Documentation.docx
Normal file
BIN
CNIRevelator Documentation.docx
Normal file
Binary file not shown.
@ -1,5 +1,5 @@
|
|||||||
# CNIRevelator
|
# CNIRevelator
|
||||||
| ![FSF Logo](https://www.os-k.eu/GPLLOGO.PNG) | This program is free software, released under the terms of the [GNU GPL](COPYING) version 3 or later as published by the Free Software Foundation |
|
| ![FSF Logo](https://www.os-k.eu/GPLLOGO.png) | This program is free software, released under the terms of the [GNU GPL](COPYING) version 3 or later as published by the Free Software Foundation |
|
||||||
|----------------------------------------------|----------------------------------------------------------------------|
|
|----------------------------------------------|----------------------------------------------------------------------|
|
||||||
|
|
||||||
### Analyzer for MRZ Codes on identity cards, passports and others for Windows.
|
### Analyzer for MRZ Codes on identity cards, passports and others for Windows.
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
# ver|url|checksum, and | as separator, one version per ||
|
# ver|url|checksum, and | as separator, one version per ||
|
||||||
3.0.4|https://github.com/neox95/CNIRevelator/releases/download/3.0.4/CNIRevelator.zip|d03a18b35dfbb20d90664dc2c0f990adc5522e46||3.0.5|https://github.com/neox95/CNIRevelator/releases/download/3.0.5/CNIRevelator.zip|8b52290fb0910d8b9c4ec43293b08017e0031ca2||3.0.6|https://github.com/neox95/CNIRevelator/releases/download/3.0.6/CNIRevelator.zip|4bb4606dc9310d7b34b1fb38f9a0c2daf9518dc5||3.0.7|https://github.com/neox95/CNIRevelator/releases/download/3.0.7/CNIRevelator.zip|9aea1627c0b75610225a02458d5705563ca0d6af||3.0.8|https://github.com/neox95/CNIRevelator/releases/download/3.0.8/CNIRevelator.zip|8e849f8fcb5c952c09bdd4eb3392456ec9c6cf8f||
|
3.1.6|https://github.com/neox95/CNIRevelator/releases/download/3.1.6/CNIRevelator.zip|8977e1f335d08419be68133fe229ead453279b7f||
|
||||||
|
4
make.bat
4
make.bat
@ -4,9 +4,9 @@ title Compilation de CNIRevelator
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
call pyinstaller -w -D --exclude-module PyQt5 --bootloader-ignore-signals --add-data "C:\Users\adrie\Anaconda3\Lib\site-packages\tld\res\effective_tld_names.dat.txt";"tld\res" --add-data "src\id-card.ico";"id-card.ico" -i "src\id-card.ico" -n CNIRevelator src\CNIRevelator.py
|
call pyinstaller -w -D --exclude-module PyQt5 --bootloader-ignore-signals --add-data "C:\Users\pf04950\AppData\Local\Continuum\anaconda3\Lib\site-packages\tld\res\effective_tld_names.dat.txt";"tld\res" --add-data "src\id-card.ico";"id-card.ico" -i "src\id-card.ico" --version-file "src\version.res" -n CNIRevelator src\CNIRevelator.py
|
||||||
|
|
||||||
|
|
||||||
|
rem call pyi-set_version "src\version.res" "dist\CNIRevelator\CNIRevelator.exe"
|
||||||
|
|
||||||
copy LICENSE dist\CNIRevelator\LICENSE
|
copy LICENSE dist\CNIRevelator\LICENSE
|
||||||
copy src\id-card.ico dist\CNIRevelator\id-card.ico
|
copy src\id-card.ico dist\CNIRevelator\id-card.ico
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
# -*- coding: utf8 -*-
|
||||||
"""
|
"""
|
||||||
********************************************************************************
|
********************************************************************************
|
||||||
* CNIRevelator *
|
* CNIRevelator *
|
||||||
@ -42,7 +43,7 @@ try:
|
|||||||
from tkinter.messagebox import *
|
from tkinter.messagebox import *
|
||||||
from tkinter import *
|
from tkinter import *
|
||||||
except:
|
except:
|
||||||
critical.LASTCHANCECRASH()
|
critical.crashCNIR()
|
||||||
|
|
||||||
# Global handler
|
# Global handler
|
||||||
logfile = logger.logCur
|
logfile = logger.logCur
|
||||||
@ -54,8 +55,8 @@ def main():
|
|||||||
mainw = mainWindow()
|
mainw = mainWindow()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
os.environ['PATH'] = globs.CNIRFolder + '\\Tesseract-OCR4\\'
|
os.environ['PATH'] = globs.CNIRFolder + '\\Tesseract-OCR5\\'
|
||||||
os.environ['TESSDATA_PREFIX'] = globs.CNIRFolder + '\\Tesseract-OCR4\\tessdata'
|
os.environ['TESSDATA_PREFIX'] = globs.CNIRFolder + '\\Tesseract-OCR5\\tessdata'
|
||||||
tesser_version = pytesseract.get_tesseract_version()
|
tesser_version = pytesseract.get_tesseract_version()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logfile.printerr('ERROR WITH TESSERACT MODULE ' + str(e))
|
logfile.printerr('ERROR WITH TESSERACT MODULE ' + str(e))
|
||||||
@ -83,11 +84,13 @@ def main():
|
|||||||
## BOOTSTRAP OF CNIREVELATOR
|
## BOOTSTRAP OF CNIREVELATOR
|
||||||
try:
|
try:
|
||||||
|
|
||||||
|
logfile.printdbg('CNIRevelator log file version {}'.format(globs.verstring_full))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# LANGUAGE
|
# LANGUAGE
|
||||||
lang.readLang()
|
lang.readLang()
|
||||||
except:
|
except:
|
||||||
ihm.crashCNIR()
|
critical.crashCNIR()
|
||||||
updater.exitProcess(1)
|
updater.exitProcess(1)
|
||||||
|
|
||||||
from main import * # main.py
|
from main import * # main.py
|
||||||
@ -96,8 +99,7 @@ try:
|
|||||||
launcherThread = threading.Thread(target=updater.umain, daemon=False)
|
launcherThread = threading.Thread(target=updater.umain, daemon=False)
|
||||||
launcher.lmain(launcherThread)
|
launcher.lmain(launcherThread)
|
||||||
except Exception:
|
except Exception:
|
||||||
ihm.crashCNIR()
|
critical.crashCNIR(False)
|
||||||
updater.exitProcess(1)
|
|
||||||
|
|
||||||
if updater.UPDATE_IS_MADE:
|
if updater.UPDATE_IS_MADE:
|
||||||
# Launch app !
|
# Launch app !
|
||||||
@ -116,10 +118,10 @@ try:
|
|||||||
try:
|
try:
|
||||||
main()
|
main()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
ihm.crashCNIR()
|
critical.crashCNIR()
|
||||||
updater.exitProcess(1)
|
updater.exitProcess(1)
|
||||||
|
|
||||||
except:
|
except:
|
||||||
critical.LASTCHANCECRASH()
|
critical.crashCNIR()
|
||||||
|
|
||||||
updater.exitProcess(0)
|
updater.exitProcess(0)
|
@ -1,3 +1,4 @@
|
|||||||
|
# -*- coding: utf8 -*-
|
||||||
"""
|
"""
|
||||||
********************************************************************************
|
********************************************************************************
|
||||||
* CNIRevelator *
|
* CNIRevelator *
|
||||||
@ -23,6 +24,7 @@
|
|||||||
********************************************************************************
|
********************************************************************************
|
||||||
"""
|
"""
|
||||||
from tkinter.messagebox import *
|
from tkinter.messagebox import *
|
||||||
|
from importlib import reload
|
||||||
from tkinter import *
|
from tkinter import *
|
||||||
import webbrowser
|
import webbrowser
|
||||||
import traceback
|
import traceback
|
||||||
@ -32,25 +34,59 @@ import os
|
|||||||
import lang # lang.py
|
import lang # lang.py
|
||||||
import logger # logger.py
|
import logger # logger.py
|
||||||
import globs # globs.py
|
import globs # globs.py
|
||||||
|
import github # github.py
|
||||||
|
|
||||||
def LASTCHANCECRASH():
|
def crashCNIR(shutdown=True, option="", isVoluntary=False):
|
||||||
"""
|
"""
|
||||||
very last solution
|
very last solution
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
root = Tk()
|
root = Tk()
|
||||||
root.withdraw()
|
root.withdraw()
|
||||||
logfile = logger.logCur
|
logfile = logger.logCur
|
||||||
logfile.printerr("FATAL ERROR : see traceback below.\n{}".format(traceback.format_exc()))
|
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"])
|
|
||||||
|
if not isVoluntary:
|
||||||
|
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"] + "\n\n{}\n{}".format(option, traceback.format_exc()))
|
||||||
|
|
||||||
|
# Force new update
|
||||||
|
try:
|
||||||
|
os.remove(globs.CNIRLastUpdate)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
res = askquestion(lang.all[globs.CNIRlang]["CNIRevelator Fatal Eror"], lang.all[globs.CNIRlang]["Would you like to report this bug ?"])
|
||||||
|
if res == "yes":
|
||||||
|
# read the log
|
||||||
|
data = "No log."
|
||||||
|
try:
|
||||||
|
with open(globs.CNIRMainLog, 'r') as file:
|
||||||
|
data = file.read()
|
||||||
|
except:
|
||||||
|
logfile.printerr("Can't read the log file.")
|
||||||
|
|
||||||
|
# send it
|
||||||
|
success = github.reportBug(traceback.format_exc(), data, isVoluntary)
|
||||||
|
|
||||||
|
if not success:
|
||||||
|
logfile.printerr("Can't send to Github.")
|
||||||
res = askquestion(lang.all[globs.CNIRlang]["CNIRevelator Fatal Eror"], lang.all[globs.CNIRlang]["Would you like to open the log file ?"])
|
res = askquestion(lang.all[globs.CNIRlang]["CNIRevelator Fatal Eror"], lang.all[globs.CNIRlang]["Would you like to open the log file ?"])
|
||||||
if res == "yes":
|
if res == "yes":
|
||||||
webbrowser.open_new(globs.CNIRErrLog)
|
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 ?"])
|
else:
|
||||||
if res == "yes":
|
showinfo(lang.all[globs.CNIRlang]["CNIRevelator Fatal Eror"], lang.all[globs.CNIRlang]["Bug reported successfully. Thanks."])
|
||||||
webbrowser.open_new("https://github.com/neox95/CNIRevelator/issues")
|
|
||||||
root.destroy()
|
root.destroy()
|
||||||
|
|
||||||
|
# Quit ?
|
||||||
|
if not shutdown:
|
||||||
|
return
|
||||||
|
|
||||||
# Quit totally without remain in memory
|
# Quit totally without remain in memory
|
||||||
for process in psutil.process_iter():
|
for process in psutil.process_iter():
|
||||||
if process.pid == os.getpid():
|
if process.pid == os.getpid():
|
||||||
process.terminate()
|
process.terminate()
|
||||||
sys.exit(arg)
|
sys.exit(arg)
|
||||||
|
except:
|
||||||
|
traceback.print_exc()
|
@ -1,3 +1,4 @@
|
|||||||
|
# -*- coding: utf8 -*-
|
||||||
"""
|
"""
|
||||||
********************************************************************************
|
********************************************************************************
|
||||||
* CNIRevelator *
|
* CNIRevelator *
|
||||||
@ -32,6 +33,7 @@ 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
|
||||||
@ -79,10 +81,11 @@ class newcredentials:
|
|||||||
self.trying += 1
|
self.trying += 1
|
||||||
|
|
||||||
try:
|
try:
|
||||||
sessionAnswer = session.get('https://www.google.com')
|
sessionAnswer = session.get('http://www.google.com')
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logfile.printdbg('Network Error : ' + str(e))
|
logfile.printdbg('Network Error : ' + str(e))
|
||||||
sessionAnswer = ''
|
self.login = "nointernet"
|
||||||
|
return
|
||||||
|
|
||||||
logfile.printdbg("Session Answer : " + str(sessionAnswer))
|
logfile.printdbg("Session Answer : " + str(sessionAnswer))
|
||||||
|
|
||||||
@ -92,11 +95,6 @@ class newcredentials:
|
|||||||
self.valid = True
|
self.valid = True
|
||||||
return
|
return
|
||||||
|
|
||||||
if str(sessionAnswer) != '<Response [407]>' and self.trying > 2:
|
|
||||||
# because sometimes the proxy does not return an error (especially if we do not provide either credentials)
|
|
||||||
logfile.printerr('Network Error, or need a proxy !')
|
|
||||||
return
|
|
||||||
|
|
||||||
if self.trying > 4:
|
if self.trying > 4:
|
||||||
logfile.printerr('Invalid credentials : access denied, a maximum of 3 trials have been raised !')
|
logfile.printerr('Invalid credentials : access denied, a maximum of 3 trials have been raised !')
|
||||||
return
|
return
|
||||||
|
189
src/github.py
Normal file
189
src/github.py
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
# -*- coding: utf8 -*-
|
||||||
|
"""
|
||||||
|
********************************************************************************
|
||||||
|
* CNIRevelator *
|
||||||
|
* *
|
||||||
|
* Desc: Github 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 requests.auth import HTTPProxyAuth
|
||||||
|
from pypac import PACSession
|
||||||
|
from Crypto import Random
|
||||||
|
from Crypto.Cipher import AES
|
||||||
|
from requests import Session
|
||||||
|
import json, hashlib, base64
|
||||||
|
|
||||||
|
import logger # logger.py
|
||||||
|
import globs # globs.py
|
||||||
|
|
||||||
|
credentials = False
|
||||||
|
|
||||||
|
class AESCipher(object):
|
||||||
|
|
||||||
|
def __init__(self, key):
|
||||||
|
self.bs = 32
|
||||||
|
self.key = hashlib.sha256(key.encode()).digest()
|
||||||
|
|
||||||
|
def encrypt(self, raw):
|
||||||
|
raw = self._pad(raw)
|
||||||
|
iv = Random.new().read(AES.block_size)
|
||||||
|
cipher = AES.new(self.key, AES.MODE_CBC, iv)
|
||||||
|
return base64.b64encode(iv + cipher.encrypt(raw))
|
||||||
|
|
||||||
|
def decrypt(self, enc):
|
||||||
|
enc = base64.b64decode(enc)
|
||||||
|
iv = enc[:AES.block_size]
|
||||||
|
cipher = AES.new(self.key, AES.MODE_CBC, iv)
|
||||||
|
return self._unpad(cipher.decrypt(enc[AES.block_size:])).decode('utf-8')
|
||||||
|
|
||||||
|
def _pad(self, s):
|
||||||
|
return s + (self.bs - len(s) % self.bs) * chr(self.bs - len(s) % self.bs)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _unpad(s):
|
||||||
|
return s[:-ord(s[len(s) - 1:])]
|
||||||
|
|
||||||
|
def reportBug(reason="",log="", isVoluntary=False):
|
||||||
|
|
||||||
|
logfile = logger.logCur
|
||||||
|
|
||||||
|
if not credentials:
|
||||||
|
logfile.printerr("No credentials")
|
||||||
|
return False
|
||||||
|
|
||||||
|
session = credentials.sessionHandler
|
||||||
|
|
||||||
|
if not isVoluntary:
|
||||||
|
payload = {
|
||||||
|
'title':"CNIRevelator App Bug Report",
|
||||||
|
'body': (
|
||||||
|
"**An error has been reported by a CNIRevelator instance.**\n\n"
|
||||||
|
|
||||||
|
"**Global informations:**\n"
|
||||||
|
"verType = {}\n"
|
||||||
|
"version= {}\n"
|
||||||
|
"verstring_full = {}\n"
|
||||||
|
"CNIRTesserHash = {}\n"
|
||||||
|
"CNIRGitToken = {}\n"
|
||||||
|
"CNIRName = {}\n"
|
||||||
|
"CNIRCryptoKey = {}\n"
|
||||||
|
"CNIRlang = {}\n"
|
||||||
|
"CNIRVerStock = {}\n"
|
||||||
|
"CNIREnv = {}\n"
|
||||||
|
"CNIRBetaURL = {}\n"
|
||||||
|
"CNIRDefaultURL = {}\n"
|
||||||
|
"CNIRNewVersion = {}\n"
|
||||||
|
"CNIROpenFile = {}\n"
|
||||||
|
"debug = {}\n"
|
||||||
|
"\n\n"
|
||||||
|
|
||||||
|
"**Full reason of the crash:**\n{}\n\n"
|
||||||
|
|
||||||
|
"**Full log:** {}"
|
||||||
|
|
||||||
|
).format(
|
||||||
|
globs.verType,
|
||||||
|
globs.version,
|
||||||
|
globs.verstring_full,
|
||||||
|
globs.CNIRTesserHash,
|
||||||
|
globs.CNIRGitToken,
|
||||||
|
globs.CNIRName,
|
||||||
|
globs.CNIRCryptoKey,
|
||||||
|
globs.CNIRlang,
|
||||||
|
globs.CNIRVerStock,
|
||||||
|
globs.CNIREnv,
|
||||||
|
globs.CNIRBetaURL,
|
||||||
|
globs.CNIRDefaultURL,
|
||||||
|
globs.CNIRNewVersion,
|
||||||
|
globs.CNIROpenFile,
|
||||||
|
globs.debug,
|
||||||
|
reason,
|
||||||
|
log
|
||||||
|
),
|
||||||
|
"assignees":["neox95"], "labels":["bug", "AUTO"]
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
payload = {
|
||||||
|
'title':"CNIRevelator User Bug Report",
|
||||||
|
'body': (
|
||||||
|
"**An error has been reported by a CNIRevelator user.**\n\n"
|
||||||
|
|
||||||
|
"**Global informations:**\n"
|
||||||
|
"verType = {}\n"
|
||||||
|
"version= {}\n"
|
||||||
|
"verstring_full = {}\n"
|
||||||
|
"CNIRTesserHash = {}\n"
|
||||||
|
"CNIRGitToken = {}\n"
|
||||||
|
"CNIRName = {}\n"
|
||||||
|
"CNIRCryptoKey = {}\n"
|
||||||
|
"CNIRlang = {}\n"
|
||||||
|
"CNIRVerStock = {}\n"
|
||||||
|
"CNIREnv = {}\n"
|
||||||
|
"CNIRBetaURL = {}\n"
|
||||||
|
"CNIRDefaultURL = {}\n"
|
||||||
|
"CNIRNewVersion = {}\n"
|
||||||
|
"CNIROpenFile = {}\n"
|
||||||
|
"debug = {}\n"
|
||||||
|
"\n\n"
|
||||||
|
|
||||||
|
"**Possible reason:**\n{}\n\n"
|
||||||
|
|
||||||
|
"**Full log:** {}"
|
||||||
|
|
||||||
|
).format(
|
||||||
|
globs.verType,
|
||||||
|
globs.version,
|
||||||
|
globs.verstring_full,
|
||||||
|
globs.CNIRTesserHash,
|
||||||
|
globs.CNIRGitToken,
|
||||||
|
globs.CNIRName,
|
||||||
|
globs.CNIRCryptoKey,
|
||||||
|
globs.CNIRlang,
|
||||||
|
globs.CNIRVerStock,
|
||||||
|
globs.CNIREnv,
|
||||||
|
globs.CNIRBetaURL,
|
||||||
|
globs.CNIRDefaultURL,
|
||||||
|
globs.CNIRNewVersion,
|
||||||
|
globs.CNIROpenFile,
|
||||||
|
globs.debug,
|
||||||
|
reason,
|
||||||
|
log
|
||||||
|
),
|
||||||
|
"assignees":["neox95"], "labels":["bug", "AUTO"]
|
||||||
|
}
|
||||||
|
|
||||||
|
handler = session.post('https://api.github.com/repos/neox95/cnirevelator/issues', headers={'Authorization': 'token %s' % decryptToken(globs.CNIRGitToken)}, data=json.dumps(payload))
|
||||||
|
|
||||||
|
logfile.printdbg("Issue is " + handler.reason)
|
||||||
|
|
||||||
|
if handler.reason == "Created":
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def encryptToken(token):
|
||||||
|
AESObj = AESCipher(globs.CNIRCryptoKey)
|
||||||
|
return AESObj.encrypt(token)
|
||||||
|
|
||||||
|
def decryptToken(token):
|
||||||
|
AESObj = AESCipher(globs.CNIRCryptoKey)
|
||||||
|
return AESObj.decrypt(token)
|
||||||
|
|
||||||
|
|
27
src/globs.py
27
src/globs.py
@ -1,3 +1,4 @@
|
|||||||
|
# -*- coding: utf8 -*-
|
||||||
"""
|
"""
|
||||||
********************************************************************************
|
********************************************************************************
|
||||||
* CNIRevelator *
|
* CNIRevelator *
|
||||||
@ -25,28 +26,13 @@
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
# CNIRevelator version
|
# CNIRevelator version
|
||||||
verType = "final release"
|
verType = "stable release"
|
||||||
version = [3, 1, 0]
|
version = [3, 1, 6]
|
||||||
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])
|
||||||
|
|
||||||
CNIRTesserHash = '5b58db27f7bc08c58a2cb33d01533b034b067cf8'
|
CNIRTesserHash = "947224361ffab8c01f05c9394b44b1bd7c8c3d4d"
|
||||||
CNIRFolder = os.getcwd()
|
CNIRGitToken = "mJHKXqnazO/xZ9Fs18SDMqcGJ15A27OlZyd27cDe5dhHKklO2YShdWwUgEDUZQI02kpgYaLceMidTK37ZqakW+VYgPPuh0e9Ry2IH0KHc3o="
|
||||||
CNIRLColor = "#006699"
|
|
||||||
CNIRName = "CNIRevelator {}".format(verstring)
|
|
||||||
CNIRCryptoKey = '82Xh!efX3#@P~2eG'
|
|
||||||
CNIRNewVersion = False
|
|
||||||
|
|
||||||
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\\'
|
|
||||||
|
|
||||||
|
|
||||||
CNIRTesserHash = '5b58db27f7bc08c58a2cb33d01533b034b067cf8'
|
|
||||||
CNIRFolder = os.path.dirname(os.path.realpath(__file__))
|
CNIRFolder = os.path.dirname(os.path.realpath(__file__))
|
||||||
CNIRLColor = "#006699"
|
CNIRLColor = "#006699"
|
||||||
CNIRName = "CNIRevelator {}".format(verstring)
|
CNIRName = "CNIRevelator {}".format(verstring)
|
||||||
@ -56,10 +42,11 @@ CNIRLangFile = CNIRFolder + '\\config\\lang.ig'
|
|||||||
CNIRlang = "fr"
|
CNIRlang = "fr"
|
||||||
|
|
||||||
CNIRConfig = CNIRFolder + '\\config\\conf.ig'
|
CNIRConfig = CNIRFolder + '\\config\\conf.ig'
|
||||||
CNIRTesser = CNIRFolder + '\\Tesseract-OCR4\\'
|
CNIRTesser = CNIRFolder + '\\Tesseract-OCR5\\'
|
||||||
CNIRErrLog = CNIRFolder + '\\logs\\error.log'
|
CNIRErrLog = CNIRFolder + '\\logs\\error.log'
|
||||||
CNIRMainLog = CNIRFolder + '\\logs\\main.log'
|
CNIRMainLog = CNIRFolder + '\\logs\\main.log'
|
||||||
CNIRUrlConfig = CNIRFolder + '\\config\\urlconf.ig'
|
CNIRUrlConfig = CNIRFolder + '\\config\\urlconf.ig'
|
||||||
|
CNIRLastUpdate = CNIRFolder + '\\config\\lastupdate.ig'
|
||||||
CNIRVerStock = CNIRFolder + '\\downloads\\versions.lst'
|
CNIRVerStock = CNIRFolder + '\\downloads\\versions.lst'
|
||||||
CNIREnv = CNIRFolder + '\\Data\\'
|
CNIREnv = CNIRFolder + '\\Data\\'
|
||||||
|
|
||||||
|
81
src/ihm.py
81
src/ihm.py
@ -1,3 +1,4 @@
|
|||||||
|
# -*- coding: utf8 -*-
|
||||||
"""
|
"""
|
||||||
********************************************************************************
|
********************************************************************************
|
||||||
* CNIRevelator *
|
* CNIRevelator *
|
||||||
@ -23,32 +24,36 @@
|
|||||||
********************************************************************************
|
********************************************************************************
|
||||||
"""
|
"""
|
||||||
|
|
||||||
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 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 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"]
|
||||||
|
|
||||||
class DocumentAsk(Toplevel):
|
class DocumentAsk(Toplevel):
|
||||||
|
|
||||||
def __init__(self, parent, choices):
|
def __init__(self, parent, choices):
|
||||||
self.choice = 0
|
|
||||||
vals = [0, 1]
|
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.title("{} :".format(lang.all[globs.CNIRlang]["Choose the identity document"]))
|
self.title("{} :".format(lang.all[globs.CNIRlang]["Choose the identity document"]))
|
||||||
|
|
||||||
ttk.Radiobutton(self, text=choices[0], command=self.register0, value=vals[0]).pack()
|
self.choice = 0
|
||||||
ttk.Radiobutton(self, text=choices[1], command=self.register1, value=vals[1]).pack()
|
vals = [i[2] for i in choices]
|
||||||
|
for i in range(len(vals)):
|
||||||
|
a = ttk.Radiobutton(self, text=vals[i], command=self.createRegister(i), value=vals[i])
|
||||||
|
a.pack(fill=Y)
|
||||||
|
if i == 0:
|
||||||
|
a.invoke()
|
||||||
|
|
||||||
self.button = Button(self, text='OK', command=(self.ok)).pack()
|
self.button = Button(self, text='OK', command=(self.ok)).pack()
|
||||||
self.resizable(width=False, height=False)
|
self.resizable(width=False, height=False)
|
||||||
@ -65,10 +70,11 @@ class DocumentAsk(Toplevel):
|
|||||||
y = hs / 2 - h / 2
|
y = hs / 2 - h / 2
|
||||||
self.geometry('%dx%d+%d+%d' % (w, h, x, y))
|
self.geometry('%dx%d+%d+%d' % (w, h, x, y))
|
||||||
|
|
||||||
def register0(self):
|
def createRegister(self, i):
|
||||||
self.choice = 0
|
def register():
|
||||||
def register1(self):
|
self.choice = i
|
||||||
self.choice = 1
|
return register
|
||||||
|
|
||||||
def ok(self):
|
def ok(self):
|
||||||
self.destroy()
|
self.destroy()
|
||||||
|
|
||||||
@ -190,7 +196,7 @@ class ChangelogDialog(Toplevel):
|
|||||||
|
|
||||||
class langDialog(Toplevel):
|
class langDialog(Toplevel):
|
||||||
|
|
||||||
def __init__(self, parent):
|
def __init__(self, parent, currentLang):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
|
|
||||||
self.title(lang.all[globs.CNIRlang]["Language"])
|
self.title(lang.all[globs.CNIRlang]["Language"])
|
||||||
@ -199,7 +205,10 @@ class langDialog(Toplevel):
|
|||||||
|
|
||||||
vals = [i for i in lang.all]
|
vals = [i for i in lang.all]
|
||||||
for i in range(len(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)
|
a = ttk.Radiobutton(self, text=vals[i], command=self.createRegister(i), value=vals[i])
|
||||||
|
a.pack(fill=Y)
|
||||||
|
if i == vals.index(currentLang):
|
||||||
|
a.invoke()
|
||||||
|
|
||||||
ttk.Button(self, text="OK", command=(self.oki)).pack(fill=Y, pady=5)
|
ttk.Button(self, text="OK", command=(self.oki)).pack(fill=Y, pady=5)
|
||||||
|
|
||||||
@ -228,7 +237,7 @@ class langDialog(Toplevel):
|
|||||||
|
|
||||||
class updateSetDialog(Toplevel):
|
class updateSetDialog(Toplevel):
|
||||||
|
|
||||||
def __init__(self, parent):
|
def __init__(self, parent, currentChannel):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
|
|
||||||
self.title(lang.all[globs.CNIRlang]["Update options"])
|
self.title(lang.all[globs.CNIRlang]["Update options"])
|
||||||
@ -238,7 +247,11 @@ class updateSetDialog(Toplevel):
|
|||||||
self.vals = ["Stable", "Beta"]
|
self.vals = ["Stable", "Beta"]
|
||||||
vals = self.vals
|
vals = self.vals
|
||||||
for i in range(len(vals)):
|
for i in range(len(vals)):
|
||||||
ttk.Radiobutton(self, text=vals[i], command=self.createRegister(i), value=vals[i]).pack(fill=Y)
|
a = ttk.Radiobutton(self, text=vals[i], command=self.createRegister(i), value=vals[i])
|
||||||
|
a.pack(fill=Y)
|
||||||
|
if i == self.vals.index(currentChannel):
|
||||||
|
a.invoke()
|
||||||
|
|
||||||
|
|
||||||
ttk.Button(self, text="OK", command=(self.oki)).pack(fill=Y, pady=5)
|
ttk.Button(self, text="OK", command=(self.oki)).pack(fill=Y, pady=5)
|
||||||
|
|
||||||
@ -262,7 +275,7 @@ class updateSetDialog(Toplevel):
|
|||||||
|
|
||||||
def createRegister(self, i):
|
def createRegister(self, i):
|
||||||
def register():
|
def register():
|
||||||
updater.updateChannel(self.vals[i])
|
updater.setUpdateChannel(self.vals[i])
|
||||||
return register
|
return register
|
||||||
|
|
||||||
class LauncherWindow(Tk):
|
class LauncherWindow(Tk):
|
||||||
@ -272,6 +285,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()
|
||||||
@ -287,8 +306,6 @@ class LauncherWindow(Tk):
|
|||||||
# if getattr(sys, 'frozen', False):
|
# if getattr(sys, 'frozen', False):
|
||||||
# cv_img = cv2.imread(sys._MEIPASS + r"\background.png\background.png")
|
# cv_img = cv2.imread(sys._MEIPASS + r"\background.png\background.png")
|
||||||
# else:
|
# else:
|
||||||
cv_img = cv2.imread("background.png")
|
|
||||||
|
|
||||||
cv_img = cv2.imread("background.png")
|
cv_img = cv2.imread("background.png")
|
||||||
cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB)
|
cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB)
|
||||||
cv_img = cv2.blur(cv_img, (15, 15))
|
cv_img = cv2.blur(cv_img, (15, 15))
|
||||||
@ -320,11 +337,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)
|
||||||
@ -367,28 +379,7 @@ class StatusBar(Frame):
|
|||||||
self.label.config(text="")
|
self.label.config(text="")
|
||||||
self.label.update_idletasks()
|
self.label.update_idletasks()
|
||||||
|
|
||||||
## Crash
|
|
||||||
|
|
||||||
def crashCNIR():
|
|
||||||
"""
|
|
||||||
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 the log file ?"])
|
|
||||||
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 ?"])
|
|
||||||
if res == "yes":
|
|
||||||
webbrowser.open_new("https://github.com/neox95/CNIRevelator/issues")
|
|
||||||
root.destroy()
|
|
||||||
|
|
||||||
|
|
||||||
## Global Handler
|
## Global Handler
|
||||||
launcherWindowCur = LauncherWindow()
|
launcherWindowCur = LauncherWindow()
|
||||||
|
|
||||||
|
# test ?
|
||||||
|
95
src/lang.py
95
src/lang.py
@ -1,3 +1,4 @@
|
|||||||
|
# -*- coding: utf8 -*-
|
||||||
"""
|
"""
|
||||||
********************************************************************************
|
********************************************************************************
|
||||||
* CNIRevelator *
|
* CNIRevelator *
|
||||||
@ -25,6 +26,7 @@
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
import globs # globs.py
|
import globs # globs.py
|
||||||
|
import critical # critical.py
|
||||||
|
|
||||||
## FRENCH LANGUAGE
|
## FRENCH LANGUAGE
|
||||||
french = \
|
french = \
|
||||||
@ -49,11 +51,13 @@ french = \
|
|||||||
"CNIRevelator crashed because a "
|
"CNIRevelator crashed because a "
|
||||||
"fatal error occured. View log for "
|
"fatal error occured. View log for "
|
||||||
"more infos and please open "
|
"more infos and please open "
|
||||||
"an issue on Github" : "CNIRevelator s'est arrêté car une erreur fatale s'est produite. Consultez le journal pour plus d'informations et ouvrez s'il vous plaît un ticket sur Github.",
|
"an issue on Github" : "CNIRevelator s'est arrêté car une erreur fatale s'est produite. Consultez le journal pour plus d'informations et signalez le bogue.",
|
||||||
"Would you like to open the "
|
"Would you like to open the "
|
||||||
"log file ?" : "Souhaitez-vous ouvrir le fichier de log ?",
|
"log file ?" : "Le signalement a échoué. Souhaitez-vous ouvrir le fichier de log ?",
|
||||||
"Would you like to open an issue "
|
"Bug reported successfully. "
|
||||||
"on Github to report this bug ?" : "Souhaitez-vous ouvrir un ticket sur Github pour signaler ce bogue?",
|
"Thanks." : "Bogue signalé avec succès, merci.",
|
||||||
|
"Would you like to report this "
|
||||||
|
"bug ?" : "Souhaitez-vous signaler ce bogue?",
|
||||||
"Starting..." : "Lancement...",
|
"Starting..." : "Lancement...",
|
||||||
"Informations about the current "
|
"Informations about the current "
|
||||||
"document" : "Informations sur la pièce d'identité",
|
"document" : "Informations sur la pièce d'identité",
|
||||||
@ -68,6 +72,8 @@ french = \
|
|||||||
"Nationality" : "Nationalité",
|
"Nationality" : "Nationalité",
|
||||||
"Registration" : "Immatriculation",
|
"Registration" : "Immatriculation",
|
||||||
"Document number" : "N° de document",
|
"Document number" : "N° de document",
|
||||||
|
"Length" : "Longueur",
|
||||||
|
"Facultative" : "Facultatif",
|
||||||
"Unknown" : "Inconnu(e)",
|
"Unknown" : "Inconnu(e)",
|
||||||
"Display and processing of "
|
"Display and processing of "
|
||||||
"documents" : "Affichage et traitement de documents",
|
"documents" : "Affichage et traitement de documents",
|
||||||
@ -137,7 +143,13 @@ french = \
|
|||||||
"Coller :\t\t\t\tCtrl-V \n"
|
"Coller :\t\t\t\tCtrl-V \n"
|
||||||
"Forcer une nouvelle détection du document :\tEchap\n",
|
"Forcer une nouvelle détection du document :\tEchap\n",
|
||||||
|
|
||||||
"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\n- Rationalisation du système de langues\n- Ajout des canaux de mise-à-jour\n\n" + \
|
"CHANGELOG" : "Version 3.1.5 \nMise-à-jour mineure avec les progressions suivantes :\n- Ajout de la longueur de la MRZ dans les informations\n- Correction d'un bug affectant les Visas\n\n" + \
|
||||||
|
"Version 3.1.5 \nMise-à-jour mineure avec les progressions suivantes :\n- Correction d'un bug affectant le signalement de bug\n- Améliorations de l'affichage de la conformité des informations\n- Ajout d'un nouveau système de selection plus simple et fiable'\n\n" + \
|
||||||
|
"Version 3.1.4 \nMise-à-jour mineure avec les progressions suivantes :\n- Correction d'un bug affectant la rotation de documents dans l'afficheur d'images\n- Ajout d'une période de mise-à-jour afin d'éviter de rechercher les mises-à-jour tous les jours\n\n" + \
|
||||||
|
"Version 3.1.3 \nMise-à-jour mineure avec les progressions suivantes :\n- Correction d'un bug de la détection automatique de documents\n- Ajout d'une fonctionnalité de rapport d'erreur\n\n" + \
|
||||||
|
"Version 3.1.2 \nMise-à-jour mineure avec les progressions suivantes :\n- Montée de version de Tesseract OCR : 5.0\n- Correction de noms des documents\n- Résolution d'un problème avec le système de mise-à-jour\n- Amélioration des effets sur images\n\n" + \
|
||||||
|
"Version 3.1.1 \nMise-à-jour mineure avec les progressions suivantes :\n- Correction d'un bug sévère du système de mise à jour\n\n" + \
|
||||||
|
"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\n- Rationalisation du système de langues\n- Ajout des canaux de mise-à-jour\n\n" + \
|
||||||
"Version 3.0.8 finale\nCorrectif : bug du système de mise-à-jour'\n\n" + \
|
"Version 3.0.8 finale\nCorrectif : bug du système de mise-à-jour'\n\n" + \
|
||||||
"Version 3.0.6 \nMise-à-jour mineure avec les corrections suivantes :\n- Changement de l'apparence du launcher de l'application\n- Améliorations de l'interface, notamment de la stabilité\n- Ajout de la signature numérique de l'exécutable\n\n" + \
|
"Version 3.0.6 \nMise-à-jour mineure avec les corrections suivantes :\n- Changement de l'apparence du launcher de l'application\n- Améliorations de l'interface, notamment de la stabilité\n- Ajout de la signature numérique de l'exécutable\n\n" + \
|
||||||
"Version 3.0.7 finale\nMise-à-jour majeure avec les corrections suivantes :\n- Refonte de l'interface utilisateur\n- Fonction OCR intégrée à l'application avec support des TIFF et JPEG\n- Corrections d'erreurs sur le traitement des VISA de type A et B, ainsi que les titres de séjour\n\n" + \
|
"Version 3.0.7 finale\nMise-à-jour majeure avec les corrections suivantes :\n- Refonte de l'interface utilisateur\n- Fonction OCR intégrée à l'application avec support des TIFF et JPEG\n- Corrections d'erreurs sur le traitement des VISA de type A et B, ainsi que les titres de séjour\n\n" + \
|
||||||
@ -149,7 +161,8 @@ french = \
|
|||||||
"Version 3.0.1 \nMise-à-jour majeure avec les corrections suivantes :\n- Renouvellement de la signature numérique de l'exécutable\n- Amélioration de présentation du log en cas d'erreur\n- Refonte totale du code source et désobfuscation\n- Téléchargements en HTTPS fiables avec somme de contrôle\n- Nouveaux terminaux d'entrées : un rapide (731) et un complet\n- Détection des documents améliorée, possibilité de choix plus fin\nEt les regressions suivantes :\n- Suppression temporaire de la fonction de lecture OCR. Retour planifié pour une prochaine version",
|
"Version 3.0.1 \nMise-à-jour majeure avec les corrections suivantes :\n- Renouvellement de la signature numérique de l'exécutable\n- Amélioration de présentation du log en cas d'erreur\n- Refonte totale du code source et désobfuscation\n- Téléchargements en HTTPS fiables avec somme de contrôle\n- Nouveaux terminaux d'entrées : un rapide (731) et un complet\n- Détection des documents améliorée, possibilité de choix plus fin\nEt les regressions suivantes :\n- Suppression temporaire de la fonction de lecture OCR. Retour planifié pour une prochaine version",
|
||||||
|
|
||||||
"Document Review: {}\n\n" : "Examen du document : {}\n\n",
|
"Document Review: {}\n\n" : "Examen du document : {}\n\n",
|
||||||
"Calculated {} [facultative]\n" : "Checksum position {}: Lu {} VS Calculé {} [facultatif]\n",
|
"Checksum position {}: Lu {} "
|
||||||
|
"VS Calculated {} [facultative]\n" : "Checksum position {}: Lu {} VS Calculé {} [facultatif]\n",
|
||||||
"Checksum position {}: Lu {} VS "
|
"Checksum position {}: Lu {} VS "
|
||||||
"Calculated {}\n" : "Checksum position {}: Lu {} VS Calculé {}\n",
|
"Calculated {}\n" : "Checksum position {}: Lu {} VS Calculé {}\n",
|
||||||
"COMPLIANT" : "CONFORME",
|
"COMPLIANT" : "CONFORME",
|
||||||
@ -177,16 +190,30 @@ french = \
|
|||||||
"Please choose your language : " : "Merci de choisir votre langue : ",
|
"Please choose your language : " : "Merci de choisir votre langue : ",
|
||||||
"Please choose your update "
|
"Please choose your update "
|
||||||
"channel : " : "Merci de choisir votre canal de mise-à-jour : ",
|
"channel : " : "Merci de choisir votre canal de mise-à-jour : ",
|
||||||
"Passeport" : "Passeport",
|
"Passeport lisible à la machine" : "Passeport lisible à la machine",
|
||||||
"Carte-passeport" : "Carte-passeport",
|
"Carte-passeport" : "Carte-passeport",
|
||||||
"Titre d'identité/de voyage" : "Titre d'identité/de voyage",
|
"Titre d'identité/de voyage" : "Titre d'identité/de voyage",
|
||||||
|
"Carte d’identité européenne" : "Carte d’identité européenne",
|
||||||
"Certificat de membre d'équipage" : "Certificat de membre d'équipage",
|
"Certificat de membre d'équipage" : "Certificat de membre d'équipage",
|
||||||
|
"Carte de séjour européenne" : "Carte de séjour européenne",
|
||||||
"Visa de type A" : "Visa de type A",
|
"Visa de type A" : "Visa de type A",
|
||||||
"Visa de type B" : "Visa de type B",
|
"Visa de type B" : "Visa de type B",
|
||||||
"Carte de séjour" : "Carte de séjour",
|
"Carte de séjour FR" : "Carte de séjour français",
|
||||||
"Pièce d'identité/de voyage" : "Pièce d'identité/de voyage",
|
"Pièce d'identité/de voyage" : "Pièce d'identité/de voyage",
|
||||||
"Pièce d'identité FR" : "Pièce d'identité FR",
|
"Pièce d'identité FR" : "Pièce d'identité française",
|
||||||
"Permis de conduire" : "Permis de conduire",
|
"Permis de conduire" : "Permis de conduire",
|
||||||
|
"The file you provided is not "
|
||||||
|
"valid : {}" : "Le fichier transmis n'est pas valide : {}",
|
||||||
|
"A critical error has occurred in "
|
||||||
|
"the OpenCV image processing "
|
||||||
|
"manager used by CNIRevelator. "
|
||||||
|
"Please be sure that the filename "
|
||||||
|
"does not contain any non unicode "
|
||||||
|
"character such as accent and "
|
||||||
|
"foreign characters." : "Une erreur critique s'est produite dans le gestionnaire de traitement d'images OpenCV utilisé par CNIRevelator. Veuillez vous assurer que le nom de fichier ne contient pas de caractères non unicode tels que des accents et des caractères étrangers.",
|
||||||
|
"No Internet Error. No effective "
|
||||||
|
"update !" : "Aucune connectivité. Pas de mise-à-jour !",
|
||||||
|
"Project Webpage" : "Site internet du projet",
|
||||||
|
|
||||||
"LANDCODE2" : {
|
"LANDCODE2" : {
|
||||||
'AW': 'Aruba',
|
'AW': 'Aruba',
|
||||||
@ -735,11 +762,13 @@ english = \
|
|||||||
"CNIRevelator crashed because a "
|
"CNIRevelator crashed because a "
|
||||||
"fatal error occured. View log for "
|
"fatal error occured. View log for "
|
||||||
"more infos and please open "
|
"more infos and please open "
|
||||||
"an issue on Github" : "CNIRevelator crashed because a fatal error occured. View log for more infos and please open an issue on Github",
|
"an issue on Github" : "CNIRevelator crashed because a fatal error occured. View log for more infos and please report this bug.",
|
||||||
"Would you like to open an issue "
|
"Would you like to report this "
|
||||||
"on Github to report this bug ?" : "Would you like to open an issue on Github to report this bug ?",
|
"bug ?" : "Would you like to report this bug ?",
|
||||||
"Would you like to open the "
|
"Would you like to open the "
|
||||||
"log file ?" : "Would you like to open the log file ?",
|
"log file ?" : "Reporting the bug has failed. Would you like to open the log file ?",
|
||||||
|
"Bug reported successfully. "
|
||||||
|
"Thanks." : "Bug reported successfully. Thanks.",
|
||||||
"Starting..." : "Starting...",
|
"Starting..." : "Starting...",
|
||||||
"Informations about the current "
|
"Informations about the current "
|
||||||
"document" : "Informations about the current document",
|
"document" : "Informations about the current document",
|
||||||
@ -754,6 +783,8 @@ english = \
|
|||||||
"Nationality" : "Nationality",
|
"Nationality" : "Nationality",
|
||||||
"Registration" : "Registration",
|
"Registration" : "Registration",
|
||||||
"Document number" : "Document number",
|
"Document number" : "Document number",
|
||||||
|
"Length" : "Length",
|
||||||
|
"Facultative" : "Facultative",
|
||||||
"Unknown" : "Unknown",
|
"Unknown" : "Unknown",
|
||||||
"Display and processing of "
|
"Display and processing of "
|
||||||
"documents" : "Display and processing of documents",
|
"documents" : "Display and processing of documents",
|
||||||
@ -787,6 +818,8 @@ english = \
|
|||||||
"the OpenCV image processing "
|
"the OpenCV image processing "
|
||||||
"manager used by CNIRevelator, the "
|
"manager used by CNIRevelator, the "
|
||||||
"application will reset itself" : "A critical error has occurred in the OpenCV image processing manager used by CNIRevelator, the application will reset itself",
|
"application will reset itself" : "A critical error has occurred in the OpenCV image processing manager used by CNIRevelator, the application will reset itself",
|
||||||
|
"No Internet Error. No effective "
|
||||||
|
"update !" : "No Internet Error. No effective update !",
|
||||||
|
|
||||||
"ABOUT" : 'Software Version: CNIRevelator' + globs.verstring_full + '\n\n'
|
"ABOUT" : 'Software Version: CNIRevelator' + globs.verstring_full + '\n\n'
|
||||||
"Copyright © 2018-2019 Adrien Bourmault (neox95)" + "\n\n"
|
"Copyright © 2018-2019 Adrien Bourmault (neox95)" + "\n\n"
|
||||||
@ -825,7 +858,13 @@ english = \
|
|||||||
"Paste:\t\t\t\tCtrl-V\n"
|
"Paste:\t\t\t\tCtrl-V\n"
|
||||||
"Force a new document detection:\tEchap\n",
|
"Force a new document detection:\tEchap\n",
|
||||||
|
|
||||||
"CHANGELOG" : "Version 3.1.0 \nMajor update with the following progressions: \n- Cosmetic modifications of the user interface \n- Stabilization of the changes made on the minor version 3.0 : user interface, OCR, VISA A and B, logging\n- Rationalization of the language system\n- Added update channels\n\n" + \
|
"CHANGELOG" : "Version 3.1.6 \nMinor update with the following progressionss :\n- Added MRZ length in the information\n- Fixed a bug affecting Visas\n\n" + \
|
||||||
|
"Version 3.1.5 \nMinor update with the following progressions:\n- Correction of a bug affecting bug reporting\n - Enhancements on information compliance display\n- Added new selection system to be more userfriendly\n\n" + \
|
||||||
|
"Version 3.1.4 \nMinor update with the following progressions:\n- Correction of a bug affecting rotation of document in image viewer\n- Added a new update period to prevent updating everyday\n\n" + \
|
||||||
|
"Version 3.1.3 \nMinor update with the following progressions:\n- Correction of a bug affecting automated document detection\n- Added bug reporting functionnality\n\n" + \
|
||||||
|
"Version 3.1.2 \nMinor update with the following progressions: \n- Tesseract OCR version upgrade : 5.0\n- Correction of document names\n- Fixed a problem with the update system\n- Some enhancements about effects on images\n\n" + \
|
||||||
|
"Version 3.1.1 \nMinor update with the following progressions: \n- Fixed a severe bug in the update system\n\n" + \
|
||||||
|
"Version 3.1.0 \nMajor update with the following progressions: \n- Cosmetic modifications of the user interface \n- Stabilization of the changes made on the minor version 3.0 : user interface, OCR, VISA A and B, logging\n- Rationalization of the language system\n- Added update channels\n\n" + \
|
||||||
"Version 3.0.8 final\nCorrection: bug in the update system'\n\n" + \
|
"Version 3.0.8 final\nCorrection: bug in the update system'\n\n" + \
|
||||||
"Version 3.0.6 \nMinor update with the following fixes:\n- Change in the appearance of the application launcher\n- Improvements to the interface, including stability\n- Added digital signature of the executable\n" + \
|
"Version 3.0.6 \nMinor update with the following fixes:\n- Change in the appearance of the application launcher\n- Improvements to the interface, including stability\n- Added digital signature of the executable\n" + \
|
||||||
"Version 3.0.7 final\nMajor update with the following corrections: \n- Redesign of the user interface\n- OCR function integrated into the application with TIFF and JPEG support\n- Corrections of errors on the processing of VISA type A and B, as well as residence permits\n\n" + \
|
"Version 3.0.7 final\nMajor update with the following corrections: \n- Redesign of the user interface\n- OCR function integrated into the application with TIFF and JPEG support\n- Corrections of errors on the processing of VISA type A and B, as well as residence permits\n\n" + \
|
||||||
@ -837,8 +876,8 @@ english = \
|
|||||||
"Version 3.0.1 \nMajor update with the following corrections: \n- Renewal of the executable's digital signature- Improvement of the log presentation in case of error\n- Total overhaul of the source code and disobfuscation\n- Reliable HTTPS downloads with checksum\n- New input terminals : a fast (731) and a complete one\n- Improved document detection, possibility of finer choice and the following regressions:\n- Temporary deletion of the OCR reading function. Planned return for a next version",
|
"Version 3.0.1 \nMajor update with the following corrections: \n- Renewal of the executable's digital signature- Improvement of the log presentation in case of error\n- Total overhaul of the source code and disobfuscation\n- Reliable HTTPS downloads with checksum\n- New input terminals : a fast (731) and a complete one\n- Improved document detection, possibility of finer choice and the following regressions:\n- Temporary deletion of the OCR reading function. Planned return for a next version",
|
||||||
|
|
||||||
"Document Review: {}\n\n" : "Document Review: {}\n\n",
|
"Document Review: {}\n\n" : "Document Review: {}\n\n",
|
||||||
"Checksum position {}: Lu {} VS "
|
"Checksum position {}: Lu {} "
|
||||||
"Calculated {} [facultative]\n" : "Checksum position {}: Read {} VS Calculated {} [facultative]\n",
|
"VS Calculated {} [facultative]\n" : "Checksum position {}: Lu {} VS Calculated {} [facultative]\n",
|
||||||
"Checksum position {}: Lu {} VS "
|
"Checksum position {}: Lu {} VS "
|
||||||
"Calculated {}\n" : "Checksum position {}: Read {} VS Calculated {}\n",
|
"Calculated {}\n" : "Checksum position {}: Read {} VS Calculated {}\n",
|
||||||
"COMPLIANT" : "COMPLIANT",
|
"COMPLIANT" : "COMPLIANT",
|
||||||
@ -866,16 +905,28 @@ english = \
|
|||||||
"Please choose your language : " : "Please choose your language : ",
|
"Please choose your language : " : "Please choose your language : ",
|
||||||
"Please choose your update "
|
"Please choose your update "
|
||||||
"channel : " : "Please choose your update channel : ",
|
"channel : " : "Please choose your update channel : ",
|
||||||
"Passeport" : "Passport",
|
"Passeport lisible à la machine" : "Machine Readable Passport",
|
||||||
"Carte-passeport" : "Passport card",
|
"Carte-passeport" : "Passport card",
|
||||||
|
"Carte d’identité européenne" : "European identity document",
|
||||||
|
"Carte de séjour européenne" : "European Residence permit",
|
||||||
"Titre d'identité/de voyage" : "Identity/travel document",
|
"Titre d'identité/de voyage" : "Identity/travel document",
|
||||||
"Certificat de membre d'équipage" : "Crew member certificate",
|
"Certificat de membre d'équipage" : "Crew member certificate",
|
||||||
"Visa de type A" : "Type A visa",
|
"Visa de type A" : "Type A visa",
|
||||||
"Visa de type B" : "Type B visa",
|
"Visa de type B" : "Type B visa",
|
||||||
"Carte de séjour" : "Residence permit",
|
"Carte de séjour FR" : "French Residence permit",
|
||||||
"Pièce d'identité/de voyage" : "Identity/travel document",
|
"Pièce d'identité/de voyage" : "Identity/travel document",
|
||||||
"Pièce d'identité FR" : "French Identity card",
|
"Pièce d'identité FR" : "French Identity card",
|
||||||
"Permis de conduire" : "Driver License",
|
"Permis de conduire" : "Driver License",
|
||||||
|
"The file you provided is not "
|
||||||
|
"valid : {}" : "The file you provided is not valid : {}",
|
||||||
|
"A critical error has occurred in "
|
||||||
|
"the OpenCV image processing "
|
||||||
|
"manager used by CNIRevelator. "
|
||||||
|
"Please be sure that the filename "
|
||||||
|
"does not contain any non unicode "
|
||||||
|
"character such as accent and "
|
||||||
|
"foreign characters." : "A critical error has occurred in the OpenCV image processing manager used by CNIRevelator. Please be sure that the filename does not contain any non unicode character such as accent and foreign characters.",
|
||||||
|
"Project Webpage" : "Project website",
|
||||||
|
|
||||||
"LANDCODE2" : {
|
"LANDCODE2" : {
|
||||||
"AW": "Aruba",
|
"AW": "Aruba",
|
||||||
@ -1418,7 +1469,7 @@ def readLang():
|
|||||||
# Reading it
|
# Reading it
|
||||||
globs.CNIRlang = configFile.read()
|
globs.CNIRlang = configFile.read()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
ihm.crashCNIR()
|
critical.crashCNIR()
|
||||||
raise IOError(str(e))
|
raise IOError(str(e))
|
||||||
else:
|
else:
|
||||||
# Recreating the url file
|
# Recreating the url file
|
||||||
@ -1432,7 +1483,7 @@ def readLang():
|
|||||||
# Writing it
|
# Writing it
|
||||||
configFile.write(globs.CNIRlang)
|
configFile.write(globs.CNIRlang)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
ihm.crashCNIR()
|
critical.crashCNIR()
|
||||||
raise IOError(str(e))
|
raise IOError(str(e))
|
||||||
|
|
||||||
def updateLang(choice):
|
def updateLang(choice):
|
||||||
@ -1444,7 +1495,7 @@ def updateLang(choice):
|
|||||||
globs.CNIRlang = choice
|
globs.CNIRlang = choice
|
||||||
configFile.write(choice)
|
configFile.write(choice)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
ihm.crashCNIR()
|
critical.crashCNIR()
|
||||||
raise IOError(str(e))
|
raise IOError(str(e))
|
||||||
else:
|
else:
|
||||||
# Recreating the url file
|
# Recreating the url file
|
||||||
@ -1458,5 +1509,5 @@ def updateLang(choice):
|
|||||||
# Writing it
|
# Writing it
|
||||||
configFile.write(globs.CNIRlang)
|
configFile.write(globs.CNIRlang)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
ihm.crashCNIR()
|
critical.crashCNIR()
|
||||||
raise IOError(str(e))
|
raise IOError(str(e))
|
@ -1,3 +1,4 @@
|
|||||||
|
# -*- coding: utf8 -*-
|
||||||
"""
|
"""
|
||||||
********************************************************************************
|
********************************************************************************
|
||||||
* CNIRevelator *
|
* CNIRevelator *
|
||||||
@ -27,6 +28,7 @@ import sys
|
|||||||
import os
|
import os
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
|
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
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
# -*- coding: utf8 -*-
|
||||||
"""
|
"""
|
||||||
********************************************************************************
|
********************************************************************************
|
||||||
* CNIRevelator *
|
* CNIRevelator *
|
||||||
@ -26,6 +27,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
|
||||||
|
211
src/main.py
211
src/main.py
@ -1,3 +1,4 @@
|
|||||||
|
# -*- coding: utf8 -*-
|
||||||
"""
|
"""
|
||||||
********************************************************************************
|
********************************************************************************
|
||||||
* CNIRevelator *
|
* CNIRevelator *
|
||||||
@ -32,19 +33,23 @@ from tkinter import ttk
|
|||||||
import threading
|
import threading
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from importlib import reload
|
from importlib import reload
|
||||||
|
import unicodedata
|
||||||
import re
|
import re
|
||||||
import cv2
|
import cv2
|
||||||
import PIL.Image, PIL.ImageTk
|
import PIL.Image, PIL.ImageTk
|
||||||
import os, shutil
|
import os, shutil
|
||||||
import webbrowser
|
|
||||||
import sys, os
|
import sys, os
|
||||||
|
import numpy
|
||||||
|
import webbrowser
|
||||||
|
|
||||||
|
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
|
import lang # lang.py
|
||||||
|
import updater # updater.py
|
||||||
|
|
||||||
# Global handler
|
# Global handler
|
||||||
logfile = logger.logCur
|
logfile = logger.logCur
|
||||||
@ -66,8 +71,15 @@ class mainWindow(Tk):
|
|||||||
self.Tags = []
|
self.Tags = []
|
||||||
self.compliance = True
|
self.compliance = True
|
||||||
self.corners = []
|
self.corners = []
|
||||||
|
self.indicators = []
|
||||||
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()
|
||||||
|
|
||||||
@ -98,6 +110,7 @@ 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)
|
||||||
|
self.lecteur_ci.grid_rowconfigure(6, weight=1)
|
||||||
|
|
||||||
# And what about the status bar ?
|
# And what about the status bar ?
|
||||||
self.statusbar = ihm.StatusBar(self)
|
self.statusbar = ihm.StatusBar(self)
|
||||||
@ -138,6 +151,9 @@ class mainWindow(Tk):
|
|||||||
ttk.Label((self.lecteur_ci), text='{} : '.format(lang.all[globs.CNIRlang]["Document number"])).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)
|
||||||
|
ttk.Label((self.lecteur_ci), text='{} : '.format(lang.all[globs.CNIRlang]["Length"])).grid(column=0, row=6, padx=5, pady=5)
|
||||||
|
self.len = ttk.Label((self.lecteur_ci), text=' ')
|
||||||
|
self.len.grid(column=1, row=6, padx=5, pady=5)
|
||||||
|
|
||||||
self.nom['text'] = lang.all[globs.CNIRlang]["Unknown"]
|
self.nom['text'] = lang.all[globs.CNIRlang]["Unknown"]
|
||||||
self.prenom['text'] = lang.all[globs.CNIRlang]["Unknown"]
|
self.prenom['text'] = lang.all[globs.CNIRlang]["Unknown"]
|
||||||
@ -149,6 +165,7 @@ class mainWindow(Tk):
|
|||||||
self.nat['text'] = lang.all[globs.CNIRlang]["Unknown"]
|
self.nat['text'] = lang.all[globs.CNIRlang]["Unknown"]
|
||||||
self.pays['text'] = lang.all[globs.CNIRlang]["Unknown"]
|
self.pays['text'] = lang.all[globs.CNIRlang]["Unknown"]
|
||||||
self.indic['text'] = lang.all[globs.CNIRlang]["Unknown"]
|
self.indic['text'] = lang.all[globs.CNIRlang]["Unknown"]
|
||||||
|
self.len['text'] = lang.all[globs.CNIRlang]["Unknown"]
|
||||||
|
|
||||||
|
|
||||||
self.infoList = \
|
self.infoList = \
|
||||||
@ -163,6 +180,7 @@ class mainWindow(Tk):
|
|||||||
"NAT" : self.nat,
|
"NAT" : self.nat,
|
||||||
"PAYS" : self.pays,
|
"PAYS" : self.pays,
|
||||||
"INDIC" : self.indic,
|
"INDIC" : self.indic,
|
||||||
|
"LEN" : self.len,
|
||||||
}
|
}
|
||||||
|
|
||||||
# The the image viewer
|
# The the image viewer
|
||||||
@ -222,7 +240,7 @@ class mainWindow(Tk):
|
|||||||
self.toolbar.zoomOut50.grid(column=5, row=0)
|
self.toolbar.zoomOut50.grid(column=5, row=0)
|
||||||
|
|
||||||
self.toolbar.invertImg = ImageTk.PhotoImage(PIL.Image.open("invert.png"))
|
self.toolbar.invertImg = ImageTk.PhotoImage(PIL.Image.open("invert.png"))
|
||||||
self.toolbar.invert = ttk.Button(self.toolbar, image=self.toolbar.invertImg, command=self.negativeScan)
|
self.toolbar.invert = ttk.Button(self.toolbar, image=self.toolbar.invertImg, command=self.threshScan)
|
||||||
self.toolbar.invert.grid(column=7, row=0)
|
self.toolbar.invert.grid(column=7, row=0)
|
||||||
|
|
||||||
self.toolbar.rotateLeftImg = ImageTk.PhotoImage(PIL.Image.open("rotateLeft.png"))
|
self.toolbar.rotateLeftImg = ImageTk.PhotoImage(PIL.Image.open("rotateLeft.png"))
|
||||||
@ -302,9 +320,9 @@ class mainWindow(Tk):
|
|||||||
self.speed731.grid_columnconfigure(9, weight=1)
|
self.speed731.grid_columnconfigure(9, weight=1)
|
||||||
self.speed731.grid_rowconfigure(0, weight=1)
|
self.speed731.grid_rowconfigure(0, weight=1)
|
||||||
self.speed731text = Entry(self.speed731, font='Terminal 14')
|
self.speed731text = Entry(self.speed731, font='Terminal 14')
|
||||||
self.speed731text.grid(column=0, row=0, sticky='NEW', padx=5, pady=5)
|
self.speed731text.grid(column=0, row=0, columnspan=7, sticky='NEW', padx=5, pady=5)
|
||||||
self.speedResult = Text((self.speed731), state='disabled', width=1, height=1, wrap='none', font='Terminal 14')
|
self.speedResult = Text((self.speed731), state='disabled', width=1, height=1, wrap='none', font='Terminal 14')
|
||||||
self.speedResult.grid(column=2, row=0, sticky='NEW', padx=5, pady=5)
|
self.speedResult.grid(column=7, 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=lang.all[globs.CNIRlang]["Monitor"])
|
self.monitor = ttk.Labelframe(self, text=lang.all[globs.CNIRlang]["Monitor"])
|
||||||
@ -341,6 +359,7 @@ class mainWindow(Tk):
|
|||||||
menu3.add_command(label=lang.all[globs.CNIRlang]["Keyboard commands"], command=(self.helpbox))
|
menu3.add_command(label=lang.all[globs.CNIRlang]["Keyboard commands"], command=(self.helpbox))
|
||||||
menu3.add_command(label=lang.all[globs.CNIRlang]["Report a bug"], 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=lang.all[globs.CNIRlang]["Project Webpage"], command=(self.openProjectPage))
|
||||||
menu3.add_command(label=lang.all[globs.CNIRlang]["About CNIRevelator"], command=(self.infobox))
|
menu3.add_command(label=lang.all[globs.CNIRlang]["About CNIRevelator"], command=(self.infobox))
|
||||||
menubar.add_cascade(label=lang.all[globs.CNIRlang]["Help"], menu=menu3)
|
menubar.add_cascade(label=lang.all[globs.CNIRlang]["Help"], menu=menu3)
|
||||||
menubar.add_command(label="<|>", command=(self.panelResize))
|
menubar.add_command(label="<|>", command=(self.panelResize))
|
||||||
@ -349,12 +368,6 @@ class mainWindow(Tk):
|
|||||||
# 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(0, 0)
|
self.resizable(0, 0)
|
||||||
self.update()
|
self.update()
|
||||||
@ -367,7 +380,7 @@ class mainWindow(Tk):
|
|||||||
self.geometry('%dx%d+%d+%d' % (self.w, self.h, self.x, self.y))
|
self.geometry('%dx%d+%d+%d' % (self.w, self.h, self.x, self.y))
|
||||||
self.update()
|
self.update()
|
||||||
self.deiconify()
|
self.deiconify()
|
||||||
self.attributes("-topmost", 1)
|
#self.attributes("-topmost", 1)
|
||||||
self.maxsize(self.w, self.h)
|
self.maxsize(self.w, self.h)
|
||||||
self.minsize(int(2.15 * (self.ws / 2 * 0.3333333333333333)), self.h)
|
self.minsize(int(2.15 * (self.ws / 2 * 0.3333333333333333)), self.h)
|
||||||
self.currentw = self.w
|
self.currentw = self.w
|
||||||
@ -377,10 +390,11 @@ class mainWindow(Tk):
|
|||||||
self.imageViewer.imagePath = None
|
self.imageViewer.imagePath = None
|
||||||
self.imageViewer.imgZoom = 1
|
self.imageViewer.imgZoom = 1
|
||||||
self.imageViewer.rotateCount = 0
|
self.imageViewer.rotateCount = 0
|
||||||
self.imageViewer.blackhat = False
|
self.imageViewer.blackhat = 0
|
||||||
self.imageViewer.pagenumber = 0
|
self.imageViewer.pagenumber = 0
|
||||||
|
|
||||||
# Some bindings
|
# Some bindings
|
||||||
|
self.bind('<Control_R>', self.entryValidation)
|
||||||
self.termtext.bind('<Key>', self.entryValidation)
|
self.termtext.bind('<Key>', self.entryValidation)
|
||||||
self.termtext.bind('<<Paste>>', self.pasteValidation)
|
self.termtext.bind('<<Paste>>', self.pasteValidation)
|
||||||
self.speed731text.bind('<Control_R>', self.speedValidation)
|
self.speed731text.bind('<Control_R>', self.speedValidation)
|
||||||
@ -404,11 +418,19 @@ class mainWindow(Tk):
|
|||||||
|
|
||||||
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 ='red', 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]))
|
||||||
|
|
||||||
|
# Reinit
|
||||||
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)
|
||||||
|
for k in self.indicators:
|
||||||
|
self.imageViewer.ZONE.delete(k)
|
||||||
|
|
||||||
|
# Draw indicator
|
||||||
|
else:
|
||||||
|
self.indicators.append(self.imageViewer.ZONE.create_oval(canvas.canvasx(event.x)-4, canvas.canvasy(event.y)-4,canvas.canvasx(event.x)+4, canvas.canvasy(event.y)+4, fill='red', outline='red', width = 2))
|
||||||
|
|
||||||
def goOCRDetection(self):
|
def goOCRDetection(self):
|
||||||
"""
|
"""
|
||||||
@ -417,10 +439,13 @@ class mainWindow(Tk):
|
|||||||
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)
|
||||||
if self.imageViewer.blackhat:
|
if self.imageViewer.blackhat == 1:
|
||||||
cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2GRAY)
|
cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2GRAY)
|
||||||
cv_img = cv2.GaussianBlur(cv_img, (3, 3), 0)
|
cv_img = cv2.threshold(cv_img, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
|
||||||
cv_img = cv2.bitwise_not(cv_img)
|
elif self.imageViewer.blackhat == 2:
|
||||||
|
cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2GRAY)
|
||||||
|
cv_img = cv2.medianBlur(cv_img, 3)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Get the image dimensions (OpenCV stores image data as NumPy ndarray)
|
# Get the image dimensions (OpenCV stores image data as NumPy ndarray)
|
||||||
height, width, channels_no = cv_img.shape
|
height, width, channels_no = cv_img.shape
|
||||||
@ -431,18 +456,21 @@ class mainWindow(Tk):
|
|||||||
height, width = cv_img.shape
|
height, width = cv_img.shape
|
||||||
# Get the image dimensions (OpenCV stores image data as NumPy ndarray)
|
# Get the image dimensions (OpenCV stores image data as NumPy ndarray)
|
||||||
height, width = cv_img.shape
|
height, width = cv_img.shape
|
||||||
|
|
||||||
# Rotate
|
# Rotate
|
||||||
rotationMatrix=cv2.getRotationMatrix2D((width/2, height/2),int(self.imageViewer.rotateCount*90),1)
|
cv_img, width, height = self.rotateBound(cv_img, int(self.imageViewer.rotateCount*90))
|
||||||
cv_img=cv2.warpAffine(cv_img,rotationMatrix,(width,height))
|
|
||||||
# Resize
|
# Resize
|
||||||
dim = (int(width * (self.imageViewer.imgZoom + 100) / 100), int(height * (self.imageViewer.imgZoom + 100) / 100))
|
dim = (int(width * (self.imageViewer.imgZoom + 100) / 100), int(height * (self.imageViewer.imgZoom + 100) / 100))
|
||||||
cv_img = cv2.resize(cv_img, dim, interpolation = cv2.INTER_AREA)
|
cv_img = cv2.resize(cv_img, dim, interpolation = cv2.INTER_AREA)
|
||||||
|
|
||||||
x0 = int(self.corners[0][0])
|
# Crop
|
||||||
y0 = int(self.corners[0][1])
|
|
||||||
x1 = int(self.corners[1][0])
|
|
||||||
y1 = int(self.corners[1][1])
|
|
||||||
|
|
||||||
|
coords = self.imageViewer.ZONE.coords(self.select)
|
||||||
|
|
||||||
|
x0 = int(coords[0])
|
||||||
|
y0 = int(coords[1])
|
||||||
|
x1 = int(coords[2])
|
||||||
|
y1 = int(coords[3])
|
||||||
crop_img = cv_img[y0:y1, x0:x1]
|
crop_img = cv_img[y0:y1, x0:x1]
|
||||||
|
|
||||||
# Get the text by OCR
|
# Get the text by OCR
|
||||||
@ -450,7 +478,7 @@ class mainWindow(Tk):
|
|||||||
os.environ['PATH'] = globs.CNIRTesser
|
os.environ['PATH'] = globs.CNIRTesser
|
||||||
os.environ['TESSDATA_PREFIX'] = globs.CNIRTesser + '\\tessdata'
|
os.environ['TESSDATA_PREFIX'] = globs.CNIRTesser + '\\tessdata'
|
||||||
|
|
||||||
text = pytesseract.image_to_string(crop_img, lang='ocrb', boxes=False, config='--psm 6 --oem 0 -c tessedit_char_whitelist=ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890<')
|
text = pytesseract.image_to_string(crop_img, lang='ocrb', config='--psm 6 --oem 1 -c tessedit_char_whitelist=ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890<')
|
||||||
|
|
||||||
# manual validation
|
# manual validation
|
||||||
# the regex
|
# the regex
|
||||||
@ -473,7 +501,7 @@ class mainWindow(Tk):
|
|||||||
self.termtext.insert("1.0", self.mrzChar)
|
self.termtext.insert("1.0", self.mrzChar)
|
||||||
self.mrzChar = self.mrzChar + char
|
self.mrzChar = self.mrzChar + char
|
||||||
|
|
||||||
self.stringValidation("")
|
self.stringValidation(isFull=True)
|
||||||
#print(self.mrzChar)
|
#print(self.mrzChar)
|
||||||
|
|
||||||
# Reinstall tesseract
|
# Reinstall tesseract
|
||||||
@ -492,7 +520,7 @@ class mainWindow(Tk):
|
|||||||
|
|
||||||
## Regex and document detection + control related functions
|
## Regex and document detection + control related functions
|
||||||
|
|
||||||
def stringValidation(self, keysym):
|
def stringValidation(self, keysym="", isFull=False):
|
||||||
"""
|
"""
|
||||||
Analysis of the already typed document
|
Analysis of the already typed document
|
||||||
"""
|
"""
|
||||||
@ -500,11 +528,11 @@ class mainWindow(Tk):
|
|||||||
# 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:
|
||||||
# Get the candidates
|
# Get the candidates
|
||||||
candidates = mrz.allDocMatch(self.mrzChar.split("\n"))
|
candidates = mrz.allDocMatch(self.mrzChar.split("\n"), final=isFull)
|
||||||
|
|
||||||
if len(candidates) == 2 and len(self.mrzChar) >= 8:
|
if len(candidates) >= 2 and len(candidates) < 4 and len(self.mrzChar) >= 8:
|
||||||
# Parameters for the choice invite
|
# Parameters for the choice invite
|
||||||
invite = ihm.DocumentAsk(self, [candidates[0][2], candidates[1][2]])
|
invite = ihm.DocumentAsk(self, candidates)
|
||||||
invite.transient(self)
|
invite.transient(self)
|
||||||
invite.grab_set()
|
invite.grab_set()
|
||||||
invite.focus_force()
|
invite.focus_force()
|
||||||
@ -540,6 +568,9 @@ class mainWindow(Tk):
|
|||||||
self.termtext.insert("1.0", self.mrzChar)
|
self.termtext.insert("1.0", self.mrzChar)
|
||||||
# stop when limit reached
|
# stop when limit reached
|
||||||
elif (len(self.mrzChar) - 3 >= 2 * len(self.mrzDecided[0][0])):
|
elif (len(self.mrzChar) - 3 >= 2 * len(self.mrzDecided[0][0])):
|
||||||
|
i = len(self.mrzChar) - 3
|
||||||
|
while i >= 2 * len(self.mrzDecided[0][0]):
|
||||||
|
i-=1
|
||||||
self.mrzChar = self.termtext.get("1.0", "end")[:-1]
|
self.mrzChar = self.termtext.get("1.0", "end")[:-1]
|
||||||
self.termtext.delete("1.0","end")
|
self.termtext.delete("1.0","end")
|
||||||
self.termtext.insert("1.0", self.mrzChar[:-1])
|
self.termtext.insert("1.0", self.mrzChar[:-1])
|
||||||
@ -595,9 +626,9 @@ class mainWindow(Tk):
|
|||||||
# Get the candidates
|
# Get the candidates
|
||||||
candidates = mrz.allDocMatch(self.mrzChar.split("\n"))
|
candidates = mrz.allDocMatch(self.mrzChar.split("\n"))
|
||||||
|
|
||||||
if len(candidates) == 2 and len(self.mrzChar) >= 8:
|
if len(candidates) >= 2 and len(candidates) < 4 and len(self.mrzChar) >= 8:
|
||||||
# Parameters for the choice invite
|
# Parameters for the choice invite
|
||||||
invite = ihm.DocumentAsk(self, [candidates[0][2], candidates[1][2]])
|
invite = ihm.DocumentAsk(self, candidates)
|
||||||
invite.transient(self)
|
invite.transient(self)
|
||||||
invite.grab_set()
|
invite.grab_set()
|
||||||
invite.focus_force()
|
invite.focus_force()
|
||||||
@ -622,6 +653,7 @@ class mainWindow(Tk):
|
|||||||
if not regex.fullmatch(event.char):
|
if not regex.fullmatch(event.char):
|
||||||
self.logOnTerm(lang.all[globs.CNIRlang]["Character not accepted !\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]
|
||||||
self.mrzChar = tempChar[:pos+1] + event.char + tempChar[pos+1:] + '\n'
|
self.mrzChar = tempChar[:pos+1] + event.char + tempChar[pos+1:] + '\n'
|
||||||
@ -711,17 +743,22 @@ class mainWindow(Tk):
|
|||||||
#print(docInfos)
|
#print(docInfos)
|
||||||
# display the infos
|
# display the infos
|
||||||
for key in [ e for e in docInfos ]:
|
for key in [ e for e in docInfos ]:
|
||||||
#print(docInfos[key])
|
#printkey)
|
||||||
if key in ["CODE", "CTRL", "CTRLF"]:
|
if key in ["CODE", "CTRL", "CTRLF", "FACULT", "NOINT"]:
|
||||||
continue
|
continue
|
||||||
if not docInfos[key] == False:
|
if not docInfos[key][1] == False:
|
||||||
self.infoList[key]['text'] = docInfos[key]
|
if not docInfos[key][0] == "":
|
||||||
|
self.infoList[key]['text'] = docInfos[key][0]
|
||||||
|
self.infoList[key]['background'] = self['background']
|
||||||
|
self.infoList[key]['foreground'] = "black"
|
||||||
|
else:
|
||||||
|
self.infoList[key]['text'] = lang.all[globs.CNIRlang]["Unknown"]
|
||||||
self.infoList[key]['background'] = self['background']
|
self.infoList[key]['background'] = self['background']
|
||||||
self.infoList[key]['foreground'] = "black"
|
self.infoList[key]['foreground'] = "black"
|
||||||
else:
|
else:
|
||||||
self.infoList[key]['background'] = "red"
|
self.infoList[key]['background'] = "red"
|
||||||
self.infoList[key]['foreground'] = "white"
|
self.infoList[key]['foreground'] = "white"
|
||||||
self.infoList[key]['text'] = "NC"
|
self.infoList[key]['text'] = docInfos[key][0]
|
||||||
self.compliance = False
|
self.compliance = False
|
||||||
|
|
||||||
if self.compliance == True:
|
if self.compliance == True:
|
||||||
@ -784,11 +821,15 @@ class mainWindow(Tk):
|
|||||||
"""
|
"""
|
||||||
Open the scan, ask its path and displays it
|
Open the scan, ask its path and displays it
|
||||||
"""
|
"""
|
||||||
|
self.initialize()
|
||||||
path = ''
|
path = ''
|
||||||
path = filedialog.askopenfilename(parent=self, title=lang.all[globs.CNIRlang]["Open a scan of document..."], 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'),
|
||||||
|
('PNG files', '*.png')
|
||||||
|
))
|
||||||
self.openScanFile(path)
|
self.openScanFile(path)
|
||||||
|
|
||||||
def openScanFile(self, path):
|
def openScanFile(self, path):
|
||||||
@ -799,14 +840,15 @@ class mainWindow(Tk):
|
|||||||
if ( path[-3:] != 'jpg'
|
if ( path[-3:] != 'jpg'
|
||||||
and path[-3:] != 'tif'
|
and path[-3:] != 'tif'
|
||||||
and path[-4:] != 'jpeg'
|
and path[-4:] != 'jpeg'
|
||||||
and path[-4:] != 'tiff' ) or not os.path.isfile(path):
|
and path[-4:] != 'tiff'
|
||||||
|
and path[-3:] != 'png' ) 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))
|
showerror(lang.all[globs.CNIRlang]["Open a scan of document..."], lang.all[globs.CNIRlang]["The file you provided is not valid : {}"].format(path))
|
||||||
return
|
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
|
||||||
self.imageViewer.blackhat = False
|
self.imageViewer.blackhat = 0
|
||||||
self.imageViewer.rotateCount = 0
|
self.imageViewer.rotateCount = 0
|
||||||
self.imageViewer.pagenumber = 0
|
self.imageViewer.pagenumber = 0
|
||||||
|
|
||||||
@ -818,8 +860,12 @@ class mainWindow(Tk):
|
|||||||
self.toolbar.pageChooser['values'] += tuple(str(i))
|
self.toolbar.pageChooser['values'] += tuple(str(i))
|
||||||
|
|
||||||
# Open the first page
|
# Open the first page
|
||||||
|
try:
|
||||||
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)
|
||||||
|
except:
|
||||||
|
logfile.printerr("Error with : {} in {} with total of {} pages".format(cv2.imreadmulti(self.imageViewer.imagePath), self.imageViewer.imagePath, total))
|
||||||
|
critical.crashCNIR(False, "OpenCV openScanFile() error")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Get the image dimensions (OpenCV stores image data as NumPy ndarray)
|
# Get the image dimensions (OpenCV stores image data as NumPy ndarray)
|
||||||
@ -832,6 +878,10 @@ class mainWindow(Tk):
|
|||||||
# Get the image dimensions (OpenCV stores image data as NumPy ndarray)
|
# Get the image dimensions (OpenCV stores image data as NumPy ndarray)
|
||||||
height, width = cv_img.shape
|
height, width = cv_img.shape
|
||||||
|
|
||||||
|
|
||||||
|
# Update shape
|
||||||
|
self.imageViewer.height, self.imageViewer.width = cv_img.shape[:2]
|
||||||
|
|
||||||
# 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.DisplayUpdate(photo)
|
self.DisplayUpdate(photo)
|
||||||
@ -842,7 +892,7 @@ class mainWindow(Tk):
|
|||||||
self.resizeScan()
|
self.resizeScan()
|
||||||
|
|
||||||
def zoomOutScan50(self, quantity = 50):
|
def zoomOutScan50(self, quantity = 50):
|
||||||
if self.imageViewer.image:
|
if self.imageViewer.image and int(self.imageViewer.width * (self.imageViewer.imgZoom - quantity + 100) / 100) > 100:
|
||||||
self.imageViewer.imgZoom -= quantity
|
self.imageViewer.imgZoom -= quantity
|
||||||
self.resizeScan()
|
self.resizeScan()
|
||||||
|
|
||||||
@ -852,7 +902,7 @@ class mainWindow(Tk):
|
|||||||
self.resizeScan()
|
self.resizeScan()
|
||||||
|
|
||||||
def zoomOutScan20(self, quantity = 20):
|
def zoomOutScan20(self, quantity = 20):
|
||||||
if self.imageViewer.image:
|
if self.imageViewer.image and int(self.imageViewer.width * (self.imageViewer.imgZoom - quantity + 100) / 100) > 100:
|
||||||
self.imageViewer.imgZoom -= quantity
|
self.imageViewer.imgZoom -= quantity
|
||||||
self.resizeScan()
|
self.resizeScan()
|
||||||
|
|
||||||
@ -862,7 +912,7 @@ class mainWindow(Tk):
|
|||||||
self.resizeScan()
|
self.resizeScan()
|
||||||
|
|
||||||
def zoomOutScan(self, quantity = 1):
|
def zoomOutScan(self, quantity = 1):
|
||||||
if self.imageViewer.image:
|
if self.imageViewer.image and int(self.imageViewer.width * (self.imageViewer.imgZoom - quantity + 100) / 100) > 100:
|
||||||
self.imageViewer.imgZoom -= quantity
|
self.imageViewer.imgZoom -= quantity
|
||||||
self.resizeScan()
|
self.resizeScan()
|
||||||
|
|
||||||
@ -894,7 +944,7 @@ class mainWindow(Tk):
|
|||||||
self.imageViewer.rotateCount = 4
|
self.imageViewer.rotateCount = 4
|
||||||
self.resizeScan()
|
self.resizeScan()
|
||||||
|
|
||||||
def negativeScan(self):
|
def threshScan(self):
|
||||||
"""
|
"""
|
||||||
Invert the bits to make a negative of the scan (and highlight the contrasts)
|
Invert the bits to make a negative of the scan (and highlight the contrasts)
|
||||||
"""
|
"""
|
||||||
@ -902,15 +952,44 @@ class mainWindow(Tk):
|
|||||||
# 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]
|
||||||
cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB)
|
cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB)
|
||||||
if not self.imageViewer.blackhat:
|
if self.imageViewer.blackhat == 0:
|
||||||
self.imageViewer.blackhat = True
|
self.imageViewer.blackhat = 1
|
||||||
cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2GRAY)
|
cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2GRAY)
|
||||||
cv_img = cv2.GaussianBlur(cv_img, (3, 3), 0)
|
cv_img = cv2.threshold(cv_img, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
|
||||||
cv_img = cv2.bitwise_not(cv_img)
|
elif self.imageViewer.blackhat == 1:
|
||||||
|
self.imageViewer.blackhat = 2
|
||||||
|
cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2GRAY)
|
||||||
|
cv_img = cv2.medianBlur(cv_img, 3)
|
||||||
else:
|
else:
|
||||||
self.imageViewer.blackhat = False
|
self.imageViewer.blackhat = 0
|
||||||
self.resizeScan(cv_img)
|
self.resizeScan(cv_img)
|
||||||
|
|
||||||
|
def rotateBound(self, image, angle):
|
||||||
|
"""
|
||||||
|
Computes the rotation matrix and the new shapes in order to rotate an image
|
||||||
|
"""
|
||||||
|
# grab the dimensions of the image and then determine the
|
||||||
|
# center
|
||||||
|
(h, w) = image.shape[:2]
|
||||||
|
(cX, cY) = (w // 2, h // 2)
|
||||||
|
|
||||||
|
# grab the rotation matrix , then grab the sine and cosine
|
||||||
|
# (i.e., the rotation components of the matrix)
|
||||||
|
M = cv2.getRotationMatrix2D((cX, cY), angle, 1.0)
|
||||||
|
cos = numpy.abs(M[0, 0])
|
||||||
|
sin = numpy.abs(M[0, 1])
|
||||||
|
|
||||||
|
# compute the new bounding dimensions of the image
|
||||||
|
nW = int((h * sin) + (w * cos))
|
||||||
|
nH = int((h * cos) + (w * sin))
|
||||||
|
|
||||||
|
# adjust the rotation matrix to take into account translation
|
||||||
|
M[0, 2] += (nW / 2) - cX
|
||||||
|
M[1, 2] += (nH / 2) - cY
|
||||||
|
|
||||||
|
# perform the actual rotation and return the image
|
||||||
|
return cv2.warpAffine(image, M, (nW, nH)), nW, nH
|
||||||
|
|
||||||
def resizeScan(self, cv_img = None):
|
def resizeScan(self, cv_img = None):
|
||||||
"""
|
"""
|
||||||
Reloads the image according to settings
|
Reloads the image according to settings
|
||||||
@ -921,10 +1000,12 @@ class mainWindow(Tk):
|
|||||||
# 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]
|
||||||
cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB)
|
cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB)
|
||||||
if self.imageViewer.blackhat:
|
if self.imageViewer.blackhat == 1:
|
||||||
cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2GRAY)
|
cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2GRAY)
|
||||||
cv_img = cv2.GaussianBlur(cv_img, (3, 3), 0)
|
cv_img = cv2.threshold(cv_img, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
|
||||||
cv_img = cv2.bitwise_not(cv_img)
|
elif self.imageViewer.blackhat == 2:
|
||||||
|
cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2GRAY)
|
||||||
|
cv_img = cv2.medianBlur(cv_img, 3)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Get the image dimensions (OpenCV stores image data as NumPy ndarray)
|
# Get the image dimensions (OpenCV stores image data as NumPy ndarray)
|
||||||
@ -936,23 +1017,26 @@ class mainWindow(Tk):
|
|||||||
height, width = cv_img.shape
|
height, width = cv_img.shape
|
||||||
# Get the image dimensions (OpenCV stores image data as NumPy ndarray)
|
# Get the image dimensions (OpenCV stores image data as NumPy ndarray)
|
||||||
height, width = cv_img.shape
|
height, width = cv_img.shape
|
||||||
|
|
||||||
# Rotate
|
# Rotate
|
||||||
rotationMatrix=cv2.getRotationMatrix2D((width/2, height/2),int(self.imageViewer.rotateCount*90),1)
|
cv_img, width, height = self.rotateBound(cv_img, int(self.imageViewer.rotateCount*90))
|
||||||
cv_img=cv2.warpAffine(cv_img,rotationMatrix,(width,height))
|
|
||||||
# Resize
|
# Resize
|
||||||
dim = (int(width * (self.imageViewer.imgZoom + 100) / 100), int(height * (self.imageViewer.imgZoom + 100) / 100))
|
dim = (int(width * (self.imageViewer.imgZoom + 100) / 100), int(height * (self.imageViewer.imgZoom + 100) / 100))
|
||||||
cv_img = cv2.resize(cv_img, dim, interpolation = cv2.INTER_AREA)
|
cv_img = cv2.resize(cv_img, dim, interpolation = cv2.INTER_AREA)
|
||||||
|
|
||||||
|
# Update shape
|
||||||
|
self.imageViewer.height, self.imageViewer.width = cv_img.shape[:2]
|
||||||
|
|
||||||
# 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.DisplayUpdate( 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))
|
||||||
ihm.crashCNIR()
|
|
||||||
try:
|
try:
|
||||||
# Reload an image using OpenCV
|
# Reload an image using OpenCV
|
||||||
path = self.imageViewer.imagePath
|
path = self.imageViewer.imagePath
|
||||||
self.imageViewer.imgZoom = 1
|
self.imageViewer.imgZoom = 1
|
||||||
self.imageViewer.blackhat = False
|
self.imageViewer.blackhat = 0
|
||||||
self.imageViewer.rotateCount = 0
|
self.imageViewer.rotateCount = 0
|
||||||
cv_img = cv2.imreadmulti(path)
|
cv_img = cv2.imreadmulti(path)
|
||||||
cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB)
|
cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB)
|
||||||
@ -965,8 +1049,7 @@ class mainWindow(Tk):
|
|||||||
self.DisplayUpdate(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))
|
||||||
ihm.crashCNIR()
|
critical.crashCNIR(False, "OpenCV resizeScan() error")
|
||||||
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
|
## IHM and user interface related functions
|
||||||
@ -1005,9 +1088,15 @@ class mainWindow(Tk):
|
|||||||
|
|
||||||
def openIssuePage(self):
|
def openIssuePage(self):
|
||||||
"""
|
"""
|
||||||
Opens the Github Issue Repository page
|
Sends a bug report
|
||||||
"""
|
"""
|
||||||
webbrowser.open_new("https://github.com/neox95/CNIRevelator/issues")
|
critical.crashCNIR(shutdown=False, option="Voluntary Bug Report", isVoluntary=True)
|
||||||
|
|
||||||
|
def openProjectPage(self):
|
||||||
|
"""
|
||||||
|
Opens the Project Repository webpage
|
||||||
|
"""
|
||||||
|
webbrowser.open_new("https://github.com/neox95/CNIRevelator")
|
||||||
|
|
||||||
def showChangeLog(self):
|
def showChangeLog(self):
|
||||||
changelogWin = ihm.ChangelogDialog(self, ('{} : CNIRevelator {}\n\n{}'.format(lang.all[globs.CNIRlang]["Program version"], globs.verstring_full, lang.all[globs.CNIRlang]["CHANGELOG"])))
|
changelogWin = ihm.ChangelogDialog(self, ('{} : CNIRevelator {}\n\n{}'.format(lang.all[globs.CNIRlang]["Program version"], globs.verstring_full, lang.all[globs.CNIRlang]["CHANGELOG"])))
|
||||||
@ -1020,7 +1109,7 @@ class mainWindow(Tk):
|
|||||||
"""
|
"""
|
||||||
Update Settings
|
Update Settings
|
||||||
"""
|
"""
|
||||||
changeupdateWin = ihm.updateSetDialog(self)
|
changeupdateWin = ihm.updateSetDialog(self, updater.getUpdateChannel())
|
||||||
changeupdateWin.transient(self)
|
changeupdateWin.transient(self)
|
||||||
changeupdateWin.grab_set()
|
changeupdateWin.grab_set()
|
||||||
changeupdateWin.focus_force()
|
changeupdateWin.focus_force()
|
||||||
@ -1030,7 +1119,7 @@ class mainWindow(Tk):
|
|||||||
"""
|
"""
|
||||||
Lang Settings
|
Lang Settings
|
||||||
"""
|
"""
|
||||||
changelangWin = ihm.langDialog(self)
|
changelangWin = ihm.langDialog(self, globs.CNIRlang)
|
||||||
changelangWin.transient(self)
|
changelangWin.transient(self)
|
||||||
changelangWin.grab_set()
|
changelangWin.grab_set()
|
||||||
changelangWin.focus_force()
|
changelangWin.focus_force()
|
||||||
|
113
src/mrz.py
113
src/mrz.py
@ -1,3 +1,4 @@
|
|||||||
|
# -*- coding: utf8 -*-
|
||||||
"""
|
"""
|
||||||
********************************************************************************
|
********************************************************************************
|
||||||
* CNIRevelator *
|
* CNIRevelator *
|
||||||
@ -30,6 +31,7 @@ import datetime
|
|||||||
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 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é'}
|
||||||
@ -60,7 +62,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"]
|
||||||
},
|
},
|
||||||
lang.all[globs.CNIRlang]["Passeport"]
|
lang.all[globs.CNIRlang]["Passeport lisible à la machine"]
|
||||||
]
|
]
|
||||||
|
|
||||||
IP = [
|
IP = [
|
||||||
@ -83,7 +85,7 @@ IP = [
|
|||||||
lang.all[globs.CNIRlang]["Carte-passeport"]
|
lang.all[globs.CNIRlang]["Carte-passeport"]
|
||||||
]
|
]
|
||||||
|
|
||||||
I_ = [
|
IDEUR = [
|
||||||
["112223333333334555555555555555", "66666678999999ABBBCCCCCCCCCCCD"],
|
["112223333333334555555555555555", "66666678999999ABBBCCCCCCCCCCCD"],
|
||||||
{
|
{
|
||||||
"1": ["2", "CODE", "I."],
|
"1": ["2", "CODE", "I."],
|
||||||
@ -100,7 +102,27 @@ I_ = [
|
|||||||
"C": ["11", "FACULT", ".+"],
|
"C": ["11", "FACULT", ".+"],
|
||||||
"D": ["1", "CTRL", "[0-9]", "345679AC"]
|
"D": ["1", "CTRL", "[0-9]", "345679AC"]
|
||||||
},
|
},
|
||||||
lang.all[globs.CNIRlang]["Titre d'identité/de voyage"]
|
lang.all[globs.CNIRlang]["Carte d’identité européenne"]
|
||||||
|
]
|
||||||
|
|
||||||
|
TSEUR = [
|
||||||
|
["112223333333334555555555555555", "66666678999999ABBBCCCCCCCCCCCD"],
|
||||||
|
{
|
||||||
|
"1": ["2", "CODE", "IR"],
|
||||||
|
"2": ["3", "PAYS", "[A-Z]+"],
|
||||||
|
"3": ["9", "NO", ".+"],
|
||||||
|
"4": ["1", "CTRL", "[0-9]", "3"],
|
||||||
|
"5": ["15", "FACULT", ".+"],
|
||||||
|
"6": ["6", "BDATE", "[0-9]+"],
|
||||||
|
"7": ["1", "CTRL", "[0-9]", "6"],
|
||||||
|
"8": ["1", "SEX", "[A-Z]"],
|
||||||
|
"9": ["6", "EDATE", "[0-9]+"],
|
||||||
|
"A": ["1", "CTRL", "[0-9]", "9"],
|
||||||
|
"B": ["3", "NAT", "[A-Z]+"],
|
||||||
|
"C": ["11", "FACULT", ".+"],
|
||||||
|
"D": ["1", "CTRL", "[0-9]", "345679AC"]
|
||||||
|
},
|
||||||
|
lang.all[globs.CNIRlang]["Carte de séjour européenne"]
|
||||||
]
|
]
|
||||||
|
|
||||||
AC = [
|
AC = [
|
||||||
@ -125,11 +147,11 @@ AC = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
VA = [
|
VA = [
|
||||||
["11222333333333333333333333333333333333333333", "444444444566677777789AAAAAABCCCCCCCCCCCCCCCCC"],
|
["11222333333333333333333333333333333333333333", "444444444566677777789AAAAAABCCCCCCCCCCCCCCCC"],
|
||||||
{
|
{
|
||||||
"1": ["2", "CODE", "V."],
|
"1": ["2", "CODE", "V."],
|
||||||
"2": ["3", "PAYS", "[A-Z]+"],
|
"2": ["3", "PAYS", "[A-Z]+"],
|
||||||
"3": ["39", "NOM", "[A-Z]+"],
|
"3": ["39", "NOM", "([A-Z]|<)+"],
|
||||||
"4": ["9", "NO", ".+"],
|
"4": ["9", "NO", ".+"],
|
||||||
"5": ["1", "CTRL", "[0-9]","4"],
|
"5": ["1", "CTRL", "[0-9]","4"],
|
||||||
"6": ["3", "NAT", "[A-Z]+"],
|
"6": ["3", "NAT", "[A-Z]+"],
|
||||||
@ -144,7 +166,7 @@ VA = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
VB = [
|
VB = [
|
||||||
["112223333333333333333333333333333333", "444444444566677777789AAAAAABCCCCCC"],
|
["112223333333333333333333333333333333", "444444444566677777789AAAAAABCCCCCCCC"],
|
||||||
{
|
{
|
||||||
"1": ["2", "CODE", "V."],
|
"1": ["2", "CODE", "V."],
|
||||||
"2": ["3", "PAYS", "[A-Z]+"],
|
"2": ["3", "PAYS", "[A-Z]+"],
|
||||||
@ -178,10 +200,10 @@ TSF = [
|
|||||||
"B": ["1", "CTRL", "[0-9]", "A"],
|
"B": ["1", "CTRL", "[0-9]", "A"],
|
||||||
"C": ["8", "FACULT", ".+"]
|
"C": ["8", "FACULT", ".+"]
|
||||||
},
|
},
|
||||||
lang.all[globs.CNIRlang]["Carte de séjour"]
|
lang.all[globs.CNIRlang]["Carte de séjour FR"]
|
||||||
]
|
]
|
||||||
|
|
||||||
I__ = [
|
TDV = [
|
||||||
["112223333333333333333333333333333333", "444444444566677777789AAAAAABCCCCCCCD"],
|
["112223333333333333333333333333333333", "444444444566677777789AAAAAABCCCCCCCD"],
|
||||||
{
|
{
|
||||||
"1": ["2", "CODE", "I."],
|
"1": ["2", "CODE", "I."],
|
||||||
@ -198,7 +220,7 @@ I__ = [
|
|||||||
"C": ["7", "FACULT", ".+"],
|
"C": ["7", "FACULT", ".+"],
|
||||||
"D": ["1", "CTRL", "[0-9]", "4578ABC"]
|
"D": ["1", "CTRL", "[0-9]", "4578ABC"]
|
||||||
},
|
},
|
||||||
lang.all[globs.CNIRlang]["Pièce d'identité/de voyage"]
|
lang.all[globs.CNIRlang]["Titre d'identité/de voyage"]
|
||||||
]
|
]
|
||||||
|
|
||||||
IDFR = [
|
IDFR = [
|
||||||
@ -235,7 +257,7 @@ DL = [
|
|||||||
lang.all[globs.CNIRlang]["Permis de conduire"]
|
lang.all[globs.CNIRlang]["Permis de conduire"]
|
||||||
]
|
]
|
||||||
|
|
||||||
TYPES = [IDFR, I__, VB, VA, AC, I_, IP, P, DL, TSF]
|
TYPES = [IDFR, TDV, VB, VA, AC, IDEUR, IP, P, DL, TSF, TSEUR]
|
||||||
|
|
||||||
# longest document MRZ line
|
# longest document MRZ line
|
||||||
longest = max([len(x[0][0]) for x in TYPES])
|
longest = max([len(x[0][0]) for x in TYPES])
|
||||||
@ -320,7 +342,7 @@ def docMatch(doc, strs):
|
|||||||
# logfile.printdbg(" REGEX : {}, match : {}".format(regex, matching))
|
# logfile.printdbg(" REGEX : {}, match : {}".format(regex, matching))
|
||||||
# exit the loop
|
# exit the loop
|
||||||
|
|
||||||
#logfile.printdbg("{} level : {}/{} (+{})".format(doc[2], level, nchar, bonus))
|
logfile.printdbg("{} level : {}/{} (+{})".format(doc[2], level, nchar, bonus))
|
||||||
return (level, nchar, bonus)
|
return (level, nchar, bonus)
|
||||||
|
|
||||||
def allDocMatch(strs, final=False):
|
def allDocMatch(strs, final=False):
|
||||||
@ -346,14 +368,25 @@ def allDocMatch(strs, final=False):
|
|||||||
candidate = SCORES.index(max(SCORES))
|
candidate = SCORES.index(max(SCORES))
|
||||||
candidates = []
|
candidates = []
|
||||||
canditxt = []
|
canditxt = []
|
||||||
|
|
||||||
# Search the candidates
|
# Search the candidates
|
||||||
for i in range(len(SCORES)):
|
for i in range(len(SCORES)):
|
||||||
if SCORES[i] == SCORES[candidate]:
|
if SCORES[i] == SCORES[candidate]:
|
||||||
candidates += [TYPES[i]]
|
candidates += [TYPES[i]]
|
||||||
canditxt += [TYPES[i][2]]
|
canditxt += [TYPES[i][2]]
|
||||||
|
# Continue searching
|
||||||
|
if len(candidates) < 2:
|
||||||
|
tempRemovedCandidate = SCORES.pop(candidate)
|
||||||
|
if (SCORES.index(max(SCORES)) != candidate) and (max(SCORES) >= tempRemovedCandidate - 20):
|
||||||
|
if SCORES.index(max(SCORES)) < candidate:
|
||||||
|
candidates += [ TYPES[SCORES.index(max(SCORES))] ]
|
||||||
|
else:
|
||||||
|
candidates += [ TYPES[SCORES.index(max(SCORES)) + 1] ]
|
||||||
|
SCORES.insert(candidate, tempRemovedCandidate)
|
||||||
|
|
||||||
# Return the candidates
|
# Return the candidates
|
||||||
#logfile.printdbg("Scores : {}".format(SCORES))
|
logfile.printdbg("Scores : {}".format(SCORES))
|
||||||
#logfile.printdbg("Candidates : {}".format(canditxt))
|
logfile.printdbg("Candidates : {}".format(canditxt))
|
||||||
return candidates
|
return candidates
|
||||||
|
|
||||||
def computeControlSum(code):
|
def computeControlSum(code):
|
||||||
@ -391,6 +424,11 @@ def computeAllControlSum(doc, code):
|
|||||||
|
|
||||||
# iteration on each char of the given MRZ
|
# iteration on each char of the given MRZ
|
||||||
for charPos in range(len(code)):
|
for charPos in range(len(code)):
|
||||||
|
|
||||||
|
# Sanity check
|
||||||
|
if len(getDocString(doc)) <= charPos:
|
||||||
|
break
|
||||||
|
|
||||||
field = getDocString(doc)[charPos]
|
field = getDocString(doc)[charPos]
|
||||||
|
|
||||||
if doc[1][field][1] == "CTRL":
|
if doc[1][field][1] == "CTRL":
|
||||||
@ -399,6 +437,12 @@ def computeAllControlSum(doc, code):
|
|||||||
codeChain = ""
|
codeChain = ""
|
||||||
# iteration on the fields to control
|
# iteration on the fields to control
|
||||||
for pos in range(len(code)):
|
for pos in range(len(code)):
|
||||||
|
|
||||||
|
#print("Len : {}, pos : {}".format(len(getDocString(doc)), pos))
|
||||||
|
# Sanity check
|
||||||
|
if len(getDocString(doc)) <= pos:
|
||||||
|
break
|
||||||
|
|
||||||
target = getDocString(doc)[pos]
|
target = getDocString(doc)[pos]
|
||||||
if target in doc[1][field][3]:
|
if target in doc[1][field][3]:
|
||||||
#print("__field : {} {} {} {}".format(target, pos, field, doc[1][field][3]))
|
#print("__field : {} {} {} {}".format(target, pos, field, doc[1][field][3]))
|
||||||
@ -443,21 +487,30 @@ def getDocInfos(doc, code):
|
|||||||
|
|
||||||
res = {}
|
res = {}
|
||||||
|
|
||||||
|
# Length of MRZ
|
||||||
|
length = len(code)
|
||||||
|
if length == len(doc[0][0]+doc[0][1]):
|
||||||
|
res["LEN"] = [length, True]
|
||||||
|
else:
|
||||||
|
res["LEN"] = [length, False]
|
||||||
|
|
||||||
|
|
||||||
for field in infoTypes:
|
for field in infoTypes:
|
||||||
|
|
||||||
value = code[ field[1][0] : field[1][1] ].replace("<", " ").strip()
|
value = code[ field[1][0] : field[1][1] ].replace("<", " ").strip()
|
||||||
|
res[field[0]] = [0,0]
|
||||||
|
|
||||||
# State code
|
# State code
|
||||||
if field[0] == 'PAYS' or field[0] == 'NAT':
|
if field[0] == 'PAYS' or field[0] == 'NAT':
|
||||||
try:
|
try:
|
||||||
if len(value) == 3 and value[-1] != "<":
|
if len(value) == 3 and value[-1] != "<":
|
||||||
res[field[0]] = landcode3[value]
|
res[field[0]] = (landcode3[value], True)
|
||||||
elif len(value) == 3 and value[-1] == "<":
|
elif len(value) == 3 and value[-1] == "<":
|
||||||
res[field[0]] = landcode2[value[:-1]]
|
res[field[0]] = (landcode2[value[:-1]], True)
|
||||||
else:
|
else:
|
||||||
res[field[0]] = landcode2[value]
|
res[field[0]] = (landcode2[value], True)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
res[field[0]] = False
|
res[field[0]] = [value, False]
|
||||||
|
|
||||||
# Dates
|
# Dates
|
||||||
elif field[0][1:] == 'DATE':
|
elif field[0][1:] == 'DATE':
|
||||||
@ -473,39 +526,43 @@ def getDocInfos(doc, code):
|
|||||||
except ValueError:
|
except ValueError:
|
||||||
#print(value)
|
#print(value)
|
||||||
if value != "":
|
if value != "":
|
||||||
res[field[0]] = False
|
res[field[0]] = [value, False]
|
||||||
else:
|
else:
|
||||||
res[field[0]] = value
|
res[field[0]] = [value, True]
|
||||||
|
|
||||||
# Numbers
|
# Numbers
|
||||||
elif field[0][:-1] == 'NOINT':
|
elif field[0][:-1] == 'NOINT':
|
||||||
try:
|
try:
|
||||||
res["NO"] += value
|
res["NO"][0] += value
|
||||||
|
res["NO"][1] = True
|
||||||
except KeyError:
|
except KeyError:
|
||||||
res["NO"] = value
|
res["NO"] = [value, True]
|
||||||
|
|
||||||
elif field[0] == 'NOINT':
|
elif field[0] == 'NOINT':
|
||||||
try:
|
try:
|
||||||
res["NO"] += value
|
res["NO"][0] += value
|
||||||
|
res["NO"][1] = True
|
||||||
except KeyError:
|
except KeyError:
|
||||||
res["NO"] = value
|
res["NO"] = [value, True]
|
||||||
|
|
||||||
elif field[0] == 'FACULT':
|
elif field[0] == 'FACULT':
|
||||||
try:
|
try:
|
||||||
res["INDIC"] += value
|
res["INDIC"][0] += value
|
||||||
|
res["INDIC"][1] = True
|
||||||
except KeyError:
|
except KeyError:
|
||||||
res["INDIC"] = value
|
res["INDIC"] = [value, True]
|
||||||
|
|
||||||
# Sex
|
# Sex
|
||||||
elif field[0] == 'SEX':
|
elif field[0] == 'SEX':
|
||||||
if not value in "MF":
|
if not value in "MF":
|
||||||
res[field[0]] = False
|
res[field[0]] = [value, False]
|
||||||
else:
|
else:
|
||||||
res[field[0]] = value
|
res[field[0]] = [value, True]
|
||||||
|
|
||||||
# All other cases
|
# All other cases
|
||||||
else:
|
else:
|
||||||
if value != "":
|
if value != "":
|
||||||
res[field[0]] = value
|
res[field[0]] = [value, True]
|
||||||
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
# -*- coding: utf8 -*-
|
||||||
"""
|
"""
|
||||||
********************************************************************************
|
********************************************************************************
|
||||||
* CNIRevelator *
|
* CNIRevelator *
|
||||||
@ -23,7 +24,7 @@
|
|||||||
* along with CNIRevelator. If not, see <https:*www.gnu.org/licenses/>. *
|
* along with CNIRevelator. If not, see <https:*www.gnu.org/licenses/>. *
|
||||||
********************************************************************************
|
********************************************************************************
|
||||||
"""
|
"""
|
||||||
|
import logger # logger.pu
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import Image
|
import Image
|
||||||
@ -247,7 +248,7 @@ def image_to_string(image, lang=None, config='', nice=0, boxes=False, output_typ
|
|||||||
Returns the result of a Tesseract OCR run on the provided image to string
|
Returns the result of a Tesseract OCR run on the provided image to string
|
||||||
"""
|
"""
|
||||||
if boxes:
|
if boxes:
|
||||||
print("\nWarning: Argument 'boxes' is deprecated and will be removed in future versions. Use function image_to_boxes instead.\n")
|
logfile.printdbg("\nWarning: Argument 'boxes' is deprecated and will be removed in future versions. Use function image_to_boxes instead.\n")
|
||||||
return image_to_boxes(image, lang, config, nice, output_type)
|
return image_to_boxes(image, lang, config, nice, output_type)
|
||||||
else:
|
else:
|
||||||
args = [
|
args = [
|
||||||
@ -316,7 +317,7 @@ def main():
|
|||||||
sys.stderr.write('Usage: python pytesseract.py [-l lang] input_file\n')
|
sys.stderr.write('Usage: python pytesseract.py [-l lang] input_file\n')
|
||||||
exit(2)
|
exit(2)
|
||||||
try:
|
try:
|
||||||
print(image_to_string((Image.open(filename)), lang=lang))
|
logfile.printdbg(image_to_string((Image.open(filename)), lang=lang))
|
||||||
except IOError:
|
except IOError:
|
||||||
sys.stderr.write('ERROR: Could not open file "%s"\n' % filename)
|
sys.stderr.write('ERROR: Could not open file "%s"\n' % filename)
|
||||||
exit(1)
|
exit(1)
|
||||||
|
135
src/updater.py
135
src/updater.py
@ -1,3 +1,4 @@
|
|||||||
|
# -*- coding: utf8 -*-
|
||||||
"""
|
"""
|
||||||
********************************************************************************
|
********************************************************************************
|
||||||
* CNIRevelator *
|
* CNIRevelator *
|
||||||
@ -24,6 +25,9 @@
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from win32com.client import Dispatch
|
from win32com.client import Dispatch
|
||||||
|
from tkinter.messagebox import *
|
||||||
|
from tkinter import *
|
||||||
|
import pythoncom
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
import os
|
import os
|
||||||
@ -32,7 +36,10 @@ import zipfile
|
|||||||
import hashlib
|
import hashlib
|
||||||
import subprocess
|
import subprocess
|
||||||
import psutil
|
import psutil
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
import critical # critical.py
|
||||||
|
import github # github.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
|
||||||
@ -81,19 +88,45 @@ def exitProcess(arg):
|
|||||||
process.terminate()
|
process.terminate()
|
||||||
sys.exit(arg)
|
sys.exit(arg)
|
||||||
|
|
||||||
def updateChannel(choice):
|
def setUpdateChannel(choice):
|
||||||
|
"""
|
||||||
|
Sets the new update channel and forces new update at next launch
|
||||||
|
"""
|
||||||
if choice == "Beta":
|
if choice == "Beta":
|
||||||
with open(globs.CNIRUrlConfig, 'w') as (configFile):
|
with open(globs.CNIRUrlConfig, 'w') as (configFile):
|
||||||
configFile.write("{}\n0\n0".format(globs.CNIRBetaURL))
|
configFile.write("{}\n0\n0".format(globs.CNIRBetaURL))
|
||||||
else:
|
# Force new update
|
||||||
|
try:
|
||||||
|
os.remove(globs.CNIRLastUpdate)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
elif choice == "Stable":
|
||||||
with open(globs.CNIRUrlConfig, 'w') as (configFile):
|
with open(globs.CNIRUrlConfig, 'w') as (configFile):
|
||||||
configFile.write("{}\n0\n0".format(globs.CNIRDefaultURL))
|
configFile.write("{}\n0\n0".format(globs.CNIRDefaultURL))
|
||||||
|
# Force new update
|
||||||
|
try:
|
||||||
|
os.remove(globs.CNIRLastUpdate)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def getUpdateChannel():
|
||||||
|
"""
|
||||||
|
Returns the current update channel
|
||||||
|
"""
|
||||||
|
with open(globs.CNIRUrlConfig, 'r') as (configFile):
|
||||||
|
url = configFile.read()
|
||||||
|
if not "master" in url:
|
||||||
|
return "Beta"
|
||||||
|
else:
|
||||||
|
return "Stable"
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
@ -165,13 +198,18 @@ 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-OCR5\\'):
|
||||||
finalver, finalurl, finalchecksum = getLatestVersion(credentials)
|
finalver, finalurl, finalchecksum = getLatestVersion(credentials)
|
||||||
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
|
if finalurl == None:
|
||||||
|
logfile.printerr('Unable to get the Tesseract url')
|
||||||
|
return False
|
||||||
|
|
||||||
|
tesseracturl = finalurl.replace("CNIRevelator.zip", "tesseract_5.zip")
|
||||||
|
|
||||||
|
# WE ASSUME THAT THE MAIN FILE IS CNIRevelator.zip AND THAT THE TESSERACT PACKAGE IS tesseract_5.zip
|
||||||
logfile.printdbg('Preparing download of Tesseract OCR 4...')
|
logfile.printdbg('Preparing download of Tesseract OCR 4...')
|
||||||
getTesseract = downloader.newdownload(credentials, tesseracturl, PATH + '\\downloads\\TsrtPackage.zip', "Tesseract 4 OCR Module").download()
|
getTesseract = downloader.newdownload(credentials, tesseracturl, PATH + '\\downloads\\TsrtPackage.zip', "Tesseract 5 OCR Module").download()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# CHECKSUM
|
# CHECKSUM
|
||||||
@ -277,6 +315,7 @@ def batch(credentials):
|
|||||||
|
|
||||||
# Make a shortcut
|
# Make a shortcut
|
||||||
# hide main window
|
# hide main window
|
||||||
|
pythoncom.CoInitialize()
|
||||||
root = Tk()
|
root = Tk()
|
||||||
root.withdraw()
|
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 ?"])
|
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 ?"])
|
||||||
@ -303,21 +342,11 @@ def umain():
|
|||||||
# Global Handlers
|
# Global Handlers
|
||||||
logfile = logger.logCur
|
logfile = logger.logCur
|
||||||
|
|
||||||
|
|
||||||
credentials = downloader.newcredentials()
|
|
||||||
|
|
||||||
if not credentials.valid:
|
|
||||||
logfile.printerr("Credentials Error. No effective update !")
|
|
||||||
launcherWindow.printmsg(lang.all[globs.CNIRlang]["Credentials Error. No effective update !"])
|
|
||||||
time.sleep(2)
|
|
||||||
launcherWindow.exit()
|
|
||||||
return 0
|
|
||||||
|
|
||||||
# Cleaner for the old version if detected
|
# Cleaner for the old version if detected
|
||||||
if len(sys.argv) > 2 and str(sys.argv[1]) == "DELETE":
|
if len(sys.argv) > 2 and str(sys.argv[1]) == "DELETE":
|
||||||
globs.CNIRNewVersion = True
|
globs.CNIRNewVersion = True
|
||||||
launcherWindow.printmsg(lang.all[globs.CNIRlang]["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[2]))
|
||||||
while os.path.exists(str(sys.argv[2])):
|
while os.path.exists(str(sys.argv[2])):
|
||||||
try:
|
try:
|
||||||
shutil.rmtree(str(sys.argv[2]))
|
shutil.rmtree(str(sys.argv[2]))
|
||||||
@ -344,14 +373,51 @@ def umain():
|
|||||||
# check we want open a file
|
# check we want open a file
|
||||||
elif len(sys.argv) > 1 and str(sys.argv[1]) != "DELETE":
|
elif len(sys.argv) > 1 and str(sys.argv[1]) != "DELETE":
|
||||||
globs.CNIROpenFile = True
|
globs.CNIROpenFile = True
|
||||||
print(sys.argv)
|
logfile.printdbg("Command line received : {}".format(sys.argv))
|
||||||
|
|
||||||
|
credentials = downloader.newcredentials()
|
||||||
|
|
||||||
|
if not credentials.valid:
|
||||||
|
if credentials.login == "nointernet":
|
||||||
|
logfile.printerr("No Internet Error. No effective update !")
|
||||||
|
launcherWindow.printmsg(lang.all[globs.CNIRlang]["No Internet Error. No effective update !"])
|
||||||
|
else:
|
||||||
|
logfile.printerr("Credentials Error. No effective update !")
|
||||||
|
launcherWindow.printmsg(lang.all[globs.CNIRlang]["Credentials Error. No effective update !"])
|
||||||
|
time.sleep(2)
|
||||||
|
launcherWindow.exit()
|
||||||
|
return 0
|
||||||
|
|
||||||
|
github.credentials = credentials
|
||||||
|
|
||||||
|
# Check if update is needed
|
||||||
|
currentDate = datetime.datetime.now()
|
||||||
|
|
||||||
|
if os.path.isfile(globs.CNIRLastUpdate):
|
||||||
|
with open(globs.CNIRLastUpdate, 'r') as (configFile):
|
||||||
|
try:
|
||||||
|
# Reading it
|
||||||
|
lastUpdate = datetime.datetime.strptime(configFile.read(),"%d/%m/%Y")
|
||||||
|
except Exception as e:
|
||||||
|
critical.crashCNIR(False)
|
||||||
|
time.sleep(3)
|
||||||
|
launcherWindow.exit()
|
||||||
|
return 1
|
||||||
|
else:
|
||||||
|
lastUpdate = datetime.datetime(1970,1,1)
|
||||||
|
|
||||||
|
if not globs.CNIRNewVersion and os.path.exists(globs.CNIRFolder + '\\Tesseract-OCR5\\') and (currentDate - lastUpdate).days < 7:
|
||||||
|
logfile.printdbg("No need to update, {} days remaining".format(7 - (currentDate - lastUpdate).days))
|
||||||
|
launcherWindow.exit()
|
||||||
|
return 0
|
||||||
|
|
||||||
|
# Update batch
|
||||||
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:
|
||||||
ihm.crashCNIR()
|
critical.crashCNIR(False)
|
||||||
launcherWindow.printmsg('ERROR : ' + str(e))
|
launcherWindow.printmsg('ERROR : ' + str(e))
|
||||||
time.sleep(3)
|
time.sleep(3)
|
||||||
launcherWindow.exit()
|
launcherWindow.exit()
|
||||||
@ -360,6 +426,26 @@ 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('Software is up-to-date !')
|
||||||
|
# Recreating the url file
|
||||||
|
lastUpdate = currentDate
|
||||||
|
try:
|
||||||
|
os.mkdir(globs.CNIRFolder + '\\config')
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
with open(globs.CNIRLastUpdate, 'w') as (configFile):
|
||||||
|
try:
|
||||||
|
# Writing it
|
||||||
|
configFile.write("{}/{}/{}".format(currentDate.day, currentDate.month, currentDate.year))
|
||||||
|
except Exception as e:
|
||||||
|
critical.crashCNIR(False)
|
||||||
|
time.sleep(3)
|
||||||
|
launcherWindow.exit()
|
||||||
|
return
|
||||||
|
if UPDATE_IS_MADE:
|
||||||
|
launcherWindow.exit()
|
||||||
|
return 0
|
||||||
|
|
||||||
else:
|
else:
|
||||||
logfile.printerr("An error occured. No effective update !")
|
logfile.printerr("An error occured. No effective update !")
|
||||||
launcherWindow.printmsg(lang.all[globs.CNIRlang]['An error occured. No effective update !'])
|
launcherWindow.printmsg(lang.all[globs.CNIRlang]['An error occured. No effective update !'])
|
||||||
@ -367,13 +453,9 @@ def umain():
|
|||||||
launcherWindow.exit()
|
launcherWindow.exit()
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
if UPDATE_IS_MADE:
|
|
||||||
launcherWindow.exit()
|
|
||||||
return 0
|
|
||||||
except:
|
except:
|
||||||
ihm.crashCNIR()
|
critical.crashCNIR(False)
|
||||||
launcherWindow.exit()
|
launcherWindow.exit()
|
||||||
sys.exit(2)
|
|
||||||
return 2
|
return 2
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -381,7 +463,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:
|
||||||
ihm.crashCNIR()
|
critical.crashCNIR(False)
|
||||||
launcherWindow.printmsg('ERROR : ' + str(e))
|
launcherWindow.printmsg('ERROR : ' + str(e))
|
||||||
time.sleep(3)
|
time.sleep(3)
|
||||||
launcherWindow.exit()
|
launcherWindow.exit()
|
||||||
@ -398,9 +480,8 @@ def umain():
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
except:
|
except:
|
||||||
ihm.crashCNIR()
|
critical.crashCNIR(False)
|
||||||
launcherWindow.exit()
|
launcherWindow.exit()
|
||||||
sys.exit(2)
|
|
||||||
return 2
|
return 2
|
||||||
|
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
|
43
src/version.res
Normal file
43
src/version.res
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
# UTF-8
|
||||||
|
#
|
||||||
|
# For more details about fixed file info 'ffi' see:
|
||||||
|
# http://msdn.microsoft.com/en-us/library/ms646997.aspx
|
||||||
|
VSVersionInfo(
|
||||||
|
ffi=FixedFileInfo(
|
||||||
|
# filevers and prodvers should be always a tuple with four items: (1, 2, 3, 4)
|
||||||
|
# Set not needed items to zero 0.
|
||||||
|
filevers=(3, 1, 6, 0),
|
||||||
|
prodvers=(3, 1, 6, 0),
|
||||||
|
# Contains a bitmask that specifies the valid bits 'flags'r
|
||||||
|
mask=0x3f,
|
||||||
|
# Contains a bitmask that specifies the Boolean attributes of the file.
|
||||||
|
flags=0x0,
|
||||||
|
# The operating system for which this file was designed.
|
||||||
|
# 0x4 - NT and there is no need to change it.
|
||||||
|
OS=0x4,
|
||||||
|
# The general type of file.
|
||||||
|
# 0x1 - the file is an application.
|
||||||
|
fileType=0x1,
|
||||||
|
# The function of the file.
|
||||||
|
# 0x0 - the function is not defined for this fileType
|
||||||
|
subtype=0x0,
|
||||||
|
# Creation date and time stamp.
|
||||||
|
date=(0, 0)
|
||||||
|
),
|
||||||
|
kids=[
|
||||||
|
StringFileInfo(
|
||||||
|
[
|
||||||
|
StringTable(
|
||||||
|
u'040904B0',
|
||||||
|
[StringStruct(u'CompanyName', u'Adrien Bourmault (neox95)'),
|
||||||
|
StringStruct(u'FileDescription', u'This file is part of CNIRevelator.'),
|
||||||
|
StringStruct(u'FileVersion', u'3.1.6'),
|
||||||
|
StringStruct(u'InternalName', u'CNIRevelator'),
|
||||||
|
StringStruct(u'LegalCopyright', u'Copyright (c) Adrien Bourmault (neox95)'),
|
||||||
|
StringStruct(u'OriginalFilename', u'CNIRevelator.exe'),
|
||||||
|
StringStruct(u'ProductName', u'CNIRevelator 3.1'),
|
||||||
|
StringStruct(u'ProductVersion', u'3.1.6')])
|
||||||
|
]),
|
||||||
|
VarFileInfo([VarStruct(u'Translation', [1033, 1200])])
|
||||||
|
]
|
||||||
|
)
|
Loading…
Reference in New Issue
Block a user