diff --git a/hostfile/hostfile.go b/hostfile/hostfile.go index 87ca7a5..609dc49 100644 --- a/hostfile/hostfile.go +++ b/hostfile/hostfile.go @@ -11,6 +11,13 @@ import ( const ( StartMarker = "# ekDNSHelper <<-> START CONFIG" EndMarker = "# ekDNSHelper <->> END CONFIG" + + // Legacy markers from the pre-rename "DNSHelper" era. + // ParseManagedBlock recognises these so that hosts files written by + // the old binary are detected, parsed, and silently upgraded to the + // current markers on the next write. + LegacyStartMarker = "# DNSHelper <<-> START CONFIG" + LegacyEndMarker = "# DNSHelper <->> END CONFIG" ) // DNSEntry represents a single IP-to-hostname mapping. diff --git a/hostfile/managed.go b/hostfile/managed.go index 4fe1b5c..09bd4c4 100644 --- a/hostfile/managed.go +++ b/hostfile/managed.go @@ -17,13 +17,17 @@ func ParseManagedBlock(lines []string) (prefix, managed, postfix []string, hasMa endCount := 0 for i, line := range lines { - if strings.Contains(line, "ekDNSHelper <<-> START CONFIG") { + // Recognise both current and legacy markers so that hosts files + // written by the old "DNSHelper" binary are parsed correctly. + if strings.Contains(line, "ekDNSHelper <<-> START CONFIG") || + strings.Contains(line, "DNSHelper <<-> START CONFIG") { startCount++ if startIdx == -1 { startIdx = i } } - if strings.Contains(line, "ekDNSHelper <->> END CONFIG") { + if strings.Contains(line, "ekDNSHelper <->> END CONFIG") || + strings.Contains(line, "DNSHelper <->> END CONFIG") { endCount++ if endIdx == -1 { endIdx = i diff --git a/hostfile/managed_test.go b/hostfile/managed_test.go index 537716d..d77de56 100644 --- a/hostfile/managed_test.go +++ b/hostfile/managed_test.go @@ -159,6 +159,134 @@ func TestParseManagedBlock_CorruptDuplicateMarkers(t *testing.T) { } } +// --------------------------------------------------------------------------- +// ParseManagedBlock — legacy marker tests +// --------------------------------------------------------------------------- + +func TestParseManagedBlock_LegacyMarkers(t *testing.T) { + lines := []string{ + "127.0.0.1 localhost", + hostfile.LegacyStartMarker, + "1.1.1.1\thost1", + "2.2.2.2\thost2", + hostfile.LegacyEndMarker, + "# trailing comment", + } + prefix, managed, postfix, has, err := hostfile.ParseManagedBlock(lines) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if !has { + t.Fatal("expected HasManagedBlock=true for legacy markers") + } + if len(prefix) != 1 || prefix[0] != "127.0.0.1 localhost" { + t.Errorf("unexpected prefix: %v", prefix) + } + if len(managed) != 2 { + t.Errorf("expected 2 managed lines, got %v", managed) + } + if len(postfix) != 1 || postfix[0] != "# trailing comment" { + t.Errorf("unexpected postfix: %v", postfix) + } +} + +func TestParseManagedBlock_LegacyStartMarkerAtLine0(t *testing.T) { + lines := []string{ + hostfile.LegacyStartMarker, + "1.1.1.1\thost1", + hostfile.LegacyEndMarker, + } + prefix, managed, postfix, has, err := hostfile.ParseManagedBlock(lines) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if !has { + t.Fatal("expected HasManagedBlock=true") + } + if len(prefix) != 0 { + t.Errorf("expected empty prefix, got %v", prefix) + } + if len(managed) != 1 || managed[0] != "1.1.1.1\thost1" { + t.Errorf("unexpected managed: %v", managed) + } + if len(postfix) != 0 { + t.Errorf("expected empty postfix, got %v", postfix) + } +} + +func TestParseManagedBlock_LegacyCorruptStartWithoutEnd(t *testing.T) { + lines := []string{ + "127.0.0.1 localhost", + hostfile.LegacyStartMarker, + "1.1.1.1\thost1", + } + _, _, _, _, err := hostfile.ParseManagedBlock(lines) + if err == nil { + t.Fatal("expected error for legacy start marker without end marker") + } +} + +func TestParseManagedBlock_LegacyCorruptEndWithoutStart(t *testing.T) { + lines := []string{ + "127.0.0.1 localhost", + "1.1.1.1\thost1", + hostfile.LegacyEndMarker, + } + _, _, _, _, err := hostfile.ParseManagedBlock(lines) + if err == nil { + t.Fatal("expected error for legacy end marker without start marker") + } +} + +func TestParseManagedBlock_MixedOldStartNewEnd(t *testing.T) { + // Legacy start with current end — still a valid block (both substrings match). + lines := []string{ + "127.0.0.1 localhost", + hostfile.LegacyStartMarker, + "1.1.1.1\thost1", + hostfile.EndMarker, + } + _, managed, _, has, err := hostfile.ParseManagedBlock(lines) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if !has { + t.Fatal("expected HasManagedBlock=true for mixed markers") + } + if len(managed) != 1 { + t.Errorf("expected 1 managed line, got %v", managed) + } +} + +func TestParseManagedBlock_LegacyUpgradedOnWrite(t *testing.T) { + // Verify that a legacy block is parsed and then reassembled with current markers. + lines := []string{ + "127.0.0.1 localhost", + hostfile.LegacyStartMarker, + "1.1.1.1\thost1", + hostfile.LegacyEndMarker, + "# trailing", + } + prefix, managed, postfix, _, err := hostfile.ParseManagedBlock(lines) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + result := hostfile.AssembleContent(prefix, managed, postfix) + // The reassembled output should use the current markers, not legacy. + found := false + for _, l := range result { + if l == hostfile.StartMarker { + found = true + } + if l == hostfile.LegacyStartMarker { + t.Fatal("reassembled content should not contain legacy start marker") + } + } + if !found { + t.Fatal("reassembled content should contain current start marker") + } +} + // --------------------------------------------------------------------------- // AddEntries tests // ---------------------------------------------------------------------------