Metadata-Version: 2.4
Name: pywimparser
Version: 0.2.0
Summary: Python library for parsing and extracting Microsoft WIM archives via libwim
Author: pywimparser contributors
License-Expression: MIT
Project-URL: Homepage, https://github.com/bwhitn/pywimparser
Project-URL: Repository, https://github.com/bwhitn/pywimparser
Project-URL: Issues, https://github.com/bwhitn/pywimparser/issues
Project-URL: Documentation, https://github.com/bwhitn/pywimparser#readme
Project-URL: Security, https://github.com/bwhitn/pywimparser/security/policy
Keywords: wim,windows,forensics,parser,archive
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries
Classifier: Topic :: System :: Archiving
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: defusedxml>=0.7.1
Provides-Extra: dev
Requires-Dist: bandit[toml]>=1.8.0; extra == "dev"
Requires-Dist: build>=1.2.2; extra == "dev"
Requires-Dist: coverage[toml]>=7.6.0; extra == "dev"
Requires-Dist: hypothesis>=6.120.0; extra == "dev"
Requires-Dist: pip-audit>=2.7.0; extra == "dev"
Requires-Dist: pytest>=8.3.0; extra == "dev"
Requires-Dist: pytest-cov>=6.0.0; extra == "dev"
Requires-Dist: ruff>=0.9.0; extra == "dev"
Requires-Dist: twine>=5.1.1; extra == "dev"
Provides-Extra: fuzz
Requires-Dist: atheris>=3.0.0; (python_version >= "3.11" and platform_system == "Linux") and extra == "fuzz"
Dynamic: license-file

# pywimparser

`pywimparser` is a Python library for reading Microsoft WIM archives.

It focuses on:
- parsing as much metadata as possible
- listing files/directories inside images
- extracting full images or selected paths

This project is read-only for WIM operations. It does **not** create or modify WIM files.

## Backend Model

`pywimparser` has two runtime paths:

- Native `libwim` backend (`ctypes`, raw C API)
  - full metadata traversal
  - robust extraction support
  - supports XPRESS, LZX, and LZMS through `libwim`
- Pure Python fallback
  - parses core WIM structures directly
  - can list/extract uncompressed resources
  - cannot fully decompress entropy-coded XPRESS/LZX/LZMS resources

Use `WimParser.parse_backend` to see which backend was used for a parse call.

## Features

- Archive-level metadata
  - header fields (signature, version, flags, chunk size, GUID, parts, image count)
  - lookup/offset table entries
  - XML document (when available)
- Image metadata
  - name, description, display name/description
  - file/dir counts and total bytes (when present)
  - selected Windows metadata from XML (when present)
- Filesystem metadata
  - path, type, timestamps, attributes, size, packed size, stream hash
- Extraction
  - `extract_all()` for an image
  - `extract([...])` for selected paths

## Platform Support

- Packaging:
  - `pywimparser` is distributed as a pure-Python wheel (`py3-none-any`) plus sdist.
  - The same wheel is installable on Linux/macOS/Windows for Intel and ARM.
- CI coverage:
  - Linux: x64 + arm64
  - macOS: Intel + Apple Silicon
  - Windows: x64 + arm64
- Native `libwim` backend CI:
  - validated on Linux x64 + arm64
  - other platforms use the pure-Python fallback unless `libwim` is installed and discoverable

## Installation

From PyPI:

```bash
pip install pywimparser
```

For full extraction/compression support, ensure `libwim` is installed and discoverable.

## Build `libwim` Without `ntfs-3g`

The repository includes `scripts/build_libwim.sh` to build shared `libwim` with:
- `--without-ntfs-3g`
- `--without-fuse`
- `--enable-shared`
- `--disable-static`

This keeps usage in the `libwim` dual-license path that allows LGPL option when `ntfs-3g` is not linked.

```bash
./scripts/build_libwim.sh
```

After build, point `pywimparser` to the library:

