1
0
mirror of https://github.com/ciromattia/kcc synced 2025-12-13 01:36:27 +00:00

fix p7zip-rar error and files with ' or " by using arg lists instead of strings (#633)

* Revert "Revert "fix files with ' or " by using arg lists instead of strings (#581)" (#628)"

This reverts commit b528dab711.

* handle FileNotFoundError

* modify unar handling

* remove unneeded utf-8 encoding

* dont uft-8 encode 7z

* remove utf-8 encoding from 7z calls

* don't extract stderr

* add extraction error

* edit error message

* remove debug

* remove kindlegen location from GUI

* remove comment
This commit is contained in:
Alex Xu
2023-12-21 12:52:35 -08:00
committed by GitHub
parent 6cdd9d5909
commit 3988f2012f
3 changed files with 39 additions and 54 deletions

View File

@@ -28,7 +28,7 @@ import requests
# noinspection PyUnresolvedReferences # noinspection PyUnresolvedReferences
from PyQt5 import QtGui, QtCore, QtWidgets, QtNetwork from PyQt5 import QtGui, QtCore, QtWidgets, QtNetwork
from xml.sax.saxutils import escape from xml.sax.saxutils import escape
from psutil import Popen, Process from psutil import Process
from copy import copy from copy import copy
from distutils.version import StrictVersion from distutils.version import StrictVersion
from raven import Client from raven import Client
@@ -835,26 +835,21 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
os.chmod('/usr/local/bin/kindlegen', 0o755) os.chmod('/usr/local/bin/kindlegen', 0o755)
except Exception: except Exception:
pass pass
kindleGenExitCode = Popen('kindlegen -locale en', stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True) try:
kindleGenExitCode.communicate() versionCheck = subprocess.run(['kindlegen', '-locale', 'en'], stdout=PIPE, stderr=STDOUT, encoding='UTF-8')
if kindleGenExitCode.returncode == 0:
self.kindleGen = True self.kindleGen = True
versionCheck = Popen('kindlegen -locale en', stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True) for line in versionCheck.stdout.splitlines():
for line in versionCheck.stdout:
line = line.decode("utf-8")
if 'Amazon kindlegen' in line: if 'Amazon kindlegen' in line:
versionCheck = line.split('V')[1].split(' ')[0] versionCheck = line.split('V')[1].split(' ')[0]
if StrictVersion(versionCheck) < StrictVersion('2.9'): if StrictVersion(versionCheck) < StrictVersion('2.9'):
self.addMessage('Your <a href="https://www.amazon.com/b?node=23496309011">KindleGen</a>' self.addMessage('Your <a href="https://www.amazon.com/b?node=23496309011">KindleGen</a>'
' is outdated! MOBI conversion might fail.', 'warning') ' is outdated! MOBI conversion might fail.', 'warning')
break break
else: except FileNotFoundError:
self.kindleGen = False self.kindleGen = False
if startup: if startup:
self.display_kindlegen_missing() self.display_kindlegen_missing()
def __init__(self, kccapp, kccwindow): def __init__(self, kccapp, kccwindow):
global APP, MW, GUI global APP, MW, GUI
APP = kccapp APP = kccapp
@@ -1029,11 +1024,10 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
self.addMessage('Since you are a new user of <b>KCC</b> please see few ' self.addMessage('Since you are a new user of <b>KCC</b> please see few '
'<a href="https://github.com/ciromattia/kcc/wiki/Important-tips">important tips</a>.', '<a href="https://github.com/ciromattia/kcc/wiki/Important-tips">important tips</a>.',
'info') 'info')
process = Popen('7z', stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True) try:
process.communicate() subprocess.run(['7z'], stdout=PIPE, stderr=STDOUT)
if process.returncode == 0 or process.returncode == 7:
self.sevenzip = True self.sevenzip = True
else: except FileNotFoundError:
self.sevenzip = False self.sevenzip = False
self.addMessage('<a href="https://github.com/ciromattia/kcc#7-zip">Install 7z (link)</a>' self.addMessage('<a href="https://github.com/ciromattia/kcc#7-zip">Install 7z (link)</a>'
' to enable CBZ/CBR/ZIP/etc processing.', 'warning') ' to enable CBZ/CBR/ZIP/etc processing.', 'warning')

View File

