libxml.c 7.87 KB
Newer Older
gbazin's avatar
gbazin committed
1
2
3
/*****************************************************************************
 * libxml.c: XML parser using libxml2
 *****************************************************************************
4
 * Copyright (C) 2004 the VideoLAN team
gbazin's avatar
gbazin committed
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 * $Id$
 *
 * Authors: Gildas Bazin <gbazin@videolan.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
dionoea's avatar
dionoea committed
21
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
gbazin's avatar
gbazin committed
22
23
 *****************************************************************************/

24
25
26
27
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

28
#include <vlc_common.h>
29
#include <vlc_plugin.h>
gbazin's avatar
gbazin committed
30

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
31
32
33
#include <vlc_block.h>
#include <vlc_stream.h>
#include <vlc_xml.h>
gbazin's avatar
gbazin committed
34
35
36
37
38
39
40
41
42
43

#include <libxml/xmlreader.h>
#include <libxml/catalog.h>

/*****************************************************************************
 * Module descriptor
 *****************************************************************************/
static int  Open ( vlc_object_t * );
static void Close( vlc_object_t * );

44
45
46
47
48
vlc_module_begin ()
    set_description( N_("XML Parser (using libxml2)") )
    set_capability( "xml", 10 )
    set_callbacks( Open, Close )
vlc_module_end ()
gbazin's avatar
gbazin committed
49
50
51
52
53
54
55

struct xml_reader_sys_t
{
    /* libxml2 reader context */
    xmlTextReaderPtr p_reader;
};

sigmunau's avatar
sigmunau committed
56
static xml_reader_t *ReaderCreate( xml_t *, stream_t * );
gbazin's avatar
gbazin committed
57
58
59
60
61
62
63
static void ReaderDelete( xml_reader_t * );
static int ReaderRead( xml_reader_t * );
static int ReaderNodeType( xml_reader_t * );
static char *ReaderName( xml_reader_t * );
static char *ReaderValue( xml_reader_t * );
static int ReaderNextAttr( xml_reader_t * );

64
static int ReaderUseDTD ( xml_reader_t *, bool );
65

gbazin's avatar
gbazin committed
66
67
static void CatalogLoad( xml_t *, const char * );
static void CatalogAdd( xml_t *, const char *, const char *, const char * );
sigmunau's avatar
sigmunau committed
68
static int StreamRead( void *p_context, char *p_buffer, int i_buffer );
gbazin's avatar
gbazin committed
69

70
71
static vlc_mutex_t lock = VLC_STATIC_MUTEX;

gbazin's avatar
gbazin committed
72
73
74
75
76
77
78
/*****************************************************************************
 * Module initialization
 *****************************************************************************/
static int Open( vlc_object_t *p_this )
{
    xml_t *p_xml = (xml_t *)p_this;

79
80
81
82
    if( !xmlHasFeature( XML_WITH_THREAD ) )
        return VLC_EGENERIC;

    vlc_mutex_lock( &lock );
83
    xmlInitParser();
84
    vlc_mutex_unlock( &lock );
geal's avatar
geal committed
85

gbazin's avatar
gbazin committed
86
87
88
89
90
91
92
93
94
95
96
97
98
99
    p_xml->pf_reader_create = ReaderCreate;
    p_xml->pf_reader_delete = ReaderDelete;

    p_xml->pf_catalog_load = CatalogLoad;
    p_xml->pf_catalog_add  = CatalogAdd;

    return VLC_SUCCESS;
}

/*****************************************************************************
 * Module deinitialization
 *****************************************************************************/
static void Close( vlc_object_t *p_this )
{
100
#ifdef LIBXML_GETS_A_CLUE_ABOUT_REENTRANCY_AND_MEMORY_LEAKS
101
    vlc_mutex_lock( &lock );
102
    xmlCleanupParser();
103
    vlc_mutex_unlock( &lock );
104
#endif
Rafaël Carré's avatar
Rafaël Carré committed
105
    VLC_UNUSED(p_this);
gbazin's avatar
gbazin committed
106
107
108
109
110
111
112
113
    return;
}

/*****************************************************************************
 * Catalogue functions
 *****************************************************************************/
static void CatalogLoad( xml_t *p_xml, const char *psz_filename )
{
Rafaël Carré's avatar
Rafaël Carré committed
114
    VLC_UNUSED(p_xml);
gbazin's avatar
gbazin committed
115
116
117
118
119
120
121
    if( !psz_filename ) xmlInitializeCatalog();
    else xmlLoadCatalog( psz_filename );
}

static void CatalogAdd( xml_t *p_xml, const char *psz_arg1,
                          const char *psz_arg2, const char *psz_filename )
{
Rafaël Carré's avatar
Rafaël Carré committed
122
    VLC_UNUSED(p_xml);
123
    xmlCatalogAdd( (unsigned char*)psz_arg1, (unsigned char*)psz_arg2,
124
        (unsigned char*)psz_filename );
gbazin's avatar
gbazin committed
125
126
127
128
129
130
131
132
133
}

/*****************************************************************************
 * Reader functions
 *****************************************************************************/
static void ReaderErrorHandler( void *p_arg, const char *p_msg,
                                xmlParserSeverities severity,
                                xmlTextReaderLocatorPtr locator)
{
Rafaël Carré's avatar
Rafaël Carré committed
134
    VLC_UNUSED(severity);
gbazin's avatar
gbazin committed
135
136
137
138
139
    xml_reader_t *p_reader = (xml_reader_t *)p_arg;
    int line = xmlTextReaderLocatorLineNumber( locator );
    msg_Err( p_reader->p_xml, "XML parser error (line %d) : %s", line, p_msg );
}

