| File: System\IO\IsolatedStorage\Helper.cs | Web Access |
| Project: src\runtime\src\libraries\System.IO.IsolatedStorage\src\System.IO.IsolatedStorage.csproj (System.IO.IsolatedStorage) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Security; using System.Threading; namespace System.IO.IsolatedStorage { internal static partial class Helper { private static string? s_machineRootDirectory; private static string? s_roamingUserRootDirectory; private static string? s_userRootDirectory; /// <summary> /// The full root directory is the relevant special folder from Environment.GetFolderPath() plus IsolatedStorageDirectoryName /// and a set of random directory names if not roaming. (The random directories aren't created for Android/iOS as /// the FolderPath locations for Android/iOS are app isolated already.) /// /// Examples: /// /// User: @"C:\Users\jerem\AppData\Local\IsolatedStorage\10v31ho4.bo2\eeolfu22.f2w\" /// User|Roaming: @"C:\Users\jerem\AppData\Roaming\IsolatedStorage\" /// Machine: @"C:\ProgramData\IsolatedStorage\nin03cyc.wr0\o3j0urs3.0sn\" /// Android path: "/data/user/0/{packageName}/files/.config/.isolated-storage" /// iOS path: "/var/mobile/Containers/Data/Application/A323CBB9-A2B3-4432-9449-48CC20C07A7D/Documents/.config/.isolated-storage" /// /// Identity for the current store gets tacked on after this. /// </summary> internal static string GetRootDirectory(IsolatedStorageScope scope) { if (IsRoaming(scope)) { if (string.IsNullOrEmpty(s_roamingUserRootDirectory)) { s_roamingUserRootDirectory = GetDataDirectory(scope); } return s_roamingUserRootDirectory; } if (IsMachine(scope)) { if (string.IsNullOrEmpty(s_machineRootDirectory)) { s_machineRootDirectory = GetRandomDirectory(GetDataDirectory(scope), scope); } return s_machineRootDirectory; } if (string.IsNullOrEmpty(s_userRootDirectory)) s_userRootDirectory = GetRandomDirectory(GetDataDirectory(scope), scope); return s_userRootDirectory; } internal static string? GetExistingRandomDirectory(string rootDirectory) { // Look for an existing random directory at the given root // (a set of nested directories that were created via Path.GetRandomFileName()) // Older versions of the .NET Framework created longer (24 character) random paths and would // migrate them if they could not find the new style directory. if (!Directory.Exists(rootDirectory)) return null; foreach (string directory in Directory.GetDirectories(rootDirectory)) { if (Path.GetFileName(directory)?.Length == 12) { foreach (string subdirectory in Directory.GetDirectories(directory)) { if (Path.GetFileName(subdirectory)?.Length == 12) { return subdirectory; } } } } return null; } [UnconditionalSuppressMessage("SingleFile", "IL3000:Avoid accessing Assembly file path when publishing as a single file", Justification = "Code handles single-file deployment by using the information of the .exe file")] internal static void GetDefaultIdentityAndHash(out object identity, out string hash, char separator) { // In .NET Framework IsolatedStorage uses identity from System.Security.Policy.Evidence to build // the folder structure on disk. It would use the "best" available evidence in this order: // // 1. Publisher (Authenticode) // 2. StrongName // 3. Url (CodeBase) // 4. Site // 5. Zone // // For .NET Core StrongName and Url are the only relevant types. By default evidence for the Domain comes // from the Assembly which comes from the EntryAssembly(). We'll emulate the legacy default behavior // by pulling directly from EntryAssembly. // // Note that it is possible that there won't be an EntryAssembly, which is something the .NET Framework doesn't // have to deal with and isn't likely on .NET Core due to a single AppDomain. The exception is Android which // doesn't set an EntryAssembly. Assembly? assembly = Assembly.GetEntryAssembly(); string? location = null; if (assembly != null) { AssemblyName assemblyName = assembly.GetName(); hash = IdentityHelper.GetNormalizedStrongNameHash(assemblyName)!; if (hash != null) { hash = string.Concat("StrongName", new ReadOnlySpan<char>(in separator), hash); identity = assemblyName; return; } else { location = assembly.Location; } } // In case of SingleFile deployment, Assembly.Location is empty. On Android there is no entry assembly. if (string.IsNullOrEmpty(location)) location = Environment.ProcessPath; if (string.IsNullOrEmpty(location)) throw new IsolatedStorageException(SR.IsolatedStorage_Init); Uri locationUri = new Uri(location); hash = string.Concat("Url", new ReadOnlySpan<char>(in separator), IdentityHelper.GetNormalizedUriHash(locationUri)); identity = locationUri; } internal static bool IsMachine(IsolatedStorageScope scope) => ((scope & IsolatedStorageScope.Machine) != 0); internal static bool IsAssembly(IsolatedStorageScope scope) => ((scope & IsolatedStorageScope.Assembly) != 0); internal static bool IsApplication(IsolatedStorageScope scope) => ((scope & IsolatedStorageScope.Application) != 0); internal static bool IsRoaming(IsolatedStorageScope scope) => ((scope & IsolatedStorageScope.Roaming) != 0); internal static bool IsDomain(IsolatedStorageScope scope) => ((scope & IsolatedStorageScope.Domain) != 0); } }