Move and rename xrdp_load_keyboard_layout()

xrdp_load_keyboard_layout() is used exclusively by the xup module to
work out the parameters to pass to xorgxrdp for XKB. This function
does not need to be called locally from the SEC module.

This commit moves the function to xrdp/lang.c and renames it as
xrdp_init_xkb_layout(). The module interface is modified so that xup can
call this function. Other modules do not need to call it.
This commit is contained in:
matt335672 2024-06-24 14:55:49 +01:00
parent d83fc8a93f
commit c9a2039858
10 changed files with 290 additions and 246 deletions

View File

@ -155,246 +155,6 @@ hex_str_to_bin(char *in, char *out, int out_len)
}
}
/*****************************************************************************/
static void
xrdp_load_keyboard_layout(struct xrdp_client_info *client_info)
{
int fd;
int index = 0;
int bytes;
struct list *names = (struct list *)NULL;
struct list *items = (struct list *)NULL;
struct list *values = (struct list *)NULL;
char *item = (char *)NULL;
char *value = (char *)NULL;
char *q = (char *)NULL;
char keyboard_cfg_file[256] = { 0 };
char rdp_layout[256] = { 0 };
const struct xrdp_keyboard_overrides *ko =
&client_info->xrdp_keyboard_overrides;
LOG(LOG_LEVEL_INFO, "xrdp_load_keyboard_layout: Keyboard information sent"
" by the RDP client, keyboard_type:[0x%02X], keyboard_subtype:[0x%02X],"
" keylayout:[0x%08X]",
client_info->keyboard_type, client_info->keyboard_subtype,
client_info->keylayout);
if (ko->type != -1)
{
LOG(LOG_LEVEL_INFO, "overrode keyboard_type 0x%02X"
" with 0x%02X", client_info->keyboard_type, ko->type);
client_info->keyboard_type = ko->type;
}
if (ko->subtype != -1)
{
LOG(LOG_LEVEL_INFO, "overrode keyboard_subtype 0x%02X"
" with 0x%02X", client_info->keyboard_subtype,
ko->subtype);
client_info->keyboard_subtype = ko->subtype;
}
if (ko->layout != -1)
{
LOG(LOG_LEVEL_INFO, "overrode keylayout 0x%08X"
" with 0x%08X", client_info->keylayout, ko->layout);
client_info->keylayout = ko->layout;
}
/* infer model/variant */
/* TODO specify different X11 keyboard models/variants */
g_memset(client_info->model, 0, sizeof(client_info->model));
g_memset(client_info->variant, 0, sizeof(client_info->variant));
g_strncpy(client_info->layout, "us", sizeof(client_info->layout) - 1);
if (client_info->keyboard_subtype == 3)
{
/* macintosh keyboard */
bytes = sizeof(client_info->variant);
g_strncpy(client_info->variant, "mac", bytes - 1);
}
else if (client_info->keyboard_subtype == 0)
{
/* default - standard subtype */
client_info->keyboard_subtype = 1;
}
g_snprintf(keyboard_cfg_file, 255, "%s/xrdp_keyboard.ini", XRDP_CFG_PATH);
LOG(LOG_LEVEL_DEBUG, "keyboard_cfg_file %s", keyboard_cfg_file);
fd = g_file_open_ro(keyboard_cfg_file);
if (fd >= 0)
{
int section_found = -1;
char section_rdp_layouts[256] = { 0 };
char section_layouts_map[256] = { 0 };
names = list_create();
names->auto_free = 1;
items = list_create();
items->auto_free = 1;
values = list_create();
values->auto_free = 1;
file_read_sections(fd, names);
for (index = 0; index < names->count; index++)
{
q = (char *)list_get_item(names, index);
if (g_strncasecmp("default", q, 8) != 0)
{
int i;
file_read_section(fd, q, items, values);
for (i = 0; i < items->count; i++)
{
item = (char *)list_get_item(items, i);
value = (char *)list_get_item(values, i);
LOG(LOG_LEVEL_DEBUG, "xrdp_load_keyboard_layout: item %s value %s",
item, value);
if (g_strcasecmp(item, "keyboard_type") == 0)
{
int v = g_atoi(value);
if (v == client_info->keyboard_type)
{
section_found = index;
}
}
else if (g_strcasecmp(item, "keyboard_subtype") == 0)
{
int v = g_atoi(value);
if (v != client_info->keyboard_subtype &&
section_found == index)
{
section_found = -1;
break;
}
}
else if (g_strcasecmp(item, "rdp_layouts") == 0)
{
if (section_found != -1 && section_found == index)
{
g_strncpy(section_rdp_layouts, value, 255);
}
}
else if (g_strcasecmp(item, "layouts_map") == 0)
{
if (section_found != -1 && section_found == index)
{
g_strncpy(section_layouts_map, value, 255);
}
}
else if (g_strcasecmp(item, "model") == 0)
{
if (section_found != -1 && section_found == index)
{
bytes = sizeof(client_info->model);
g_memset(client_info->model, 0, bytes);
g_strncpy(client_info->model, value, bytes - 1);
}
}
else if (g_strcasecmp(item, "variant") == 0)
{
if (section_found != -1 && section_found == index)
{
bytes = sizeof(client_info->variant);
g_memset(client_info->variant, 0, bytes);
g_strncpy(client_info->variant, value, bytes - 1);
}
}
else if (g_strcasecmp(item, "options") == 0)
{
if (section_found != -1 && section_found == index)
{
bytes = sizeof(client_info->options);
g_memset(client_info->options, 0, bytes);
g_strncpy(client_info->options, value, bytes - 1);
}
}
else
{
/*
* mixing items from different sections will result in
* skipping over current section.
*/
LOG(LOG_LEVEL_DEBUG, "xrdp_load_keyboard_layout: skipping "
"configuration item - %s, continuing to next "
"section", item);
break;
}
}
list_clear(items);
list_clear(values);
}
}
if (section_found == -1)
{
g_memset(section_rdp_layouts, 0, sizeof(char) * 256);
g_memset(section_layouts_map, 0, sizeof(char) * 256);
// read default section
file_read_section(fd, "default", items, values);
for (index = 0; index < items->count; index++)
{
item = (char *)list_get_item(items, index);
value = (char *)list_get_item(values, index);
if (g_strcasecmp(item, "rdp_layouts") == 0)
{
g_strncpy(section_rdp_layouts, value, 255);
}
else if (g_strcasecmp(item, "layouts_map") == 0)
{
g_strncpy(section_layouts_map, value, 255);
}
}
list_clear(items);
list_clear(values);
}
/* load the map */
file_read_section(fd, section_rdp_layouts, items, values);
for (index = 0; index < items->count; index++)
{
int rdp_layout_id;
item = (char *)list_get_item(items, index);
value = (char *)list_get_item(values, index);
rdp_layout_id = g_htoi(value);
if (rdp_layout_id == client_info->keylayout)
{
g_strncpy(rdp_layout, item, 255);
break;
}
}
list_clear(items);
list_clear(values);
file_read_section(fd, section_layouts_map, items, values);
for (index = 0; index < items->count; index++)
{
item = (char *)list_get_item(items, index);
value = (char *)list_get_item(values, index);
if (g_strcasecmp(item, rdp_layout) == 0)
{
bytes = sizeof(client_info->layout);
g_strncpy(client_info->layout, value, bytes - 1);
break;
}
}
list_delete(names);
list_delete(items);
list_delete(values);
LOG(LOG_LEVEL_INFO, "xrdp_load_keyboard_layout: model [%s] variant [%s] "
"layout [%s] options [%s]", client_info->model,
client_info->variant, client_info->layout, client_info->options);
g_file_close(fd);
}
else
{
LOG(LOG_LEVEL_ERROR, "xrdp_load_keyboard_layout: error opening %s",
keyboard_cfg_file);
}
}
/*****************************************************************************/
struct xrdp_sec *
xrdp_sec_create(struct xrdp_rdp *owner, struct trans *trans)
@ -2496,7 +2256,6 @@ xrdp_sec_in_mcs_data(struct xrdp_sec *self)
client_info->keyboard_type,
client_info->keyboard_subtype);
xrdp_load_keyboard_layout(client_info);
s->p = s->data;
return 0;

