Files
mmd-pdf/Services/ProtocolRegistrar.cs
kua-agent 6610acfa44 feat: rebrand to MMD PDF, single corporate theme, and remove original text under an edit
- Services/PdfRedactText.cs: strip text whose origin falls inside a CoverAnnotation
  from the page content stream at save time, hooked into PdfBurn.DrawAnnotationsIntoDoc.
  Fixes edited values staying recoverable by text extraction.
- Themes/MMD.xaml replaces all thirteen themes; picker and accent strip removed; no dark mode.
- Rename KillerPDF -> MMD PDF across code, resources, packaging and locale strings; new icon.
- Remove the upstream author credit and the in-app install button.
2026-08-27 07:37:09 +02:00

66 lines
2.9 KiB
C#

using System;
using System.Diagnostics;
using Microsoft.Win32;
namespace MmdPdf.Services
{
internal static class ProtocolRegistrar
{
internal const string Scheme = "mmdpdf";
private const string RegistryPath = @"Software\Classes\mmdpdf";
internal static void Register() => Register(Registry.CurrentUser, null);
// #183: machine-wide installs must register under HKLM so every user gets the handler,
// not just whoever ran the installer. Root is chosen by the caller; appPath defaults to
// the running executable (the per-user refresh path) but the elevated installer passes
// the Program Files copy explicitly since IT is the source exe at that moment.
internal static void Register(RegistryKey root, string? appPath)
{
try
{
appPath ??= Process.GetCurrentProcess().MainModule!.FileName;
using var protocol = root.CreateSubKey(RegistryPath);
if (protocol == null) return;
protocol.SetValue("", "URL:MmdPdf Protocol");
protocol.SetValue("URL Protocol", "");
using (var icon = protocol.CreateSubKey("DefaultIcon"))
icon?.SetValue("", $"\"{appPath}\",0");
using (var command = protocol.CreateSubKey(@"shell\open\command"))
command?.SetValue("", $"\"{appPath}\" \"%1\"");
}
catch (Exception ex) { Debug.WriteLine($"Failed to register MmdPdf protocol: {ex.Message}"); }
}
internal static void Unregister() => Unregister(Registry.CurrentUser);
internal static void Unregister(RegistryKey root)
{
try { root.DeleteSubKeyTree(RegistryPath, false); } catch { }
}
internal static bool TryGetTargetUrl(string? protocolUrl, out Uri? target)
{
target = null;
if (!Uri.TryCreate(protocolUrl, UriKind.Absolute, out var launch) ||
!launch.Scheme.Equals(Scheme, StringComparison.OrdinalIgnoreCase) ||
!launch.Host.Equals("open", StringComparison.OrdinalIgnoreCase)) return false;
string query = launch.Query.TrimStart('?');
foreach (string pair in query.Split('&'))
{
int equals = pair.IndexOf('=');
if (equals < 0) continue;
string name = Uri.UnescapeDataString(pair.Substring(0, equals).Replace("+", " "));
if (!name.Equals("url", StringComparison.OrdinalIgnoreCase)) continue;
string value = Uri.UnescapeDataString(pair.Substring(equals + 1).Replace("+", " "));
if (!Uri.TryCreate(value, UriKind.Absolute, out var parsed)) return false;
if (!parsed.Scheme.Equals(Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase)) return false;
target = parsed;
return true;
}
return false;
}
}
}