.gear/rules | 2 + .../tags/3a7102dedd7b7cb24404bee27292ae7cd0d5fd20 | 6 +++ .gear/tags/list | 1 + .gear/upstream/remotes | 3 ++ rosa-crypto-tool.desktop | 4 +- rosa-crypto-tool.spec | 61 ++++++++++++++++++++++ setup.py | 7 +-- src/errors.py | 4 +- src/rename.py | 2 +- src/rosa_crypto_tool.py | 6 +-- src/rosa_crypto_tool_main.py | 60 +++++++++++---------- src/rosa_crypto_tool_ui.py | 18 +++---- 12 files changed, 125 insertions(+), 49 deletions(-) diff --git a/.gear/rules b/.gear/rules new file mode 100644 index 0000000..4fcfd99 --- /dev/null +++ b/.gear/rules @@ -0,0 +1,2 @@ +tar: @version@:. +diff: @version@:. . diff --git a/.gear/tags/3a7102dedd7b7cb24404bee27292ae7cd0d5fd20 b/.gear/tags/3a7102dedd7b7cb24404bee27292ae7cd0d5fd20 new file mode 100644 index 0000000..7eff8a6 --- /dev/null +++ b/.gear/tags/3a7102dedd7b7cb24404bee27292ae7cd0d5fd20 @@ -0,0 +1,6 @@ +object 91898b1deeb05a15b20b510c8f804e7e3841c00f +type commit +tag 1.0.0 +tagger Michl Voznesensky 1523272929 +0300 + +Release 1.0.0 diff --git a/.gear/tags/list b/.gear/tags/list new file mode 100644 index 0000000..784c935 --- /dev/null +++ b/.gear/tags/list @@ -0,0 +1 @@ +3a7102dedd7b7cb24404bee27292ae7cd0d5fd20 1.0.0 diff --git a/.gear/upstream/remotes b/.gear/upstream/remotes new file mode 100644 index 0000000..7d569f4 --- /dev/null +++ b/.gear/upstream/remotes @@ -0,0 +1,3 @@ +[remote "upstream"] + url = https://abf.io/uxteam/rosa-crypto-tool-devel.git + fetch = +refs/heads/*:refs/remotes/upstream/* diff --git a/rosa-crypto-tool.desktop b/rosa-crypto-tool.desktop index 23d3dc2..56a9fd1 100644 --- a/rosa-crypto-tool.desktop +++ b/rosa-crypto-tool.desktop @@ -1,9 +1,9 @@ [Desktop Entry] Categories=Utility;System; -Comment[ru]=Программа для работы с электронно цифровыми подписями +Comment[ru]=Программа для работы с электронными подписями Comment=Program for working with electronic digital signatures Exec=rosa-crypto-tool -GenericName[ru]=Работа с электронно цифровыми подписями +GenericName[ru]=Работа с электронными подписями GenericName=Working with electronic digital signatures Icon=rosa-crypto-tool MimeType= diff --git a/rosa-crypto-tool.spec b/rosa-crypto-tool.spec new file mode 100644 index 0000000..24c332f --- /dev/null +++ b/rosa-crypto-tool.spec @@ -0,0 +1,61 @@ +Name: rosa-crypto-tool +Version: 1.0.0 +Release: alt2 + +Summary: Program for working with electronic digital signatures +Group: Text tools +License: BSD +URL: https://abf.io/uxteam/rosa-crypto-tool-devel.git +BuildArch: noarch + +Source0: %name-%version.tar +Patch: %name-%version-%release.patch + +BuildRequires(pre): rpm-build-python3 +BuildRequires: gettext-tools + +%description +Program for working with electronic digital signatures. + +%prep +%setup -q +%patch -p1 +# Set all python shebang to python3 executable +sed -i 's|#!.* python$|#!%__python3|' \ + $(find ./ \( -name '*.py' -o -name '%name' \)) + +%build +%python3_build + +%install +%python3_install +%find_lang %name + +%files -f %name.lang +%_bindir/%name +%doc %_defaultdocdir/%name/help.pdf +%python3_sitelibdir/* +%_desktopdir/%name.desktop +%_iconsdir/hicolor/scalable/apps/%name.svg + + +%changelog +* Tue Nov 30 2021 Andrey Cherepanov 1.0.0-alt2 +- Finish adapt for Python3 and PyQt5. + +* Mon Nov 29 2021 Andrey Cherepanov 1.0.0-alt1 +- New version. + +* Mon Nov 11 2019 Andrey Bychkov 0.1.5-alt2 +- python2 -> python3 + +* Wed Nov 02 2016 Andrey Cherepanov 0.1.5-alt1 +- New version + +* Tue Oct 04 2016 Andrey Cherepanov 0.1.0-alt0.1.beta +- New beta version +- Added executable and desktop files + +* Sun Aug 14 2016 Andrey Cherepanov 0.0.8-alt1 +- Initial build in Sisyphus + diff --git a/setup.py b/setup.py index 703c75d..76e5224 100644 --- a/setup.py +++ b/setup.py @@ -2,17 +2,14 @@ import os import sys +import sysconfig import subprocess from distutils.core import setup major = sys.version_info[0] minor = sys.version_info[1] -if major == 2: - if minor == 7: - PURE_PYTHON = "lib/python2.7/site-packages/" - elif minor == 6: - PURE_PYTHON = "lib/python2.6/site-packages/" +PURE_PYTHON = sysconfig.get_paths()["purelib"].replace('/usr/','') + '/' def get_data(): """ Return all needed data files """ diff --git a/src/errors.py b/src/errors.py index 95a8a11..2f5744e 100644 --- a/src/errors.py +++ b/src/errors.py @@ -42,7 +42,7 @@ import re import gettext -gettext.install('rosa-crypto-tool', unicode=True) +gettext.install('rosa-crypto-tool') # Dictionary all available CryptoPro errors errors = {"0x20000064": _("Little memory"),#Мало памяти @@ -113,5 +113,5 @@ def searchError(output_mess): if __name__ == '__main__': - print "You run the part program rosa crypto tool, please launch the main file" + print("You run the part program rosa crypto tool, please launch the main file") diff --git a/src/rename.py b/src/rename.py index 640fde7..5302df3 100644 --- a/src/rename.py +++ b/src/rename.py @@ -40,7 +40,7 @@ # ################################################################################ -from PyQt4.QtCore import QString, QLatin1String +from PyQt5.QtCore import QString, QLatin1String def translit(name_file): new_name = QString(name_file) #if not create new_name, original name_fale replaced on new diff --git a/src/rosa_crypto_tool.py b/src/rosa_crypto_tool.py index 2c924ae..4277c1e 100755 --- a/src/rosa_crypto_tool.py +++ b/src/rosa_crypto_tool.py @@ -43,13 +43,13 @@ #TODO __str__().encode('utf-8') maybe should be make this for path_name in openFile -import rosa_crypto_tool_ui -import rosa_crypto_tool_main +from rosa_crypto_tool import rosa_crypto_tool_ui +from rosa_crypto_tool import rosa_crypto_tool_main import gettext import sys def main(): - gettext.install('rosa-crypto-tool', unicode=True) + gettext.install('rosa-crypto-tool') app = rosa_crypto_tool_ui.QApplication(sys.argv) app_ui = rosa_crypto_tool_ui.MainWindow() diff --git a/src/rosa_crypto_tool_main.py b/src/rosa_crypto_tool_main.py index 33bb488..b2b8bf6 100644 --- a/src/rosa_crypto_tool_main.py +++ b/src/rosa_crypto_tool_main.py @@ -43,17 +43,18 @@ import time import os.path import subprocess -import rename -#rename nedeed for vefify sign +from transliterate import translit +#translit nedeed for vefify sign #files with the name Cyrillic characters are not available to take certificate import re import datetime -from errors import * -from PyQt4.QtCore import QUrl, Qt -from PyQt4.QtGui import QDesktopServices, QMessageBox, QCheckBox +from rosa_crypto_tool.errors import * +from PyQt5.QtCore import QUrl, Qt +from PyQt5.QtGui import QDesktopServices +from PyQt5.QtWidgets import QMessageBox, QCheckBox from pyudev import Context, Monitor -from pyudev.pyqt4 import MonitorObserver -from ConfigParser import ConfigParser +from pyudev.pyqt5 import MonitorObserver +from configparser import ConfigParser UTILS_CRYPT = ('csptest', 'certmgr', 'cryptcp') CONFIG_FILE = os.path.expanduser("~")+"/.config/rosa-crypto-tool.cf" @@ -137,12 +138,12 @@ class RosaApp(object): else: #check CryptoPro license cp_lic_out, cp_lic_err = subprocess.Popen("%scpconfig -license -view" %self.dir_crypt.replace("bin", "sbin"), stdout=subprocess.PIPE, stderr=subprocess.PIPE , shell=True).communicate() - if "3" in cp_lic_err: + if "3" in cp_lic_err.decode(): self.valid_lic = False map(lambda field: field.setEnabled(False), self._ui.list_off_lic) messages.append("license") else: - self.cp_ver = int(re.findall("\d", cp_lic_out)[0]) + self.cp_ver = int(re.findall("\d", cp_lic_out.decode())[0]) #chek token if self.__listToken(): @@ -162,7 +163,7 @@ class RosaApp(object): # Can use subprocess.check_output, but this function work on Python since 2.7 # To work on python 2.6 uses the old style info_cert = subprocess.Popen("%scsptest -keyset -enum_cont -verifyc -fq -uniq" %self.dir_crypt, stdout=subprocess.PIPE, shell=True).communicate()[0] - self.name_cert = self.__parseConsole(info_cert, "\\\\") + self.name_cert = self.__parseConsole(info_cert.decode(), "\\\\") if not self.name_cert: map(lambda field: field.setEnabled(False), self._ui.list_off_container) #disable components linked to signature messages.append("cntnr_missing") @@ -181,9 +182,9 @@ class RosaApp(object): #if cert_all empty then triggered exception cert_all, cert_err = subprocess.Popen("%scertmgr -list" %self.dir_crypt, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True).communicate() self.dict_subject = dict() #empty dictionary for storage the names and hashes certificates - if "Empty certificate list\n" not in cert_err: - subject_all = self.__parseConsole(cert_all, "Subject") - sha_all = self.__parseConsole(cert_all, "SHA1") + if "Empty certificate list\n" not in cert_err.decode(): + subject_all = self.__parseConsole(cert_all.decode(), "Subject") + sha_all = self.__parseConsole(cert_all.decode(), "SHA1") self.dict_subject = dict(zip(subject_all, sha_all)) self._ui.encrypt.list_avail_cert.addItems(sorted(self.dict_subject)) self.__setIndex(self._ui.encrypt, self.user_preference.get("preference", "last_encrypt")) @@ -207,6 +208,7 @@ class RosaApp(object): elif where_cert == "store": status_cert = subprocess.Popen("%scertmgr -list -thumbprint '%s'" %(self.dir_crypt, self.dict_subject[unicode(mode.list_avail_cert.currentText())]), stdout=subprocess.PIPE, shell=True).communicate()[0] + status_cert = status_cert.decode() row_valid_cert = self.__parseConsole(status_cert, "Not valid after")[0] #need to check valid certificate self.date_valid_cert = datetime.datetime.strptime(row_valid_cert, "%d/%m/%Y %H:%M:%S UTC") self.sha = self.__parseConsole(status_cert, "SHA1")[0] @@ -231,13 +233,13 @@ class RosaApp(object): if self._ui.sign.file_edit.text(): self.infoCert("container", self._ui.sign) - new_name = rename.translit(self._ui.sign.file_name) + ".sig" + new_name = translit(self._ui.sign.file_name, reversed=True) + ".sig" #console_cmd = '%scryptcp -dir "%s" -sign -thumbprint "%s" "%s" -der "%s" "%s"' %(self.dir_crypt, self._ui.sign.currently_dir, self.sha, NOASK, self._ui.sign.path_name, self._ui.sign.currently_dir + new_name) console_cmd = [self.dir_crypt+'cryptcp', '-dir', self._ui.sign.currently_dir, '-sign', '-thumbprint', self.sha, NOASK, '-der', self._ui.sign.path_name.__str__().encode('utf-8'), os.path.join(self._ui.sign.currently_dir, new_name.__str__())] raw_result_sign = subprocess.Popen(console_cmd, stdout=subprocess.PIPE).communicate()[0] - result_sign = searchError(raw_result_sign) #return tuple (code error, message error) + result_sign = searchError(raw_result_sign.decode()) #return tuple (code error, message error) # Signature successful if result_sign[0] == "0": @@ -248,12 +250,12 @@ class RosaApp(object): # Dont't change the single quotation marks in the name of the container, else slashes must be doubled raw_result_inst_cert = subprocess.Popen("%scertmgr -inst -cont '%s' -store uMy" %(self.dir_crypt, self._ui.sign.list_avail_cert.currentText()), stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) out_result_inst_cert, err_result_inst_cert = raw_result_inst_cert.communicate() - if err_result_inst_cert: - out_status_sig = _('\nError: ') + err_result_inst_cert + if err_result_inst_cert.decode(): + out_status_sig = _('\nError: ') + err_result_inst_cert.decode() self.__outMessage(out_status_sig, self._ui.sign.icon_atten, self._ui.sign, False) else: - subject_new = self.__parseConsole(out_result_inst_cert, "Subject") - sha_new = self.__parseConsole(out_result_inst_cert, "SHA1")[0] + subject_new = self.__parseConsole(out_result_inst_cert.decode(), "Subject") + sha_new = self.__parseConsole(out_result_inst_cert.decode(), "SHA1")[0] self._ui.encrypt.list_avail_cert.insertItems(0, subject_new) self.dict_subject[subject_new[0]] = sha_new self._ui.encrypt.ability_visible = True @@ -284,7 +286,7 @@ class RosaApp(object): console_cmd = [self.dir_crypt+'cryptcp', '-verify', self._ui.verify_sign.path_name.__str__().encode('utf-8'), new_name, '-f', self._ui.verify_sign.file_name, NOASK] raw_result_verify = subprocess.Popen(console_cmd, stdout=subprocess.PIPE).communicate()[0] - result_verify = searchError(raw_result_verify) + result_verify = searchError(raw_result_verify.decode()) if result_verify[0] == "0": out_status_verify_sign = _('The signature file "%s" is checked.\nThe source file is separated from the signature and saved with the name "%s"') %(self._ui.verify_sign.file_name, new_name) @@ -295,7 +297,7 @@ class RosaApp(object): console_cmd = [self.dir_crypt+'cryptcp', '-verify', self._ui.verify_sign.path_name.__str__().encode('utf-8'), '-f', self._ui.verify_sign.file_name, NOASK] raw_result_verify = subprocess.Popen(console_cmd, stdout=subprocess.PIPE).communicate()[0] - result_verify = searchError(raw_result_verify) + result_verify = searchError(raw_result_verify.decode()) if result_verify[0] == "0": out_status_verify_sign = _('The signature file "%s" is checked.') %self._ui.verify_sign.file_name @@ -314,7 +316,8 @@ class RosaApp(object): if self._ui.verify_sign.verify_install.checkState(): #result_inst_cert = subprocess.Popen("%scertmgr -inst -file '%s' -store uMy" %(self.dir_crypt, self._ui.verify_sign.file_name), stdout=subprocess.PIPE, shell=True).communicate()[0] result_inst_cert = subprocess.Popen([self.dir_crypt+'certmgr', '-inst', '-file', self._ui.verify_sign.file_name.__str__().encode('utf-8'), '-store', 'uMy'], stdout=subprocess.PIPE).communicate()[0] - print result_inst_cert + result_inst_cert = result_inst_cert.decode() + print(result_inst_cert) out_status_verify_sign += _("\nThe certificate is installed.") subject_inst_cert = self.__parseConsole(result_inst_cert, "Subject")[0] #check installed already this certificate or not @@ -338,13 +341,13 @@ class RosaApp(object): self.infoCert("store", self._ui.encrypt) - new_name = rename.translit(self._ui.encrypt.file_name) + ".enc" + new_name = translit(self._ui.encrypt.file_name, reversed=True) + ".enc" #console_cmd = '%scryptcp -encr -thumbprint "%s" "%s" -der "%s" "%s"' %(self.dir_crypt, self.sha, NOASK, self._ui.encrypt.path_name, self._ui.encrypt.currently_dir + new_name) console_cmd = [self.dir_crypt+'cryptcp', '-encr', '-thumbprint', self.sha, NOASK, '-der', self._ui.encrypt.path_name.__str__().encode('utf-8'), os.path.join(self._ui.encrypt.currently_dir, new_name.__str__())] raw_result_encrypt = subprocess.Popen(console_cmd, stdout=subprocess.PIPE).communicate()[0] - result_encrypt = searchError(raw_result_encrypt) + result_encrypt = searchError(raw_result_encrypt.decode()) if result_encrypt[0] == "0": out_status_encrypt_file = _('The file "%s" is encrypted in file "%s"') %(self._ui.encrypt.file_name, new_name) @@ -371,7 +374,7 @@ class RosaApp(object): console_cmd = [self.dir_crypt+'cryptcp', '-decr', '-thumbprint', self.sha, NOASK, '-start', self._ui.decrypt.file_name.__str__().encode('utf-8'), new_name] raw_result_decrypt = subprocess.Popen(console_cmd, stdout=subprocess.PIPE).communicate()[0] - result_decrypt = searchError(raw_result_decrypt) + result_decrypt = searchError(raw_result_decrypt.decode()) if result_decrypt[0] == "0": out_status_decrypt = _('The file "%s" is decrypted in file "%s"') %(self._ui.decrypt.file_name, new_name) @@ -379,7 +382,10 @@ class RosaApp(object): elif result_decrypt[0] == "0x2000012d" or result_decrypt[0] == "0x20000136": # Dont't change the single quotation marks in the name of the container, else slashes must be doubled raw_result_inst_cert = subprocess.Popen("%scertmgr -inst -cont '%s' -store uMy" %(self.dir_crypt, self._ui.decrypt.list_avail_cert.currentText()), stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) + raw_result_inst_cert = raw_result_inst_cert.decode() out_result_inst_cert, err_result_inst_cert = raw_result_inst_cert.communicate() + out_result_inst_cert = out_result_inst_cert.decode() + err_result_inst_cert = err_result_inst_cert.decode() if err_result_inst_cert: out_status_decrypt = _('\nError: ') + err_result_inst_cert self.__outMessage(out_status_decrypt, self._ui.decrypt.icon_atten, self._ui.decrypt, False) @@ -461,7 +467,7 @@ class RosaApp(object): time.sleep(1) #need a delay, otherwise the CryptoPro may not have time to see the presence of a token in the computer info_cert = subprocess.Popen("%scsptest -keyset -enum_cont -verifyc -fq -uniq" %self.dir_crypt, stdout=subprocess.PIPE, shell=True).communicate()[0] - self.name_cert = self.__parseConsole(info_cert, "\\\\") + self.name_cert = self.__parseConsole(info_cert.decode(), "\\\\") if not self.name_cert: map(lambda field: field.setEnabled(False), self._ui.list_off_container) #disable components linked to signature messages.append("cntnr_missing") @@ -636,7 +642,7 @@ class RosaApp(object): if __name__ == '__main__': - print "You run the part program rosa crypto tool, please launch the main file" + print("You run the part program rosa crypto tool, please launch the main file") #for debug subprocess #try: diff --git a/src/rosa_crypto_tool_ui.py b/src/rosa_crypto_tool_ui.py index f2089c8..da2a78a 100644 --- a/src/rosa_crypto_tool_ui.py +++ b/src/rosa_crypto_tool_ui.py @@ -42,18 +42,18 @@ import os import subprocess -from PyQt4.QtCore import * +from PyQt5.QtCore import * import magic #this binding to libmagic almost always include in program "file" #NOT CONFUSE with another module python-magic sources which placed on GitHub #homepage this module http://www.darwinsys.com/file/ -from PyQt4.QtGui import QApplication, QMainWindow, QWidget, QCursor, \ +from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, \ QGridLayout, QLayout, QPushButton, QLabel, QLineEdit, \ QTextEdit, QFileDialog, QAction, QActionGroup, \ QSizePolicy, QHBoxLayout, QVBoxLayout, QFrame, \ QComboBox, QCheckBox, QToolButton, QMenu, \ - QIcon, QPixmap, QKeySequence, QFont, QFontMetrics, \ - QProgressBar, QDesktopServices + QProgressBar +from PyQt5.QtGui import QCursor, QIcon, QPixmap, QKeySequence, QFont, QFontMetrics, QDesktopServices #const size window app MAX_WIDTH = 1024 @@ -309,7 +309,7 @@ class ThumbShow(QFrame): map(lambda item: item.setVisible(False), self.wait_items) self.no_thumb.setVisible(False) self.back_image = QPixmap(OUTPUT_PNG) - self.setStyleSheet(QString.fromUtf8("background-image: url(%s); background-repeat: no-repeat" %OUTPUT_PNG)) + self.setStyleSheet("background-image: url(%s); background-repeat: no-repeat" %OUTPUT_PNG) elif image_ready is None: self.setStyleSheet('') self.back_image = QPixmap(300, 400) #empty QPixmap @@ -338,7 +338,7 @@ class ThumbButton(QPushButton): self.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Fixed) self.setLayoutDirection(Qt.RightToLeft) self.setFlat(True) - self.setStyleSheet(QString.fromUtf8("border: 0px")) + self.setStyleSheet("border: 0px") #set Icon self.setIcon(self.normal_icon) self.setIconSize(QSize(16, 16)) @@ -660,19 +660,19 @@ class AboutWidget(QWidget): if __name__ == '__main__': - print "You run the part program rosa crypto tool, please launch the main file" + print("You run the part program rosa crypto tool, please launch the main file") #for debugger UI # import sys import gettext - from PyQt4.QtGui import QApplication + from PyQt5.QtGui import QApplication PREFIX16 ='../icon/16x16/' #directory icons PREFIX32 ='../icon/32x32/' PREFIX48 ='../icon/48x48/' - gettext.install('rosa-crypto-tool', unicode=True) + gettext.install('rosa-crypto-tool') app = QApplication(sys.argv) app_ui = MainWindow() sys.exit(app.exec_())