예제 #1
0
 def iter_contents(self):
     with process.popen(_mupdf['mutool'] +
                        ['show', '--', self.archive, 'pages'],
                        text=True) as proc:
         for line in proc.stdout:
             if line.startswith('page '):
                 yield line.split()[1] + '.png'
예제 #2
0
    def execute(self, window):
        """ Spawns a new process with the given executable
        and arguments. """
        if (self.is_disabled_for_archives() and
            window.filehandler.archive_type is not None):
            window.osd.show(_("'%s' is disabled for archives.") % self.get_label())
            return

        current_dir = os.getcwd()
        try:
            if self.is_valid_workdir(window):
                workdir = self.parse(window, text=self.get_cwd())[0]
                os.chdir(workdir)

            # Redirect process output to null here?
            # FIXME: Close process when finished to avoid zombie process
            args = self.parse(window)
            if sys.platform == 'win32':
                proc = process.Win32Popen(args)
            else:
                proc = process.popen(args, stdout=process.NULL)
            del proc

        except Exception, e:
            text = _("Could not run command %(cmdlabel)s: %(exception)s") % \
                {'cmdlabel': self.get_label(), 'exception': unicode(e)}
            window.osd.show(text)
예제 #3
0
    def execute(self, window):
        """ Spawns a new process with the given executable
        and arguments. """
        if (self.is_disabled_for_archives()
                and window.filehandler.archive_type is not None):
            window.osd.show(
                _("'%s' is disabled for archives.") % self.get_label())
            return

        current_dir = os.getcwd()
        try:
            if self.is_valid_workdir(window):
                workdir = self.parse(window, text=self.get_cwd())[0]
                os.chdir(workdir)

            # Redirect process output to null here?
            args = self.parse(window)
            with process.popen(args, stdout=process.NULL) as proc:
                pass

        except Exception as e:
            text = _("Could not run command %(cmdlabel)s: %(exception)s") % \
                {'cmdlabel': self.get_label(), 'exception': str(e)}
            window.osd.show(text)
        finally:
            os.chdir(current_dir)
예제 #4
0
 def extract(self, filename, destination_dir):
     self._create_directory(destination_dir)
     destination_path = os.path.join(destination_dir, filename)
     page_num = int(filename[0:-4])
     # Try to find optimal DPI.
     cmd = _mudraw_exec + _mudraw_trace_args + ["--", self.archive, str(page_num)]
     log.debug("finding optimal DPI for %s: %s", filename, " ".join(cmd))
     proc = process.popen(cmd)
     try:
         max_size = 0
         max_dpi = PDF_RENDER_DPI_DEF
         for line in proc.stdout:
             match = self._fill_image_regex.match(line)
             if not match:
                 continue
             matrix = [float(f) for f in match.group("matrix").split()]
             for size, coeff1, coeff2 in (
                 (int(match.group("width")), matrix[0], matrix[1]),
                 (int(match.group("height")), matrix[2], matrix[3]),
             ):
                 if size < max_size:
                     continue
                 render_size = math.sqrt(coeff1 * coeff1 + coeff2 * coeff2)
                 dpi = int(size * 72 / render_size)
                 if dpi > PDF_RENDER_DPI_MAX:
                     dpi = PDF_RENDER_DPI_MAX
                 max_size = size
                 max_dpi = dpi
     finally:
         proc.stdout.close()
         proc.wait()
     # Render...
     cmd = _mudraw_exec + ["-r", str(max_dpi), "-o", destination_path, "--", self.archive, str(page_num)]
     log.debug("rendering %s: %s", filename, " ".join(cmd))
     process.call(cmd)
예제 #5
0
 def iter_contents(self):
     with process.popen(_mutool_exec +
                        ['show', '--', self.archive, 'pages'],
                        universal_newlines=True) as proc:
         for line in proc.stdout:
             if line.startswith('page '):
                 yield line.split()[1] + '.png'
예제 #6
0
    def iter_contents(self):
        if not self._get_executable():
            return

        # We'll try at most 2 times:
        # - the first time without a password
        # - a second time with a password if the header is encrypted
        for retry_count in range(2):
            #: Indicates which part of the file listing has been read.
            self._state = self.STATE_HEADER
            #: Current path while listing contents.
            self._path = None
            proc = process.popen(self._get_list_arguments(),
                                 stderr=process.STDOUT)
            try:
                for line in proc.stdout:
                    filename = self._parse_list_output_line(
                        line.rstrip(os.linesep))
                    if filename is not None:
                        yield self._unicode_filename(filename)
            except self.EncryptedHeader:
                # The header is encrypted, try again
                # if it was our first attempt.
                if 0 == retry_count:
                    continue
            finally:
                proc.stdout.close()
                proc.wait()
            # Last and/or successful attempt.
            break

        self.filenames_initialized = True
