private void CleanUpRoute() { NameHelper.EnsureValidFilenameCharacters(_parts); // NB: process all inner special directories of the route segments // "" -> remove empty segments // "." -> reference to current folder, remove unless it is the first segment of a relative path // ".." -> reference parent folder, remove this and parent folder, as long as the parent is not first segment or special too var ring = _parts.ToRing(); var link = ring.Head.Next; // first item path segment while (link != ring.Head) { Ring.Link previous = link.Previous; Ring.Link next = link.Next; switch ((string)link.Value) { case "": ring.RemoveLink(link); link = next; break; case ".": if (IsRelativePath && previous == ring.Head) { link = next; break; } ring.RemoveLink(link); link = next; break; case "..": if (previous == ring.Head) { if (IsRelativePath) { link = next; break; } throw new Exception("Attempt to reference parent above absolute root."); } if ((string)previous.Value == ".") { ring.RemoveLink(previous); link = next; break; } if ((string)previous.Value == "..") { link = next; break; } ring.RemoveLink(previous); ring.RemoveLink(link); link = next; break; default: link = link.Next; break; } } if (_parts.Count < 1) { throw new Exception("Empty path is not valid."); } if (_parts.Count == 1) { if (IsFolderPath && IsAbsolutePath) { //a single root folder is allowed. return; } throw new Exception("Empty path is not valid."); } // .\ and ..\ required for relative path part[1] // .\ and ..\ illegal for absolute path[1] var firstPart = (string)ring.Head.Next.Value; bool startsWithRelativeSpecialPart = RelativePath.IsRelativeSpecialPart(firstPart); if (IsAbsolutePath) { if (startsWithRelativeSpecialPart) { throw new Exception("Not a valid absolute path."); } } else { if (!startsWithRelativeSpecialPart) { throw new Exception("Not a valid relative path."); } } if ((IsFilePath) && ((IsAbsolutePath && _parts.Count == 1) || (IsRelativePath && _parts.Count == 2))) { throw new Exception("No file name specified."); } }