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