예제 #7
0
    def iter_extract(self, entries, destination_dir):

        if not self._get_executable():
            return

        if not self.filenames_initialized:
            self.list_contents()

        proc = process.popen(self._get_extract_arguments())
        try:
            wanted = dict([(self._original_filename(unicode_name),
                            unicode_name) for unicode_name in entries])

            for filename, filesize in self._contents:
                data = proc.stdout.read(filesize)
                if filename not in wanted:
                    continue
                unicode_name = wanted.get(filename, None)
                if unicode_name is None:
                    continue
                new = self._create_file(
                    os.path.join(destination_dir, unicode_name))
                new.write(data)
                new.close()
                yield unicode_name
                del wanted[filename]
                if 0 == len(wanted):
                    break

        finally:
            proc.stdout.close()
            proc.wait()
예제 #8
0
    def iter_contents(self):
        if not self._get_executable():
            return

        # We'll try at most 2 times:
        # - the first time without a password
        # - a second time with a password if the header is encrypted
        for retry_count in range(2):
            #: Indicates which part of the file listing has been read.
            self._state = self.STATE_HEADER
            #: Current path while listing contents.
            self._path = None
            proc = process.popen(self._get_list_arguments(), stderr=process.STDOUT)
            try:
                for line in proc.stdout:
                    filename = self._parse_list_output_line(line.rstrip(os.linesep))
                    if filename is not None:
                        yield self._unicode_filename(filename)
            except self.EncryptedHeader:
                # The header is encrypted, try again
                # if it was our first attempt.
                if 0 == retry_count:
                    continue
            finally:
                proc.stdout.close()
                proc.wait()
            # Last and/or successful attempt.
            break

        self.filenames_initialized = True
예제 #9
0
    def iter_extract(self, entries, destination_dir):

        if not self._get_executable():
            return

        if not self.filenames_initialized:
            self.list_contents()

        proc = process.popen(self._get_extract_arguments())
        try:
            wanted = dict([(self._original_filename(unicode_name), unicode_name)
                           for unicode_name in entries])

            for filename, filesize in self._contents:
                data = proc.stdout.read(filesize)
                if filename not in wanted:
                    continue
                unicode_name = wanted.get(filename, None)
                if unicode_name is None:
                    continue
                new = self._create_file(os.path.join(destination_dir, unicode_name))
                new.write(data)
                new.close()
                yield unicode_name
                del wanted[filename]
                if 0 == len(wanted):
                    break

        finally:
            proc.stdout.close()
            proc.wait()
예제 #10
0
파일: openwith.py 프로젝트: roadt/mcomix
    def execute(self, window):
        """ Spawns a new process with the given executable
        and arguments. """
        if (self.is_disabled_for_archives()
                and window.filehandler.archive_type is not None):
            window.osd.show(
                _("'%s' is disabled for archives.") % self.get_label())
            return

        current_dir = os.getcwd()
        try:
            if self.is_valid_workdir(window):
                workdir = self.parse(window, text=self.get_cwd())[0]
                os.chdir(workdir)

            # Redirect process output to null here?
            # FIXME: Close process when finished to avoid zombie process
            args = self.parse(window)
            if sys.platform == 'win32':
                proc = process.Win32Popen(args)
            else:
                proc = process.popen(args, stdout=process.NULL)
            del proc

        except Exception, e:
            text = _("Could not run command %(cmdlabel)s: %(exception)s") % \
                {'cmdlabel': self.get_label(), 'exception': unicode(e)}
            window.osd.show(text)
예제 #11
0
 def iter_contents(self):
     proc = process.popen(_mutool_exec + ["show", "--", self.archive, "pages"])
     try:
         for line in proc.stdout:
             if line.startswith("page "):
                 yield line.split()[1] + ".png"
     finally:
         proc.stdout.close()
         proc.wait()
예제 #12
0
 def extract(self, filename, destination_dir):
     self._create_directory(destination_dir)
     destination_path = os.path.join(destination_dir, filename)
     page_num, ext = os.path.splitext(filename)
     # Try to find optimal DPI.
     cmd = _mupdf['mudraw'] + _mupdf['mudraw_trace_args'] + [
         '--', self.archive, str(page_num)
     ]
     log.debug('finding optimal DPI for %s: %s', filename, ' '.join(cmd))
     with process.popen(cmd, text=True) as proc:
         max_size = 0
         max_dpi = PDF_RENDER_DPI_DEF
         for line in proc.stdout:
             match = self._fill_image_regex.match(line)
             if not match:
                 continue
             matrix = [float(f) for f in match.group('matrix').split()]
             for size, coeff1, coeff2 in (
                 (int(match.group('width')), matrix[0], matrix[1]),
                 (int(match.group('height')), matrix[2], matrix[3]),
             ):
                 if size < max_size:
                     continue
                 render_size = math.sqrt(coeff1 * coeff1 + coeff2 * coeff2)
                 dpi = int(size * 72 / render_size)
                 if dpi > PDF_RENDER_DPI_MAX:
                     dpi = PDF_RENDER_DPI_MAX
                 max_size = size
                 max_dpi = dpi
     # Render...
     cmd = _mupdf['mudraw'] + [
         '-r',
         str(max_dpi), '-o', destination_path, '--', self.archive,
         str(page_num)
     ]
     log.debug('rendering %s: %s', filename, ' '.join(cmd))
     with process.popen(cmd, stdout=process.NULL) as proc:
         with self._pdf_procs_lock:
             self._pdf_procs[(pid := proc.pid)] = proc
         proc.wait()
         with self._pdf_procs_lock:
             self._pdf_procs.pop(pid)
     return destination_path
