(linenum→info "unix/slp.c:2238")

dbus/1.0.2/bus/config-loader-libxml.c

    1: /* -*- mode: C; c-file-style: "gnu" -*- */
    2: /* config-loader-libxml.c  libxml2 XML loader
    3:  *
    4:  * Copyright (C) 2003 Red Hat, Inc.
    5:  *
    6:  * Licensed under the Academic Free License version 2.1
    7:  * 
    8:  * This program is free software; you can redistribute it and/or modify
    9:  * it under the terms of the GNU General Public License as published by
   10:  * the Free Software Foundation; either version 2 of the License, or
   11:  * (at your option) any later version.
   12:  *
   13:  * This program is distributed in the hope that it will be useful,
   14:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   15:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   16:  * GNU General Public License for more details.
   17:  * 
   18:  * You should have received a copy of the GNU General Public License
   19:  * along with this program; if not, write to the Free Software
   20:  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   21:  *
   22:  */
   23: 
   24: #include "config-parser.h"
   25: #include <dbus/dbus-internals.h>
   26: #include <libxml/xmlreader.h>
   27: #include <libxml/parser.h>
   28: #include <libxml/globals.h>
   29: #include <libxml/xmlmemory.h>
   30: #include <errno.h>
   31: #include <string.h>
   32: 
   33: /* About the error handling: 
   34:  *  - setup a "structured" error handler that catches structural
   35:  *    errors and some oom errors 
   36:  *  - assume that a libxml function returning an error code means
   37:  *    out-of-memory
   38:  */
   39: #define _DBUS_MAYBE_SET_OOM(e) (dbus_error_is_set(e) ? (void)0 : _DBUS_SET_OOM(e))
   40: 
   41: 
   42: static dbus_bool_t
   43: xml_text_start_element (BusConfigParser   *parser,
   44:                         xmlTextReader     *reader,
   45:                         DBusError         *error)
   46: {
   47:   const char *name;
   48:   int n_attributes;
   49:   const char **attribute_names, **attribute_values;
   50:   dbus_bool_t ret;
   51:   int i, status, is_empty;
   52: 
   53:   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
   54: 
   55:   ret = FALSE;
   56:   attribute_names = NULL;
   57:   attribute_values = NULL;
   58: 
   59:   name = xmlTextReaderConstName (reader);
   60:   n_attributes = xmlTextReaderAttributeCount (reader);
   61:   is_empty = xmlTextReaderIsEmptyElement (reader);
   62: 
   63:   if (name == NULL || n_attributes < 0 || is_empty == -1)
   64:     {
   65:       _DBUS_MAYBE_SET_OOM (error);
   66:       goto out;
   67:     }
   68: 
   69:   attribute_names = dbus_new0 (const char *, n_attributes + 1);
   70:   attribute_values = dbus_new0 (const char *, n_attributes + 1);
   71:   if (attribute_names == NULL || attribute_values == NULL)
   72:     {
   73:       _DBUS_SET_OOM (error);
   74:       goto out;
   75:     }
   76:   i = 0;
   77:   while ((status = xmlTextReaderMoveToNextAttribute (reader)) == 1)
   78:     {
   79:       _dbus_assert (i < n_attributes);
   80:       attribute_names[i] = xmlTextReaderConstName (reader);
   81:       attribute_values[i] = xmlTextReaderConstValue (reader);
   82:       if (attribute_names[i] == NULL || attribute_values[i] == NULL)
   83:         { 
   84:           _DBUS_MAYBE_SET_OOM (error);
   85:           goto out;
   86:         }
   87:       i++;
   88:     }
   89:   if (status == -1)
   90:     {
   91:       _DBUS_MAYBE_SET_OOM (error);
   92:       goto out;
   93:     }
   94:   _dbus_assert (i == n_attributes);
   95: 
   96:   ret = bus_config_parser_start_element (parser, name,
   97:                                          attribute_names, attribute_values,
   98:                                          error);
   99:   if (ret && is_empty == 1)
  100:     ret = bus_config_parser_end_element (parser, name, error);
  101: 
  102:  out:
  103:   dbus_free (attribute_names);
  104:   dbus_free (attribute_values);
  105: 
  106:   return ret;
  107: }
  108: 
  109: static void xml_shut_up (void *ctx, const char *msg, ...)
  110: {
  111:     return;
  112: }
  113: 
  114: static void
  115: xml_text_reader_error (void *arg, xmlErrorPtr xml_error)
  116: {
  117:   DBusError *error = arg;
  118: 
  119: #if 0
  120:   _dbus_verbose ("XML_ERROR level=%d, domain=%d, code=%d, msg=%s\n",
  121:                  xml_error->level, xml_error->domain,
  122:                  xml_error->code, xml_error->message);
  123: #endif
  124: 
  125:   if (!dbus_error_is_set (error))
  126:     {
  127:       if (xml_error->code == XML_ERR_NO_MEMORY)
  128:         _DBUS_SET_OOM (error);
  129:       else if (xml_error->level == XML_ERR_ERROR ||
  130:                xml_error->level == XML_ERR_FATAL)
  131:         dbus_set_error (error, DBUS_ERROR_FAILED,
  132:                         "Error loading config file: '%s'",
  133:                         xml_error->message);
  134:     }
  135: }
  136: 
  137: 
  138: BusConfigParser*
  139: bus_config_load (const DBusString      *file,
  140:                  dbus_bool_t            is_toplevel,
  141:                  const BusConfigParser *parent,
  142:                  DBusError             *error)
  143: 
  144: {
  145:   xmlTextReader *reader;
  146:   BusConfigParser *parser;
  147:   DBusString dirname, data;
  148:   DBusError tmp_error;
  149:   int ret;
  150:   
  151:   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
  152:   
  153:   parser = NULL;
  154:   reader = NULL;
  155: 
  156:   if (!_dbus_string_init (&dirname))
  157:     {
  158:       _DBUS_SET_OOM (error);
  159:       return NULL;
  160:     }
  161: 
  162:   if (!_dbus_string_init (&data))
  163:     {
  164:       _DBUS_SET_OOM (error);
  165:       _dbus_string_free (&dirname);
  166:       return NULL;
  167:     }
  168: 
  169:   if (is_toplevel)
  170:     {
  171:       /* xmlMemSetup only fails if one of the functions is NULL */
  172:       xmlMemSetup (dbus_free,
  173:                    dbus_malloc,
  174:                    dbus_realloc,
  175:                    _dbus_strdup);
  176:       xmlInitParser ();
  177:       xmlSetGenericErrorFunc (NULL, xml_shut_up);
  178:     }
  179: 
  180:   if (!_dbus_string_get_dirname (file, &dirname))
  181:     {
  182:       _DBUS_SET_OOM (error);
  183:       goto failed;
  184:     }
  185:   
  186:   parser = bus_config_parser_new (&dirname, is_toplevel, parent);
  187:   if (parser == NULL)
  188:     {
  189:       _DBUS_SET_OOM (error);
  190:       goto failed;
  191:     }
  192:   
  193:   if (!_dbus_file_get_contents (&data, file, error))
  194:     goto failed;
  195: 
  196:   reader = xmlReaderForMemory (_dbus_string_get_const_data (&data), 
  197:                                _dbus_string_get_length (&data),
  198:                                NULL, NULL, 0);
  199:   if (reader == NULL)
  200:     {
  201:       _DBUS_SET_OOM (error);
  202:       goto failed;
  203:     }
  204: 
  205:   xmlTextReaderSetParserProp (reader, XML_PARSER_SUBST_ENTITIES, 1);
  206: 
  207:   dbus_error_init (&tmp_error);
  208:   xmlTextReaderSetStructuredErrorHandler (reader, xml_text_reader_error, &tmp_error);
  209: 
  210:   while ((ret = xmlTextReaderRead (reader)) == 1)
  211:     {
  212:       int type;
  213:       
  214:       if (dbus_error_is_set (&tmp_error))
  215:         goto reader_out;
  216: 
  217:       type = xmlTextReaderNodeType (reader);
  218:       if (type == -1)
  219:         {
  220:           _DBUS_MAYBE_SET_OOM (&tmp_error);
  221:           goto reader_out;
  222:         }
  223: 
  224:       switch ((xmlReaderTypes) type) {
  225:       case XML_READER_TYPE_ELEMENT:
  226:         xml_text_start_element (parser, reader, &tmp_error);
  227:         break;
  228: 
  229:       case XML_READER_TYPE_TEXT:
  230:       case XML_READER_TYPE_CDATA:
  231:         {
  232:           DBusString content;
  233:           const char *value;
  234:           value = xmlTextReaderConstValue (reader);
  235:           if (value != NULL)
  236:             {
  237:               _dbus_string_init_const (&content, value);
  238:               bus_config_parser_content (parser, &content, &tmp_error);
  239:             }
  240:           else
  241:             _DBUS_MAYBE_SET_OOM (&tmp_error);
  242:           break;
  243:         }
  244: 
  245:       case XML_READER_TYPE_DOCUMENT_TYPE:
  246:         {
  247:           const char *name;
  248:           name = xmlTextReaderConstName (reader);
  249:           if (name != NULL)
  250:             bus_config_parser_check_doctype (parser, name, &tmp_error);
  251:           else
  252:             _DBUS_MAYBE_SET_OOM (&tmp_error);
  253:           break;
  254:         }
  255: 
  256:       case XML_READER_TYPE_END_ELEMENT:
  257:         {
  258:           const char *name;
  259:           name = xmlTextReaderConstName (reader);
  260:           if (name != NULL)
  261:             bus_config_parser_end_element (parser, name, &tmp_error);
  262:           else
  263:             _DBUS_MAYBE_SET_OOM (&tmp_error);
  264:           break;
  265:         }
  266: 
  267:       case XML_READER_TYPE_DOCUMENT:
  268:       case XML_READER_TYPE_DOCUMENT_FRAGMENT:
  269:       case XML_READER_TYPE_PROCESSING_INSTRUCTION:
  270:       case XML_READER_TYPE_COMMENT:
  271:       case XML_READER_TYPE_ENTITY:
  272:       case XML_READER_TYPE_NOTATION:
  273:       case XML_READER_TYPE_WHITESPACE:
  274:       case XML_READER_TYPE_SIGNIFICANT_WHITESPACE:
  275:       case XML_READER_TYPE_END_ENTITY:
  276:       case XML_READER_TYPE_XML_DECLARATION:
  277:         /* nothing to do, just read on */
  278:         break;
  279: 
  280:       case XML_READER_TYPE_NONE:
  281:       case XML_READER_TYPE_ATTRIBUTE:
  282:       case XML_READER_TYPE_ENTITY_REFERENCE:
  283:         _dbus_assert_not_reached ("unexpected nodes in XML");
  284:       }
  285: 
  286:       if (dbus_error_is_set (&tmp_error))
  287:         goto reader_out;
  288:     }
  289: 
  290:   if (ret == -1)
  291:     _DBUS_MAYBE_SET_OOM (&tmp_error);
  292: 
  293:  reader_out:
  294:   xmlFreeTextReader (reader);
  295:   reader = NULL;
  296:   if (dbus_error_is_set (&tmp_error))
  297:     {
  298:       dbus_move_error (&tmp_error, error);
  299:       goto failed;
  300:     }
  301:   
  302:   if (!bus_config_parser_finished (parser, error))
  303:     goto failed;
  304:   _dbus_string_free (&dirname);
  305:   _dbus_string_free (&data);
  306:   if (is_toplevel)
  307:     xmlCleanupParser();
  308:   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
  309:   return parser;
  310:   
  311:  failed:
  312:   _DBUS_ASSERT_ERROR_IS_SET (error);
  313:   _dbus_string_free (&dirname);
  314:   _dbus_string_free (&data);
  315:   if (is_toplevel)
  316:     xmlCleanupParser();
  317:   if (parser)
  318:     bus_config_parser_unref (parser);
  319:   _dbus_assert (reader == NULL); /* must go to reader_out first */
  320:   return NULL;
  321: }
Syntax (Markdown)