@@ -38,7 +38,7 @@ from natsort import os_sorted
from slugify import slugify as slugify_ext from slugify import slugify as slugify_ext
from PIL import Image from PIL import Image
from subprocess import STDOUT, PIPE from subprocess import STDOUT, PIPE
from psutil import Popen, virtual_memory, disk_usage from psutil import virtual_memory, disk_usage
from html import escape as hescape from html import escape as hescape
try: try:
from PyQt5 import QtCore from PyQt5 import QtCore
@@ -1103,15 +1103,15 @@ def checkTools(source):
source = source.upper() source = source.upper()
if source.endswith('.CB7') or source.endswith('.7Z') or source.endswith('.RAR') or source.endswith('.CBR') or \ if source.endswith('.CB7') or source.endswith('.7Z') or source.endswith('.RAR') or source.endswith('.CBR') or \
source.endswith('.ZIP') or source.endswith('.CBZ'): source.endswith('.ZIP') or source.endswith('.CBZ'):
process = Popen('7z', stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True) try:
process.communicate() subprocess.run(['7z'], stdout=PIPE, stderr=STDOUT)
if process.returncode != 0 and process.returncode != 7: except FileNotFoundError:
print('ERROR: 7z is missing!') print('ERROR: 7z is missing!')
sys.exit(1) sys.exit(1)
if options.format == 'MOBI': if options.format == 'MOBI':
kindleGenExitCode = Popen('kindlegen -locale en', stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True) try:
kindleGenExitCode.communicate() subprocess.run(['kindlegen', '-locale', 'en'], stdout=PIPE, stderr=STDOUT)
if kindleGenExitCode.returncode != 0: except FileNotFoundError:
print('ERROR: KindleGen is missing!') print('ERROR: KindleGen is missing!')
sys.exit(1) sys.exit(1)
@@ -1267,10 +1267,9 @@ def makeMOBIWorker(item):
kindlegenError = '' kindlegenError = ''
try: try:
if os.path.getsize(item) < 629145600: if os.path.getsize(item) < 629145600:
output = Popen('kindlegen -dont_append_source -locale en "' + item + '"', output = subprocess.run(['kindlegen', '-dont_append_source', '-locale', 'en', item],
stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True) stdout=PIPE, stderr=STDOUT, encoding='UTF-8')
for line in output.stdout: for line in output.stdout.splitlines():
line = line.decode('utf-8')
# ERROR: Generic error # ERROR: Generic error
if "Error(" in line: if "Error(" in line:
kindlegenErrorCode = 1 kindlegenErrorCode = 1
@@ -1281,7 +1280,6 @@ def makeMOBIWorker(item):
if kindlegenErrorCode > 0: if kindlegenErrorCode > 0:
break break
if ":I1036: Mobi file built successfully" in line: if ":I1036: Mobi file built successfully" in line:
output.communicate()
break break
else: else:
# ERROR: EPUB too big # ERROR: EPUB too big

View File

