Beta Release

This commit is contained in:
2026-09-26 19:37:28 +02:00
parent adca4d9167
commit e77ccf2f33
29 changed files with 6819 additions and 293 deletions
+127
View File
@@ -0,0 +1,127 @@
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
namespace MSCO
{
/// <summary>
/// HTTPS-Abruf über Windows (WinHTTP). Unitys WWW in My Summer Car (Unity 5.0) kann nur TLS 1.0,
/// heutige Server verlangen TLS 1.2+. WinHTTP nutzt die TLS-Version des Betriebssystems
/// (unter Proton/Wine über GnuTLS). Blockierend - nur in einem Hintergrund-Thread aufrufen.
/// </summary>
public static class WinHttp
{
public static string Get(string url, int timeoutMs, out string error)
{
error = null;
IntPtr session = IntPtr.Zero, connect = IntPtr.Zero, request = IntPtr.Zero;
try
{
var uri = new Uri(url);
bool secure = uri.Scheme == "https";
session = WinHttpOpen("MSCO/" + MSCO.ModVersion, AccessTypeDefaultProxy, null, null, 0);
if (session == IntPtr.Zero) return Fail(out error, "WinHttpOpen");
WinHttpSetTimeouts(session, timeoutMs, timeoutMs, timeoutMs, timeoutMs);
// Ältere Windows-Versionen haben TLS 1.2 nicht standardmäßig an - ausdrücklich erlauben
int protocols = ProtocolTls12 | ProtocolTls13;
if (!WinHttpSetOption(session, OptionSecureProtocols, ref protocols, 4))
{
protocols = ProtocolTls12;
WinHttpSetOption(session, OptionSecureProtocols, ref protocols, 4);
}
connect = WinHttpConnect(session, uri.Host, (ushort)uri.Port, 0);
if (connect == IntPtr.Zero) return Fail(out error, "WinHttpConnect");
request = WinHttpOpenRequest(connect, "GET", uri.PathAndQuery, null, null, IntPtr.Zero, secure ? FlagSecure : 0);
if (request == IntPtr.Zero) return Fail(out error, "WinHttpOpenRequest");
if (!WinHttpSendRequest(request, null, 0, IntPtr.Zero, 0, 0, IntPtr.Zero)) return Fail(out error, "WinHttpSendRequest");
if (!WinHttpReceiveResponse(request, IntPtr.Zero)) return Fail(out error, "WinHttpReceiveResponse");
int status = 0, size = 4;
WinHttpQueryHeaders(request, QueryStatusCode | QueryFlagNumber, null, ref status, ref size, IntPtr.Zero);
if (status != 0 && status != 200)
{
error = "HTTP " + status;
return null;
}
using (var body = new MemoryStream())
{
var buffer = new byte[16 * 1024];
while (true)
{
int read;
if (!WinHttpReadData(request, buffer, buffer.Length, out read)) return Fail(out error, "WinHttpReadData");
if (read == 0) break;
body.Write(buffer, 0, read);
if (body.Length > 4 * 1024 * 1024) { error = "Response too large"; return null; }
}
return Encoding.UTF8.GetString(body.ToArray());
}
}
catch (Exception e)
{
error = e.Message;
return null;
}
finally
{
if (request != IntPtr.Zero) WinHttpCloseHandle(request);
if (connect != IntPtr.Zero) WinHttpCloseHandle(connect);
if (session != IntPtr.Zero) WinHttpCloseHandle(session);
}
}
static string Fail(out string error, string step)
{
int code = Marshal.GetLastWin32Error();
error = step + " failed (" + code + (code == 12175 ? ", secure connection failed" : code == 12002 ? ", timeout" : code == 12029 ? ", cannot connect" : "") + ")";
return null;
}
const int AccessTypeDefaultProxy = 0;
const int FlagSecure = 0x00800000;
const int OptionSecureProtocols = 84;
const int ProtocolTls12 = 0x00000800;
const int ProtocolTls13 = 0x00002000;
const int QueryStatusCode = 19;
const int QueryFlagNumber = 0x20000000;
[DllImport("winhttp.dll", SetLastError = true, CharSet = CharSet.Unicode)]
static extern IntPtr WinHttpOpen(string agent, int accessType, string proxy, string bypass, int flags);
[DllImport("winhttp.dll", SetLastError = true)]
static extern bool WinHttpSetTimeouts(IntPtr handle, int resolve, int connect, int send, int receive);
[DllImport("winhttp.dll", SetLastError = true)]
static extern bool WinHttpSetOption(IntPtr handle, int option, ref int value, int length);
[DllImport("winhttp.dll", SetLastError = true, CharSet = CharSet.Unicode)]
static extern IntPtr WinHttpConnect(IntPtr session, string server, ushort port, int reserved);
[DllImport("winhttp.dll", SetLastError = true, CharSet = CharSet.Unicode)]
static extern IntPtr WinHttpOpenRequest(IntPtr connect, string verb, string path, string version, string referrer,
IntPtr acceptTypes, int flags);
[DllImport("winhttp.dll", SetLastError = true, CharSet = CharSet.Unicode)]
static extern bool WinHttpSendRequest(IntPtr request, string headers, int headersLength, IntPtr optional,
int optionalLength, int totalLength, IntPtr context);
[DllImport("winhttp.dll", SetLastError = true)]
static extern bool WinHttpReceiveResponse(IntPtr request, IntPtr reserved);
[DllImport("winhttp.dll", SetLastError = true, CharSet = CharSet.Unicode)]
static extern bool WinHttpQueryHeaders(IntPtr request, int infoLevel, string name, ref int buffer, ref int bufferLength, IntPtr index);
[DllImport("winhttp.dll", SetLastError = true)]
static extern bool WinHttpReadData(IntPtr request, byte[] buffer, int toRead, out int read);
[DllImport("winhttp.dll", SetLastError = true)]
static extern bool WinHttpCloseHandle(IntPtr handle);
}
}