Skip to content

Commit 6ef451f

Browse files
committed
fix(Core): correct CustomUploaderItem parsing logic
1 parent 73f86ee commit 6ef451f

9 files changed

Lines changed: 142 additions & 156 deletions

File tree

SnapX.Core/Upload/Custom/CustomUploaderInput.cs

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,8 @@
44

55
namespace SnapX.Core.Upload.Custom;
66

7-
public class CustomUploaderInput
7+
public record CustomUploaderInput(string? FileName, string? Input)
88
{
9-
public string? FileName { get; set; }
10-
public string? Input { get; set; }
11-
12-
public CustomUploaderInput(string? fileName, string? input)
13-
{
14-
FileName = fileName;
15-
Input = input;
16-
}
9+
public string? FileName { get; set; } = FileName;
10+
public string? Input { get; set; } = Input;
1711
}

SnapX.Core/Upload/Custom/CustomUploaderItem.cs

Lines changed: 100 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,12 @@
1111
using SnapX.Core.Upload.Utils;
1212
using SnapX.Core.Utils;
1313
using SnapX.Core.Utils.Extensions;
14+
using SnapX.Core.Utils.Miscellaneous;
1415
using SnapX.Core.Utils.Parsers;
1516

1617
namespace SnapX.Core.Upload.Custom;
1718

