Skip to content

Migrate settings storage from XML to JSON with automatic migration - #3282

Merged
mergify[bot] merged 8 commits into
mainfrom
copilot/migrate-settings-to-json
Dec 24, 2025
Merged

mergify[bot] merged 8 commits into
mainfrom
copilot/migrate-settings-to-json

Conversation

Copilot AI commented Dec 23, 2025 •

Copy link
Copy Markdown
Contributor

Changes proposed in this pull request

  • Changed settings file format from XML to JSON (Settings.xml → Settings.json)
  • Implemented automatic migration on first load with timestamped backups (Settings_[timestamp].xml.backup)
  • Added null-safe deserialization for both formats with descriptive exceptions
  • Extracted shared JsonOptions configuration (indented, case-insensitive, enum-to-string)
  • Refactored error handling in App.xaml.cs to eliminate duplication via HandleCorruptedSettingsFile()

Related issue(s)

N/A

Copilot generated summary

Copilot summary

Migration Logic (SettingsManager.cs):

  1. Check for Settings.json → load if exists
  2. If not found, check for Settings.xml → deserialize, save as JSON, create timestamped backup
  3. If neither exists → initialize defaults

Files Changed:

  • SettingsManager.cs: Added JSON serialization, migration logic, shared JsonOptions, null checks
  • SettingsInfo.cs: Replaced [XmlIgnore] with [JsonIgnore]
  • App.xaml.cs: Added JsonException handler, extracted common recovery logic

Safety:

  • Timestamped backups prevent overwriting (Settings_20231223140532.xml.backup)
  • Original XML preserved for manual rollback
  • Null-safe deserialization throws InvalidOperationException with clear messages
  • Corrupted files backed up before reset

JSON Configuration:

private static readonly JsonSerializerOptions JsonOptions = new()
{
    WriteIndented = true,                           // Human-readable
    PropertyNameCaseInsensitive = true,             // Flexible matching
    DefaultIgnoreCondition = JsonIgnoreCondition.Never,  // All properties
    Converters = { new JsonStringEnumConverter() }  // Enums as strings
};

To-Do

Contributing

By submitting this pull request, I confirm the following:

Original prompt

can you migrate the NETworkManager.Settings.SettingsManager to use json as new file format. The existing settings files should be automatically migrated to the new file.


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot AI and others added 5 commits December 23, 2025 23:52
Co-authored-by: BornToBeRoot <16019165+BornToBeRoot@users.noreply.github.com>
Co-authored-by: BornToBeRoot <16019165+BornToBeRoot@users.noreply.github.com>
Co-authored-by: BornToBeRoot <16019165+BornToBeRoot@users.noreply.github.com>
…null checks, use timestamped backups

