FreeRDP
fetch_language_identifiers.py
1 #!/bin/env python3
2 #
3 # This is a helper script that fetches the current language and keyboard tables
4 # and writes the result to a C compatible struct.
5 #
6 import os
7 import sys
8 import requests
9 import numpy as np
10 import traceback
11 from bs4 import BeautifulSoup
12 from bs4 import element
13 
14 intro = '''/* This file is auto generated from
15  *
16  * https://docs.microsoft.com/en-us/windows/win32/intl/language-identifier-constants-and-strings
17  *
18  * please do not edit but use ./scripts/fetch_language_identifiers.py to regenerate!
19  */
20 
21 '''
22 
23 def parse_html(text):
24  soup = BeautifulSoup(text, 'html.parser')
25  table = soup.find("table")
26  head = table.find('thead').find('tr')
27  headers = []
28  for th in head:
29  if type(th) == element.Tag:
30  headers += th
31 
32  body = table.find('tbody')
33  languages = []
34 
35  for tr in body:
36  if type(tr) == element.Tag:
37  entry = []
38  for th in tr:
39  if type(th) == element.Tag:
40  if th.string:
41  entry += [th.string]
42  else:
43  entry += ['']
44  languages += [entry]
45  return [headers, languages]
46 
47 def is_base(num, base):
48  try:
49  v = int(num, base)
50  return True
51  except ValueError:
52  return False
53 
54 def padhexa(v):
55  s = hex(v)
56  return '0x' + s[2:].zfill(8)
57 
58 def write_struct(fp, struct, name, url, base, inv = False, typemap = None):
59  li = requests.get(url)
60  if li.status_code != requests.codes.ok:
61  print('Could not fetch ' + str(url) + ', reponse code ' + str(li.status_code))
62  sys.exit(1)
63  headers, languages = parse_html(li.text)
64 
65  fp.write('const ' + str(struct) + ' ' + str(name) + '[] =\n')
66  fp.write('{\n')
67  fp.write('/* ')
68  for h in headers:
69  fp.write('\t[')
70  fp.write(h)
71  fp.write(']\t')
72  fp.write('*/\n')
73  last = [None] * 32
74  for language in languages:
75  fp.write('\t{ ')
76  line = ''
77  pos = 0
78  for e in language:
79  try:
80  v = int(e, base=base)
81  switcher = {
82  0: padhexa(v),
83  2: bin(v),
84  8: oct(v),
85  10: str(v),
86  16: padhexa(v)
87  }
88  h = str(switcher.get(base))
89  if h != "None":
90  last[pos] = h
91  if inv:
92  line = h + ', ' + line
93  else:
94  line += h + ', '
95  except ValueError:
96  if typemap and typemap[pos] != str:
97  line += str(last[pos]) + ',\t'
98  else:
99  if e == "":
100  line += '"' + str(last[pos]) + '",\t'
101  else:
102  line += '"' + e + '",\t'
103  if e != "None":
104  last[pos] = str(e)
105  pos = pos + 1
106  fp.write(line[:-2] + '},\n')
107  fp.write('};\n')
108  fp.write('\n')
109 
110 def update_lang_identifiers(fp):
111 # [Language identifier] [Primary language] [Prim. lang. identifier] [Prim. lang. symbol] [Sublanguage] [Sublang. identifier] [Sublang. symbol]
112  write_struct(fp, 'LanguageIdentifier', 'language_identifiers', 'https://docs.microsoft.com/en-us/windows/win32/intl/language-identifier-constants-and-strings', 16, False, [int, str, int, str, str, int, str])
113 
114 def update_code_pages(fp):
115  write_struct(fp, 'CodePage', 'code_pages', 'https://docs.microsoft.com/en-us/windows/win32/intl/code-page-identifiers', 10)
116 
117 def update_input_locales(fp):
118  write_struct(fp, 'KeyboardIdentifier', 'keyboard_identifiers', 'https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-vista/cc766503(v=ws.10)', 0)
119  write_struct(fp, 'RDP_KEYBOARD_LAYOUT', 'RDP_KEYBOARD_LAYOUT_TABLE', 'https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/windows-language-pack-default-values', 16, True)
120 
121 try:
122  with open('language_identifiers.c', 'w') as fp:
123  fp.write(intro)
124  update_lang_identifiers(fp)
125  update_code_pages(fp)
126  update_input_locales(fp)
127 except:
128  print('exception cought')
129  traceback.print_exc()