FreeRDP
tzextract.cs
1 using System;
2 using System.IO;
3 using System.Net;
4 using System.Text;
5 using System.Xml;
6 using System.Xml.Linq;
7 using System.Xml.Schema;
8 
9 internal class Program
10 {
11  private static string app = AppDomain.CurrentDomain.FriendlyName;
12  private static TextWriter stderr = Console.Error;
13  private static TextWriter stdout = Console.Out;
14 
15  private static void usage()
16  {
17  stderr.WriteLine("Usage:");
18  stderr.WriteLine(app + " <path to output files>");
19  Environment.Exit(1);
20  }
21 
22  private static bool writeZoneMapC(string path)
23  {
24  string fname = "TimeZoneNameMap";
25  string fpath = Path.Combine(path, fname + "_static.h");
26 
27  using (StreamWriter fs = new StreamWriter(fpath))
28  {
29  fs.WriteLine("/* Automatically generated by " + app + " */");
30  fs.WriteLine("");
31  fs.WriteLine("#include \"" + fname + ".h\"");
32  fs.WriteLine("");
33  fs.WriteLine("static const " + fname + "Entry " + fname + "[] ={");
34 
35  bool first = true;
36  foreach (System.TimeZoneInfo tz in System.TimeZoneInfo.GetSystemTimeZones())
37  {
38  string iana;
39  System.TimeZoneInfo.TryConvertWindowsIdToIanaId(tz.Id, out iana);
40 
41  StringBuilder sb = new StringBuilder();
42  if (!first)
43  sb.Append(",");
44  first = false;
45  sb.Append("{ \"");
46  sb.Append(tz.Id);
47  sb.Append("\", \"");
48  sb.Append(tz.StandardName);
49  sb.Append("\", \"");
50  sb.Append(tz.DisplayName);
51  sb.Append("\", \"");
52  sb.Append(tz.DaylightName);
53  sb.Append("\", \"");
54  sb.Append(iana);
55  sb.Append("\" }");
56  fs.WriteLine(sb.ToString());
57  }
58 
59  fs.WriteLine("};");
60  fs.WriteLine("");
61  fs.WriteLine("static const size_t " + fname + "Size = ARRAYSIZE(" + fname + ");");
62  }
63  return true;
64  }
65 
66  private static bool writeZoneMapJSON(string path)
67  {
68  string fname = "TimeZoneNameMap";
69  string fpath = Path.Combine(path, fname + ".json");
70 
71  using (StreamWriter fs = new StreamWriter(fpath))
72  {
73  fs.WriteLine("{");
74  fs.WriteLine("\"TimeZoneNameMap\": [");
75 
76  bool first = true;
77  foreach (System.TimeZoneInfo tz in System.TimeZoneInfo.GetSystemTimeZones())
78  {
79  string iana;
80  System.TimeZoneInfo.TryConvertWindowsIdToIanaId(tz.Id, out iana);
81 
82  StringBuilder sb = new StringBuilder();
83  if (!first)
84  sb.Append(",");
85  first = false;
86  sb.Append("{ ");
87  sb.Append("\"Id\": \"");
88  sb.Append(tz.Id);
89  sb.Append("\", \"StandardName\": \"");
90  sb.Append(tz.StandardName);
91  sb.Append("\", \"DisplayName\": \"");
92  sb.Append(tz.DisplayName);
93  sb.Append("\", \"DaylightName\": \"");
94  sb.Append(tz.DaylightName);
95  sb.Append("\", \"Iana\": \"");
96  sb.Append(iana);
97  sb.Append("\" }");
98  fs.WriteLine(sb.ToString());
99  }
100 
101  fs.WriteLine("]");
102  fs.WriteLine("}");
103  }
104  return true;
105  }
106 
107  private static bool writeZoneMap(string path)
108  {
109  if (!writeZoneMapC(path))
110  return false;
111  if (!writeZoneMapJSON(path))
112  return false;
113  return true;
114  }
115 
116  private static void onValidation(object sender, ValidationEventArgs e)
117  {
118  switch (e.Severity)
119  {
120  case XmlSeverityType.Warning:
121  case XmlSeverityType.Error:
122  stderr.WriteLine(e.ToString());
123  break;
124  default:
125  break;
126  }
127  }
128  private static bool updateWindowsIanaMap(string path)
129  {
130  string url =
131  "https://raw.githubusercontent.com/unicode-org/cldr/main/common/supplemental/windowsZones.xml";
132  string fname = "WindowsZones";
133  string fpath = Path.Combine(path, fname + ".c");
134 
135  XmlDocument doc = new XmlDocument();
136  doc.Load(url);
137 
138  stdout.WriteLine("Downloaded and parsed XML from '" + url + "'");
139 
140  ValidationEventHandler handler = new ValidationEventHandler(onValidation);
141  // doc.Validate(handler);
142 
143  XmlNodeList versions = doc.SelectNodes("//supplementalData/version");
144  XmlNodeList zones = doc.SelectNodes("//supplementalData/windowsZones/mapTimezones");
145  XmlNodeList mzones =
146  doc.SelectNodes("//supplementalData/windowsZones/mapTimezones/mapZone");
147 
148  using (StreamWriter fs = new StreamWriter(fpath))
149  {
150  fs.WriteLine("/* Automatically generated by " + app);
151  fs.WriteLine(" *");
152  fs.WriteLine(" * url " + url);
153 
154  foreach (XmlNode version in versions)
155  {
156  XmlNode nr = version.Attributes.GetNamedItem("number");
157  fs.WriteLine(" * version: " + nr.InnerText);
158  }
159 
160  foreach (XmlNode node in zones)
161  {
162  XmlNode over = node.Attributes.GetNamedItem("otherVersion");
163  XmlNode tver = node.Attributes.GetNamedItem("typeVersion");
164  fs.WriteLine(" * mapTimezones: otherVersion: " + over.InnerText +
165  ", typeVersion: " + tver.InnerText);
166  }
167 
168  fs.WriteLine(" */");
169  fs.WriteLine("");
170  fs.WriteLine("#include \"" + fname + ".h\"");
171  fs.WriteLine("");
172  fs.WriteLine("const WINDOWS_TZID_ENTRY " + fname + "[] = {");
173 
174  foreach (XmlNode mzone in mzones)
175  {
176  XmlAttributeCollection attrs = mzone.Attributes;
177  XmlNode wzid = attrs.GetNamedItem("other");
178  XmlNode territory = attrs.GetNamedItem("territory");
179  XmlNode iana = attrs.GetNamedItem("type");
180  fs.WriteLine("\t{ \"" + iana.InnerText + "\", \"" + wzid.InnerText + "\" }, // " +
181  territory.InnerText);
182  }
183 
184  fs.WriteLine("};");
185  fs.WriteLine("");
186  fs.WriteLine("const size_t " + fname + "NrElements = ARRAYSIZE(" + fname + ");");
187  }
188  stdout.WriteLine("Finished update");
189  return true;
190  }
191 
192  private static void Main(string[] args)
193  {
194  try
195  {
196  if (args.Length == 0)
197  {
198  stderr.WriteLine("Missing arguments!");
199  usage();
200  }
201 
202  DirectoryInfo info = new DirectoryInfo(args[0]);
203  if (!info.Exists)
204  {
205  stderr.WriteLine("Path '" + info.FullName + "' does not exist");
206  usage();
207  }
208 
209  if (!writeZoneMap(info.FullName))
210  return;
211 
212  updateWindowsIanaMap(info.FullName);
213  }
214  catch (Exception e)
215  {
216  stderr.WriteLine(e.ToString());
217  Environment.Exit(-23);
218  }
219  }
220 }