예제 #13
0
 def iter_contents(self):
     proc = process.popen(_mutool_exec +
                          ['show', '--', self.archive, 'pages'])
     try:
         for line in proc.stdout:
             if line.startswith('page '):
                 yield line.split()[1] + '.png'
     finally:
         proc.stdout.close()
         proc.wait()
예제 #14
0
 def _has_encryption(self):
     with process.popen(self._get_list_arguments(),
                        stderr=process.STDOUT,
                        text=True) as proc:
         for line in proc.stdout:
             if line.startswith('Encrypted = +'):
                 return True
             if 'Can not open encrypted archive. Wrong password' in line:
                 return True
     return False
예제 #15
0
 def _has_encryption(self):
     with process.popen(self._get_list_arguments(),
                        stderr=process.STDOUT,
                        text=True) as proc:
         for line in proc.stdout:
             line=line.strip()
             if line.startswith('Details: ') and 'encrypted headers' in line:
                 return True
             if line.startswith('Flags: ') and 'encrypted' in line:
                 return True
     return False
예제 #16
0
 def is_available():
     global _pdf_possible
     if _pdf_possible is not None:
         return _pdf_possible
     global _mutool_exec, _mudraw_exec, _mudraw_trace_args
     mutool = process.find_executable((u'mutool', ))
     _pdf_possible = False
     version = None
     if mutool is None:
         log.debug('mutool executable not found')
     else:
         _mutool_exec = [mutool]
         # Find MuPDF version; assume 1.6 version since
         # the '-v' switch is only supported from 1.7 onward...
         version = '1.6'
         proc = process.popen([mutool, '-v'],
                              stdout=process.NULL,
                              stderr=process.PIPE)
         try:
             output = proc.stderr.read()
             if output.startswith('mutool version '):
                 version = output[15:].rstrip()
         finally:
             proc.stderr.close()
             proc.wait()
         version = LooseVersion(version)
         if version >= LooseVersion('1.8'):
             # Mutool executable with draw support.
             _mudraw_exec = [mutool, 'draw']
             _mudraw_trace_args = ['-F', 'trace']
             _pdf_possible = True
         else:
             # Separate mudraw executable.
             mudraw = process.find_executable((u'mudraw', ))
             if mudraw is None:
                 log.debug('mudraw executable not found')
             else:
                 _mudraw_exec = [mudraw]
                 if version >= LooseVersion('1.7'):
                     _mudraw_trace_args = ['-F', 'trace']
                 else:
                     _mudraw_trace_args = ['-x']
                 _pdf_possible = True
     if _pdf_possible:
         log.info('Using MuPDF version: %s', version)
         log.debug('mutool: %s', ' '.join(_mutool_exec))
         log.debug('mudraw: %s', ' '.join(_mudraw_exec))
         log.debug('mudraw trace arguments: %s',
                   ' '.join(_mudraw_trace_args))
     else:
         log.info('MuPDF not available.')
     return _pdf_possible
예제 #17
0
 def is_available():
     global _pdf_possible
     if _pdf_possible is not None:
         return _pdf_possible
     mutool = process.find_executable(('mutool', ))
     _pdf_possible = False
     version = None
     if mutool is None:
         log.debug('mutool executable not found')
     else:
         _mutool_exec.append(mutool)
         # Find MuPDF version; assume 1.6 version since
         # the '-v' switch is only supported from 1.7 onward...
         version = (1, 6)
         with process.popen([mutool, '-v'],
                            stdout=process.NULL,
                            stderr=process.PIPE,
                            universal_newlines=True) as proc:
             output = re.match(
                 r'mutool version '
                 r'(?P<version>[\d.]+)([^\d].*)?', proc.stderr.read())
             if output:
                 version = tuple(
                     map(int,
                         output.group('version').split('.')))
         if version >= (1, 8):
             # Mutool executable with draw support.
             _mudraw_exec.extend((mutool, 'draw', '-q'))
             _mudraw_trace_args.extend(('-F', 'trace'))
             _pdf_possible = True
         else:
             # Separate mudraw executable.
             mudraw = process.find_executable(('mudraw', ))
             if mudraw is None:
                 log.debug('mudraw executable not found')
             else:
                 _mudraw_exec.append(mudraw)
                 if version >= (1, 7):
                     _mudraw_trace_args.extend(('-F', 'trace'))
                 else:
                     _mudraw_trace_args.append('-x')
                 _pdf_possible = True
     if _pdf_possible:
         log.info('Using MuPDF version: %s', '.'.join(map(str, version)))
         log.debug('mutool: %s', ' '.join(_mutool_exec))
         log.debug('mudraw: %s', ' '.join(_mudraw_exec))
         log.debug('mudraw trace arguments: %s',
                   ' '.join(_mudraw_trace_args))
     else:
         log.info('MuPDF not available.')
     return _pdf_possible
예제 #18
0
    def iter_contents(self):
        if not self._get_executable():
            return

        with process.popen([self._get_executable()] +
                           self._get_list_arguments() +
                           [self.archive]) as proc:
            for line in proc.stdout:
                filename = self._parse_list_output_line(line.rstrip(
                    os.linesep))
                if filename is not None:
                    yield self._unicode_filename(filename)

        self.filenames_initialized = True
