static string UrlEncode(string value, PhpQueryRfc type) { if (string.IsNullOrEmpty(value)) { return(string.Empty); } switch (type) { case PhpQueryRfc.RFC3986: // NOTE: this is not correct, // behavior depends on IRI configuration // see https://docs.microsoft.com/en-us/dotnet/api/system.uri.escapeuristring#remarks return(Uri.EscapeUriString(value)); case PhpQueryRfc.RFC1738: default: // ' ' encoded as '+' return(WebUtility.UrlEncode(value)); } }
static string http_build_query(Context ctx, PhpValue formData, string numericPrefix, string argSeparator, PhpQueryRfc encType, string indexerPrefix) { var result = new StringBuilder(64); var first = true; var enumerator = formData.GetForeachEnumerator(false, default); while (enumerator.MoveNext()) { var key = enumerator.CurrentKey; var value = enumerator.CurrentValue; // the query parameter name (key name) // the parameter name is URL encoded string keyName = key.IsLong(out var l) ? UrlEncode(numericPrefix, encType) + l.ToString() : UrlEncode(key.ToStringOrThrow(ctx), encType); if (indexerPrefix != null) { keyName = indexerPrefix + "%5B" + keyName + "%5D"; // == prefix[key] (url encoded brackets) } // write the query element if (value.IsPhpArray(out var valueArray)) { // value is an array, emit query recursively, use current keyName as an array variable name var queryStr = http_build_query(ctx, valueArray, null, argSeparator, encType, keyName); // emit the query recursively if (string.IsNullOrEmpty(queryStr) == false) { if (!first) { result.Append(argSeparator); } result.Append(queryStr); } } else { // simple value, emit query in a form of (key=value), URL encoded ! if (!first) { result.Append(argSeparator); } result.Append(keyName); result.Append("="); result.Append(UrlEncode(value.ToStringOrThrow(ctx), encType)); // == "keyName=keyValue" } // separator will be used in next loop first = false; } return(result.ToString()); }