Compare commits

...

113 Commits

Author SHA1 Message Date
Adrien Bourmault e52c34319f
Update README.MD 2020-01-06 00:00:22 +01:00
Adrien Bourmault fba076d245
test gpg 2019-10-06 21:17:39 +02:00
Adrien Bourmault 9ca31bd744
test gpg 2019-10-06 21:14:39 +02:00
Adrien Bourmault 3ab1ed9570
Test ssh 2019-09-26 19:01:10 +02:00
Adrien Bourmault db84dbd13c Update VERSIONS.LST 2019-08-30 15:26:08 +02:00
Adrien Bourmault 88c41b2a48 Update VERSIONS.LST 2019-08-30 15:26:08 +02:00
Adrien Bourmault 17acb12992 Enhancing UI/Infos and resolving bugs about Visas 2019-08-30 15:26:08 +02:00
Adrien Bourmault bbb2e43f61
Merge pull request #47 from neox95/v3.1
V3.1.5
2019-08-30 11:25:58 +02:00
Adrien Bourmault 01b4a6ea4b
Update VERSIONS.LST 2019-08-30 11:21:17 +02:00
Adrien Bourmault f744c6fedd
Correcting some bugs and enhance the selection and UI 2019-08-30 11:18:51 +02:00
Adrien Bourmault e230d65cd4
Update VERSIONS.LST 2019-08-29 15:00:29 +02:00
Adrien Bourmault d1bf646118
Somes changes on UI and update system 2019-08-29 12:54:43 +02:00
Adrien Bourmault 4f36d5904e
Update VERSIONS.LST 2019-08-29 11:15:07 +02:00
Adrien Bourmault 102b1d1e67
Add files via upload 2019-08-29 11:04:50 +02:00
Adrien Bourmault de31c9d79c
Update VERSIONS.LST 2019-08-28 16:47:02 +02:00
Adrien Bourmault 535583e010
Update changelog 2019-08-28 16:38:18 +02:00
Adrien Bourmault c880645949
Bug reporting bug correction (encrypt the token was the solution) 2019-08-28 16:24:02 +02:00
Adrien Bourmault 83a6e110f6
Correcting "token clear in repo" 2019-08-27 16:49:01 +02:00
Adrien Bourmault 624b78d9d1
Merge pull request #39 from neox95/v3.1
V3.1.4
2019-08-27 14:22:18 +02:00
Adrien Bourmault 1fe97b425a
Update VERSIONS.LST 2019-08-27 14:07:31 +02:00
Adrien Bourmault 6a7d8ea5fb
Correcting bug reporting bug ;) 2019-08-27 14:06:33 +02:00
Adrien Bourmault 5e616e5283
Update VERSIONS.LST 2019-08-27 13:30:16 +02:00
Adrien Bourmault 072f1a2510
Correction of a bug in bug reporting system 2019-08-27 13:24:12 +02:00
Adrien Bourmault a7a22be152
Update VERSIONS.LST 2019-08-27 09:37:49 +02:00
Adrien Bourmault 7aed2c6623
Update VERSIONS.LST 2019-08-27 09:37:15 +02:00
Adrien Bourmault b78d2842bf
Update VERSIONS.LST 2019-08-27 09:34:18 +02:00
Adrien Bourmault f44fd1add7
Release 3.1.4 2019-08-27 09:26:16 +02:00
Adrien Bourmault 9972359ac1
Update VERSIONS.LST 2019-08-26 16:58:08 +02:00
Adrien Bourmault b69e312cf7
Add files via upload 2019-08-26 16:54:03 +02:00
Adrien Bourmault 30e1b15dd1
Added temporization on update to prevent updating every launch 2019-08-26 16:50:51 +02:00
Adrien Bourmault 6d4104e6fa
Add files via upload 2019-08-26 13:46:22 +02:00
Adrien Bourmault 98cae9b951
Update VERSIONS.LST 2019-08-26 13:46:00 +02:00
Adrien Bourmault 1cce5184fd
Add files via upload 2019-08-26 13:45:33 +02:00
Adrien Bourmault bf508555da
Merge pull request #33 from neox95/v3.1
V3.1.3
2019-08-26 10:11:36 +02:00
Adrien Bourmault 9e57123850
Update VERSIONS.LST 2019-08-26 10:03:56 +02:00
Adrien Bourmault 685f7aab5a
Update VERSIONS.LST 2019-08-26 10:03:19 +02:00
Adrien Bourmault 43fca39314
Update VERSIONS.LST 2019-08-26 10:02:33 +02:00
Adrien Bourmault 3110872310
Added version.res 2019-08-26 10:00:46 +02:00
Adrien Bourmault 46b7eb8c26
Update VERSIONS.LST 2019-08-26 09:47:52 +02:00
Adrien Bourmault c7fb8d4c4b
Patching 3.1.3 2019-08-26 09:45:03 +02:00
Adrien Bourmault fe940585ac
Added version.res in the buildchain 2019-08-26 09:43:41 +02:00
Adrien Bourmault 2dee9b79cf
Update VERSIONS.LST 2019-08-23 16:57:18 +02:00
Adrien Bourmault e037bba76e
Add files via upload 2019-08-23 16:46:25 +02:00
Adrien Bourmault e7d164d355
Add files via upload 2019-08-23 16:44:58 +02:00
Adrien Bourmault 19684df1c1 Update issue templates 2019-08-23 15:22:27 +02:00
Adrien Bourmault c2503d411b Update issue templates 2019-08-23 15:15:35 +02:00
Adrien Bourmault d5620bdd30 Update issue templates 2019-08-23 15:14:40 +02:00
Adrien Bourmault 1f19344896
Merge pull request #19 from neox95/v3.1
Update VERSIONS.LST
2019-08-21 16:07:17 +02:00
Adrien Bourmault 085cb2f571
Update VERSIONS.LST 2019-08-21 16:07:00 +02:00
Adrien Bourmault e45af9d903
Merge pull request #18 from neox95/v3.1
Correction of some bugs with the image processing and adding some too…
2019-08-21 14:55:42 +02:00
Adrien Bourmault 4062d68b2b
Correction of some bugs with the image processing and adding some tools for images 2019-08-21 14:54:05 +02:00
Adrien Bourmault cb46844fec
Merge pull request #17 from neox95/v3.1
V3.1
2019-08-21 10:44:32 +02:00
Adrien Bourmault 1c38f1c8b4
Merge branch 'master' into v3.1 2019-08-21 10:44:22 +02:00
Adrien Bourmault a277295374
Create VERSIONS.LST 2019-08-21 10:43:58 +02:00
Adrien Bourmault 0897452d06
Delete VERSIONS.LST 2019-08-21 10:43:19 +02:00
Adrien Bourmault 20c0b44d7b
Delete CNIRevelator Documentation.docx 2019-08-21 10:42:58 +02:00
Adrien Bourmault d45a0a9e9c
Update VERSIONS.LST 2019-08-21 10:38:56 +02:00
Adrien Bourmault 17ad747e50
Release 3.1.2 2019-08-21 10:36:57 +02:00
Adrien Bourmault 086d98fa3d
Delete zoomOut50.png 2019-08-21 10:35:54 +02:00
Adrien Bourmault 840d70d9a3
Delete rotateRight1.png 2019-08-21 10:35:48 +02:00
Adrien Bourmault cff6c44c91
Delete logger.py 2019-08-21 10:35:40 +02:00
Adrien Bourmault f58e964e78
Delete ihm.py 2019-08-21 10:35:33 +02:00
Adrien Bourmault 31672ec6f6
Delete globs.py 2019-08-21 10:35:25 +02:00
Adrien Bourmault dfd0b9c988
Delete main.py 2019-08-21 10:34:53 +02:00
Adrien Bourmault 0b0661bfa9
Delete launcher.py 2019-08-21 10:34:52 +02:00
Adrien Bourmault 1483797828
Delete lang.py 2019-08-21 10:34:51 +02:00
Adrien Bourmault a59b9cfff1
Delete id-card.svg 2019-08-21 10:34:49 +02:00
Adrien Bourmault ff5c480929
Delete id-card.ico.png 2019-08-21 10:34:48 +02:00
Adrien Bourmault 20532650eb
Delete id-card.ico 2019-08-21 10:34:41 +02:00
Adrien Bourmault 2be7a7568e
Delete downloader.py 2019-08-21 10:34:39 +02:00
Adrien Bourmault 31a3518213
Delete critical.py 2019-08-21 10:34:38 +02:00
Adrien Bourmault 2bc2c9c13b
Delete background.svg 2019-08-21 10:34:37 +02:00
Adrien Bourmault a9b7056114
Delete background.png 2019-08-21 10:34:36 +02:00
Adrien Bourmault eabb676c28
Delete OCR.png 2019-08-21 10:34:34 +02:00
Adrien Bourmault e065642f8b
Delete zoomOut20.png 2019-08-21 10:34:33 +02:00
Adrien Bourmault a13ca281ba
Delete zoomOut.png 2019-08-21 10:34:32 +02:00
Adrien Bourmault f1dd2129ca
Delete zoomIn50.png 2019-08-21 10:34:31 +02:00
Adrien Bourmault 659d47f47f
Delete zoomIn20.png 2019-08-21 10:34:31 +02:00
Adrien Bourmault 942f6dd9da
Delete zoomIn.png 2019-08-21 10:34:30 +02:00
Adrien Bourmault bcf0fde819
Delete updater.py 2019-08-21 10:34:28 +02:00
Adrien Bourmault 14f98e8493
Delete rotateRight.png 2019-08-21 10:33:50 +02:00
Adrien Bourmault afed0fe6ec
Delete rotateLeft1.png 2019-08-21 10:33:46 +02:00
Adrien Bourmault d55146b532
Delete rotateLeft.png 2019-08-21 10:33:41 +02:00
Adrien Bourmault ea40cf5938
Delete pytesseract.py 2019-08-21 10:33:30 +02:00
Adrien Bourmault 99ce7d59f7
Delete mrz.py 2019-08-21 10:33:26 +02:00
Adrien Bourmault 5eb98d2004
Delete Invert.png 2019-08-21 10:32:35 +02:00
Adrien Bourmault 06d50121c7
Delete CNIRevelator.py 2019-08-21 10:32:26 +02:00
Adrien Bourmault 017329257e
Add files via upload 2019-08-21 10:31:53 +02:00
Adrien Bourmault 81313007b0
Releasing 3.1.2 2019-08-21 10:26:17 +02:00
Adrien Bourmault ad813c0b14
Update VERSIONS.LST 2019-08-20 19:14:15 +02:00
Adrien Bourmault ea93e4a7dd
Merge pull request #16 from neox95/v3.1
V3.1.2
2019-08-20 19:13:23 +02:00
Adrien Bourmault 45d8734f7d
Update VERSIONS.LST 2019-08-20 19:12:57 +02:00
Adrien Bourmault 9d7e866807
Update VERSIONS.LST 2019-08-20 19:08:40 +02:00
Adrien Bourmault fd7c68e4a1
Update VERSIONS.LST 2019-08-20 19:07:04 +02:00
Adrien Bourmault 26b2c7c564
Update VERSIONS.LST 2019-08-20 19:01:40 +02:00
Adrien Bourmault 4bf8fad661
Update VERSIONS.LST 2019-08-20 18:59:33 +02:00
Adrien Bourmault 16f1d00e35
Update VERSIONS.LST 2019-08-20 18:58:20 +02:00
Adrien Bourmault d399c4d7ca
Update VERSIONS.LST 2019-08-20 18:56:58 +02:00
Adrien Bourmault 1054884b51
Update VERSIONS.LST 2019-08-20 18:54:26 +02:00
Adrien Bourmault 5547305794
Update VERSIONS.LST 2019-08-20 18:50:09 +02:00
Adrien Bourmault 822b206280
Add files via upload 2019-08-20 18:41:33 +02:00
Adrien Bourmault 6d514b1ada
Add files via upload 2019-08-20 18:41:07 +02:00
Adrien Bourmault 2db1c28e24
Upgrade Tesseract to 5.0 2019-08-20 18:38:22 +02:00
Adrien Bourmault 6c480d49b9
Add files via upload 2019-08-20 15:43:00 +02:00
Adrien Bourmault 73f0c1b583
Merge pull request #15 from neox95/v3.1
Release 3.1.1
2019-08-20 10:31:02 +02:00
Adrien Bourmault 9423e316eb
Release 3.1.1 2019-08-20 10:30:30 +02:00
Adrien Bourmault 9bc808d785
Merge pull request #14 from neox95/v3.1
V3.1.1 release
2019-08-20 10:29:59 +02:00
Adrien Bourmault 49ee60e58a
Merge branch 'master' into v3.1 2019-08-20 10:29:48 +02:00
Adrien Bourmault f117fb8658
Testing 3.1.1 update system 2019-08-20 10:21:56 +02:00
Adrien Bourmault fcf8949c6b
Release 3.1.1 2019-08-20 10:19:32 +02:00
Adrien Bourmault b0d4fbf2fc
Update VERSIONS.LST 2019-08-20 09:43:36 +02:00
Adrien Bourmault c34a88abc5
Minor correction 2019-08-12 17:15:51 +02:00
Adrien Bourmault 8e389ddf25
Minor correction 2019-08-12 17:14:41 +02:00
20 changed files with 784 additions and 208 deletions

