html2pdf-secure 0.1.0

A Rust crate for converting HTML to password-protected PDF files
Documentation
# html2pdf-secure

A Rust crate for converting HTML to password-protected PDF files using headless Chrome and robust encryption.

[![Crates.io](https://img.shields.io/crates/v/html2pdf-secure.svg)](https://crates.io/crates/html2pdf-secure)
[![Documentation](https://docs.rs/html2pdf-secure/badge.svg)](https://docs.rs/html2pdf-secure)
[![License](https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-blue.svg)](LICENSE)

## Features

- 🌐 **HTML to PDF Conversion**: Convert HTML content, files, or URLs to PDF using headless Chrome
- 🔒 **Password Protection**: Add user and owner passwords to generated PDFs
- 🛡️ **Multiple Encryption Levels**: Support for various encryption standards (40-bit, 128-bit, AES-128, AES-256)
- ⚙️ **Customizable PDF Options**: Control page format, orientation, margins, and more
- 🔧 **Flexible Permissions**: Fine-grained control over PDF permissions (printing, copying, editing, etc.)
- 🚀 **Async Support**: Built with async/await for non-blocking operations
- 🔗 **External Tool Integration**: Optional integration with qpdf for stronger encryption

## Quick Start

Add this to your `Cargo.toml`:

```toml
[dependencies]
html2pdf-secure = "0.1"
tokio = { version = "1.0", features = ["full"] }
```

### Basic Usage

```rust
use html2pdf_secure::{Html2PdfConverter, PdfOptions, PasswordOptions};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Create converter
    let converter = Html2PdfConverter::new().await?;
    
    // HTML content
    let html = "<html><body><h1>Hello, Secure World!</h1></body></html>";
    
    // Configure password protection (uses AES-256 by default)
    let password_options = PasswordOptions::new("user123", "owner456");

    // Convert to protected PDF (requires qpdf)
    let pdf_data = converter
        .convert_html_to_protected_pdf(html, PdfOptions::default(), password_options)
        .await?;
    
    // Save to file
    std::fs::write("secure_document.pdf", pdf_data)?;
    
    Ok(())
}
```

## Installation Requirements

### Basic Requirements

- **Rust 1.85+**: Required for Rust 2024 edition features
- **Chrome/Chromium**: Automatically downloaded by headless_chrome crate

### Required: qpdf for Password Protection

**Important**: Password protection requires qpdf to be installed. Without qpdf, PDFs will be generated without encryption.

```bash
# Ubuntu/Debian
sudo apt-get install qpdf

# macOS
brew install qpdf

# Windows
# Download from https://qpdf.sourceforge.io/
```

To verify qpdf installation:
```bash
qpdf --version
```

## Examples

### Convert URL to Protected PDF

```rust
use html2pdf_secure::{Html2PdfConverter, PdfOptions, PasswordOptions, PageFormat};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let converter = Html2PdfConverter::new().await?;
    
    let pdf_options = PdfOptions {
        page_format: PageFormat::A4,
        print_background: true,
        ..Default::default()
    };
    
    let password_options = PasswordOptions::new("secret", "admin");
    
    let pdf_data = converter
        .convert_url_to_protected_pdf(
            "https://www.rust-lang.org/", 
            pdf_options, 
            password_options
        )
        .await?;
    
    std::fs::write("rust_website.pdf", pdf_data)?;
    Ok(())
}
```

### Advanced Configuration

```rust
use html2pdf_secure::{
    Html2PdfConverter, PdfOptions, PasswordOptions, 
    EncryptionLevel, PdfPermissions, PageFormat, PageOrientation
};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let converter = Html2PdfConverter::new().await?;
    
    // Advanced PDF options
    let pdf_options = PdfOptions {
        page_format: PageFormat::Letter,
        orientation: PageOrientation::Landscape,
        print_background: true,
        scale: 0.8,
        ..Default::default()
    };
    
    // Strong encryption with restricted permissions
    let password_options = PasswordOptions::new("user_pass", "owner_pass")
        .with_encryption_level(EncryptionLevel::Aes256)
        .with_permissions(PdfPermissions {
            allow_printing: false,
            allow_copy: false,
            allow_modify_contents: false,
            ..Default::default()
        });
    
    let html = "<html><body><h1>Highly Secure Document</h1></body></html>";
    
    // Use qpdf for strongest encryption (if available)
    let pdf_data = converter
        .convert_html_to_protected_pdf_with_qpdf(
            html, 
            pdf_options, 
            password_options, 
            Some("/tmp")
        )
        .await?;
    
    std::fs::write("highly_secure.pdf", pdf_data)?;
    Ok(())
}
```

## API Reference

### Core Types

- **`Html2PdfConverter`**: Main converter for HTML to PDF operations
- **`PdfOptions`**: Configuration for PDF generation (page size, margins, etc.)
- **`PasswordOptions`**: Password and encryption configuration
- **`EncryptionLevel`**: Encryption strength options
- **`PdfPermissions`**: Fine-grained permission control

### Conversion Methods

- `convert_html_to_pdf()`: Convert HTML string to PDF
- `convert_html_file_to_pdf()`: Convert HTML file to PDF
- `convert_url_to_pdf()`: Convert web page to PDF
- `convert_html_to_protected_pdf()`: Convert HTML to password-protected PDF
- `convert_html_to_protected_pdf_with_qpdf()`: Convert with qpdf encryption

## Encryption Levels

| Level | Description | Key Length | Security |
|-------|-------------|------------|----------|
| `Standard40` | RC4 40-bit | 40-bit | Basic |
| `Standard128` | RC4 128-bit | 128-bit | Good |
| `Aes128` | AES 128-bit | 128-bit | Strong |
| `Aes256` | AES 256-bit | 256-bit | Very Strong |

## Security Considerations

### Encryption Behavior

**Important**: This library requires qpdf for password protection:

- **With qpdf installed**: PDFs are properly encrypted with AES-256 by default
- **Without qpdf**: PDFs are generated **without encryption** and a warning is logged
- **Fallback behavior**: The library will attempt qpdf first, then fall back to unencrypted PDF

### Encryption Levels

The library supports multiple encryption levels when qpdf is available:

- **AES-256** (default): Strongest encryption, recommended for all use cases
- **AES-128**: Strong encryption, good for most applications
- **128-bit RC4**: Legacy encryption, requires `--allow-weak-crypto` flag
- **40-bit RC4**: Very weak encryption, requires `--allow-weak-crypto` flag

### Production Recommendations

For production use with sensitive data:
- **Always install qpdf** for proper encryption
- **Use AES-256** (default) or AES-128 encryption levels
- **Avoid RC4** encryption levels (weak and deprecated)
- **Test encryption** by verifying password requirements

## Error Handling

```rust
use html2pdf_secure::{Html2PdfConverter, Html2PdfError};

#[tokio::main]
async fn main() {
    let converter = Html2PdfConverter::new().await.unwrap();
    
    match converter.convert_html_to_pdf("<html></html>", Default::default()).await {
        Ok(pdf_data) => println!("Success: {} bytes", pdf_data.len()),
        Err(Html2PdfError::ChromeError(msg)) => eprintln!("Chrome error: {}", msg),
        Err(Html2PdfError::EncryptionError(msg)) => eprintln!("Encryption error: {}", msg),
        Err(e) => eprintln!("Other error: {}", e),
    }
}
```

## Examples

Run the included examples:

```bash
# Basic usage
cargo run --example basic_usage

# qpdf encryption (requires qpdf installed)
cargo run --example qpdf_encryption

# URL to PDF conversion
cargo run --example url_to_pdf
```

## Testing

Run the test suite:

```bash
cargo test
```

## Performance

The crate is designed for efficiency:
- Reuses Chrome instances when possible
- Supports concurrent PDF generation
- Minimal memory footprint for PDF processing

## Troubleshooting

### Chrome/Chromium Issues

If you encounter Chrome-related errors:
1. Ensure sufficient system resources
2. Check Chrome installation
3. Verify network connectivity for URL conversions

### qpdf Integration

If qpdf encryption fails:
1. Verify qpdf installation: `qpdf --version`
2. Check file permissions in temp directory
3. Ensure sufficient disk space

### Common Issues

- **"Chrome browser error"**: Usually indicates Chrome startup issues
- **"Encryption error"**: Check password requirements and qpdf availability
- **"Invalid input"**: Verify HTML syntax and file paths

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

### Development Setup

```bash
git clone https://github.com/yourusername/html2pdf-secure
cd html2pdf-secure
cargo build
cargo test
```

## License

This project is licensed under either of

- Apache License, Version 2.0, ([LICENSE-APACHE]LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license ([LICENSE-MIT]LICENSE-MIT or http://opensource.org/licenses/MIT)

at your option.