2001-05-10 18:17:55 +04:00
/**
* catalog . c : set of generic Catalog related routines
*
* Reference : SGML Open Technical Resolution TR9401 : 1997.
* http : //www.jclark.com/sp/catalog.htm
*
2001-08-20 04:08:40 +04:00
* XML Catalogs Working Draft 06 August 2001
* http : //www.oasis-open.org/committees/entity/spec-2001-08-06.html
*
2001-05-10 18:17:55 +04:00
* See Copyright for the status of this software .
*
* Daniel . Veillard @ imag . fr
*/
# include "libxml.h"
# ifdef LIBXML_CATALOG_ENABLED
# ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
# endif
# ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
# endif
# ifdef HAVE_UNISTD_H
# include <unistd.h>
# endif
# ifdef HAVE_FCNTL_H
# include <fcntl.h>
# endif
# include <string.h>
# include <libxml/xmlmemory.h>
# include <libxml/hash.h>
# include <libxml/uri.h>
# include <libxml/parserInternals.h>
# include <libxml/catalog.h>
# include <libxml/xmlerror.h>
2001-08-20 04:08:40 +04:00
/**
* TODO :
*
* macro to flag unimplemented blocks
*/
# define TODO \
xmlGenericError ( xmlGenericErrorContext , \
" Unimplemented block at %s:%d \n " , \
__FILE__ , __LINE__ ) ;
2001-05-10 18:17:55 +04:00
/************************************************************************
* *
* Types , all private *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-08-20 04:08:40 +04:00
typedef enum {
XML_CATA_PREFER_PUBLIC = 1 ,
XML_CATA_PREFER_SYSTEM
} xmlCatalogPrefer ;
2001-05-10 18:17:55 +04:00
typedef enum {
XML_CATA_NONE = 0 ,
XML_CATA_CATALOG ,
2001-08-20 04:08:40 +04:00
XML_CATA_NEXT_CATALOG ,
XML_CATA_PUBLIC ,
XML_CATA_SYSTEM ,
XML_CATA_REWRITE_SYSTEM ,
XML_CATA_DELEGATE_PUBLIC ,
XML_CATA_DELEGATE_SYSTEM ,
XML_CATA_URI ,
XML_CATA_REWRITE_URI ,
XML_CATA_DELEGATE_URI ,
SGML_CATA_SYSTEM ,
SGML_CATA_PUBLIC ,
SGML_CATA_ENTITY ,
SGML_CATA_PENTITY ,
SGML_CATA_DOCTYPE ,
SGML_CATA_LINKTYPE ,
SGML_CATA_NOTATION ,
SGML_CATA_DELEGATE ,
SGML_CATA_BASE ,
SGML_CATA_CATALOG ,
SGML_CATA_DOCUMENT ,
SGML_CATA_SGMLDECL
2001-05-10 18:17:55 +04:00
} xmlCatalogEntryType ;
typedef struct _xmlCatalogEntry xmlCatalogEntry ;
typedef xmlCatalogEntry * xmlCatalogEntryPtr ;
struct _xmlCatalogEntry {
2001-08-20 04:08:40 +04:00
struct _xmlCatalogEntry * next ;
struct _xmlCatalogEntry * parent ;
struct _xmlCatalogEntry * children ;
2001-05-10 18:17:55 +04:00
xmlCatalogEntryType type ;
xmlChar * name ;
xmlChar * value ;
} ;
static xmlHashTablePtr xmlDefaultCatalog ;
2001-08-20 04:08:40 +04:00
static xmlCatalogEntryPtr xmlDefaultXMLCatalogList = NULL ;
2001-05-10 18:17:55 +04:00
2001-05-21 18:11:26 +04:00
/* Catalog stack */
2001-05-22 19:08:55 +04:00
static const char * catalTab [ 10 ] ; /* stack of catals */
static int catalNr = 0 ; /* Number of current catal streams */
static int catalMax = 10 ; /* Max number of catal streams */
2001-05-21 18:11:26 +04:00
2001-08-20 04:08:40 +04:00
static int xmlDebugCatalogs = 0 ; /* used for debugging */
2001-05-10 18:17:55 +04:00
/************************************************************************
* *
* alloc or dealloc *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static xmlCatalogEntryPtr
2001-08-20 04:08:40 +04:00
xmlNewCatalogEntry ( xmlCatalogEntryType type , const xmlChar * name ,
const xmlChar * value ) {
2001-05-10 18:17:55 +04:00
xmlCatalogEntryPtr ret ;
ret = ( xmlCatalogEntryPtr ) xmlMalloc ( sizeof ( xmlCatalogEntry ) ) ;
if ( ret = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" malloc of %d byte failed \n " , sizeof ( xmlCatalogEntry ) ) ;
return ( NULL ) ;
}
2001-08-20 04:08:40 +04:00
ret - > next = NULL ;
ret - > parent = NULL ;
ret - > children = NULL ;
2001-05-10 18:17:55 +04:00
ret - > type = type ;
2001-08-20 04:08:40 +04:00
if ( name ! = NULL )
ret - > name = xmlStrdup ( name ) ;
else
ret - > name = NULL ;
if ( value ! = NULL )
ret - > value = xmlStrdup ( value ) ;
else
ret - > value = NULL ;
2001-05-10 18:17:55 +04:00
return ( ret ) ;
}
2001-08-20 04:08:40 +04:00
static void
xmlFreeCatalogEntryList ( xmlCatalogEntryPtr ret ) ;
2001-05-10 18:17:55 +04:00
static void
xmlFreeCatalogEntry ( xmlCatalogEntryPtr ret ) {
if ( ret = = NULL )
return ;
2001-08-20 04:08:40 +04:00
if ( ret - > children ! = NULL )
xmlFreeCatalogEntryList ( ret - > children ) ;
2001-05-10 18:17:55 +04:00
if ( ret - > name ! = NULL )
xmlFree ( ret - > name ) ;
if ( ret - > value ! = NULL )
xmlFree ( ret - > value ) ;
xmlFree ( ret ) ;
}
2001-08-20 04:08:40 +04:00
static void
xmlFreeCatalogEntryList ( xmlCatalogEntryPtr ret ) {
xmlCatalogEntryPtr next ;
while ( ret ! = NULL ) {
next = ret - > next ;
xmlFreeCatalogEntry ( ret ) ;
ret = next ;
}
}
2001-05-10 19:34:11 +04:00
/**
* xmlCatalogDumpEntry :
* @ entry : the
* @ out : the file .
*
* Free up all the memory associated with catalogs
*/
static void
xmlCatalogDumpEntry ( xmlCatalogEntryPtr entry , FILE * out ) {
if ( ( entry = = NULL ) | | ( out = = NULL ) )
return ;
switch ( entry - > type ) {
2001-08-20 04:08:40 +04:00
case SGML_CATA_ENTITY :
2001-05-10 19:34:11 +04:00
fprintf ( out , " ENTITY " ) ; break ;
2001-08-20 04:08:40 +04:00
case SGML_CATA_PENTITY :
2001-05-10 19:34:11 +04:00
fprintf ( out , " ENTITY %% " ) ; break ;
2001-08-20 04:08:40 +04:00
case SGML_CATA_DOCTYPE :
2001-05-10 19:34:11 +04:00
fprintf ( out , " DOCTYPE " ) ; break ;
2001-08-20 04:08:40 +04:00
case SGML_CATA_LINKTYPE :
2001-05-10 19:34:11 +04:00
fprintf ( out , " LINKTYPE " ) ; break ;
2001-08-20 04:08:40 +04:00
case SGML_CATA_NOTATION :
2001-05-10 19:34:11 +04:00
fprintf ( out , " NOTATION " ) ; break ;
2001-08-20 04:08:40 +04:00
case SGML_CATA_PUBLIC :
2001-05-10 19:34:11 +04:00
fprintf ( out , " PUBLIC " ) ; break ;
2001-08-20 04:08:40 +04:00
case SGML_CATA_SYSTEM :
2001-05-10 19:34:11 +04:00
fprintf ( out , " SYSTEM " ) ; break ;
2001-08-20 04:08:40 +04:00
case SGML_CATA_DELEGATE :
2001-05-10 19:34:11 +04:00
fprintf ( out , " DELEGATE " ) ; break ;
2001-08-20 04:08:40 +04:00
case SGML_CATA_BASE :
2001-05-10 19:34:11 +04:00
fprintf ( out , " BASE " ) ; break ;
2001-08-20 04:08:40 +04:00
case SGML_CATA_CATALOG :
2001-05-10 19:34:11 +04:00
fprintf ( out , " CATALOG " ) ; break ;
2001-08-20 04:08:40 +04:00
case SGML_CATA_DOCUMENT :
2001-05-10 19:34:11 +04:00
fprintf ( out , " DOCUMENT " ) ; break ;
2001-08-20 04:08:40 +04:00
case SGML_CATA_SGMLDECL :
2001-05-10 19:34:11 +04:00
fprintf ( out , " SGMLDECL " ) ; break ;
default :
return ;
}
switch ( entry - > type ) {
2001-08-20 04:08:40 +04:00
case SGML_CATA_ENTITY :
case SGML_CATA_PENTITY :
case SGML_CATA_DOCTYPE :
case SGML_CATA_LINKTYPE :
case SGML_CATA_NOTATION :
2001-05-10 19:34:11 +04:00
fprintf ( out , " %s " , entry - > name ) ; break ;
2001-08-20 04:08:40 +04:00
case SGML_CATA_PUBLIC :
case SGML_CATA_SYSTEM :
case SGML_CATA_SGMLDECL :
case SGML_CATA_DOCUMENT :
case SGML_CATA_CATALOG :
case SGML_CATA_BASE :
case SGML_CATA_DELEGATE :
2001-05-10 19:34:11 +04:00
fprintf ( out , " \" %s \" " , entry - > name ) ; break ;
default :
break ;
}
switch ( entry - > type ) {
2001-08-20 04:08:40 +04:00
case SGML_CATA_ENTITY :
case SGML_CATA_PENTITY :
case SGML_CATA_DOCTYPE :
case SGML_CATA_LINKTYPE :
case SGML_CATA_NOTATION :
case SGML_CATA_PUBLIC :
case SGML_CATA_SYSTEM :
case SGML_CATA_DELEGATE :
2001-05-10 19:34:11 +04:00
fprintf ( out , " \" %s \" " , entry - > value ) ; break ;
default :
break ;
}
fprintf ( out , " \n " ) ;
}
2001-05-10 18:17:55 +04:00
/************************************************************************
* *
2001-08-20 04:08:40 +04:00
* The XML Catalog parser *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static xmlCatalogEntryPtr
xmlParseXMLCatalogFile ( xmlCatalogPrefer prefer , const xmlChar * filename ) ;
static xmlCatalogEntryPtr
xmlParseXMLCatalog ( const xmlChar * value , xmlCatalogPrefer prefer ,
const char * file ) ;
static void
xmlParseXMLCatalogNodeList ( xmlNodePtr cur , xmlCatalogPrefer prefer ,
xmlCatalogEntryPtr parent ) ;
static xmlCatalogEntryType
xmlGetXMLCatalogEntryType ( const xmlChar * name ) {
xmlCatalogEntryType type = XML_CATA_NONE ;
if ( xmlStrEqual ( name , ( const xmlChar * ) " system " ) )
type = XML_CATA_SYSTEM ;
else if ( xmlStrEqual ( name , ( const xmlChar * ) " public " ) )
type = XML_CATA_PUBLIC ;
else if ( xmlStrEqual ( name , ( const xmlChar * ) " rewriteSystem " ) )
type = XML_CATA_REWRITE_SYSTEM ;
else if ( xmlStrEqual ( name , ( const xmlChar * ) " delegatePublic " ) )
type = XML_CATA_DELEGATE_PUBLIC ;
else if ( xmlStrEqual ( name , ( const xmlChar * ) " delegateSystem " ) )
type = XML_CATA_DELEGATE_SYSTEM ;
else if ( xmlStrEqual ( name , ( const xmlChar * ) " uri " ) )
type = XML_CATA_URI ;
else if ( xmlStrEqual ( name , ( const xmlChar * ) " rewriteURI " ) )
type = XML_CATA_REWRITE_URI ;
else if ( xmlStrEqual ( name , ( const xmlChar * ) " delegateURI " ) )
type = XML_CATA_DELEGATE_URI ;
else if ( xmlStrEqual ( name , ( const xmlChar * ) " nextCatalog " ) )
type = XML_CATA_NEXT_CATALOG ;
else if ( xmlStrEqual ( name , ( const xmlChar * ) " catalog " ) )
type = XML_CATA_CATALOG ;
return ( type ) ;
}
static xmlCatalogEntryPtr
xmlParseXMLCatalogOneNode ( xmlNodePtr cur , xmlCatalogEntryType type ,
const xmlChar * name , const xmlChar * attrName ,
const xmlChar * uriAttrName ) {
int ok = 1 ;
xmlChar * uriValue ;
xmlChar * nameValue = NULL ;
xmlChar * base = NULL ;
xmlChar * URL = NULL ;
xmlCatalogEntryPtr ret = NULL ;
if ( attrName ! = NULL ) {
nameValue = xmlGetProp ( cur , attrName ) ;
if ( nameValue = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" %s entry lacks '%s' \n " , name , attrName ) ;
ok = 0 ;
}
}
uriValue = xmlGetProp ( cur , uriAttrName ) ;
if ( uriValue = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" %s entry lacks '%s' \n " , name , uriAttrName ) ;
ok = 0 ;
}
if ( ! ok ) {
if ( nameValue ! = NULL )
xmlFree ( nameValue ) ;
if ( uriValue ! = NULL )
xmlFree ( uriValue ) ;
return ( NULL ) ;
}
base = xmlNodeGetBase ( cur - > doc , cur ) ;
URL = xmlBuildURI ( uriValue , base ) ;
if ( URL ! = NULL ) {
if ( xmlDebugCatalogs ) {
if ( nameValue ! = NULL )
printf ( " Found %s: '%s' '%s' \n " , name , nameValue , URL ) ;
else
printf ( " Found %s: '%s' \n " , name , URL ) ;
}
ret = xmlNewCatalogEntry ( type , nameValue , URL ) ;
} else {
xmlGenericError ( xmlGenericErrorContext ,
" %s entry '%s' broken ?: %s \n " , name , uriAttrName , uriValue ) ;
}
if ( nameValue ! = NULL )
xmlFree ( nameValue ) ;
if ( uriValue ! = NULL )
xmlFree ( uriValue ) ;
if ( base ! = NULL )
xmlFree ( base ) ;
if ( URL ! = NULL )
xmlFree ( URL ) ;
return ( ret ) ;
}
static void
xmlParseXMLCatalogNode ( xmlNodePtr cur , xmlCatalogPrefer prefer ,
xmlCatalogEntryPtr parent )
{
xmlChar * uri = NULL ;
xmlChar * URL = NULL ;
xmlChar * base = NULL ;
xmlCatalogEntryPtr entry = NULL ;
if ( cur = = NULL )
return ;
if ( xmlStrEqual ( cur - > name , BAD_CAST " group " ) ) {
xmlChar * prop ;
prop = xmlGetProp ( cur , BAD_CAST " prefer " ) ;
if ( prop ! = NULL ) {
if ( xmlStrEqual ( prop , BAD_CAST " system " ) ) {
prefer = XML_CATA_PREFER_SYSTEM ;
} else if ( xmlStrEqual ( prop , BAD_CAST " public " ) ) {
prefer = XML_CATA_PREFER_PUBLIC ;
} else {
xmlGenericError ( xmlGenericErrorContext ,
" Invalid value for prefer: '%s' \n " , prop ) ;
}
xmlFree ( prop ) ;
}
/*
* Recurse to propagate prefer to the subtree
* ( xml : base handling is automated )
*/
xmlParseXMLCatalogNodeList ( cur - > children , prefer , parent ) ;
} else if ( xmlStrEqual ( cur - > name , BAD_CAST " public " ) ) {
entry = xmlParseXMLCatalogOneNode ( cur , XML_CATA_PUBLIC ,
BAD_CAST " public " , BAD_CAST " publicId " , BAD_CAST " uri " ) ;
} else if ( xmlStrEqual ( cur - > name , BAD_CAST " system " ) ) {
entry = xmlParseXMLCatalogOneNode ( cur , XML_CATA_SYSTEM ,
BAD_CAST " system " , BAD_CAST " systemId " , BAD_CAST " uri " ) ;
} else if ( xmlStrEqual ( cur - > name , BAD_CAST " rewriteSystem " ) ) {
entry = xmlParseXMLCatalogOneNode ( cur , XML_CATA_REWRITE_SYSTEM ,
BAD_CAST " rewriteSystem " , BAD_CAST " systemIdStartString " ,
BAD_CAST " rewritePrefix " ) ;
} else if ( xmlStrEqual ( cur - > name , BAD_CAST " delegatePublic " ) ) {
entry = xmlParseXMLCatalogOneNode ( cur , XML_CATA_DELEGATE_PUBLIC ,
BAD_CAST " delegatePublic " , BAD_CAST " publicIdStartString " ,
BAD_CAST " catalog " ) ;
} else if ( xmlStrEqual ( cur - > name , BAD_CAST " delegateSystem " ) ) {
entry = xmlParseXMLCatalogOneNode ( cur , XML_CATA_DELEGATE_SYSTEM ,
BAD_CAST " delegateSystem " , BAD_CAST " systemIdStartString " ,
BAD_CAST " catalog " ) ;
} else if ( xmlStrEqual ( cur - > name , BAD_CAST " uri " ) ) {
entry = xmlParseXMLCatalogOneNode ( cur , XML_CATA_URI ,
BAD_CAST " uri " , BAD_CAST " name " ,
BAD_CAST " uri " ) ;
} else if ( xmlStrEqual ( cur - > name , BAD_CAST " rewriteURI " ) ) {
entry = xmlParseXMLCatalogOneNode ( cur , XML_CATA_REWRITE_URI ,
BAD_CAST " rewriteURI " , BAD_CAST " uriStartString " ,
BAD_CAST " rewritePrefix " ) ;
} else if ( xmlStrEqual ( cur - > name , BAD_CAST " delegateURI " ) ) {
entry = xmlParseXMLCatalogOneNode ( cur , XML_CATA_DELEGATE_URI ,
BAD_CAST " delegateURI " , BAD_CAST " uriStartString " ,
BAD_CAST " catalog " ) ;
} else if ( xmlStrEqual ( cur - > name , BAD_CAST " nextCatalog " ) ) {
entry = xmlParseXMLCatalogOneNode ( cur , XML_CATA_NEXT_CATALOG ,
BAD_CAST " nextCatalog " , NULL ,
BAD_CAST " catalog " ) ;
}
if ( ( entry ! = NULL ) & & ( parent ! = NULL ) ) {
entry - > parent = parent ;
if ( parent - > children = = NULL )
parent - > children = entry ;
else {
xmlCatalogEntryPtr prev ;
prev = parent - > children ;
while ( prev - > next ! = NULL )
prev = prev - > next ;
prev - > next = entry ;
}
}
if ( base ! = NULL )
xmlFree ( base ) ;
if ( uri ! = NULL )
xmlFree ( uri ) ;
if ( URL ! = NULL )
xmlFree ( URL ) ;
}
static void
xmlParseXMLCatalogNodeList ( xmlNodePtr cur , xmlCatalogPrefer prefer ,
xmlCatalogEntryPtr parent ) {
while ( cur ! = NULL ) {
if ( ( cur - > ns ! = NULL ) & & ( cur - > ns - > href ! = NULL ) & &
( xmlStrEqual ( cur - > ns - > href , XML_CATALOGS_NAMESPACE ) ) ) {
xmlParseXMLCatalogNode ( cur , prefer , parent ) ;
}
cur = cur - > next ;
}
/* TODO: sort the list according to REWRITE lengths and prefer value */
}
static xmlCatalogEntryPtr
xmlParseXMLCatalog ( const xmlChar * value , xmlCatalogPrefer prefer ,
const char * file ) {
xmlDocPtr doc ;
xmlNodePtr cur ;
xmlChar * prop ;
xmlCatalogEntryPtr parent = NULL ;
if ( ( value = = NULL ) | | ( file = = NULL ) )
return ( NULL ) ;
doc = xmlParseDoc ( ( xmlChar * ) value ) ;
if ( doc = = NULL )
return ( NULL ) ;
doc - > URL = xmlStrdup ( ( const xmlChar * ) file ) ;
cur = xmlDocGetRootElement ( doc ) ;
if ( ( cur ! = NULL ) & & ( xmlStrEqual ( cur - > name , BAD_CAST " catalog " ) ) & &
( cur - > ns ! = NULL ) & & ( cur - > ns - > href ! = NULL ) & &
( xmlStrEqual ( cur - > ns - > href , XML_CATALOGS_NAMESPACE ) ) ) {
parent = xmlNewCatalogEntry ( XML_CATA_CATALOG ,
( const xmlChar * ) file , NULL ) ;
if ( parent = = NULL ) {
xmlFreeDoc ( doc ) ;
return ( NULL ) ;
}
prop = xmlGetProp ( cur , BAD_CAST " prefer " ) ;
if ( prop ! = NULL ) {
if ( xmlStrEqual ( prop , BAD_CAST " system " ) ) {
prefer = XML_CATA_PREFER_SYSTEM ;
} else if ( xmlStrEqual ( prop , BAD_CAST " public " ) ) {
prefer = XML_CATA_PREFER_PUBLIC ;
} else {
xmlGenericError ( xmlGenericErrorContext ,
" Invalid value for prefer: '%s' \n " ,
prop ) ;
}
xmlFree ( prop ) ;
}
cur = cur - > children ;
xmlParseXMLCatalogNodeList ( cur , prefer , parent ) ;
} else {
xmlGenericError ( xmlGenericErrorContext ,
" File %s is not an XML Catalog \n " , file ) ;
xmlFreeDoc ( doc ) ;
return ( NULL ) ;
}
xmlFreeDoc ( doc ) ;
return ( parent ) ;
}
static xmlCatalogEntryPtr
xmlParseXMLCatalogFile ( xmlCatalogPrefer prefer , const xmlChar * filename ) {
xmlDocPtr doc ;
xmlNodePtr cur ;
xmlChar * prop ;
xmlCatalogEntryPtr parent = NULL ;
if ( filename = = NULL )
return ( NULL ) ;
doc = xmlParseFile ( ( const char * ) filename ) ;
if ( doc = = NULL )
return ( NULL ) ;
cur = xmlDocGetRootElement ( doc ) ;
if ( ( cur ! = NULL ) & & ( xmlStrEqual ( cur - > name , BAD_CAST " catalog " ) ) & &
( cur - > ns ! = NULL ) & & ( cur - > ns - > href ! = NULL ) & &
( xmlStrEqual ( cur - > ns - > href , XML_CATALOGS_NAMESPACE ) ) ) {
parent = xmlNewCatalogEntry ( XML_CATA_CATALOG ,
( const xmlChar * ) filename , NULL ) ;
if ( parent = = NULL ) {
xmlFreeDoc ( doc ) ;
return ( NULL ) ;
}
prop = xmlGetProp ( cur , BAD_CAST " prefer " ) ;
if ( prop ! = NULL ) {
if ( xmlStrEqual ( prop , BAD_CAST " system " ) ) {
prefer = XML_CATA_PREFER_SYSTEM ;
} else if ( xmlStrEqual ( prop , BAD_CAST " public " ) ) {
prefer = XML_CATA_PREFER_PUBLIC ;
} else {
xmlGenericError ( xmlGenericErrorContext ,
" Invalid value for prefer: '%s' \n " ,
prop ) ;
}
xmlFree ( prop ) ;
}
cur = cur - > children ;
xmlParseXMLCatalogNodeList ( cur , prefer , parent ) ;
} else {
xmlGenericError ( xmlGenericErrorContext ,
" File %s is not an XML Catalog \n " , filename ) ;
xmlFreeDoc ( doc ) ;
return ( NULL ) ;
}
xmlFreeDoc ( doc ) ;
return ( parent ) ;
}
static int
xmlDumpXMLCatalog ( FILE * out , xmlCatalogEntryPtr catal ) {
int ret ;
xmlDocPtr doc ;
xmlNsPtr ns ;
xmlDtdPtr dtd ;
xmlNodePtr node , catalog ;
xmlOutputBufferPtr buf ;
xmlCatalogEntryPtr cur ;
/*
* Rebuild a catalog
*/
doc = xmlNewDoc ( NULL ) ;
if ( doc = = NULL )
return ( - 1 ) ;
dtd = xmlNewDtd ( doc , BAD_CAST " catalog " ,
BAD_CAST " -//OASIS//DTD Entity Resolution XML Catalog V1.0//EN " ,
BAD_CAST " http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd " ) ;
xmlAddChild ( ( xmlNodePtr ) doc , ( xmlNodePtr ) dtd ) ;
ns = xmlNewNs ( NULL , XML_CATALOGS_NAMESPACE , NULL ) ;
if ( ns = = NULL ) {
xmlFreeDoc ( doc ) ;
return ( - 1 ) ;
}
catalog = xmlNewDocNode ( doc , ns , BAD_CAST " catalog " , NULL ) ;
if ( catalog = = NULL ) {
xmlFreeNs ( ns ) ;
xmlFreeDoc ( doc ) ;
return ( - 1 ) ;
}
catalog - > nsDef = ns ;
xmlAddChild ( ( xmlNodePtr ) doc , catalog ) ;
/*
* add all the catalog entries
*/
cur = catal ;
while ( cur ! = NULL ) {
switch ( cur - > type ) {
case XML_CATA_CATALOG :
if ( cur = = catal ) {
cur = cur - > children ;
continue ;
}
break ;
case XML_CATA_NEXT_CATALOG :
node = xmlNewDocNode ( doc , ns , BAD_CAST " nextCatalog " , NULL ) ;
xmlSetProp ( node , BAD_CAST " catalog " , cur - > value ) ;
xmlAddChild ( catalog , node ) ;
break ;
case XML_CATA_NONE :
break ;
case XML_CATA_PUBLIC :
node = xmlNewDocNode ( doc , ns , BAD_CAST " public " , NULL ) ;
xmlSetProp ( node , BAD_CAST " publicId " , cur - > name ) ;
xmlSetProp ( node , BAD_CAST " uri " , cur - > value ) ;
xmlAddChild ( catalog , node ) ;
break ;
case XML_CATA_SYSTEM :
node = xmlNewDocNode ( doc , ns , BAD_CAST " system " , NULL ) ;
xmlSetProp ( node , BAD_CAST " systemId " , cur - > name ) ;
xmlSetProp ( node , BAD_CAST " uri " , cur - > value ) ;
xmlAddChild ( catalog , node ) ;
break ;
case XML_CATA_REWRITE_SYSTEM :
node = xmlNewDocNode ( doc , ns , BAD_CAST " rewriteSystem " , NULL ) ;
xmlSetProp ( node , BAD_CAST " systemIdStartString " , cur - > name ) ;
xmlSetProp ( node , BAD_CAST " rewritePrefix " , cur - > value ) ;
xmlAddChild ( catalog , node ) ;
break ;
case XML_CATA_DELEGATE_PUBLIC :
node = xmlNewDocNode ( doc , ns , BAD_CAST " delegatePublic " , NULL ) ;
xmlSetProp ( node , BAD_CAST " publicIdStartString " , cur - > name ) ;
xmlSetProp ( node , BAD_CAST " catalog " , cur - > value ) ;
xmlAddChild ( catalog , node ) ;
break ;
case XML_CATA_DELEGATE_SYSTEM :
node = xmlNewDocNode ( doc , ns , BAD_CAST " delegateSystem " , NULL ) ;
xmlSetProp ( node , BAD_CAST " systemIdStartString " , cur - > name ) ;
xmlSetProp ( node , BAD_CAST " catalog " , cur - > value ) ;
xmlAddChild ( catalog , node ) ;
break ;
case XML_CATA_URI :
node = xmlNewDocNode ( doc , ns , BAD_CAST " uri " , NULL ) ;
xmlSetProp ( node , BAD_CAST " name " , cur - > name ) ;
xmlSetProp ( node , BAD_CAST " uri " , cur - > value ) ;
xmlAddChild ( catalog , node ) ;
break ;
case XML_CATA_REWRITE_URI :
node = xmlNewDocNode ( doc , ns , BAD_CAST " rewriteURI " , NULL ) ;
xmlSetProp ( node , BAD_CAST " uriStartString " , cur - > name ) ;
xmlSetProp ( node , BAD_CAST " rewritePrefix " , cur - > value ) ;
xmlAddChild ( catalog , node ) ;
break ;
case XML_CATA_DELEGATE_URI :
node = xmlNewDocNode ( doc , ns , BAD_CAST " delegateURI " , NULL ) ;
xmlSetProp ( node , BAD_CAST " uriStartString " , cur - > name ) ;
xmlSetProp ( node , BAD_CAST " catalog " , cur - > value ) ;
xmlAddChild ( catalog , node ) ;
break ;
case SGML_CATA_SYSTEM :
case SGML_CATA_PUBLIC :
case SGML_CATA_ENTITY :
case SGML_CATA_PENTITY :
case SGML_CATA_DOCTYPE :
case SGML_CATA_LINKTYPE :
case SGML_CATA_NOTATION :
case SGML_CATA_DELEGATE :
case SGML_CATA_BASE :
case SGML_CATA_CATALOG :
case SGML_CATA_DOCUMENT :
case SGML_CATA_SGMLDECL :
break ;
}
cur = cur - > next ;
}
/*
* reserialize it
*/
buf = xmlOutputBufferCreateFile ( out , NULL ) ;
if ( buf = = NULL ) {
xmlFreeDoc ( doc ) ;
return ( - 1 ) ;
}
ret = xmlSaveFormatFileTo ( buf , doc , NULL , 1 ) ;
/*
* Free it
*/
xmlFreeDoc ( doc ) ;
return ( ret ) ;
}
/**
* xmlAddXMLCatalog :
* @ catal : top of an XML catalog
* @ type : the type of record to add to the catalog
* @ orig : the system , public or prefix to match
* @ replace : the replacement value for the match
*
* Add an entry in the XML catalog , it may overwrite existing but
* different entries .
*
* Returns 0 if successful , - 1 otherwise
*/
static int
xmlAddXMLCatalog ( xmlCatalogEntryPtr catal , const xmlChar * type ,
const xmlChar * orig , const xmlChar * replace ) {
xmlCatalogEntryPtr cur ;
xmlCatalogEntryType typ ;
if ( ( catal = = NULL ) | | ( catal - > type ! = XML_CATA_CATALOG ) )
return ( - 1 ) ;
typ = xmlGetXMLCatalogEntryType ( type ) ;
if ( typ = = XML_CATA_NONE )
return ( - 1 ) ;
cur = catal - > children ;
/*
* Might be a simple " update in place "
*/
if ( cur ! = NULL ) {
while ( cur ! = NULL ) {
cur = cur - > next ;
if ( ( cur - > type = = typ ) & & ( xmlStrEqual ( orig , cur - > name ) ) ) {
if ( cur - > value ! = NULL )
xmlFree ( cur - > value ) ;
cur - > value = xmlStrdup ( replace ) ;
return ( 1 ) ;
}
if ( cur - > next = = NULL )
break ;
cur = cur - > next ;
}
}
if ( cur = = NULL )
catal - > children = xmlNewCatalogEntry ( typ , orig , replace ) ;
else
cur - > next = xmlNewCatalogEntry ( typ , orig , replace ) ;
return ( 1 ) ;
}
/************************************************************************
* *
* The SGML Catalog parser *
2001-05-10 18:17:55 +04:00
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# define RAW *cur
# define NEXT cur++;
# define SKIP(x) cur += x;
# define SKIP_BLANKS while (IS_BLANK(*cur)) NEXT;
static const xmlChar *
xmlParseCatalogComment ( const xmlChar * cur ) {
if ( ( cur [ 0 ] ! = ' - ' ) | | ( cur [ 1 ] ! = ' - ' ) )
return ( cur ) ;
SKIP ( 2 ) ;
while ( ( cur [ 0 ] ! = 0 ) & & ( ( cur [ 0 ] ! = ' - ' ) | | ( ( cur [ 1 ] ! = ' - ' ) ) ) )
NEXT ;
if ( cur [ 0 ] = = 0 ) {
return ( NULL ) ;
}
2001-05-21 18:11:26 +04:00
return ( cur + 2 ) ;
2001-05-10 18:17:55 +04:00
}
static const xmlChar *
xmlParseCatalogPubid ( const xmlChar * cur , xmlChar * * id ) {
xmlChar * buf = NULL ;
int len = 0 ;
int size = 50 ;
xmlChar stop ;
int count = 0 ;
* id = NULL ;
if ( RAW = = ' " ' ) {
NEXT ;
stop = ' " ' ;
} else if ( RAW = = ' \' ' ) {
NEXT ;
stop = ' \' ' ;
} else {
stop = ' ' ;
}
buf = ( xmlChar * ) xmlMalloc ( size * sizeof ( xmlChar ) ) ;
if ( buf = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" malloc of %d byte failed \n " , size ) ;
return ( NULL ) ;
}
while ( xmlIsPubidChar ( * cur ) ) {
if ( ( * cur = = stop ) & & ( stop ! = ' ' ) )
break ;
if ( ( stop = = ' ' ) & & ( IS_BLANK ( * cur ) ) )
break ;
if ( len + 1 > = size ) {
size * = 2 ;
buf = ( xmlChar * ) xmlRealloc ( buf , size * sizeof ( xmlChar ) ) ;
if ( buf = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" realloc of %d byte failed \n " , size ) ;
return ( NULL ) ;
}
}
buf [ len + + ] = * cur ;
count + + ;
NEXT ;
}
buf [ len ] = 0 ;
if ( stop = = ' ' ) {
if ( ! IS_BLANK ( * cur ) ) {
xmlFree ( buf ) ;
return ( NULL ) ;
}
} else {
if ( * cur ! = stop ) {
xmlFree ( buf ) ;
return ( NULL ) ;
}
NEXT ;
}
* id = buf ;
return ( cur ) ;
}
static const xmlChar *
xmlParseCatalogName ( const xmlChar * cur , xmlChar * * name ) {
xmlChar buf [ XML_MAX_NAMELEN + 5 ] ;
int len = 0 ;
int c ;
* name = NULL ;
/*
* Handler for more complex cases
*/
c = * cur ;
if ( ( ! IS_LETTER ( c ) & & ( c ! = ' _ ' ) & & ( c ! = ' : ' ) ) ) {
return ( NULL ) ;
}
while ( ( ( IS_LETTER ( c ) ) | | ( IS_DIGIT ( c ) ) | |
( c = = ' . ' ) | | ( c = = ' - ' ) | |
( c = = ' _ ' ) | | ( c = = ' : ' ) ) ) {
buf [ len + + ] = c ;
cur + + ;
c = * cur ;
if ( len > = XML_MAX_NAMELEN )
return ( NULL ) ;
}
* name = xmlStrndup ( buf , len ) ;
return ( cur ) ;
}
2001-08-20 04:08:40 +04:00
static xmlCatalogEntryType
xmlGetCatalogEntryType ( const xmlChar * name ) {
xmlCatalogEntryType type = XML_CATA_NONE ;
if ( xmlStrEqual ( name , ( const xmlChar * ) " SYSTEM " ) )
type = SGML_CATA_SYSTEM ;
else if ( xmlStrEqual ( name , ( const xmlChar * ) " PUBLIC " ) )
type = SGML_CATA_PUBLIC ;
else if ( xmlStrEqual ( name , ( const xmlChar * ) " DELEGATE " ) )
type = SGML_CATA_DELEGATE ;
else if ( xmlStrEqual ( name , ( const xmlChar * ) " ENTITY " ) )
type = SGML_CATA_ENTITY ;
else if ( xmlStrEqual ( name , ( const xmlChar * ) " DOCTYPE " ) )
type = SGML_CATA_DOCTYPE ;
else if ( xmlStrEqual ( name , ( const xmlChar * ) " LINKTYPE " ) )
type = SGML_CATA_LINKTYPE ;
else if ( xmlStrEqual ( name , ( const xmlChar * ) " NOTATION " ) )
type = SGML_CATA_NOTATION ;
else if ( xmlStrEqual ( name , ( const xmlChar * ) " SGMLDECL " ) )
type = SGML_CATA_SGMLDECL ;
else if ( xmlStrEqual ( name , ( const xmlChar * ) " DOCUMENT " ) )
type = SGML_CATA_DOCUMENT ;
else if ( xmlStrEqual ( name , ( const xmlChar * ) " CATALOG " ) )
type = SGML_CATA_CATALOG ;
else if ( xmlStrEqual ( name , ( const xmlChar * ) " BASE " ) )
type = SGML_CATA_BASE ;
else if ( xmlStrEqual ( name , ( const xmlChar * ) " DELEGATE " ) )
type = SGML_CATA_DELEGATE ;
return ( type ) ;
}
2001-05-10 18:17:55 +04:00
static int
xmlParseCatalog ( const xmlChar * value , const char * file ) {
const xmlChar * cur = value ;
xmlChar * base = NULL ;
2001-05-21 18:11:26 +04:00
int res ;
2001-05-10 18:17:55 +04:00
if ( ( cur = = NULL ) | | ( file = = NULL ) )
return ( - 1 ) ;
base = xmlStrdup ( ( const xmlChar * ) file ) ;
while ( ( cur ! = NULL ) & & ( cur [ 0 ] ! = ' 0 ' ) ) {
SKIP_BLANKS ;
if ( ( cur [ 0 ] = = ' - ' ) & & ( cur [ 1 ] = = ' - ' ) ) {
cur = xmlParseCatalogComment ( cur ) ;
if ( cur = = NULL ) {
/* error */
break ;
}
} else {
xmlChar * sysid = NULL ;
xmlChar * name = NULL ;
xmlCatalogEntryType type = XML_CATA_NONE ;
cur = xmlParseCatalogName ( cur , & name ) ;
if ( name = = NULL ) {
/* error */
break ;
}
if ( ! IS_BLANK ( * cur ) ) {
/* error */
break ;
}
SKIP_BLANKS ;
if ( xmlStrEqual ( name , ( const xmlChar * ) " SYSTEM " ) )
2001-08-20 04:08:40 +04:00
type = SGML_CATA_SYSTEM ;
2001-05-10 18:17:55 +04:00
else if ( xmlStrEqual ( name , ( const xmlChar * ) " PUBLIC " ) )
2001-08-20 04:08:40 +04:00
type = SGML_CATA_PUBLIC ;
2001-05-10 18:17:55 +04:00
else if ( xmlStrEqual ( name , ( const xmlChar * ) " DELEGATE " ) )
2001-08-20 04:08:40 +04:00
type = SGML_CATA_DELEGATE ;
2001-05-10 18:17:55 +04:00
else if ( xmlStrEqual ( name , ( const xmlChar * ) " ENTITY " ) )
2001-08-20 04:08:40 +04:00
type = SGML_CATA_ENTITY ;
2001-05-10 18:17:55 +04:00
else if ( xmlStrEqual ( name , ( const xmlChar * ) " DOCTYPE " ) )
2001-08-20 04:08:40 +04:00
type = SGML_CATA_DOCTYPE ;
2001-05-10 18:17:55 +04:00
else if ( xmlStrEqual ( name , ( const xmlChar * ) " LINKTYPE " ) )
2001-08-20 04:08:40 +04:00
type = SGML_CATA_LINKTYPE ;
2001-05-10 18:17:55 +04:00
else if ( xmlStrEqual ( name , ( const xmlChar * ) " NOTATION " ) )
2001-08-20 04:08:40 +04:00
type = SGML_CATA_NOTATION ;
2001-05-10 18:17:55 +04:00
else if ( xmlStrEqual ( name , ( const xmlChar * ) " SGMLDECL " ) )
2001-08-20 04:08:40 +04:00
type = SGML_CATA_SGMLDECL ;
2001-05-10 18:17:55 +04:00
else if ( xmlStrEqual ( name , ( const xmlChar * ) " DOCUMENT " ) )
2001-08-20 04:08:40 +04:00
type = SGML_CATA_DOCUMENT ;
2001-05-10 18:17:55 +04:00
else if ( xmlStrEqual ( name , ( const xmlChar * ) " CATALOG " ) )
2001-08-20 04:08:40 +04:00
type = SGML_CATA_CATALOG ;
2001-05-10 18:17:55 +04:00
else if ( xmlStrEqual ( name , ( const xmlChar * ) " BASE " ) )
2001-08-20 04:08:40 +04:00
type = SGML_CATA_BASE ;
2001-05-10 18:17:55 +04:00
else if ( xmlStrEqual ( name , ( const xmlChar * ) " DELEGATE " ) )
2001-08-20 04:08:40 +04:00
type = SGML_CATA_DELEGATE ;
2001-05-10 18:17:55 +04:00
else if ( xmlStrEqual ( name , ( const xmlChar * ) " OVERRIDE " ) ) {
xmlFree ( name ) ;
cur = xmlParseCatalogName ( cur , & name ) ;
if ( name = = NULL ) {
/* error */
break ;
}
2001-05-21 18:11:26 +04:00
xmlFree ( name ) ;
2001-05-10 18:17:55 +04:00
continue ;
}
xmlFree ( name ) ;
2001-05-21 18:11:26 +04:00
name = NULL ;
2001-05-10 18:17:55 +04:00
switch ( type ) {
2001-08-20 04:08:40 +04:00
case SGML_CATA_ENTITY :
2001-05-10 18:17:55 +04:00
if ( * cur = = ' % ' )
2001-08-20 04:08:40 +04:00
type = SGML_CATA_PENTITY ;
case SGML_CATA_PENTITY :
case SGML_CATA_DOCTYPE :
case SGML_CATA_LINKTYPE :
case SGML_CATA_NOTATION :
2001-05-10 18:17:55 +04:00
cur = xmlParseCatalogName ( cur , & name ) ;
if ( cur = = NULL ) {
/* error */
break ;
}
if ( ! IS_BLANK ( * cur ) ) {
/* error */
break ;
}
SKIP_BLANKS ;
cur = xmlParseCatalogPubid ( cur , & sysid ) ;
if ( cur = = NULL ) {
/* error */
break ;
}
break ;
2001-08-20 04:08:40 +04:00
case SGML_CATA_PUBLIC :
case SGML_CATA_SYSTEM :
case SGML_CATA_DELEGATE :
2001-05-10 18:17:55 +04:00
cur = xmlParseCatalogPubid ( cur , & name ) ;
if ( cur = = NULL ) {
/* error */
break ;
}
if ( ! IS_BLANK ( * cur ) ) {
/* error */
break ;
}
SKIP_BLANKS ;
cur = xmlParseCatalogPubid ( cur , & sysid ) ;
if ( cur = = NULL ) {
/* error */
break ;
}
break ;
2001-08-20 04:08:40 +04:00
case SGML_CATA_BASE :
case SGML_CATA_CATALOG :
case SGML_CATA_DOCUMENT :
case SGML_CATA_SGMLDECL :
2001-05-10 18:17:55 +04:00
cur = xmlParseCatalogPubid ( cur , & sysid ) ;
if ( cur = = NULL ) {
/* error */
break ;
}
break ;
default :
break ;
}
if ( cur = = NULL ) {
if ( name ! = NULL )
xmlFree ( name ) ;
if ( sysid ! = NULL )
xmlFree ( sysid ) ;
break ;
2001-08-20 04:08:40 +04:00
} else if ( type = = SGML_CATA_BASE ) {
2001-05-10 18:17:55 +04:00
if ( base ! = NULL )
xmlFree ( base ) ;
2001-05-21 18:11:26 +04:00
base = xmlStrdup ( sysid ) ;
2001-08-20 04:08:40 +04:00
} else if ( ( type = = SGML_CATA_PUBLIC ) | |
( type = = SGML_CATA_SYSTEM ) ) {
2001-05-10 18:17:55 +04:00
xmlChar * filename ;
filename = xmlBuildURI ( sysid , base ) ;
if ( filename ! = NULL ) {
2001-05-21 18:11:26 +04:00
xmlCatalogEntryPtr entry ;
2001-05-10 18:17:55 +04:00
2001-05-21 18:11:26 +04:00
entry = xmlNewCatalogEntry ( type , name , filename ) ;
res = xmlHashAddEntry ( xmlDefaultCatalog , name , entry ) ;
if ( res < 0 ) {
xmlFreeCatalogEntry ( entry ) ;
}
xmlFree ( filename ) ;
}
2001-08-20 04:08:40 +04:00
} else if ( type = = SGML_CATA_CATALOG ) {
2001-05-21 18:11:26 +04:00
xmlChar * filename ;
filename = xmlBuildURI ( sysid , base ) ;
if ( filename ! = NULL ) {
xmlLoadCatalog ( ( const char * ) filename ) ;
xmlFree ( filename ) ;
2001-05-10 18:17:55 +04:00
}
}
2001-05-21 18:11:26 +04:00
/*
* drop anything else we won ' t handle it
*/
if ( name ! = NULL )
xmlFree ( name ) ;
if ( sysid ! = NULL )
xmlFree ( sysid ) ;
2001-05-10 18:17:55 +04:00
}
}
if ( base ! = NULL )
xmlFree ( base ) ;
if ( cur = = NULL )
return ( - 1 ) ;
return ( 0 ) ;
}
/************************************************************************
* *
* Public interfaces *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-07-18 23:30:27 +04:00
/**
2001-05-10 18:17:55 +04:00
* xmlLoadCatalog :
* @ filename : a file path
*
2001-05-22 19:08:55 +04:00
* Load the catalog and makes its definitions effective for the default
* external entity loader . It will recuse in CATALOG entries .
2001-05-21 18:11:26 +04:00
* TODO : this function is not thread safe , catalog initialization should
* be done once at startup
2001-05-10 18:17:55 +04:00
*
* Returns 0 in case of success - 1 in case of error
*/
int
xmlLoadCatalog ( const char * filename ) {
2001-05-21 18:11:26 +04:00
int fd , len , ret , i ;
2001-05-10 18:17:55 +04:00
struct stat info ;
xmlChar * content ;
if ( filename = = NULL )
return ( - 1 ) ;
2001-05-21 18:11:26 +04:00
2001-05-10 18:17:55 +04:00
if ( xmlDefaultCatalog = = NULL )
xmlDefaultCatalog = xmlHashCreate ( 20 ) ;
if ( xmlDefaultCatalog = = NULL )
return ( - 1 ) ;
if ( stat ( filename , & info ) < 0 )
return ( - 1 ) ;
2001-05-21 18:11:26 +04:00
/*
* Prevent loops
*/
for ( i = 0 ; i < catalNr ; i + + ) {
2001-05-22 19:08:55 +04:00
if ( xmlStrEqual ( ( const xmlChar * ) catalTab [ i ] ,
( const xmlChar * ) filename ) ) {
2001-05-21 18:11:26 +04:00
xmlGenericError ( xmlGenericErrorContext ,
" xmlLoadCatalog: %s seems to induce a loop \n " ,
filename ) ;
return ( - 1 ) ;
}
}
if ( catalNr > = catalMax ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlLoadCatalog: %s catalog list too deep \n " ,
filename ) ;
return ( - 1 ) ;
}
catalTab [ catalNr + + ] = filename ;
if ( ( fd = open ( filename , O_RDONLY ) ) < 0 ) {
catalNr - - ;
2001-05-10 18:17:55 +04:00
return ( - 1 ) ;
2001-05-21 18:11:26 +04:00
}
2001-05-10 18:17:55 +04:00
content = xmlMalloc ( info . st_size + 10 ) ;
if ( content = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" realloc of %d byte failed \n " , info . st_size + 10 ) ;
2001-05-21 18:11:26 +04:00
catalNr - - ;
return ( - 1 ) ;
2001-05-10 18:17:55 +04:00
}
len = read ( fd , content , info . st_size ) ;
if ( len < 0 ) {
xmlFree ( content ) ;
2001-05-21 18:11:26 +04:00
catalNr - - ;
2001-05-10 18:17:55 +04:00
return ( - 1 ) ;
}
content [ len ] = 0 ;
close ( fd ) ;
2001-08-20 04:08:40 +04:00
if ( ( content [ 0 ] = = ' ' ) | | ( content [ 0 ] = = ' - ' ) | |
( ( content [ 0 ] > = ' A ' ) & & ( content [ 0 ] < = ' Z ' ) ) | |
( ( content [ 0 ] > = ' a ' ) & & ( content [ 0 ] < = ' z ' ) ) )
ret = xmlParseCatalog ( content , filename ) ;
else {
xmlCatalogEntryPtr catal , tmp ;
/* TODO: allow to switch the default preference */
catal = xmlParseXMLCatalog ( content , XML_CATA_PREFER_PUBLIC , filename ) ;
if ( catal ! = NULL ) {
if ( xmlDefaultXMLCatalogList = = NULL )
xmlDefaultXMLCatalogList = catal ;
else {
tmp = xmlDefaultXMLCatalogList ;
while ( tmp - > next ! = NULL )
tmp = tmp - > next ;
tmp - > next = catal ;
}
ret = 0 ;
} else
ret = - 1 ;
}
2001-05-10 18:17:55 +04:00
xmlFree ( content ) ;
2001-05-21 18:11:26 +04:00
catalNr - - ;
2001-05-10 18:17:55 +04:00
return ( ret ) ;
}
2001-07-18 23:30:27 +04:00
/**
2001-05-22 19:08:55 +04:00
* xmlLoadCatalogs :
* @ paths : a list of file path separated by ' : ' or spaces
*
* Load the catalogs and makes their definitions effective for the default
* external entity loader .
* TODO : this function is not thread safe , catalog initialization should
* be done once at startup
*/
void
xmlLoadCatalogs ( const char * pathss ) {
const char * cur ;
const char * paths ;
xmlChar * path ;
cur = pathss ;
while ( ( cur ! = NULL ) & & ( * cur ! = 0 ) ) {
while ( IS_BLANK ( * cur ) ) cur + + ;
if ( * cur ! = 0 ) {
paths = cur ;
while ( ( * cur ! = 0 ) & & ( * cur ! = ' : ' ) & & ( ! IS_BLANK ( * cur ) ) )
cur + + ;
path = xmlStrndup ( ( const xmlChar * ) paths , cur - paths ) ;
if ( path ! = NULL ) {
xmlLoadCatalog ( ( const char * ) path ) ;
xmlFree ( path ) ;
}
}
while ( * cur = = ' : ' )
cur + + ;
}
}
2001-05-10 18:17:55 +04:00
/**
* xmlCatalogCleanup :
*
* Free up all the memory associated with catalogs
*/
void
xmlCatalogCleanup ( void ) {
if ( xmlDefaultCatalog ! = NULL )
xmlHashFree ( xmlDefaultCatalog ,
( xmlHashDeallocator ) xmlFreeCatalogEntry ) ;
xmlDefaultCatalog = NULL ;
}
/**
2001-05-10 19:34:11 +04:00
* xmlCatalogGetSystem :
* @ sysId : the system ID string
2001-05-10 18:17:55 +04:00
*
2001-05-10 19:34:11 +04:00
* Try to lookup the resource associated to a system ID
*
* Returns the resource name if found or NULL otherwise .
2001-05-10 18:17:55 +04:00
*/
2001-05-10 19:34:11 +04:00
const xmlChar *
xmlCatalogGetSystem ( const xmlChar * sysID ) {
xmlCatalogEntryPtr entry ;
if ( ( sysID = = NULL ) | | ( xmlDefaultCatalog = = NULL ) )
return ( NULL ) ;
entry = ( xmlCatalogEntryPtr ) xmlHashLookup ( xmlDefaultCatalog , sysID ) ;
if ( entry = = NULL )
return ( NULL ) ;
2001-08-20 04:08:40 +04:00
if ( entry - > type = = SGML_CATA_SYSTEM )
2001-05-10 19:34:11 +04:00
return ( entry - > value ) ;
return ( NULL ) ;
2001-05-10 18:17:55 +04:00
}
2001-05-10 19:34:11 +04:00
/**
2001-08-20 04:08:40 +04:00
* xmlCatalogGetXMLPublic :
* @ catal : an XML catalog
2001-05-10 19:34:11 +04:00
* @ pubId : the public ID string
*
* Try to lookup the system ID associated to a public ID
*
* Returns the system ID if found or NULL otherwise .
*/
const xmlChar *
2001-08-20 04:08:40 +04:00
xmlCatalogGetXMLPublic ( xmlCatalogEntryPtr catal , const xmlChar * pubID ) {
const xmlChar * ret ;
while ( catal ! = NULL ) {
switch ( catal - > type ) {
case XML_CATA_CATALOG :
if ( catal - > children = = NULL ) {
TODO /* fetch and fill */
}
ret = xmlCatalogGetXMLPublic ( catal - > children , pubID ) ;
if ( ret ! = NULL )
return ( ret ) ;
break ;
case XML_CATA_NEXT_CATALOG :
if ( catal - > children = = NULL ) {
TODO /* fetch and fill */
}
case XML_CATA_PUBLIC :
if ( xmlStrEqual ( pubID , catal - > name ) )
return ( catal - > value ) ;
break ;
case XML_CATA_SYSTEM :
case XML_CATA_REWRITE_SYSTEM :
case XML_CATA_DELEGATE_PUBLIC :
case XML_CATA_DELEGATE_SYSTEM :
case XML_CATA_URI :
case XML_CATA_REWRITE_URI :
case XML_CATA_DELEGATE_URI :
TODO ;
break ;
case XML_CATA_NONE :
case SGML_CATA_SYSTEM :
case SGML_CATA_PUBLIC :
case SGML_CATA_ENTITY :
case SGML_CATA_PENTITY :
case SGML_CATA_DOCTYPE :
case SGML_CATA_LINKTYPE :
case SGML_CATA_NOTATION :
case SGML_CATA_DELEGATE :
case SGML_CATA_BASE :
case SGML_CATA_CATALOG :
case SGML_CATA_DOCUMENT :
case SGML_CATA_SGMLDECL :
/* Ignored entries */
break ;
}
catal = catal - > next ;
}
return ( NULL ) ;
}
/**
* xmlCatalogGetSGMLPublic :
* @ catal : an SGML catalog hash
* @ pubId : the public ID string
*
* Try to lookup the system ID associated to a public ID
*
* Returns the system ID if found or NULL otherwise .
*/
static const xmlChar *
xmlCatalogGetSGMLPublic ( xmlHashTablePtr catal , const xmlChar * pubID ) {
2001-05-10 19:34:11 +04:00
xmlCatalogEntryPtr entry ;
2001-08-20 04:08:40 +04:00
if ( catal = = NULL )
2001-05-10 19:34:11 +04:00
return ( NULL ) ;
2001-08-20 04:08:40 +04:00
entry = ( xmlCatalogEntryPtr ) xmlHashLookup ( catal , pubID ) ;
2001-05-10 19:34:11 +04:00
if ( entry = = NULL )
return ( NULL ) ;
2001-08-20 04:08:40 +04:00
if ( entry - > type = = SGML_CATA_PUBLIC )
2001-05-10 19:34:11 +04:00
return ( entry - > value ) ;
return ( NULL ) ;
}
2001-08-20 04:08:40 +04:00
/**
* xmlCatalogGetPublic :
* @ pubId : the public ID string
*
* Try to lookup the system ID associated to a public ID
*
* Returns the system ID if found or NULL otherwise .
*/
const xmlChar *
xmlCatalogGetPublic ( const xmlChar * pubID ) {
xmlCatalogEntryPtr catal ;
const xmlChar * ret ;
if ( pubID = = NULL )
return ( NULL ) ;
/*
* Check first the XML catalogs
*/
catal = xmlDefaultXMLCatalogList ;
if ( catal ! = NULL ) {
ret = xmlCatalogGetXMLPublic ( catal , pubID ) ;
if ( ret ! = NULL )
return ( ret ) ;
}
if ( xmlDefaultCatalog ! = NULL )
return ( xmlCatalogGetSGMLPublic ( xmlDefaultCatalog , pubID ) ) ;
return ( NULL ) ;
}
2001-05-10 18:17:55 +04:00
/**
* xmlCatalogDump :
* @ out : the file .
*
* Free up all the memory associated with catalogs
*/
void
xmlCatalogDump ( FILE * out ) {
if ( out = = NULL )
return ;
2001-08-20 04:08:40 +04:00
if ( xmlDefaultXMLCatalogList ! = NULL ) {
xmlDumpXMLCatalog ( out , xmlDefaultXMLCatalogList ) ;
} else if ( xmlDefaultCatalog ! = NULL ) {
2001-05-10 18:17:55 +04:00
xmlHashScan ( xmlDefaultCatalog ,
( xmlHashScanner ) xmlCatalogDumpEntry , out ) ;
2001-08-20 04:08:40 +04:00
}
}
/**
* xmlCatalogAdd :
* @ type : the type of record to add to the catalog
* @ orig : the system , public or prefix to match
* @ replace : the replacement value for the match
*
* Add an entry in the catalog , it may overwrite existing but
* different entries .
*
* Returns 0 if successful , - 1 otherwise
*/
int
xmlCatalogAdd ( const xmlChar * type , const xmlChar * orig , const xmlChar * replace ) {
int res = - 1 ;
if ( xmlDefaultXMLCatalogList ! = NULL ) {
res = xmlAddXMLCatalog ( xmlDefaultXMLCatalogList , type , orig , replace ) ;
} else if ( xmlDefaultCatalog ! = NULL ) {
xmlCatalogEntryType typ ;
typ = xmlGetCatalogEntryType ( type ) ;
if ( type ! = XML_CATA_NONE ) {
xmlCatalogEntryPtr entry ;
entry = xmlNewCatalogEntry ( typ , orig , replace ) ;
res = xmlHashAddEntry ( xmlDefaultCatalog , orig , entry ) ;
}
}
return ( res ) ;
}
/**
* xmlCatalogRemove :
* @ value : the value to remove
*
* Remove an entry from the catalog
*
* Returns 0 if successful , - 1 otherwise
*/
int
xmlCatalogRemove ( const xmlChar * value ) {
}
/**
* xmlCatalogSetDebug :
* @ level : the debug level of catalogs required
*
* Used to set the debug level for catalog operation , 0 disable
* debugging , 1 enable it
*
* Returns the previous value of the catalog debugging level
*/
int
xmlCatalogSetDebug ( int level ) {
int ret = xmlDebugCatalogs ;
if ( level < = 0 )
xmlDebugCatalogs = 0 ;
else
xmlDebugCatalogs = level ;
return ( ret ) ;
2001-05-10 18:17:55 +04:00
}
# endif /* LIBXML_CATALOG_ENABLED */