38
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View 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.

View 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.

Binary file not shown.

View File

@ -1,5 +1,5 @@
# 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.

View File

@ -1,2 +1,2 @@
# ver|url|checksum, and | as separator, one version per ||
3.1.1|https://github.com/neox95/CNIRevelator/releases/download/3.1.0/CNIRevelator.zip|24f872345701e4088c194b471c502bd72cf54aff||
# ver|url|checksum, and | as separator, one version per ||
3.1.6|https://github.com/neox95/CNIRevelator/releases/download/3.1.6/CNIRevelator.zip|8977e1f335d08419be68133fe229ead453279b7f||

View File

@ -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 src\id-card.ico dist\CNIRevelator\id-card.ico

View File

@ -1,3 +1,4 @@
# -*- coding: utf8 -*-
"""
********************************************************************************
* CNIRevelator *
@ -54,8 +55,8 @@ def main():
mainw = mainWindow()
try:
os.environ['PATH'] = globs.CNIRFolder + '\\Tesseract-OCR4\\'
os.environ['TESSDATA_PREFIX'] = globs.CNIRFolder + '\\Tesseract-OCR4\\tessdata'
os.environ['PATH'] = globs.CNIRFolder + '\\Tesseract-OCR5\\'
os.environ['TESSDATA_PREFIX'] = globs.CNIRFolder + '\\Tesseract-OCR5\\tessdata'
tesser_version = pytesseract.get_tesseract_version()
except Exception as e:
logfile.printerr('ERROR WITH TESSERACT MODULE ' + str(e))
@ -83,6 +84,8 @@ def main():
## BOOTSTRAP OF CNIREVELATOR
try:
logfile.printdbg('CNIRevelator log file version {}'.format(globs.verstring_full))
try:
# LANGUAGE
lang.readLang()
@ -96,8 +99,7 @@ try:
launcherThread = threading.Thread(target=updater.umain, daemon=False)
launcher.lmain(launcherThread)
except Exception:
critical.crashCNIR()
updater.exitProcess(1)
critical.crashCNIR(False)
if updater.UPDATE_IS_MADE:
# Launch app !

View File

@ -1,3 +1,4 @@
# -*- coding: utf8 -*-
"""
********************************************************************************
* CNIRevelator *
@ -30,11 +31,12 @@ import traceback
import psutil
import os
import lang # lang.py
import logger # logger.py
import globs # globs.py
import lang # lang.py
import logger # logger.py
import globs # globs.py
import github # github.py
def crashCNIR(shutdown=True):
def crashCNIR(shutdown=True, option="", isVoluntary=False):
"""
very last solution
"""
@ -44,13 +46,37 @@ def crashCNIR(shutdown=True):
root.withdraw()
logfile = logger.logCur
logfile.printerr("FATAL ERROR : see traceback below.\n{}".format(traceback.format_exc()))
showerror(lang.all[globs.CNIRlang]["CNIRevelator Fatal Eror"], lang.all[globs.CNIRlang]["CNIRevelator crashed because a fatal error occured. View log for more infos and please open an issue on Github"], parent=root)
res = askquestion(lang.all[globs.CNIRlang]["CNIRevelator Fatal Eror"], lang.all[globs.CNIRlang]["Would you like to open the log file ?"], parent=root)
if 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":
webbrowser.open_new(globs.CNIRErrLog)
res = askquestion(lang.all[globs.CNIRlang]["CNIRevelator Fatal Eror"], lang.all[globs.CNIRlang]["Would you like to open an issue on Github to report this bug ?"], parent=root)
if res == "yes":
webbrowser.open_new("https://github.com/neox95/CNIRevelator/issues")
# 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 ?"])
if res == "yes":
webbrowser.open_new(globs.CNIRErrLog)
else:
showinfo(lang.all[globs.CNIRlang]["CNIRevelator Fatal Eror"], lang.all[globs.CNIRlang]["Bug reported successfully. Thanks."])
root.destroy()
# Quit ?