```bash
export PYWIMPARSER_WIMLIB_PREFIX="$(pwd)/.vendor/wimlib"
# or provide the platform-specific .so, .dylib, or .dll path:
export PYWIMPARSER_LIBWIM="$(pwd)/.vendor/wimlib/lib/libwim.so"
```

## Quick Start

```python
from pywimparser import WimParser

parser = WimParser("install.wim")
metadata = parser.parse()

print(parser.parse_backend)              # "libwim-c" or "python"
print(parser.native_backend_available)   # True if libwim is usable
print(metadata.header.compression_format)

entries = parser.list_entries(image_index=1)
print(entries[0].path)

parser.extract_all("./out", image_index=1)
parser.extract(["Windows/System32/notepad.exe"], "./out", image_index=1)
```

## CLI

```bash
pywimparser info install.wim
pywimparser list install.wim --image 1
pywimparser extract install.wim ./out --image 1
pywimparser extract install.wim ./out --image 1 --path Windows/System32/cmd.exe
```

## Development

Create and activate a virtual environment:

```bash
python3 -m venv .venv
source .venv/bin/activate
```

Install package + dev tooling:

```bash
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"
```

Run the complete local quality suite:

```bash
ruff check .
ruff format --check .
python -m coverage run -m pytest -q
python -m coverage report
python -m bandit -c pyproject.toml -r src
python -m pip_audit
python -m fuzz.run_smoke --iterations 10000
```

Coverage is branch-aware and enforced at 90% for the portable Python
implementation. The native binding is validated in dedicated libwim CI jobs.
Fixture notes are in `tests/fixtures/README.md`; the full workflow is in
[`CONTRIBUTING.md`](CONTRIBUTING.md), and the latest review evidence is in
[`AUDIT.md`](AUDIT.md).

For coverage-guided Linux fuzzing:

```bash
python -m pip install -e ".[fuzz]"
python -m fuzz.fuzz_parser --seed-corpus tests/fixtures -atheris_runs=20000 -max_len=8192
```

## Build Artifacts

Build wheel + sdist:

```bash
python -m build
```

## Releases

Release notes are maintained in [`CHANGELOG.md`](CHANGELOG.md). The project uses
Semantic Versioning; while the major version is zero, minor releases may include
intentional compatibility changes and patch releases remain backward-compatible.
Release tags use `vMAJOR.MINOR.PATCH` and must match the version in
`pyproject.toml`.

## GitHub Actions / PyPI Readiness

The repository includes workflows for:

- linting and formatting checks
- branch-aware tests and coverage enforcement
- Bandit static analysis and dependency vulnerability auditing
- portable mutation fuzzing and Linux Atheris coverage-guided fuzzing
- Python/platform matrices and native libwim integration tests
- wheel/sdist construction and package validation
- Publish (build sdist/wheel, publish with trusted publishing)

Tagged releases verify that the tag matches the package version, validate the
wheel and sdist, and publish through PyPI trusted publishing.

## Public API

Main class:

- `WimParser(path)`

Methods:

- `parse(force_reload=False)`
- `list_entries(image_index=1)`
- `extract_all(destination, image_index=1)`
- `extract(paths, destination, image_index=1)`

Properties:

- `parse_backend`
- `native_backend_available`
- `rust_backend_available` (compatibility alias)
- `extraction_available`

Passing an empty list to `extract()` is an error; use `extract_all()` when full
archive extraction is intended.

## Security

Treat WIM archives as untrusted data. The pure-Python path validates archive
paths before writing, rejects pre-existing symlink hops, verifies WIM resource
hashes, and parses embedded XML with `defusedxml`. WIM SHA-1 identifiers are not
proof of authenticity, the pure-Python parser reads the archive into memory, and
native operation depends on the libwim library selected by the environment.

Extract hostile archives with least privilege and application-level size/time
limits. See [`SECURITY.md`](SECURITY.md) for the threat model and private
reporting process.

## License

`pywimparser` is licensed under MIT.

`libwim` is third-party software with its own license terms. See `THIRD_PARTY_NOTICES.md`.

This README is technical guidance, not legal advice.