18-
public class CustomUploaderItem
19+
public record CustomUploaderItem
1920
{
2021
[DefaultValue("")]
2122
public string Version { get; set; }
@@ -24,48 +25,50 @@ public class CustomUploaderItem
2425
public string? Name { get; set; }
2526

2627
public bool ShouldSerializeName() => !string.IsNullOrEmpty(Name) && Name != URLHelpers.GetHostName(RequestURL);
27-
28+
[JsonConverter(typeof(JsonStringEnumConverter))]
2829
[DefaultValue(CustomUploaderDestinationType.None)]
2930
public CustomUploaderDestinationType DestinationType { get; set; }
30-
31+
[JsonConverter(typeof(HttpMethodConverter))]
32+
[JsonInclude]
33+
// System.Text.Json does not automatically apply custom converters to built-in reference types like HttpMethod,
34+
// even if the converter is registered globally.
35+
// To ensure the converter is used during serialization and deserialization,
36+
// we must explicitly declare [JsonConverter(typeof(HttpMethodConverter))] on the property or type.
3137
public HttpMethod RequestMethod { get; set; } = HttpMethod.Post;
3238

33-
// TEMP: For backward compatibility
34-
[JsonPropertyName("RequestType")]
35-
private HttpMethod RequestType { set => RequestMethod = value; }
36-
3739
[DefaultValue("")]
3840
public string? RequestURL { get; set; }
3941

4042
[DefaultValue(null)]
41-
public Dictionary<string, string?> Parameters { get; set; }
43+
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
44+
public Dictionary<string, string?>? Parameters { get; set; }
4245

43-
public bool ShouldSerializeParameters() => Parameters != null && Parameters.Count > 0;
46+
public bool ShouldSerializeParameters() => Parameters is { Count: > 0 };
4447

45-
[DefaultValue(null)]
48+
[DefaultValue(null)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
4649
public Dictionary<string, string?> Headers { get; set; }
4750

48-
public bool ShouldSerializeHeaders() => Headers != null && Headers.Count > 0;
49-
51+
public bool ShouldSerializeHeaders() => Headers is { Count: > 0 };
52+
[JsonConverter(typeof(JsonStringEnumConverter))]
5053
[DefaultValue(CustomUploaderBody.None)]
5154
public CustomUploaderBody Body { get; set; }
5255

53-
[DefaultValue(null)]
56+
[DefaultValue(null)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
5457
public Dictionary<string, string?>? Arguments { get; set; }
5558

5659
public bool ShouldSerializeArguments() => (Body == CustomUploaderBody.MultipartFormData || Body == CustomUploaderBody.FormURLEncoded) &&
57-
Arguments != null && Arguments.Count > 0;
60+
Arguments is { Count: > 0 };
5861

59-
[DefaultValue("")]
60-
public string FileFormName { get; set; }
62+
[DefaultValue("")] public string FileFormName { get; set; } = "";
6163

6264
public bool ShouldSerializeFileFormName() => Body == CustomUploaderBody.MultipartFormData && !string.IsNullOrEmpty(FileFormName);
6365

64-
[DefaultValue("")]
66+
[DefaultValue(null)]
67+
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
6568
public string? Data { get; set; }
6669

6770
public bool ShouldSerializeData() => (Body == CustomUploaderBody.JSON || Body == CustomUploaderBody.XML) && !string.IsNullOrEmpty(Data);
68-
71+
[JsonConverter(typeof(JsonStringEnumConverter))]
6972
// TEMP: For backward compatibility
7073
public ResponseType ResponseType { private get; set; }
7174

@@ -126,29 +129,31 @@ public string GetFileName()
126129
throw new Exception("Custom uploader RequestURL must be configured.");
127130
}
128131

129-
ShareXCustomUploaderSyntaxParser parser = new ShareXCustomUploaderSyntaxParser(input);
130-
parser.URLEncode = true;
131-
string? url = parser.Parse(RequestURL);
132+
var parser = new ShareXCustomUploaderSyntaxParser(input)
133+
{
134+
URLEncode = true
135+
};
136+
var url = parser.Parse(RequestURL);
132137

133138
url = URLHelpers.FixPrefix(url);
134139

135-
Dictionary<string, string?> parameters = GetParameters(input);
140+
var parameters = GetParameters(input);
136141
return URLHelpers.CreateQueryString(url, parameters);
137142
}
138143

139144
public Dictionary<string, string?> GetParameters(CustomUploaderInput input)
140145
{
141146
Dictionary<string, string?> parameters = [];
142147

143-
if (Parameters != null)
148+
if (Parameters == null) return parameters;
149+
var parser = new ShareXCustomUploaderSyntaxParser(input)
144150
{
145-
ShareXCustomUploaderSyntaxParser parser = new ShareXCustomUploaderSyntaxParser(input);
146-
parser.UseNameParser = true;
151+
UseNameParser = true
152+
};
147153

148-
foreach (KeyValuePair<string, string?> parameter in Parameters)
149-
{
150-
parameters.Add(parameter.Key, parser.Parse(parameter.Value));
151-
}
154+
foreach (KeyValuePair<string, string?> parameter in Parameters)
155+
{
156+
parameters.Add(parameter.Key, parser.Parse(parameter.Value));
152157
}
153158

154159
return parameters;
@@ -222,8 +227,10 @@ public string GetFileFormName()
222227

223228
if (Arguments != null)
224229
{
225-
var parser = new ShareXCustomUploaderSyntaxParser(input);
226-
parser.UseNameParser = true;
230+
var parser = new ShareXCustomUploaderSyntaxParser(input)
231+
{
232+
UseNameParser = true
233+
};
227234

228235
foreach (KeyValuePair<string, string?> arg in Arguments)
229236
{
@@ -236,12 +243,14 @@ public string GetFileFormName()
236243

237244
public NameValueCollection GetHeaders(CustomUploaderInput input)
238245
{
239-
if (Headers != null && Headers.Count > 0)
246+
if (Headers is { Count: > 0 })
240247
{
241248
var collection = new NameValueCollection();
242249

243-
var parser = new ShareXCustomUploaderSyntaxParser(input);
244-
parser.UseNameParser = true;
250+
var parser = new ShareXCustomUploaderSyntaxParser(input)
251+
{
252+
UseNameParser = true
253+
};
245254

246255
foreach (KeyValuePair<string, string?> header in Headers)
247256
{
@@ -256,62 +265,57 @@ public NameValueCollection GetHeaders(CustomUploaderInput input)
256265

257266
public void ParseResponse(UploadResult result, ResponseInfo responseInfo, UploaderErrorManager errors, CustomUploaderInput input, bool isShortenedURL = false)
258267
{
259-
if (result != null && responseInfo != null)
260-
{
261-
result.ResponseInfo = responseInfo;
268+
if (result == null || responseInfo == null) return;
269+
result.ResponseInfo = responseInfo;
262270

263-
if (responseInfo.ResponseText == null)
264-
{
265-
responseInfo.ResponseText = "";
266-
}
267-
268-
var parser = new ShareXCustomUploaderSyntaxParser()
269-
{
270-
FileName = input.FileName,
271-
ResponseInfo = responseInfo,
272-
URLEncode = true
273-
};
271+
responseInfo.ResponseText ??= "";
274272

275-
if (responseInfo.IsSuccess)
276-
{
277-
string? url;
273+
var parser = new ShareXCustomUploaderSyntaxParser()
274+
{
275+
FileName = input.FileName,
276+
ResponseInfo = responseInfo,
277+
URLEncode = true
278+
};
278279

279-
if (!string.IsNullOrEmpty(URL))
280-
{
281-
url = parser.Parse(URL);
280+
if (responseInfo.IsSuccess)
281+
{
282+
string? url;
282283

283-
if (string.IsNullOrEmpty(url) && !string.IsNullOrEmpty(URL) && URL.Contains("{output:"))
284-
{
285-
result.IsURLExpected = false;
286-
}
287-
}
288-
else
289-
{
290-
url = parser.ResponseInfo.ResponseText;
291-
}
284+
if (!string.IsNullOrEmpty(URL))
285+
{
286+
url = parser.Parse(URL);
292287

293-
if (isShortenedURL)
288+
if (string.IsNullOrEmpty(url) && !string.IsNullOrEmpty(URL) && URL.Contains("{output:"))
294289
{
295-
result.ShortenedURL = url;
296-
}
297-
else
298-
{
299-
result.URL = url;
290+
result.IsURLExpected = false;
300291
}
292+
}
293+
else
294+
{
295+
url = parser.ResponseInfo.ResponseText;
296+
}
301297

302-
result.ThumbnailURL = parser.Parse(ThumbnailURL);
303-
result.DeletionURL = parser.Parse(DeletionURL);
298+
if (isShortenedURL)
299+
{
300+
result.ShortenedURL = url;
304301
}
305302
else
306303
{
307-
if (!string.IsNullOrEmpty(ErrorMessage))
308-
{
309-
string? parsedErrorMessage = parser.Parse(ErrorMessage);
304+
result.URL = url;
305+
}
310306

311-
if (!string.IsNullOrEmpty(parsedErrorMessage))
312-
{
313-
errors.AddFirst(parsedErrorMessage);
314-
}
307+
result.ThumbnailURL = parser.Parse(ThumbnailURL);
308+
result.DeletionURL = parser.Parse(DeletionURL);
309+
}
310+
else
311+
{
312+
if (!string.IsNullOrEmpty(ErrorMessage))
313+
{
314+
string? parsedErrorMessage = parser.Parse(ErrorMessage);
315+
316+
if (!string.IsNullOrEmpty(parsedErrorMessage))
317+
{
318+
errors.AddFirst(parsedErrorMessage);
315319
}
316320
}
317321
}
@@ -353,10 +357,7 @@ public void CheckBackwardCompatibility()
353357

354358
if (Arguments != null)
355359
{
356-
if (Parameters == null)
357-
{
358-
Parameters = [];
359-
}
360+
Parameters ??= [];
360361

361362
foreach (KeyValuePair<string, string?> pair in Arguments)
362363
{
@@ -481,38 +482,28 @@ public void CheckBackwardCompatibility()
481482

482483
private void CheckRequestURL()
483484
{
484-
if (!string.IsNullOrEmpty(RequestURL))
485-
{
486-
var nvc = URLHelpers.ParseQueryString(RequestURL);
485+
if (string.IsNullOrEmpty(RequestURL)) return;
486+
var nvc = URLHelpers.ParseQueryString(RequestURL);
487487

488-
if (nvc != null && nvc.Count > 0)
489-
{
490-
if (Parameters == null)
491-
{
492-
Parameters = [];
493-
}
488+
if (nvc is not { Count: > 0 }) return;
489+
Parameters ??= [];
494490

495-
foreach (string key in nvc)
491+
foreach (string key in nvc)
492+
{
493+
if (key == null)
494+
{
495+
foreach (string value in nvc.GetValues(key))
496496
{
497-
if (key == null)
498-
{
499-
foreach (string value in nvc.GetValues(key))
500-
{
501-
if (!Parameters.ContainsKey(value))
502-
{
503-
Parameters.Add(value, "");
504-
}
505-
}
506-
}
507-
else if (!Parameters.ContainsKey(key))
508-
{
509-
string value = nvc[key];
510-
Parameters.Add(key, value);
511-
}
497+
Parameters.TryAdd(value, "");
512498
}
513-
514-
RequestURL = URLHelpers.RemoveQueryString(RequestURL);
499+
}
500+
else if (!Parameters.ContainsKey(key))
501+
{
502+
var value = nvc[key];
503+
Parameters.Add(key, value);
515504
}
516505
}
506+
507+
RequestURL = URLHelpers.RemoveQueryString(RequestURL);
517508
}
518509
}

SnapX.Core/Upload/Custom/Functions/CustomUploaderFunction.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ internal abstract class CustomUploaderFunction
88
{
99
public abstract string Name { get; }
1010

11-
public virtual string[] Aliases { get; }
11+
public virtual string[]? Aliases { get; }
1212

1313
public virtual int MinParameterCount { get; } = 0;
1414

SnapX.Core/Upload/Custom/Functions/CustomUploaderFunctionJson.cs

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,22 +31,18 @@ internal class CustomUploaderFunctionJson : CustomUploaderFunction
3131
else
3232
{
3333
// {json:jsonPath}
34-
input = parser.ResponseInfo.ResponseText;
34+
input = parser.ResponseInfo?.ResponseText;
3535
jsonPath = parameters[0];
3636
}
3737

38-
if (!string.IsNullOrEmpty(input) && !string.IsNullOrEmpty(jsonPath))
38+
if (string.IsNullOrEmpty(input) || string.IsNullOrEmpty(jsonPath)) return null;
39+
if (!jsonPath.StartsWith("$."))
3940
{
40-
if (!jsonPath.StartsWith("$."))
41-
{
42-
jsonPath = "$." + jsonPath;
43-
}
44-
var json = JsonPath.Parse(jsonPath);
45-
var parsed = JsonNode.Parse(input);
46-
return json.Evaluate(parsed).ToString();
47-
41+
jsonPath = "$." + jsonPath;
4842
}
43+
var json = JsonPath.Parse(jsonPath);
44+
var parsed = JsonNode.Parse(input);
45+
return json.Evaluate(parsed).ToString();
4946

50-
return null;
5147
}
5248
}

0 commit comments

Comments
 (0)