1 /**
2  * xrdp: A Remote Desktop Protocol server.
3  *
4  * Copyright (C) Jay Sorg 2004-2014
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * keylayout
19  * maximum unicode 19996(0x4e00)
20  */
21 
22 #if defined(HAVE_CONFIG_H)
23 #include <config_ac.h>
24 #endif
25 
26 #include "xrdp.h"
27 #include "ms-rdpbcgr.h"
28 #include "log.h"
29 #include "string_calls.h"
30 
31 /* map for rdp to x11 scancodes
32    code1 is regular scancode, code2 is extended scancode */
33 struct codepair
34 {
35     tui8 code1;
36     tui8 code2;
37 };
38 static struct codepair g_map[] =
39 {
40     { 0, 0 }, { 9, 0 }, { 10, 0 }, { 11, 0 }, { 12, 0 }, /* 0 - 4 */
41     { 13, 0 }, { 14, 0 }, { 15, 0 }, { 16, 0 }, { 17, 0 }, /* 5 - 9 */
42     { 18, 0 }, { 19, 0 }, { 20, 0 }, { 21, 0 }, { 22, 0 }, /* 10 - 14 */
43     { 23, 0 }, { 24, 0 }, { 25, 0 }, { 26, 0 }, { 27, 0 }, /* 15 - 19 */
44     { 28, 0 }, { 29, 0 }, { 30, 0 }, { 31, 0 }, { 32, 0 }, /* 20 - 24 */
45     { 33, 0 }, { 34, 0 }, { 35, 0 }, { 36, 108 }, { 37, 109 }, /* 25 - 29 */
46     { 38, 0 }, { 39, 0 }, { 40, 0 }, { 41, 0 }, { 42, 0 }, /* 30 - 34 */
47     { 43, 0 }, { 44, 0 }, { 45, 0 }, { 46, 0 }, { 47, 0 }, /* 35 - 39 */
48     { 48, 0 }, { 49, 0 }, { 50, 0 }, { 51, 0 }, { 52, 0 }, /* 40 - 44 */
49     { 53, 0 }, { 54, 0 }, { 55, 0 }, { 56, 0 }, { 57, 0 }, /* 45 - 49 */
50     { 58, 0 }, { 59, 0 }, { 60, 0 }, { 61, 112 }, { 62, 0 }, /* 50 - 54 */
51     { 63, 111 }, { 64, 113 }, { 65, 0 }, { 66, 0 }, { 67, 0 }, /* 55 - 59 */
52     { 68, 0 }, { 69, 0 }, { 70, 0 }, { 71, 0 }, { 72, 0 }, /* 60 - 64 */
53     { 73, 0 }, { 74, 0 }, { 75, 0 }, { 76, 0 }, { 77, 0 }, /* 65 - 69 */
54     { 78, 0 }, { 79, 97 }, { 80, 98 }, { 81, 99 }, { 82, 0 }, /* 70 - 74 */
55     { 83, 100 }, { 84, 0 }, { 85, 102 }, { 86, 0 }, { 87, 103 }, /* 75 - 79 */
56     { 88, 104 }, { 89, 105 }, { 90, 106 }, { 91, 107 }, { 92, 0 }, /* 80 - 84 */
57     { 93, 0 }, { 94, 0 }, { 95, 0 }, { 96, 0 }, { 97, 0 }, /* 85 - 89 */
58     { 98, 0 }, { 0, 115 }, { 0, 116 }, { 0, 117 }, { 102, 0 }, /* 90 - 94 */
59     { 103, 0 }, { 104, 0 }, { 105, 0 }, { 106, 0 }, { 107, 0 }, /* 95 - 99 */
60     { 108, 0 }, { 109, 0 }, { 110, 0 }, { 111, 0 }, { 112, 0 }, /* 100 - 104 */
61     { 113, 0 }, { 114, 0 }, { 115, 0 }, { 116, 0 }, { 117, 0 }, /* 105 - 109 */
62     { 118, 0 }, { 119, 0 }, { 120, 0 }, { 121, 0 }, { 122, 0 }, /* 110 - 114 */
63     { 123, 0 }, { 124, 0 }, { 125, 0 }, { 126, 0 }, { 127, 0 }, /* 115 - 119 */
64     { 128, 0 }, { 129, 0 }, { 130, 0 }, { 131, 0 }, { 132, 0 }, /* 120 - 124 */
65     { 133, 0 }, { 134, 0 }, { 135, 0 } /* 125 - 127 */
66 };
67 
68 /*****************************************************************************/
69 struct xrdp_key_info *
get_key_info_from_scan_code(int device_flags,int scan_code,int * keys,int caps_lock,int num_lock,int scroll_lock,struct xrdp_keymap * keymap)70 get_key_info_from_scan_code(int device_flags, int scan_code, int *keys,
71                             int caps_lock, int num_lock, int scroll_lock,
72                             struct xrdp_keymap *keymap)
73 {
74     struct xrdp_key_info *rv;
75     int shift;
76     int altgr;
77     int ext;
78     int index;
79 
80     ext = device_flags & KBD_FLAG_EXT;  /* 0x0100 */
81     shift = keys[42] || keys[54];
82     altgr = keys[56] & KBD_FLAG_EXT;  /* right alt */
83     rv = 0;
84     scan_code = scan_code & 0x7f;
85     index = ext ? g_map[scan_code].code2 : g_map[scan_code].code1;
86 
87     /* keymap file is created with numlock off so we have to do this */
88     if ((index >= 79) && (index <= 91))
89     {
90         if (num_lock)
91         {
92             rv = &(keymap->keys_shift[index]);
93         }
94         else
95         {
96             rv = &(keymap->keys_noshift[index]);
97         }
98     }
99     else if (shift && caps_lock && altgr)
100     {
101         rv = &(keymap->keys_shiftcapslockaltgr[index]);
102     }
103     else if (shift && caps_lock)
104     {
105         rv = &(keymap->keys_shiftcapslock[index]);
106     }
107     else if (shift && altgr)
108     {
109         rv = &(keymap->keys_shiftaltgr[index]);
110     }
111     else if (shift)
112     {
113         rv = &(keymap->keys_shift[index]);
114     }
115     else if (caps_lock && altgr)
116     {
117         rv = &(keymap->keys_capslockaltgr[index]);
118     }
119     else if (caps_lock)
120     {
121         rv = &(keymap->keys_capslock[index]);
122     }
123     else if (altgr)
124     {
125         rv = &(keymap->keys_altgr[index]);
126     }
127     else
128     {
129         rv = &(keymap->keys_noshift[index]);
130     }
131 
132     return rv;
133 }
134 
135 /*****************************************************************************/
136 int
get_keysym_from_scan_code(int device_flags,int scan_code,int * keys,int caps_lock,int num_lock,int scroll_lock,struct xrdp_keymap * keymap)137 get_keysym_from_scan_code(int device_flags, int scan_code, int *keys,
138                           int caps_lock, int num_lock, int scroll_lock,
139                           struct xrdp_keymap *keymap)
140 {
141     struct xrdp_key_info *ki;
142 
143     ki = get_key_info_from_scan_code(device_flags, scan_code, keys,
144                                      caps_lock, num_lock, scroll_lock,
145                                      keymap);
146 
147     if (ki == 0)
148     {
149         return 0;
150     }
151 
152     return ki->sym;
153 }
154 
155 /*****************************************************************************/
156 twchar
get_char_from_scan_code(int device_flags,int scan_code,int * keys,int caps_lock,int num_lock,int scroll_lock,struct xrdp_keymap * keymap)157 get_char_from_scan_code(int device_flags, int scan_code, int *keys,
158                         int caps_lock, int num_lock, int scroll_lock,
159                         struct xrdp_keymap *keymap)
160 {
161     struct xrdp_key_info *ki;
162 
163     ki = get_key_info_from_scan_code(device_flags, scan_code, keys,
164                                      caps_lock, num_lock, scroll_lock,
165                                      keymap);
166 
167     if (ki == 0)
168     {
169         return 0;
170     }
171 
172     return (twchar)(ki->chr);
173 }
174 
175 /*****************************************************************************/
176 static int
km_read_section(int fd,const char * section_name,struct xrdp_key_info * keymap)177 km_read_section(int fd, const char *section_name, struct xrdp_key_info *keymap)
178 {
179     struct list *names;
180     struct list *values;
181     int index;
182     int code;
183     int pos1;
184     char *name;
185     char *value;
186 
187     names = list_create();
188     names->auto_free = 1;
189     values = list_create();
190     values->auto_free = 1;
191 
192     if (file_read_section(fd, section_name, names, values) == 0)
193     {
194         for (index = names->count - 1; index >= 0; index--)
195         {
196             name = (char *)list_get_item(names, index);
197             value = (char *)list_get_item(values, index);
198 
199             if ((name != 0) && (value != 0))
200             {
201                 if (g_strncasecmp(name, "key", 3) == 0)
202                 {
203                     code = g_atoi(name + 3);
204                 }
205                 else
206                 {
207                     code = g_atoi(name);
208                 }
209 
210                 if ((code >= 0) && (code < 256))
211                 {
212                     pos1 = g_pos(value, ":");
213 
214                     if (pos1 >= 0)
215                     {
216                         keymap[code].chr = g_atoi(value + pos1 + 1);
217                     }
218 
219                     keymap[code].sym = g_atoi(value);
220                 }
221             }
222         }
223     }
224 
225     list_delete(names);
226     list_delete(values);
227     return 0;
228 }
229 
230 /*****************************************************************************/
231 int
get_keymaps(int keylayout,struct xrdp_keymap * keymap)232 get_keymaps(int keylayout, struct xrdp_keymap *keymap)
233 {
234     int fd;
235     int basic_key_layout = keylayout & 0x0000ffff;
236     char *filename;
237     struct xrdp_keymap *lkeymap;
238 
239     filename = (char *)g_malloc(256, 0);
240 
241     /* check if there is a keymap file e.g. km-e00100411.ini */
242     g_snprintf(filename, 255, "%s/km-%08x.ini", XRDP_CFG_PATH, keylayout);
243 
244     /* if the file does not exist, use only lower 16 bits instead */
245     if (!g_file_exist(filename))
246     {
247         LOG(LOG_LEVEL_WARNING, "Cannot find keymap file %s", filename);
248         /* e.g. km-00000411.ini */
249         g_snprintf(filename, 255, "%s/km-%08x.ini", XRDP_CFG_PATH, basic_key_layout);
250     }
251 
252     /* finally, use 'en-us' */
253     if (!g_file_exist(filename))
254     {
255         LOG(LOG_LEVEL_WARNING, "Cannot find keymap file %s", filename);
256         g_snprintf(filename, 255, "%s/km-00000409.ini", XRDP_CFG_PATH);
257     }
258 
259     if (g_file_exist(filename))
260     {
261         fd = g_file_open(filename);
262         LOG(LOG_LEVEL_INFO, "Loading keymap file %s", filename);
263 
264         if (fd != -1)
265         {
266             lkeymap = (struct xrdp_keymap *)g_malloc(sizeof(struct xrdp_keymap), 0);
267             /* make a copy of the built-in keymap */
268             g_memcpy(lkeymap, keymap, sizeof(struct xrdp_keymap));
269             /* clear the keymaps */
270             g_memset(keymap, 0, sizeof(struct xrdp_keymap));
271             /* read the keymaps */
272             km_read_section(fd, "noshift", keymap->keys_noshift);
273             km_read_section(fd, "shift", keymap->keys_shift);
274             km_read_section(fd, "altgr", keymap->keys_altgr);
275             km_read_section(fd, "shiftaltgr", keymap->keys_shiftaltgr);
276             km_read_section(fd, "capslock", keymap->keys_capslock);
277             km_read_section(fd, "capslockaltgr", keymap->keys_capslockaltgr);
278             km_read_section(fd, "shiftcapslock", keymap->keys_shiftcapslock);
279             km_read_section(fd, "shiftcapslockaltgr", keymap->keys_shiftcapslockaltgr);
280 
281             if (g_memcmp(lkeymap, keymap, sizeof(struct xrdp_keymap)) != 0)
282             {
283                 LOG(LOG_LEVEL_WARNING,
284                     "local keymap file for 0x%08x found and doesn't match "
285                     "built in keymap, using local keymap file", keylayout);
286             }
287 
288             g_free(lkeymap);
289             g_file_close(fd);
290         }
291     }
292     else
293     {
294         LOG(LOG_LEVEL_WARNING, "File does not exist: %s", filename);
295     }
296 
297     g_free(filename);
298     return 0;
299 }
300