1 /*****************************************************************************
2 * xmlparser.cpp
3 *****************************************************************************
4 * Copyright (C) 2004 the VideoLAN team
5 * $Id: e19b34b76dc31806bf2bd594f5c0ea0e9e5a8c5f $
6 *
7 * Authors: Cyril Deguet <asmax@via.ecp.fr>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
23
24 #include "xmlparser.hpp"
25 #include "../src/os_factory.hpp"
26 #include <vlc_url.h>
27
28 #include <sys/stat.h>
29 #include <vlc_fs.h>
30
XMLParser(intf_thread_t * pIntf,const std::string & rFileName)31 XMLParser::XMLParser( intf_thread_t *pIntf, const std::string &rFileName )
32 : SkinObject( pIntf ), m_pXML( NULL ), m_pReader( NULL ), m_pStream( NULL )
33 {
34 m_errors = false;
35 m_pXML = xml_Create( pIntf );
36 if( !m_pXML )
37 {
38 msg_Err( getIntf(), "cannot initialize xml" );
39 return;
40 }
41
42 LoadCatalog();
43
44 char *psz_uri = vlc_path2uri( rFileName.c_str(), NULL );
45 m_pStream = vlc_stream_NewURL( pIntf, psz_uri );
46 free( psz_uri );
47 if( !m_pStream )
48 {
49 msg_Err( getIntf(), "failed to open %s for reading",
50 rFileName.c_str() );
51 return;
52 }
53
54 m_pReader = xml_ReaderCreate( m_pXML, m_pStream );
55 if( !m_pReader )
56 {
57 msg_Err( getIntf(), "failed to open %s for parsing",
58 rFileName.c_str() );
59 return;
60 }
61
62 xml_ReaderUseDTD( m_pReader );
63 }
64
65
~XMLParser()66 XMLParser::~XMLParser()
67 {
68 if( m_pReader ) xml_ReaderDelete( m_pReader );
69 if( m_pXML ) xml_Delete( m_pXML );
70 if( m_pStream ) vlc_stream_Delete( m_pStream );
71 }
72
73
LoadCatalog()74 void XMLParser::LoadCatalog()
75 {
76 // Get the resource path and look for the DTD
77 OSFactory *pOSFactory = OSFactory::instance( getIntf() );
78 const std::list<std::string> &resPath = pOSFactory->getResourcePath();
79 const std::string &sep = pOSFactory->getDirSeparator();
80 std::list<std::string>::const_iterator it;
81
82 struct stat statBuf;
83
84 // Try to load the catalog first (needed at least on win32 where
85 // we don't have a default catalog)
86 for( it = resPath.begin(); it != resPath.end(); ++it )
87 {
88 std::string catalog_path = (*it) + sep + "skin.catalog";
89 if( !vlc_stat( catalog_path.c_str(), &statBuf ) )
90 {
91 msg_Dbg( getIntf(), "Using catalog %s", catalog_path.c_str() );
92 xml_CatalogLoad( m_pXML, catalog_path.c_str() );
93 break;
94 }
95 }
96 if( it == resPath.end() )
97 {
98 // Ok, try the default one
99 xml_CatalogLoad( m_pXML, NULL );
100 }
101
102 for( it = resPath.begin(); it != resPath.end(); ++it )
103 {
104 std::string path = (*it) + sep + "skin.dtd";
105 if( !vlc_stat( path.c_str(), &statBuf ) )
106 {
107 // DTD found
108 msg_Dbg( getIntf(), "using DTD %s", path.c_str() );
109
110 // Add an entry in the default catalog
111 xml_CatalogAdd( m_pXML, "public",
112 "-//VideoLAN//DTD VLC Skins V"
113 SKINS_DTD_VERSION "//EN", path.c_str() );
114 break;
115 }
116 }
117 if( it == resPath.end() )
118 {
119 msg_Err( getIntf(), "cannot find the skins DTD");
120 }
121 }
122
parse()123 bool XMLParser::parse()
124 {
125 const char *node;
126 int type;
127
128 if( !m_pReader ) return false;
129
130 m_errors = false;
131
132 while( (type = xml_ReaderNextNode( m_pReader, &node )) > 0 )
133 {
134 if( m_errors ) return false;
135
136 switch( type )
137 {
138 case XML_READER_STARTELEM:
139 {
140 // Read the attributes
141 AttrList_t attributes;
142 const char *name, *value;
143 while( (name = xml_ReaderNextAttr( m_pReader, &value )) != NULL )
144 attributes[strdup(name)] = strdup(value);
145
146 handleBeginElement( node, attributes );
147
148 std::map<const char*, const char*, ltstr> ::iterator it =
149 attributes.begin();
150 while( it != attributes.end() )
151 {
152 free( (char *)it->first );
153 free( (char *)it->second );
154 ++it;
155 }
156 break;
157 }
158
159 // End element
160 case XML_READER_ENDELEM:
161 {
162 handleEndElement( node );
163 break;
164 }
165 }
166 }
167 return (type == 0 && !m_errors );
168 }
169