Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
14763a002a | ||
|
|
aecdc732b9 | ||
|
|
8c09e56982 | ||
|
|
89586bd706 |
+15
-1
@@ -39,7 +39,13 @@ namespace QuickClaude
|
|||||||
"or other personal information from your context into web searches or URLs you fetch, " +
|
"or other personal information from your context into web searches or URLs you fetch, " +
|
||||||
"unless the user specifically asks you to search for them. " +
|
"unless the user specifically asks you to search for them. " +
|
||||||
"Shell commands (Bash or PowerShell) are allowed for other things, but each one first shows the user a confirm box; " +
|
"Shell commands (Bash or PowerShell) are allowed for other things, but each one first shows the user a confirm box; " +
|
||||||
"if they decline, carry on without it.";
|
"if they decline, carry on without it. " +
|
||||||
|
"When the user asks you to open something, run exactly one PowerShell Start-Process command with one quoted target " +
|
||||||
|
"and nothing else on the line (no arguments, no second command); those open without a confirm box. " +
|
||||||
|
"A website: Start-Process \"https://x.com\" (always the full https:// URL). " +
|
||||||
|
"A folder: Start-Process \"C:\\wallpapers\" (the full path). " +
|
||||||
|
"A program: Start-Process mspaint (just its name). If QuickClaude answers that the name isn't on the PATH and gives " +
|
||||||
|
"a Start Menu shortcut, run Start-Process with that shortcut's full path, exactly as given.";
|
||||||
|
|
||||||
// Run without prompts. Bash and PowerShell stay out so they go through the confirm box hook.
|
// Run without prompts. Bash and PowerShell stay out so they go through the confirm box hook.
|
||||||
// Write and Edit only when the user picked "Edit files" or "Auto"; "Only look" removes them outright.
|
// Write and Edit only when the user picked "Edit files" or "Auto"; "Only look" removes them outright.
|
||||||
@@ -214,6 +220,8 @@ namespace QuickClaude
|
|||||||
Finished?.Invoke(error);
|
Finished?.Invoke(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// File writes also go through a guard hook ("QuickClaude.exe --guard-write") that blocks the
|
||||||
|
// Desktop and AppData, where OpenRules lets things open without asking.
|
||||||
// Shell commands go through QuickClaude's own confirm box: a PreToolUse hook that runs
|
// Shell commands go through QuickClaude's own confirm box: a PreToolUse hook that runs
|
||||||
// "QuickClaude.exe --confirm" (exec form, so no shell quoting). The dialog denies after
|
// "QuickClaude.exe --confirm" (exec form, so no shell quoting). The dialog denies after
|
||||||
// 2 minutes; the hook timeout is a bit longer so Claude Code never cuts it off first.
|
// 2 minutes; the hook timeout is a bit longer so Claude Code never cuts it off first.
|
||||||
@@ -231,6 +239,12 @@ namespace QuickClaude
|
|||||||
{
|
{
|
||||||
matcher = "Bash|PowerShell|Monitor", // Monitor also runs shell commands
|
matcher = "Bash|PowerShell|Monitor", // Monitor also runs shell commands
|
||||||
hooks = new[] { new { type = "command", command = exe, args = new[] { "--confirm" }, timeout = 150 } }
|
hooks = new[] { new { type = "command", command = exe, args = new[] { "--confirm" }, timeout = 150 } }
|
||||||
|
},
|
||||||
|
new
|
||||||
|
{
|
||||||
|
// Never lets Claude write to the Desktop or AppData (see WriteGuard)
|
||||||
|
matcher = "Write|Edit|MultiEdit|NotebookEdit",
|
||||||
|
hooks = new[] { new { type = "command", command = exe, args = new[] { "--guard-write" }, timeout = 30 } }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-7
@@ -31,14 +31,31 @@ namespace QuickClaude
|
|||||||
// Nothing to show: say nothing, so Claude Code's normal permission rules decide
|
// Nothing to show: say nothing, so Claude Code's normal permission rules decide
|
||||||
if (string.IsNullOrEmpty(command)) return 0;
|
if (string.IsNullOrEmpty(command)) return 0;
|
||||||
|
|
||||||
new Application { ShutdownMode = ShutdownMode.OnExplicitShutdown };
|
string decision, reason;
|
||||||
var win = new ConfirmWindow(toolName, command, cwd);
|
var verdict = OpenRules.Check(command, cwd, out var hint);
|
||||||
win.ShowDialog();
|
if (verdict == OpenRules.Verdict.Allow)
|
||||||
|
{
|
||||||
|
// "open x.com", "open C:\wallpapers", "open mspaint": no confirm box (see OpenRules)
|
||||||
|
decision = "allow";
|
||||||
|
reason = "Opening a website, folder or installed program is allowed without asking.";
|
||||||
|
}
|
||||||
|
else if (verdict == OpenRules.Verdict.Hint)
|
||||||
|
{
|
||||||
|
// The bare name wouldn't resolve, but there's a Start Menu shortcut for it
|
||||||
|
decision = "deny";
|
||||||
|
reason = hint;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
new Application { ShutdownMode = ShutdownMode.OnExplicitShutdown };
|
||||||
|
var win = new ConfirmWindow(toolName, command, cwd);
|
||||||
|
win.ShowDialog();
|
||||||
|
|
||||||
string decision = win.Allowed ? "allow" : "deny";
|
decision = win.Allowed ? "allow" : "deny";
|
||||||
string reason = win.Allowed ? "The user allowed this command."
|
reason = win.Allowed ? "The user allowed this command."
|
||||||
: win.TimedOut ? "The user didn't answer within 2 minutes, so the command was not run. Carry on without it."
|
: win.TimedOut ? "The user didn't answer within 2 minutes, so the command was not run. Carry on without it."
|
||||||
: "The user declined to run this command. Carry on without it.";
|
: "The user declined to run this command. Carry on without it.";
|
||||||
|
}
|
||||||
|
|
||||||
var json = JsonSerializer.Serialize(new
|
var json = JsonSerializer.Serialize(new
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Windows.Media;
|
||||||
|
|
||||||
|
namespace QuickClaude
|
||||||
|
{
|
||||||
|
// The same font choices as wIRC. Saved in settings.json by Name.
|
||||||
|
// - Windows fonts (Segoe UI, Tahoma, Tw Cen MT) aren't bundled; they're listed only when
|
||||||
|
// installed (Tw Cen MT only comes with Office).
|
||||||
|
// - The rounded fonts (Nunito, Quicksand, Varela Round) are SIL OFL licensed and built into
|
||||||
|
// the exe from the fonts folder, with their license files.
|
||||||
|
// An unknown or missing font falls back to Consolas.
|
||||||
|
public static class Fonts
|
||||||
|
{
|
||||||
|
public const string Default = "Consolas";
|
||||||
|
|
||||||
|
static readonly Uri PackRoot = new Uri("pack://application:,,,/");
|
||||||
|
|
||||||
|
public class Choice
|
||||||
|
{
|
||||||
|
public string Name;
|
||||||
|
public FontFamily Family;
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<Choice> choices;
|
||||||
|
|
||||||
|
public static List<Choice> All
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (choices != null) return choices;
|
||||||
|
var installed = new HashSet<string>(
|
||||||
|
System.Windows.Media.Fonts.SystemFontFamilies.Select(f => f.Source),
|
||||||
|
StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
choices = new List<Choice>
|
||||||
|
{
|
||||||
|
new Choice { Name = "Consolas", Family = new FontFamily("Consolas, Courier New") }
|
||||||
|
};
|
||||||
|
foreach (var sys in new[] { "Segoe UI", "Tahoma", "Tw Cen MT" })
|
||||||
|
if (installed.Contains(sys))
|
||||||
|
choices.Add(new Choice { Name = sys, Family = new FontFamily(sys) });
|
||||||
|
|
||||||
|
choices.Add(Bundled("Nunito (rounded)", "Nunito"));
|
||||||
|
choices.Add(Bundled("Quicksand (rounded)", "Quicksand"));
|
||||||
|
choices.Add(Bundled("Varela Round (rounded)", "Varela Round"));
|
||||||
|
return choices;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Choice Bundled(string name, string family) =>
|
||||||
|
new Choice { Name = name, Family = new FontFamily(PackRoot, "./fonts/#" + family + ", Consolas") };
|
||||||
|
|
||||||
|
public static Choice Find(string name) =>
|
||||||
|
All.FirstOrDefault(c => string.Equals(c.Name, name, StringComparison.OrdinalIgnoreCase)) ?? All[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
+72
-9
@@ -21,20 +21,26 @@ namespace QuickClaude
|
|||||||
readonly TextBlock status = new TextBlock();
|
readonly TextBlock status = new TextBlock();
|
||||||
readonly TextBlock grip = new TextBlock();
|
readonly TextBlock grip = new TextBlock();
|
||||||
WF.NotifyIcon tray;
|
WF.NotifyIcon tray;
|
||||||
WF.ToolStripMenuItem topItem, blackItem, whiteItem, lookItem, editItem, autoItem, folderItem;
|
WF.ToolStripMenuItem fontMenu, sizeMenu, topItem, blackItem, whiteItem, lookItem, editItem, autoItem, folderItem;
|
||||||
bool lastWasTool;
|
bool lastWasTool;
|
||||||
bool quitting;
|
bool quitting;
|
||||||
|
|
||||||
// Nearly invisible fill so the window still catches the mouse (fully clear pixels click through)
|
// Nearly invisible fill so the window still catches the mouse (fully clear pixels click through)
|
||||||
static readonly Brush HitFill = new SolidColorBrush(Color.FromArgb(1, 0, 0, 0));
|
static readonly Brush HitFill = new SolidColorBrush(Color.FromArgb(1, 0, 0, 0));
|
||||||
internal static readonly FontFamily Mono = new FontFamily("Consolas, Courier New");
|
// The current font (picked from the tray's Font menu). Still called Mono since
|
||||||
// Matches wIRC at its smallest font slider setting (10sp = 10 WPF units)
|
// ConfirmWindow and DarkMenu read it when they open.
|
||||||
internal const double TextSize = 10;
|
internal static FontFamily Mono = new FontFamily("Consolas, Courier New");
|
||||||
|
// Picked from the tray's Font size menu, 10 to 18 (same units as wIRC's font size
|
||||||
|
// slider: 10sp = 10 WPF units). ConfirmWindow and DarkMenu read it when they open.
|
||||||
|
internal const double MinTextSize = 10, MaxTextSize = 18;
|
||||||
|
internal static double TextSize = 10;
|
||||||
const double ResizeEdge = 6;
|
const double ResizeEdge = 6;
|
||||||
|
|
||||||
public MainWindow()
|
public MainWindow()
|
||||||
{
|
{
|
||||||
settings = Settings.Load();
|
settings = Settings.Load();
|
||||||
|
Mono = Fonts.Find(settings.Font).Family;
|
||||||
|
TextSize = Math.Clamp(Math.Round(settings.FontSize), MinTextSize, MaxTextSize);
|
||||||
|
|
||||||
Title = "QuickClaude";
|
Title = "QuickClaude";
|
||||||
WindowStyle = WindowStyle.None;
|
WindowStyle = WindowStyle.None;
|
||||||
@@ -88,7 +94,7 @@ namespace QuickClaude
|
|||||||
rootGrid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
|
rootGrid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
|
||||||
rootGrid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
|
rootGrid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
|
||||||
|
|
||||||
// Top row: a faint "clod" label that moves the window, plus a quiet status line
|
// Top row: a solid "clod" label that moves the window, plus a quiet status line
|
||||||
grip.Text = "clod";
|
grip.Text = "clod";
|
||||||
grip.FontSize = TextSize;
|
grip.FontSize = TextSize;
|
||||||
grip.FontFamily = Mono;
|
grip.FontFamily = Mono;
|
||||||
@@ -131,12 +137,52 @@ namespace QuickClaude
|
|||||||
Grid.SetRow(bottom, 2);
|
Grid.SetRow(bottom, 2);
|
||||||
rootGrid.Children.Add(bottom);
|
rootGrid.Children.Add(bottom);
|
||||||
|
|
||||||
// Right-click menus: Copy (and Cut/Paste in the input) plus New conversation; blank areas get just the latter
|
Content = rootGrid;
|
||||||
|
BuildContextMenus();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Right-click menus: Copy (and Cut/Paste in the input) plus New conversation; blank areas get just the latter.
|
||||||
|
// Rebuilt when the font changes so they use it too.
|
||||||
|
void BuildContextMenus()
|
||||||
|
{
|
||||||
transcript.ContextMenu = DarkMenu.Make(transcript, NewConversation);
|
transcript.ContextMenu = DarkMenu.Make(transcript, NewConversation);
|
||||||
input.ContextMenu = DarkMenu.Make(input, NewConversation);
|
input.ContextMenu = DarkMenu.Make(input, NewConversation);
|
||||||
rootGrid.ContextMenu = DarkMenu.Make(null, NewConversation);
|
((Grid)Content).ContextMenu = DarkMenu.Make(null, NewConversation);
|
||||||
|
}
|
||||||
|
|
||||||
Content = rootGrid;
|
void SetFontSize(double size)
|
||||||
|
{
|
||||||
|
size = Math.Clamp(size, MinTextSize, MaxTextSize);
|
||||||
|
settings.FontSize = size;
|
||||||
|
settings.Save();
|
||||||
|
TextSize = size;
|
||||||
|
FontSize = size;
|
||||||
|
transcript.FontSize = size;
|
||||||
|
input.FontSize = size;
|
||||||
|
status.FontSize = size;
|
||||||
|
grip.FontSize = size;
|
||||||
|
BuildContextMenus();
|
||||||
|
transcript.ScrollToEnd();
|
||||||
|
if (sizeMenu != null)
|
||||||
|
foreach (WF.ToolStripMenuItem item in sizeMenu.DropDownItems)
|
||||||
|
item.Checked = item.Text == size.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetFont(string name)
|
||||||
|
{
|
||||||
|
var choice = Fonts.Find(name);
|
||||||
|
settings.Font = choice.Name;
|
||||||
|
settings.Save();
|
||||||
|
Mono = choice.Family;
|
||||||
|
FontFamily = Mono;
|
||||||
|
transcript.FontFamily = Mono;
|
||||||
|
input.FontFamily = Mono;
|
||||||
|
status.FontFamily = Mono;
|
||||||
|
grip.FontFamily = Mono;
|
||||||
|
BuildContextMenus();
|
||||||
|
if (fontMenu != null)
|
||||||
|
foreach (WF.ToolStripMenuItem item in fontMenu.DropDownItems)
|
||||||
|
item.Checked = item.Text == choice.Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void StyleBox(TextBox tb)
|
static void StyleBox(TextBox tb)
|
||||||
@@ -178,7 +224,7 @@ namespace QuickClaude
|
|||||||
input.CaretBrush = solid;
|
input.CaretBrush = solid;
|
||||||
transcript.CaretBrush = solid;
|
transcript.CaretBrush = solid;
|
||||||
status.Foreground = faint;
|
status.Foreground = faint;
|
||||||
grip.Foreground = faint;
|
grip.Foreground = solid;
|
||||||
if (blackItem != null) { blackItem.Checked = c == Colors.Black; whiteItem.Checked = c == Colors.White; }
|
if (blackItem != null) { blackItem.Checked = c == Colors.Black; whiteItem.Checked = c == Colors.White; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -354,6 +400,23 @@ namespace QuickClaude
|
|||||||
color.DropDownItems.Add(whiteItem);
|
color.DropDownItems.Add(whiteItem);
|
||||||
menu.Items.Add(color);
|
menu.Items.Add(color);
|
||||||
|
|
||||||
|
fontMenu = new WF.ToolStripMenuItem("Font");
|
||||||
|
var current = Fonts.Find(settings.Font).Name;
|
||||||
|
foreach (var choice in Fonts.All)
|
||||||
|
{
|
||||||
|
var name = choice.Name;
|
||||||
|
fontMenu.DropDownItems.Add(new WF.ToolStripMenuItem(name, null, (s, e) => SetFont(name)) { Checked = name == current });
|
||||||
|
}
|
||||||
|
menu.Items.Add(fontMenu);
|
||||||
|
|
||||||
|
sizeMenu = new WF.ToolStripMenuItem("Font size");
|
||||||
|
for (int px = (int)MinTextSize; px <= (int)MaxTextSize; px++)
|
||||||
|
{
|
||||||
|
double sz = px;
|
||||||
|
sizeMenu.DropDownItems.Add(new WF.ToolStripMenuItem(px.ToString(), null, (s, e) => SetFontSize(sz)) { Checked = sz == TextSize });
|
||||||
|
}
|
||||||
|
menu.Items.Add(sizeMenu);
|
||||||
|
|
||||||
topItem = new WF.ToolStripMenuItem("Always on top", null, (s, e) =>
|
topItem = new WF.ToolStripMenuItem("Always on top", null, (s, e) =>
|
||||||
{
|
{
|
||||||
settings.Topmost = !settings.Topmost; Topmost = settings.Topmost; topItem.Checked = settings.Topmost; settings.Save();
|
settings.Topmost = !settings.Topmost; Topmost = settings.Topmost; topItem.Checked = settings.Topmost; settings.Save();
|
||||||
|
|||||||
+147
@@ -0,0 +1,147 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using Microsoft.Win32;
|
||||||
|
|
||||||
|
namespace QuickClaude
|
||||||
|
{
|
||||||
|
// Decides which "open ..." shell commands skip the confirm box. Only a command that is a
|
||||||
|
// single open of ONE target, with no arguments and nothing chained on, qualifies:
|
||||||
|
// Start-Process "https://x.com" a website (http/https only)
|
||||||
|
// Start-Process "C:\wallpapers" a folder that exists (no network paths)
|
||||||
|
// Start-Process mspaint a program: an .exe in Program Files, Windows,
|
||||||
|
// Start-Process "C:\...\mirc.exe" AppData\Local\Programs or the Store app aliases,
|
||||||
|
// Start-Process "...\mIRC.lnk" or a shortcut in the Start Menu or on the Desktop
|
||||||
|
// Scripts (.bat, .ps1 and so on) and programs anywhere else still get the confirm box.
|
||||||
|
public static class OpenRules
|
||||||
|
{
|
||||||
|
public enum Verdict { Ask, Allow, Hint }
|
||||||
|
|
||||||
|
// verb, optional "" title (cmd start), optional -FilePath/-Path, then ONE target.
|
||||||
|
// Quoted targets may contain spaces and ( ) for "Program Files (x86)", but never quotes,
|
||||||
|
// ` $ % or line breaks (PowerShell and cmd expand those). Unquoted targets are stricter.
|
||||||
|
static readonly Regex OpenCmd = new Regex(
|
||||||
|
@"^\s*(?:cmd(?:\.exe)?\s+/c\s+)?(?:Start-Process|saps|start|explorer(?:\.exe)?|Invoke-Item|ii)\s+" +
|
||||||
|
@"(?:""""\s+)?(?:-(?:FilePath|Path|LiteralPath)\s+)?" +
|
||||||
|
@"(?:""(?<t>[^""'`$%\r\n;&|<>^]+)""|'(?<t>[^""'`$%\r\n;&|<>^]+)'|(?<t>[^\s""'`$%;&|<>()^]+))\s*$",
|
||||||
|
RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
|
||||||
|
|
||||||
|
static readonly Regex Url = new Regex(@"^https?://[^\s""'`;&|<>$()^%]+$", RegexOptions.IgnoreCase);
|
||||||
|
static readonly Regex BareName = new Regex(@"^[A-Za-z0-9_.\-]+$");
|
||||||
|
|
||||||
|
public static Verdict Check(string command, string cwd, out string hint)
|
||||||
|
{
|
||||||
|
hint = null;
|
||||||
|
if (string.IsNullOrEmpty(command) || command.IndexOfAny(new[] { '\n', '\r' }) >= 0) return Verdict.Ask;
|
||||||
|
var m = OpenCmd.Match(command);
|
||||||
|
if (!m.Success) return Verdict.Ask;
|
||||||
|
var target = m.Groups["t"].Value.Trim();
|
||||||
|
if (target.Length == 0) return Verdict.Ask;
|
||||||
|
|
||||||
|
if (Url.IsMatch(target)) return Verdict.Allow;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (Path.IsPathFullyQualified(target))
|
||||||
|
{
|
||||||
|
if (target.StartsWith(@"\\")) return Verdict.Ask; // no network paths
|
||||||
|
var full = Path.GetFullPath(target);
|
||||||
|
if (Directory.Exists(full)) return Verdict.Allow;
|
||||||
|
if (File.Exists(full) && TrustedProgram(full)) return Verdict.Allow;
|
||||||
|
return Verdict.Ask;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BareName.IsMatch(target))
|
||||||
|
{
|
||||||
|
// A bare name could also pick up a file sitting in the work folder; never allow that
|
||||||
|
if (!string.IsNullOrEmpty(cwd) && Directory.Exists(cwd) &&
|
||||||
|
(File.Exists(Path.Combine(cwd, target)) || Directory.EnumerateFiles(cwd, target + ".*").Any())) return Verdict.Ask;
|
||||||
|
|
||||||
|
if (FindProgram(target) != null) return Verdict.Allow;
|
||||||
|
|
||||||
|
var lnk = FindShortcut(target);
|
||||||
|
if (lnk != null)
|
||||||
|
{
|
||||||
|
hint = "\"" + target + "\" isn't on the PATH, so that command wouldn't find it. " +
|
||||||
|
"Its Start Menu shortcut is " + lnk + ". Run Start-Process \"" + lnk + "\" instead " +
|
||||||
|
"(that one opens without a confirm box).";
|
||||||
|
return Verdict.Hint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
return Verdict.Ask;
|
||||||
|
}
|
||||||
|
|
||||||
|
static string Env(string name) => Environment.GetEnvironmentVariable(name) ?? "";
|
||||||
|
static string Special(Environment.SpecialFolder f) => Environment.GetFolderPath(f);
|
||||||
|
|
||||||
|
static string[] ProgramDirs => new[]
|
||||||
|
{
|
||||||
|
Env("ProgramFiles"), Env("ProgramFiles(x86)"), Env("ProgramW6432"),
|
||||||
|
Env("WINDIR"),
|
||||||
|
Path.Combine(Special(Environment.SpecialFolder.LocalApplicationData), "Programs"),
|
||||||
|
Path.Combine(Special(Environment.SpecialFolder.LocalApplicationData), "Microsoft", "WindowsApps"),
|
||||||
|
}.Where(d => d.Length > 0).ToArray();
|
||||||
|
|
||||||
|
static string[] ShortcutDirs => new[]
|
||||||
|
{
|
||||||
|
Path.Combine(Special(Environment.SpecialFolder.CommonApplicationData), "Microsoft", "Windows", "Start Menu"),
|
||||||
|
Path.Combine(Special(Environment.SpecialFolder.ApplicationData), "Microsoft", "Windows", "Start Menu"),
|
||||||
|
Special(Environment.SpecialFolder.DesktopDirectory),
|
||||||
|
Special(Environment.SpecialFolder.CommonDesktopDirectory),
|
||||||
|
}.Where(d => d.Length > 0).ToArray();
|
||||||
|
|
||||||
|
static bool Under(string path, string dir)
|
||||||
|
{
|
||||||
|
var d = Path.GetFullPath(dir).TrimEnd('\\') + "\\";
|
||||||
|
return path.StartsWith(d, StringComparison.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool TrustedProgram(string full)
|
||||||
|
{
|
||||||
|
var ext = Path.GetExtension(full).ToLowerInvariant();
|
||||||
|
if (ext == ".exe") return ProgramDirs.Any(d => Under(full, d));
|
||||||
|
if (ext == ".lnk") return ShortcutDirs.Any(d => Under(full, d));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Where Windows itself would find a bare program name: the Windows folders, the Store app
|
||||||
|
// aliases, and the App Paths registry (how "mspaint" and friends resolve).
|
||||||
|
static string FindProgram(string name)
|
||||||
|
{
|
||||||
|
var exe = name.EndsWith(".exe", StringComparison.OrdinalIgnoreCase) ? name : name + ".exe";
|
||||||
|
var win = Env("WINDIR");
|
||||||
|
foreach (var dir in new[]
|
||||||
|
{
|
||||||
|
Path.Combine(win, "System32"), win,
|
||||||
|
Path.Combine(Special(Environment.SpecialFolder.LocalApplicationData), "Microsoft", "WindowsApps"),
|
||||||
|
})
|
||||||
|
{
|
||||||
|
var p = Path.Combine(dir, exe);
|
||||||
|
if (File.Exists(p)) return p;
|
||||||
|
}
|
||||||
|
foreach (var hive in new[] { Registry.CurrentUser, Registry.LocalMachine })
|
||||||
|
{
|
||||||
|
using var key = hive.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\App Paths\" + exe);
|
||||||
|
var val = (key?.GetValue(null) as string)?.Trim('"');
|
||||||
|
if (!string.IsNullOrEmpty(val) && File.Exists(val) && TrustedProgram(Path.GetFullPath(val))) return val;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Start Menu or Desktop shortcut named like the program ("mirc" finds "mIRC.lnk").
|
||||||
|
// Exact name first, then the shortest name that starts with it.
|
||||||
|
static string FindShortcut(string name)
|
||||||
|
{
|
||||||
|
var all = ShortcutDirs.Where(Directory.Exists)
|
||||||
|
.SelectMany(d => { try { return Directory.EnumerateFiles(d, "*.lnk", SearchOption.AllDirectories); } catch { return Enumerable.Empty<string>(); } })
|
||||||
|
.ToList();
|
||||||
|
var exact = all.FirstOrDefault(f => string.Equals(Path.GetFileNameWithoutExtension(f), name, StringComparison.OrdinalIgnoreCase));
|
||||||
|
if (exact != null) return exact;
|
||||||
|
return all.Where(f => Path.GetFileNameWithoutExtension(f).StartsWith(name, StringComparison.OrdinalIgnoreCase))
|
||||||
|
.OrderBy(f => Path.GetFileNameWithoutExtension(f).Length).FirstOrDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,6 +12,8 @@ namespace QuickClaude
|
|||||||
{
|
{
|
||||||
// Run as Claude Code's shell-command confirm hook (separate short-lived process)
|
// Run as Claude Code's shell-command confirm hook (separate short-lived process)
|
||||||
if (Array.IndexOf(args, "--confirm") >= 0) return ConfirmHook.Run();
|
if (Array.IndexOf(args, "--confirm") >= 0) return ConfirmHook.Run();
|
||||||
|
// Run as Claude Code's file-write guard hook (see WriteGuard)
|
||||||
|
if (Array.IndexOf(args, "--guard-write") >= 0) return WriteGuard.Run();
|
||||||
|
|
||||||
using var mutex = new Mutex(true, "QuickClaude.SingleInstance", out bool first);
|
using var mutex = new Mutex(true, "QuickClaude.SingleInstance", out bool first);
|
||||||
if (!first) return 0;
|
if (!first) return 0;
|
||||||
|
|||||||
+5
-1
@@ -10,7 +10,7 @@
|
|||||||
<Nullable>disable</Nullable>
|
<Nullable>disable</Nullable>
|
||||||
<AssemblyName>QuickClaude</AssemblyName>
|
<AssemblyName>QuickClaude</AssemblyName>
|
||||||
<RootNamespace>QuickClaude</RootNamespace>
|
<RootNamespace>QuickClaude</RootNamespace>
|
||||||
<Version>1.0.0</Version>
|
<Version>1.4.0</Version>
|
||||||
<Product>QuickClaude</Product>
|
<Product>QuickClaude</Product>
|
||||||
<ApplicationIcon>app.ico</ApplicationIcon>
|
<ApplicationIcon>app.ico</ApplicationIcon>
|
||||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||||
@@ -21,4 +21,8 @@
|
|||||||
<DebugType>none</DebugType>
|
<DebugType>none</DebugType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Resource Include="fonts\*.ttf" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ namespace QuickClaude
|
|||||||
public double Width { get; set; } = 460;
|
public double Width { get; set; } = 460;
|
||||||
public double Height { get; set; } = 380;
|
public double Height { get; set; } = 380;
|
||||||
public string TextColor { get; set; } = "Black";
|
public string TextColor { get; set; } = "Black";
|
||||||
|
public string Font { get; set; } = "Consolas";
|
||||||
|
public double FontSize { get; set; } = 10;
|
||||||
public bool Topmost { get; set; } = false;
|
public bool Topmost { get; set; } = false;
|
||||||
public string WorkDir { get; set; } = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
|
public string WorkDir { get; set; } = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
|
||||||
public string Mode { get; set; } = "default";
|
public string Mode { get; set; } = "default";
|
||||||
|
|||||||
@@ -0,0 +1,81 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.Json;
|
||||||
|
|
||||||
|
namespace QuickClaude
|
||||||
|
{
|
||||||
|
// QuickClaude.exe --guard-write: Claude Code's PreToolUse hook for Write, Edit and NotebookEdit.
|
||||||
|
// Keeps Claude from writing anywhere OpenRules lets things open without a confirm box that a
|
||||||
|
// normal (non-admin) account can write to: your Desktop and all of AppData (which holds your
|
||||||
|
// own Start Menu, AppData\Local\Programs and the Store app aliases). Without this, Claude in
|
||||||
|
// "Edit files" or "Auto" mode could drop a shortcut or program there and then open it unasked.
|
||||||
|
// Every other folder is left to the "Claude can" setting as before.
|
||||||
|
public static class WriteGuard
|
||||||
|
{
|
||||||
|
public static int Run()
|
||||||
|
{
|
||||||
|
string path = null, cwd = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var stdin = new StreamReader(Console.OpenStandardInput(), new UTF8Encoding(false));
|
||||||
|
using var doc = JsonDocument.Parse(stdin.ReadToEnd());
|
||||||
|
var root = doc.RootElement;
|
||||||
|
cwd = Str(root, "cwd");
|
||||||
|
if (root.TryGetProperty("tool_input", out var input))
|
||||||
|
path = Str(input, "file_path") ?? Str(input, "notebook_path") ?? Str(input, "path");
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(path)) return 0; // nothing to check: normal rules decide
|
||||||
|
|
||||||
|
if (!Blocked(path, cwd)) return 0;
|
||||||
|
|
||||||
|
var json = JsonSerializer.Serialize(new
|
||||||
|
{
|
||||||
|
hookSpecificOutput = new
|
||||||
|
{
|
||||||
|
hookEventName = "PreToolUse",
|
||||||
|
permissionDecision = "deny",
|
||||||
|
permissionDecisionReason =
|
||||||
|
"QuickClaude doesn't let Claude write to the Desktop or AppData folders (programs and shortcuts there " +
|
||||||
|
"can open without a confirm box). Tell the user, and suggest a different folder if one would do."
|
||||||
|
}
|
||||||
|
});
|
||||||
|
using var stdout = new StreamWriter(Console.OpenStandardOutput(), new UTF8Encoding(false));
|
||||||
|
stdout.Write(json);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool Blocked(string path, string cwd)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var full = Path.IsPathRooted(path) || string.IsNullOrEmpty(cwd)
|
||||||
|
? Path.GetFullPath(path)
|
||||||
|
: Path.GetFullPath(Path.Combine(cwd, path));
|
||||||
|
var home = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
|
||||||
|
var dirs = new[]
|
||||||
|
{
|
||||||
|
Path.Combine(home, "AppData"),
|
||||||
|
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
|
||||||
|
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
|
||||||
|
Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory),
|
||||||
|
Environment.GetFolderPath(Environment.SpecialFolder.CommonDesktopDirectory),
|
||||||
|
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "Microsoft", "Windows", "Start Menu"),
|
||||||
|
}.Where(d => !string.IsNullOrEmpty(d));
|
||||||
|
return dirs.Any(d =>
|
||||||
|
{
|
||||||
|
var root = Path.GetFullPath(d).TrimEnd('\\');
|
||||||
|
return full.Equals(root, StringComparison.OrdinalIgnoreCase) ||
|
||||||
|
full.StartsWith(root + "\\", StringComparison.OrdinalIgnoreCase);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch { return true; } // a path we can't even parse doesn't get written
|
||||||
|
}
|
||||||
|
|
||||||
|
static string Str(JsonElement e, string name) =>
|
||||||
|
e.ValueKind == JsonValueKind.Object && e.TryGetProperty(name, out var v) && v.ValueKind == JsonValueKind.String ? v.GetString() : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
@@ -0,0 +1,93 @@
|
|||||||
|
Copyright 2014 The Nunito Project Authors (https://github.com/googlefonts/nunito)
|
||||||
|
|
||||||
|
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||||
|
This license is copied below, and is also available with a FAQ at:
|
||||||
|
http://scripts.sil.org/OFL
|
||||||
|
|
||||||
|
|
||||||
|
-----------------------------------------------------------
|
||||||
|
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||||
|
-----------------------------------------------------------
|
||||||
|
|
||||||
|
PREAMBLE
|
||||||
|
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||||
|
development of collaborative font projects, to support the font creation
|
||||||
|
efforts of academic and linguistic communities, and to provide a free and
|
||||||
|
open framework in which fonts may be shared and improved in partnership
|
||||||
|
with others.
|
||||||
|
|
||||||
|
The OFL allows the licensed fonts to be used, studied, modified and
|
||||||
|
redistributed freely as long as they are not sold by themselves. The
|
||||||
|
fonts, including any derivative works, can be bundled, embedded,
|
||||||
|
redistributed and/or sold with any software provided that any reserved
|
||||||
|
names are not used by derivative works. The fonts and derivatives,
|
||||||
|
however, cannot be released under any other type of license. The
|
||||||
|
requirement for fonts to remain under this license does not apply
|
||||||
|
to any document created using the fonts or their derivatives.
|
||||||
|
|
||||||
|
DEFINITIONS
|
||||||
|
"Font Software" refers to the set of files released by the Copyright
|
||||||
|
Holder(s) under this license and clearly marked as such. This may
|
||||||
|
include source files, build scripts and documentation.
|
||||||
|
|
||||||
|
"Reserved Font Name" refers to any names specified as such after the
|
||||||
|
copyright statement(s).
|
||||||
|
|
||||||
|
"Original Version" refers to the collection of Font Software components as
|
||||||
|
distributed by the Copyright Holder(s).
|
||||||
|
|
||||||
|
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||||
|
or substituting -- in part or in whole -- any of the components of the
|
||||||
|
Original Version, by changing formats or by porting the Font Software to a
|
||||||
|
new environment.
|
||||||
|
|
||||||
|
"Author" refers to any designer, engineer, programmer, technical
|
||||||
|
writer or other person who contributed to the Font Software.
|
||||||
|
|
||||||
|
PERMISSION & CONDITIONS
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||||
|
redistribute, and sell modified and unmodified copies of the Font
|
||||||
|
Software, subject to the following conditions:
|
||||||
|
|
||||||
|
1) Neither the Font Software nor any of its individual components,
|
||||||
|
in Original or Modified Versions, may be sold by itself.
|
||||||
|
|
||||||
|
2) Original or Modified Versions of the Font Software may be bundled,
|
||||||
|
redistributed and/or sold with any software, provided that each copy
|
||||||
|
contains the above copyright notice and this license. These can be
|
||||||
|
included either as stand-alone text files, human-readable headers or
|
||||||
|
in the appropriate machine-readable metadata fields within text or
|
||||||
|
binary files as long as those fields can be easily viewed by the user.
|
||||||
|
|
||||||
|
3) No Modified Version of the Font Software may use the Reserved Font
|
||||||
|
Name(s) unless explicit written permission is granted by the corresponding
|
||||||
|
Copyright Holder. This restriction only applies to the primary font name as
|
||||||
|
presented to the users.
|
||||||
|
|
||||||
|
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||||
|
Software shall not be used to promote, endorse or advertise any
|
||||||
|
Modified Version, except to acknowledge the contribution(s) of the
|
||||||
|
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||||
|
permission.
|
||||||
|
|
||||||
|
5) The Font Software, modified or unmodified, in part or in whole,
|
||||||
|
must be distributed entirely under this license, and must not be
|
||||||
|
distributed under any other license. The requirement for fonts to
|
||||||
|
remain under this license does not apply to any document created
|
||||||
|
using the Font Software.
|
||||||
|
|
||||||
|
TERMINATION
|
||||||
|
This license becomes null and void if any of the above conditions are
|
||||||
|
not met.
|
||||||
|
|
||||||
|
DISCLAIMER
|
||||||
|
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||||
|
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||||
|
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||||
|
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||||
|
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
Copyright 2011 The Quicksand Project Authors (https://github.com/andrew-paglinawan/QuicksandFamily), with Reserved Font Name “Quicksand”.
|
||||||
|
|
||||||
|
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||||
|
This license is copied below, and is also available with a FAQ at:
|
||||||
|
http://scripts.sil.org/OFL
|
||||||
|
|
||||||
|
|
||||||
|
-----------------------------------------------------------
|
||||||
|
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||||
|
-----------------------------------------------------------
|
||||||
|
|
||||||
|
PREAMBLE
|
||||||
|
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||||
|
development of collaborative font projects, to support the font creation
|
||||||
|
efforts of academic and linguistic communities, and to provide a free and
|
||||||
|
open framework in which fonts may be shared and improved in partnership
|
||||||
|
with others.
|
||||||
|
|
||||||
|
The OFL allows the licensed fonts to be used, studied, modified and
|
||||||
|
redistributed freely as long as they are not sold by themselves. The
|
||||||
|
fonts, including any derivative works, can be bundled, embedded,
|
||||||
|
redistributed and/or sold with any software provided that any reserved
|
||||||
|
names are not used by derivative works. The fonts and derivatives,
|
||||||
|
however, cannot be released under any other type of license. The
|
||||||
|
requirement for fonts to remain under this license does not apply
|
||||||
|
to any document created using the fonts or their derivatives.
|
||||||
|
|
||||||
|
DEFINITIONS
|
||||||
|
"Font Software" refers to the set of files released by the Copyright
|
||||||
|
Holder(s) under this license and clearly marked as such. This may
|
||||||
|
include source files, build scripts and documentation.
|
||||||
|
|
||||||
|
"Reserved Font Name" refers to any names specified as such after the
|
||||||
|
copyright statement(s).
|
||||||
|
|
||||||
|
"Original Version" refers to the collection of Font Software components as
|
||||||
|
distributed by the Copyright Holder(s).
|
||||||
|
|
||||||
|
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||||
|
or substituting -- in part or in whole -- any of the components of the
|
||||||
|
Original Version, by changing formats or by porting the Font Software to a
|
||||||
|
new environment.
|
||||||
|
|
||||||
|
"Author" refers to any designer, engineer, programmer, technical
|
||||||
|
writer or other person who contributed to the Font Software.
|
||||||
|
|
||||||
|
PERMISSION & CONDITIONS
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||||
|
redistribute, and sell modified and unmodified copies of the Font
|
||||||
|
Software, subject to the following conditions:
|
||||||
|
|
||||||
|
1) Neither the Font Software nor any of its individual components,
|
||||||
|
in Original or Modified Versions, may be sold by itself.
|
||||||
|
|
||||||
|
2) Original or Modified Versions of the Font Software may be bundled,
|
||||||
|
redistributed and/or sold with any software, provided that each copy
|
||||||
|
contains the above copyright notice and this license. These can be
|
||||||
|
included either as stand-alone text files, human-readable headers or
|
||||||
|
in the appropriate machine-readable metadata fields within text or
|
||||||
|
binary files as long as those fields can be easily viewed by the user.
|
||||||
|
|
||||||
|
3) No Modified Version of the Font Software may use the Reserved Font
|
||||||
|
Name(s) unless explicit written permission is granted by the corresponding
|
||||||
|
Copyright Holder. This restriction only applies to the primary font name as
|
||||||
|
presented to the users.
|
||||||
|
|
||||||
|
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||||
|
Software shall not be used to promote, endorse or advertise any
|
||||||
|
Modified Version, except to acknowledge the contribution(s) of the
|
||||||
|
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||||
|
permission.
|
||||||
|
|
||||||
|
5) The Font Software, modified or unmodified, in part or in whole,
|
||||||
|
must be distributed entirely under this license, and must not be
|
||||||
|
distributed under any other license. The requirement for fonts to
|
||||||
|
remain under this license does not apply to any document created
|
||||||
|
using the Font Software.
|
||||||
|
|
||||||
|
TERMINATION
|
||||||
|
This license becomes null and void if any of the above conditions are
|
||||||
|
not met.
|
||||||
|
|
||||||
|
DISCLAIMER
|
||||||
|
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||||
|
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||||
|
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||||
|
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||||
|
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
Copyright 2023 The Varela Round Project Authors (https://github.com/alefalefalef/Varela-Round-Hebrew/), with Reserved Font Names 'Varela' and ‘Varela Round’.
|
||||||
|
|
||||||
|
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||||
|
This license is copied below, and is also available with a FAQ at:
|
||||||
|
https://scripts.sil.org/OFL
|
||||||
|
|
||||||
|
|
||||||
|
-----------------------------------------------------------
|
||||||
|
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||||
|
-----------------------------------------------------------
|
||||||
|
|
||||||
|
PREAMBLE
|
||||||
|
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||||
|
development of collaborative font projects, to support the font creation
|
||||||
|
efforts of academic and linguistic communities, and to provide a free and
|
||||||
|
open framework in which fonts may be shared and improved in partnership
|
||||||
|
with others.
|
||||||
|
|
||||||
|
The OFL allows the licensed fonts to be used, studied, modified and
|
||||||
|
redistributed freely as long as they are not sold by themselves. The
|
||||||
|
fonts, including any derivative works, can be bundled, embedded,
|
||||||
|
redistributed and/or sold with any software provided that any reserved
|
||||||
|
names are not used by derivative works. The fonts and derivatives,
|
||||||
|
however, cannot be released under any other type of license. The
|
||||||
|
requirement for fonts to remain under this license does not apply
|
||||||
|
to any document created using the fonts or their derivatives.
|
||||||
|
|
||||||
|
DEFINITIONS
|
||||||
|
"Font Software" refers to the set of files released by the Copyright
|
||||||
|
Holder(s) under this license and clearly marked as such. This may
|
||||||
|
include source files, build scripts and documentation.
|
||||||
|
|
||||||
|
"Reserved Font Name" refers to any names specified as such after the
|
||||||
|
copyright statement(s).
|
||||||
|
|
||||||
|
"Original Version" refers to the collection of Font Software components as
|
||||||
|
distributed by the Copyright Holder(s).
|
||||||
|
|
||||||
|
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||||
|
or substituting -- in part or in whole -- any of the components of the
|
||||||
|
Original Version, by changing formats or by porting the Font Software to a
|
||||||
|
new environment.
|
||||||
|
|
||||||
|
"Author" refers to any designer, engineer, programmer, technical
|
||||||
|
writer or other person who contributed to the Font Software.
|
||||||
|
|
||||||
|
PERMISSION & CONDITIONS
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||||
|
redistribute, and sell modified and unmodified copies of the Font
|
||||||
|
Software, subject to the following conditions:
|
||||||
|
|
||||||
|
1) Neither the Font Software nor any of its individual components,
|
||||||
|
in Original or Modified Versions, may be sold by itself.
|
||||||
|
|
||||||
|
2) Original or Modified Versions of the Font Software may be bundled,
|
||||||
|
redistributed and/or sold with any software, provided that each copy
|
||||||
|
contains the above copyright notice and this license. These can be
|
||||||
|
included either as stand-alone text files, human-readable headers or
|
||||||
|
in the appropriate machine-readable metadata fields within text or
|
||||||
|
binary files as long as those fields can be easily viewed by the user.
|
||||||
|
|
||||||
|
3) No Modified Version of the Font Software may use the Reserved Font
|
||||||
|
Name(s) unless explicit written permission is granted by the corresponding
|
||||||
|
Copyright Holder. This restriction only applies to the primary font name as
|
||||||
|
presented to the users.
|
||||||
|
|
||||||
|
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||||
|
Software shall not be used to promote, endorse or advertise any
|
||||||
|
Modified Version, except to acknowledge the contribution(s) of the
|
||||||
|
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||||
|
permission.
|
||||||
|
|
||||||
|
5) The Font Software, modified or unmodified, in part or in whole,
|
||||||
|
must be distributed entirely under this license, and must not be
|
||||||
|
distributed under any other license. The requirement for fonts to
|
||||||
|
remain under this license does not apply to any document created
|
||||||
|
using the Font Software.
|
||||||
|
|
||||||
|
TERMINATION
|
||||||
|
This license becomes null and void if any of the above conditions are
|
||||||
|
not met.
|
||||||
|
|
||||||
|
DISCLAIMER
|
||||||
|
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||||
|
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||||
|
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||||
|
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||||
|
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user