예제 #19
0
 def is_available():
     global _pdf_possible
     if _pdf_possible is not None:
         return _pdf_possible
     global _mutool_exec, _mudraw_exec, _mudraw_trace_args
     mutool = process.find_executable((u"mutool",))
     _pdf_possible = False
     version = None
     if mutool is None:
         log.debug("mutool executable not found")
     else:
         _mutool_exec = [mutool]
         # Find MuPDF version; assume 1.6 version since
         # the '-v' switch is only supported from 1.7 onward...
         version = "1.6"
         proc = process.popen([mutool, "-v"], stdout=process.NULL, stderr=process.PIPE)
         try:
             output = proc.stderr.read()
             if output.startswith("mutool version "):
                 version = output[15:].rstrip()
         finally:
             proc.stderr.close()
             proc.wait()
         version = LooseVersion(version)
         if version >= LooseVersion("1.8"):
             # Mutool executable with draw support.
             _mudraw_exec = [mutool, "draw"]
             _mudraw_trace_args = ["-F", "trace"]
             _pdf_possible = True
         else:
             # Separate mudraw executable.
             mudraw = process.find_executable((u"mudraw",))
             if mudraw is None:
                 log.debug("mudraw executable not found")
             else:
                 _mudraw_exec = [mudraw]
                 if version >= LooseVersion("1.7"):
                     _mudraw_trace_args = ["-F", "trace"]
                 else:
                     _mudraw_trace_args = ["-x"]
                 _pdf_possible = True
     if _pdf_possible:
         log.info("Using MuPDF version: %s", version)
         log.debug("mutool: %s", " ".join(_mutool_exec))
         log.debug("mudraw: %s", " ".join(_mudraw_exec))
         log.debug("mudraw trace arguments: %s", " ".join(_mudraw_trace_args))
     else:
         log.info("MuPDF not available.")
     return _pdf_possible
예제 #20
0
 def is_available():
     global _pdf_possible
     if _pdf_possible is not None:
         return _pdf_possible
     mutool = process.find_executable(('mutool', ))
     _pdf_possible = False
     version = None
     if mutool is None:
         log.debug('mutool executable not found')
     else:
         _mutool_exec.append(mutool)
         # Find MuPDF version; assume 1.6 version since
         # the '-v' switch is only supported from 1.7 onward...
         version = '1.6'
         with process.popen([mutool, '-v'],
                            stdout=process.NULL,
                            stderr=process.PIPE,
                            universal_newlines=True) as proc:
             output = proc.stderr.read()
             if output.startswith('mutool version '):
                 version = output[15:].rstrip()
         version = LooseVersion(version)
         if version >= LooseVersion('1.8'):
             # Mutool executable with draw support.
             _mudraw_exec.extend((mutool, 'draw', '-q'))
             _mudraw_trace_args.extend(('-F', 'trace'))
             _pdf_possible = True
         else:
             # Separate mudraw executable.
             mudraw = process.find_executable(('mudraw', ))
             if mudraw is None:
                 log.debug('mudraw executable not found')
             else:
                 _mudraw_exec.append(mudraw)
                 if version >= LooseVersion('1.7'):
                     _mudraw_trace_args.extend(('-F', 'trace'))
                 else:
                     _mudraw_trace_args.append('-x')
                 _pdf_possible = True
     if _pdf_possible:
         log.info('Using MuPDF version: %s', version)
         log.debug('mutool: %s', ' '.join(_mutool_exec))
         log.debug('mudraw: %s', ' '.join(_mudraw_exec))
         log.debug('mudraw trace arguments: %s',
                   ' '.join(_mudraw_trace_args))
     else:
         log.info('MuPDF not available.')
     return _pdf_possible
예제 #21
0
    def iter_contents(self):
        if not self._get_executable():
            return

        proc = process.popen([self._get_executable()] +
                             self._get_list_arguments() +
                             [self.archive])
        try:
            for line in proc.stdout:
                filename = self._parse_list_output_line(line.rstrip(os.linesep))
                if filename is not None:
                    yield self._unicode_filename(filename)
        finally:
            proc.stdout.close()
            proc.wait()

        self.filenames_initialized = True
예제 #22
0
def _find_unrar_executable():
    ''' Tries to start rar/unrar, and returns either 'rar' or 'unrar' if
        one of them was started successfully.
        Returns None if neither could be started. '''

    if 'path' not in _rar_executable:
        path = process.find_executable(('unrar-nonfree', 'unrar', 'rar'),
                                       is_valid_candidate=_is_not_unrar_free)
        _rar_executable['path'] = path
        if path is not None:
            with process.popen([path], text=True) as proc:
                # only check first line
                line = proc.stdout.read().strip().splitlines()[0].split()
                if line[0]=='UNRAR':
                    log.debug('unrar version: %s', line[1])

    return _rar_executable['path']
예제 #23
0
 def iter_contents(self):
     if not self._get_executable():
         return
     self._state = self.STATE_HEADER
     # We make up a name that's guaranteed to be
     # recognized as an archive by MComix.
     self._path = 'archive.tar'
     proc = process.popen(self._get_list_arguments(), stderr=process.STDOUT)
     try:
         for line in proc.stdout:
             self._parse_list_output_line(line.rstrip(os.linesep))
     finally:
         proc.stdout.close()
         proc.wait()
     if self._contents:
         # The archive should not contain more than 1 member.
         assert 1 == len(self._contents)
         yield self._unicode_filename(self._path)
     self.filenames_initialized = True
예제 #24
0
 def iter_contents(self):
     if not self._get_executable():
         return
     self._state = self.STATE_HEADER
     # We make up a name that's guaranteed to be
     # recognized as an archive by MComix.
     self._path = 'archive.tar'
     proc = process.popen(self._get_list_arguments(), stderr=process.STDOUT)
     try:
         for line in proc.stdout:
             self._parse_list_output_line(line.rstrip(os.linesep))
     finally:
         proc.stdout.close()
         proc.wait()
     if self._contents:
         # The archive should not contain more than 1 member.
         assert 1 == len(self._contents)
         yield self._unicode_filename(self._path)
     self.filenames_initialized = True
예제 #25
0
 def extract(self, filename, destination_dir):
     self._create_directory(destination_dir)
     destination_path = os.path.join(destination_dir, filename)
     page_num = int(filename[0:-4])
     # Try to find optimal DPI.
     cmd = _mudraw_exec + _mudraw_trace_args + [
         '--', self.archive, str(page_num)
     ]
     log.debug('finding optimal DPI for %s: %s', filename, ' '.join(cmd))
     proc = process.popen(cmd)
     try:
         max_size = 0
         max_dpi = PDF_RENDER_DPI_DEF
         for line in proc.stdout:
             match = self._fill_image_regex.match(line)
             if not match:
                 continue
             matrix = [float(f) for f in match.group('matrix').split()]
             for size, coeff1, coeff2 in (
                 (int(match.group('width')), matrix[0], matrix[1]),
                 (int(match.group('height')), matrix[2], matrix[3]),
             ):
                 if size < max_size:
                     continue
                 render_size = math.sqrt(coeff1 * coeff1 + coeff2 * coeff2)
                 dpi = int(size * 72 / render_size)
                 if dpi > PDF_RENDER_DPI_MAX:
                     dpi = PDF_RENDER_DPI_MAX
                 max_size = size
                 max_dpi = dpi
     finally:
         proc.stdout.close()
         proc.wait()
     # Render...
     cmd = _mudraw_exec + [
         '-r',
         str(max_dpi), '-o', destination_path, '--', self.archive,
         str(page_num)
     ]
     log.debug('rendering %s: %s', filename, ' '.join(cmd))
     process.call(cmd)
예제 #26
0
def is_7z_support_rar():
    '''Check whether p7zip has Rar.so, which is needed to Rar format'''
    if sys.platform=='win32':
        # assume 7z in windows already support rar
        return True
    has_rar_so=False
    with process.popen((SevenZipArchive._find_7z_executable(),'i'),
                       universal_newlines=True) as proc:
        libsblock=False
        for line in proc.stdout:
            line=line.rstrip()
            if line=='Libs:':
                libsblock=True
                continue
            if libsblock and not line:
                break
            if libsblock:
                idx,path=line.strip().split()
                if os.path.basename(path)=='Rar.so':
                    has_rar_so=True
    return has_rar_so
예제 #27
0
from mcomix import log
from mcomix import process
from mcomix.archive import archive_base

# Filled on-demand by SevenZipArchive
_7z_executable = {}


def _has_rar_so():
    if not (_7z := SevenZipArchive._find_7z_executable()):
        return False
    if sys.platform == 'win32':
        # assume 7z in windows already support rar
        return True
    with process.popen((_7z, 'i'), universal_newlines=True) as proc:
        lines = proc.stdout.read().splitlines()
        try:
            del lines[:lines.index('Libs:') + 1]
            del lines[lines.index(''):]
        except ValueError:
            # no library found
            return False
        for line in lines:
            if line.endswith('/Rar.so'):
                return True
    return False


def is_7z_support_rar():
    '''Check whether p7zip has Rar.so, which is needed to Rar format'''