Co-authored-by: BornToBeRoot <16019165+BornToBeRoot@users.noreply.github.com>
Co-authored-by: BornToBeRoot <16019165+BornToBeRoot@users.noreply.github.com>
Copilot AI changed the title [WIP] Migrate SettingsManager to use JSON file format Migrate settings storage from XML to JSON with automatic migration Dec 24, 2025
Copilot AI requested a review from BornToBeRoot December 24, 2025 00:06
@BornToBeRoot BornToBeRoot added this to the next-release milestone Dec 24, 2025
@BornToBeRoot
BornToBeRoot marked this pull request as ready for review December 24, 2025 16:14
@mergify
mergify Bot merged commit a4c7122 into main Dec 24, 2025
4 checks passed
@mergify
mergify Bot deleted the copilot/migrate-settings-to-json branch December 24, 2025 16:28
BornToBeRoot added a commit that referenced this pull request Oct 11, 2026
The CollectionChanged handlers were only attached to the initial collections
in the constructor. Since the settings are stored as JSON (#3282),
System.Text.Json replaces the collections when loading, and some views
replace them at runtime (e.g. PuTTY/PowerShell histories, reset to
defaults), so changes to these lists no longer marked the settings as
changed and were lost if nothing else changed. Each collection setter now
moves the handler to the new collection. Also adds the missing handler for
Network_CustomDNSServers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
BornToBeRoot added a commit that referenced this pull request Oct 11, 2026
The CollectionChanged handlers were only attached to the initial collections
in the constructor. Since the settings are stored as JSON (#3282),
System.Text.Json replaces the collections when loading, and some views
replace them at runtime (e.g. PuTTY/PowerShell histories, reset to
defaults), so changes to these lists no longer marked the settings as
changed and were lost if nothing else changed. Each collection setter now
moves the handler to the new collection. Also adds the missing handler for
Network_CustomDNSServers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
BornToBeRoot added a commit that referenced this pull request Oct 11, 2026
* Feature: Add RDAP client and IANA bootstrap service

Adds the RDAP (RFC 7480, 9082, 9083, 9224) client to NETworkManager.Models:
query parser (IDN, CIDR, asplain/asdot ASN, object-tag handles), IANA
bootstrap download/cache with conditional GET, label-wise/longest-prefix/
range matching, ARIN fallback for unlisted number resources, a small table
of RDAP servers not listed by IANA (.de, .ch/.li, .io), HTTPS-first server
selection, manual redirect handling, registrar referral and a tolerant
jCard parser.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Feature: Register RDAP application, settings and strings

Adds ApplicationName.RDAP (before Whois), its icon, settings (query history,
query type, referral, timeout, export), the RDAP settings page entry, tab
count, documentation link, query type converter and English strings. Existing
users get the new app via the settings upgrade.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Feature: Add RDAP view, settings page and Whois hand-off

Adds the RDAP tool (tabs, query type, registrar referral, structured result
view with raw JSON toggle, JSON/TXT export, history) and the RDAP settings
page (IANA bootstrap cache status, update now, timeout). Domains without a
known RDAP server can be opened in Whois; for this, WhoisHostViewModel.AddTab
is public, WhoisHostView forwards it and the redirect in MainWindow now
creates a Whois tab instead of ignoring the data.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Feature: Add RDAP profile support

Profiles can store an RDAP query and its query type (inherits the host by
default), including the profile dialog tab, the profile list column and the
import of hosts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Fix: IP Geolocation history written to Whois history

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Docs: Add RDAP documentation and changelog

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Feature: Move RDAP referral option to settings, align export

"Follow referral to registrar" is now a setting (Settings > RDAP) instead of
a checkbox next to the query button. Export is available via an Export...
button below the result and via right-click, like IP Geolocation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Feature: Show links of RDAP notices and remarks

Notices like terms of service, privacy policy or inaccuracy report forms now
show their links, which open in the browser (LinkTextBlock style,
ExternalProcessStarter.OpenUrl). The URLs come from the RDAP server and are
therefore restricted to absolute HTTP(S) URIs in normalized form before they
are passed to the shell. Links are also included in the text export.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Fix: RDAP bootstrap cache status and publication dates

- Publication date is parsed as UTC and shown in local time (was a culture
  dependent string, shown with the wrong offset) and always read from the
  cached file.
- Incomplete cache entries (file present, no download time) are repaired:
  the file is downloaded again instead of sending a conditional request.
- Replacing a cached file is retried, since it can be locked briefly (e.g. by
  a virus scanner).
- The last error per file is stored and shown in Settings > RDAP.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Feature: Follow RDAP registrar referral by default

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Feature: Refresh RDAP bootstrap files once a week

The IANA files rarely change, so they are now checked automatically once a
week instead of daily (data.iana.org max-age). A longer server cache lifetime
is still honored, and "Update now" checks immediately.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Feature: Use help icons in RDAP settings

Additional information for "Bootstrap files" and "Follow referral to
registrar" is shown as an info icon tooltip, like on the other settings
pages, instead of a text below the setting.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Feature: Align RDAP result layout with other tools

- Detail rows use CenterTextBlock labels and a 10px gap without extra row
  margins, like IP Geolocation and Network Interface.
- Section labels (Events, Nameservers, ...) use the gray group label style
  instead of an enlarged header.
- No duplicate "Result" title; Registry/Registrar titles are only shown if
  the referral was followed.
- Notice texts are shown in normal weight (only values are bold).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Fix: Limit RDAP bootstrap retries if IANA is not reachable

- A failed update is retried after one hour, at most 3 times; then the
  cached files are used until the regular weekly update ("Update now"
  always checks). The cached copy is never removed before a new file was
  downloaded and validated.
- After a network error, the remaining files are not tried in the same
  update (same server), so a blocked server costs at most one timeout.
- cache-info.json is only written if something was checked.
- A temporary file is removed if replacing the cached file fails.
- The "bootstrap unavailable" message includes the reason.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Feature: Secure RDAP referrals and validate the query per type

- The referral to the registrar (and its redirects) is only followed via
  HTTPS and not to local or private addresses, since the URL is sent by the
  registry. A skipped referral is logged and shown as status message.
- New RDAPQueryValidator validates the query depending on the query type
  (domain, TLD, IP address/CIDR, ASN, entity) while typing, in the RDAP tool
  and in the profile dialog, and validates again if the type changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Feature: Add export button to Whois

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Docs: RDAP retries, referral security, Whois export

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Docs: Add PR link to changelog

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Fix: Address review feedback for RDAP (#3607)

- Referrals: pin the connection to the checked addresses (SocketsHttpHandler
  ConnectCallback) to prevent DNS rebinding to local/private addresses, fail
  closed if the host cannot be resolved; proxied connections (CONNECT) are
  checked before the request.
- Run command / redirected data: detect the query type from the input
  instead of using the last selected type.
- Notice links: use a keyboard accessible Hyperlink (Tab + Enter).
- Clarify why zone IDs are removed from IPv6 input (RFC 9082 3.1.1).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Feature: Make links keyboard accessible (#3607)

New shared LinkHyperlink style (looks like LinkTextBlock, but focusable with
Tab and opened with Enter). Used for the links in About (license, community,
update), Web Console (WebView2 runtime download) and the RDAP notices, which
were mouse-only TextBlocks before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Fix: Limit RDAP response size

Responses (RDAP queries, referrals, bootstrap files) are limited to 10 MB, so
a broken or malicious server cannot exhaust the memory. Larger responses fail
as network error.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Fix: Settings lists not saved after the settings were loaded

The CollectionChanged handlers were only attached to the initial collections
in the constructor. Since the settings are stored as JSON (#3282),
System.Text.Json replaces the collections when loading, and some views
replace them at runtime (e.g. PuTTY/PowerShell histories, reset to
defaults), so changes to these lists no longer marked the settings as
changed and were lost if nothing else changed. Each collection setter now
moves the handler to the new collection. Also adds the missing handler for
Network_CustomDNSServers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Feature: Show "Open in Whois" in the center of the RDAP view

If no RDAP server is known for a domain, the error stays in the status line
and the center of the view (instead of the "Enter a domain..." placeholder)
shows a hint and an "Open in Whois" button, like the WebView2 hint in Web
Console.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Docs: Add RDAP screenshot

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Docs: Add blog post "Introducing RDAP"

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Docs: Clarify RDAP transport in blog post

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Docs: Add RDAP to website tool list and command line arguments

- Homepage / docs introduction: RDAP chip (28 built-in tools).
- --application: values updated to the current applications (RDAP,
  HostsFileEditor, Firewall, NeighborTable added; obsolete ARPTable removed).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants