about summary refs log tree commit diff
path: root/kindlecomicconverter/cbxarchive.py
diff options
context:
space:
mode:
Diffstat (limited to 'kindlecomicconverter/cbxarchive.py')
-rw-r--r--kindlecomicconverter/cbxarchive.py105
1 files changed, 105 insertions, 0 deletions
diff --git a/kindlecomicconverter/cbxarchive.py b/kindlecomicconverter/cbxarchive.py
new file mode 100644
index 0000000..726432b
--- /dev/null
+++ b/kindlecomicconverter/cbxarchive.py
@@ -0,0 +1,105 @@
+# Copyright (c) 2012-2014 Ciro Mattia Gonano <[email protected]>
+# Copyright (c) 2013-2017 Pawel Jastrzebski <[email protected]>
+#
+# Permission to use, copy, modify, and/or distribute this software for
+# any purpose with or without fee is hereby granted, provided that the
+# above copyright notice and this permission notice appear in all
+# copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+# AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+# DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
+# OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+#
+
+import sys
+import os
+from zipfile import is_zipfile, ZipFile
+from subprocess import STDOUT, PIPE
+from psutil import Popen
+from shutil import move, copy
+try:
+    from scandir import walk
+except ImportError:
+    walk = os.walk
+from . import rarfile
+from .shared import check7ZFile as is_7zfile, saferReplace, saferRemove
+
+
+class CBxArchive:
+    def __init__(self, origFileName):
+        self.origFileName = origFileName
+        if is_zipfile(origFileName):
+            self.compressor = 'zip'
+        elif rarfile.is_rarfile(origFileName):
+            self.compressor = 'rar'
+        elif is_7zfile(origFileName):
+            self.compressor = '7z'
+        else:
+            self.compressor = None
+
+    def isCbxFile(self):
+        return self.compressor is not None
+
+    def extractCBZ(self, targetdir):
+        cbzFile = ZipFile(self.origFileName)
+        filelist = []
+        for f in cbzFile.namelist():
+            if f.startswith('__MACOSX') or f.endswith('.DS_Store') or f.endswith('humbs.db'):
+                pass    # skip MacOS special files
+            elif f.endswith('/'):
+                try:
+                    os.makedirs(os.path.join(targetdir, f))
+                except Exception:
+                    pass  # the dir exists so we are going to extract the images only.
+            else:
+                filelist.append(f)
+        cbzFile.extractall(targetdir, filelist)
+
+    def extractCBR(self, targetdir):
+        cbrFile = rarfile.RarFile(self.origFileName)
+        cbrFile.extractall(targetdir)
+        for root, dirnames, filenames in walk(targetdir):
+            for filename in filenames:
+                if filename.startswith('__MACOSX') or filename.endswith('.DS_Store') or filename.endswith('humbs.db'):
+                    saferRemove(os.path.join(root, filename))
+
+    def extractCB7(self, targetdir):
+        # Workaround for some wide UTF-8 + Popen abnormalities
+        if sys.platform.startswith('darwin'):
+            copy(self.origFileName, os.path.join(os.path.dirname(self.origFileName), 'TMP_KCC_TMP'))
+            self.origFileName = os.path.join(os.path.dirname(self.origFileName), 'TMP_KCC_TMP')
+        output = Popen('7za x "' + self.origFileName + '" -xr!__MACOSX -xr!.DS_Store -xr!thumbs.db -xr!Thumbs.db -o"' +
+                       targetdir + '"', stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True)
+        extracted = False
+        for line in output.stdout:
+            if b"Everything is Ok" in line:
+                extracted = True
+        if sys.platform.startswith('darwin'):
+            saferRemove(self.origFileName)
+        if not extracted:
+            raise OSError
+
+    def extract(self, targetdir):
+        if self.compressor == 'rar':
+            self.extractCBR(targetdir)
+        elif self.compressor == 'zip':
+            self.extractCBZ(targetdir)
+        elif self.compressor == '7z':
+            self.extractCB7(targetdir)
+        adir = os.listdir(targetdir)
+        if 'ComicInfo.xml' in adir:
+            adir.remove('ComicInfo.xml')
+        if len(adir) == 1 and os.path.isdir(os.path.join(targetdir, adir[0])):
+            for f in os.listdir(os.path.join(targetdir, adir[0])):
+                # If directory names contain UTF-8 chars shutil.move can't clean up the mess alone
+                if os.path.isdir(os.path.join(targetdir, f)):
+                    saferReplace(os.path.join(targetdir, adir[0], f), os.path.join(targetdir, adir[0], f + '-A'))
+                    f += '-A'
+                move(os.path.join(targetdir, adir[0], f), targetdir)
+            os.rmdir(os.path.join(targetdir, adir[0]))
+        return targetdir