예제 #28
0
def update(args=[], notification_delay=3, notification_duration=3):
    '''Update fontconfig cache by calling fc-cache.exe manually.

    The function will block until fc-cache.exe has finished. If the update
    takes more than <notification_delay> seconds, a notification window will be
    shown for at least <notification_duration> seconds.
    '''

    cmd = [fc_cache_exe]
    cmd.extend(args)
    proc = process.popen(cmd, stdout=process.NULL)

    notif_time = time.time() + notification_delay
    end_time = notif_time + notification_duration

    i18n.install_gettext()

    import pygtk
    pygtk.require('2.0')
    import gtk, gobject
    gobject.threads_init()

    class Window(gtk.Window):

        def __init__(self):
            super(Window, self).__init__()
            self.set_title('MComix')
            self.set_border_width(10)
            self.set_wmclass('MComix', 'MComix')
            self.set_resizable(False)
            self.set_deletable(False)
            self._displayed = False
            vbox = gtk.VBox(spacing=5)
            label = gtk.Label(_('Updating font cache. This may take a few minutes.'))
            vbox.pack_start(label)
            self._spinner = gtk.Spinner()
            vbox.pack_start(self._spinner, expand=False, fill=False)
            vbox.show_all()
            self.add(vbox)
            self.set_geometry_hints(vbox)
            gobject.timeout_add(200, self._on_ping)

        def _on_ping(self):
            now = time.time()
            returncode = proc.poll()
            if returncode is None:
                # Process is still running.
                if now <= notif_time:
                    # Not enough time elapsed, do not show dialog yet.
                    return True
            else:
                # Process has terminated.
                if not notif_time < now < end_time:
                    # Dialog is not being shown or it has already
                    # been displayed for the required amount of time.
                    gtk.main_quit()
                    return False
            if not self._displayed:
                # Show dialog.
                self.show()
                self._spinner.start()
                self._displayed = True
            return True

    # Create a very simple fontconfig configuration,
    # with a temporary cache directory, and only a few fonts.
    tmpdir = tempfile.mkdtemp(suffix='-mcomix-fc_cache')
    try:
        cachedir = os.path.join(tmpdir, 'cache')
        os.mkdir(cachedir)
        config = os.path.join(tmpdir, 'fonts.conf')
        exe_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
        with open(config, 'w') as f:
            f.write('''<?xml version="1.0"?>
                    <!DOCTYPE fontconfig SYSTEM "fonts.dtd">
                    <fontconfig>
                      <dir>c:/Python27/Lib/site-packages/gnome/share/fonts</dir>
                      <dir>%(executable_dir)s/share/fonts</dir>
                      <cachedir>%(cache_dir)s</cachedir>
                      <alias>
                        <family>Times</family>
                        <default><family>Vera</family></default>
                      </alias>
                      <alias>
                        <family>Helvetica</family>
                        <default><family>Vera</family></default>
                      </alias>
                      <alias>
                        <family>Courier</family>
                        <default><family>Vera</family></default>
                    </alias>
                    </fontconfig>''' % {
                        'executable_dir': exe_dir,
                        'cache_dir': cachedir,
                    })
        previous_config = os.environ.get('FONTCONFIG_FILE', None)
        os.environ['FONTCONFIG_FILE'] = config
        try:
            win = Window()
            gtk.main()
        finally:
            if previous_config is None:
                del os.environ['FONTCONFIG_FILE']
            else:
                os.environ['FONTCONFIG_FILE'] = previous_config
    finally:
        shutil.rmtree(tmpdir)
예제 #29
0
def update(args=[], notification_delay=3, notification_duration=3):
    '''Update fontconfig cache by calling fc-cache.exe manually.

    The function will block until fc-cache.exe has finished. If the update
    takes more than <notification_delay> seconds, a notification window will be
    shown for at least <notification_duration> seconds.
    '''

    cmd = [fc_cache_exe]
    cmd.extend(args)
    proc = process.popen(cmd, stdout=process.NULL)

    notif_time = time.time() + notification_delay
    end_time = notif_time + notification_duration

    i18n.install_gettext()

    import pygtk
    pygtk.require('2.0')
    import gtk, gobject
    gobject.threads_init()

    class Window(gtk.Window):
        def __init__(self):
            super(Window, self).__init__()
            self.set_title('MComix')
            self.set_border_width(10)
            self.set_wmclass('MComix', 'MComix')
            self.set_resizable(False)
            self.set_deletable(False)
            self._displayed = False
            vbox = gtk.VBox(spacing=5)
            label = gtk.Label(
                _('Updating font cache. This may take a few minutes.'))
            vbox.pack_start(label)
            self._spinner = gtk.Spinner()
            vbox.pack_start(self._spinner, expand=False, fill=False)
            vbox.show_all()
            self.add(vbox)
            self.set_geometry_hints(vbox)
            gobject.timeout_add(200, self._on_ping)

        def _on_ping(self):
            now = time.time()
            returncode = proc.poll()
            if returncode is None:
                # Process is still running.
                if now <= notif_time:
                    # Not enough time elapsed, do not show dialog yet.
                    return True
            else:
                # Process has terminated.
                if not notif_time < now < end_time:
                    # Dialog is not being shown or it has already
                    # been displayed for the required amount of time.
                    gtk.main_quit()
                    return False
            if not self._displayed:
                # Show dialog.
                self.show()
                self._spinner.start()
                self._displayed = True
            return True

    # Create a very simple fontconfig configuration,
    # with a temporary cache directory, and only a few fonts.
    tmpdir = tempfile.mkdtemp(suffix='-mcomix-fc_cache')
    try:
        cachedir = os.path.join(tmpdir, 'cache')
        os.mkdir(cachedir)
        config = os.path.join(tmpdir, 'fonts.conf')
        exe_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
        with open(config, 'w') as f:
            f.write('''<?xml version="1.0"?>
                    <!DOCTYPE fontconfig SYSTEM "fonts.dtd">
                    <fontconfig>
                      <dir>c:/Python27/Lib/site-packages/gnome/share/fonts</dir>
                      <dir>%(executable_dir)s/share/fonts</dir>
                      <cachedir>%(cache_dir)s</cachedir>
                      <alias>
                        <family>Times</family>
                        <default><family>Vera</family></default>
                      </alias>
                      <alias>
                        <family>Helvetica</family>
                        <default><family>Vera</family></default>
                      </alias>
                      <alias>
                        <family>Courier</family>
                        <default><family>Vera</family></default>
                    </alias>
                    </fontconfig>''' % {
                'executable_dir': exe_dir,
                'cache_dir': cachedir,
            })
        previous_config = os.environ.get('FONTCONFIG_FILE', None)
        os.environ['FONTCONFIG_FILE'] = config
        try:
            win = Window()
            gtk.main()
        finally:
            if previous_config is None:
                del os.environ['FONTCONFIG_FILE']
            else:
                os.environ['FONTCONFIG_FILE'] = previous_config
    finally:
        shutil.rmtree(tmpdir)