@@ -22,12 +22,13 @@ import os
import platform import platform
import subprocess import subprocess
import distro import distro
from psutil import Popen
from shutil import move from shutil import move
from subprocess import STDOUT, PIPE from subprocess import STDOUT, PIPE
from xml.dom.minidom import parseString from xml.dom.minidom import parseString
from xml.parsers.expat import ExpatError from xml.parsers.expat import ExpatError
EXTRACTION_ERROR = 'Failed to extract archive. Try extracting file outside of KCC.'
class ComicArchive: class ComicArchive:
def __init__(self, filepath): def __init__(self, filepath):
@@ -35,41 +36,35 @@ class ComicArchive:
self.type = None self.type = None
if not os.path.isfile(self.filepath): if not os.path.isfile(self.filepath):
raise OSError('File not found.') raise OSError('File not found.')
process = Popen('7z l -y -p1 "' + self.filepath + '"', stderr=STDOUT, stdout=PIPE, stdin=PIPE, shell=True) process = subprocess.run(['7z', 'l', '-y', '-p1', self.filepath], stderr=STDOUT, stdout=PIPE)
for line in process.stdout: for line in process.stdout.splitlines():
if b'Type =' in line: if b'Type =' in line:
self.type = line.rstrip().decode().split(' = ')[1].upper() self.type = line.rstrip().decode().split(' = ')[1].upper()
break break
process.communicate()
if process.returncode != 0 and distro.id() == 'fedora': if process.returncode != 0 and distro.id() == 'fedora':
process = Popen('unrar l -y -p1 "' + self.filepath + '"', stderr=STDOUT, stdout=PIPE, stdin=PIPE, shell=True) process = subprocess.run(['unrar', 'l', '-y', '-p1', self.filepath], stderr=STDOUT, stdout=PIPE)
for line in process.stdout: for line in process.stdout.splitlines():
if b'Details: ' in line: if b'Details: ' in line:
self.type = line.rstrip().decode().split(' ')[1].upper() self.type = line.rstrip().decode().split(' ')[1].upper()
break break
process.communicate()
if process.returncode != 0: if process.returncode != 0:
raise OSError(process.stdout.strip()) raise OSError(EXTRACTION_ERROR)
def extract(self, targetdir): def extract(self, targetdir):
if not os.path.isdir(targetdir): if not os.path.isdir(targetdir):
raise OSError('Target directory doesn\'t exist.') raise OSError('Target directory doesn\'t exist.')
process = Popen('7z x -y -xr!__MACOSX -xr!.DS_Store -xr!thumbs.db -xr!Thumbs.db -o"' + targetdir + '" "' + process = subprocess.run(['7z', 'x', '-y', '-xr!__MACOSX', '-xr!.DS_Store', '-xr!thumbs.db', '-xr!Thumbs.db', '-o' + targetdir, self.filepath],
self.filepath + '"', stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True) stdout=PIPE, stderr=STDOUT)
process.communicate()
if process.returncode != 0 and distro.id() == 'fedora': if process.returncode != 0 and distro.id() == 'fedora':
process = Popen('unrar x -y -x__MACOSX -x.DS_Store -xthumbs.db -xThumbs.db "' + self.filepath + '" "' + process = subprocess.run(['unrar', 'x', '-y', '-x__MACOSX', '-x.DS_Store', '-xthumbs.db', '-xThumbs.db', self.filepath, targetdir]
targetdir + '"', stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True) , stdout=PIPE, stderr=STDOUT)
process.communicate()
if process.returncode != 0: if process.returncode != 0:
raise OSError('Failed to extract archive.') raise OSError(EXTRACTION_ERROR)
elif process.returncode != 0 and platform.system() == 'Darwin': elif process.returncode != 0 and platform.system() == 'Darwin':
process = subprocess.run(f"unar '{self.filepath}' -f -o '{targetdir}'", process = subprocess.run(['unar', self.filepath, '-f', '-o', targetdir],
stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True) stdout=PIPE, stderr=STDOUT)
if process.returncode != 0:
raise Exception(process.stdout.decode("utf-8"))
elif process.returncode != 0: elif process.returncode != 0:
raise OSError('Failed to extract archive. Check if p7zip-rar is installed.') raise OSError(EXTRACTION_ERROR)
tdir = os.listdir(targetdir) tdir = os.listdir(targetdir)
if 'ComicInfo.xml' in tdir: if 'ComicInfo.xml' in tdir:
tdir.remove('ComicInfo.xml') tdir.remove('ComicInfo.xml')
@@ -78,19 +73,17 @@ class ComicArchive:
def addFile(self, sourcefile): def addFile(self, sourcefile):
if self.type in ['RAR', 'RAR5']: if self.type in ['RAR', 'RAR5']:
raise NotImplementedError raise NotImplementedError
process = Popen('7z a -y "' + self.filepath + '" "' + sourcefile + '"', process = subprocess.run(['7z', 'a', '-y', self.filepath, sourcefile],
stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True) stdout=PIPE, stderr=STDOUT)
process.communicate()
if process.returncode != 0: if process.returncode != 0:
raise OSError('Failed to add the file.') raise OSError('Failed to add the file.')
def extractMetadata(self): def extractMetadata(self):
process = Popen('7z x -y -so "' + self.filepath + '" ComicInfo.xml', process = subprocess.run(['7z', 'x', '-y', '-so', self.filepath, 'ComicInfo.xml'],
stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True) stdout=PIPE, stderr=STDOUT)
xml = process.communicate()
if process.returncode != 0: if process.returncode != 0:
raise OSError('Failed to extract archive.') raise OSError(EXTRACTION_ERROR)
try: try:
return parseString(xml[0]) return parseString(process.stdout)
except ExpatError: except ExpatError:
return None return None