Tools: Improve xkbcli help messages and manual pages
[platform/upstream/libxkbcommon.git] / src / registry.c
1 /*
2  * Copyright © 2020 Red Hat, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  */
23
24 #include "config.h"
25
26 #include <sys/stat.h>
27 #include <fcntl.h>
28 #include <stdbool.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <stdint.h>
32 #include <libxml/parser.h>
33
34 #include "xkbcommon/xkbregistry.h"
35 #include "utils.h"
36 #include "util-list.h"
37
38 struct rxkb_object;
39
40 typedef void (*destroy_func_t)(struct rxkb_object *object);
41
42 /**
43  * All our objects are refcounted and are linked to iterate through them.
44  * Abstract those bits away into a shared parent class so we can generate
45  * most of the functions through macros.
46  */
47 struct rxkb_object {
48     struct rxkb_object *parent;
49     uint32_t refcount;
50     struct list link;
51     destroy_func_t destroy;
52 };
53
54 struct rxkb_iso639_code {
55     struct rxkb_object base;
56     char *code;
57 };
58
59 struct rxkb_iso3166_code {
60     struct rxkb_object base;
61     char *code;
62 };
63
64 enum context_state {
65     CONTEXT_NEW,
66     CONTEXT_PARSED,
67     CONTEXT_FAILED,
68 };
69
70 struct rxkb_context {
71     struct rxkb_object base;
72     enum context_state context_state;
73
74     bool load_extra_rules_files;
75     bool use_secure_getenv;
76
77     struct list models;         /* list of struct rxkb_models */
78     struct list layouts;        /* list of struct rxkb_layouts */
79     struct list option_groups;  /* list of struct rxkb_option_group */
80
81     darray(char *) includes;
82
83
84     ATTR_PRINTF(3, 0) void (*log_fn)(struct rxkb_context *ctx,
85                                      enum rxkb_log_level level,
86                                      const char *fmt, va_list args);
87     enum rxkb_log_level log_level;
88
89     void *userdata;
90 };
91
92 struct rxkb_model {
93     struct rxkb_object base;
94
95     char *name;
96     char *vendor;
97     char *description;
98     enum rxkb_popularity popularity;
99 };
100
101 struct rxkb_layout {
102     struct rxkb_object base;
103
104     char *name;
105     char *brief;
106     char *description;
107     char *variant;
108     enum rxkb_popularity popularity;
109
110     struct list iso639s;  /* list of struct rxkb_iso639_code */
111     struct list iso3166s; /* list of struct rxkb_iso3166_code */
112 };
113
114 struct rxkb_option_group {
115     struct rxkb_object base;
116
117     bool allow_multiple;
118     struct list options; /* list of struct rxkb_options */
119     char *name;
120     char *description;
121     enum rxkb_popularity popularity;
122 };
123
124 struct rxkb_option {
125     struct rxkb_object base;
126
127     char *name;
128     char *brief;
129     char *description;
130     enum rxkb_popularity popularity;
131 };
132
133 static bool
134 parse(struct rxkb_context *ctx, const char *path,
135       enum rxkb_popularity popularity);
136
137 ATTR_PRINTF(3, 4)
138 static void
139 rxkb_log(struct rxkb_context *ctx, enum rxkb_log_level level,
140          const char *fmt, ...)
141 {
142     va_list args;
143
144     if (ctx->log_level < level)
145         return;
146
147     va_start(args, fmt);
148     ctx->log_fn(ctx, level, fmt, args);
149     va_end(args);
150 }
151
152 /*
153  * The format is not part of the argument list in order to avoid the
154  * "ISO C99 requires rest arguments to be used" warning when only the
155  * format is supplied without arguments. Not supplying it would still
156  * result in an error, though.
157  */
158 #define log_dbg(ctx, ...) \
159     rxkb_log((ctx), RXKB_LOG_LEVEL_DEBUG, __VA_ARGS__)
160 #define log_info(ctx, ...) \
161     rxkb_log((ctx), RXKB_LOG_LEVEL_INFO, __VA_ARGS__)
162 #define log_warn(ctx, ...) \
163     rxkb_log((ctx), RXKB_LOG_LEVEL_WARNING,  __VA_ARGS__)
164 #define log_err(ctx, ...) \
165     rxkb_log((ctx), RXKB_LOG_LEVEL_ERROR,  __VA_ARGS__)
166 #define log_wsgo(ctx, ...) \
167     rxkb_log((ctx), RXKB_LOG_LEVEL_CRITICAL, __VA_ARGS__)
168
169
170 #define DECLARE_REF_UNREF_FOR_TYPE(type_) \
171 XKB_EXPORT struct type_ * type_##_ref(struct type_ *object) { \
172     rxkb_object_ref(&object->base); \
173     return object; \
174 } \
175 XKB_EXPORT struct type_ * type_##_unref(struct type_ *object) { \
176     if (!object) return NULL; \
177     return rxkb_object_unref(&object->base); \
178 }
179
180 #define DECLARE_CREATE_FOR_TYPE(type_) \
181 static inline struct type_ * type_##_create(struct rxkb_object *parent) { \
182     struct type_ *t = calloc(1, sizeof *t); \
183     if (t) \
184         rxkb_object_init(&t->base, parent, (destroy_func_t)type_##_destroy); \
185     return t; \
186 }
187
188 #define DECLARE_TYPED_GETTER_FOR_TYPE(type_, field_, rtype_) \
189 XKB_EXPORT rtype_ type_##_get_##field_(struct type_ *object) { \
190     return object->field_; \
191 }
192
193 #define DECLARE_GETTER_FOR_TYPE(type_, field_) \
194    DECLARE_TYPED_GETTER_FOR_TYPE(type_, field_, const char*)
195
196 #define DECLARE_FIRST_NEXT_FOR_TYPE(type_, parent_type_, parent_field_) \
197 XKB_EXPORT struct type_ * type_##_first(struct parent_type_ *parent) { \
198     struct type_ *o = NULL; \
199     if (!list_empty(&parent->parent_field_)) \
200         o = list_first_entry(&parent->parent_field_, o, base.link); \
201     return o; \
202 } \
203 XKB_EXPORT struct type_ * \
204 type_##_next(struct type_ *o) \
205 { \
206     struct parent_type_ *parent; \
207     struct type_ *next; \
208     parent = container_of(o->base.parent, struct parent_type_, base); \
209     next = list_first_entry(&o->base.link, o, base.link); \
210     if (list_is_last(&parent->parent_field_, &o->base.link)) \
211         return NULL; \
212     return next; \
213 }
214
215 static void
216 rxkb_object_init(struct rxkb_object *object, struct rxkb_object *parent, destroy_func_t destroy)
217 {
218     object->refcount = 1;
219     object->destroy = destroy;
220     object->parent = parent;
221     list_init(&object->link);
222 }
223
224 static void
225 rxkb_object_destroy(struct rxkb_object *object)
226 {
227     if (object->destroy)
228         object->destroy(object);
229     list_remove(&object->link);
230     free(object);
231 }
232
233 static void *
234 rxkb_object_ref(struct rxkb_object *object)
235 {
236     assert(object->refcount >= 1);
237     ++object->refcount;
238     return object;
239 }
240
241 static void *
242 rxkb_object_unref(struct rxkb_object *object)
243 {
244     assert(object->refcount >= 1);
245     if (--object->refcount == 0)
246         rxkb_object_destroy(object);
247     return NULL;
248 }
249
250 static void
251 rxkb_iso639_code_destroy(struct rxkb_iso639_code *code)
252 {
253     free(code->code);
254 }
255
256 XKB_EXPORT struct rxkb_iso639_code *
257 rxkb_layout_get_iso639_first(struct rxkb_layout *layout)
258 {
259     struct rxkb_iso639_code *code = NULL;
260
261     if (!list_empty(&layout->iso639s))
262         code = list_first_entry(&layout->iso639s, code, base.link);
263
264     return code;
265 }
266
267 XKB_EXPORT struct rxkb_iso639_code *
268 rxkb_iso639_code_next(struct rxkb_iso639_code *code)
269 {
270     struct rxkb_iso639_code *next = NULL;
271     struct rxkb_layout *layout;
272
273     layout = container_of(code->base.parent, struct rxkb_layout, base);
274
275     if (list_is_last(&layout->iso639s, &code->base.link))
276         return NULL;
277
278     next = list_first_entry(&code->base.link, code, base.link);
279
280     return next;
281 }
282
283 DECLARE_REF_UNREF_FOR_TYPE(rxkb_iso639_code);
284 DECLARE_CREATE_FOR_TYPE(rxkb_iso639_code);
285 DECLARE_GETTER_FOR_TYPE(rxkb_iso639_code, code);
286
287 static void
288 rxkb_iso3166_code_destroy(struct rxkb_iso3166_code *code)
289 {
290     free(code->code);
291 }
292
293 XKB_EXPORT struct rxkb_iso3166_code *
294 rxkb_layout_get_iso3166_first(struct rxkb_layout *layout)
295 {
296     struct rxkb_iso3166_code *code = NULL;
297
298     if (!list_empty(&layout->iso3166s))
299         code = list_first_entry(&layout->iso3166s, code, base.link);
300
301     return code;
302 }
303
304 XKB_EXPORT struct rxkb_iso3166_code *
305 rxkb_iso3166_code_next(struct rxkb_iso3166_code *code)
306 {
307     struct rxkb_iso3166_code *next = NULL;
308     struct rxkb_layout *layout;
309
310     layout = container_of(code->base.parent, struct rxkb_layout, base);
311
312     if (list_is_last(&layout->iso3166s, &code->base.link))
313         return NULL;
314
315     next = list_first_entry(&code->base.link, code, base.link);
316
317     return next;
318 }
319
320 DECLARE_REF_UNREF_FOR_TYPE(rxkb_iso3166_code);
321 DECLARE_CREATE_FOR_TYPE(rxkb_iso3166_code);
322 DECLARE_GETTER_FOR_TYPE(rxkb_iso3166_code, code);
323
324 static void
325 rxkb_option_destroy(struct rxkb_option *o)
326 {
327     free(o->name);
328     free(o->brief);
329     free(o->description);
330 }
331
332 DECLARE_REF_UNREF_FOR_TYPE(rxkb_option);
333 DECLARE_CREATE_FOR_TYPE(rxkb_option);
334 DECLARE_GETTER_FOR_TYPE(rxkb_option, name);
335 DECLARE_GETTER_FOR_TYPE(rxkb_option, brief);
336 DECLARE_GETTER_FOR_TYPE(rxkb_option, description);
337 DECLARE_TYPED_GETTER_FOR_TYPE(rxkb_option, popularity, enum rxkb_popularity);
338 DECLARE_FIRST_NEXT_FOR_TYPE(rxkb_option, rxkb_option_group, options);
339
340 static void
341 rxkb_layout_destroy(struct rxkb_layout *l)
342 {
343     struct rxkb_iso639_code *iso639, *tmp_639;
344     struct rxkb_iso3166_code *iso3166, *tmp_3166;
345
346     free(l->name);
347     free(l->brief);
348     free(l->description);
349     free(l->variant);
350
351     list_for_each_safe(iso639, tmp_639, &l->iso639s, base.link) {
352         rxkb_iso639_code_unref(iso639);
353     }
354     list_for_each_safe(iso3166, tmp_3166, &l->iso3166s, base.link) {
355         rxkb_iso3166_code_unref(iso3166);
356     }
357 }
358
359 DECLARE_REF_UNREF_FOR_TYPE(rxkb_layout);
360 DECLARE_CREATE_FOR_TYPE(rxkb_layout);
361 DECLARE_GETTER_FOR_TYPE(rxkb_layout, name);
362 DECLARE_GETTER_FOR_TYPE(rxkb_layout, brief);
363 DECLARE_GETTER_FOR_TYPE(rxkb_layout, description);
364 DECLARE_GETTER_FOR_TYPE(rxkb_layout, variant);
365 DECLARE_TYPED_GETTER_FOR_TYPE(rxkb_layout, popularity, enum rxkb_popularity);
366 DECLARE_FIRST_NEXT_FOR_TYPE(rxkb_layout, rxkb_context, layouts);
367
368 static void
369 rxkb_model_destroy(struct rxkb_model *m)
370 {
371     free(m->name);
372     free(m->vendor);
373     free(m->description);
374 }
375
376 DECLARE_REF_UNREF_FOR_TYPE(rxkb_model);
377 DECLARE_CREATE_FOR_TYPE(rxkb_model);
378 DECLARE_GETTER_FOR_TYPE(rxkb_model, name);
379 DECLARE_GETTER_FOR_TYPE(rxkb_model, vendor);
380 DECLARE_GETTER_FOR_TYPE(rxkb_model, description);
381 DECLARE_TYPED_GETTER_FOR_TYPE(rxkb_model, popularity, enum rxkb_popularity);
382 DECLARE_FIRST_NEXT_FOR_TYPE(rxkb_model, rxkb_context, models);
383
384 static void
385 rxkb_option_group_destroy(struct rxkb_option_group *og)
386 {
387     struct rxkb_option *o, *otmp;
388
389     free(og->name);
390     free(og->description);
391
392     list_for_each_safe(o, otmp, &og->options, base.link) {
393         rxkb_option_unref(o);
394     }
395 }
396
397 XKB_EXPORT bool
398 rxkb_option_group_allows_multiple(struct rxkb_option_group *g)
399 {
400     return g->allow_multiple;
401 }
402
403 DECLARE_REF_UNREF_FOR_TYPE(rxkb_option_group);
404 DECLARE_CREATE_FOR_TYPE(rxkb_option_group);
405 DECLARE_GETTER_FOR_TYPE(rxkb_option_group, name);
406 DECLARE_GETTER_FOR_TYPE(rxkb_option_group, description);
407 DECLARE_TYPED_GETTER_FOR_TYPE(rxkb_option_group, popularity, enum rxkb_popularity);
408 DECLARE_FIRST_NEXT_FOR_TYPE(rxkb_option_group, rxkb_context, option_groups);
409
410 static void
411 rxkb_context_destroy(struct rxkb_context *ctx)
412 {
413     struct rxkb_model *m, *mtmp;
414     struct rxkb_layout *l, *ltmp;
415     struct rxkb_option_group *og, *ogtmp;
416     char **path;
417
418     list_for_each_safe(m, mtmp, &ctx->models, base.link)
419         rxkb_model_unref(m);
420     assert(list_empty(&ctx->models));
421
422     list_for_each_safe(l, ltmp, &ctx->layouts, base.link)
423         rxkb_layout_unref(l);
424     assert(list_empty(&ctx->layouts));
425
426     list_for_each_safe(og, ogtmp, &ctx->option_groups, base.link)
427         rxkb_option_group_unref(og);
428     assert(list_empty(&ctx->option_groups));
429
430     darray_foreach(path, ctx->includes)
431         free(*path);
432     darray_free(ctx->includes);
433
434     assert(darray_empty(ctx->includes));
435 }
436
437 DECLARE_REF_UNREF_FOR_TYPE(rxkb_context);
438 DECLARE_CREATE_FOR_TYPE(rxkb_context);
439 DECLARE_TYPED_GETTER_FOR_TYPE(rxkb_context, log_level, enum rxkb_log_level);
440
441 static char *
442 rxkb_context_getenv(struct rxkb_context *ctx, const char *name)
443 {
444     if (ctx->use_secure_getenv) {
445         return secure_getenv(name);
446     } else {
447         return getenv(name);
448     }
449 }
450
451
452 XKB_EXPORT void
453 rxkb_context_set_log_level(struct rxkb_context *ctx,
454                            enum rxkb_log_level level)
455 {
456     ctx->log_level = level;
457 }
458
459 static const char *
460 log_level_to_prefix(enum rxkb_log_level level)
461 {
462     switch (level) {
463     case RXKB_LOG_LEVEL_DEBUG:
464         return "xkbregistry: DEBUG: ";
465     case RXKB_LOG_LEVEL_INFO:
466         return "xkbregistry: INFO: ";
467     case RXKB_LOG_LEVEL_WARNING:
468         return "xkbregistry: WARNING: ";
469     case RXKB_LOG_LEVEL_ERROR:
470         return "xkbregistry: ERROR: ";
471     case RXKB_LOG_LEVEL_CRITICAL:
472         return "xkbregistry: CRITICAL: ";
473     default:
474         return NULL;
475     }
476 }
477
478 ATTR_PRINTF(3, 0) static void
479 default_log_fn(struct rxkb_context *ctx, enum rxkb_log_level level,
480                const char *fmt, va_list args)
481 {
482     const char *prefix = log_level_to_prefix(level);
483
484     if (prefix)
485         fprintf(stderr, "%s", prefix);
486     vfprintf(stderr, fmt, args);
487 }
488
489 static enum rxkb_log_level
490 log_level(const char *level) {
491     char *endptr;
492     enum rxkb_log_level lvl;
493
494     errno = 0;
495     lvl = strtol(level, &endptr, 10);
496     if (errno == 0 && (endptr[0] == '\0' || is_space(endptr[0])))
497         return lvl;
498     if (istreq_prefix("crit", level))
499         return RXKB_LOG_LEVEL_CRITICAL;
500     if (istreq_prefix("err", level))
501         return RXKB_LOG_LEVEL_ERROR;
502     if (istreq_prefix("warn", level))
503         return RXKB_LOG_LEVEL_WARNING;
504     if (istreq_prefix("info", level))
505         return RXKB_LOG_LEVEL_INFO;
506     if (istreq_prefix("debug", level) || istreq_prefix("dbg", level))
507         return RXKB_LOG_LEVEL_DEBUG;
508
509     return RXKB_LOG_LEVEL_ERROR;
510 }
511
512 XKB_EXPORT struct rxkb_context *
513 rxkb_context_new(enum rxkb_context_flags flags)
514 {
515     struct rxkb_context *ctx = rxkb_context_create(NULL);
516     const char *env;
517
518     if (!ctx)
519         return NULL;
520
521     ctx->context_state = CONTEXT_NEW;
522     ctx->load_extra_rules_files = flags & RXKB_CONTEXT_LOAD_EXOTIC_RULES;
523     ctx->use_secure_getenv = !(flags & RXKB_CONTEXT_NO_SECURE_GETENV);
524     ctx->log_fn = default_log_fn;
525     ctx->log_level = RXKB_LOG_LEVEL_ERROR;
526
527     /* Environment overwrites defaults. */
528     env = rxkb_context_getenv(ctx, "RXKB_LOG_LEVEL");
529     if (env)
530         rxkb_context_set_log_level(ctx, log_level(env));
531
532     list_init(&ctx->models);
533     list_init(&ctx->layouts);
534     list_init(&ctx->option_groups);
535
536     if (!(flags & RXKB_CONTEXT_NO_DEFAULT_INCLUDES) &&
537         !rxkb_context_include_path_append_default(ctx)) {
538         rxkb_context_unref(ctx);
539         return NULL;
540     }
541
542     return ctx;
543 }
544
545 XKB_EXPORT void
546 rxkb_context_set_log_fn(struct rxkb_context *ctx,
547                         void (*log_fn)(struct rxkb_context *ctx,
548                                        enum rxkb_log_level level,
549                                        const char *fmt, va_list args))
550 {
551     ctx->log_fn = (log_fn ? log_fn : default_log_fn);
552 }
553
554 XKB_EXPORT bool
555 rxkb_context_include_path_append(struct rxkb_context *ctx, const char *path)
556 {
557     struct stat stat_buf;
558     int err;
559     char *tmp = NULL;
560     char rules[PATH_MAX];
561
562     if (ctx->context_state != CONTEXT_NEW) {
563         log_err(ctx, "include paths can only be appended to a new context\n");
564         return false;
565     }
566
567     err = stat(path, &stat_buf);
568     if (err != 0)
569         return false;
570     if (!S_ISDIR(stat_buf.st_mode))
571         return false;
572
573     if (!check_eaccess(path, R_OK | X_OK))
574         return false;
575
576     /* Pre-filter for the 99.9% case - if we can't assemble the default ruleset
577      * path, complain here instead of during parsing later. The niche cases
578      * where this is the wrong behaviour aren't worth worrying about.
579      */
580     if (!snprintf_safe(rules, sizeof(rules), "%s/rules/%s.xml",
581                        path, DEFAULT_XKB_RULES))
582         return false;
583
584     tmp = strdup(path);
585     if (!tmp)
586         return false;
587
588     darray_append(ctx->includes, tmp);
589
590     return true;
591 }
592
593 XKB_EXPORT bool
594 rxkb_context_include_path_append_default(struct rxkb_context *ctx)
595 {
596     const char *home, *xdg, *root, *extra;
597     char user_path[PATH_MAX];
598     bool ret = false;
599
600     if (ctx->context_state != CONTEXT_NEW) {
601         log_err(ctx, "include paths can only be appended to a new context\n");
602         return false;
603     }
604
605     home = rxkb_context_getenv(ctx, "HOME");
606
607     xdg = rxkb_context_getenv(ctx, "XDG_CONFIG_HOME");
608     if (xdg != NULL) {
609         if (snprintf_safe(user_path, sizeof(user_path), "%s/xkb", xdg))
610             ret |= rxkb_context_include_path_append(ctx, user_path);
611     } else if (home != NULL) {
612         /* XDG_CONFIG_HOME fallback is $HOME/.config/ */
613         if (snprintf_safe(user_path, sizeof(user_path), "%s/.config/xkb", home))
614             ret |= rxkb_context_include_path_append(ctx, user_path);
615     }
616
617     if (home != NULL) {
618         if (snprintf_safe(user_path, sizeof(user_path), "%s/.xkb", home))
619             ret |= rxkb_context_include_path_append(ctx, user_path);
620     }
621
622     extra = rxkb_context_getenv(ctx, "XKB_CONFIG_EXTRA_PATH");
623     if (extra != NULL)
624         ret |= rxkb_context_include_path_append(ctx, extra);
625     else
626         ret |= rxkb_context_include_path_append(ctx, DFLT_XKB_CONFIG_EXTRA_PATH);
627
628     root = rxkb_context_getenv(ctx, "XKB_CONFIG_ROOT");
629     if (root != NULL)
630         ret |= rxkb_context_include_path_append(ctx, root);
631     else
632         ret |= rxkb_context_include_path_append(ctx, DFLT_XKB_CONFIG_ROOT);
633
634     return ret;
635 }
636
637 XKB_EXPORT bool
638 rxkb_context_parse_default_ruleset(struct rxkb_context *ctx)
639 {
640     return rxkb_context_parse(ctx, DEFAULT_XKB_RULES);
641 }
642
643 XKB_EXPORT bool
644 rxkb_context_parse(struct rxkb_context *ctx, const char *ruleset)
645 {
646     char **path;
647     bool success = false;
648
649     if (ctx->context_state != CONTEXT_NEW) {
650         log_err(ctx, "parse must only be called on a new context\n");
651         return false;
652     }
653
654     darray_foreach_reverse(path, ctx->includes) {
655         char rules[PATH_MAX];
656
657         if (snprintf_safe(rules, sizeof(rules), "%s/rules/%s.xml",
658                            *path, ruleset)) {
659             log_dbg(ctx, "Parsing %s\n", rules);
660             if (parse(ctx, rules, RXKB_POPULARITY_STANDARD))
661                 success = true;
662         }
663
664         if (ctx->load_extra_rules_files &&
665             snprintf_safe(rules, sizeof(rules), "%s/rules/%s.extras.xml",
666                           *path, ruleset)) {
667             log_dbg(ctx, "Parsing %s\n", rules);
668             if (parse(ctx, rules, RXKB_POPULARITY_EXOTIC))
669                 success = true;
670         }
671     }
672
673     ctx->context_state = success ? CONTEXT_PARSED : CONTEXT_FAILED;
674
675     return success;
676 }
677
678
679 XKB_EXPORT void
680 rxkb_context_set_user_data(struct rxkb_context *ctx, void *userdata)
681 {
682     ctx->userdata = userdata;
683 }
684
685 XKB_EXPORT void *
686 rxkb_context_get_user_data(struct rxkb_context *ctx)
687 {
688     return ctx->userdata;
689 }
690
691 static inline bool
692 is_node(xmlNode *node, const char *name)
693 {
694     return node->type == XML_ELEMENT_NODE &&
695         xmlStrEqual(node->name, (const xmlChar*)name);
696 }
697
698 /* return a copy of the text content from the first text node of this node */
699 static char *
700 extract_text(xmlNode *node)
701 {
702     xmlNode *n;
703
704     for (n = node->children; n; n = n->next) {
705         if (n->type == XML_TEXT_NODE)
706             return (char *)xmlStrdup(n->content);
707     }
708     return NULL;
709 }
710
711 static bool
712 parse_config_item(struct rxkb_context *ctx,
713                   xmlNode *parent,
714                   char **name,
715                   char **description,
716                   char **brief,
717                   char **vendor)
718 {
719     xmlNode *node = NULL;
720     xmlNode *ci = NULL;
721
722     for (ci = parent->children; ci; ci = ci->next) {
723         if (is_node(ci, "configItem")) {
724             *name = NULL;
725             *description = NULL;
726             *brief = NULL;
727             *vendor = NULL;
728
729             for (node = ci->children; node; node = node->next) {
730                 if (is_node(node, "name"))
731                     *name = extract_text(node);
732                 else if (is_node(node, "description"))
733                     *description = extract_text(node);
734                 else if (is_node(node, "shortDescription"))
735                     *brief = extract_text(node);
736                 else if (is_node(node, "vendor"))
737                     *vendor = extract_text(node);
738                 /* Note: the DTD allows for vendor + brief but models only use
739                  * vendor and everything else only uses shortDescription */
740             }
741
742             if (!*name || !strlen(*name))  {
743                 log_err(ctx, "xml:%d: missing required element 'name'\n",
744                         ci->line);
745                 free(*name);
746                 free(*description);
747                 free(*brief);
748                 free(*vendor);
749                 return false;
750             }
751
752             return true; /* only one configItem allowed in the dtd */
753         }
754     }
755
756     return false;
757 }
758
759 static void
760 parse_model(struct rxkb_context *ctx, xmlNode *model,
761             enum rxkb_popularity popularity)
762 {
763     char *name, *description, *brief, *vendor;
764
765     if (parse_config_item(ctx, model, &name, &description, &brief, &vendor)) {
766         struct rxkb_model *m;
767
768         list_for_each(m, &ctx->models, base.link) {
769             if (streq(m->name, name)) {
770                 free(name);
771                 free(description);
772                 free(brief);
773                 free(vendor);
774                 return;
775             }
776         }
777
778         /* new model */
779         m = rxkb_model_create(&ctx->base);
780         m->name = name;
781         m->description = description;
782         m->vendor = vendor;
783         m->popularity = popularity;
784         list_append(&ctx->models, &m->base.link);
785     }
786 }
787
788 static void
789 parse_model_list(struct rxkb_context *ctx, xmlNode *model_list,
790                 enum rxkb_popularity popularity)
791 {
792     xmlNode *node = NULL;
793
794     for (node = model_list->children; node; node = node->next) {
795         if (is_node(node, "model"))
796             parse_model(ctx, node, popularity);
797     }
798 }
799
800 static void
801 parse_language_list(xmlNode *language_list, struct rxkb_layout *layout)
802 {
803     xmlNode *node = NULL;
804     struct rxkb_iso639_code *code;
805
806     for (node = language_list->children; node; node = node->next) {
807         if (is_node(node, "iso639Id")) {
808             char *str = extract_text(node);
809             struct rxkb_object *parent;
810
811             if (!str || strlen(str) != 3) {
812                 free(str);
813                 continue;
814             }
815
816             parent = &layout->base;
817             code = rxkb_iso639_code_create(parent);
818             code->code = str;
819             list_append(&layout->iso639s, &code->base.link);
820         }
821     }
822 }
823
824 static void
825 parse_country_list(xmlNode *country_list, struct rxkb_layout *layout)
826 {
827     xmlNode *node = NULL;
828     struct rxkb_iso3166_code *code;
829
830     for (node = country_list->children; node; node = node->next) {
831         if (is_node(node, "iso3166Id")) {
832             char *str = extract_text(node);
833             struct rxkb_object *parent;
834
835             if (!str || strlen(str) != 2) {
836                 free(str);
837                 continue;
838             }
839
840             parent = &layout->base;
841             code = rxkb_iso3166_code_create(parent);
842             code->code = str;
843             list_append(&layout->iso3166s, &code->base.link);
844         }
845     }
846 }
847
848 static void
849 parse_variant(struct rxkb_context *ctx, struct rxkb_layout *l,
850               xmlNode *variant, enum rxkb_popularity popularity)
851 {
852     xmlNode *ci;
853     char *name, *description, *brief, *vendor;
854
855     if (parse_config_item(ctx, variant, &name, &description, &brief, &vendor)) {
856         struct rxkb_layout *v;
857         bool exists = false;
858
859         list_for_each(v, &ctx->layouts, base.link) {
860             if (streq(v->name, name) && streq(v->name, l->name)) {
861                 exists = true;
862                 break;
863             }
864         }
865
866         if (!exists) {
867             v = rxkb_layout_create(&ctx->base);
868             list_init(&v->iso639s);
869             list_init(&v->iso3166s);
870             v->name = strdup(l->name);
871             v->variant = name;
872             v->description = description;
873             // if variant omits brief, inherit from parent layout.
874             v->brief = brief == NULL ? strdup_safe(l->brief) : brief;
875             v->popularity = popularity;
876             list_append(&ctx->layouts, &v->base.link);
877
878             for (ci = variant->children; ci; ci = ci->next) {
879                 xmlNode *node;
880
881                 if (!is_node(ci, "configItem"))
882                     continue;
883
884                 bool found_language_list = false;
885                 bool found_country_list = false;
886                 for (node = ci->children; node; node = node->next) {
887                     if (is_node(node, "languageList")) {
888                         parse_language_list(node, v);
889                         found_language_list = true;
890                     }
891                     if (is_node(node, "countryList")) {
892                         parse_country_list(node, v);
893                         found_country_list = true;
894                     }
895                 }
896                 if (!found_language_list) {
897                     // inherit from parent layout
898                     struct rxkb_iso639_code* x;
899                     list_for_each(x, &l->iso639s, base.link) {
900                         struct rxkb_iso639_code* code = rxkb_iso639_code_create(&v->base);
901                         code->code = strdup(x->code);
902                         list_append(&v->iso639s, &code->base.link);
903                     }
904                 }
905                 if (!found_country_list) {
906                     // inherit from parent layout
907                     struct rxkb_iso3166_code* x;
908                     list_for_each(x, &l->iso3166s, base.link) {
909                         struct rxkb_iso3166_code* code = rxkb_iso3166_code_create(&v->base);
910                         code->code = strdup(x->code);
911                         list_append(&v->iso3166s, &code->base.link);
912                     }
913                 }
914             }
915         } else {
916             free(name);
917             free(description);
918             free(brief);
919             free(vendor);
920         }
921     }
922 }
923
924 static void
925 parse_variant_list(struct rxkb_context *ctx, struct rxkb_layout *l,
926                    xmlNode *variant_list, enum rxkb_popularity popularity)
927 {
928     xmlNode *node = NULL;
929
930     for (node = variant_list->children; node; node = node->next) {
931         if (is_node(node, "variant"))
932             parse_variant(ctx, l, node, popularity);
933     }
934 }
935
936 static void
937 parse_layout(struct rxkb_context *ctx, xmlNode *layout,
938              enum rxkb_popularity popularity)
939 {
940     char *name, *description, *brief, *vendor;
941     struct rxkb_layout *l;
942     xmlNode *node = NULL;
943     bool exists = false;
944
945     if (!parse_config_item(ctx, layout, &name, &description, &brief, &vendor))
946         return;
947
948     list_for_each(l, &ctx->layouts, base.link) {
949         if (streq(l->name, name) && l->variant == NULL) {
950             exists = true;
951             break;
952         }
953     }
954
955     if (!exists) {
956         l = rxkb_layout_create(&ctx->base);
957         list_init(&l->iso639s);
958         list_init(&l->iso3166s);
959         l->name = name;
960         l->variant = NULL;
961         l->description = description;
962         l->brief = brief;
963         l->popularity = popularity;
964         list_append(&ctx->layouts, &l->base.link);
965     } else {
966         free(name);
967         free(description);
968         free(brief);
969         free(vendor);
970     }
971
972     for (node = layout->children; node; node = node->next) {
973         if (is_node(node, "variantList")) {
974             parse_variant_list(ctx, l, node, popularity);
975         }
976         if (!exists && is_node(node, "configItem")) {
977             xmlNode *ll;
978             for (ll = node->children; ll; ll = ll->next) {
979                 if (is_node(ll, "languageList"))
980                     parse_language_list(ll, l);
981                 if (is_node(ll, "countryList"))
982                     parse_country_list(ll, l);
983             }
984         }
985     }
986 }
987
988 static void
989 parse_layout_list(struct rxkb_context *ctx, xmlNode *layout_list,
990                   enum rxkb_popularity popularity)
991 {
992     xmlNode *node = NULL;
993
994     for (node = layout_list->children; node; node = node->next) {
995         if (is_node(node, "layout"))
996             parse_layout(ctx, node, popularity);
997     }
998 }
999
1000 static void
1001 parse_option(struct rxkb_context *ctx, struct rxkb_option_group *group,
1002              xmlNode *option, enum rxkb_popularity popularity)
1003 {
1004     char *name, *description, *brief, *vendor;
1005
1006     if (parse_config_item(ctx, option, &name, &description, &brief, &vendor)) {
1007         struct rxkb_option *o;
1008
1009         list_for_each(o, &group->options, base.link) {
1010             if (streq(o->name, name)) {
1011                 free(name);
1012                 free(description);
1013                 free(brief);
1014                 free(vendor);
1015                 return;
1016             }
1017         }
1018
1019         o = rxkb_option_create(&group->base);
1020         o->name = name;
1021         o->description = description;
1022         o->popularity = popularity;
1023         list_append(&group->options, &o->base.link);
1024     }
1025 }
1026
1027 static void
1028 parse_group(struct rxkb_context *ctx, xmlNode *group,
1029             enum rxkb_popularity popularity)
1030 {
1031     char *name, *description, *brief, *vendor;
1032     struct rxkb_option_group *g;
1033     xmlNode *node = NULL;
1034     xmlChar *multiple;
1035     bool exists = false;
1036
1037     if (!parse_config_item(ctx, group, &name, &description, &brief, &vendor))
1038         return;
1039
1040     list_for_each(g, &ctx->option_groups, base.link) {
1041         if (streq(g->name, name)) {
1042             exists = true;
1043             break;
1044         }
1045     }
1046
1047     if (!exists) {
1048         g = rxkb_option_group_create(&ctx->base);
1049         g->name = name;
1050         g->description = description;
1051         g->popularity = popularity;
1052
1053         multiple = xmlGetProp(group, (const xmlChar*)"allowMultipleSelection");
1054         if (multiple && xmlStrEqual(multiple, (const xmlChar*)"true"))
1055             g->allow_multiple = true;
1056         xmlFree(multiple);
1057
1058         list_init(&g->options);
1059         list_append(&ctx->option_groups, &g->base.link);
1060     } else {
1061         free(name);
1062         free(description);
1063         free(brief);
1064         free(vendor);
1065     }
1066
1067     for (node = group->children; node; node = node->next) {
1068         if (is_node(node, "option"))
1069             parse_option(ctx, g, node, popularity);
1070     }
1071 }
1072
1073 static void
1074 parse_option_list(struct rxkb_context *ctx, xmlNode *option_list,
1075                   enum rxkb_popularity popularity)
1076 {
1077     xmlNode *node = NULL;
1078
1079     for (node = option_list->children; node; node = node->next) {
1080         if (is_node(node, "group"))
1081             parse_group(ctx, node, popularity);
1082     }
1083 }
1084
1085 static void
1086 parse_rules_xml(struct rxkb_context *ctx, xmlNode *root,
1087                 enum rxkb_popularity popularity)
1088 {
1089     xmlNode *node = NULL;
1090
1091     for (node = root->children; node; node = node->next) {
1092         if (is_node(node, "modelList"))
1093             parse_model_list(ctx, node, popularity);
1094         else if (is_node(node, "layoutList"))
1095             parse_layout_list(ctx, node, popularity);
1096         else if (is_node(node, "optionList"))
1097             parse_option_list(ctx, node, popularity);
1098     }
1099 }
1100
1101 static void
1102 ATTR_PRINTF(2, 0)
1103 xml_error_func(void *ctx, const char *msg, ...)
1104 {
1105     static char buf[PATH_MAX];
1106     static int slen = 0;
1107     va_list args;
1108     int rc;
1109
1110     /* libxml2 prints IO errors from bad includes paths by
1111      * calling the error function once per word. So we get to
1112      * re-assemble the message here and print it when we get
1113      * the line break. My enthusiasm about this is indescribable.
1114      */
1115     va_start(args, msg);
1116     rc = vsnprintf(&buf[slen], sizeof(buf) - slen, msg, args);
1117     va_end(args);
1118
1119     /* This shouldn't really happen */
1120     if (rc < 0) {
1121         log_err(ctx, "+++ out of cheese error. redo from start +++\n");
1122         slen = 0;
1123         memset(buf, 0, sizeof(buf));
1124         return;
1125     }
1126
1127     slen += rc;
1128     if (slen >= (int)sizeof(buf)) {
1129         /* truncated, let's flush this */
1130         buf[sizeof(buf) - 1] = '\n';
1131         slen = sizeof(buf);
1132     }
1133
1134     /* We're assuming here that the last character is \n. */
1135     if (buf[slen - 1] == '\n') {
1136         log_err(ctx, "%s", buf);
1137         memset(buf, 0, sizeof(buf));
1138         slen = 0;
1139     }
1140 }
1141
1142 static bool
1143 validate(struct rxkb_context *ctx, xmlDoc *doc)
1144 {
1145     bool success = false;
1146     xmlValidCtxt *dtdvalid = NULL;
1147     xmlDtd *dtd = NULL;
1148     xmlParserInputBufferPtr buf = NULL;
1149     /* This is a modified version of the xkeyboard-config xkb.dtd. That one
1150      * requires modelList, layoutList and optionList, we
1151      * allow for any of those to be missing.
1152      */
1153     const char dtdstr[] =
1154         "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
1155         "<!ELEMENT xkbConfigRegistry (modelList?, layoutList?, optionList?)>\n"
1156         "<!ATTLIST xkbConfigRegistry version CDATA \"1.1\">\n"
1157         "<!ELEMENT modelList (model*)>\n"
1158         "<!ELEMENT model (configItem)>\n"
1159         "<!ELEMENT layoutList (layout*)>\n"
1160         "<!ELEMENT layout (configItem,  variantList?)>\n"
1161         "<!ELEMENT optionList (group*)>\n"
1162         "<!ELEMENT variantList (variant*)>\n"
1163         "<!ELEMENT variant (configItem)>\n"
1164         "<!ELEMENT group (configItem, option*)>\n"
1165         "<!ATTLIST group allowMultipleSelection (true|false) \"false\">\n"
1166         "<!ELEMENT option (configItem)>\n"
1167         "<!ELEMENT configItem (name, shortDescription?, description?, vendor?, countryList?, languageList?, hwList?)>\n"
1168         "<!ATTLIST configItem popularity (standard|exotic) \"standard\">\n"
1169         "<!ELEMENT name (#PCDATA)>\n"
1170         "<!ELEMENT shortDescription (#PCDATA)>\n"
1171         "<!ELEMENT description (#PCDATA)>\n"
1172         "<!ELEMENT vendor (#PCDATA)>\n"
1173         "<!ELEMENT countryList (iso3166Id+)>\n"
1174         "<!ELEMENT iso3166Id (#PCDATA)>\n"
1175         "<!ELEMENT languageList (iso639Id+)>\n"
1176         "<!ELEMENT iso639Id (#PCDATA)>\n"
1177         "<!ELEMENT hwList (hwId+)>\n"
1178         "<!ELEMENT hwId (#PCDATA)>\n";
1179
1180     /* Note: do not use xmlParserInputBufferCreateStatic, it generates random
1181      * DTD validity errors for unknown reasons */
1182     buf = xmlParserInputBufferCreateMem(dtdstr, sizeof(dtdstr),
1183                                         XML_CHAR_ENCODING_UTF8);
1184     if (!buf)
1185         return false;
1186
1187     dtd = xmlIOParseDTD(NULL, buf, XML_CHAR_ENCODING_UTF8);
1188     if (!dtd) {
1189         log_err(ctx, "Failed to load DTD\n");
1190         return false;
1191     }
1192
1193     dtdvalid = xmlNewValidCtxt();
1194     if (xmlValidateDtd(dtdvalid, doc, dtd))
1195         success = true;
1196
1197     if (dtd)
1198         xmlFreeDtd(dtd);
1199     if (dtdvalid)
1200         xmlFreeValidCtxt(dtdvalid);
1201
1202     return success;
1203 }
1204
1205 static bool
1206 parse(struct rxkb_context *ctx, const char *path,
1207       enum rxkb_popularity popularity)
1208 {
1209     bool success = false;
1210     xmlDoc *doc = NULL;
1211     xmlNode *root = NULL;
1212
1213     if (!check_eaccess(path, R_OK))
1214         return false;
1215
1216     LIBXML_TEST_VERSION
1217
1218     xmlSetGenericErrorFunc(ctx, xml_error_func);
1219
1220     doc = xmlParseFile(path);
1221     if (!doc)
1222         return false;
1223
1224     if (!validate(ctx, doc)) {
1225         log_err(ctx, "XML error: failed to validate document at %s\n", path);
1226         goto error;
1227     }
1228
1229     root = xmlDocGetRootElement(doc);
1230     parse_rules_xml(ctx, root, popularity);
1231
1232     success = true;
1233 error:
1234     xmlFreeDoc(doc);
1235
1236     return success;
1237 }