View File

@ -30,6 +30,7 @@
#define CURRENT_MOD_VER 3
struct source_info;
struct xrdp_client_info;
/* Defined in xrdp_client_info.h */
struct monitor_info;
@ -98,7 +99,9 @@ struct mod
int total_data_len, int flags);
int (*server_bell_trigger)(struct mod *v);
int (*server_chansrv_in_use)(struct mod *v);
tintptr server_dumby[100 - 28]; /* align, 100 minus the number of server
void (*server_init_xkb_layout)(struct mod *v,
struct xrdp_client_info *client_info);
tintptr server_dumby[100 - 29]; /* align, 100 minus the number of server
functions above */
/* common */
tintptr handle; /* pointer to self as long */

View File

@ -143,6 +143,8 @@ struct mod
int total_data_len, int flags);
int (*server_bell_trigger)(struct mod *v);
int (*server_chansrv_in_use)(struct mod *v);
void (*server_init_xkb_layout)(struct mod *v,
struct xrdp_client_info *client_info);
/* off screen bitmaps */
int (*server_create_os_surface)(struct mod *v, int rdpindex,
int width, int height);
@ -197,7 +199,7 @@ struct mod
int flags, int frame_id);
int (*server_session_info)(struct mod *v, const char *data,
int data_bytes);
tintptr server_dumby[100 - 47]; /* align, 100 minus the number of server
tintptr server_dumby[100 - 48]; /* align, 100 minus the number of server
functions above */
/* common */
tintptr handle; /* pointer to self as long */

