Skip to content

Commit

Permalink
Merge pull request #3 from hughsie/setup
Browse files Browse the repository at this point in the history
Add Setup and other minor updates for a release
  • Loading branch information
hughsie authored Feb 9, 2018
2 parents abe56c0 + 8fbe24f commit 521e7e9
Show file tree
Hide file tree
Showing 10 changed files with 114 additions and 37 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,4 @@ docs/_build/

# PyBuilder
target/
/tmp/
10 changes: 10 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
language: python

python:
- 2.7.13

install:
- sudo apt-get install cabextract

script:
- python test.py
9 changes: 6 additions & 3 deletions cabarchive/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301, USA

from file import CabFile
from archive import CabArchive
from errors import CorruptionError, NotSupportedError
from __future__ import absolute_import
from __future__ import print_function

from cabarchive.file import CabFile
from cabarchive.archive import CabArchive
from cabarchive.errors import CorruptionError, NotSupportedError
19 changes: 11 additions & 8 deletions cabarchive/archive.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,17 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301, USA

from __future__ import absolute_import
from __future__ import print_function

import os
import struct
import fnmatch
import zlib
import datetime

from file import CabFile
from errors import *
from cabarchive.file import CabFile
from cabarchive.errors import CorruptionError, NotSupportedError


FMT_CFHEADER = '<4sxxxxIxxxxIxxxxBBHHHHH'
FMT_CFFOLDER = '<IHH'
Expand Down Expand Up @@ -100,7 +103,7 @@ def _parse_cffile(self, offset):

# debugging
if os.getenv('PYTHON_CABARCHIVE_DEBUG'):
print "CFFILE", vals
print("CFFILE", vals)

# parse filename
offset += struct.calcsize(fmt)
Expand Down Expand Up @@ -137,7 +140,7 @@ def _parse_cffolder(self, idx, offset):

# debugging
if os.getenv('PYTHON_CABARCHIVE_DEBUG'):
print "CFFOLDER", vals
print("CFFOLDER", vals)

# no data blocks?
if vals[1] == 0:
Expand All @@ -159,7 +162,7 @@ def _parse_cffolder(self, idx, offset):
# parse CDATA
self._folder_data.append(bytearray())
offset = vals[0]
for i in range(vals[1]):
for _ in range(vals[1]):
offset += self._parse_cfdata(idx, offset, is_zlib)

def _parse_cfdata(self, idx, offset, is_zlib):
Expand All @@ -173,7 +176,7 @@ def _parse_cfdata(self, idx, offset, is_zlib):
raise CorruptionError(str(e))
# debugging
if os.getenv('PYTHON_CABARCHIVE_DEBUG'):
print "CFDATA", vals
print("CFDATA", vals)
if not is_zlib and vals[1] != vals[2]:
raise CorruptionError('Mismatched data %i != %i' % (vals[1], vals[2]))
hdr_sz = struct.calcsize(fmt)
Expand Down Expand Up @@ -234,7 +237,7 @@ def parse(self, buf):

# debugging
if os.getenv('PYTHON_CABARCHIVE_DEBUG'):
print "CFHEADER", vals
print("CFHEADER", vals)

# check magic bytes
if vals[0] != b'MSCF':
Expand Down
6 changes: 6 additions & 0 deletions cabarchive/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,13 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301, USA

from __future__ import absolute_import
from __future__ import print_function


class CorruptionError(Exception):
pass


class NotSupportedError(Exception):
pass
16 changes: 11 additions & 5 deletions cabarchive/file.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,31 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301, USA

from __future__ import absolute_import
from __future__ import print_function

import datetime


def _is_ascii(text):
""" Check if a string is ASCII only """
return all(ord(c) < 128 for c in text)


class CabFile(object):

"""An object representing a file in a Cab archive """

def __init__(self, filename, contents=None):
self.filename = filename
self.contents = contents
self.date = datetime.date.today()
self.time = datetime.datetime.now().time()
self.is_readonly = False # file is read-only
self.is_hidden = False # file is hidden
self.is_system = False # file is a system file
self.is_arch = True # file modified since last backup
self.is_exec = False # file is executable
self.is_readonly = False # file is read-only
self.is_hidden = False # file is hidden
self.is_system = False # file is a system file
self.is_arch = True # file modified since last backup
self.is_exec = False # file is executable
self.is_name_utf8 = not _is_ascii(filename)

def _attr_encode(self):
Expand Down
9 changes: 7 additions & 2 deletions fix-checksum.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,18 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301, USA

from __future__ import absolute_import
from __future__ import print_function

import cabarchive as cab
import struct
import sys


def main():

if len(sys.argv) == 1:
print "No input files given"
print("No input files given")
return 1

