Please note that this script can only remove the password-protected editing restriction.

#Requires -Version 5.1
<#
.SYNOPSIS
    A script to process a Word document, remove document protection, and restore its original file format.

.DESCRIPTION
    This script performs a three-stage process on a Word document provided via command-line.
    It correctly handles both relative and absolute file paths.

    Stage 1: Converts legacy '.doc' files to the modern '.docx' format if necessary.
    Stage 2: Treats the .docx file as a ZIP archive to modify its internal 'word/settings.xml'.
             It removes the entire '<w:documentProtection>...</w:documentProtection>' XML node from this file.
    Stage 3: If the original file was a '.doc', it converts the modified '.docx' file back
             to the '.doc' format, preserving the original filename.

    IMPORTANT:
    - You must have Microsoft Word installed for the conversion steps.
    - The .NET Framework 4.5 or higher is required for the ZIP manipulation functions.

.PARAMETER InputFilePath
    The full or relative path to the Word document you want to process.

.EXAMPLE
    # Using a full path
    .\Process-WordDoc.ps1 -InputFilePath "C:\Shared\ProtectedReport.docx"

.EXAMPLE
    # Using a relative path from the script's location
    .\Process-WordDoc.ps1 -InputFilePath "..\Reports\LegacyProtected.doc"
#>

# --- PARAMETERS ---
param (
    [Parameter(Mandatory = $true, HelpMessage = "Please provide the full or relative path to the Word document.")]
    [ValidateScript({
        if (-not (Test-Path $_ -PathType Leaf)) {
            throw "File not found at path: $_"
        }
        return $true
    })]
    [string]$InputFilePath
)

# --- SCRIPT INITIALIZATION ---
# Convert the provided path (which could be relative) to a fully qualified absolute path.
# This is crucial for ensuring the Word COM object and other file operations work reliably.
$InputFilePath = (Resolve-Path -LiteralPath $InputFilePath).ProviderPath
Write-Host "Processing absolute file path: $InputFilePath"


# This flag tracks if the original file was a .doc format.
$wasOriginallyDoc = $false
# This variable will hold the path to the .docx file we need to modify.
$targetDocxPath = $InputFilePath


# --- STAGE 1: CONVERT .DOC TO .DOCX (IF NECESSARY) ---

if ([System.IO.Path]::GetExtension($InputFilePath).ToLower() -eq ".doc") {
    $wasOriginallyDoc = $true
    Write-Host "Stage 1: Legacy '.doc' format detected. Starting conversion."
    $word = $null
    $doc = $null
    try {
        $word = New-Object -ComObject Word.Application
        $word.Visible = $false
        $targetDocxPath = $InputFilePath -replace '\.doc$', '.docx'
        $doc = $word.Documents.Open($InputFilePath)
        $wdFormatXMLDocument = 12 # Constant for .docx format
        $doc.SaveAs2($targetDocxPath, $wdFormatXMLDocument)
        Write-Host "Successfully converted and saved file to: $targetDocxPath"
    }
    catch {
        Write-Error "An error occurred during the Word conversion process: $_"
        return # Stop the script if conversion fails.
    }
    finally {
        if ($doc) { $doc.Close($false) }
        if ($word) { $word.Quit() }
        if ($doc) { [System.Runtime.InteropServices.Marshal]::ReleaseComObject($doc) | Out-Null }
        if ($word) { [System.Runtime.InteropServices.Marshal]::ReleaseComObject($word) | Out-Null }
        Remove-Variable doc, word -ErrorAction SilentlyContinue
    }
}
else {
    Write-Host "Stage 1: File is already a .docx. No conversion necessary."
}


# --- STAGE 2: MODIFY SETTINGS.XML WITHIN THE .DOCX ARCHIVE ---

Write-Host "Stage 2: Modifying internal XML for file: $targetDocxPath"

# Explicitly load the assembly containing the ZipFile class.
# This resolves the "Unable to find type" error on systems where it's not loaded by default.
try {
    Add-Type -AssemblyName System.IO.Compression.FileSystem
}
catch {
    Write-Error "Failed to load the System.IO.Compression.FileSystem assembly. This script requires .NET Framework 4.5 or higher."
    return
}


$tempDir = Join-Path ([System.IO.Path]::GetTempPath()) ([System.Guid]::NewGuid().ToString())
New-Item -Path $tempDir -ItemType Directory -Force | Out-Null
try {
    Write-Host "Extracting archive to temporary location..."
    [System.IO.Compression.ZipFile]::ExtractToDirectory($targetDocxPath, $tempDir)
    $settingsXmlPath = Join-Path $tempDir "word\settings.xml"

    if (Test-Path $settingsXmlPath) {
        Write-Host "Found word/settings.xml. Attempting to remove document protection node."
        $xml = [xml](Get-Content $settingsXmlPath)
        $nsm = New-Object System.Xml.XmlNamespaceManager($xml.NameTable)
        $nsm.AddNamespace("w", "http://schemas.openxmlformats.org/wordprocessingml/2006/main")
        
        # Find the <w:documentProtection> node using the namespace manager.
        $protectionNode = $xml.SelectSingleNode("//w:documentProtection", $nsm)

        if ($protectionNode) {
            # If the node is found, remove it from its parent.
            $protectionNode.ParentNode.RemoveChild($protectionNode) | Out-Null
            $xml.Save($settingsXmlPath)
            Write-Host "Successfully removed <w:documentProtection> node and saved changes."
        }
        else {
            Write-Host "<w:documentProtection> node not found. No changes made."
        }
    }
    else {
        Write-Host "File 'word/settings.xml' does not exist in the archive. Skipping modification."
    }

    Write-Host "Re-compressing archive..."
    if (Test-Path $targetDocxPath) { Remove-Item $targetDocxPath -Force }
    [System.IO.Compression.ZipFile]::CreateFromDirectory($tempDir, $targetDocxPath)
    Write-Host "Successfully updated the Word document."
}
catch {
    Write-Error "An error occurred during the ZIP archive manipulation: $_"
}
finally {
    if (Test-Path $tempDir) {
        Remove-Item -Path $tempDir -Recurse -Force
        Write-Host "Temporary files have been cleaned up."
    }
}

# --- STAGE 3: CONVERT BACK TO .DOC (IF NECESSARY) ---

if ($wasOriginallyDoc) {
    Write-Host "Stage 3: Original file was '.doc'. Converting back."
    $word = $null
    $doc = $null
    try {
        $word = New-Object -ComObject Word.Application
        $word.Visible = $false
        $doc = $word.Documents.Open($targetDocxPath)
        $wdFormatDocument = 0 # Constant for .doc format
        $doc.SaveAs2($InputFilePath, $wdFormatDocument) # Save back to original filename
        Write-Host "Successfully converted back and saved to: $InputFilePath"
    }
    catch {
        Write-Error "An error occurred during the final conversion back to .doc: $_"
    }
    finally {
        if ($doc) { $doc.Close($false) }
        if ($word) { $word.Quit() }
        if ($doc) { [System.Runtime.InteropServices.Marshal]::ReleaseComObject($doc) | Out-Null }
        if ($word) { [System.Runtime.InteropServices.Marshal]::ReleaseComObject($word) | Out-Null }
        Remove-Variable doc, word -ErrorAction SilentlyContinue

        # Clean up the intermediate .docx file.
        if (Test-Path $targetDocxPath) {
            Remove-Item $targetDocxPath -Force
            Write-Host "Cleaned up intermediate .docx file."
        }
    }
}

Write-Host "Processing complete."