View File

@ -69,6 +69,7 @@ enum vnc_resize_support_status
};
struct source_info;
struct xrdp_client_info;
/* Defined in vnc_clip.c */
struct vnc_clipboard_data;
@ -151,7 +152,9 @@ struct vnc
int total_data_len, int flags);
int (*server_bell_trigger)(struct vnc *v);
int (*server_chansrv_in_use)(struct vnc *v);
tintptr server_dumby[100 - 28]; /* align, 100 minus the number of server
void (*server_init_xkb_layout)(struct vnc *v,
struct xrdp_client_info *client_info);
tintptr server_dumby[100 - 29]; /* align, 100 minus the number of server
functions above */
/* common */
tintptr handle; /* pointer to self as long */

View File

@ -414,3 +414,243 @@ km_load_file(const char *filename, struct xrdp_keymap *keymap)
return rv;
}
/*****************************************************************************/
void
xrdp_init_xkb_layout(struct xrdp_client_info *client_info)
{
int fd;
int index = 0;
int bytes;
struct list *names = (struct list *)NULL;
struct list *items = (struct list *)NULL;
struct list *values = (struct list *)NULL;
char *item = (char *)NULL;
char *value = (char *)NULL;
char *q = (char *)NULL;
char keyboard_cfg_file[256] = { 0 };
char rdp_layout[256] = { 0 };
const struct xrdp_keyboard_overrides *ko =
&client_info->xrdp_keyboard_overrides;
LOG(LOG_LEVEL_INFO, "xrdp_init_xkb_layout: Keyboard information sent"
" by the RDP client, keyboard_type:[0x%02X], keyboard_subtype:[0x%02X],"
" keylayout:[0x%08X]",
client_info->keyboard_type, client_info->keyboard_subtype,
client_info->keylayout);
if (ko->type != -1)
{
LOG(LOG_LEVEL_INFO, "overrode keyboard_type 0x%02X"
" with 0x%02X", client_info->keyboard_type, ko->type);
client_info->keyboard_type = ko->type;
}
if (ko->subtype != -1)
{
LOG(LOG_LEVEL_INFO, "overrode keyboard_subtype 0x%02X"
" with 0x%02X", client_info->keyboard_subtype,
ko->subtype);
client_info->keyboard_subtype = ko->subtype;
}
if (ko->layout != -1)
{
LOG(LOG_LEVEL_INFO, "overrode keylayout 0x%08X"
" with 0x%08X", client_info->keylayout, ko->layout);
client_info->keylayout = ko->layout;
}
/* infer model/variant */
/* TODO specify different X11 keyboard models/variants */
g_memset(client_info->model, 0, sizeof(client_info->model));
g_memset(client_info->variant, 0, sizeof(client_info->variant));
g_strncpy(client_info->layout, "us", sizeof(client_info->layout) - 1);
if (client_info->keyboard_subtype == 3)
{
/* macintosh keyboard */
bytes = sizeof(client_info->variant);
g_strncpy(client_info->variant, "mac", bytes - 1);
}
else if (client_info->keyboard_subtype == 0)
{
/* default - standard subtype */
client_info->keyboard_subtype = 1;
}
g_snprintf(keyboard_cfg_file, 255, "%s/xrdp_keyboard.ini", XRDP_CFG_PATH);
LOG(LOG_LEVEL_DEBUG, "keyboard_cfg_file %s", keyboard_cfg_file);
fd = g_file_open_ro(keyboard_cfg_file);
if (fd >= 0)
{
int section_found = -1;
char section_rdp_layouts[256] = { 0 };
char section_layouts_map[256] = { 0 };
names = list_create();
names->auto_free = 1;
items = list_create();
items->auto_free = 1;
values = list_create();
values->auto_free = 1;
file_read_sections(fd, names);
for (index = 0; index < names->count; index++)
{
q = (char *)list_get_item(names, index);
if (g_strncasecmp("default", q, 8) != 0)
{
int i;
file_read_section(fd, q, items, values);
for (i = 0; i < items->count; i++)
{
item = (char *)list_get_item(items, i);
value = (char *)list_get_item(values, i);
LOG(LOG_LEVEL_DEBUG, "xrdp_init_xkb_layout: item %s value %s",
item, value);
if (g_strcasecmp(item, "keyboard_type") == 0)
{
int v = g_atoi(value);
if (v == client_info->keyboard_type)
{
section_found = index;
}
}
else if (g_strcasecmp(item, "keyboard_subtype") == 0)
{
int v = g_atoi(value);
if (v != client_info->keyboard_subtype &&
section_found == index)
{
section_found = -1;
break;
}
}
else if (g_strcasecmp(item, "rdp_layouts") == 0)
{
if (section_found != -1 && section_found == index)
{
g_strncpy(section_rdp_layouts, value, 255);
}
}
else if (g_strcasecmp(item, "layouts_map") == 0)
{
if (section_found != -1 && section_found == index)
{
g_strncpy(section_layouts_map, value, 255);
}
}
else if (g_strcasecmp(item, "model") == 0)
{
if (section_found != -1 && section_found == index)
{
bytes = sizeof(client_info->model);
g_memset(client_info->model, 0, bytes);
g_strncpy(client_info->model, value, bytes - 1);
}
}
else if (g_strcasecmp(item, "variant") == 0)
{
if (section_found != -1 && section_found == index)
{
bytes = sizeof(client_info->variant);
g_memset(client_info->variant, 0, bytes);
g_strncpy(client_info->variant, value, bytes - 1);
}
}
else if (g_strcasecmp(item, "options") == 0)
{
if (section_found != -1 && section_found == index)
{
bytes = sizeof(client_info->options);
g_memset(client_info->options, 0, bytes);
g_strncpy(client_info->options, value, bytes - 1);
}
}
else
{
/*
* mixing items from different sections will result in
* skipping over current section.
*/
LOG(LOG_LEVEL_DEBUG, "xrdp_init_xkb_layout: skipping "
"configuration item - %s, continuing to next "
"section", item);
break;
}
}
list_clear(items);
list_clear(values);
}
}
if (section_found == -1)
{
g_memset(section_rdp_layouts, 0, sizeof(char) * 256);
g_memset(section_layouts_map, 0, sizeof(char) * 256);
// read default section
file_read_section(fd, "default", items, values);
for (index = 0; index < items->count; index++)
{
item = (char *)list_get_item(items, index);
value = (char *)list_get_item(values, index);
if (g_strcasecmp(item, "rdp_layouts") == 0)
{
g_strncpy(section_rdp_layouts, value, 255);
}
else if (g_strcasecmp(item, "layouts_map") == 0)
{
g_strncpy(section_layouts_map, value, 255);
}
}
list_clear(items);
list_clear(values);
}
/* load the map */
file_read_section(fd, section_rdp_layouts, items, values);
for (index = 0; index < items->count; index++)
{
int rdp_layout_id;
item = (char *)list_get_item(items, index);
value = (char *)list_get_item(values, index);
rdp_layout_id = g_htoi(value);
if (rdp_layout_id == client_info->keylayout)
{
g_strncpy(rdp_layout, item, 255);
break;
}
}
list_clear(items);
list_clear(values);
file_read_section(fd, section_layouts_map, items, values);
for (index = 0; index < items->count; index++)
{
item = (char *)list_get_item(items, index);
value = (char *)list_get_item(values, index);
if (g_strcasecmp(item, rdp_layout) == 0)
{
bytes = sizeof(client_info->layout);
g_strncpy(client_info->layout, value, bytes - 1);
break;
}
}
list_delete(names);
list_delete(items);
list_delete(values);
LOG(LOG_LEVEL_INFO, "xrdp_init_xkb_layout: model [%s] variant [%s] "
"layout [%s] options [%s]", client_info->model,
client_info->variant, client_info->layout, client_info->options);
g_file_close(fd);
}
else
{
LOG(LOG_LEVEL_ERROR, "xrdp_init_xkb_layout: error opening %s",
keyboard_cfg_file);
}
}

