diff --git a/Huxley2/Connected Services/OpenLDBWS/BaseServiceItem.cs b/Huxley2/Connected Services/OpenLDBWS/BaseServiceItem.cs index 6e299df..aedaef5 100644 --- a/Huxley2/Connected Services/OpenLDBWS/BaseServiceItem.cs +++ b/Huxley2/Connected Services/OpenLDBWS/BaseServiceItem.cs @@ -3,6 +3,7 @@ using Microsoft.AspNetCore.WebUtilities; using System; using System.Diagnostics.CodeAnalysis; +using System.Globalization; namespace OpenLDBWS { @@ -45,7 +46,7 @@ public static Guid ToGuid(string serviceID) public static string FromGuid(Guid serviceGuid) { // reverse of ToGuid above - string guidString = serviceGuid.ToString("N"); + string guidString = serviceGuid.ToString("N", CultureInfo.InvariantCulture); string num = guidString.Substring(0, 7); // get digits string hexString = guidString.Substring(16, 16); // get letters byte[] bytes = Convert.FromHexString(hexString); diff --git a/Huxley2/Huxley2.csproj b/Huxley2/Huxley2.csproj index 30d5292..570056d 100644 --- a/Huxley2/Huxley2.csproj +++ b/Huxley2/Huxley2.csproj @@ -7,7 +7,7 @@ enable true Huxley2 - 2.0.3 + 2.0.4 © James Singleton diff --git a/Huxley2/Pages/Index.cshtml b/Huxley2/Pages/Index.cshtml index dae0d27..89a7187 100644 --- a/Huxley2/Pages/Index.cshtml +++ b/Huxley2/Pages/Index.cshtml @@ -567,9 +567,8 @@ various different encoders.

- This endpoint also accepts the GUID + This endpoint also accepts the GUID representation of the ID - as /, + and case sensitivity can cause trouble if you're not careful.

If the ID is a RID (a 15 digit long integer) then the staff API will be used. In this case a staff diff --git a/Huxley2/Services/ServiceDetailsService.cs b/Huxley2/Services/ServiceDetailsService.cs index bc45c51..462d454 100644 --- a/Huxley2/Services/ServiceDetailsService.cs +++ b/Huxley2/Services/ServiceDetailsService.cs @@ -33,28 +33,11 @@ LDBSVServiceSoap staffSoapClient public async Task GetServiceDetailsAsync(ServiceRequest request) { - // The (non-staff) Darwin API requires service ID to be a standard base 64 string - // As it's simply a GUID in base 64 there'll always be maximum padding (== suffix) - // %2F will still be escaped if from the route and not from the query but nothing else will - // https://docs.microsoft.com/en-us/aspnet/core/web-api/#binding-source-parameter-inference - request.ServiceId = request.ServiceId.Replace("%2F", "/", StringComparison.OrdinalIgnoreCase); - - if (request.ServiceId.Length == 24) - { - if (Convert.TryFromBase64String(request.ServiceId, new byte[16], out var length) && length == 16) - { - _logger.LogInformation($"Calling service details SOAP endpoint for {request.ServiceId}"); - var s = await _soapClient.GetServiceDetailsAsync(new GetServiceDetailsRequest - { - AccessToken = _accessTokenService.MakeAccessToken(request), - serviceID = request.ServiceId, - }); - return s.GetServiceDetailsResult; - } - } - - // If ID looks like a RID (15 decimal digit long base 10 integer) then use the staff API if configured + // Staff API + // Formatted as a 15 digit base-10 long // This appears to be the date and the UID (with the first character in decimal representation) + + // use the staff API if configured if (request.ServiceId.Length == 15 && long.TryParse(request.ServiceId, out _) && _accessTokenService.TryMakeStaffAccessToken(out var staffToken)) { @@ -68,6 +51,11 @@ public async Task GetServiceDetailsAsync(ServiceRequest request) return staffService.GetServiceDetailsResult; } + + // Public API + // 7 digit base-10 number and an up-to-8 character TIPLOC, + // padded with underscore characters + // We also accept the standard hexadecimal (base 16) GUID representation if (Guid.TryParse(request.ServiceId, out Guid sid)) { @@ -75,53 +63,32 @@ public async Task GetServiceDetailsAsync(ServiceRequest request) request.ServiceId = OpenLDBWS.BaseServiceItem.FromGuid(sid); } - // handle new-format version - // structure: 0000000XXXXXXX, where 0 is any numeric char and X is - // any alpha char or an underscore - if (request.ServiceId.Length == 15) - { - _logger.LogInformation($"Calling service details SOAP endpoint for {request.ServiceId}"); - var s = await _soapClient.GetServiceDetailsAsync(new GetServiceDetailsRequest - { - AccessToken = _accessTokenService.MakeAccessToken(request), - serviceID = request.ServiceId, - }); - return s.GetServiceDetailsResult; - } - // Support URL safe base 64 encoding as it's more suitable for this situation // https://en.wikipedia.org/wiki/Base64#The_URL_applications // https://tools.ietf.org/html/rfc4648#section-5 // Encoder available as part of ASP.NET Core: Microsoft.Extensions.WebEncoders // For more info read ASP.NET Core 2 High Performance (https://unop.uk/book) :) - - if (request.ServiceId.Length == 22) + if (request.ServiceId.Length == 20) { var sidBytes = WebEncoders.Base64UrlDecode(request.ServiceId); - if (sidBytes.Length == 16) + if (sidBytes.Length == 15) { - request.ServiceId = Convert.ToBase64String(sidBytes); + request.ServiceId = System.Text.Encoding.UTF8.GetString(sidBytes); } } - // If ID wasn't percent-encoded then it may be missing / + = - // We try to fix it up if it isn't the correct length - while (!request.ServiceId.EndsWith("==", StringComparison.OrdinalIgnoreCase)) - { - request.ServiceId += "="; - } - while (request.ServiceId.Length < 24) + if (request.ServiceId.Length == 15) { - request.ServiceId = "/" + request.ServiceId; + _logger.LogInformation($"Calling service details SOAP endpoint for {request.ServiceId}"); + var service = await _soapClient.GetServiceDetailsAsync(new GetServiceDetailsRequest + { + AccessToken = _accessTokenService.MakeAccessToken(request), + serviceID = request.ServiceId, + }); + return service.GetServiceDetailsResult; } - _logger.LogInformation($"Calling service details SOAP endpoint for {request.ServiceId}"); - var service = await _soapClient.GetServiceDetailsAsync(new GetServiceDetailsRequest - { - AccessToken = _accessTokenService.MakeAccessToken(request), - serviceID = request.ServiceId, - }); - return service.GetServiceDetailsResult; + throw new Exception("Invalid Service ID provided"); } public string GenerateChecksum(object service) => ChecksumGenerator.GenerateChecksum(service); diff --git a/Huxley2Tests/Services/ServiceDetailsServiceTests.cs b/Huxley2Tests/Services/ServiceDetailsServiceTests.cs index 1ba016f..8792e71 100644 --- a/Huxley2Tests/Services/ServiceDetailsServiceTests.cs +++ b/Huxley2Tests/Services/ServiceDetailsServiceTests.cs @@ -20,9 +20,29 @@ public class ServiceDetailsServiceTests private OpenLDBSVWS.LDBSVServiceSoap staffClient; private ServiceDetailsService service; + private string GenerateServiceId() + { + // generate a mock new-format serviceid + const string digitChars = "0123456789"; + const string locChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + var random = new System.Random(); + var sid_array = new char[15]; + for (int i = 0; i < 7; i++) + { + sid_array[i] = digitChars[random.Next(digitChars.Length)]; + } + for (int i = 8; i < 14; i++) + { + sid_array[i] = locChars[random.Next(locChars.Length)]; + } + sid_array[14] = '_'; + + return new String(sid_array); + } + public ServiceDetailsServiceTests() { - var sid = Convert.ToBase64String(Guid.NewGuid().ToByteArray()); + var sid = GenerateServiceId(); var cat = Guid.NewGuid().ToString(); dat = Guid.NewGuid().ToString(); restRequest = new ServiceRequest diff --git a/station_codes.csv b/station_codes.csv index a63f82d..9af4611 100644 --- a/station_codes.csv +++ b/station_codes.csv @@ -1,6 +1,5 @@ "stationName","crsCode" "Abbey Wood","ABW" -"Abbey Wood (Elizabeth line)","ABX" "Aber","ABE" "Abercynon","ACY" "Aberdare","ABA" @@ -868,6 +867,7 @@ "East Garforth","EGF" "East Grinstead","EGR" "East Kilbride","EKL" +"East Linton","ELT" "East Malling","EML" "East Midlands Airport (Bus)","EMA" "East Midlands Parkway","EMD" @@ -965,7 +965,6 @@ "Farningham Road","FNR" "Farnworth","FNW" "Farringdon","ZFD" -"Farringdon (Elizabeth line)","FDX" "Fauldhouse","FLD" "Faversham","FAV" "Faygate","FGT" @@ -1378,6 +1377,7 @@ "Inverkeithing","INK" "Inverkip","INP" "Inverness","INV" +"Inverness Airport","IVA" "Invershin","INH" "Inverurie","INR" "Ipswich","IPS" @@ -1571,7 +1571,6 @@ "Liverpool Landing Stage","LVS" "Liverpool Lime Street","LIV" "Liverpool South Parkway","LPY" -"Liverpool St. (Elizabeth line)","LSX" "Livingston North","LSN" "Livingston South","LVG" "Llanaber","LLA" @@ -1947,7 +1946,6 @@ "Oxford Parkway","OXP" "Oxshott","OXS" "Oxted","OXT" -"Paddington (Elizabeth line)","PDX" "Paddock Wood","PDW" "Padgate","PDG" "Padstow Bus Terminus","PDT" @@ -2785,7 +2783,6 @@ "White Hart Lane","WHL" "White Notley","WNY" "Whitechapel","ZLW" -"Whitechapel (Elizabeth line)","WHX" "Whitecraigs","WCR" "Whitehaven","WTH" "Whitehill Prince of Wales (Bus","WHH"