src/common/details/helpers/url_helpers.cs (256 lines of code) (raw):

// // Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE.md file in the project root for full license information. // using System; using System.IO; using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Net; using System.Collections.Generic; using System.Text.Json; namespace Azure.AI.Details.Common.CLI { [Flags] public enum IdKind { None = 0, Guid = 1, FlatDateTime = 2, Name = 4, Id = 8 } public class IdHelpers { public static string IdFromString(string value, IdKind kind = IdKind.Guid) { if ((kind & IdKind.Guid) != 0) { var match = Regex.Match(value, guidPatternEnd); return match.Success ? match.Value : string.Empty; } if ((kind & IdKind.FlatDateTime) != 0) { var match = Regex.Match(value, flatDateTimePatternEnd); return match.Success ? match.Value : string.Empty; } if ((kind & IdKind.Name) != 0) { var match = Regex.Match(value, namePatternEnd); return match.Success ? match.Value : string.Empty; } return string.Empty; } public static string GetIdFromNamedValue(ICommandValues values, string name, string defaultValue = "") { var value = values.GetOrDefault(name, defaultValue); return IdHelpers.IdFromString(value!); } public static void CheckWriteOutputNameOrId(string nameOrId, INamedValues values, string domain, IdKind kind) { var atIdName = kind == IdKind.Name ? $"{domain}.output.name" : $"{domain}.output.id"; var atId = values.GetOrEmpty(atIdName); var atIdOk = !string.IsNullOrEmpty(atId); if (atIdOk) { var atIdFile = FileHelpers.GetOutputDataFileName(atId, values)!; FileHelpers.WriteAllText(atIdFile, nameOrId, Encoding.UTF8); values.Reset(atIdName); // once we wrote it, don't try to again } var addIdName = kind == IdKind.Name ? $"{domain}.output.add.name" : $"{domain}.output.add.id"; var addId = values.GetOrEmpty(addIdName); var addIdOk = !string.IsNullOrEmpty(addId); if (addIdOk) { var addIdFile = FileHelpers.GetOutputDataFileName(addId, values)!; FileHelpers.AppendAllText(addIdFile, "\n" + nameOrId, Encoding.UTF8); values.Reset(addIdName); // once we wrote it, don't try to again } } public static void CheckWriteOutputNameOrId(string json, string nameOrIdName, INamedValues values, string domain, IdKind kind) { var parsed = JsonDocument.Parse(json); var value = parsed.GetPropertyElementOrNull(nameOrIdName); var nameOrId = value?.GetString(); if (nameOrId != null) { CheckWriteOutputNameOrId(nameOrId, values, domain, kind); } } public static void CheckWriteOutputNamesOrIds<T>(IEnumerable<T> items, ICommandValues values, string domain, IdKind kind, Func<T, string> func) { var outKey = kind == IdKind.Name ? $"{domain}.output.names" : $"{domain}.output.ids"; var outVal = values.GetOrEmpty(outKey); var outOk = !string.IsNullOrEmpty(outVal); if (outOk) { var atFile = FileHelpers.GetOutputDataFileName(outVal, values)!; var namesOrIds = string.Join('\n', items.Select(func)); FileHelpers.WriteAllText(atFile, namesOrIds, Encoding.UTF8); values.Reset(outKey); // once we wrote it, don't try to again } var addKey = kind == IdKind.Name ? $"{domain}.output.add.names" : $"{domain}.output.add.ids"; var addVal = values.GetOrEmpty(addKey); var addOk = !string.IsNullOrEmpty(addVal); if (addOk) { var addFile = FileHelpers.GetOutputDataFileName(addVal, values)!; var namesOrIds = string.Join('\n', items.Select(func)); FileHelpers.AppendAllText(addFile, "\n" + namesOrIds, Encoding.UTF8); values.Reset(addKey); // once we wrote it, don't try to again } } #region private data private static readonly string guidPatternEnd = "([0-9A-Fa-f]{8}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{12})$"; private static readonly string flatDateTimePatternEnd = "((?#year)20[0-9][0-9])((?#month)(0[1-9])|(1[0-2]))((?#day)(0[1-9])|([12][0-9])|(3[0-1]))((?#time)[0-9]{10})$"; private static readonly string namePatternEnd = "(?<=[/\\\\])[^/\\\\]+$"; #endregion } public class UrlHelpers { public static string ContinueWithQueryString(string name, string value) { return $"&{name}={value}"; } public static string ContinueWithQueryString(string name, INamedValues values, string valueName) { var value = values.GetOrEmpty(valueName); return ContinueWithQueryString(name, value); } public static string ContinueWithQueryStringOrEmpty(string name, string value) { return !string.IsNullOrEmpty(value) ? ContinueWithQueryString(name, value) : ""; } public static string ContinueWithQueryStringOrEmpty(string name, INamedValues values, string valueName) { var value = values.GetOrEmpty(valueName); return ContinueWithQueryStringOrEmpty(name, value); } public static string IdFromUrl(string value, IdKind kinds = IdKind.Guid) { return IdHelpers.IdFromString(value, kinds); } public static string CheckWriteOutputUrlOrId(string url, INamedValues values, string domain, IdKind kinds = IdKind.Guid) { CheckWriteOutputUrl(url, values, domain); CheckWriteOutputId(url, values, domain, kinds); return url; } public static string? CheckWriteOutputUrlOrId(string json, string urlName, INamedValues values, string domain, IdKind kinds = IdKind.Guid) { var parsed = JsonDocument.Parse(json); var value = parsed?.GetPropertyElementOrNull(urlName); var url = value?.GetString(); return url != null ? CheckWriteOutputUrlOrId(url!, values, domain, kinds) : null; } public static void CheckWriteOutputUrlsOrIds(string json, string arrayName, string urlName, INamedValues values, string domain, IdKind kinds = IdKind.Guid) { var urls = new List<string>(); var ids = new List<string>(); GetUrlsOrIds(json, arrayName, urlName, urls, ids, kinds); CheckWriteOutputUrlsOrIds(values, domain, urls, ids, kinds); } public static void CheckWriteOutputUrlsOrIds(INamedValues values, string domain, List<string> urls, List<string> ids, IdKind kind) { var atUrlsName = $"{domain}.output.urls"; var atUrls = values.GetOrEmpty(atUrlsName); var atUrlsOk = !string.IsNullOrEmpty(atUrls); var atIdsName = kind == IdKind.Name ? $"{domain}.output.names" : $"{domain}.output.ids"; var atIds = values.GetOrEmpty(atIdsName); var atIdsOk = !string.IsNullOrEmpty(atIds); if (atUrlsOk) { var atUrlsFile = FileHelpers.GetOutputDataFileName(atUrls, values)!; FileHelpers.WriteAllLines(atUrlsFile, urls, new UTF8Encoding(false)); values.Reset(atUrlsName); // only write once } if (atIdsOk) { var atIdsFile = FileHelpers.GetOutputDataFileName(atIds, values)!; FileHelpers.WriteAllLines(atIdsFile, ids, new UTF8Encoding(false)); values.Reset(atIdsName); } var outputLast = values.GetOrDefault($"{domain}.output.list.last", false); if (outputLast && urls.Count() > 0) { var url = urls.Last(); UrlHelpers.CheckWriteOutputUrlOrId(url, values, domain, kind); } } #region private methods private static void CheckWriteOutputUrl(string url, INamedValues values, string domain) { var urlOk = !string.IsNullOrEmpty(url) && url.StartsWith("http"); if (!urlOk) return; var atUrlName = $"{domain}.output.url"; var atUrl = values.GetOrEmpty(atUrlName); var atUrlOk = !string.IsNullOrEmpty(atUrl); if (atUrlOk) { var atUrlFile = FileHelpers.GetOutputDataFileName(atUrl, values)!; FileHelpers.WriteAllText(atUrlFile, url, Encoding.UTF8); values.Reset(atUrlName); // once we wrote it, don't try to again } var addUrlName = $"{domain}.output.add.url"; var addUrl = values.GetOrEmpty(addUrlName); var addUrlOk = !string.IsNullOrEmpty(addUrl); if (addUrlOk) { var addUrlFile = FileHelpers.GetOutputDataFileName(addUrl, values)!; FileHelpers.AppendAllText(addUrlFile, "\n" + url, Encoding.UTF8); values.Reset(addUrlName); // once we wrote it, don't try to again } } private static void CheckWriteOutputId(string url, INamedValues values, string domain, IdKind kinds = IdKind.Guid) { var urlOk = !string.IsNullOrEmpty(url) && url.StartsWith("http"); if (!urlOk) return; foreach (var kind in Enum.GetValues(typeof(IdKind)).Cast<IdKind>()) { if ((kind & kinds) != 0) { var id = IdFromUrl(url, kind); var idOk = !string.IsNullOrEmpty(id); if (!idOk) continue; IdHelpers.CheckWriteOutputNameOrId(id, values, domain, kind); } } } public static void GetUrlsOrIds(string json, string arrayName, string urlName, IList<string> urls, IList<string> ids, IdKind kinds) { var getUrlsOnlyOnce = urls; foreach (var thisKind in Enum.GetValues(typeof(IdKind)).Cast<IdKind>()) { var askedForThisKind = (thisKind & kinds) != 0; if (askedForThisKind) { GetUrlsAndIdsForOneKind(json, arrayName, urlName, getUrlsOnlyOnce!, ids, thisKind); getUrlsOnlyOnce = null; // we'll get the URLs on the first } } } private static void GetUrlsAndIdsForOneKind(string json, string arrayName, string urlName, IList<string> urls, IList<string> ids, IdKind oneKind) { var parsed = JsonDocument.Parse(json); var items = parsed.GetPropertyArrayOrEmpty(arrayName); foreach (var item in items) { var url = item.GetPropertyStringOrNull(urlName); if (string.IsNullOrEmpty(url)) continue; var id = UrlHelpers.IdFromUrl(url, oneKind); if (urls != null) urls.Add(url); if (ids != null) ids.Add(id); } } #endregion } }