View File

@ -1,3 +1,4 @@
# -*- coding: utf8 -*-
"""
********************************************************************************
* CNIRevelator *
@ -80,10 +81,11 @@ class newcredentials:
self.trying += 1
try:
sessionAnswer = session.get('https://www.google.com')
sessionAnswer = session.get('http://www.google.com')
except Exception as e:
logfile.printdbg('Network Error : ' + str(e))
sessionAnswer = ''
self.login = "nointernet"
return
logfile.printdbg("Session Answer : " + str(sessionAnswer))
@ -93,11 +95,6 @@ class newcredentials:
self.valid = True
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:
logfile.printerr('Invalid credentials : access denied, a maximum of 3 trials have been raised !')
return

189
src/github.py Normal file
View 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)

View File

@ -1,3 +1,4 @@
# -*- coding: utf8 -*-
"""
********************************************************************************
* CNIRevelator *
@ -25,28 +26,13 @@
import os
# CNIRevelator version
verType = "final release"
version = [3, 1, 1]
verType = "stable release"
version = [3, 1, 6]
verstring_full = "{}.{}.{} {}".format(version[0], version[1], version[2], verType)
verstring = "{}.{}".format(version[0], version[1])
CNIRTesserHash = '5b58db27f7bc08c58a2cb33d01533b034b067cf8'
CNIRFolder = os.getcwd()
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'
CNIRTesserHash = "947224361ffab8c01f05c9394b44b1bd7c8c3d4d"
CNIRGitToken = "mJHKXqnazO/xZ9Fs18SDMqcGJ15A27OlZyd27cDe5dhHKklO2YShdWwUgEDUZQI02kpgYaLceMidTK37ZqakW+VYgPPuh0e9Ry2IH0KHc3o="
CNIRFolder = os.path.dirname(os.path.realpath(__file__))
CNIRLColor = "#006699"
CNIRName = "CNIRevelator {}".format(verstring)
@ -56,10 +42,11 @@ CNIRLangFile = CNIRFolder + '\\config\\lang.ig'
CNIRlang = "fr"
CNIRConfig = CNIRFolder + '\\config\\conf.ig'
CNIRTesser = CNIRFolder + '\\Tesseract-OCR4\\'
CNIRTesser = CNIRFolder + '\\Tesseract-OCR5\\'
CNIRErrLog = CNIRFolder + '\\logs\\error.log'
CNIRMainLog = CNIRFolder + '\\logs\\main.log'
CNIRUrlConfig = CNIRFolder + '\\config\\urlconf.ig'
CNIRLastUpdate = CNIRFolder + '\\config\\lastupdate.ig'
CNIRVerStock = CNIRFolder + '\\downloads\\versions.lst'
CNIREnv = CNIRFolder + '\\Data\\'

