1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-gparser.c parse DBus description files
3  *
4  * Copyright (C) 2003, 2005  Red Hat, Inc.
5  *
6  * SPDX-License-Identifier: AFL-2.1 OR GPL-2.0-or-later
7  *
8  * Licensed under the Academic Free License version 2.1
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
23  *
24  */
25 
26 #include <config.h>
27 
28 #include "dbus-gparser.h"
29 #include "dbus/dbus-glib-lowlevel.h"
30 #include "dbus-gidl.h"
31 #include "dbus-gobject.h"
32 #include "dbus/dbus-signature.h"
33 #include <string.h>
34 
35 #include <gio/gio.h>
36 
37 #define ELEMENT_IS(name) (strcmp (element_name, (name)) == 0)
38 
39 typedef struct
40 {
41   const char  *name;
42   const char **retloc;
43 } LocateAttr;
44 
45 static gboolean
locate_attributes(const char * element_name,const char ** attribute_names,const char ** attribute_values,GError ** error,const char * first_attribute_name,const char ** first_attribute_retloc,...)46 locate_attributes (const char  *element_name,
47                    const char **attribute_names,
48                    const char **attribute_values,
49                    GError     **error,
50                    const char  *first_attribute_name,
51                    const char **first_attribute_retloc,
52                    ...)
53 {
54   va_list args;
55   const char *name;
56   const char **retloc;
57   int n_attrs;
58 #define MAX_ATTRS 24
59   LocateAttr attrs[MAX_ATTRS];
60   gboolean retval;
61   int i;
62 
63   g_return_val_if_fail (first_attribute_name != NULL, FALSE);
64   g_return_val_if_fail (first_attribute_retloc != NULL, FALSE);
65 
66   retval = TRUE;
67 
68   n_attrs = 1;
69   attrs[0].name = first_attribute_name;
70   attrs[0].retloc = first_attribute_retloc;
71   *first_attribute_retloc = NULL;
72 
73   va_start (args, first_attribute_retloc);
74 
75   name = va_arg (args, const char*);
76   retloc = va_arg (args, const char**);
77 
78   while (name != NULL)
79     {
80       if (retloc == NULL)
81         {
82           va_end (args);
83           return FALSE;
84         }
85 
86       g_assert (n_attrs < MAX_ATTRS);
87 
88       attrs[n_attrs].name = name;
89       attrs[n_attrs].retloc = retloc;
90       n_attrs += 1;
91       *retloc = NULL;
92 
93       name = va_arg (args, const char*);
94       retloc = va_arg (args, const char**);
95     }
96 
97   va_end (args);
98 
99   i = 0;
100   while (attribute_names[i])
101     {
102       int j;
103       gboolean found;
104 
105       found = FALSE;
106       j = 0;
107       while (j < n_attrs)
108         {
109           if (strcmp (attrs[j].name, attribute_names[i]) == 0)
110             {
111               retloc = attrs[j].retloc;
112 
113               if (*retloc != NULL)
114                 {
115                   g_set_error (error,
116                                G_MARKUP_ERROR,
117                                G_MARKUP_ERROR_PARSE,
118                                "Attribute \"%s\" repeated twice on the same <%s> element",
119                                attrs[j].name, element_name);
120                   retval = FALSE;
121                   goto out;
122                 }
123 
124               *retloc = attribute_values[i];
125               found = TRUE;
126             }
127 
128           ++j;
129         }
130 
131       if (!found)
132         {
133           /* We want to passthrough namespaced XML nodes that we don't know anything about. */
134           if (strchr (attribute_names[i], ':') == NULL)
135             {
136               g_set_error (error,
137                            G_MARKUP_ERROR,
138                            G_MARKUP_ERROR_PARSE,
139                            "Attribute \"%s\" is invalid on <%s> element in this context",
140                            attribute_names[i], element_name);
141               retval = FALSE;
142               goto out;
143             }
144         }
145 
146       ++i;
147     }
148 
149  out:
150   return retval;
151 }
152 
153 #if 0
154 static gboolean
155 check_no_attributes (const char  *element_name,
156                      const char **attribute_names,
157                      const char **attribute_values,
158                      GError     **error)
159 {
160   if (attribute_names[0] != NULL)
161     {
162       g_set_error (error,
163                    G_MARKUP_ERROR,
164                    G_MARKUP_ERROR_PARSE,
165                    "Attribute \"%s\" is invalid on <%s> element in this context",
166                    attribute_names[0], element_name);
167       return FALSE;
168     }
169 
170   return TRUE;
171 }
172 #endif
173 
174 struct Parser
175 {
176   int refcount;
177 
178   NodeInfo *result; /* Filled in when we pop the last node */
179   GSList *node_stack;
180   InterfaceInfo *interface;
181   MethodInfo *method;
182   SignalInfo *signal;
183   PropertyInfo *property;
184   ArgInfo *arg;
185   gboolean in_annotation;
186   guint unknown_namespaced_depth;
187 };
188 
189 Parser*
parser_new(void)190 parser_new (void)
191 {
192   Parser *parser;
193 
194   parser = g_new0 (Parser, 1);
195 
196   parser->refcount = 1;
197 
198   return parser;
199 }
200 
201 Parser *
parser_ref(Parser * parser)202 parser_ref (Parser *parser)
203 {
204   parser->refcount += 1;
205 
206   return parser;
207 }
208 
209 void
parser_unref(Parser * parser)210 parser_unref (Parser *parser)
211 {
212   parser->refcount -= 1;
213   if (parser->refcount == 0)
214     {
215       if (parser->result)
216         node_info_unref (parser->result);
217 
218       g_free (parser);
219     }
220 }
221 
222 gboolean
parser_check_doctype(Parser * parser,const char * doctype,GError ** error)223 parser_check_doctype (Parser      *parser,
224                       const char  *doctype,
225                       GError     **error)
226 {
227   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
228 
229   if (strcmp (doctype, "node") != 0)
230     {
231       g_set_error (error,
232                    G_MARKUP_ERROR,
233                    G_MARKUP_ERROR_PARSE,
234                    "D-BUS description file has the wrong document type %s, use node or interface",
235                    doctype);
236       return FALSE;
237     }
238   else
239     return TRUE;
240 }
241 
242 static gboolean
parse_node(Parser * parser,const char * element_name,const char ** attribute_names,const char ** attribute_values,GError ** error)243 parse_node (Parser      *parser,
244             const char  *element_name,
245             const char **attribute_names,
246             const char **attribute_values,
247             GError     **error)
248 {
249   const char *name;
250   NodeInfo *node;
251 
252   if (parser->interface ||
253       parser->method ||
254       parser->signal ||
255       parser->property ||
256       parser->arg ||
257       parser->in_annotation)
258     {
259       g_set_error (error, G_MARKUP_ERROR,
260                    G_MARKUP_ERROR_PARSE,
261                    "Can't put <%s> element here",
262                    element_name);
263       return FALSE;
264     }
265 
266   name = NULL;
267   if (!locate_attributes (element_name, attribute_names,
268                           attribute_values, error,
269                           "name", &name,
270                           NULL))
271     return FALSE;
272 
273   /* Only the root node can have no name */
274   if (parser->node_stack != NULL && name == NULL)
275     {
276       g_set_error (error, G_MARKUP_ERROR,
277                    G_MARKUP_ERROR_PARSE,
278                    "\"%s\" attribute required on <%s> element ",
279                    "name", element_name);
280       return FALSE;
281     }
282 
283   /* Root element name must be absolute */
284   if (parser->node_stack == NULL && name && *name != '/')
285     {
286       g_set_error (error, G_MARKUP_ERROR,
287                    G_MARKUP_ERROR_PARSE,
288                    "\"%s\" attribute on <%s> element must be an absolute object path, \"%s\" not OK",
289                    "name", element_name, name);
290       return FALSE;
291     }
292 
293   /* Other element names must not be absolute */
294   if (parser->node_stack != NULL && name && *name == '/')
295     {
296       g_set_error (error, G_MARKUP_ERROR,
297                    G_MARKUP_ERROR_PARSE,
298                    "\"%s\" attribute on <%s> element must not be an absolute object path, \"%s\" starts with /",
299                    "name", element_name, name);
300       return FALSE;
301     }
302 
303   node = node_info_new (name);
304 
305   if (parser->node_stack != NULL)
306     {
307       node_info_add_node (parser->node_stack->data,
308                           node);
309     }
310 
311   parser->node_stack = g_slist_prepend (parser->node_stack,
312                                         node);
313 
314   return TRUE;
315 }
316 
317 static gboolean
parse_interface(Parser * parser,const char * element_name,const char ** attribute_names,const char ** attribute_values,GError ** error)318 parse_interface (Parser      *parser,
319                  const char  *element_name,
320                  const char **attribute_names,
321                  const char **attribute_values,
322                  GError     **error)
323 {
324   const char *name;
325   InterfaceInfo *iface;
326   NodeInfo *top;
327 
328   if (parser->interface ||
329       parser->method ||
330       parser->signal ||
331       parser->property ||
332       parser->arg ||
333       parser->in_annotation ||
334       (parser->node_stack == NULL))
335     {
336       g_set_error (error, G_MARKUP_ERROR,
337                    G_MARKUP_ERROR_PARSE,
338                    "Can't put <%s> element here",
339                    element_name);
340       return FALSE;
341     }
342 
343   name = NULL;
344   if (!locate_attributes (element_name, attribute_names,
345                           attribute_values, error,
346                           "name", &name,
347                           NULL))
348     return FALSE;
349 
350   if (name == NULL)
351     {
352       g_set_error (error, G_MARKUP_ERROR,
353                    G_MARKUP_ERROR_PARSE,
354                    "\"%s\" attribute required on <%s> element ",
355                    "name", element_name);
356       return FALSE;
357     }
358 
359   if (!g_dbus_is_interface_name (name))
360     {
361       g_set_error (error, G_MARKUP_ERROR,
362                    G_MARKUP_ERROR_PARSE,
363                    "\"%s\" is not a valid D-Bus interface name", name);
364       return FALSE;
365     }
366 
367   top = parser->node_stack->data;
368 
369   iface = interface_info_new (name);
370   node_info_add_interface (top, iface);
371   interface_info_unref (iface);
372 
373   parser->interface = iface;
374 
375   return TRUE;
376 }
377 
378 static gboolean
parse_method(Parser * parser,const char * element_name,const char ** attribute_names,const char ** attribute_values,GError ** error)379 parse_method (Parser      *parser,
380               const char  *element_name,
381               const char **attribute_names,
382               const char **attribute_values,
383               GError     **error)
384 {
385   const char *name;
386   MethodInfo *method;
387 
388   if (parser->interface == NULL ||
389       parser->node_stack == NULL ||
390       parser->method ||
391       parser->signal ||
392       parser->property ||
393       parser->in_annotation ||
394       parser->arg)
395     {
396       g_set_error (error, G_MARKUP_ERROR,
397                    G_MARKUP_ERROR_PARSE,
398                    "Can't put <%s> element here",
399                    element_name);
400       return FALSE;
401     }
402 
403   name = NULL;
404   if (!locate_attributes (element_name, attribute_names,
405                           attribute_values, error,
406                           "name", &name,
407                           NULL))
408     return FALSE;
409 
410   if (name == NULL)
411     {
412       g_set_error (error, G_MARKUP_ERROR,
413                    G_MARKUP_ERROR_PARSE,
414                    "\"%s\" attribute required on <%s> element ",
415                    "name", element_name);
416       return FALSE;
417     }
418 
419   if (!g_dbus_is_member_name (name))
420     {
421       g_set_error (error, G_MARKUP_ERROR,
422                    G_MARKUP_ERROR_PARSE,
423                    "\"%s\" is not a valid D-Bus member name", name);
424       return FALSE;
425     }
426 
427   method = method_info_new (name);
428   interface_info_add_method (parser->interface, method);
429   method_info_unref (method);
430 
431   parser->method = method;
432 
433   return TRUE;
434 }
435 
436 static gboolean
parse_signal(Parser * parser,const char * element_name,const char ** attribute_names,const char ** attribute_values,GError ** error)437 parse_signal (Parser      *parser,
438               const char  *element_name,
439               const char **attribute_names,
440               const char **attribute_values,
441               GError     **error)
442 {
443   const char *name;
444   SignalInfo *signal;
445 
446   if (parser->interface == NULL ||
447       parser->node_stack == NULL ||
448       parser->signal ||
449       parser->method ||
450       parser->property ||
451       parser->in_annotation ||
452       parser->arg)
453     {
454       g_set_error (error, G_MARKUP_ERROR,
455                    G_MARKUP_ERROR_PARSE,
456                    "Can't put <%s> element here",
457                    element_name);
458       return FALSE;
459     }
460 
461   name = NULL;
462   if (!locate_attributes (element_name, attribute_names,
463                           attribute_values, error,
464                           "name", &name,
465                           NULL))
466     return FALSE;
467 
468   if (name == NULL)
469     {
470       g_set_error (error, G_MARKUP_ERROR,
471                    G_MARKUP_ERROR_PARSE,
472                    "\"%s\" attribute required on <%s> element ",
473                    "name", element_name);
474       return FALSE;
475     }
476 
477   if (!g_dbus_is_member_name (name))
478     {
479       g_set_error (error, G_MARKUP_ERROR,
480                    G_MARKUP_ERROR_PARSE,
481                    "\"%s\" is not a valid D-Bus member name", name);
482       return FALSE;
483     }
484 
485   signal = signal_info_new (name);
486   interface_info_add_signal (parser->interface, signal);
487   signal_info_unref (signal);
488 
489   parser->signal = signal;
490 
491   return TRUE;
492 }
493 
494 static gboolean
validate_signature(const char * str,const char * element_name,GError ** error)495 validate_signature (const char *str,
496 		    const char *element_name,
497 		    GError    **error)
498 {
499   DBusError derror;
500 
501   dbus_error_init (&derror);
502 
503   if (!dbus_signature_validate (str, &derror))
504     {
505       dbus_set_g_error (error, &derror);
506       return FALSE;
507     }
508   return TRUE;
509 }
510 
511 static gboolean
parse_property(Parser * parser,const char * element_name,const char ** attribute_names,const char ** attribute_values,GError ** error)512 parse_property (Parser      *parser,
513                 const char  *element_name,
514                 const char **attribute_names,
515                 const char **attribute_values,
516                 GError     **error)
517 {
518   const char *name;
519   const char *access;
520   const char *type;
521   PropertyInfo *property;
522   PropertyAccessFlags access_flags;
523 
524   if (parser->interface == NULL ||
525       parser->node_stack == NULL ||
526       parser->signal ||
527       parser->method ||
528       parser->property ||
529       parser->in_annotation ||
530       parser->arg)
531     {
532       g_set_error (error, G_MARKUP_ERROR,
533                    G_MARKUP_ERROR_PARSE,
534                    "Can't put <%s> element here",
535                    element_name);
536       return FALSE;
537     }
538 
539   name = NULL;
540   if (!locate_attributes (element_name, attribute_names,
541                           attribute_values, error,
542                           "name", &name,
543                           "access", &access,
544                           "type", &type,
545                           NULL))
546     return FALSE;
547 
548   if (name == NULL)
549     {
550       g_set_error (error, G_MARKUP_ERROR,
551                    G_MARKUP_ERROR_PARSE,
552                    "\"%s\" attribute required on <%s> element ",
553                    "name", element_name);
554       return FALSE;
555     }
556 
557   if (access == NULL)
558     {
559       g_set_error (error, G_MARKUP_ERROR,
560                    G_MARKUP_ERROR_PARSE,
561                    "\"%s\" attribute required on <%s> element ",
562                    "access", element_name);
563       return FALSE;
564     }
565 
566   if (type == NULL)
567     {
568       g_set_error (error, G_MARKUP_ERROR,
569                    G_MARKUP_ERROR_PARSE,
570                    "\"%s\" attribute required on <%s> element ",
571                    "type", element_name);
572       return FALSE;
573     }
574 
575   if (!validate_signature (type, element_name, error))
576     return FALSE;
577 
578   access_flags = 0;
579   if (strcmp (access, "readwrite") == 0)
580     access_flags = PROPERTY_READ | PROPERTY_WRITE;
581   else if (strcmp (access, "read") == 0)
582     access_flags = PROPERTY_READ;
583   else if (strcmp (access, "write") == 0)
584     access_flags = PROPERTY_WRITE;
585   else
586     {
587       g_set_error (error, G_MARKUP_ERROR,
588                    G_MARKUP_ERROR_PARSE,
589                    "access=\"%s\" must have value readwrite, read, or write on %s\n",
590                    access, element_name);
591       return FALSE;
592     }
593 
594   if (!g_utf8_validate (name, -1, NULL))
595     {
596       g_set_error (error, G_MARKUP_ERROR,
597                    G_MARKUP_ERROR_PARSE,
598                    "\"%s\" is not UTF-8", name);
599       return FALSE;
600     }
601 
602   property = property_info_new (name, type, access_flags);
603   interface_info_add_property (parser->interface, property);
604   property_info_unref (property);
605 
606   parser->property = property;
607 
608   return TRUE;
609 }
610 
611 static gboolean
parse_arg(Parser * parser,const char * element_name,const char ** attribute_names,const char ** attribute_values,GError ** error)612 parse_arg (Parser      *parser,
613            const char  *element_name,
614            const char **attribute_names,
615            const char **attribute_values,
616            GError     **error)
617 {
618   const char *name;
619   const char *type;
620   const char *direction;
621   ArgDirection dir;
622   ArgInfo *arg;
623   char *generated_name;
624 
625   if (!(parser->method || parser->signal) ||
626       parser->node_stack == NULL ||
627       parser->property ||
628       parser->in_annotation ||
629       parser->arg)
630     {
631       g_set_error (error, G_MARKUP_ERROR,
632                    G_MARKUP_ERROR_PARSE,
633                    "Can't put <%s> element here",
634                    element_name);
635       return FALSE;
636     }
637 
638   name = NULL;
639   if (!locate_attributes (element_name, attribute_names,
640                           attribute_values, error,
641                           "name", &name,
642                           "type", &type,
643                           "direction", &direction,
644                           NULL))
645     return FALSE;
646 
647   /* name can be null for args */
648 
649   if (type == NULL)
650     {
651       g_set_error (error, G_MARKUP_ERROR,
652                    G_MARKUP_ERROR_PARSE,
653                    "\"%s\" attribute required on <%s> element ",
654                    "type", element_name);
655       return FALSE;
656     }
657 
658   if (direction == NULL)
659     {
660       /* methods default to in, signal to out */
661       if (parser->method)
662         direction = "in";
663       else if (parser->signal)
664         direction = "out";
665       else
666         g_assert_not_reached ();
667     }
668 
669   dir = ARG_INVALID;
670 
671   if (strcmp (direction, "in") == 0)
672     dir = ARG_IN;
673   else if (strcmp (direction, "out") == 0)
674     dir = ARG_OUT;
675 
676   if (dir == ARG_INVALID ||
677       (parser->signal && dir == ARG_IN))
678     {
679       if (parser->signal)
680         g_set_error (error, G_MARKUP_ERROR,
681                      G_MARKUP_ERROR_PARSE,
682                      "Signals must have direction=\"out\" (just omit the direction attribute)");
683       else
684         g_set_error (error, G_MARKUP_ERROR,
685                      G_MARKUP_ERROR_PARSE,
686                      "\"%s\" attribute on <%s> has value \"in\" or \"out\"",
687                      "direction", element_name);
688       return FALSE;
689     }
690 
691   if (!validate_signature (type, element_name, error))
692     return FALSE;
693 
694   generated_name = NULL;
695   if (name == NULL)
696     generated_name = g_strdup_printf ("arg%d",
697                                       parser->method ?
698                                       method_info_get_n_args (parser->method) :
699                                       signal_info_get_n_args (parser->signal));
700 
701   arg = arg_info_new (name ? name : generated_name, dir, type);
702   if (parser->method)
703     method_info_add_arg (parser->method, arg);
704   else if (parser->signal)
705     signal_info_add_arg (parser->signal, arg);
706   else
707     g_assert_not_reached ();
708 
709   g_free (generated_name);
710 
711   arg_info_unref (arg);
712 
713   parser->arg = arg;
714 
715   return TRUE;
716 }
717 
718 static gboolean
parse_annotation(Parser * parser,const char * element_name,const char ** attribute_names,const char ** attribute_values,GError ** error)719 parse_annotation (Parser      *parser,
720 		  const char  *element_name,
721 		  const char **attribute_names,
722 		  const char **attribute_values,
723 		  GError     **error)
724 {
725   const char *name;
726   const char *value;
727 
728   if (!(parser->method || parser->interface || parser->arg ||
729         parser->property || parser->signal) ||
730       parser->node_stack == NULL ||
731       parser->in_annotation)
732     {
733       g_set_error (error, G_MARKUP_ERROR,
734                    G_MARKUP_ERROR_PARSE,
735                    "Can't put <%s> element here",
736                    element_name);
737       return FALSE;
738     }
739 
740   name = NULL;
741   if (!locate_attributes (element_name, attribute_names,
742                           attribute_values, error,
743                           "name", &name,
744                           "value", &value,
745                           NULL))
746     return FALSE;
747 
748   if (name == NULL)
749     {
750       g_set_error (error, G_MARKUP_ERROR,
751                    G_MARKUP_ERROR_PARSE,
752                    "\"%s\" attribute required on <%s> element ",
753                    "name", element_name);
754       return FALSE;
755     }
756   if (value == NULL)
757     {
758       g_set_error (error, G_MARKUP_ERROR,
759                    G_MARKUP_ERROR_PARSE,
760                    "\"%s\" attribute required on <%s> element ",
761                    "value", element_name);
762       return FALSE;
763     }
764 
765   if (parser->arg)
766     arg_info_add_annotation (parser->arg, name, value);
767   else if (parser->method)
768     method_info_add_annotation (parser->method, name, value);
769   else if (parser->interface)
770     interface_info_add_annotation (parser->interface, name, value);
771   else
772     g_assert_not_reached ();
773 
774   parser->in_annotation = TRUE;
775 
776   return TRUE;
777 }
778 
779 gboolean
parser_start_element(Parser * parser,const char * element_name,const char ** attribute_names,const char ** attribute_values,GError ** error)780 parser_start_element (Parser      *parser,
781                       const char  *element_name,
782                       const char **attribute_names,
783                       const char **attribute_values,
784                       GError     **error)
785 {
786   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
787 
788   if (ELEMENT_IS ("node"))
789     {
790       if (!parse_node (parser, element_name, attribute_names,
791                        attribute_values, error))
792         return FALSE;
793     }
794   else if (ELEMENT_IS ("interface"))
795     {
796       if (!parse_interface (parser, element_name, attribute_names,
797                             attribute_values, error))
798         return FALSE;
799     }
800   else if (ELEMENT_IS ("method"))
801     {
802       if (!parse_method (parser, element_name, attribute_names,
803                          attribute_values, error))
804         return FALSE;
805     }
806   else if (ELEMENT_IS ("signal"))
807     {
808       if (!parse_signal (parser, element_name, attribute_names,
809                          attribute_values, error))
810         return FALSE;
811     }
812   else if (ELEMENT_IS ("property"))
813     {
814       if (!parse_property (parser, element_name, attribute_names,
815                            attribute_values, error))
816         return FALSE;
817     }
818   else if (ELEMENT_IS ("arg"))
819     {
820       if (!parse_arg (parser, element_name, attribute_names,
821                       attribute_values, error))
822         return FALSE;
823     }
824   else if (ELEMENT_IS ("annotation"))
825     {
826       if (!parse_annotation (parser, element_name, attribute_names,
827 			     attribute_values, error))
828         return FALSE;
829     }
830   else
831     {
832       if (strchr (element_name, ':') != NULL)
833         /* Passthrough XML-namespaced nodes */
834         parser->unknown_namespaced_depth += 1;
835       else if (parser->unknown_namespaced_depth == 0)
836         {
837           g_set_error (error, G_MARKUP_ERROR,
838                        G_MARKUP_ERROR_PARSE,
839                        "Element <%s> not recognized",
840                        element_name);
841           return FALSE;
842         }
843     }
844 
845   return TRUE;
846 }
847 
848 gboolean
parser_end_element(Parser * parser,const char * element_name,GError ** error)849 parser_end_element (Parser      *parser,
850                     const char  *element_name,
851                     GError     **error)
852 {
853   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
854 
855   if (ELEMENT_IS ("interface"))
856     {
857       parser->interface = NULL;
858     }
859   else if (ELEMENT_IS ("method"))
860     {
861       parser->method = NULL;
862     }
863   else if (ELEMENT_IS ("signal"))
864     {
865       parser->signal = NULL;
866     }
867   else if (ELEMENT_IS ("property"))
868     {
869       parser->property = NULL;
870     }
871   else if (ELEMENT_IS ("arg"))
872     {
873       parser->arg = NULL;
874     }
875   else if (ELEMENT_IS ("annotation"))
876     {
877       parser->in_annotation = FALSE;
878     }
879   else if (ELEMENT_IS ("node"))
880     {
881       NodeInfo *top;
882 
883       g_assert (parser->node_stack != NULL);
884       top = parser->node_stack->data;
885 
886       parser->node_stack = g_slist_remove (parser->node_stack,
887                                            top);
888 
889       if (parser->node_stack == NULL)
890         parser->result = top; /* We are done, store the result */
891     }
892   else if (strchr (element_name, ':') != NULL)
893     {
894       /* Passthrough XML-namespaced nodes */
895       parser->unknown_namespaced_depth -= 1;
896     }
897   else if (parser->unknown_namespaced_depth > 0)
898     {
899 		/* pass through unknown elements underneath a namespace */
900     }
901   else
902     g_assert_not_reached (); /* should have had an error on start_element */
903 
904   return TRUE;
905 }
906 
907 gboolean
parser_content(Parser * parser,const char * content,int len,GError ** error)908 parser_content (Parser      *parser,
909                 const char  *content,
910                 int          len,
911                 GError     **error)
912 {
913   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
914 
915   /* FIXME check that it's all whitespace */
916 
917   return TRUE;
918 }
919 
920 gboolean
parser_finished(Parser * parser,GError ** error)921 parser_finished (Parser      *parser,
922                  GError     **error)
923 {
924   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
925 
926   return TRUE;
927 }
928 
929 NodeInfo*
parser_get_nodes(Parser * parser)930 parser_get_nodes (Parser *parser)
931 {
932   return parser->result;
933 }
934