# filters.py - conversion filters for compression and encryption # # Copyright (C) 2015 Arthur de Jong # # This program 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 2 of the License, or # (at your option) any later version. # # This program 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 this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # # The files produced as output from the software do not automatically fall # under the copyright of the software, unless explicitly stated otherwise. import os import subprocess class Reader(object): def __init__(self, cmd, fileobj): self.cmdline = ' '.join(cmd) self.fileobj = fileobj self.proc = subprocess.Popen( cmd, universal_newlines=False, stdin=fileobj, stdout=subprocess.PIPE, stderr=subprocess.PIPE) def close(self): # complete command (stdout, stderr) = self.proc.communicate(None) self.fileobj.close() # FIXME: check stderr if self.proc.returncode: print(stderr) raise EnvironmentError('%s failed' % self.cmdline) def __getattr__(self, attr): return getattr(self.proc.stdout, attr) def __iter__(self): return self.proc.stdout.__iter__() def __enter__(self): return self def __exit__(self, type, value, traceback): self.close() class Writer(object): def __init__(self, cmd, fileobj): self.cmdline = ' '.join(cmd) self.fileobj = fileobj self.proc = subprocess.Popen( cmd, universal_newlines=False, stdin=subprocess.PIPE, stdout=fileobj, stderr=subprocess.PIPE) def close(self): # complete command (stdout, stderr) = self.proc.communicate(None) self.fileobj.close() # FIXME: check stderr if self.proc.returncode: print(stderr) raise EnvironmentError('%s failed' % self.cmdline) def __getattr__(self, attr): return getattr(self.proc.stdin, attr) def __enter__(self): return self def __exit__(self, type, value, traceback): self.close() class Filter(object): extension = '' def rename(self, fname): if self.extension: return '%s.%s' % (fname, self.extension) return fname class GzipCompression(Filter): extension = 'gz' restore_cmd = 'gzip -dc' def reader(self, fileobj): return Reader(['gzip', '-dc'], fileobj) def writer(self, fileobj): return Writer(['gzip', '-c', '-n', '-9'], fileobj) class Bzip2Compression(Filter): extension = 'bz2' restore_cmd = 'bzip2 -dc' def reader(self, fileobj): return Reader(['bzip2', '-dc'], fileobj) def writer(self, fileobj): return Writer(['bzip2', '-c', '-9'], fileobj) class XZCompression(Filter): extension = 'xz' restore_cmd = 'xz -dc' def reader(self, fileobj): return Reader(['xz', '-dc'], fileobj) def writer(self, fileobj): return Writer(['xz', '-zc'], fileobj) class NoEncryption(Filter): restore_cmd = 'cat' def reader(self, fileobj): return fileobj def writer(self, fileobj): return fileobj class GnuPGEncryption(Filter): extension = 'gpg' restore_cmd = 'gpg -q --batch --no-use-agent ' + \ '--passphrase-file "$EXTMPDIR"/passphrase -d' def __init__(self, repo): self.repo = repo def reader(self, fileobj): infd, outfd = os.pipe() os.write(outfd, self.repo.get_passphrase() + '\n') os.close(outfd) f = Reader([ 'gpg', '--batch', '--no-use-agent', '-q', '--passphrase-fd', str(infd), '--no-textmode', '-d'], fileobj) os.close(infd) return f def writer(self, fileobj): infd, outfd = os.pipe() os.write(outfd, (self.repo.get_passphrase() + '\n').encode('ascii')) os.close(outfd) f = Writer([ 'gpg', '--batch', '--symmetric', '--cipher-algo', 'AES256', '-q', '--compress-algo', 'none', '--passphrase-fd', str(infd), '--no-textmode'], fileobj) os.close(infd) return f class GnuPGKeyEncryption(Filter): extension = 'gpg' restore_cmd = 'gpg -d' def __init__(self, keys=()): self.keys = keys def reader(self, fileobj): return Reader(['gpg', '-d', '-q'], fileobj) def writer(self, fileobj): args = ['gpg', '--batch', '-q', '--encrypt', '--trust-model', 'always'] for key in self.keys: args.extend(['--recipient', key]) return Writer(args, fileobj)