sigmunau's avatar
sigmunau committed
140
static xml_reader_t *ReaderCreate( xml_t *p_xml, stream_t *p_stream )
gbazin's avatar
gbazin committed
141
142
143
144
{
    xml_reader_t *p_reader;
    xml_reader_sys_t *p_sys;
    xmlTextReaderPtr p_libxml_reader;
sigmunau's avatar
sigmunau committed
145
146
147

    p_libxml_reader = xmlReaderForIO( StreamRead, NULL, p_stream,
                                      NULL, NULL, 0 );
gbazin's avatar
gbazin committed
148
149
    if( !p_libxml_reader )
    {
150
        msg_Err( p_xml, "failed to create XML parser" );
ivoire's avatar
ivoire committed
151
        return NULL;
gbazin's avatar
gbazin committed
152
153
154
    }

    p_reader = malloc( sizeof(xml_reader_t) );
ivoire's avatar
ivoire committed
155
156
    if( !p_reader )
    {
157
        xmlFreeTextReader( p_libxml_reader );
ivoire's avatar
ivoire committed
158
159
        return NULL;
    }
gbazin's avatar
gbazin committed
160
    p_reader->p_sys = p_sys = malloc( sizeof(xml_reader_sys_t) );
ivoire's avatar
ivoire committed
161
162
    if( !p_sys )
    {
163
        xmlFreeTextReader( p_libxml_reader );
ivoire's avatar
ivoire committed
164
165
166
        free( p_reader );
        return NULL;
    }
gbazin's avatar
gbazin committed
167
168
169
170
171
172
173
174
175
176
177
178
179
    p_reader->p_sys->p_reader = p_libxml_reader;
    p_reader->p_xml = p_xml;

    /* Set the error handler */
    xmlTextReaderSetErrorHandler( p_libxml_reader,
                                  ReaderErrorHandler, p_reader );


    p_reader->pf_read = ReaderRead;
    p_reader->pf_node_type = ReaderNodeType;
    p_reader->pf_name = ReaderName;
    p_reader->pf_value = ReaderValue;
    p_reader->pf_next_attr = ReaderNextAttr;
180
    p_reader->pf_use_dtd = ReaderUseDTD;
gbazin's avatar
gbazin committed
181
182
183
184
185
186
187
188
189
190
191

    return p_reader;
}

static void ReaderDelete( xml_reader_t *p_reader )
{
    xmlFreeTextReader( p_reader->p_sys->p_reader );
    free( p_reader->p_sys );
    free( p_reader );
}

192
static int ReaderUseDTD ( xml_reader_t *p_reader, bool b_use )
193
194
195
196
197
198
199
200
201
202
{
    /* Activate DTD validation */
    xmlTextReaderSetParserProp( p_reader->p_sys->p_reader,
                                XML_PARSER_DEFAULTATTRS, b_use );
    xmlTextReaderSetParserProp( p_reader->p_sys->p_reader,
                                XML_PARSER_VALIDATE, b_use );

    return VLC_SUCCESS;
}

gbazin's avatar
gbazin committed
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
static int ReaderRead( xml_reader_t *p_reader )
{
    int i_ret = xmlTextReaderRead( p_reader->p_sys->p_reader );

#if 0
    switch( i_ret )
    {
    default:
    }
#endif

    return i_ret;
}

static int ReaderNodeType( xml_reader_t *p_reader )
{
    int i_ret = xmlTextReaderNodeType( p_reader->p_sys->p_reader );

    switch( i_ret )
    {
    case XML_READER_TYPE_ELEMENT:
        i_ret = XML_READER_STARTELEM;
        break;
    case XML_READER_TYPE_END_ELEMENT:
        i_ret = XML_READER_ENDELEM;
        break;
229
    case XML_READER_TYPE_CDATA:
230
231
232
    case XML_READER_TYPE_TEXT:
        i_ret = XML_READER_TEXT;
        break;
gbazin's avatar
gbazin committed
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
    case -1:
        i_ret = -1;
        break;
    default:
        i_ret = XML_READER_NONE;
        break;
    }

    return i_ret;
}

static char *ReaderName( xml_reader_t *p_reader )
{
    const xmlChar *psz_name =
        xmlTextReaderConstName( p_reader->p_sys->p_reader );

gbazin's avatar
gbazin committed
249
    if( psz_name ) return strdup( (const char *)psz_name );
gbazin's avatar
gbazin committed
250
251
252
253
254
255
256
257
    else return 0;
}

static char *ReaderValue( xml_reader_t *p_reader )
{
    const xmlChar *psz_value =
        xmlTextReaderConstValue( p_reader->p_sys->p_reader );

gbazin's avatar
gbazin committed
258
    if( psz_value ) return strdup( (const char *)psz_value );
gbazin's avatar
gbazin committed
259
260
261
262
263
264
265
266
    else return 0;
}

static int ReaderNextAttr( xml_reader_t *p_reader )
{
    return ( xmlTextReaderMoveToNextAttribute( p_reader->p_sys->p_reader )
             == 1 ) ? VLC_SUCCESS : VLC_EGENERIC;
}
sigmunau's avatar
sigmunau committed
267
268
269
270

static int StreamRead( void *p_context, char *p_buffer, int i_buffer )
{
    stream_t *s = (stream_t*)p_context;
271
    return stream_Read( s, p_buffer, i_buffer );
sigmunau's avatar
sigmunau committed
272
}