]> git.sesse.net Git - vlc/blobdiff - modules/gui/skins2/parser/xmlparser.cpp
skins2: don't load XML catalog if DTD not requested
[vlc] / modules / gui / skins2 / parser / xmlparser.cpp
index 037fd12f10f2dd2a5d3dc8547cfd3a652bd8a81e..ca287da27f95484e2f8d27f3ba838bcbfa26dd0f 100644 (file)
@@ -1,8 +1,8 @@
 /*****************************************************************************
  * xmlparser.cpp
  *****************************************************************************
- * Copyright (C) 2004 VideoLAN
- * $Id: xmlparser.cpp,v 1.5 2004/02/01 14:44:11 asmax Exp $
+ * Copyright (C) 2004 the VideoLAN team
+ * $Id$
  *
  * Authors: Cyril Deguet     <asmax@via.ecp.fr>
  *
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  *****************************************************************************/
 
 #include "xmlparser.hpp"
+#include "../src/os_factory.hpp"
+#include <vlc_url.h>
 
-XMLParser::XMLParser( intf_thread_t *pIntf, const string &rFileName ):
+#ifdef HAVE_SYS_STAT_H
+#   include <sys/stat.h>
+#endif
+
+// Static variable to avoid initializing catalogs twice
+static bool m_initialized = false;
+
+XMLParser::XMLParser( intf_thread_t *pIntf, const string &rFileName,
+                      bool useDTD ):
     SkinObject( pIntf )
 {
-    m_pReader = xmlNewTextReaderFilename( rFileName.c_str() );
+    m_pReader = NULL;
+    m_pStream = NULL;
+
+    if( useDTD )
+    {
+        m_pXML = xml_Create( pIntf );
+        if( m_pXML )
+            LoadCatalog();
+        else
+        {
+            msg_Err( getIntf(), "DTD not supported" );
+            useDTD = false;
+        }
+    }
+    else
+        m_pXML = NULL;
+
+    char* psz_uri = make_URI( rFileName.c_str(), NULL );
+    m_pStream = stream_UrlNew( pIntf, psz_uri );
+    free( psz_uri );
+
+    if( !m_pStream )
+    {
+        msg_Err( getIntf(), "failed to open %s for reading",
+                 rFileName.c_str() );
+        return;
+    }
+    m_pReader = xml_ReaderCreate( m_pXML, m_pStream );
     if( !m_pReader )
     {
-        msg_Err( getIntf(), "Failed to open %s for parsing",
+        msg_Err( getIntf(), "failed to open %s for parsing",
                  rFileName.c_str() );
         return;
     }
 
-    // Activate DTD validation
-    xmlTextReaderSetParserProp( m_pReader, XML_PARSER_DEFAULTATTRS, 1 );
-    xmlTextReaderSetParserProp( m_pReader, XML_PARSER_VALIDATE, 1 );
-
-    // Set the error handler
-    xmlTextReaderSetErrorHandler( m_pReader, handleError, this );
+    xml_ReaderUseDTD( m_pReader, useDTD );
 }
 
 
 XMLParser::~XMLParser()
 {
-    if( m_pReader )
-    {
-        xmlFreeTextReader( m_pReader );
-    }
+    if( m_pReader ) xml_ReaderDelete( m_pReader );
+    if( m_pXML ) xml_Delete( m_pXML );
+    if( m_pStream ) stream_Delete( m_pStream );
 }
 
 
-bool XMLParser::parse()
+void XMLParser::LoadCatalog()
 {
-    if( !m_pReader )
+    // Get the resource path and look for the DTD
+    OSFactory *pOSFactory = OSFactory::instance( getIntf() );
+    const list<string> &resPath = pOSFactory->getResourcePath();
+    const string &sep = pOSFactory->getDirSeparator();
+    list<string>::const_iterator it;
+
+#ifdef HAVE_SYS_STAT_H
+    struct stat statBuf;
+
+    // Try to load the catalog first (needed at least on win32 where
+    // we don't have a default catalog)
+    for( it = resPath.begin(); it != resPath.end(); it++ )
+    {
+        string catalog_path = (*it) + sep + "skin.catalog";
+        if( !stat( catalog_path.c_str(), &statBuf ) )
+        {
+            msg_Dbg( getIntf(), "Using catalog %s", catalog_path.c_str() );
+            xml_CatalogLoad( m_pXML, catalog_path.c_str() );
+            break;
+        }
+    }
+    if( it == resPath.end() )
     {
-        return false;
+        // Ok, try the default one
+        xml_CatalogLoad( m_pXML, 0 );
     }
 
-    m_errors = false;
-
-    int ret = xmlTextReaderRead( m_pReader );
-    while (ret == 1)
+    for( it = resPath.begin(); it != resPath.end(); it++ )
     {
-        if( m_errors )
+        string path = (*it) + sep + "skin.dtd";
+        if( !stat( path.c_str(), &statBuf ) )
         {
-            return false;
+            // DTD found
+            msg_Dbg( getIntf(), "using DTD %s", path.c_str() );
+
+            // Add an entry in the default catalog
+            xml_CatalogAdd( m_pXML, "public",
+                            "-//VideoLAN//DTD VLC Skins V"
+                            SKINS_DTD_VERSION "//EN", path.c_str() );
+            break;
         }
+    }
+    if( it == resPath.end() )
+    {
+        msg_Err( getIntf(), "cannot find the skins DTD");
+    }
+#endif
+}
+
+bool XMLParser::parse()
+{
+    if( !m_pReader ) return false;
+
+    m_errors = false;
+
+    int ret = xml_ReaderRead( m_pReader );
+    while( ret == 1 )
+    {
+        if( m_errors ) return false;
+
         // Get the node type
-        int type = xmlTextReaderNodeType( m_pReader );
-        switch (type )
+        int type = xml_ReaderNodeType( m_pReader );
+        switchtype )
         {
             // Error
             case -1:
                 return false;
                 break;
 
-            // Begin element
-            case 1:
+            case XML_READER_STARTELEM:
             {
                 // Read the element name
-                const xmlChar *eltName = xmlTextReaderConstName( m_pReader );
-                if( !eltName )
-                {
-                    return false;
-                }
+                char *eltName = xml_ReaderName( m_pReader );
+                if( !eltName ) return false;
+
                 // Read the attributes
                 AttrList_t attributes;
-                while( xmlTextReaderMoveToNextAttribute( m_pReader ) == 1 )
+                while( xml_ReaderNextAttr( m_pReader ) == VLC_SUCCESS )
                 {
-                    const xmlChar *name = xmlTextReaderConstName( m_pReader );
-                    const xmlChar *value = xmlTextReaderConstValue( m_pReader );
+                    char *name = xml_ReaderName( m_pReader );
+                    char *value = xml_ReaderValue( m_pReader );
                     if( !name || !value )
                     {
+                        free( name );
+                        free( value );
                         return false;
                     }
-                    attributes[(const char*)name] = (const char*)value;
+                    attributes[name] = value;
+                }
+
+                handleBeginElement( eltName, attributes );
+                free( eltName );
+
+                map<const char*, const char*, ltstr> ::iterator it =
+                    attributes.begin();
+                while( it != attributes.end() )
+                {
+                    free( (char *)it->first );
+                    free( (char *)it->second );
+                    it++;
                 }
-                handleBeginElement( (const char*)eltName, attributes);
                 break;
             }
 
             // End element
-            case 15:
+            case XML_READER_ENDELEM:
+            {
                 // Read the element name
-                const xmlChar *eltName = xmlTextReaderConstName( m_pReader );
-                if( !eltName )
-                {
-                    return false;
-                }
-                handleEndElement( (const char*)eltName );
+                char *eltName = xml_ReaderName( m_pReader );
+                if( !eltName ) return false;
+
+                handleEndElement( eltName );
+                free( eltName );
                 break;
+            }
         }
-        ret = xmlTextReaderRead( m_pReader );
+        ret = xml_ReaderRead( m_pReader );
     }
     return (ret == 0 && !m_errors );
 }
-
-
-void XMLParser::handleError( void *pArg,  const char *pMsg,
-                             xmlParserSeverities severity,
-                             xmlTextReaderLocatorPtr locator)
-{
-    XMLParser *pThis = (XMLParser*)pArg;
-    int line = xmlTextReaderLocatorLineNumber( locator );
-    msg_Err( pThis->getIntf(), "XML parser error (line %d) : %s", line, pMsg );
-    pThis->m_errors = true;
-}