View File

@ -447,6 +447,19 @@ get_keymaps(int keylayout, struct xrdp_keymap *keymap);
int
km_load_file(const char *filename, struct xrdp_keymap *keymap);
/**
* initialise the XKB layout
*
* Not all backends need to use XKB for keyboard mapping. This
* call is used by those modules that do need an XKB mapping.
*
* Other modules and the login screen use other routines in
* lang.c to interpret incoming RDP scancodes
* @param client_info Client info struct to initialise
*/
void
xrdp_init_xkb_layout(struct xrdp_client_info *client_info);
/* xrdp_login_wnd.c */
/**
* Gets the DPI of the login (primary) monitor
@ -528,6 +541,9 @@ int
server_bell_trigger(struct xrdp_mod *mod);
int
server_chansrv_in_use(struct xrdp_mod *mod);
void
server_init_xkb_layout(struct xrdp_mod *mod,
struct xrdp_client_info *client_info);
int
server_fill_rect(struct xrdp_mod *mod, int x, int y, int cx, int cy);
int

View File

@ -384,6 +384,7 @@ xrdp_mm_setup_mod1(struct xrdp_mm *self)
self->mod->server_end_update = server_end_update;
self->mod->server_bell_trigger = server_bell_trigger;
self->mod->server_chansrv_in_use = server_chansrv_in_use;
self->mod->server_init_xkb_layout = server_init_xkb_layout;
self->mod->server_fill_rect = server_fill_rect;
self->mod->server_screen_blt = server_screen_blt;
self->mod->server_paint_rect = server_paint_rect;
@ -3986,6 +3987,15 @@ server_chansrv_in_use(struct xrdp_mod *mod)
return wm->mm->use_chansrv;
}
/*****************************************************************************/
/* Init the XKB layout */
void
server_init_xkb_layout(struct xrdp_mod *mod,
struct xrdp_client_info *client_info)
{
xrdp_init_xkb_layout(client_info);
}
/*****************************************************************************/
int