예제 #30
0

def _find_mupdf():
    _mupdf['found'] = False
    _mupdf['version'] = None
    _mupdf['mutool'] = []
    _mupdf['mudraw'] = []
    _mupdf['mudraw_trace_args'] = []
    if (mutool := process.find_executable(('mutool', ))) is None:
        return log.debug('mutool executable not found')
    _mupdf['mutool'].append(mutool)
    # Find MuPDF version; assume 1.6 version since
    # the '-v' switch is only supported from 1.7 onward...
    _mupdf['version'] = (1, 6)
    with process.popen([mutool, '-v'],
                       stdout=process.NULL,
                       stderr=process.PIPE,
                       text=True) as proc:
        if output := re.match(r'mutool version (?P<version>[\d.]+)([^\d].*)?',
                              proc.stderr.read()):
            _mupdf['version'] = tuple(
                map(int,
                    output.group('version').split('.')))
    if _mupdf['version'] >= (1, 8):
        # Mutool executable with draw support.
        _mupdf['found'] = True
        _mupdf['mudraw'].extend((mutool, 'draw', '-q'))
        _mupdf['mudraw_trace_args'].extend(('-F', 'trace'))
        return
    # Separate mudraw executable.
    if (mudraw := process.find_executable(('mudraw', ))) is None:
        return log.debug('mudraw executable not found')
예제 #31
0
def make_archive(outfile,
                 contents,
                 format='zip',
                 solid=False,
                 password=None,
                 header_encryption=False):
    if os.path.exists(outfile):
        raise Exception('%s already exists' % outfile)
    cleanup = []
    try:
        outpath = os.path.abspath(outfile)
        tmp_dir = tempfile.mkdtemp(dir=u'test/tmp', prefix=u'make_archive.')
        cleanup.append(lambda: shutil.rmtree(tmp_dir))
        entry_list = []
        for name, filename in contents:
            entry_list.append(name)
            path = os.path.join(tmp_dir, name)
            if filename is None:
                os.makedirs(path)
                continue
            dir = os.path.dirname(path)
            if not os.path.exists(dir):
                os.makedirs(dir)
            shutil.copy(filename, path)
        if '7z' == format:
            cmd = ['7z', 'a']
            cmd.append('-ms=on' if solid else '-ms=off')
            if password is not None:
                cmd.append('-p' + password)
                if header_encryption:
                    cmd.append('-mhe=on')
            else:
                assert not header_encryption
            cmd.extend(('--', outpath))
            # To avoid @ being treated as a special character...
            tmp_file = tempfile.NamedTemporaryFile(dir=u'test/tmp',
                                                   prefix=u'make_archive.',
                                                   delete=False)
            cleanup.append(lambda: os.unlink(tmp_file.name))
            for entry in entry_list:
                tmp_file.write(
                    entry.encode(locale.getpreferredencoding()) + '\n')
            tmp_file.close()
            entry_list = ['@' + tmp_file.name]
        elif 'lha' == format:
            assert password is None
            assert not header_encryption
            if solid:
                raise UnsupportedOption(format, 'solid')
            cmd = ['lha', 'a', outpath, '--']
        elif 'rar' == format:
            cmd = ['rar', 'a', '-r']
            cmd.append('-s' if solid else '-s-')
            if password is not None:
                if header_encryption:
                    cmd.append('-hp' + password)
                else:
                    cmd.append('-p' + password)
            else:
                assert not header_encryption
            cmd.extend(('--', outpath))
        elif format.startswith('tar'):
            assert password is None
            assert not header_encryption
            if not solid:
                raise UnsupportedOption(format, 'not solid')
            if 'tar' == format:
                compression = ''
            elif 'tar.bz2' == format:
                compression = 'j'
            elif 'tar.gz' == format:
                compression = 'z'
            elif 'tar.xz' == format:
                compression = 'J'
            else:
                raise UnsupportedFormat(format)
            cmd = ['tar', '-cv%sf' % compression, outpath, '--']
            # entry_list = [ name.replace('\\', '\\\\') for name in entry_list]
        elif 'zip' == format:
            assert not header_encryption
            if solid:
                raise UnsupportedOption(format, 'solid')
            cmd = ['zip', '-r']
            if password is not None:
                cmd.extend(['-P', password])
            cmd.extend([outpath, '--'])
        else:
            raise UnsupportedFormat(format)
        cmd.extend(entry_list)
        cwd = os.getcwd()
        cleanup.append(lambda: os.chdir(cwd))
        os.chdir(tmp_dir)
        proc = process.popen(cmd, stderr=process.PIPE)
        cleanup.append(proc.stdout.close)
        cleanup.append(proc.stderr.close)
        cleanup.append(proc.wait)
        stdout, stderr = proc.communicate()
    finally:
        for fn in reversed(cleanup):
            fn()
    if not os.path.exists(outfile):
        raise Exception(
            'archive creation failed: %s\nstdout:\n%s\nstderr:\n%s\n' %
            (' '.join(cmd), stdout, stderr))
