Refactored plugin architecture out of WebThing.cs
[WebThing.git] / Config.cs
1 using System;
2 using System.IO;
3 using System.Collections;
4 using System.Collections.Generic;
5 using System.Text.RegularExpressions;
6
7 namespace bytex64.WebThing {
8     public class Config {
9         public static List<string> ConfigPath;
10
11         public static Dictionary<string,string> Options;
12         public static Dictionary<string,Dictionary<string,string>> PluginOptions;
13         public static string[] Arguments;
14         public static List<string> Plugins;
15
16         private static HashSet<string> CommandLineOptions;
17         private static Regex item_re = new Regex(@"^(?:([\w.]+)\.)?(\w+)$");
18         private static Regex file_var_re = new Regex(@"^([\w.]+)\s*=\s*(.*)$");
19         private static Regex file_command_re = new Regex(@"^([\w]+)\s*(.*)$");
20
21         static Config() {
22             Options = new Dictionary<string,string>();
23             PluginOptions = new Dictionary<string,Dictionary<string,string>>();
24             CommandLineOptions = new HashSet<string>();
25             Plugins = new List<string>();
26
27             // Set up ConfigPath
28             IDictionary Env = Environment.GetEnvironmentVariables();
29             ConfigPath = new List<string>();
30             ConfigPath.Add("/etc/WebThing");
31             if (Env.Contains("HOME")) {
32                 ConfigPath.Add(Env["HOME"] + "/.config/WebThing");
33                 ConfigPath.Add(Env["HOME"] + "/.WebThing");
34             }
35             string LocalAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
36             if (LocalAppData != "") {
37                 ConfigPath.Add(LocalAppData + "/WebThing");
38             }
39         }
40
41         private static void ParseOption(string key, string val) {
42             Match m = item_re.Match(key);
43             string plugin = m.Groups[1].Value;
44             string name = m.Groups[2].Value;
45             if (plugin.Length > 0) {   // Plugin Option
46                 if (!PluginOptions.ContainsKey(plugin))
47                     PluginOptions[plugin] = new Dictionary<string,string>();
48                 PluginOptions[plugin][name] = val;
49             } else {                   // Global Option
50                 switch(key) {
51                 case "Plugin":
52                 case "plugin":
53                     Plugins.Add(val);
54                     break;
55                 default:
56                     Options[key] = val;
57                     break;
58                 }
59             }
60         }
61
62         public static void DumpOptions() {
63             Console.WriteLine("Options:");
64             foreach (string key in Options.Keys)
65                 Console.WriteLine("   {0}\t{1}", key, Options[key]);
66
67             Console.WriteLine("Plugin Options:");
68             foreach (string plugin in PluginOptions.Keys) {
69                 Console.WriteLine("    {0}", plugin);
70                 foreach (string key in PluginOptions[plugin].Keys)
71                     Console.WriteLine("        {0}\t{1}", key, PluginOptions[plugin][key]);
72             }
73
74             Console.WriteLine("Arguments: {0}", String.Join(" ", Arguments));
75         }
76
77         public static void ParseCommandLine() {
78             Queue<string> q = new Queue<string>();
79             foreach (string s in System.Environment.GetCommandLineArgs()) {
80                 q.Enqueue(s);
81             }
82             q.Dequeue();   // Remove self argument
83
84             Regex SimpleOpt = new Regex(@"^-([\w.]+)(?:[:=](.*))?$");
85             Regex LongOpt   = new Regex(@"^--([\w.]+)$");
86             List<string> args = new List<string>();
87
88             while (q.Count > 0) {
89                 string opt = q.Dequeue();
90                 Match m;
91                    
92                 m = SimpleOpt.Match(opt);
93                 if (m.Success) {
94                     string key = m.Groups[1].Value;
95                     string val = m.Groups[2].Value;
96                     if (val.Length > 0) {
97                         ParseOption(key, val);
98                     } else {
99                         ParseOption(key, null);
100                     }
101                     CommandLineOptions.Add(key);
102                     continue;
103                 }
104
105                 m = LongOpt.Match(opt);
106                 if (m.Success) {
107                     string key = m.Groups[1].Value;
108                     if (q.Count > 0) {
109                         string val = q.Peek();
110                         if (!(SimpleOpt.IsMatch(val) || LongOpt.IsMatch(val))) {
111                             q.Dequeue();
112                             ParseOption(key, val);
113                         } else {
114                             ParseOption(key, null);
115                         }
116                     } else {
117                         ParseOption(key, null);
118                     }
119                     CommandLineOptions.Add(key);
120                     continue;
121                 }
122
123                 // else
124
125                 args.Add(opt);
126             }
127             Arguments = args.ToArray();
128         }
129
130         public static void Load() {
131             foreach (string path in ConfigPath) {
132                 if (!Directory.Exists(path)) continue;
133                 string[] ConfigFiles = Directory.GetFiles(path, "*.conf");
134                 foreach (string file in ConfigFiles) {
135                     LoadFile(file);
136                 }
137             }
138             if (Options.ContainsKey("config"))
139                 LoadFile(Options["config"]);
140         }
141
142         public static void LoadFile(string filename) {
143             TextReader f;
144             try {
145                 f = new StreamReader(File.OpenRead(filename));
146             } catch (FileNotFoundException) {
147                 Console.WriteLine("Could not open configuration file {0}", filename);
148                 return;
149             }
150
151             string line;
152             while ((line = f.ReadLine()) != null) {
153                 Match m;
154
155                 line = line.Trim();
156                 m = file_var_re.Match(line);
157                 if (m.Success) {
158                     string key = m.Groups[1].Value;
159                     if (!CommandLineOptions.Contains(key))
160                         ParseOption(key, m.Groups[2].Value);
161                     continue;
162                 }
163
164                 m = file_command_re.Match(line);
165                 if (m.Success) {
166                     string cmd = m.Groups[1].Value;
167                     switch(cmd) {
168                     case "Plugin":
169                     case "plugin":
170                         Plugins.Add(m.Groups[2].Value);
171                         break;
172                     default:
173                         Console.WriteLine("Unknown Command in {0}: {1}", filename, line);
174                         break;
175                     }
176                     continue;
177                 }
178             }
179
180             f.Close();
181         }
182     }
183 }