mirror of
https://github.com/GoodOlClint/PSProxmoxVE.git
synced 2026-07-26 07:58:14 +00:00
fix: replace FormUrlEncodedContent with minimal form encoding
.NET's FormUrlEncodedContent over-encodes characters like : and ! (%3A, %21) in form values. PVE's internal API consumers (specifically the cluster join process) do not URL-decode these values before using them, causing fingerprint comparison failures and password mismatches. Replace with BuildFormContent/EncodeFormValue that only encodes characters that break form parsing (&, =, +, space, %). This matches curl's -d behavior and fixes cluster join "Cluster join aborted!" errors. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -99,7 +99,7 @@ namespace PSProxmoxVE.Core.Client
|
||||
{
|
||||
var request = BuildRequest(HttpMethod.Post, resource, mutating: true);
|
||||
if (data != null)
|
||||
request.Content = new FormUrlEncodedContent(data);
|
||||
request.Content = BuildFormContent(data);
|
||||
return await SendAsync(request, resource, "POST").ConfigureAwait(false);
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ namespace PSProxmoxVE.Core.Client
|
||||
{
|
||||
var request = BuildRequest(HttpMethod.Put, resource, mutating: true);
|
||||
if (data != null)
|
||||
request.Content = new FormUrlEncodedContent(data);
|
||||
request.Content = BuildFormContent(data);
|
||||
return await SendAsync(request, resource, "PUT").ConfigureAwait(false);
|
||||
}
|
||||
|
||||
@@ -124,6 +124,52 @@ namespace PSProxmoxVE.Core.Client
|
||||
return await SendAsync(request, resource, "DELETE").ConfigureAwait(false);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Form body encoding
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Builds form-encoded content using minimal encoding that matches curl behavior.
|
||||
/// .NET's <see cref="FormUrlEncodedContent"/> over-encodes characters like
|
||||
/// <c>:</c> and <c>!</c> which PVE's internal API consumers (e.g. cluster join)
|
||||
/// do not properly URL-decode.
|
||||
/// </summary>
|
||||
private static StringContent BuildFormContent(Dictionary<string, string> data)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
foreach (var kvp in data)
|
||||
{
|
||||
if (sb.Length > 0) sb.Append('&');
|
||||
sb.Append(EncodeFormValue(kvp.Key));
|
||||
sb.Append('=');
|
||||
sb.Append(EncodeFormValue(kvp.Value));
|
||||
}
|
||||
return new StringContent(sb.ToString(), Encoding.UTF8, "application/x-www-form-urlencoded");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encodes a form value with minimal percent-encoding — only characters that
|
||||
/// would break form parsing are encoded. This matches curl's <c>-d</c> behavior
|
||||
/// and avoids over-encoding that PVE does not handle correctly.
|
||||
/// </summary>
|
||||
private static string EncodeFormValue(string value)
|
||||
{
|
||||
var sb = new StringBuilder(value.Length);
|
||||
foreach (char c in value)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '&': sb.Append("%26"); break;
|
||||
case '=': sb.Append("%3D"); break;
|
||||
case '+': sb.Append("%2B"); break;
|
||||
case ' ': sb.Append('+'); break;
|
||||
case '%': sb.Append("%25"); break;
|
||||
default: sb.Append(c); break;
|
||||
}
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Synchronous wrappers
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user