Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix double-absolute SpaceDock URLs #3466

Merged
merged 1 commit into from
Oct 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Netkan/CKAN-netkan.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@
<Compile Include="Sources\Jenkins\JenkinsOptions.cs" />
<Compile Include="Sources\Jenkins\JenkinsRef.cs" />
<Compile Include="Sources\Spacedock\ISpaceDock.cs" />
<Compile Include="Sources\Spacedock\JsonConvertFromRelativeSdUri.cs" />
<Compile Include="Sources\Spacedock\SDVersion.cs" />
<Compile Include="Sources\Spacedock\SpaceDockApi.cs" />
<Compile Include="Sources\Spacedock\SpacedockError.cs" />
Expand Down
65 changes: 65 additions & 0 deletions Netkan/Sources/Spacedock/JsonConvertFromRelativeSdUri.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
using System;
using System.Net;
using System.Text.RegularExpressions;
using CKAN.NetKAN.Services;
using log4net;
using Newtonsoft.Json;

namespace CKAN.NetKAN.Sources.Spacedock
{
/// <summary>
/// A simple helper class to prepend SpaceDock URLs.
/// </summary>
internal class JsonConvertFromRelativeSdUri : JsonConverter
{
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.Value != null)
return ExpandPath(reader.Value.ToString());
return null;

}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}

public override bool CanConvert(Type objectType)
{
throw new NotImplementedException();
}

/// <summary>
/// Returns the route with the SpaceDock URI (not the API URI) pre-pended.
/// </summary>
private static Uri ExpandPath(string route)
{
Log.DebugFormat("Expanding {0} to full SpaceDock URL", route);

// Alas, this isn't as simple as it may sound. For some reason
// some—but not all—SD mods don't work the same way if the path provided
// is escaped or un-escaped.

// Update: The Uri class under mono doesn't un-escape everything when
// .ToString() is called, even though the .NET documentation says that it
// should. Rather than using it and going through escaping hell, we'll simply
// concat our strings together and preserve escaping that way. If SD ever
// start returning fully qualified URLs then we should see everyting break
// pretty quickly, and we can rejoice because we won't need any of this code
// again. -- PJF, KSP-CKAN/CKAN#816.

// Step 1: Escape any spaces present. SD seems to escape everything else fine.
route = Regex.Replace(route, " ", "%20");

// Step 2: Trim leading slashes and prepend the SD host
var urlFixed = new Uri(SpacedockApi.SpacedockBase + route.TrimStart('/'));

// Step 3: Profit!
Log.DebugFormat("Expanded URL is {0}", urlFixed.OriginalString);
return urlFixed;
}

private static readonly ILog Log = LogManager.GetLogger(typeof(JsonConvertFromRelativeSdUri));
}
}
26 changes: 0 additions & 26 deletions Netkan/Sources/Spacedock/SDVersion.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,31 +69,5 @@ public override bool CanConvert(Type objectType)
throw new NotImplementedException();
}
}

/// <summary>
/// A simple helper class to prepend SpaceDock URLs.
/// </summary>
internal class JsonConvertFromRelativeSdUri : JsonConverter
{
public override object ReadJson(
JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer
)
{
if (reader.Value != null)
return SpacedockApi.ExpandPath(reader.Value.ToString());
return null;

}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}

public override bool CanConvert(Type objectType)
{
throw new NotImplementedException();
}
}
}
}
33 changes: 1 addition & 32 deletions Netkan/Sources/Spacedock/SpaceDockApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ internal sealed class SpacedockApi : ISpacedockApi
{
private static readonly ILog Log = LogManager.GetLogger(typeof(SpacedockApi));

private static readonly Uri SpacedockBase = new Uri("https://spacedock.info/");
public static readonly Uri SpacedockBase = new Uri("https://spacedock.info/");
private static readonly Uri SpacedockApiBase = new Uri(SpacedockBase, "/api/");

private readonly IHttpService _http;
Expand Down Expand Up @@ -57,37 +57,6 @@ public SpacedockMod GetMod(int modId)
return SpacedockMod.FromJson(json);
}

// TODO: DBB: Make this private
/// <summary>
/// Returns the route with the SpaceDock URI (not the API URI) pre-pended.
/// </summary>
public static Uri ExpandPath(string route)
{
Log.DebugFormat("Expanding {0} to full SpaceDock URL", route);

// Alas, this isn't as simple as it may sound. For some reason
// some—but not all—SD mods don't work the same way if the path provided
// is escaped or un-escaped.

// Update: The Uri class under mono doesn't un-escape everything when
// .ToString() is called, even though the .NET documentation says that it
// should. Rather than using it and going through escaping hell, we'll simply
// concat our strings together and preserve escaping that way. If SD ever
// start returning fully qualified URLs then we should see everyting break
// pretty quickly, and we can rejoice because we won't need any of this code
// again. -- PJF, KSP-CKAN/CKAN#816.

// Step 1: Escape any spaces present. SD seems to escape everything else fine.
route = Regex.Replace(route, " ", "%20");

// Step 2: Trim leading slashes and prepend the SD host
var urlFixed = new Uri(SpacedockBase + route.TrimStart('/'));

// Step 3: Profit!
Log.DebugFormat("Expanded URL is {0}", urlFixed.OriginalString);
return urlFixed;
}

private string Call(string path)
{
// TODO: There's got to be a better way than using regexps.
Expand Down
3 changes: 1 addition & 2 deletions Netkan/Sources/Spacedock/SpacedockMod.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ internal class SpacedockMod
[JsonProperty] public string source_code;
[JsonProperty] public int default_version_id;
[JsonProperty] public SpacedockUser[] shared_authors;
[JsonConverter(typeof(SDVersion.JsonConvertFromRelativeSdUri))]
public Uri background;

public SDVersion Latest()
Expand Down Expand Up @@ -46,7 +45,7 @@ public IEnumerable<SDVersion> All()
/// <returns>The home.</returns>
public Uri GetPageUrl()
{
return SpacedockApi.ExpandPath(string.Format("/mod/{0}/{1}", id, name));
return new Uri($"{SpacedockApi.SpacedockBase}mod/{id}/{name.Replace(" ", "%20")}");
}

public override string ToString()
Expand Down
5 changes: 4 additions & 1 deletion Tests/NetKAN/SDMod.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@ public void SD_Version_Select_214()
// GH #816: Ensure URLs with & are encoded correctly.
public string SD_URL_encode_816(string path)
{
return SpacedockApi.ExpandPath(path).OriginalString;
return SpacedockMod.FromJson(string.Format(
@"{{""name"":""Mod"",""id"":69420,""game"":""Kerbal Space Program"",""game_id"":3102,""short_description"":""A mod"",""description"":""A mod"",""downloads"":0,""followers"":0,""author"":""linuxgurugamer"",""default_version_id"":1,""shared_authors"":[],""background"":null,""bg_offset_y"":null,""license"":""MIT"",""website"":null,""donations"":null,""source_code"":null,""url"":""/mod/69420/Mod"",""versions"":[{{""friendly_version"":""1"",""game_version"":""1.12.2"",""id"":1,""created"":""2021-07-16T20:46:12.309009+00:00"",""download_path"":""{0}"",""changelog"":"""",""downloads"":0}}]}}",
path
)).versions[0].download_path.OriginalString;
}

[Test]
Expand Down