View File

@ -124,6 +124,8 @@ struct xrdp_mod
int total_data_len, int flags);
int (*server_bell_trigger)(struct xrdp_mod *v);
int (*server_chansrv_in_use)(struct xrdp_mod *v);
void (*server_init_xkb_layout)(struct xrdp_mod *v,
struct xrdp_client_info *client_info);
/* off screen bitmaps */
int (*server_create_os_surface)(struct xrdp_mod *v, int rdpindex,
int width, int height);
@ -192,7 +194,7 @@ struct xrdp_mod
int (*server_egfx_cmd)(struct xrdp_mod *v,
char *cmd, int cmd_bytes,
char *data, int data_bytes);
tintptr server_dumby[100 - 50]; /* align, 100 minus the number of server
tintptr server_dumby[100 - 51]; /* align, 100 minus the number of server
functions above */
/* common */
tintptr handle; /* pointer to self as int */

View File

@ -171,6 +171,12 @@ lib_mod_connect(struct mod *mod)
return 1;
}
// This is a good place to finalise any parameters that need to
// be set.
//
// Load the XKB layout
mod->server_init_xkb_layout(mod, &(mod->client_info));
make_stream(s);
g_sprintf(con_port, "%s", mod->port);

View File

@ -34,6 +34,7 @@
#define CURRENT_MOD_VER 4
struct source_info;
struct xrdp_client_info;
struct mod
{
@ -111,6 +112,8 @@ struct mod
int total_data_len, int flags);
int (*server_bell_trigger)(struct mod *v);
int (*server_chansrv_in_use)(struct mod *v);
void (*server_init_xkb_layout)(struct mod *v,
struct xrdp_client_info *client_info);
/* off screen bitmaps */
int (*server_create_os_surface)(struct mod *v, int rdpindex,
int width, int height);
@ -176,7 +179,7 @@ struct mod
int (*server_egfx_cmd)(struct mod *v,
char *cmd, int cmd_bytes,
char *data, int data_bytes);
tintptr server_dumby[100 - 50]; /* align, 100 minus the number of server
tintptr server_dumby[100 - 51]; /* align, 100 minus the number of server
functions above */
/* common */
tintptr handle; /* pointer to self as long */