Загрузка данных


$ErrorActionPreference = 'Stop'

$port = 8765
$ruleName = 'TEMP_Report_Share_8765'
$desktop = [Environment]::GetFolderPath('Desktop')
$reportNames = @('NETWORK_DIAG.txt', 'NETWORK_WFP_STATE.xml')

$isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole(
    [Security.Principal.WindowsBuiltInRole]::Administrator
)

if (-not $isAdmin) {
    $arguments = "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`""
    Start-Process powershell.exe -Verb RunAs -ArgumentList $arguments
    exit
}

$availableFiles = @{}
foreach ($name in $reportNames) {
    $path = Join-Path $desktop $name
    if (Test-Path -LiteralPath $path -PathType Leaf) {
        $availableFiles[$name] = $path
    }
}

if ($availableFiles.Count -eq 0) {
    Write-Host 'No report files were found on the Desktop.' -ForegroundColor Red
    Write-Host 'Expected: NETWORK_DIAG.txt or NETWORK_WFP_STATE.xml'
    Read-Host 'Press Enter to close'
    exit 1
}

function Send-Bytes {
    param(
        [Parameter(Mandatory)] $Context,
        [Parameter(Mandatory)] [byte[]] $Bytes,
        [Parameter(Mandatory)] [string] $ContentType,
        [string] $DownloadName
    )

    $Context.Response.StatusCode = 200
    $Context.Response.ContentType = $ContentType
    $Context.Response.ContentLength64 = $Bytes.Length
    $Context.Response.Headers.Add('Cache-Control', 'no-store')
    if ($DownloadName) {
        $Context.Response.Headers.Add('Content-Disposition', "attachment; filename=`"$DownloadName`"")
    }
    $Context.Response.OutputStream.Write($Bytes, 0, $Bytes.Length)
    $Context.Response.OutputStream.Close()
}

function Send-Text {
    param(
        [Parameter(Mandatory)] $Context,
        [Parameter(Mandatory)] [string] $Text,
        [string] $ContentType = 'text/html; charset=utf-8',
        [int] $StatusCode = 200
    )

    $bytes = [Text.Encoding]::UTF8.GetBytes($Text)
    $Context.Response.StatusCode = $StatusCode
    $Context.Response.ContentType = $ContentType
    $Context.Response.ContentLength64 = $bytes.Length
    $Context.Response.Headers.Add('Cache-Control', 'no-store')
    $Context.Response.OutputStream.Write($bytes, 0, $bytes.Length)
    $Context.Response.OutputStream.Close()
}

$links = foreach ($name in $reportNames) {
    if ($availableFiles.ContainsKey($name)) {
        $size = (Get-Item -LiteralPath $availableFiles[$name]).Length
        "<p><a class='button' href='/$name'>Download $name</a><br><small>$size bytes</small></p>"
    }
}

$indexHtml = @"
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Windows reports</title>
<style>
body{font-family:-apple-system,system-ui,sans-serif;max-width:650px;margin:40px auto;padding:0 20px;background:#f5f5f7;color:#111}
.card{background:white;border-radius:18px;padding:24px;box-shadow:0 4px 24px #0001}
.button{display:inline-block;background:#1677ff;color:white;padding:13px 17px;border-radius:11px;text-decoration:none;font-weight:600}
.stop{color:#b00020} small{color:#666}
</style>
</head>
<body><div class="card">
<h2>Windows diagnostic reports</h2>
<p>Tap a button to save the file on the iPhone.</p>
$($links -join "`n")
<hr>
<p><a class="stop" href="/stop">Stop server and close access</a></p>
</div></body></html>
"@

$listener = [Net.HttpListener]::new()
$listener.Prefixes.Add("http://+:$port/")

try {
    & netsh advfirewall firewall delete rule name="$ruleName" | Out-Null
    & netsh advfirewall firewall add rule name="$ruleName" dir=in action=allow protocol=TCP localport=$port profile=any | Out-Null

    $listener.Start()

    $addresses = Get-NetIPConfiguration -ErrorAction SilentlyContinue |
        Where-Object { $_.IPv4DefaultGateway -and $_.NetAdapter.Status -eq 'Up' } |
        ForEach-Object { $_.IPv4Address.IPAddress } |
        Where-Object { $_ -and $_ -notlike '169.254.*' } |
        Select-Object -Unique

    Clear-Host
    Write-Host 'LOCAL FILE SERVER IS RUNNING' -ForegroundColor Green
    Write-Host 'Connect the iPhone to the same Wi-Fi network.'
    Write-Host 'Open one of these addresses in Safari:' -ForegroundColor Cyan
    foreach ($address in $addresses) {
        Write-Host "  http://${address}:$port/" -ForegroundColor Yellow
    }
    Write-Host ''
    Write-Host 'After downloading, tap Stop server on the web page.'
    Write-Host 'You can also stop it with Ctrl+C.'

    while ($listener.IsListening) {
        $context = $listener.GetContext()
        $requestPath = [Uri]::UnescapeDataString($context.Request.Url.AbsolutePath.TrimStart('/'))

        if ([string]::IsNullOrWhiteSpace($requestPath)) {
            Send-Text -Context $context -Text $indexHtml
            continue
        }

        if ($requestPath -eq 'stop') {
            Send-Text -Context $context -Text '<h2>Server stopped. The files are no longer shared.</h2>'
            $listener.Stop()
            break
        }

        if ($availableFiles.ContainsKey($requestPath)) {
            $bytes = [IO.File]::ReadAllBytes($availableFiles[$requestPath])
            $contentType = if ($requestPath.EndsWith('.xml')) { 'application/xml' } else { 'text/plain; charset=utf-8' }
            Send-Bytes -Context $context -Bytes $bytes -ContentType $contentType -DownloadName $requestPath
            Write-Host "Downloaded: $requestPath" -ForegroundColor Green
            continue
        }

        Send-Text -Context $context -Text 'Not found' -ContentType 'text/plain; charset=utf-8' -StatusCode 404
    }
}
catch {
    Write-Host ''
    Write-Host "ERROR: $($_.Exception.Message)" -ForegroundColor Red
    Read-Host 'Press Enter to close'
}
finally {
    if ($listener.IsListening) {
        $listener.Stop()
    }
    $listener.Close()
    & netsh advfirewall firewall delete rule name="$ruleName" | Out-Null
    Write-Host 'Server stopped and temporary firewall rule removed.' -ForegroundColor Cyan
}