View File

@ -1,3 +1,4 @@
# -*- coding: utf8 -*-
"""
********************************************************************************
* CNIRevelator *
@ -29,7 +30,6 @@ from tkinter import filedialog
from tkinter import ttk
import PIL.Image, PIL.ImageTk
import traceback
import webbrowser
import cv2
import critical # critical.py
@ -44,13 +44,16 @@ controlKeys = ["Escape", "Right", "Left", "Up", "Down", "Home", "End", "BackSpac
class DocumentAsk(Toplevel):
def __init__(self, parent, choices):
self.choice = 0
vals = [0, 1]
super().__init__(parent)
self.title("{} :".format(lang.all[globs.CNIRlang]["Choose the identity document"]))
ttk.Radiobutton(self, text=choices[0], command=self.register0, value=vals[0]).pack()
ttk.Radiobutton(self, text=choices[1], command=self.register1, value=vals[1]).pack()
self.choice = 0
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.resizable(width=False, height=False)
@ -67,10 +70,11 @@ class DocumentAsk(Toplevel):
y = hs / 2 - h / 2
self.geometry('%dx%d+%d+%d' % (w, h, x, y))
def register0(self):
self.choice = 0
def register1(self):
self.choice = 1
def createRegister(self, i):
def register():
self.choice = i
return register
def ok(self):
self.destroy()
@ -192,7 +196,7 @@ class ChangelogDialog(Toplevel):
class langDialog(Toplevel):
def __init__(self, parent):
def __init__(self, parent, currentLang):
super().__init__(parent)
self.title(lang.all[globs.CNIRlang]["Language"])
@ -201,7 +205,10 @@ class langDialog(Toplevel):
vals = [i for i in lang.all]
for i in range(len(lang.all)):
ttk.Radiobutton(self, text=vals[i], command=self.createRegister(i), value=vals[i]).pack(fill=Y)
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)
@ -230,7 +237,7 @@ class langDialog(Toplevel):
class updateSetDialog(Toplevel):
def __init__(self, parent):
def __init__(self, parent, currentChannel):
super().__init__(parent)
self.title(lang.all[globs.CNIRlang]["Update options"])
@ -240,7 +247,11 @@ class updateSetDialog(Toplevel):
self.vals = ["Stable", "Beta"]
vals = self.vals
for i in range(len(vals)):
ttk.Radiobutton(self, text=vals[i], command=self.createRegister(i), value=vals[i]).pack(fill=Y)
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)
@ -264,7 +275,7 @@ class updateSetDialog(Toplevel):
def createRegister(self, i):
def register():
updater.updateChannel(self.vals[i])
updater.setUpdateChannel(self.vals[i])
return register
class LauncherWindow(Tk):
@ -295,8 +306,6 @@ class LauncherWindow(Tk):
# if getattr(sys, 'frozen', False):
# cv_img = cv2.imread(sys._MEIPASS + r"\background.png\background.png")
# else:
cv_img = cv2.imread("background.png")
cv_img = cv2.imread("background.png")
cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB)
cv_img = cv2.blur(cv_img, (15, 15))
@ -373,3 +382,4 @@ class StatusBar(Frame):
## Global Handler
launcherWindowCur = LauncherWindow()
# test ?

View File

@ -1,3 +1,4 @@
# -*- coding: utf8 -*-
"""
********************************************************************************
* CNIRevelator *
@ -50,11 +51,13 @@ french = \
"CNIRevelator crashed because a "
"fatal error occured. View log for "
"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 "
"log file ?" : "Souhaitez-vous ouvrir le fichier de log ?",
"Would you like to open an issue "
"on Github to report this bug ?" : "Souhaitez-vous ouvrir un ticket sur Github pour signaler ce bogue?",
"log file ?" : "Le signalement a échoué. Souhaitez-vous ouvrir le fichier de log ?",
"Bug reported successfully. "
"Thanks." : "Bogue signalé avec succès, merci.",
"Would you like to report this "
"bug ?" : "Souhaitez-vous signaler ce bogue?",
"Starting..." : "Lancement...",
"Informations about the current "
"document" : "Informations sur la pièce d'identité",
@ -69,6 +72,8 @@ french = \
"Nationality" : "Nationalité",
"Registration" : "Immatriculation",
"Document number" : "N° de document",
"Length" : "Longueur",
"Facultative" : "Facultatif",
"Unknown" : "Inconnu(e)",
"Display and processing of "
"documents" : "Affichage et traitement de documents",
@ -138,7 +143,12 @@ french = \
"Coller :\t\t\t\tCtrl-V \n"
"Forcer une nouvelle détection du document :\tEchap\n",
"CHANGELOG" : "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" + \
"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.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" + \
@ -151,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",
"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 "
"Calculated {}\n" : "Checksum position {}: Lu {} VS Calculé {}\n",
"COMPLIANT" : "CONFORME",
@ -179,16 +190,30 @@ french = \
"Please choose your language : " : "Merci de choisir votre langue : ",
"Please choose your update "
"channel : " : "Merci de choisir votre canal de mise-à-jour : ",
"Passeport" : "Passeport",
"Passeport lisible à la machine" : "Passeport lisible à la machine",
"Carte-passeport" : "Carte-passeport",
"Titre d'identité/de voyage" : "Titre d'identité/de voyage",
"Carte didentité européenne" : "Carte didentité européenne",
"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 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é FR" : "Pièce d'identité FR",
"Pièce d'identité FR" : "Pièce d'identité française",
"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" : {
'AW': 'Aruba',
@ -737,11 +762,13 @@ english = \
"CNIRevelator crashed because a "
"fatal error occured. View log for "
"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",
"Would you like to open an issue "
"on Github to report this bug ?" : "Would you like to open an issue on Github to report this bug ?",
"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 report this "
"bug ?" : "Would you like to report this bug ?",
"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...",
"Informations about the current "
"document" : "Informations about the current document",
@ -756,6 +783,8 @@ english = \
"Nationality" : "Nationality",
"Registration" : "Registration",
"Document number" : "Document number",
"Length" : "Length",
"Facultative" : "Facultative",
"Unknown" : "Unknown",
"Display and processing of "
"documents" : "Display and processing of documents",
@ -789,6 +818,8 @@ english = \
"the OpenCV image processing "
"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",
"No Internet Error. No effective "
"update !" : "No Internet Error. No effective update !",
"ABOUT" : 'Software Version: CNIRevelator' + globs.verstring_full + '\n\n'
"Copyright © 2018-2019 Adrien Bourmault (neox95)" + "\n\n"
@ -827,7 +858,12 @@ english = \
"Paste:\t\t\t\tCtrl-V\n"
"Force a new document detection:\tEchap\n",
"CHANGELOG" : "Version 3.1.1 \nMinor update with the following progressions: \n- Fixed a severe bug in the update system" + \
"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.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" + \
@ -840,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",
"Document Review: {}\n\n" : "Document Review: {}\n\n",
"Checksum position {}: Lu {} VS "
"Calculated {} [facultative]\n" : "Checksum position {}: Read {} VS Calculated {} [facultative]\n",
"Checksum position {}: Lu {} "
"VS Calculated {} [facultative]\n" : "Checksum position {}: Lu {} VS Calculated {} [facultative]\n",
"Checksum position {}: Lu {} VS "
"Calculated {}\n" : "Checksum position {}: Read {} VS Calculated {}\n",
"COMPLIANT" : "COMPLIANT",
@ -869,16 +905,28 @@ english = \
"Please choose your language : " : "Please choose your language : ",
"Please choose your update "
"channel : " : "Please choose your update channel : ",
"Passeport" : "Passport",
"Passeport lisible à la machine" : "Machine Readable Passport",
"Carte-passeport" : "Passport card",
"Carte didentité européenne" : "European identity document",
"Carte de séjour européenne" : "European Residence permit",
"Titre d'identité/de voyage" : "Identity/travel document",
"Certificat de membre d'équipage" : "Crew member certificate",
"Visa de type A" : "Type A 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é FR" : "French Identity card",
"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" : {
"AW": "Aruba",

View File

@ -1,3 +1,4 @@
# -*- coding: utf8 -*-
"""
********************************************************************************
* CNIRevelator *

View File

@ -1,3 +1,4 @@
# -*- coding: utf8 -*-
"""
********************************************************************************
* CNIRevelator *

View File

@ -1,3 +1,4 @@
# -*- coding: utf8 -*-
"""
********************************************************************************
* CNIRevelator *
@ -32,12 +33,14 @@ from tkinter import ttk
import threading
from datetime import datetime
from importlib import reload
import unicodedata
import re
import cv2
import PIL.Image, PIL.ImageTk
import os, shutil
import webbrowser
import sys, os
import numpy
import webbrowser
import critical # critical.py
import ihm # ihm.py
@ -46,6 +49,7 @@ import mrz # mrz.py
import globs # globs.py
import pytesseract # pytesseract.py
import lang # lang.py
import updater # updater.py
# Global handler
logfile = logger.logCur
@ -67,6 +71,7 @@ class mainWindow(Tk):
self.Tags = []
self.compliance = True
self.corners = []
self.indicators = []
self.validatedtext = ""
# The icon
@ -105,6 +110,7 @@ class mainWindow(Tk):
self.lecteur_ci.grid_rowconfigure(3, weight=1)
self.lecteur_ci.grid_rowconfigure(4, weight=1)
self.lecteur_ci.grid_rowconfigure(5, weight=1)
self.lecteur_ci.grid_rowconfigure(6, weight=1)
# And what about the status bar ?
self.statusbar = ihm.StatusBar(self)
@ -145,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)
self.no = ttk.Label((self.lecteur_ci), text=' ')
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.prenom['text'] = lang.all[globs.CNIRlang]["Unknown"]
@ -156,6 +165,7 @@ class mainWindow(Tk):
self.nat['text'] = lang.all[globs.CNIRlang]["Unknown"]
self.pays['text'] = lang.all[globs.CNIRlang]["Unknown"]
self.indic['text'] = lang.all[globs.CNIRlang]["Unknown"]
self.len['text'] = lang.all[globs.CNIRlang]["Unknown"]
self.infoList = \
@ -170,6 +180,7 @@ class mainWindow(Tk):
"NAT" : self.nat,
"PAYS" : self.pays,
"INDIC" : self.indic,
"LEN" : self.len,
}
# The the image viewer
@ -229,7 +240,7 @@ class mainWindow(Tk):
self.toolbar.zoomOut50.grid(column=5, row=0)
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.rotateLeftImg = ImageTk.PhotoImage(PIL.Image.open("rotateLeft.png"))
@ -309,9 +320,9 @@ class mainWindow(Tk):
self.speed731.grid_columnconfigure(9, weight=1)
self.speed731.grid_rowconfigure(0, weight=1)
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.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
self.monitor = ttk.Labelframe(self, text=lang.all[globs.CNIRlang]["Monitor"])
@ -348,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]["Report a bug"], command=(self.openIssuePage))
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))
menubar.add_cascade(label=lang.all[globs.CNIRlang]["Help"], menu=menu3)
menubar.add_command(label="<|>", command=(self.panelResize))
@ -368,7 +380,7 @@ class mainWindow(Tk):
self.geometry('%dx%d+%d+%d' % (self.w, self.h, self.x, self.y))
self.update()
self.deiconify()
self.attributes("-topmost", 1)
#self.attributes("-topmost", 1)
self.maxsize(self.w, self.h)
self.minsize(int(2.15 * (self.ws / 2 * 0.3333333333333333)), self.h)
self.currentw = self.w
@ -378,10 +390,11 @@ class mainWindow(Tk):
self.imageViewer.imagePath = None
self.imageViewer.imgZoom = 1
self.imageViewer.rotateCount = 0
self.imageViewer.blackhat = False
self.imageViewer.blackhat = 0
self.imageViewer.pagenumber = 0
# Some bindings
self.bind('<Control_R>', self.entryValidation)
self.termtext.bind('<Key>', self.entryValidation)
self.termtext.bind('<<Paste>>', self.pasteValidation)
self.speed731text.bind('<Control_R>', self.speedValidation)
@ -405,11 +418,19 @@ class mainWindow(Tk):
self.corners.append([canvas.canvasx(event.x), canvas.canvasy(event.y)])
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]))
# Reinit
if len(self.corners) > 2:
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):
"""
@ -418,10 +439,13 @@ class mainWindow(Tk):
if self.imageViewer.image:
cv_img = cv2.imreadmulti(self.imageViewer.imagePath)[1][self.imageViewer.pagenumber]
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.GaussianBlur(cv_img, (3, 3), 0)
cv_img = cv2.bitwise_not(cv_img)
cv_img = cv2.threshold(cv_img, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
elif self.imageViewer.blackhat == 2:
cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2GRAY)
cv_img = cv2.medianBlur(cv_img, 3)
try:
# Get the image dimensions (OpenCV stores image data as NumPy ndarray)
height, width, channels_no = cv_img.shape
@ -432,18 +456,21 @@ class mainWindow(Tk):
height, width = cv_img.shape
# Get the image dimensions (OpenCV stores image data as NumPy ndarray)
height, width = cv_img.shape
# Rotate
rotationMatrix=cv2.getRotationMatrix2D((width/2, height/2),int(self.imageViewer.rotateCount*90),1)
cv_img=cv2.warpAffine(cv_img,rotationMatrix,(width,height))
cv_img, width, height = self.rotateBound(cv_img, int(self.imageViewer.rotateCount*90))
# Resize
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)
x0 = int(self.corners[0][0])
y0 = int(self.corners[0][1])
x1 = int(self.corners[1][0])
y1 = int(self.corners[1][1])
# Crop
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]
# Get the text by OCR
@ -451,7 +478,7 @@ class mainWindow(Tk):
os.environ['PATH'] = globs.CNIRTesser
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
# the regex
@ -474,7 +501,7 @@ class mainWindow(Tk):
self.termtext.insert("1.0", self.mrzChar)
self.mrzChar = self.mrzChar + char
self.stringValidation("")
self.stringValidation(isFull=True)
#print(self.mrzChar)
# Reinstall tesseract
@ -493,7 +520,7 @@ class mainWindow(Tk):
## Regex and document detection + control related functions
def stringValidation(self, keysym):
def stringValidation(self, keysym="", isFull=False):
"""
Analysis of the already typed document
"""
@ -501,11 +528,11 @@ class mainWindow(Tk):
# If we must decide the type of the document
if not self.mrzDecided:
# 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
invite = ihm.DocumentAsk(self, [candidates[0][2], candidates[1][2]])
invite = ihm.DocumentAsk(self, candidates)
invite.transient(self)
invite.grab_set()
invite.focus_force()
@ -541,10 +568,13 @@ class mainWindow(Tk):
self.termtext.insert("1.0", self.mrzChar)
# stop when limit reached
elif (len(self.mrzChar) - 3 >= 2 * len(self.mrzDecided[0][0])):
self.mrzChar = self.termtext.get("1.0", "end")[:-1]
self.termtext.delete("1.0","end")
self.termtext.insert("1.0", self.mrzChar[:-1])
self.termtext.mark_set(INSERT, curPos)
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.termtext.delete("1.0","end")
self.termtext.insert("1.0", self.mrzChar[:-1])
self.termtext.mark_set(INSERT, curPos)
# compute the control sum if needed
self.computeSigma()
@ -596,9 +626,9 @@ class mainWindow(Tk):
# Get the candidates
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
invite = ihm.DocumentAsk(self, [candidates[0][2], candidates[1][2]])
invite = ihm.DocumentAsk(self, candidates)
invite.transient(self)
invite.grab_set()
invite.focus_force()
@ -623,6 +653,7 @@ class mainWindow(Tk):
if not regex.fullmatch(event.char):
self.logOnTerm(lang.all[globs.CNIRlang]["Character not accepted !\n"])
return "break"
# Adds the entry
tempChar = self.termtext.get("1.0", "end")[:-1]
self.mrzChar = tempChar[:pos+1] + event.char + tempChar[pos+1:] + '\n'
@ -712,17 +743,22 @@ class mainWindow(Tk):
#print(docInfos)
# display the infos
for key in [ e for e in docInfos ]:
#print(docInfos[key])
if key in ["CODE", "CTRL", "CTRLF"]:
#printkey)
if key in ["CODE", "CTRL", "CTRLF", "FACULT", "NOINT"]:
continue
if not docInfos[key] == False:
self.infoList[key]['text'] = docInfos[key]
self.infoList[key]['background'] = self['background']
self.infoList[key]['foreground'] = "black"
if not docInfos[key][1] == False:
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]['foreground'] = "black"
else:
self.infoList[key]['background'] = "red"
self.infoList[key]['foreground'] = "white"
self.infoList[key]['text'] = "NC"
self.infoList[key]['text'] = docInfos[key][0]
self.compliance = False
if self.compliance == True:
@ -785,11 +821,15 @@ class mainWindow(Tk):
"""
Open the scan, ask its path and displays it
"""
self.initialize()
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'),
('JPEG files', '*.jpg'),
('JPEG files', '*.jpeg')))
('JPEG files', '*.jpeg'),
('PNG files', '*.png')
))
self.openScanFile(path)
def openScanFile(self, path):
@ -800,17 +840,18 @@ class mainWindow(Tk):
if ( path[-3:] != 'jpg'
and path[-3:] != 'tif'
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))
return
return
# Load an image using OpenCV
self.imageViewer.imagePath = path
self.imageViewer.imgZoom = 1
self.imageViewer.blackhat = False
self.imageViewer.blackhat = 0
self.imageViewer.rotateCount = 0
self.imageViewer.pagenumber = 0
# Determine how many pages
self.toolbar.pageChooser['values'] = ('1')
total = len(cv2.imreadmulti(self.imageViewer.imagePath)[1])
@ -819,8 +860,12 @@ class mainWindow(Tk):
self.toolbar.pageChooser['values'] += tuple(str(i))
# Open the first page
cv_img = cv2.imreadmulti(self.imageViewer.imagePath)[1][self.imageViewer.pagenumber]
cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB)
try:
cv_img = cv2.imreadmulti(self.imageViewer.imagePath)[1][self.imageViewer.pagenumber]
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:
# Get the image dimensions (OpenCV stores image data as NumPy ndarray)
@ -833,6 +878,10 @@ class mainWindow(Tk):
# Get the image dimensions (OpenCV stores image data as NumPy ndarray)
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
photo = PIL.ImageTk.PhotoImage(image = PIL.Image.fromarray(cv_img))
self.DisplayUpdate(photo)
@ -843,7 +892,7 @@ class mainWindow(Tk):
self.resizeScan()
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.resizeScan()
@ -853,7 +902,7 @@ class mainWindow(Tk):
self.resizeScan()
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.resizeScan()
@ -863,7 +912,7 @@ class mainWindow(Tk):
self.resizeScan()
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.resizeScan()
@ -895,7 +944,7 @@ class mainWindow(Tk):
self.imageViewer.rotateCount = 4
self.resizeScan()
def negativeScan(self):
def threshScan(self):
"""
Invert the bits to make a negative of the scan (and highlight the contrasts)
"""
@ -903,15 +952,44 @@ class mainWindow(Tk):
# Load an image using OpenCV
cv_img = cv2.imreadmulti(self.imageViewer.imagePath)[1][self.imageViewer.pagenumber]
cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB)
if not self.imageViewer.blackhat:
self.imageViewer.blackhat = True
if self.imageViewer.blackhat == 0:
self.imageViewer.blackhat = 1
cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2GRAY)
cv_img = cv2.GaussianBlur(cv_img, (3, 3), 0)
cv_img = cv2.bitwise_not(cv_img)
cv_img = cv2.threshold(cv_img, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
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:
self.imageViewer.blackhat = False
self.imageViewer.blackhat = 0
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):
"""
Reloads the image according to settings
@ -922,11 +1000,13 @@ class mainWindow(Tk):
# Load an image using OpenCV
cv_img = cv2.imreadmulti(self.imageViewer.imagePath)[1][self.imageViewer.pagenumber]
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.GaussianBlur(cv_img, (3, 3), 0)
cv_img = cv2.bitwise_not(cv_img)
cv_img = cv2.threshold(cv_img, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
elif self.imageViewer.blackhat == 2:
cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2GRAY)
cv_img = cv2.medianBlur(cv_img, 3)
try:
# Get the image dimensions (OpenCV stores image data as NumPy ndarray)
height, width, channels_no = cv_img.shape
@ -937,23 +1017,26 @@ class mainWindow(Tk):
height, width = cv_img.shape
# Get the image dimensions (OpenCV stores image data as NumPy ndarray)
height, width = cv_img.shape
# Rotate
rotationMatrix=cv2.getRotationMatrix2D((width/2, height/2),int(self.imageViewer.rotateCount*90),1)
cv_img=cv2.warpAffine(cv_img,rotationMatrix,(width,height))
cv_img, width, height = self.rotateBound(cv_img, int(self.imageViewer.rotateCount*90))
# Resize
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)
# Update shape
self.imageViewer.height, self.imageViewer.width = cv_img.shape[:2]
# Use PIL (Pillow) to convert the NumPy ndarray to a PhotoImage
photo = PIL.ImageTk.PhotoImage(image = PIL.Image.fromarray(cv_img))
self.DisplayUpdate( photo)
except Exception as e:
logfile.printerr("Error with opencv : {}".format(e))
critical.crashCNIR()
try:
# Reload an image using OpenCV
path = self.imageViewer.imagePath
self.imageViewer.imgZoom = 1
self.imageViewer.blackhat = False
self.imageViewer.blackhat = 0
self.imageViewer.rotateCount = 0
cv_img = cv2.imreadmulti(path)
cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB)
@ -966,8 +1049,7 @@ class mainWindow(Tk):
self.DisplayUpdate(photo)
except Exception as e:
logfile.printerr("Critical error with opencv : ".format(e))
critical.crashCNIR()
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"])
critical.crashCNIR(False, "OpenCV resizeScan() error")
self.initialize()
## IHM and user interface related functions
@ -1006,9 +1088,15 @@ class mainWindow(Tk):
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):
changelogWin = ihm.ChangelogDialog(self, ('{} : CNIRevelator {}\n\n{}'.format(lang.all[globs.CNIRlang]["Program version"], globs.verstring_full, lang.all[globs.CNIRlang]["CHANGELOG"])))
@ -1021,7 +1109,7 @@ class mainWindow(Tk):
"""
Update Settings
"""
changeupdateWin = ihm.updateSetDialog(self)
changeupdateWin = ihm.updateSetDialog(self, updater.getUpdateChannel())
changeupdateWin.transient(self)
changeupdateWin.grab_set()
changeupdateWin.focus_force()
@ -1031,7 +1119,7 @@ class mainWindow(Tk):
"""
Lang Settings
"""
changelangWin = ihm.langDialog(self)
changelangWin = ihm.langDialog(self, globs.CNIRlang)
changelangWin.transient(self)
changelangWin.grab_set()
changelangWin.focus_force()

View File

@ -1,3 +1,4 @@
# -*- coding: utf8 -*-
"""
********************************************************************************
* CNIRevelator *
@ -61,7 +62,7 @@ P = [
"D": ["1", "CTRLF", "[0-9]", "C"],
"E": ["1", "CTRL", "[0-9]", "4578ABCD"]
},
lang.all[globs.CNIRlang]["Passeport"]
lang.all[globs.CNIRlang]["Passeport lisible à la machine"]
]
IP = [
@ -84,7 +85,7 @@ IP = [
lang.all[globs.CNIRlang]["Carte-passeport"]
]
I_ = [
IDEUR = [
["112223333333334555555555555555", "66666678999999ABBBCCCCCCCCCCCD"],
{
"1": ["2", "CODE", "I."],
@ -101,7 +102,27 @@ I_ = [
"C": ["11", "FACULT", ".+"],
"D": ["1", "CTRL", "[0-9]", "345679AC"]
},
lang.all[globs.CNIRlang]["Titre d'identité/de voyage"]
lang.all[globs.CNIRlang]["Carte didentité 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 = [
@ -126,11 +147,11 @@ AC = [
]
VA = [
["11222333333333333333333333333333333333333333", "444444444566677777789AAAAAABCCCCCCCCCCCCCCCCC"],
["11222333333333333333333333333333333333333333", "444444444566677777789AAAAAABCCCCCCCCCCCCCCCC"],
{
"1": ["2", "CODE", "V."],
"2": ["3", "PAYS", "[A-Z]+"],
"3": ["39", "NOM", "[A-Z]+"],
"3": ["39", "NOM", "([A-Z]|<)+"],
"4": ["9", "NO", ".+"],
"5": ["1", "CTRL", "[0-9]","4"],
"6": ["3", "NAT", "[A-Z]+"],
@ -145,7 +166,7 @@ VA = [
]
VB = [
["112223333333333333333333333333333333", "444444444566677777789AAAAAABCCCCCC"],
["112223333333333333333333333333333333", "444444444566677777789AAAAAABCCCCCCCC"],
{
"1": ["2", "CODE", "V."],
"2": ["3", "PAYS", "[A-Z]+"],
@ -179,10 +200,10 @@ TSF = [
"B": ["1", "CTRL", "[0-9]", "A"],
"C": ["8", "FACULT", ".+"]
},
lang.all[globs.CNIRlang]["Carte de séjour"]
lang.all[globs.CNIRlang]["Carte de séjour FR"]
]
I__ = [
TDV = [
["112223333333333333333333333333333333", "444444444566677777789AAAAAABCCCCCCCD"],
{
"1": ["2", "CODE", "I."],
@ -199,7 +220,7 @@ I__ = [
"C": ["7", "FACULT", ".+"],
"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 = [
@ -236,7 +257,7 @@ DL = [
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 = max([len(x[0][0]) for x in TYPES])
@ -321,7 +342,7 @@ def docMatch(doc, strs):
# logfile.printdbg(" REGEX : {}, match : {}".format(regex, matching))
# 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)
def allDocMatch(strs, final=False):
@ -347,14 +368,25 @@ def allDocMatch(strs, final=False):
candidate = SCORES.index(max(SCORES))
candidates = []
canditxt = []
# Search the candidates
for i in range(len(SCORES)):
if SCORES[i] == SCORES[candidate]:
candidates += [TYPES[i]]
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
#logfile.printdbg("Scores : {}".format(SCORES))
#logfile.printdbg("Candidates : {}".format(canditxt))
logfile.printdbg("Scores : {}".format(SCORES))
logfile.printdbg("Candidates : {}".format(canditxt))
return candidates
def computeControlSum(code):
@ -392,6 +424,11 @@ def computeAllControlSum(doc, code):
# iteration on each char of the given MRZ
for charPos in range(len(code)):
# Sanity check
if len(getDocString(doc)) <= charPos:
break
field = getDocString(doc)[charPos]
if doc[1][field][1] == "CTRL":
@ -400,6 +437,12 @@ def computeAllControlSum(doc, code):
codeChain = ""
# iteration on the fields to control
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]
if target in doc[1][field][3]:
#print("__field : {} {} {} {}".format(target, pos, field, doc[1][field][3]))
@ -444,21 +487,30 @@ def getDocInfos(doc, code):
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:
value = code[ field[1][0] : field[1][1] ].replace("<", " ").strip()
res[field[0]] = [0,0]
# State code
if field[0] == 'PAYS' or field[0] == 'NAT':
try:
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] == "<":
res[field[0]] = landcode2[value[:-1]]
res[field[0]] = (landcode2[value[:-1]], True)
else:
res[field[0]] = landcode2[value]
res[field[0]] = (landcode2[value], True)
except KeyError:
res[field[0]] = False
res[field[0]] = [value, False]
# Dates
elif field[0][1:] == 'DATE':
@ -474,39 +526,43 @@ def getDocInfos(doc, code):
except ValueError:
#print(value)
if value != "":
res[field[0]] = False
res[field[0]] = [value, False]
else:
res[field[0]] = value
res[field[0]] = [value, True]
# Numbers
elif field[0][:-1] == 'NOINT':
try:
res["NO"] += value
res["NO"][0] += value
res["NO"][1] = True
except KeyError:
res["NO"] = value
res["NO"] = [value, True]
elif field[0] == 'NOINT':
try:
res["NO"] += value
res["NO"][0] += value
res["NO"][1] = True
except KeyError:
res["NO"] = value
res["NO"] = [value, True]
elif field[0] == 'FACULT':
try:
res["INDIC"] += value
res["INDIC"][0] += value
res["INDIC"][1] = True
except KeyError:
res["INDIC"] = value
res["INDIC"] = [value, True]
# Sex
elif field[0] == 'SEX':
if not value in "MF":
res[field[0]] = False
res[field[0]] = [value, False]
else:
res[field[0]] = value
res[field[0]] = [value, True]
# All other cases
else:
if value != "":
res[field[0]] = value
res[field[0]] = [value, True]
return res

View File

@ -1,3 +1,4 @@
# -*- coding: utf8 -*-
"""
********************************************************************************
* CNIRevelator *
@ -23,7 +24,7 @@
* along with CNIRevelator. If not, see <https:*www.gnu.org/licenses/>. *
********************************************************************************
"""
import logger # logger.pu
try:
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
"""
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)
else:
args = [
@ -316,7 +317,7 @@ def main():
sys.stderr.write('Usage: python pytesseract.py [-l lang] input_file\n')
exit(2)
try:
print(image_to_string((Image.open(filename)), lang=lang))
logfile.printdbg(image_to_string((Image.open(filename)), lang=lang))
except IOError:
sys.stderr.write('ERROR: Could not open file "%s"\n' % filename)
exit(1)

View File

@ -1,3 +1,4 @@
# -*- coding: utf8 -*-
"""
********************************************************************************
* CNIRevelator *
@ -35,8 +36,10 @@ import zipfile
import hashlib
import subprocess
import psutil
import datetime
import critical # critical.py
import github # github.py
import ihm # ihm.py
import logger # logger.py
import globs # globs.py
@ -85,14 +88,38 @@ def exitProcess(arg):
process.terminate()
sys.exit(arg)
def updateChannel(choice):
def setUpdateChannel(choice):
"""
Sets the new update channel and forces new update at next launch
"""
if choice == "Beta":
with open(globs.CNIRUrlConfig, 'w') as (configFile):
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):
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):
"""
Returns the latest version of the software
@ -171,18 +198,18 @@ def tessInstall(PATH, credentials):
# 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)
if finalurl == None:
logfile.printerr('Unable to get the Tesseract url')
return False
tesseracturl = finalurl.replace("CNIRevelator.zip", "tesseract_4.zip")
tesseracturl = finalurl.replace("CNIRevelator.zip", "tesseract_5.zip")
# WE ASSUME THAT THE MAIN FILE IS CNIRevelator.zip AND THAT THE TESSERACT PACKAGE IS tesseract_4.zip
# WE ASSUME THAT THE MAIN FILE IS CNIRevelator.zip AND THAT THE TESSERACT PACKAGE IS tesseract_5.zip
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:
# CHECKSUM
@ -314,22 +341,12 @@ def umain():
# Global Handlers
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
if len(sys.argv) > 2 and str(sys.argv[1]) == "DELETE":
globs.CNIRNewVersion = True
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])):
try:
shutil.rmtree(str(sys.argv[2]))
@ -356,14 +373,51 @@ def umain():
# check we want open a file
elif len(sys.argv) > 1 and str(sys.argv[1]) != "DELETE":
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:
# EXECUTING THE UPDATE BATCH
success = batch(credentials)
except Exception as e:
critical.crashCNIR()
critical.crashCNIR(False)
launcherWindow.printmsg('ERROR : ' + str(e))
time.sleep(3)
launcherWindow.exit()
@ -372,20 +426,36 @@ def umain():
if success:
logfile.printdbg("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:
logfile.printerr("An error occured. No effective update !")
launcherWindow.printmsg(lang.all[globs.CNIRlang]['An error occured. No effective update !'])
time.sleep(2)
launcherWindow.exit()
return 0
if UPDATE_IS_MADE:
launcherWindow.exit()
return 0
except:
critical.crashCNIR()
critical.crashCNIR(False)
launcherWindow.exit()
sys.exit(2)
return 2
try:
@ -393,7 +463,7 @@ def umain():
# INSTALLING TESSERACT OCR
success = tessInstall(globs.CNIRFolder, credentials)
except Exception as e:
critical.crashCNIR()
critical.crashCNIR(False)
launcherWindow.printmsg('ERROR : ' + str(e))
time.sleep(3)
launcherWindow.exit()
@ -410,9 +480,8 @@ def umain():
return 0
except:
critical.crashCNIR()
critical.crashCNIR(False)
launcherWindow.exit()
sys.exit(2)
return 2
time.sleep(2)

43
src/version.res Normal file
View 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])])
]
)