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