예제 #32
0
from mcomix import log
from mcomix import process
from mcomix.archive import archive_base

# Filled on-demand by SevenZipArchive
_7z_executable = {}


def _has_rar_so():
    if not (_7z := SevenZipArchive._find_7z_executable()):
        return False
    if sys.platform == 'win32':
        # assume 7z in windows already support rar
        return True
    with process.popen((_7z, 'i'), text=True) as proc:
        lines = proc.stdout.read().splitlines()
        try:
            del lines[:lines.index('Libs:') + 1]
            del lines[lines.index(''):]
        except ValueError:
            # no library found
            return False
        for line in lines:
            if line.endswith('/Rar.so'):
                return True
    return False


def is_7z_support_rar():
    '''Check whether p7zip has Rar.so, which is needed to Rar format'''
예제 #33
0
def make_archive(outfile, contents, format='zip', solid=False, password=None, header_encryption=False):
    if os.path.exists(outfile):
        raise Exception('%s already exists' % outfile)
    cleanup = []
    try:
        outpath = os.path.abspath(outfile)
        tmp_dir = tempfile.mkdtemp(dir=u'test/tmp', prefix=u'make_archive.')
        cleanup.append(lambda: shutil.rmtree(tmp_dir))
        entry_list = []
        for name, filename in contents:
            entry_list.append(name)
            path = os.path.join(tmp_dir, name)
            if filename is None:
                os.makedirs(path)
                continue
            dir = os.path.dirname(path)
            if not os.path.exists(dir):
                os.makedirs(dir)
            shutil.copy(filename, path)
        if '7z' == format:
            cmd = ['7z', 'a']
            cmd.append('-ms=on' if solid else '-ms=off')
            if password is not None:
                cmd.append('-p' + password)
                if header_encryption:
                    cmd.append('-mhe=on')
            else:
                assert not header_encryption
            cmd.extend(('--', outpath))
            # To avoid @ being treated as a special character...
            tmp_file = tempfile.NamedTemporaryFile(dir=u'test/tmp',
                                                   prefix=u'make_archive.',
                                                   delete=False)
            cleanup.append(lambda: os.unlink(tmp_file.name))
            for entry in entry_list:
                tmp_file.write(entry.encode(locale.getpreferredencoding()) + '\n')
            tmp_file.close()
            entry_list = ['@' + tmp_file.name]
        elif 'lha' == format:
            assert password is None
            assert not header_encryption
            if solid:
                raise UnsupportedOption(format, 'solid')
            cmd = ['lha', 'a', outpath, '--']
        elif 'rar' == format:
            cmd = ['rar', 'a', '-r']
            cmd.append('-s' if solid else '-s-')
            if password is not None:
                if header_encryption:
                    cmd.append('-hp' + password)
                else:
                    cmd.append('-p' + password)
            else:
                assert not header_encryption
            cmd.extend(('--', outpath))
        elif format.startswith('tar'):
            assert password is None
            assert not header_encryption
            if not solid:
                raise UnsupportedOption(format, 'not solid')
            if 'tar' == format:
                compression = ''
            elif 'tar.bz2' == format:
                compression = 'j'
            elif 'tar.gz' == format:
                compression = 'z'
            else:
                raise UnsupportedFormat(format)
            cmd = ['tar', '-cv%sf' % compression, outpath, '--']
            # entry_list = [ name.replace('\\', '\\\\') for name in entry_list]
        elif 'zip' == format:
            assert not header_encryption
            if solid:
                raise UnsupportedOption(format, 'solid')
            cmd = ['zip', '-r']
            if password is not None:
                cmd.extend(['-P', password])
            cmd.extend([outpath, '--'])
        else:
            raise UnsupportedFormat(format)
        cmd.extend(entry_list)
        cwd = os.getcwd()
        cleanup.append(lambda: os.chdir(cwd))
        os.chdir(tmp_dir)
        proc = process.popen(cmd, stderr=process.PIPE)
        cleanup.append(proc.stdout.close)
        cleanup.append(proc.stderr.close)
        cleanup.append(proc.wait)
        stdout, stderr = proc.communicate()
    finally:
        for fn in reversed(cleanup):
            fn()
    if not os.path.exists(outfile):
        raise Exception('archive creation failed: %s\nstdout:\n%s\nstderr:\n%s\n' % (
            ' '.join(cmd), stdout, stderr
        ))