/Config.cs
using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;
namespace bytex64.WebThing {
public struct SearchHandlerPair {
public string Shortcut;
public string Plugin;
public SearchHandlerPair(string s, string p) {
Shortcut = s;
Plugin = p;
}
}
public class Config {
public static List<string> ConfigPath;
public static string ConfigPathOut = null;
public static List<string> PluginPath;
public static Dictionary<string,string> Options;
public static Dictionary<string,Dictionary<string,string>> PluginOptions;
public static string[] Arguments;
public static List<string> Plugins;
public static List<SearchHandlerPair> SearchHandlers;
public static string DefaultSearchHandler;
private static HashSet<string> CommandLineOptions;
private static Regex item_re = new Regex(@"^(?:([\w.]+)\.)?(\w+)$");
private static Regex file_var_re = new Regex(@"^([\w.]+)\s*=\s*(.*)$");
private static Regex file_command_re = new Regex(@"^([\w]+)\s*(.*)$");
static Config() {
Options = new Dictionary<string,string>();
PluginOptions = new Dictionary<string,Dictionary<string,string>>();
CommandLineOptions = new HashSet<string>();
Plugins = new List<string>();
SearchHandlers = new List<SearchHandlerPair>();
// Set up ConfigPath
IDictionary Env = Environment.GetEnvironmentVariables();
ConfigPath = new List<string>();
ConfigPath.Add("/etc/WebThing");
if (Env.Contains("HOME")) {
string homepath = Env["HOME"] + "/.config/WebThing";
ConfigPath.Add(homepath);
if (Directory.Exists(homepath))
ConfigPathOut = homepath;
}
string LocalAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
if (LocalAppData != "") {
string homepath = LocalAppData + "/WebThing";
ConfigPath.Add(homepath);
if (Directory.Exists(homepath))
ConfigPathOut = homepath;
}
// Set up PluginPath
PluginPath = new List<string>();
PluginPath.Add(Environment.GetEnvironmentVariable("WEBTHING_HOME") + "/plugins");
PluginPath.Add(Environment.GetEnvironmentVariable("WEBTHING_HOME") + "/searchplugins");
}
private static void ParseOption(string key, string val) {
Match m = item_re.Match(key);
string plugin = m.Groups[1].Value;
string name = m.Groups[2].Value;
if (plugin.Length > 0) { // Plugin Option
if (!PluginOptions.ContainsKey(plugin))
PluginOptions[plugin] = new Dictionary<string,string>();
PluginOptions[plugin][name] = val;
} else { // Global Option
switch(key.ToLower()) {
case "plugin":
Plugins.Add(val);
break;
default:
Options[key] = val;
break;
}
}
}
public static void DumpOptions() {
Console.WriteLine("Options:");
foreach (string key in Options.Keys)
Console.WriteLine(" {0}\t{1}", key, Options[key]);
Console.WriteLine("Plugin Options:");
foreach (string plugin in PluginOptions.Keys) {
Console.WriteLine(" {0}", plugin);
foreach (string key in PluginOptions[plugin].Keys)
Console.WriteLine(" {0}\t{1}", key, PluginOptions[plugin][key]);
}
Console.WriteLine("Arguments: {0}", String.Join(" ", Arguments));
}
public static void ParseCommandLine() {
Queue<string> q = new Queue<string>();
foreach (string s in System.Environment.GetCommandLineArgs()) {
q.Enqueue(s);
}
q.Dequeue(); // Remove self argument
Regex SimpleOpt = new Regex(@"^-([\w.]+)(?:[:=](.*))?$");
Regex LongOpt = new Regex(@"^--([\w.]+)$");
List<string> args = new List<string>();
while (q.Count > 0) {
string opt = q.Dequeue();
Match m;
m = SimpleOpt.Match(opt);
if (m.Success) {
string key = m.Groups[1].Value;
string val = m.Groups[2].Value;
if (val.Length > 0) {
ParseOption(key, val);
} else {
ParseOption(key, null);
}
CommandLineOptions.Add(key);
continue;
}
m = LongOpt.Match(opt);
if (m.Success) {
string key = m.Groups[1].Value;
if (q.Count > 0) {
string val = q.Peek();
if (!(SimpleOpt.IsMatch(val) || LongOpt.IsMatch(val))) {
q.Dequeue();
ParseOption(key, val);
} else {
ParseOption(key, null);
}
} else {
ParseOption(key, null);
}
CommandLineOptions.Add(key);
continue;
}
// else
args.Add(opt);
}
Arguments = args.ToArray();
}
public static void Load() {
foreach (string path in ConfigPath) {
if (!Directory.Exists(path)) continue;
string[] ConfigFiles = Directory.GetFiles(path, "*.conf");
foreach (string file in ConfigFiles) {
LoadFile(file);
}
}
if (Options.ContainsKey("config"))
LoadFile(Options["config"]);
}
public static void LoadFile(string filename) {
TextReader f;
try {
f = new StreamReader(filename);
} catch (FileNotFoundException) {
Console.WriteLine("Could not open configuration file {0}", filename);
return;
}
string line;
while ((line = f.ReadLine()) != null) {
Match m;
line = line.Trim();
m = file_var_re.Match(line);
if (m.Success) {
string key = m.Groups[1].Value;
if (!CommandLineOptions.Contains(key))
ParseOption(key, m.Groups[2].Value);
continue;
}
m = file_command_re.Match(line);
if (m.Success) {
string cmd = m.Groups[1].Value.ToLower();
switch(cmd) {
case "plugin":
Plugins.Add(m.Groups[2].Value);
break;
case "searchhandler":
string[] args = Regex.Split(m.Groups[2].Value, @"\s+");
if (args.Length != 2) {
Console.WriteLine("Expecting two arguments for SearchHandler.");
break;
}
SearchHandlers.Add(new SearchHandlerPair(args[0], args[1]));
break;
case "defaultsearchhandler":
DefaultSearchHandler = m.Groups[2].Value;
break;
default:
Console.WriteLine("Unknown Command in {0}: {1}", filename, line);
break;
}
continue;
}
}
f.Close();
}
public static void SaveFile(string filename) {
TextWriter f;
try {
f = new StreamWriter(filename);
} catch (IOException) {
Console.WriteLine("Could not save configuration to {0}", filename);
return;
}
foreach (string key in Options.Keys) {
if (CommandLineOptions.Contains(key)) continue;
f.WriteLine("{0} = {1}", key, Options[key]);
}
foreach (string plugin in PluginOptions.Keys) {
foreach (string key in PluginOptions[plugin].Keys) {
string pkey = String.Format("{0}.{1}", plugin, key);
if (CommandLineOptions.Contains(pkey)) continue;
f.WriteLine("{0} = {1}", pkey, PluginOptions[plugin][key]);
}
}
f.Close();
}
public static void SaveFile(WebThingPlugin p, string filename) {
string plugin_name = p.GetType().FullName;
SaveFile(plugin_name, filename);
}
public static void SaveFile(string plugin_name, string filename) {
// TODO: Throw exception if plugin does not exist
TextWriter f = new StreamWriter(filename);
foreach (string key in PluginOptions[plugin_name].Keys) {
f.WriteLine("{0}.{1} = {2}", plugin_name, key, PluginOptions[plugin_name][key]);
}
f.Close();
}
// Data parsers
public static bool ParseBool(string v) {
switch(v.ToLower()) {
case "true":
case "t":
case "1":
case "on":
case "yes":
return true;
}
return false;
}
}
}