for arg in sys.argv[1:]:
Expand All @@ -42,12 +46,13 @@ def main():
break
except cab.CorruptionError as e:
offset = e[1]
buf = buf[:offset] + struct.pack('<I', e[3]) + buf[offset+4:]
buf = buf[:offset] + struct.pack('<I', e[3]) + buf[offset + 4:]

# save file
f = open(arg, 'wb')
f.write(buf);
f.close();


if __name__ == "__main__":
main()
2 changes: 2 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[metadata]
license_file = LICENSE
47 changes: 43 additions & 4 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,46 @@
#!/usr/bin/env python
import setuptools

setuptools.setup(
name="cabarchive",
packages=["cabarchive"],
from __future__ import absolute_import
from __future__ import print_function

from setuptools import setup

# note: this is a repeat of the README, to evolve, good enough for now.
long_desc = '''
If you want to parse Microsoft Cabinet files in Python you probably
should just install gcab, and use the GObjectIntrospection bindings
for that. GCab is a much better library than this and handles many more
kinds of archive.
If GCab is not available to you (e.g. you're trying to run in an
OpenShift instance on RHEL 6.2), this project might be somewhat useful.
Contributors welcome, either adding new functionality or fixing bugs.
See also: https://msdn.microsoft.com/en-us/library/bb417343.aspx
'''

setup(
name='cabarchive',
version='0.1.0',
license='LGPL-2.1-or-later',
description='A pure-python library for creating and extracting cab files',
long_description=long_desc,
author='Richard Hughes',
author_email='[email protected]',
url='https://github.com/hughsie/python-cabarchive',
packages=['cabarchive', ],
include_package_data=True,
zip_safe=False,
classifiers=[
# complete classifier list: http://pypi.python.org/pypi?%3Aaction=list_classifiers
'Development Status :: 4 - Beta',
'Intended Audience :: Developers',
'License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+)',
'Programming Language :: Python',
'Programming Language :: Python :: 2.7',
'Topic :: Utilities',
'Topic :: System :: Archiving',
],
keywords=['cabextract', 'cab', 'archive', 'extract'],
)
32 changes: 17 additions & 15 deletions test.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,49 +18,50 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301, USA

from __future__ import absolute_import
from __future__ import print_function

import cabarchive as cab
import datetime
import subprocess
import time
import hashlib

def check_archive(filename):

def check_archive(filename, expected_rc=0):
argv = ['cabextract', '--test', '/tmp/test.cab']
rc = subprocess.call(argv)
assert rc == 0
assert rc == expected_rc, "invalid return code: %r" % rc


def check_range(data, expected):
assert data
assert expected
failures = 0
if len(data) != len(expected):
print "different sizes, got %i expected %i" % (len(data), len(expected))
print("different sizes, got %i expected %i" % (len(data), len(expected)))
failures += 1
for i in range(0, len(data)):
if data[i] != expected[i]:
print "@0x%02x got 0x%02x expected 0x%02x" % (i, data[i], expected[i])
print("@0x%02x got 0x%02x expected 0x%02x" % (i, data[i], expected[i]))
failures += 1
if failures > 10:
print "More than 10 failures, giving up..."
print("More than 10 failures, giving up...")
break
assert failures == 0, "Data is not the same"


def main():

# parse junk
arc = cab.CabArchive()
try:
arc.parse('hello')
except cab.CorruptionError as e:
except cab.CorruptionError:
pass

# parse junk
arc = cab.CabArchive()
arc.set_decompressor('cabextract')
try:
arc.parse('hello')
except cab.CorruptionError as e:
pass
check_archive('hello', expected_rc=1)

# test checksum function
csum = cab.archive._checksum_compute('hello123')
Expand All @@ -72,7 +73,7 @@ def main():
data = open('data/random.bin').read()
start = time.time()
csum = cab.archive._checksum_compute(data)
print "profile checksum: %fms" % ((time.time() - start) * 1000)
print("profile checksum: %fms" % ((time.time() - start) * 1000))

# parse test files
for fn in ['data/simple.cab',
Expand All @@ -81,7 +82,7 @@ def main():
'data/large.cab',
'data/large-compressed.cab']:
arc = cab.CabArchive()
print 'Parsing:', fn
print('Parsing:', fn)
old = open(fn, 'rb').read()
arc.parse(old)
assert len(arc.files) == 1
Expand Down Expand Up @@ -173,7 +174,7 @@ def main():
# open a folder with multiple folders
for fn in ['data/multi-folder.cab', 'data/ddf-fixed.cab']:
arc = cab.CabArchive()
print 'Parsing:', fn
print('Parsing:', fn)
old = open(fn, 'rb').read()
arc.parse(old)
assert len(arc.files) == 2, len(arc.files)
Expand All @@ -187,5 +188,6 @@ def main():
except cab.NotSupportedError as e:
pass


if __name__ == "__main__":
main()

0 comments on commit 521e7e9

Please sign in to comment.