public static string GetCleanUriPath(string absolutePath) { if (string.IsNullOrWhiteSpace(absolutePath) || (absolutePath.Length == 1 && absolutePath[0] == '/')) { return(absolutePath); } // Sanitized url will be at worse as long as the original var sb = StringBuilderCache.Acquire(absolutePath.Length); int previousIndex = 0; int index; int segmentLength; int indexOfFileExtension = 0; do { index = absolutePath.IndexOf('/', previousIndex); if (index == -1) { // Last segment // Is this a filename with an extension? if (absolutePath.Length > previousIndex && (indexOfFileExtension = absolutePath.LastIndexOf('.')) != -1 && indexOfFileExtension > previousIndex) { // Only try and clean the filename, excluding the file extension segmentLength = indexOfFileExtension - previousIndex; } else { segmentLength = absolutePath.Length - previousIndex; } } else { segmentLength = index - previousIndex; } if (IsIdentifierSegment(absolutePath, previousIndex, segmentLength)) { sb.Append('?'); } else { sb.Append(absolutePath, previousIndex, segmentLength); } if (index == -1) { if (segmentLength > 0 && indexOfFileExtension > previousIndex) { // add the file extension sb.Append(absolutePath, indexOfFileExtension, absolutePath.Length - indexOfFileExtension); } } else { sb.Append('/'); } previousIndex = index + 1; }while (index != -1); return(StringBuilderCache.GetStringAndRelease(sb)); }
public static string CleanUriSegment(string absolutePath) { if (string.IsNullOrWhiteSpace(absolutePath) || (absolutePath.Length == 1 && absolutePath[0] == '/')) { return(absolutePath); } #if NETCOREAPP ReadOnlySpan <char> absPath = absolutePath.AsSpan(); // Sanitized url will be at worse as long as the original var sb = StringBuilderCache.Acquire(absPath.Length); int previousIndex = 0; int index; do { ReadOnlySpan <char> nStart = absPath.Slice(previousIndex); index = nStart.IndexOf('/'); ReadOnlySpan <char> segment = index == -1 ? nStart : nStart.Slice(0, index); // replace path segments that look like numbers or guid // GUID format N "d85b1407351d4694939203acc5870eb1" length: 32 // GUID format D "d85b1407-351d-4694-9392-03acc5870eb1" length: 36 with dashes in indices 8, 13, 18 and 23. if (long.TryParse(segment, out _) || (segment.Length == 32 && IsAGuid(segment, "N")) || (segment.Length == 36 && IsAGuid(segment, "D"))) { sb.Append('?'); } else { sb.Append(segment); } if (index != -1) { sb.Append('/'); } previousIndex += index + 1; }while (index != -1); return(StringBuilderCache.GetStringAndRelease(sb)); #else // Sanitized url will be at worse as long as the original var sb = StringBuilderCache.Acquire(absolutePath.Length); int previousIndex = 0; int index = 0; do { index = absolutePath.IndexOf('/', previousIndex); string segment; if (index == -1) { // Last segment segment = absolutePath.Substring(previousIndex); } else { segment = absolutePath.Substring(previousIndex, index - previousIndex); } // replace path segments that look like numbers or guid // GUID format N "d85b1407351d4694939203acc5870eb1" length: 32 // GUID format D "d85b1407-351d-4694-9392-03acc5870eb1" length: 36 with dashes in indices 8, 13, 18 and 23. if (long.TryParse(segment, out _) || (segment.Length == 32 && IsAGuid(segment, "N")) || (segment.Length == 36 && IsAGuid(segment, "D"))) { segment = "?"; } sb.Append(segment); if (index != -1) { sb.Append("/"); } previousIndex = index + 1; }while (index != -1); return(StringBuilderCache.GetStringAndRelease(sb)); #endif }
/// <summary> /// Cleans identifiers from an absolute path, and optionally removes the provided prefix /// </summary> /// <param name="absolutePath">The path to clean</param> /// <param name="virtualPathToRemove">The optional virtual path to remove from the front of the path</param> /// <returns>The cleaned path</returns> public static string GetCleanUriPath(string absolutePath, string virtualPathToRemove) { if (string.IsNullOrWhiteSpace(absolutePath) || (absolutePath.Length == 1 && absolutePath[0] == '/')) { return(absolutePath); } if (!string.IsNullOrEmpty(virtualPathToRemove) && string.Equals(absolutePath, virtualPathToRemove)) { return("/"); } // If the virtual path is "/" then we're hosted at the root, so nothing to remove // If not, it will be of the form "/myapp", so remove whole thing // Make sure we only remove _whole_ segment i.e. /myapp/controller, but not /myappcontroller var hasPrefix = !string.IsNullOrEmpty(virtualPathToRemove) && virtualPathToRemove != "/" && virtualPathToRemove[0] == '/' && absolutePath.StartsWith(virtualPathToRemove, StringComparison.OrdinalIgnoreCase) && absolutePath.Length > virtualPathToRemove.Length && absolutePath[virtualPathToRemove.Length] == '/'; // Sanitized url will be at worse as long as the original, minus a removed virtual path var maxLength = absolutePath.Length - (hasPrefix ? virtualPathToRemove.Length : 0); var sb = StringBuilderCache.Acquire(maxLength); int previousIndex = hasPrefix ? virtualPathToRemove.Length : 0; int index; int segmentLength; int indexOfFileExtension = 0; do { index = absolutePath.IndexOf('/', previousIndex); if (index == -1) { // Last segment // Is this a filename with an extension? if (absolutePath.Length > previousIndex && (indexOfFileExtension = absolutePath.LastIndexOf('.')) != -1 && indexOfFileExtension > previousIndex) { // Only try and clean the filename, excluding the file extension segmentLength = indexOfFileExtension - previousIndex; } else { segmentLength = absolutePath.Length - previousIndex; } } else { segmentLength = index - previousIndex; } if (IsIdentifierSegment(absolutePath, previousIndex, segmentLength)) { sb.Append('?'); } else { sb.Append(absolutePath, previousIndex, segmentLength); } if (index == -1) { if (segmentLength > 0 && indexOfFileExtension > previousIndex) { // add the file extension sb.Append(absolutePath, indexOfFileExtension, absolutePath.Length - indexOfFileExtension); } } else { sb.Append('/'); } previousIndex = index + 1; }while (index != -1); return(StringBuilderCache.GetStringAndRelease(sb)); }