diff --git a/ChangeLog b/ChangeLog index 22e5a344..226c6f0b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +Tue Jul 24 15:06:58 CEST 2001 Daniel Veillard + + * configure.in: get rid of the readline and libhistory + dependancies by default, release 2.4.1 with IA64 fix + * nanohttp.c tree.c xmlIO.c include/libxml/nanohttp.h + include/libxml/tree.h include/libxml/xmlIO.h: incorporated + John Kroll fixes to allow saving to HTTP via PUT (or + POST of needed). + * doc/html/*.html: regenerated the docs + Sun Jul 22 05:56:16 CEST 2001 Thomas Broyer * hash.c include/libxml/hash.h: added xmlHashScannerFull, diff --git a/configure.in b/configure.in index 068061cf..a1402e1d 100644 --- a/configure.in +++ b/configure.in @@ -6,7 +6,7 @@ AC_CANONICAL_HOST LIBXML_MAJOR_VERSION=2 LIBXML_MINOR_VERSION=4 -LIBXML_MICRO_VERSION=0 +LIBXML_MICRO_VERSION=1 LIBXML_VERSION=$LIBXML_MAJOR_VERSION.$LIBXML_MINOR_VERSION.$LIBXML_MICRO_VERSION LIBXML_VERSION_INFO=`expr $LIBXML_MAJOR_VERSION + $LIBXML_MINOR_VERSION`:$LIBXML_MICRO_VERSION:$LIBXML_MINOR_VERSION @@ -206,30 +206,6 @@ AC_ARG_WITH(readline, fi ]) -dnl check for terminal library. this is a very cool solution -dnl from octave's configure.in -unset tcap -for termlib in ncurses curses termcap terminfo termlib; do - AC_CHECK_LIB(${termlib}, tputs, [tcap="-l$termlib"]) - test -n "$tcap" && break -done - -AC_CHECK_HEADER(readline/history.h, - AC_CHECK_LIB(history, append_history,[ - RDL_LIBS="-lhistory" - AC_DEFINE(HAVE_LIBHISTORY)])) -AC_CHECK_HEADER(readline/readline.h, - AC_CHECK_LIB(readline, readline,[ - RDL_LIBS="-lreadline $RDL_LIBS $tcap" - AC_DEFINE(HAVE_LIBREADLINE)], , $tcap)) -if test -n "$RDL_DIR" -a -n "$RDL_LIBS"; then - CPPFLAGS="$CPPFLAGS -I${RDL_DIR}/include" - RDL_LIBS="-L${RDL_DIR}/lib $RDL_LIBS" -else - CPPFLAGS=${_cppflags} -fi -LDFLAGS=${_ldflags} - dnl dnl specific tests to setup DV's devel environment with debug etc ... dnl (-Wunreachable-code) @@ -265,6 +241,36 @@ dnl dnl Aloow to disable various pieces dnl +AC_ARG_WITH(history, [ --with-history Add history support to xmllint shell(off)]) +if test "$with_ftp" = "yes" ; then + echo Enabling xmllint shell history + dnl check for terminal library. this is a very cool solution + dnl from octave's configure.in + unset tcap + for termlib in ncurses curses termcap terminfo termlib; do + AC_CHECK_LIB(${termlib}, tputs, [tcap="-l$termlib"]) + test -n "$tcap" && break + done + + AC_CHECK_HEADER(readline/history.h, + AC_CHECK_LIB(history, append_history,[ + RDL_LIBS="-lhistory" + AC_DEFINE(HAVE_LIBHISTORY)])) + AC_CHECK_HEADER(readline/readline.h, + AC_CHECK_LIB(readline, readline,[ + RDL_LIBS="-lreadline $RDL_LIBS $tcap" + AC_DEFINE(HAVE_LIBREADLINE)], , $tcap)) + if test -n "$RDL_DIR" -a -n "$RDL_LIBS"; then + CPPFLAGS="$CPPFLAGS -I${RDL_DIR}/include" + RDL_LIBS="-L${RDL_DIR}/lib $RDL_LIBS" + else + CPPFLAGS=${_cppflags} + fi + LDFLAGS=${_ldflags} +fi + +AC_SUBST(WITH_FTP) +AC_SUBST(FTP_OBJ) AC_ARG_WITH(ftp, [ --with-ftp Add the FTP support (on)]) if test "$with_ftp" = "no" ; then echo Disabling FTP support diff --git a/doc/html/index.sgml b/doc/html/index.sgml index de2aad3d..dea1ad81 100644 --- a/doc/html/index.sgml +++ b/doc/html/index.sgml @@ -312,6 +312,7 @@ + @@ -374,13 +375,11 @@ - - @@ -507,6 +506,7 @@ + @@ -534,13 +534,35 @@ - + + + + + + + + + + + + + + + + + + + + + + + @@ -551,11 +573,24 @@ - + + + + + + + + + + + + + + @@ -601,6 +636,7 @@ + @@ -753,6 +789,7 @@ + @@ -943,7 +980,6 @@ - diff --git a/doc/html/libxml-catalog.html b/doc/html/libxml-catalog.html index f9bb3fa8..6d97a4bd 100644 --- a/doc/html/libxml-catalog.html +++ b/doc/html/libxml-catalog.html @@ -122,7 +122,7 @@ NAME="LIBXML-CATALOG" >

Name

Synopsis

xmlLoadCatalog (const char *URL); +> (const char *filename); void xmlLoadCatalogs

Description

Details


int         xmlLoadCatalog                  (const char *URL);
int xmlLoadCatalog (const char *filename);

Load the catalog and makes its definitions effective for the default +external entity loader. It will recuse in CATALOG entries. +TODO: this function is not thread safe, catalog initialization should +be done once at startup

URLfilename :  a file path 0 in case of success -1 in case of error

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

  a list of file path separated by ':' or spaces




Name

Synopsis

xmlDtdPtr doc); +> dtd); void xmlDebugDumpEntitiesxmlDocPtr doc); -void xmlLsOneNode (FILE *output, - xmlNodePtr node); char* (*xmlShellReadlineFunc

Description

Details

Dumps informations about the string, shorten it if necessary

  the FILE * for the output  the string

Dumps debug information for the attribute

  the FILE * for the output  the attribute  the indentation level.

Dumps debug information for the attribute list

  the FILE * for the output  the attribute list  the indentation level.

Dumps debug information for the element node, it is not recursive

  the FILE * for the output  the node  the indentation level.

Dumps debug information for the element node, it is recursive

  the FILE * for the output  the node  the indentation level.

Dumps debug information for the list of element node, it is recursive

  the FILE * for the output  the node list  the indentation level.

Dumps debug information cncerning the document, not recursive

  the FILE * for the output  the document

Dumps debug information for the document, it's recursive

  the FILE * for the output  the document

xmlDtdPtr doc); dtd);

Dumps debug information for the DTD

  the FILE * for the outputdocdtd :  the DTD

Dumps debug information for all the entities in use by the document

  the FILE * for the output  the document

xmlLsOneNode ()

void        xmlLsOneNode                    (FILE *output,
-                                             xmlNodePtr node);

output : 
node : 


This is a generic signature for the XML shell input function

a string prompt a string which will be freed by the Shell 


This is a generic signature for the XML shell functions

a shell context  a string argument  a first node  a second node an int, negative returns indicating errors 

Name

Synopsis

Description

Details



















Name

Synopsis

Description

Details


Take a block of chars in the original encoding and try to convert -it to an UTF-8 block of chars out.

a pointer ot an array of bytes to store the UTF-8 result  the lenght of out  a pointer ot an array of chars in the original encoding  the lenght of in the number of byte written, or -1 by lack of space, or -2 -if the transcoding failed. -The value of inlen after return is the number of octets consumed -as the return value is positive, else unpredictiable. -The value of outlen after return is the number of ocetes consumed. 

Take a block of UTF-8 chars in and try to convert it to an other -encoding. -Note: a first call designed to produce heading info is called with -in = NULL. If stateful this should also initialize the encoder state

a pointer ot an array of bytes to store the result  the lenght of out  a pointer ot an array of UTF-8 chars  the lenght of in the number of byte written, or -1 by lack of space, or -2 -if the transcoding failed. -The value of inlen after return is the number of octets consumed -as the return value is positive, else unpredictiable. -The value of outlen after return is the number of ocetes consumed. 






an xmlCharEncoding value.Returns :the handler or NULL if not found


xmlFindCharEncodingHandler ()

xmlCharEncodingHandlerPtr xmlFindCharEncodingHandler
+                                            (const char *name);

Search in the registrered set the handler able to read/write that encoding.


xmlFindCharEncodingHandler ()

name : a string describing the char encoding.
xmlCharEncodingHandlerPtr xmlFindCharEncodingHandler
-                                            (const char *name);

name : 
Returns : 




















start: relative pos of first char -len: total number to copy

Note: positions are given in units of UTF-8 chars

  relative pos of first char  total number to copy

Name

Synopsis

Description

Details




















Name

Synopsis

htmlEntityDescPtr; -htmlElemDescPtr htmlTagLookup (const (const xmlChar *tag); -htmlEntityDescPtr htmlEntityLookup (const (const xmlChar *name); -htmlEntityDescPtr htmlEntityValueLookup (unsigned int value); +> + (unsigned int value); int htmlIsAutoClosed

Description

Details














const htmlElemDescPtr htmlTagLookup               (const  htmlTagLookup         (const xmlChar *tag);


const htmlEntityDescPtr htmlEntityLookup          (const  htmlEntityLookup    (const xmlChar *name);


const htmlEntityDescPtr htmlEntityValueLookup     (unsigned int value);
htmlEntityValueLookup + (unsigned int value);

















Name

Synopsis

Description

Details






Creates a new HTML document


Creates a new HTML document without a DTD node if URI and ExternalID +are NULL











Name

Synopsis

Description

Details

A callback for the xmlNanoFTPList command -Note that only one of year and day:minute are specified

user provided data for the callback  the file name (including "->" when links are shown)  the attribute string  the owner string  the group string  the file size  the link count  the year  the month  the day  the hour  the minute 

A callback for the xmlNanoFTPGet command

the user provided context  the data received  its size in bytes 





















Name

Synopsis

xmlNanoHTTPMethodRedirxmlNanoHTTPOpen

Description

Details



The proxy URL used to initialize the proxy context 

The URL to load  the filename where the content should be saved  if available the Content-Type information will be -returned at that location -1 in case of failure, 0 incase of success. The contentType, -if provided must be freed by the caller 

The URL to load  the HTTP method to use  the input string if any  the Content-Type information IN and OUT  the extra headers ilen : 

The URL to load  the HTTP method to use  the input string if any  the Content-Type information IN and OUT  the redirected URL OUT  the extra headers ilen : 

The URL to load  if available the Content-Type information will be -returned at that location 

The URL to load  if available the Content-Type information will be -returned at that location  if availble the redirected URL will be returned 

the HTTP context the HTTP return code for the request. 

the HTTP context the stashed value of the WWW-Authenticate or Proxy-Authenticate -header. 

the HTTP context  a buffer  the buffer length the number of byte read. 0 is an indication of an end of connection. --1 indicates a parameter error. 

the HTTP context  the filename where the content should be saved -1 in case of failure, 0 incase of success. 

the HTTP context 

an xmlParserInput is an input flow for the XML processor. -Each entity parsed is associated an xmlParserInput (except the -few predefined ones). This is the case both for internal entities -- in which case the flow is already completely in memory - or -external entities - in which case we use the buf structure for -progressive reading and I18N conversions to the internal UTF-8 format.












































External entity loaders types

The System ID of the resource requested  The Public ID of the resource requested 






















































Copy at most *len feature names into the result array

  the length of the features name array (input/output)  an array of string to be filled with the features name. -1 in case or error, or the total number of features, +len is updated with the number of strings copied, +strings must not be deallocated

Read the current value of one feature of this parser instance

  an XML/HTML parser context  the feature name  location to store the result -1 in case or error, 0 otherwise

Change the current value of one feature of this parser instance

  an XML/HTML parser context  the feature name  pointer to the location of the new value -1 in case or error, 0 otherwise










Changes the defaultexternal entity resolver function for the application

  the new entity resolver function

Get the default external entity resolver function for the application

 the xmlExternalEntityLoader function pointer

Load an external entity, note that the use of this function for +unparsed entities may generate problems +TODO: a more generic External entitiy API must be designed

  the URL for the entity to load  the System ID for the entity to load the xmlParserInputPtr or NULL

Name

Synopsis

Description

Details



Macro to check the following production in the XML spec

[2] Char ::= x9 | xA | xD | [x20-xD7FF] | [xE000-xFFFD] -| [x10000-x10FFFF] -any Unicode character, excluding the surrogate blocks, FFFE, and FFFF.

an UNICODE value (int) 

Macro to check the following production in the XML spec

[3] S ::= (x20 | x9 | xD | xA)+

an UNICODE value (int) 

Macro to check the following production in the XML spec

[85] BaseChar ::= ... long list see REC ...

an UNICODE value (int) 

Macro to check the following production in the XML spec

[88] Digit ::= ... long list see REC ...

an UNICODE value (int) 

Macro to check the following production in the XML spec

[87] CombiningChar ::= ... long list see REC ...

an UNICODE value (int) 

Macro to check the following production in the XML spec

[89] Extender ::= x00B7 | x02D0 | x02D1 | x0387 | x0640 | -x0E46 | x0EC6 | x3005 | [x3031-x3035] | -[x309D-x309E] | [x30FC-x30FE]

an UNICODE value (int) 

Macro to check the following production in the XML spec

[86] Ideographic ::= [x4E00-x9FA5] | x3007 | [x3021-x3029]

an UNICODE value (int) 

Macro to check the following production in the XML spec

[84] Letter ::= BaseChar | Ideographic

an UNICODE value (int) 

Macro to check the following production in the XML spec

[13] PubidChar ::= x20 | xD | xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%]

an UNICODE value (int) 

Skips the end of line chars

and UTF8 string pointer 

Skips to the next '>' char

and UTF8 string pointer 

Skips to the next '<' char

and UTF8 string pointer 





















































VMS version of xmlParseElementChildrenContentDecl()

  an XML parser context the tree of xmlElementContentPtr describing the element +hierarchy.

the tree of xmlElementContentPtr describing the element +>the tree of xmlElementContentPtr describing the element hierarchy.






























Pushes a new element node on top of the node stack

  an XML parser context

Pops the top element node from the node stack

  an XML parser context the node just removed

Pushes a new parser input on top of the input stack

  an XML parser context

Pops the top parser input from the input stack

  an XML parser context the input just removed

Pops the top element name from the name stack

  an XML parser context the name just removed

Pushes a new element name on top of the name stack

  an XML parser context





Checks that the value conforms to the LanguageID production:

NOTE: this is somewhat deprecated, those productions were removed from +the XML Second edition.

[33] LanguageID ::= Langcode ('-' Subcode)* +[34] Langcode ::= ISO639Code | IanaCode | UserCode +[35] ISO639Code ::= ([a-z] | [A-Z]) ([a-z] | [A-Z]) +[36] IanaCode ::= ('i' | 'I') '-' ([a-z] | [A-Z])+ +[37] UserCode ::= ('x' | 'X') '-' ([a-z] | [A-Z])+ +[38] Subcode ::= ([a-z] | [A-Z])+

  pointer to the string value 1 if correct 0 otherwise







Name

Synopsis

xmlChar *name, +> *fullname, int type, int def, const

Description

Details















xmlChar *name, +> *fullname, int type, int def, const

namefullname :  the attribute name






















Name

Synopsis

xmlSaveFormatFileEnc (const char *filename, + xmlDocPtr cur, + const char *encoding, + int format); +int xmlSaveFileEnc (const char *filename, @@ -1811,7 +1821,7 @@ HREF="libxml-tree.html#XMLSETCOMPRESSMODE" >

Description

Details



xmlChar

typedef unsigned char xmlChar;

This is a basic byte in an UTF-8 encoded string. -It's unsigned allowing to pinpoint case where char * are assigned -to xmlChar * (possibly making serialization back impossible).




xmlNotationPtr

typedef xmlNotation *xmlNotationPtr;





xmlEnumerationPtr

typedef xmlEnumeration *xmlEnumerationPtr;



xmlAttributePtr

typedef xmlAttribute *xmlAttributePtr;





xmlElementContentPtr

typedef xmlElementContent *xmlElementContentPtr;




xmlElementPtr

typedef xmlElement *xmlElementPtr;


#define XML_LOCAL_NAMESPACE XML_NAMESPACE_DECL
#define XML_LOCAL_NAMESPACE

xmlNsType

typedef xmlElementType xmlNsType;



xmlNsPtr

typedef xmlNs *xmlNsPtr;



xmlDtdPtr

typedef xmlDtd *xmlDtdPtr;



xmlAttrPtr

typedef xmlAttr *xmlAttrPtr;



xmlIDPtr

typedef xmlID *xmlIDPtr;



xmlRefPtr

typedef xmlRef *xmlRefPtr;




xmlBufferPtr

typedef xmlBuffer *xmlBufferPtr;



xmlNodePtr

typedef xmlNode *xmlNodePtr;



xmlDocPtr

typedef xmlDoc *xmlDocPtr;




allocation method to use 

the current allocation scheme 

the new structure. 

initial size of buffer the new structure. 

the buffer to resize  the desired size 0 in case of problems, 1 otherwise 

the buffer to free 

the file output  the buffer to dump the number of xmlChar written 

the buffer to dump  the xmlChar string  the number of xmlChar to add 

the buffer  the xmlChar string  the number of xmlChar to add 

the buffer to dump  the xmlChar string 

the buffer to dump  the C char string 

the buffer to dump  the number of xmlChar to remove the number of xmlChar removed, or -1 in case of failure. 

the buffer  the minimum free size to allocate the new available space or -1 in case of error 

the buffer 

the buffer the internal content 


the buffer to free  allocation scheme to use 

the buffer  the length of data in the internal content 

the document pointer  the DTD name  the external (PUBLIC) ID  the system ID a pointer to the new DTD structure 

the document pointer  the DTD name  the external ID  the system ID a pointer to the new DTD structure 

the document pointer a pointer to the DTD structure or NULL if not found 

the DTD structure to free up 

the document carrying the namespace  the URI associated  the prefix for the namespace NULL this functionnality had been removed 

the element carrying the namespace  the URI associated  the prefix for the namespace returns a new namespace pointer or NULL 

the namespace pointer 

the first namespace pointer 

xmlChar string giving the version of XML "1.0" a new document 

pointer to the document -@:  

the document  the name of the attribute  the value of the attribute a pointer to the attribute 

the holding node  the name of the attribute  the value of the attribute a pointer to the attribute 

the holding node  the namespace  the name of the attribute  the value of the attribute a pointer to the attribute 

the first property in the list 

an attribute 

the element where the attribute will be grafted  the attribute  a new xmlAttrPtr, or NULL in case of error. 

the element where the attributes will be grafted  the first attribute  a new xmlAttrPtr, or NULL in case of error. 

the dtd  a new xmlDtdPtr, or NULL in case of error. 

the document  if 1 do a recursive copy.  a new xmlDocPtr, or NULL in case of error. 

the document  namespace if any  the node name  the XML text content if any a pointer to the new node object. 

the document  namespace if any  the node name  the text content if any a pointer to the new node object. 

namespace if any  the node name a pointer to the new node object. 

the parent node  a namespace if any  the name of the child  the XML content of the child if any. a pointer to the new node object. 

the parent node  a namespace if any  the name of the child  the text content of the child if any. a pointer to the new node object. 

the document  the text content a pointer to the new node object. 

the text content a pointer to the new node object. 

the processing instruction name  the PI content a pointer to the new node object. 

the document  the text content  the text len. a pointer to the new node object. 

the text content  the text len. a pointer to the new node object. 

the document  the comment content a pointer to the new node object. 

the comment content a pointer to the new node object. 

the document  the CData block content content  the length of the block a pointer to the new node object. 

the document  the char ref string, starting with # or "&# ... ;" a pointer to the new node object. 

the document  the reference name, or the reference string with & and ; a pointer to the new node object. 

the node  if 1 do a recursive copy.  a new xmlNodePtr, or NULL in case of error. 

the node  if 1 do a recursive copy.  a new xmlNodePtr, or NULL in case of error. 

the first node in the list.  a new xmlNodePtr, or NULL in case of error. 

the document owning the fragment a pointer to the new node object. 

the document the xmlNodePtr for the root or NULL 

the parent node the last child or NULL if none. 

the node 1 yes, 0 no 

the node 1 yes, 0 no 

the document  the new document root element the old root element if any was found 

the node being changed  the new tag name 

the parent node  the child node the child or NULL in case of error. 

the parent node  the first node in the list the last child or NULL in case of error. 

the old node  the node the old node 

the child node  the new node the new element or NULL in case of error. 

the child node  the new node the new element or NULL in case of error. 

the child node  the new node the new element or NULL in case of error. 

the node 

the first text node  the second text node being merged the first text node augmented 

the node  the content  content lenght 

the first node in the list 

the node 

the top element  the document 

the document 

the document  the current node  the namespace prefix the namespace pointer or NULL. 

the document  the current node  the namespace value the namespace pointer or NULL. 

the document  the current node an NULL terminated array of all the xmlNsPtr found -that need to be freed by the caller or NULL if no -namespace if defined 

a node in the document  a namespace pointer 

the namespace  a new xmlNsPtr, or NULL in case of error. 

the first namespace  a new xmlNsPtr, or NULL in case of error. 

the node  the attribute name  the attribute value the attribute pointer. 

the node  the attribute name the attribute value or NULL if not found. -It's up to the caller to free the memory. 

the node  the attribute name the attribute or the attribute declaration or NULL if -neither was found. 

the node  the attribute name  the URI of the namespace the attribute or the attribute declaration or NULL -if neither was found. 

the node  the namespace definition  the attribute name  the attribute value the attribute pointer. 

the node  the attribute name  the URI of the namespace the attribute value or NULL if not found. -It's up to the caller to free the memory. 

the document  the value of the attribute a pointer to the first child 

the document  the value of the text  the length of the string value a pointer to the first child 

the document  a Node list  should we replace entity contents or show their external form a pointer to the string copy, the calller must free it. 

the document  a Node list  should we replace entity contents or show their external form a pointer to the string copy, the calller must free it. 

the node being modified  the new value of the content 

the node being modified  the new value of the content  the size of content 

the node being modified  extra content 

the node being modified  extra content  the size of content 

the node being read a new xmlChar * or NULL if no content is available. -It's up to the caller to free the memory. 

the node being checked a pointer to the lang value, or NULL if not found -It's up to the caller to free the memory. 

the node being changed  the langage description 

the node being checked -1 if xml:space is not inheried, 0 if "default", 1 if "preserve" 

the node being changed 

the document the node pertains to  the node being checked a pointer to the base URL, or NULL if not found -It's up to the caller to free the memory. 

the node being changed  the new base URI 

0 if success and -1 in case of error. 


the node  the attribute name 0 if successful, -1 if not found 

the node  the namespace definition  the attribute name 0 if successful, -1 if not found 

For VMS only. +routine which manages and grows an output buffer. This one adds +xmlChars at the end of the buffer.


the XML buffer  the string to add 

the XML buffer output  the string to add 

the XML buffer output  the string to add 

the document  a node defining the subtree to reconciliate the number of namespace declarations created or -1 in case of error. 

the document  OUT: the memory pointer  OUT: the memory lenght  should formatting spaces been added 

the document  OUT: the memory pointer  OUT: the memory lenght 

Document to generate XML text from  Memory pointer for allocated XML text  Length of the generated XML text  Character encoding to use when generating XML text 

Dump the current DOM tree into memory using the character encoding specified +by the caller. Note it is up to the caller of this function to free the +allocated memory.


the FILE*  the document  the number of byte written or -1 in case of failure. 

the FILE * for the output  the document  the current node 

the filename (or URL)  the document  the number of byte written or -1 in case of failure. 

the filename (or URL)  the document  should formatting spaces been added  the number of byte written or -1 in case of failure. 

the XML buffer output  the document  the current node  the imbrication level for indenting  is formatting allowed 

xmlSaveFormatFileEnc ()

int         xmlSaveFormatFileEnc            (const char *filename,
+                                             xmlDocPtr cur,
+                                             const char *encoding,
+                                             int format);

filename : 
cur : 
encoding : 
format : 
Returns : 


the filename (or URL)  the document  the name of an encoding (or NULL)  the number of byte written or -1 in case of failure. 

the document 0 (uncompressed) to 9 (max compression) 

the document  the compression ratio 

0 (uncompressed) to 9 (max compression) 

the compression ratio 

Name

Synopsis

xmlParseURI (const char *URI); +> (const char *str); int xmlParseURIReference

Description

Details


xmlURIPtr

typedef xmlURI *xmlURIPtr;


 the new structure or NULL in case of error

  the URI instance found in the document  the base value a new URI string (to be freed by the caller) or NULL in case +of error.

xmlURIPtr xmlParseURI (const char *URI); xmlParseURI (const char *str);

URIstr :  the URI string to analyze a newly build xmlURIPtr or NULL in case of error

  pointer to an URI structure  the string to analyze 0 or the error code

  pointer to an xmlURI a new string (to be deallocated by caller)

  a FILE* for the output  pointer to an xmlURI

  string to escape  exception list string of chars not to escape a new escaped string or NULL in case of error.

  the string to unescape  the lenght in bytes to unescape (or <= 0 to indicate full string)  optionnal destination buffer an copy of the string, but unescaped

  pointer to the path string 0 or an error code

  the string of the URI to escape an copy of the string, but escaped + +25 May 2001 +Uses xmlParseURI and xmlURIEscapeStr to try to escape correctly +according to RFC2396. +- Carl Douglas

  pointer to an xmlURI

Name

Synopsis

xmlAttrPtr attr); -xmlIDTablePtr xmlCopyIDTable (xmlIDTablePtr table); void xmlFreeIDTablexmlAttrPtr attr); -xmlRefTablePtr xmlCopyRefTable (xmlRefTablePtr table); void xmlFreeRefTable

Description

Details




































xmlCopyIDTable ()

xmlIDTablePtr xmlCopyIDTable                (xmlIDTablePtr table);

table : 
Returns : 







xmlCopyRefTable ()

xmlRefTablePtr xmlCopyRefTable              (xmlRefTablePtr table);

table : 
Returns : 

























Name

Synopsis

Description

Details

Name

Synopsis

Description

Details









Name

Synopsis

) (void *context, char *buffer, int len); -void (*xmlInputCloseCallback) (void *context); @@ -185,7 +185,7 @@ HREF="libxml-xmlio.html#XMLOUTPUTWRITECALLBACK" >) (void *context, const char *buffer, int len); -void (*xmlOutputCloseCallback) (void *context); @@ -475,6 +475,11 @@ HREF="libxml-xmlio.html#XMLOUTPUTWRITECALLBACK" HREF="libxml-xmlio.html#XMLOUTPUTCLOSECALLBACK" >xmlOutputCloseCallback closeFunc); +void* xmlIOHTTPOpenW (const char *post_uri, + int compression); int xmlSaveFileTo

Description

Details




void        (*xmlInputCloseCallback)        (void *context);
int (*xmlInputCloseCallback) (void *context);

 Returns



xmlParserInputBufferPtr

typedef xmlParserInputBuffer *xmlParserInputBufferPtr;





void        (*xmlOutputCloseCallback)       (void *context);
int (*xmlOutputCloseCallback) (void *context);

 Returns



xmlOutputBufferPtr

typedef xmlOutputBuffer *xmlOutputBufferPtr;



the charset encoding if known the new parser input or NULL 

VMS version of xmlParserInputBufferCreateFilename()


a C string containing the URI or filename  the charset encoding if known the new parser input or NULL 

a FILE*   the charset encoding if known the new parser input or NULL 

a file descriptor number  the charset encoding if known the new parser input or NULL 

the memory input  the length of the memory block  the charset encoding if known the new parser input or NULL 

an I/O read function  an I/O close function  an I/O handler  the charset encoding if known the new parser input or NULL 

a buffered parser input  indicative value of the amount of chars to read the number of chars read and stored in the buffer, or -1 -in case of error. 

a buffered parser input  indicative value of the amount of chars to read the number of chars read and stored in the buffer, or -1 -in case of error. 

a buffered parser input  the size in bytes of the array.  an char array the number of chars read and stored in the buffer, or -1 -in case of error. 

a buffered parser input 

lookup the directory for that file


the xmlInputMatchCallback  the xmlInputOpenCallback  the xmlInputReadCallback  the xmlInputCloseCallback the registered handler number or -1 in case of error 


the encoding converter or NULL the new parser output or NULL 

a C string containing the URI or filename  the encoding converter or NULL  the compression ration (0 none, 9 max). the new output or NULL 

a FILE*   the encoding converter or NULL the new parser output or NULL 

a file descriptor number  the encoding converter or NULL the new parser output or NULL 

an I/O write function  an I/O close function  an I/O handler the new parser output or NULL 

a buffered parser output  the size in bytes of the array.  an char array the number of chars immediately written, or -1 -in case of error. 

a buffered parser output  a zero terminated C string the number of chars immediately written, or -1 -in case of error. 

a buffered output the number of byte written or -1 in case of error. 

a buffered output the number of byte written or -1 in case of error. 

the xmlOutputMatchCallback  the xmlOutputOpenCallback  the xmlOutputWriteCallback  the xmlOutputCloseCallback the registered handler number or -1 in case of error 

xmlIOHTTPOpenW ()

void*       xmlIOHTTPOpenW                  (const char *post_uri,
+                                             int compression);

Open a temporary buffer to collect the document for a subsequent HTTP POST +request. Non-static as is called from the output buffer creation routine.

post_uri : 
compression : 


an output I/O buffer  the document  the encoding if any assuming the i/O layer handles the trancoding  the number of byte written or -1 in case of failure. 

an output I/O buffer  the document  the encoding if any assuming the i/O layer handles the trancoding  should formatting spaces been added  the number of byte written or -1 in case of failure. 

the XML buffer output  the document  the current node  the imbrication level for indenting  is formatting allowed  an optional encoding string 

the HTML buffer output  the document  the encoding string 

Name

Synopsis

*xmlMallocFunc) (...); +>) (size_t); void* (*xmlReallocFunc) (void*, - ...); + size_t); char* (*xmlStrdupFuncxmlMalloc (x) +> (size) #define xmlRealloc (p, x) +> (ptr, size) #define xmlMemStrdup (x) +> (str) void* xmlMallocLoc (int size, +> (size_t size, const char *file, int line); void* xmlReallocLoc (void *ptr, - int size, + size_t size, const char *file, int line); char*

Description

Details




void*       (*xmlMallocFunc)                (...);
void* (*xmlMallocFunc) (size_t);

...Param1 :

void*       (*xmlReallocFunc)               (void*,
-                                             ...);
size_t);

...Param2 :









#define xmlMalloc(x) xmlMallocLoc((x), __FILE__, __LINE__)
#define xmlMalloc(size) xmlMallocLoc((size), __FILE__, __LINE__)

xsize :

#define xmlRealloc(p, x) xmlReallocLoc((p), (x), __FILE__, __LINE__)
#define xmlRealloc(ptr, size) xmlReallocLoc((ptr), (size), __FILE__, __LINE__)

pptr :xsize :

#define xmlMemStrdup(x) xmlMemStrdupLoc((x), __FILE__, __LINE__)
#define xmlMemStrdup(str) xmlMemStrdupLoc((str), __FILE__, __LINE__)

xstr :

void*       xmlMallocLoc                    (int size,
+>void*       xmlMallocLoc                    (size_t size,
                                              const char *file,
                                              int line);


void*       xmlReallocLoc                   (void *ptr,
-                                             int size,
+                                             size_t size,
                                              const char *file,
                                              int line);


Name

Synopsis

xmlXPathObject; -typedef xmlXPathObjectPtr (); +>; int (*xmlXPathConvertFuncxmlXPathNodeSetItem (ns, index) +#define xmlXPathNodeSetIsEmpty (ns) void xmlXPathFreeObjectxmlXPathObjectPtr xmlXPathEvalXPtrExpr (const xmlChar *str, - xmlXPathContextPtr ctxt); -xmlXPathObjectPtr xmlXPathEvalExpression (const

Description

Details










xmlXPathObjectPtr ()

xmlXPathObjectPtr

typedef     xmlXPathObjectPtr               ();
typedef xmlXPathObject *xmlXPathObjectPtr;

Returns : 







an XPath evaluation function, the parameters are on thei XPath context stack

an XPath parser context  the number of arguments passed to the function 








An XPath function -The arguments (if any) are popped out of the context stack -and the result is pushed on the stack.




xmlXPathNodeSetIsEmpty()

#define     xmlXPathNodeSetIsEmpty(ns)

ns : 











Converts an XPath object to its boolean value

  an XPath object the boolean value


















xmlXPathEvalXPtrExpr ()

xmlXPathObjectPtr xmlXPathEvalXPtrExpr      (const xmlChar *str,
-                                             xmlXPathContextPtr ctxt);

str : 
ctxt : 
Returns : 






Name

Synopsis

+#define xmlXPathSetError (ctxt, err) +#define xmlXPathSetArityError (ctxt) +#define xmlXPathSetTypeError (ctxt) +#define xmlXPathGetError (ctxt) +#define xmlXPathCheckError (ctxt) +#define xmlXPathGetDocument (ctxt) +#define xmlXPathGetContextNode (ctxt) +int xmlXPathPopBoolean (xmlXPathParserContextPtr ctxt); +double xmlXPathPopNumber (xmlXPathParserContextPtr ctxt); +xmlChar* xmlXPathPopString (xmlXPathParserContextPtr ctxt); +xmlNodeSetPtr xmlXPathPopNodeSet (xmlXPathParserContextPtr ctxt); +void* xmlXPathPopExternal (xmlXPathParserContextPtr ctxt); +#define xmlXPathReturnBoolean (ctxt, val) +#define xmlXPathReturnTrue (ctxt) +#define xmlXPathReturnFalse (ctxt) +#define xmlXPathReturnNumber (ctxt, val) +#define xmlXPathReturnString (ctxt, str) +#define xmlXPathReturnEmptyString (ctxt) +#define xmlXPathReturnNodeSet (ctxt, ns) +#define xmlXPathReturnEmptyNodeSet (ctxt, ns) +#define xmlXPathReturnExternal (ctxt, val) +#define xmlXPathStackIsNodeSet (ctxt) +#define xmlXPathEmptyNodeSet (ns) #define CHECK_ERRORCAST_TO_BOOLEAN -typedef xmlXPathObjectPtr (); +> (*xmlXPathVariableLookupFunc) + (void *ctxt, + const xmlChar *name, + const xmlChar *ns_uri); void xmlXPathRegisterVariableLookupxmlXPathContextPtr ctxt, - xmlXPathVariableLookupFuncxmlXPathVariableLookupFunc f, void *varCtxt); void xmlXPathCompExprPtr comp, int depth); +xmlNodeSetPtr xmlXPathDifference (xmlNodeSetPtr nodes1, + xmlNodeSetPtr nodes2); +xmlNodeSetPtr xmlXPathIntersection (xmlNodeSetPtr nodes1, + xmlNodeSetPtr nodes2); +xmlNodeSetPtr xmlXPathDistinctSorted (xmlNodeSetPtr nodes); +xmlNodeSetPtr xmlXPathDistinct (xmlNodeSetPtr nodes); +int xmlXPathHasSameNodes (xmlNodeSetPtr nodes1, + xmlNodeSetPtr nodes2); +xmlNodeSetPtr xmlXPathNodeLeadingSorted (xmlNodeSetPtr nodes, + xmlNodePtr node); +xmlNodeSetPtr xmlXPathLeadingSorted (xmlNodeSetPtr nodes1, + xmlNodeSetPtr nodes2); +xmlNodeSetPtr xmlXPathNodeLeading (xmlNodeSetPtr nodes, + xmlNodePtr node); +xmlNodeSetPtr xmlXPathLeading (xmlNodeSetPtr nodes1, + xmlNodeSetPtr nodes2); +xmlNodeSetPtr xmlXPathNodeTrailingSorted (xmlNodeSetPtr nodes, + xmlNodePtr node); +xmlNodeSetPtr xmlXPathTrailingSorted (xmlNodeSetPtr nodes1, + xmlNodeSetPtr nodes2); +xmlNodeSetPtr xmlXPathNodeTrailing (xmlNodeSetPtr nodes, + xmlNodePtr node); +xmlNodeSetPtr xmlXPathTrailing (xmlNodeSetPtr nodes1, + xmlNodeSetPtr nodes2); int xmlXPathRegisterNsxmlNodeSetPtr val); +xmlXPathObjectPtr xmlXPathWrapExternal (void *val); void xmlXPathFreeNodeSetList

Description

Details

CHECK_ERROR

xmlXPathSetError()

#define     CHECK_ERROR
#define xmlXPathSetError(ctxt, err)

macro to return from the function if an XPath error was detected


CHECK_ERROR0

#define     CHECK_ERROR0

macro to return 0 from the function if an XPath error was detected


XP_ERROR()

#define     XP_ERROR(X)

Macro to raise an XPath error and return

Xctxt : the error code err : 

XP_ERROR0()

xmlXPathSetArityError()

#define     XP_ERROR0(X)
#define xmlXPathSetArityError(ctxt)

Macro to raise an XPath error and return 0

Xctxt : the error code 

CHECK_TYPE()

xmlXPathSetTypeError()

#define     CHECK_TYPE(typeval)
#define xmlXPathSetTypeError(ctxt)

Macro to check that the value on top of the XPath stack is of a given -type.

typevalctxt : the XPath type 

CHECK_TYPE0()

xmlXPathGetError()

#define     CHECK_TYPE0(typeval)
#define xmlXPathGetError(ctxt) ((ctxt)->error)

Macro to check that the value on top of the XPath stack is of a given -type. return(0) in case of failure

ctxt : 


xmlXPathCheckError()

#define xmlXPathCheckError(ctxt)  ((ctxt)->error != XPATH_EXPRESSION_OK)

typevalctxt : the XPath type 

xmlXPathGetDocument()

#define xmlXPathGetDocument(ctxt)	((ctxt)->context->doc)

ctxt : 


xmlXPathGetContextNode()

#define xmlXPathGetContextNode(ctxt)	((ctxt)->context->node)

ctxt : 


xmlXPathPopBoolean ()

int         xmlXPathPopBoolean              (xmlXPathParserContextPtr ctxt);

Pops a boolean from the stack, handling conversion if needed. +Check error with xmlXPathCheckError.

ctxt : an XPath parser context
Returns :the boolean


xmlXPathPopNumber ()

double      xmlXPathPopNumber               (xmlXPathParserContextPtr ctxt);

Pops a number from the stack, handling conversion if needed. +Check error with xmlXPathCheckError.

ctxt : an XPath parser context
Returns :the number


xmlXPathPopString ()

xmlChar*    xmlXPathPopString               (xmlXPathParserContextPtr ctxt);

Pops a string from the stack, handling conversion if needed. +Check error with xmlXPathCheckError.

ctxt : an XPath parser context
Returns :the string


xmlXPathPopNodeSet ()

xmlNodeSetPtr xmlXPathPopNodeSet            (xmlXPathParserContextPtr ctxt);

Pops a node-set from the stack, handling conversion if needed. +Check error with xmlXPathCheckError.

ctxt : an XPath parser context
Returns :the node-set


xmlXPathPopExternal ()

void*       xmlXPathPopExternal             (xmlXPathParserContextPtr ctxt);

Pops an external oject from the stack, handling conversion if needed. +Check error with xmlXPathCheckError.

ctxt : an XPath parser context


xmlXPathReturnBoolean()

#define     xmlXPathReturnBoolean(ctxt, val)

ctxt : 
val : 


xmlXPathReturnTrue()

#define xmlXPathReturnTrue(ctxt)   xmlXPathReturnBoolean((ctxt), 1)

ctxt : 


xmlXPathReturnFalse()

#define xmlXPathReturnFalse(ctxt)  xmlXPathReturnBoolean((ctxt), 0)

ctxt : 


xmlXPathReturnNumber()

#define     xmlXPathReturnNumber(ctxt, val)

ctxt : 
val : 


xmlXPathReturnString()

#define     xmlXPathReturnString(ctxt, str)

ctxt : 
str : 


xmlXPathReturnEmptyString()

#define     xmlXPathReturnEmptyString(ctxt)

ctxt : 


xmlXPathReturnNodeSet()

#define     xmlXPathReturnNodeSet(ctxt, ns)

ctxt : 
ns : 


xmlXPathReturnEmptyNodeSet()

#define     xmlXPathReturnEmptyNodeSet(ctxt, ns)

ctxt : 
ns : 


xmlXPathReturnExternal()

#define     xmlXPathReturnExternal(ctxt, val)

ctxt : 
val : 


xmlXPathStackIsNodeSet()

#define     xmlXPathStackIsNodeSet(ctxt)

ctxt : 


xmlXPathEmptyNodeSet()

#define     xmlXPathEmptyNodeSet(ns)

ns : 


CHECK_ERROR

#define     CHECK_ERROR


CHECK_ERROR0

#define     CHECK_ERROR0


XP_ERROR()

#define     XP_ERROR(X)

X : 


XP_ERROR0()

#define     XP_ERROR0(X)

X : 


CHECK_TYPE()

#define     CHECK_TYPE(typeval)

typeval : 


CHECK_TYPE0()

#define     CHECK_TYPE0(typeval)

typeval : 


CHECK_ARITY()

Macro to check that the number of args passed to an XPath function matches

typedef     xmlXPathObjectPtr               ();
xmlXPathObjectPtr (*xmlXPathVariableLookupFunc) + (void *ctxt, + const xmlChar *name, + const xmlChar *ns_uri);

ctxt : name : ns_uri : Returns

xmlXPathContextPtr ctxt, - xmlXPathVariableLookupFuncxmlXPathVariableLookupFunc f, void *varCtxt);


Formats an error message.

  the XPath Parser context  the file name  the line number  the error number


Dumps the tree of the compiled XPath expression.

  the FILE * for the output  the precompiled XPath expression  the indentation level.

xmlXPathDifference ()

xmlNodeSetPtr xmlXPathDifference            (xmlNodeSetPtr nodes1,
+                                             xmlNodeSetPtr nodes2);

Implements the EXSLT - Sets difference() function: +node-set set:difference (node-set, node-set)

nodes1 : a node-set
nodes2 : a node-set
Returns :the difference between the two node sets, or nodes1 if +nodes2 is empty


xmlXPathIntersection ()

xmlNodeSetPtr xmlXPathIntersection          (xmlNodeSetPtr nodes1,
+                                             xmlNodeSetPtr nodes2);

Implements the EXSLT - Sets intersection() function: +node-set set:intersection (node-set, node-set)

nodes1 : a node-set
nodes2 : a node-set
Returns :a node set comprising the nodes that are within both the +node sets passed as arguments


xmlXPathDistinctSorted ()

xmlNodeSetPtr xmlXPathDistinctSorted        (xmlNodeSetPtr nodes);

Implements the EXSLT - Sets distinct() function: +node-set set:distinct (node-set)

nodes : a node-set, sorted by document order
Returns :a subset of the nodes contained in nodes, or nodes if +it is empty


xmlXPathDistinct ()

xmlNodeSetPtr xmlXPathDistinct              (xmlNodeSetPtr nodes);

Implements the EXSLT - Sets distinct() function: +node-set set:distinct (node-set) +nodes is sorted by document order, then exslSetsDistinctSorted +is called with the sorted node-set

nodes : a node-set
Returns :a subset of the nodes contained in nodes, or nodes if +it is empty


xmlXPathHasSameNodes ()

int         xmlXPathHasSameNodes            (xmlNodeSetPtr nodes1,
+                                             xmlNodeSetPtr nodes2);

Implements the EXSLT - Sets has-same-nodes function: +boolean set:has-same-node(node-set, node-set)

nodes1 : a node-set
nodes2 : a node-set
Returns :true (1) if nodes1 shares any node with nodes2, false (0) +otherwise


xmlXPathNodeLeadingSorted ()

xmlNodeSetPtr xmlXPathNodeLeadingSorted     (xmlNodeSetPtr nodes,
+                                             xmlNodePtr node);

Implements the EXSLT - Sets leading() function: +node-set set:leading (node-set, node-set)

nodes : a node-set, sorted by document order
node : a node
Returns :the nodes in nodes that precede node in document order, +nodes if node is NULL or an empty node-set if nodes +doesn't contain node


xmlXPathLeadingSorted ()

xmlNodeSetPtr xmlXPathLeadingSorted         (xmlNodeSetPtr nodes1,
+                                             xmlNodeSetPtr nodes2);

Implements the EXSLT - Sets leading() function: +node-set set:leading (node-set, node-set)

nodes1 : a node-set, sorted by document order
nodes2 : a node-set, sorted by document order
Returns :the nodes in nodes1 that precede the first node in nodes2 +in document order, nodes1 if nodes2 is NULL or empty or +an empty node-set if nodes1 doesn't contain nodes2


xmlXPathNodeLeading ()

xmlNodeSetPtr xmlXPathNodeLeading           (xmlNodeSetPtr nodes,
+                                             xmlNodePtr node);

Implements the EXSLT - Sets leading() function: +node-set set:leading (node-set, node-set) +nodes is sorted by document order, then exslSetsNodeLeadingSorted +is called.

nodes : a node-set
node : a node
Returns :the nodes in nodes that precede node in document order, +nodes if node is NULL or an empty node-set if nodes +doesn't contain node


xmlXPathLeading ()

xmlNodeSetPtr xmlXPathLeading               (xmlNodeSetPtr nodes1,
+                                             xmlNodeSetPtr nodes2);

Implements the EXSLT - Sets leading() function: +node-set set:leading (node-set, node-set) +nodes1 and nodes2 are sorted by document order, then +exslSetsLeadingSorted is called.

nodes1 : a node-set
nodes2 : a node-set
Returns :the nodes in nodes1 that precede the first node in nodes2 +in document order, nodes1 if nodes2 is NULL or empty or +an empty node-set if nodes1 doesn't contain nodes2


xmlXPathNodeTrailingSorted ()

xmlNodeSetPtr xmlXPathNodeTrailingSorted    (xmlNodeSetPtr nodes,
+                                             xmlNodePtr node);

Implements the EXSLT - Sets trailing() function: +node-set set:trailing (node-set, node-set)

nodes : a node-set, sorted by document order
node : a node
Returns :the nodes in nodes that follow node in document order, +nodes if node is NULL or an empty node-set if nodes +doesn't contain node


xmlXPathTrailingSorted ()

xmlNodeSetPtr xmlXPathTrailingSorted        (xmlNodeSetPtr nodes1,
+                                             xmlNodeSetPtr nodes2);

Implements the EXSLT - Sets trailing() function: +node-set set:trailing (node-set, node-set)

nodes1 : a node-set, sorted by document order
nodes2 : a node-set, sorted by document order
Returns :the nodes in nodes1 that follow the first node in nodes2 +in document order, nodes1 if nodes2 is NULL or empty or +an empty node-set if nodes1 doesn't contain nodes2


xmlXPathNodeTrailing ()

xmlNodeSetPtr xmlXPathNodeTrailing          (xmlNodeSetPtr nodes,
+                                             xmlNodePtr node);

Implements the EXSLT - Sets trailing() function: +node-set set:trailing (node-set, node-set) +nodes is sorted by document order, then xmlXPathNodeTrailingSorted +is called.

nodes : a node-set
node : a node
Returns :the nodes in nodes that follow node in document order, +nodes if node is NULL or an empty node-set if nodes +doesn't contain node


xmlXPathTrailing ()

xmlNodeSetPtr xmlXPathTrailing              (xmlNodeSetPtr nodes1,
+                                             xmlNodeSetPtr nodes2);

Implements the EXSLT - Sets trailing() function: +node-set set:trailing (node-set, node-set) +nodes1 and nodes2 are sorted by document order, then +xmlXPathTrailingSorted is called.

nodes1 : a node-set
nodes2 : a node-set
Returns :the nodes in nodes1 that follow the first node in nodes2 +in document order, nodes1 if nodes2 is NULL or empty or +an empty node-set if nodes1 doesn't contain nodes2




Cleanup the XPath context data associated to registered variables

  the XPath context













Pops the top XPath object from the value stack

  an XPath evaluation context the XPath object just removed

Pushes a new XPath object on top of the value stack

  an XPath evaluation context  the XPath object





























xmlXPathWrapExternal ()

xmlXPathObjectPtr xmlXPathWrapExternal      (void *val);

Wraps the val data into an XPath object.

val : the user data
Returns :the newly created object.



















































Name

Synopsis

Description

Details























+#include #include #include #include @@ -28,7 +29,7 @@ extern "C" { typedef int (*xmlInputMatchCallback) (char const *filename); typedef void * (*xmlInputOpenCallback) (char const *filename); typedef int (*xmlInputReadCallback) (void * context, char * buffer, int len); -typedef void (*xmlInputCloseCallback) (void * context); +typedef int (*xmlInputCloseCallback) (void * context); typedef struct _xmlParserInputBuffer xmlParserInputBuffer; typedef xmlParserInputBuffer *xmlParserInputBufferPtr; @@ -53,7 +54,7 @@ typedef int (*xmlOutputMatchCallback) (char const *filename); typedef void * (*xmlOutputOpenCallback) (char const *filename); typedef int (*xmlOutputWriteCallback) (void * context, const char * buffer, int len); -typedef void (*xmlOutputCloseCallback) (void * context); +typedef int (*xmlOutputCloseCallback) (void * context); typedef struct _xmlOutputBuffer xmlOutputBuffer; typedef xmlOutputBuffer *xmlOutputBufferPtr; @@ -156,6 +157,13 @@ int xmlRegisterOutputCallbacks (xmlOutputMatchCallback matchFunc, xmlOutputWriteCallback writeFunc, xmlOutputCloseCallback closeFunc); +/* This function only exists if HTTP support built into the library */ +#ifdef LIBXML_HTTP_ENABLED +void * xmlIOHTTPOpenW (const char * post_uri, + int compression ); +void xmlRegisterHTTPPostCallbacksI (void ); +#endif + /* * This save function are part of tree.h and HTMLtree.h actually */ diff --git a/nanohttp.c b/nanohttp.c index fb4fbd00..c29cc7ab 100644 --- a/nanohttp.c +++ b/nanohttp.c @@ -63,6 +63,7 @@ #define SOCKET int #endif +#include #include #include /* for xmlStr(n)casecmp() */ #include @@ -75,6 +76,7 @@ #define SOCKET int #endif + #ifdef STANDALONE #define DEBUG_HTTP #define xmlStrncasecmp(a, b, n) strncasecmp((char *)a, (char *)b, n) @@ -106,6 +108,7 @@ typedef struct xmlNanoHTTPCtxt { int inlen; /* len of the input buffer */ int last; /* return code for last operation */ int returnValue; /* the protocol return value */ + int ContentLength; /* specified content length from HTTP header */ char *contentType; /* the MIME type for the input */ char *location; /* the new URL in case of redirect */ char *authHeader; /* contents of {WWW,Proxy}-Authenticate header */ @@ -116,6 +119,9 @@ static char *proxy = NULL; /* the proxy name if any */ static int proxyPort; /* the proxy port if any */ static unsigned int timeout = 60;/* the select() timeout in seconds */ +int xmlNanoHTTPFetchContent( void * ctx, char ** ptr, int * len ); +int xmlNanoHTTPContentLength( void * ctx ); + /** * A portability function */ @@ -358,6 +364,7 @@ xmlNanoHTTPNewCtxt(const char *URL) { ret->port = 80; ret->returnValue = 0; ret->fd = -1; + ret->ContentLength = -1; xmlNanoHTTPScanURL(ret, URL); @@ -393,20 +400,52 @@ xmlNanoHTTPFreeCtxt(xmlNanoHTTPCtxtPtr ctxt) { * @ctxt: an HTTP context * * Send the input needed to initiate the processing on the server side + * Returns number of bytes sent or -1 on error. */ -static void -xmlNanoHTTPSend(xmlNanoHTTPCtxtPtr ctxt) { - if (ctxt->state & XML_NANO_HTTP_WRITE) { - unsigned int total_sent = 0; - while (total_sent outptr)) { - unsigned int nsent = send(ctxt->fd, ctxt->outptr+total_sent, - strlen(ctxt->outptr)-total_sent, 0); +static int +xmlNanoHTTPSend(xmlNanoHTTPCtxtPtr ctxt, const char * xmt_ptr, int outlen) { + + int total_sent = 0; + + if ( (ctxt->state & XML_NANO_HTTP_WRITE) && (xmt_ptr != NULL ) ) { + while (total_sent < outlen) { + int nsent = send(ctxt->fd, xmt_ptr + total_sent, + outlen - total_sent, 0); if (nsent>0) total_sent += nsent; + else if ( ( nsent == -1 ) && + ( socket_errno( ) != EAGAIN ) && + ( socket_errno( ) != EWOULDBLOCK ) ) { + xmlGenericError( xmlGenericErrorContext, + "xmlNanoHTTPSend error: %s", + strerror( socket_errno( ) ) ); + + if ( total_sent == 0 ) + total_sent = -1; + break; + } + else { + /* + ** No data sent + ** Since non-blocking sockets are used, wait for + ** socket to be writable or default timeout prior + ** to retrying. + */ + + struct timeval tv; + fd_set wfd; + + tv.tv_sec = timeout; + tv.tv_usec = 0; + FD_ZERO( &wfd ); + FD_SET( ctxt->fd, &wfd ); + (void)select( ctxt->fd + 1, NULL, &wfd, NULL, &tv ); + } } - ctxt->last = total_sent; } + + return total_sent; } /** @@ -430,6 +469,8 @@ xmlNanoHTTPRecv(xmlNanoHTTPCtxtPtr ctxt) { ctxt->in = (char *) xmlMalloc(65000 * sizeof(char)); if (ctxt->in == NULL) { ctxt->last = -1; + xmlGenericError( xmlGenericErrorContext, + "xmlNanoHTTPRecv: Error allocating input memory." ); return(-1); } ctxt->inlen = 65000; @@ -448,10 +489,16 @@ xmlNanoHTTPRecv(xmlNanoHTTPCtxtPtr ctxt) { int d_inptr = ctxt->inptr - ctxt->in; int d_content = ctxt->content - ctxt->in; int d_inrptr = ctxt->inrptr - ctxt->in; + char * tmp_ptr = ctxt->in; ctxt->inlen *= 2; - ctxt->in = (char *) xmlRealloc(ctxt->in, ctxt->inlen); + ctxt->in = (char *) xmlRealloc(tmp_ptr, ctxt->inlen); if (ctxt->in == NULL) { + xmlGenericError( xmlGenericErrorContext, + "xmlNanoHTTPRecv: %s %d bytes.", + "Failed to realloc input buffer to", + ctxt->inlen ); + xmlFree( tmp_ptr ); ctxt->last = -1; return(-1); } @@ -475,8 +522,16 @@ xmlNanoHTTPRecv(xmlNanoHTTPCtxtPtr ctxt) { case EAGAIN: #endif break; + + case ECONNRESET: + case ESHUTDOWN: + return ( 0 ); + default: - return(0); + xmlGenericError( xmlGenericErrorContext, + "xmlNanoHTTPRecv: recv( ) failure - %s", + strerror( socket_errno( ) ) ); + return(-1); } } @@ -485,7 +540,7 @@ xmlNanoHTTPRecv(xmlNanoHTTPCtxtPtr ctxt) { FD_ZERO(&rfd); FD_SET(ctxt->fd, &rfd); - if (select(ctxt->fd+1, &rfd, NULL, NULL, &tv)<1) + if ( (select(ctxt->fd+1, &rfd, NULL, NULL, &tv)<1) && (errno != EINTR) ) return(0); } return(0); @@ -506,16 +561,20 @@ static char * xmlNanoHTTPReadLine(xmlNanoHTTPCtxtPtr ctxt) { char buf[4096]; char *bp = buf; + int rc; while (bp - buf < 4095) { if (ctxt->inrptr == ctxt->inptr) { - if (xmlNanoHTTPRecv(ctxt) == 0) { + if ( (rc = xmlNanoHTTPRecv(ctxt)) == 0) { if (bp == buf) return(NULL); else *bp = 0; return(xmlMemStrdup(buf)); } + else if ( rc == -1 ) { + return ( NULL ); + } } *bp = *ctxt->inrptr++; if (*bp == '\n') { @@ -610,6 +669,9 @@ xmlNanoHTTPScanAnswer(xmlNanoHTTPCtxtPtr ctxt, const char *line) { if (ctxt->authHeader != NULL) xmlFree(ctxt->authHeader); ctxt->authHeader = xmlMemStrdup(cur); + } else if ( !xmlStrncasecmp( BAD_CAST line, BAD_CAST"Content-Length:", 15) ) { + cur += 15; + ctxt->ContentLength = strtol( cur, NULL, 10 ); } } @@ -636,6 +698,10 @@ xmlNanoHTTPConnectAttempt(struct sockaddr *addr) #ifdef DEBUG_HTTP perror("socket"); #endif + xmlGenericError( xmlGenericErrorContext, + "xmlNanoHTTPConnectAttempt: %s - %s", + "socket creation failure", + strerror( socket_errno( ) ) ); return(-1); } @@ -666,20 +732,26 @@ xmlNanoHTTPConnectAttempt(struct sockaddr *addr) #ifdef DEBUG_HTTP perror("nonblocking"); #endif + xmlGenericError( xmlGenericErrorContext, + "xmlNanoHTTPConnectAttempt: %s - %s", + "error setting non-blocking IO", + strerror( socket_errno( ) ) ); closesocket(s); return(-1); } #endif /* !VMS */ #endif /* !_WINSOCKAPI_ */ - if ((connect(s, addr, sizeof(*addr))==-1)) { switch (socket_errno()) { case EINPROGRESS: case EWOULDBLOCK: break; default: - perror("connect"); + xmlGenericError( xmlGenericErrorContext, + "xmlNanoHTTPConnectAttempt: %s - %s", + "error connecting to HTTP server", + strerror( socket_errno( ) ) ); closesocket(s); return(-1); } @@ -695,13 +767,17 @@ xmlNanoHTTPConnectAttempt(struct sockaddr *addr) { case 0: /* Time out */ + xmlGenericError( xmlGenericErrorContext, + "xmlNanoHTTPConnectAttempt: %s", + "Connect attempt timed out." ); closesocket(s); return(-1); case -1: /* Ermm.. ?? */ -#ifdef DEBUG_HTTP - perror("select"); -#endif + xmlGenericError( xmlGenericErrorContext, + "xmlNanoHTTPConnectAttempt: %s - %s", + "Error connecting to host", + strerror( socket_errno( ) ) ); closesocket(s); return(-1); } @@ -711,15 +787,27 @@ xmlNanoHTTPConnectAttempt(struct sockaddr *addr) len = sizeof(status); if (getsockopt(s, SOL_SOCKET, SO_ERROR, (char*)&status, &len) < 0 ) { /* Solaris error code */ + xmlGenericError( xmlGenericErrorContext, + "xmlNanoHTTPConnectAttempt: %s - %s", + "Error retrieving pending socket errors", + strerror( socket_errno( ) ) ); return (-1); } if ( status ) { closesocket(s); errno = status; + xmlGenericError( xmlGenericErrorContext, + "xmlNanoHTTPConnectAttempt: %s - %s", + "Error connecting to remote host", + strerror( status ) ); return (-1); } } else { /* pbm */ + xmlGenericError( xmlGenericErrorContext, + "xmlNanoHTTPConnectAttempt: %s\n", + "Select returned, but descriptor not set for connection.\n" ); + closesocket(s); return (-1); } @@ -759,9 +847,34 @@ xmlNanoHTTPConnectHost(const char *host, int port) h=gethostbyname(host); if (h==NULL) { -#ifdef DEBUG_HTTP - xmlGenericError(xmlGenericErrorContext,"unable to resolve '%s'.\n", host); -#endif + const char * h_err_txt = ""; + switch ( h_errno ) + { + case HOST_NOT_FOUND: + h_err_txt = "Authoritive host not found"; + break; + + case TRY_AGAIN: + h_err_txt = + "Non-authoritive host not found or server failure."; + break; + + case NO_RECOVERY: + h_err_txt = + "Non-recoverable errors: FORMERR, REFUSED, or NOTIMP."; + break; + + case NO_ADDRESS: + h_err_txt = "Valid name, no data record of requested type."; + break; + + default: + h_err_txt = "No error text defined."; + break; + } + xmlGenericError( xmlGenericErrorContext, + "xmlNanoHTTPConnectHost: %s '%s' - %s", + "Failed to resolve host", host, h_err_txt ); return(-1); } @@ -793,7 +906,7 @@ xmlNanoHTTPConnectHost(const char *host, int port) #ifdef DEBUG_HTTP xmlGenericError(xmlGenericErrorContext, - "unable to connect to '%s'.\n", host); + "xmlNanoHTTPConnectHost: unable to connect to '%s'.\n", host); #endif return(-1); } @@ -815,7 +928,7 @@ xmlNanoHTTPConnectHost(const char *host, int port) void* xmlNanoHTTPOpen(const char *URL, char **contentType) { if (contentType != NULL) *contentType = NULL; - return(xmlNanoHTTPMethod(URL, NULL, NULL, contentType, NULL)); + return(xmlNanoHTTPMethod(URL, NULL, NULL, contentType, NULL, 0)); } /** @@ -836,7 +949,7 @@ void* xmlNanoHTTPOpenRedir(const char *URL, char **contentType, char **redir) { if (contentType != NULL) *contentType = NULL; if (redir != NULL) *redir = NULL; - return(xmlNanoHTTPMethodRedir(URL, NULL, NULL, contentType, redir, NULL)); + return(xmlNanoHTTPMethodRedir(URL, NULL, NULL, contentType, redir, NULL,0)); } /** @@ -860,7 +973,7 @@ xmlNanoHTTPRead(void *ctx, void *dest, int len) { if (len <= 0) return(0); while (ctxt->inptr - ctxt->inrptr < len) { - if (xmlNanoHTTPRecv(ctxt) == 0) break; + if (xmlNanoHTTPRecv(ctxt) <= 0) break; } if (ctxt->inptr - ctxt->inrptr < len) len = ctxt->inptr - ctxt->inrptr; @@ -904,11 +1017,13 @@ xmlNanoHTTPClose(void *ctx) { void* xmlNanoHTTPMethodRedir(const char *URL, const char *method, const char *input, - char **contentType, char **redir, const char *headers) { + char **contentType, char **redir, + const char *headers, int ilen ) { xmlNanoHTTPCtxtPtr ctxt; char *bp, *p; - int blen, ilen, ret; + int blen, ret; int head; + int xmt_bytes; int nbRedirects = 0; char *redirURL = NULL; @@ -923,12 +1038,28 @@ retry: ctxt = xmlNanoHTTPNewCtxt(redirURL); } + if ( ctxt == NULL ) { + xmlGenericError( xmlGenericErrorContext, + "xmlNanoHTTPMethodRedir: %s %s.", + "Unable to allocate HTTP context to URI", + ( ( redirURL == NULL ) ? URL : redirURL ) ); + return ( NULL ); + } + if ((ctxt->protocol == NULL) || (strcmp(ctxt->protocol, "http"))) { + xmlGenericError( xmlGenericErrorContext, + "xmlNanoHTTPMethodRedir: %s - %s.", + "Not a valid HTTP URI", + ( ( redirURL == NULL ) ? URL : redirURL ) ); xmlNanoHTTPFreeCtxt(ctxt); if (redirURL != NULL) xmlFree(redirURL); return(NULL); } if (ctxt->hostname == NULL) { + xmlGenericError( xmlGenericErrorContext, + "xmlNanoHTTPMethodRedir: %s - %s", + "Failed to identify host in URI", + ( ( redirURL == NULL ) ? URL : redirURL ) ); xmlNanoHTTPFreeCtxt(ctxt); if (redirURL != NULL) xmlFree(redirURL); return(NULL); @@ -948,43 +1079,52 @@ retry: } ctxt->fd = ret; - if (input != NULL) { - ilen = strlen(input); - blen += ilen + 32; - } - else + if (input == NULL) ilen = 0; + else + blen += 36; + if (headers != NULL) - blen += strlen(headers); + blen += strlen(headers) + 2; if (contentType && *contentType) blen += strlen(*contentType) + 16; - blen += strlen(method) + strlen(ctxt->path) + 23; + blen += strlen(method) + strlen(ctxt->path) + 24; bp = xmlMalloc(blen); + if ( bp == NULL ) { + xmlNanoHTTPFreeCtxt( ctxt ); + xmlGenericError( xmlGenericErrorContext, + "xmlNanoHTTPMethodRedir: %s", + "Error allocating HTTP header buffer." ); + return ( NULL ); + } + + p = bp; + if (proxy) { if (ctxt->port != 80) { - sprintf(bp, "%s http://%s:%d%s", method, ctxt->hostname, - ctxt->port, ctxt->path); + p += sprintf( p, "%s http://%s:%d%s", method, ctxt->hostname, + ctxt->port, ctxt->path ); } else - sprintf(bp, "%s http://%s%s", method, ctxt->hostname, ctxt->path); + p += sprintf( p, "%s http://%s%s", method, + ctxt->hostname, ctxt->path); } else - sprintf(bp, "%s %s", method, ctxt->path); - p = bp + strlen(bp); - sprintf(p, " HTTP/1.0\r\nHost: %s\r\n", ctxt->hostname); - p += strlen(p); - if (contentType != NULL && *contentType) { - sprintf(p, "Content-Type: %s\r\n", *contentType); - p += strlen(p); - } - if (headers != NULL) { - strcpy(p, headers); - p += strlen(p); - } + p += sprintf( p, "%s %s", method, ctxt->path); + + p += sprintf(p, " HTTP/1.0\r\nHost: %s\r\n", ctxt->hostname); + + if (contentType != NULL && *contentType) + p += sprintf(p, "Content-Type: %s\r\n", *contentType); + + if (headers != NULL) + p += sprintf( p, "%s", headers ); + if (input != NULL) - sprintf(p, "Content-Length: %d\r\n\r\n%s", ilen, input); + sprintf(p, "Content-Length: %d\r\n\r\n", ilen ); else strcpy(p, "\r\n"); + #ifdef DEBUG_HTTP xmlGenericError(xmlGenericErrorContext, "-> %s%s", proxy? "(Proxy) " : "", bp); @@ -994,7 +1134,30 @@ retry: #endif ctxt->outptr = ctxt->out = bp; ctxt->state = XML_NANO_HTTP_WRITE; - xmlNanoHTTPSend(ctxt); + blen = strlen( ctxt->out ); + xmt_bytes = xmlNanoHTTPSend(ctxt, ctxt->out, blen ); +#ifdef DEBUG_HTTP + if ( xmt_bytes != blen ) + xmlGenericError( xmlGenericErrorContext, + "xmlNanoHTTPMethodRedir: Only %d of %d %s %s\n", + xmt_bytes, blen, + "bytes of HTTP headers sent to host", + ctxt->hostname ); +#endif + + if ( input != NULL ) { + xmt_bytes = xmlNanoHTTPSend( ctxt, input, ilen ); + +#ifdef DEBUG_HTTP + if ( xmt_bytes != ilen ) + xmlGenericError( xmlGenericErrorContext, + "xmlNanoHTTPMethodRedir: Only %d of %d %s %s\n", + xmt_bytes, ilen, + "bytes of HTTP content sent to host", + ctxt->hostname ); +#endif + } + ctxt->state = XML_NANO_HTTP_READ; head = 1; @@ -1019,7 +1182,7 @@ retry: xmlGenericError(xmlGenericErrorContext, "\nRedirect to: %s\n", ctxt->location); #endif - while (xmlNanoHTTPRecv(ctxt)) ; + while ( xmlNanoHTTPRecv(ctxt) > 0 ) ; if (nbRedirects < XML_NANO_HTTP_MAX_REDIR) { nbRedirects++; if (redirURL != NULL) @@ -1032,10 +1195,9 @@ retry: if (redirURL != NULL) xmlFree(redirURL); #ifdef DEBUG_HTTP xmlGenericError(xmlGenericErrorContext, - "Too many redirects, aborting ...\n"); + "xmlNanoHTTPMethodRedir: Too many redirects, aborting ...\n"); #endif return(NULL); - } if (contentType != NULL) { @@ -1086,9 +1248,9 @@ retry: void* xmlNanoHTTPMethod(const char *URL, const char *method, const char *input, - char **contentType, const char *headers) { + char **contentType, const char *headers, int ilen) { return(xmlNanoHTTPMethodRedir(URL, method, input, contentType, - NULL, headers)); + NULL, headers, ilen)); } /** @@ -1106,8 +1268,8 @@ xmlNanoHTTPMethod(const char *URL, const char *method, const char *input, */ int xmlNanoHTTPFetch(const char *URL, const char *filename, char **contentType) { - void *ctxt; - char buf[4096]; + void *ctxt = NULL; + char *buf = NULL; int fd; int len; @@ -1128,7 +1290,8 @@ xmlNanoHTTPFetch(const char *URL, const char *filename, char **contentType) { } } - while ((len = xmlNanoHTTPRead(ctxt, buf, sizeof(buf))) > 0) { + xmlNanoHTTPFetchContent( ctxt, &buf, &len ); + if ( len > 0 ) { write(fd, buf, len); } @@ -1165,7 +1328,8 @@ xmlNanoHTTPSave(void *ctxt, const char *filename) { } } - while ((len = xmlNanoHTTPRead(ctxt, buf, sizeof(buf))) > 0) { + xmlNanoHTTPFetchContent( ctxt, &buf, &len ); + if ( len > 0 ) { write(fd, buf, len); } @@ -1208,6 +1372,77 @@ xmlNanoHTTPAuthHeader(void *ctx) { return(ctxt->authHeader); } +/** + * xmlNanoHTTPContentLength + * @ctx: the HTTP context + * + * Return the specified content length from the HTTP header. Note that + * a value of -1 indicates that the content length element was not included in + * the response header. + */ +int +xmlNanoHTTPContentLength( void * ctx ) { + xmlNanoHTTPCtxtPtr ctxt = ctx; + + return ( ( ctxt == NULL ) ? -1 : ctxt->ContentLength ); +} + +/** + * xmlNanoHTTPFetchContent + * @ctx: the HTTP context + * @ptr: pointer to set to the content buffer. + * @len: integer pointer to hold the length of the content + * + * Returns 0 if all the content was read and available, returns + * -1 if received content length was less than specified or an error + * occurred. + */ +int +xmlNanoHTTPFetchContent( void * ctx, char ** ptr, int * len ) { + xmlNanoHTTPCtxtPtr ctxt = ctx; + + int rc = 0; + int cur_lgth; + int rcvd_lgth; + int dummy_int; + char * dummy_ptr = NULL; + + /* Dummy up return input parameters if not provided */ + + if ( len == NULL ) + len = &dummy_int; + + if ( ptr == NULL ) + ptr = &dummy_ptr; + + /* But can't work without the context pointer */ + + if ( ( ctxt == NULL ) || ( ctxt->content == NULL ) ) { + *len = 0; + *ptr = NULL; + return ( -1 ); + } + + rcvd_lgth = ctxt->inptr - ctxt->content; + + while ( (cur_lgth = xmlNanoHTTPRecv( ctxt )) > 0 ) { + + rcvd_lgth += cur_lgth; + if ( (ctxt->ContentLength > 0) && (rcvd_lgth >= ctxt->ContentLength) ) + break; + } + + *ptr = ctxt->content; + *len = rcvd_lgth; + + if ( ( ctxt->ContentLength > 0 ) && ( rcvd_lgth < ctxt->ContentLength ) ) + rc = -1; + else if ( rcvd_lgth == 0 ) + rc = -1; + + return ( rc ); +} + #ifdef STANDALONE int main(int argc, char **argv) { char *contentType = NULL; diff --git a/tree.c b/tree.c index e6d074e9..f623476f 100644 --- a/tree.c +++ b/tree.c @@ -6408,17 +6408,15 @@ xmlSaveFormatFileTo(xmlOutputBuffer *buf, xmlDocPtr cur, const char *encoding, i } /** - * xmlSaveFileEnc: - * @filename: the filename (or URL) - * @cur: the document - * @encoding: the name of an encoding (or NULL) - * - * Dump an XML document, converting it to the given encoding - * - * returns: the number of byte written or -1 in case of failure. + * xmlSaveFormatFileEnc + * @filename: the filename or URL to output + * @cur: the document being saved + * @encoding: the name of the encoding to use or NULL. + * @format: should formatting spaces be added. */ int -xmlSaveFileEnc(const char *filename, xmlDocPtr cur, const char *encoding) { +xmlSaveFormatFileEnc( const char * filename, xmlDocPtr cur, + const char * encoding, int format ) { xmlOutputBufferPtr buf; xmlCharEncodingHandlerPtr handler = NULL; xmlCharEncoding enc; @@ -6439,18 +6437,37 @@ xmlSaveFileEnc(const char *filename, xmlDocPtr cur, const char *encoding) { } } +#ifdef HAVE_ZLIB_H + if (cur->compression < 0) cur->compression = xmlCompressMode; +#endif /* * save the content to a temp buffer. */ - buf = xmlOutputBufferCreateFilename(filename, handler, 0); + buf = xmlOutputBufferCreateFilename(filename, handler, cur->compression); if (buf == NULL) return(-1); - xmlDocContentDumpOutput(buf, cur, encoding, 0); + xmlDocContentDumpOutput(buf, cur, encoding, format); ret = xmlOutputBufferClose(buf); return(ret); } + +/** + * xmlSaveFileEnc: + * @filename: the filename (or URL) + * @cur: the document + * @encoding: the name of an encoding (or NULL) + * + * Dump an XML document, converting it to the given encoding + * + * returns: the number of byte written or -1 in case of failure. + */ +int +xmlSaveFileEnc(const char *filename, xmlDocPtr cur, const char *encoding) { + return ( xmlSaveFormatFileEnc( filename, cur, encoding, 0 ) ); +} + /** * xmlSaveFormatFile: * @filename: the filename (or URL) @@ -6465,47 +6482,7 @@ xmlSaveFileEnc(const char *filename, xmlDocPtr cur, const char *encoding) { */ int xmlSaveFormatFile(const char *filename, xmlDocPtr cur, int format) { - xmlOutputBufferPtr buf; - const char *encoding; - xmlCharEncodingHandlerPtr handler = NULL; - int ret; - - if (cur == NULL) - return(-1); - encoding = (const char *) cur->encoding; - - /* - * save the content to a temp buffer. - */ -#ifdef HAVE_ZLIB_H - if (cur->compression < 0) cur->compression = xmlCompressMode; -#endif - if (encoding != NULL) { - xmlCharEncoding enc; - - enc = xmlParseCharEncoding(encoding); - - if (cur->charset != XML_CHAR_ENCODING_UTF8) { - xmlGenericError(xmlGenericErrorContext, - "xmlSaveFile: document not in UTF8\n"); - return(-1); - } - if (enc != XML_CHAR_ENCODING_UTF8) { - handler = xmlFindCharEncodingHandler(encoding); - if (handler == NULL) { - xmlFree((char *) cur->encoding); - cur->encoding = NULL; - } - } - } - - buf = xmlOutputBufferCreateFilename(filename, handler, cur->compression); - if (buf == NULL) return(-1); - - xmlDocContentDumpOutput(buf, cur, NULL, format); - - ret = xmlOutputBufferClose(buf); - return(ret); + return ( xmlSaveFormatFileEnc( filename, cur, NULL, format ) ); } /** @@ -6520,6 +6497,6 @@ xmlSaveFormatFile(const char *filename, xmlDocPtr cur, int format) { */ int xmlSaveFile(const char *filename, xmlDocPtr cur) { - return(xmlSaveFormatFile(filename, cur, 0)); + return(xmlSaveFormatFileEnc(filename, cur, NULL, 0)); } diff --git a/xmlIO.c b/xmlIO.c index 7c328c26..b4f2efb4 100644 --- a/xmlIO.c +++ b/xmlIO.c @@ -3,7 +3,7 @@ * * See Copyright for the status of this software. * - * daniel@veillard.com + * Daniel.Veillard@w3.org * * 14 Nov 2000 ht - for VMS, truncated name of long functions to under 32 char */ @@ -75,6 +75,7 @@ #define xmlRegisterDefaultOutputCallbacks xmlRegisterDefOutputCallbacks #endif +/* #define VERBOSE_FAILURE */ /* #define DEBUG_EXTERNAL_ENTITIES */ /* #define DEBUG_INPUT */ @@ -197,10 +198,12 @@ xmlFdWrite (void * context, const char * buffer, int len) { * @context: the I/O context * * Close an I/O channel + * + * Returns 0 in case of success and error code otherwise */ -static void +static int xmlFdClose (void * context) { - close((int) (long) context); + return ( close((int) (long) context) ); } /** @@ -324,9 +327,9 @@ xmlFileWrite (void * context, const char * buffer, int len) { * * Close an I/O channel */ -static void +static int xmlFileClose (void * context) { - fclose((FILE *) context); + return ( ( fclose((FILE *) context) == EOF ) ? -1 : 0 ); } /** @@ -335,9 +338,9 @@ xmlFileClose (void * context) { * * Flush an I/O channel */ -static void +static int xmlFileFlush (void * context) { - fflush((FILE *) context); + return ( ( fflush((FILE *) context) == EOF ) ? -1 : 0 ); } #ifdef HAVE_ZLIB_H @@ -466,9 +469,9 @@ xmlGzfileWrite (void * context, const char * buffer, int len) { * * Close a compressed I/O channel */ -static void +static int xmlGzfileClose (void * context) { - gzclose((gzFile) context); + return ( ( gzclose((gzFile) context) == Z_OK ) ? 0 : -1 ); } #endif /* HAVE_ZLIB_H */ @@ -478,6 +481,369 @@ xmlGzfileClose (void * context) { * I/O for HTTP file accesses * * * ************************************************************************/ + +typedef struct xmlIOHTTPWriteCtxt_ +{ + int compression; + + char * uri; + + void * doc_buff; + +} xmlIOHTTPWriteCtxt, *xmlIOHTTPWriteCtxtPtr; + +#ifdef HAVE_ZLIB_H + +#define DFLT_WBITS ( -15 ) +#define DFLT_MEM_LVL ( 8 ) +#define GZ_MAGIC1 ( 0x1f ) +#define GZ_MAGIC2 ( 0x8b ) +#define LXML_ZLIB_OS_CODE ( 0x03 ) +#define INIT_HTTP_BUFF_SIZE ( 32768 ) +#define DFLT_ZLIB_RATIO ( 5 ) + +/* +** Data structure and functions to work with sending compressed data +** via HTTP. +*/ + +typedef struct xmlZMemBuff_ +{ + unsigned long size; + unsigned long crc; + + unsigned char * zbuff; + z_stream zctrl; + +} xmlZMemBuff, *xmlZMemBuffPtr; + +/** + * append_reverse_ulong + * @buff: Compressed memory buffer + * @data: Unsigned long to append + * + * Append a unsigned long in reverse byte order to the end of the + * memory buffer. + */ +static void +append_reverse_ulong( xmlZMemBuff * buff, unsigned long data ) { + + int idx; + + if ( buff == NULL ) + return; + + /* + ** This is plagiarized from putLong in gzio.c (zlib source) where + ** the number "4" is hardcoded. If zlib is ever patched to + ** support 64 bit file sizes, this code would need to be patched + ** as well. + */ + + for ( idx = 0; idx < 4; idx++ ) { + *buff->zctrl.next_out = ( data & 0xff ); + data >>= 8; + buff->zctrl.next_out++; + } + + return; +} + +/** + * + * xmlFreeZMemBuff + * @buff: The memory buffer context to clear + * + * Release all the resources associated with the compressed memory buffer. + */ +static void +xmlFreeZMemBuff( xmlZMemBuffPtr buff ) { + + int z_err; + + if ( buff == NULL ) + return; + + xmlFree( buff->zbuff ); + z_err = deflateEnd( &buff->zctrl ); +#ifdef DEBUG_HTTP + if ( z_err != Z_OK ) + xmlGenericError( xmlGenericErrorContext, + "xmlFreeZMemBuff: Error releasing zlib context: %d\n", + z_err ); +#endif + + xmlFree( buff ); + return; +} + +/** + * xmlCreateZMemBuff + *@compression: Compression value to use + * + * Create a memory buffer to hold the compressed XML document. The + * compressed document in memory will end up being identical to what + * would be created if gzopen/gzwrite/gzclose were being used to + * write the document to disk. The code for the header/trailer data to + * the compression is plagiarized from the zlib source files. + */ +static void * +xmlCreateZMemBuff( int compression ) { + + int z_err; + int hdr_lgth; + xmlZMemBuffPtr buff = NULL; + + if ( ( compression < 1 ) || ( compression > 9 ) ) + return ( NULL ); + + /* Create the control and data areas */ + + buff = xmlMalloc( sizeof( xmlZMemBuff ) ); + if ( buff == NULL ) { + xmlGenericError( xmlGenericErrorContext, + "xmlCreateZMemBuff: %s\n", + "Failure allocating buffer context." ); + return ( NULL ); + } + + (void)memset( buff, 0, sizeof( xmlZMemBuff ) ); + buff->size = INIT_HTTP_BUFF_SIZE; + buff->zbuff = xmlMalloc( buff->size ); + if ( buff->zbuff == NULL ) { + xmlFreeZMemBuff( buff ); + xmlGenericError( xmlGenericErrorContext, + "xmlCreateZMemBuff: %s\n", + "Failure allocating data buffer." ); + return ( NULL ); + } + + z_err = deflateInit2( &buff->zctrl, compression, Z_DEFLATED, + DFLT_WBITS, DFLT_MEM_LVL, Z_DEFAULT_STRATEGY ); + if ( z_err != Z_OK ) { + xmlFreeZMemBuff( buff ); + buff = NULL; + xmlGenericError( xmlGenericErrorContext, + "xmlCreateZMemBuff: %s %d\n", + "Error initializing compression context. ZLIB error:", + z_err ); + return ( NULL ); + } + + /* Set the header data. The CRC will be needed for the trailer */ + + buff->crc = crc32( 0L, Z_NULL, 0 ); + hdr_lgth = sprintf( (char *)buff->zbuff, "%c%c%c%c%c%c%c%c%c%c", + GZ_MAGIC1, GZ_MAGIC2, Z_DEFLATED, + 0, 0, 0, 0, 0, 0, LXML_ZLIB_OS_CODE ); + buff->zctrl.next_out = buff->zbuff + hdr_lgth; + buff->zctrl.avail_out = buff->size - hdr_lgth; + + return ( buff ); +} + +/** + * xmlZMemBuffExtend + * @buff: Buffer used to compress and consolidate data. + * @ext_amt: Number of bytes to extend the buffer. + * + * Extend the internal buffer used to store the compressed data by the + * specified amount. + * + * Returns 0 on success or -1 on failure to extend the buffer. On failure + * the original buffer still exists at the original size. + */ +static int +xmlZMemBuffExtend( xmlZMemBuffPtr buff, size_t ext_amt ) { + + int rc = -1; + size_t new_size; + size_t cur_used; + + unsigned char * tmp_ptr = NULL; + + if ( buff == NULL ) + return ( -1 ); + + else if ( ext_amt == 0 ) + return ( 0 ); + + cur_used = buff->zctrl.next_out - buff->zbuff; + new_size = buff->size + ext_amt; + +#ifdef DEBUG_HTTP + if ( cur_used > new_size ) + xmlGenericError( xmlGenericErrorContext, + "xmlZMemBuffExtend: %s\n%s %d bytes.\n", + "Buffer overwrite detected during compressed memory", + "buffer extension. Overflowed by", + (cur_used - new_size ) ); +#endif + + tmp_ptr = xmlRealloc( buff->zbuff, new_size ); + if ( tmp_ptr != NULL ) { + rc = 0; + buff->size = new_size; + buff->zbuff = tmp_ptr; + buff->zctrl.next_out = tmp_ptr + cur_used; + buff->zctrl.avail_out = new_size - cur_used; + } + else { + xmlGenericError( xmlGenericErrorContext, + "xmlZMemBuffExtend: %s %lu bytes.\n", + "Allocation failure extending output buffer to", + new_size ); + } + + return ( rc ); +} + +/** + * xmlZMemBuffAppend + * @buff: Buffer used to compress and consolidate data + * @src: Uncompressed source content to append to buffer + * @len: Length of source data to append to buffer + * + * Compress and append data to the internal buffer. The data buffer + * will be expanded if needed to store the additional data. + * + * Returns the number of bytes appended to the buffer or -1 on error. + */ +static int +xmlZMemBuffAppend( xmlZMemBuffPtr buff, const char * src, int len ) { + + int z_err; + size_t min_accept; + + if ( ( buff == NULL ) || ( src == NULL ) ) + return ( -1 ); + + buff->zctrl.avail_in = len; + buff->zctrl.next_in = (unsigned char *)src; + while ( buff->zctrl.avail_in > 0 ) { + /* + ** Extend the buffer prior to deflate call if a reasonable amount + ** of output buffer space is not available. + */ + min_accept = buff->zctrl.avail_in / DFLT_ZLIB_RATIO; + if ( buff->zctrl.avail_out <= min_accept ) { + if ( xmlZMemBuffExtend( buff, buff->size ) == -1 ) + return ( -1 ); + } + + z_err = deflate( &buff->zctrl, Z_NO_FLUSH ); + if ( z_err != Z_OK ) { + xmlGenericError( xmlGenericErrorContext, + "xmlZMemBuffAppend: %s %d %s - %d", + "Compression error while appending", + len, "bytes to buffer. ZLIB error", z_err ); + return ( -1 ); + } + } + + buff->crc = crc32( buff->crc, (unsigned char *)src, len ); + + return ( len ); +} + +/** + * xmlZMemBuffGetContent + * @buff: Compressed memory content buffer + * @data_ref: Pointer reference to point to compressed content + * + * Flushes the compression buffers, appends gzip file trailers and + * returns the compressed content and length of the compressed data. + * NOTE: The gzip trailer code here is plagiarized from zlib source. + * + * Returns the length of the compressed data or -1 on error. + */ +static int +xmlZMemBuffGetContent( xmlZMemBuffPtr buff, char ** data_ref ) { + + int zlgth = -1; + int z_err; + + if ( ( buff == NULL ) || ( data_ref == NULL ) ) + return ( -1 ); + + /* Need to loop until compression output buffers are flushed */ + + do + { + z_err = deflate( &buff->zctrl, Z_FINISH ); + if ( z_err == Z_OK ) { + /* In this case Z_OK means more buffer space needed */ + + if ( xmlZMemBuffExtend( buff, buff->size ) == -1 ) + return ( -1 ); + } + } + while ( z_err == Z_OK ); + + /* If the compression state is not Z_STREAM_END, some error occurred */ + + if ( z_err == Z_STREAM_END ) { + + /* Need to append the gzip data trailer */ + + if ( buff->zctrl.avail_out < ( 2 * sizeof( unsigned long ) ) ) { + if ( xmlZMemBuffExtend(buff, (2 * sizeof(unsigned long))) == -1 ) + return ( -1 ); + } + + /* + ** For whatever reason, the CRC and length data are pushed out + ** in reverse byte order. So a memcpy can't be used here. + */ + + append_reverse_ulong( buff, buff->crc ); + append_reverse_ulong( buff, buff->zctrl.total_in ); + + zlgth = buff->zctrl.next_out - buff->zbuff; + *data_ref = (char *)buff->zbuff; + } + + else + xmlGenericError( xmlGenericErrorContext, + "xmlZMemBuffGetContent: %s - %d\n", + "Error flushing zlib buffers. Error code", z_err ); + + return ( zlgth ); +} +#endif /* HAVE_ZLIB_H */ + +/** + * xmlFreeHTTPWriteCtxt + * @ctxt: Context to cleanup + * + * Free allocated memory and reclaim system resources. + * + * No return value. + */ +static void +xmlFreeHTTPWriteCtxt( xmlIOHTTPWriteCtxtPtr ctxt ) +{ + if ( ctxt->uri != NULL ) + free( ctxt->uri ); + + if ( ctxt->doc_buff != NULL ) { + +#ifdef HAVE_ZLIB_H + if ( ctxt->compression > 0 ) { + xmlFreeZMemBuff( ctxt->doc_buff ); + } + else +#endif + { + xmlOutputBufferClose( ctxt->doc_buff ); + } + } + + free( ctxt ); + return; +} + + /** * xmlIOHTTPMatch: * @filename: the URI for matching @@ -506,6 +872,85 @@ xmlIOHTTPOpen (const char *filename) { return(xmlNanoHTTPOpen(filename, NULL)); } +/** + * xmlIOHTTPOpenW + * @post_uri: The destination URI for the document + * @compression: The compression desired for the document. + * + * Open a temporary buffer to collect the document for a subsequent HTTP POST + * request. Non-static as is called from the output buffer creation routine. + * + * Returns an I/O context or NULL in case of error. + */ + +void * +xmlIOHTTPOpenW( const char * post_uri, int compression ) { + + xmlIOHTTPWriteCtxtPtr ctxt = NULL; + + if ( post_uri == NULL ) + return ( NULL ); + + ctxt = xmlMalloc( sizeof( xmlIOHTTPWriteCtxt ) ); + if ( ctxt == NULL ) { + xmlGenericError( xmlGenericErrorContext, + "xmlIOHTTPOpenW: Failed to create output HTTP context.\n" ); + return ( NULL ); + } + + (void)memset( ctxt, 0, sizeof( xmlIOHTTPWriteCtxt ) ); + + ctxt->uri = strdup( post_uri ); + if ( ctxt->uri == NULL ) { + xmlGenericError( xmlGenericErrorContext, + "xmlIOHTTPOpenW: Failed to duplicate destination URI.\n" ); + xmlFreeHTTPWriteCtxt( ctxt ); + return ( NULL ); + } + + /* + ** Since the document length is required for an HTTP post, + ** need to put the document into a buffer. A memory buffer + ** is being used to avoid pushing the data to disk and back. + */ + +#ifdef HAVE_ZLIB_H + if ( ( compression > 0 ) && ( compression <= 9 ) ) { + + ctxt->compression = compression; + ctxt->doc_buff = xmlCreateZMemBuff( compression ); + } + else +#endif + { + /* Any character conversions should have been done before this */ + + ctxt->doc_buff = xmlAllocOutputBuffer( NULL ); + } + + if ( ctxt->doc_buff == NULL ) { + xmlFreeHTTPWriteCtxt( ctxt ); + ctxt = NULL; + } + + return ( ctxt ); +} + +/** + * xmlIOHTTPDfltOpenW + * @post_uri: The destination URI for this document. + * + * Calls xmlIOHTTPOpenW with no compression to set up for a subsequent + * HTTP post command. This function should generally not be used as + * the open callback is short circuited in xmlOutputBufferCreateFile. + * + * Returns a pointer to the new IO context. + */ +static void * +xmlIOHTTPDfltOpenW( const char * post_uri ) { + return ( xmlIOHTTPOpenW( post_uri, 0 ) ); +} + /** * xmlIOHTTPRead: * @context: the I/O context @@ -521,16 +966,220 @@ xmlIOHTTPRead(void * context, char * buffer, int len) { return(xmlNanoHTTPRead(context, &buffer[0], len)); } +/** + * xmlIOHTTPWrite + * @context: previously opened writing context + * @buffer: data to output to temporary buffer + * @len: bytes to output + * + * Collect data from memory buffer into a temporary file for later + * processing. + * + * Returns number of bytes written. + */ + +static int +xmlIOHTTPWrite( void * context, const char * buffer, int len ) { + + xmlIOHTTPWriteCtxtPtr ctxt = context; + + if ( ( ctxt == NULL ) || ( ctxt->doc_buff == NULL ) || ( buffer == NULL ) ) + return ( -1 ); + + if ( len > 0 ) { + + /* Use gzwrite or fwrite as previously setup in the open call */ + +#ifdef HAVE_ZLIB_H + if ( ctxt->compression > 0 ) + len = xmlZMemBuffAppend( ctxt->doc_buff, buffer, len ); + + else +#endif + len = xmlOutputBufferWrite( ctxt->doc_buff, len, buffer ); + + if ( len < 0 ) { + xmlGenericError( xmlGenericErrorContext, + "xmlIOHTTPWrite: %s\n%s '%s'.\n", + "Error appending to internal buffer.", + "Error sending document to URI", + ctxt->uri ); + } + } + + return ( len ); +} + + /** * xmlIOHTTPClose: * @context: the I/O context * * Close an HTTP I/O channel */ -static void +static int xmlIOHTTPClose (void * context) { xmlNanoHTTPClose(context); + return 0; } + +/** + * xmlIOHTTCloseWrite + * @context: The I/O context + * @http_mthd: The HTTP method to be used when sending the data + * + * Close the transmit HTTP I/O channel and actually send the data. + */ +static int +xmlIOHTTPCloseWrite( void * context, const char * http_mthd ) { + + int close_rc = -1; + int http_rtn = 0; + int content_lgth = 0; + xmlIOHTTPWriteCtxtPtr ctxt = context; + + char * http_content = NULL; + char * content_encoding = NULL; + char * content_type = (char *) "text/xml"; + void * http_ctxt = NULL; + + if ( ( ctxt == NULL ) || ( http_mthd == NULL ) ) + return ( -1 ); + + /* Retrieve the content from the appropriate buffer */ + +#ifdef HAVE_ZLIB_H + + if ( ctxt->compression > 0 ) { + content_lgth = xmlZMemBuffGetContent( ctxt->doc_buff, &http_content ); + content_encoding = (char *) "Content-Encoding: gzip"; + } + else +#endif + { + /* Pull the data out of the memory output buffer */ + + xmlOutputBufferPtr dctxt = ctxt->doc_buff; + http_content = (char *)dctxt->buffer->content; + content_lgth = dctxt->buffer->use; + } + + if ( http_content == NULL ) { + xmlGenericError( xmlGenericErrorContext, + "xmlIOHTTPCloseWrite: %s '%s' %s '%s'.\n", + "Error retrieving content.\nUnable to", + http_mthd, "data to URI", ctxt->uri ); + } + + else { + + http_ctxt = xmlNanoHTTPMethod( ctxt->uri, http_mthd, http_content, + &content_type, content_encoding, + content_lgth ); + + if ( http_ctxt != NULL ) { +#ifdef DEBUG_HTTP + /* If testing/debugging - dump reply with request content */ + + FILE * tst_file = NULL; + char buffer[ 4096 ]; + char * dump_name = NULL; + int avail; + + xmlGenericError( xmlGenericErrorContext, + "xmlNanoHTTPCloseWrite: HTTP %s to\n%s returned %d.\n", + http_mthd, ctxt->uri, + xmlNanoHTTPReturnCode( http_ctxt ) ); + + /* + ** Since either content or reply may be gzipped, + ** dump them to separate files instead of the + ** standard error context. + */ + + dump_name = tempnam( NULL, "lxml" ); + if ( dump_name != NULL ) { + (void)sprintf( buffer, "%s.content", dump_name ); + + tst_file = fopen( buffer, "w" ); + if ( tst_file != NULL ) { + xmlGenericError( xmlGenericErrorContext, + "Transmitted content saved in file: %s\n", buffer ); + + fwrite( http_content, sizeof( char ), + content_lgth, tst_file ); + fclose( tst_file ); + } + + (void)sprintf( buffer, "%s.reply", dump_name ); + tst_file = fopen( buffer, "w" ); + if ( tst_file != NULL ) { + xmlGenericError( xmlGenericErrorContext, + "Reply content saved in file: %s\n", buffer ); + + + while ( (avail = xmlNanoHTTPRead( http_ctxt, + buffer, sizeof( buffer ) )) > 0 ) { + + fwrite( buffer, sizeof( char ), avail, tst_file ); + } + + fclose( tst_file ); + } + + free( dump_name ); + } +#endif /* DEBUG_HTTP */ + + http_rtn = xmlNanoHTTPReturnCode( http_ctxt ); + if ( ( http_rtn >= 200 ) && ( http_rtn < 300 ) ) + close_rc = 0; + else + xmlGenericError( xmlGenericErrorContext, + "xmlIOHTTPClose: HTTP '%s' of %d %s\n'%s' %s %d\n", + http_mthd, content_lgth, + "bytes to URI", ctxt->uri, + "failed. HTTP return code:", http_rtn ); + + xmlNanoHTTPClose( http_ctxt ); + xmlFree( content_type ); + } + } + + /* Final cleanups */ + + xmlFreeHTTPWriteCtxt( ctxt ); + + return ( close_rc ); +} + +/** + * xmlIOHTTPClosePut + * + * @context: The I/O context + * + * Close the transmit HTTP I/O channel and actually send data using a PUT + * HTTP method. + */ +static int +xmlIOHTTPClosePut( void * ctxt ) { + return ( xmlIOHTTPCloseWrite( ctxt, "PUT" ) ); +} + + +/** + * xmlIOHTTPClosePost + * + * @context: The I/O context + * + * Close the transmit HTTP I/O channel and actually send data using a POST + * HTTP method. + */ +static int +xmlIOHTTPClosePost( void * ctxt ) { + return ( xmlIOHTTPCloseWrite( ctxt, "POST" ) ); +} + #endif /* LIBXML_HTTP_ENABLED */ #ifdef LIBXML_FTP_ENABLED @@ -588,9 +1237,9 @@ xmlIOFTPRead(void * context, char * buffer, int len) { * * Close an FTP I/O channel */ -static void +static int xmlIOFTPClose (void * context) { - xmlNanoFTPClose(context); + return ( xmlNanoFTPClose(context) ); } #endif /* LIBXML_FTP_ENABLED */ @@ -696,6 +1345,12 @@ xmlRegisterDefaultOutputCallbacks xmlRegisterOutputCallbacks(xmlFileMatch, xmlFileOpenW, xmlFileWrite, xmlFileClose); + +#ifdef LIBXML_HTTP_ENABLED + xmlRegisterOutputCallbacks(xmlIOHTTPMatch, xmlIOHTTPDfltOpenW, + xmlIOHTTPWrite, xmlIOHTTPClosePut); +#endif + /********************************* No way a-priori to distinguish between gzipped files from uncompressed ones except opening if existing then closing @@ -705,12 +1360,6 @@ xmlRegisterDefaultOutputCallbacks xmlRegisterOutputCallbacks(xmlGzfileMatch, xmlGzfileOpen, xmlGzfileWrite, xmlGzfileClose); #endif - No HTTP PUT support yet, patches welcome - -#ifdef LIBXML_HTTP_ENABLED - xmlRegisterOutputCallbacks(xmlIOHTTPMatch, xmlIOHTTPOpen, - xmlIOHTTPWrite, xmlIOHTTPClose); -#endif Nor FTP PUT .... #ifdef LIBXML_FTP_ENABLED @@ -721,6 +1370,29 @@ xmlRegisterDefaultOutputCallbacks xmlOutputCallbackInitialized = 1; } +#ifdef LIBXML_HTTP_ENABLED +/** + * xmlRegisterHTTPPostCallbacks + * + * By default, libxml submits HTTP output requests using the "PUT" method. + * Calling this method changes the HTTP output method to use the "POST" + * method instead. + * + */ +void +xmlRegisterHTTPPostCallbacks( void ) { + + /* Register defaults if not done previously */ + + if ( xmlOutputCallbackInitialized == 0 ) + xmlRegisterDefaultOutputCallbacks( ); + + xmlRegisterOutputCallbacks(xmlIOHTTPMatch, xmlIOHTTPDfltOpenW, + xmlIOHTTPWrite, xmlIOHTTPClosePost); + return; +} +#endif + /** * xmlAllocParserInputBuffer: * @enc: the charset encoding if known @@ -838,13 +1510,14 @@ xmlFreeParserInputBuffer(xmlParserInputBufferPtr in) { int xmlOutputBufferClose(xmlOutputBufferPtr out) { int written; + int err_rc = 0; if (out == NULL) return(-1); if (out->writecallback != NULL) xmlOutputBufferFlush(out); if (out->closecallback != NULL) { - out->closecallback(out->context); + err_rc = out->closecallback(out->context); } written = out->written; if (out->conv) { @@ -860,7 +1533,7 @@ xmlOutputBufferClose(xmlOutputBufferPtr out) { } xmlFree(out); - return(written); + return( ( err_rc == 0 ) ? written : err_rc ); } /** @@ -973,13 +1646,21 @@ xmlOutputBufferCreateFilename(const char *URI, int i; void *context = NULL; + int is_http_uri = 0; /* Can't change if HTTP disabled */ + if (xmlOutputCallbackInitialized == 0) xmlRegisterDefaultOutputCallbacks(); if (URI == NULL) return(NULL); +#ifdef LIBXML_HTTP_ENABLED + /* Need to prevent HTTP URI's from falling into zlib short circuit */ + + is_http_uri = xmlIOHTTPMatch( URI ); +#endif + #ifdef HAVE_ZLIB_H - if ((compression > 0) && (compression <= 9)) { + if ((compression > 0) && (compression <= 9) && (is_http_uri == 0)) { context = xmlGzfileOpenW(URI, compression); if (context != NULL) { ret = xmlAllocOutputBuffer(encoder); @@ -994,17 +1675,27 @@ xmlOutputBufferCreateFilename(const char *URI, #endif /* - * Try to find one of the output accept method accepting taht scheme + * Try to find one of the output accept method accepting that scheme * Go in reverse to give precedence to user defined handlers. */ for (i = xmlOutputCallbackNr - 1;i >= 0;i--) { if ((xmlOutputCallbackTable[i].matchcallback != NULL) && (xmlOutputCallbackTable[i].matchcallback(URI) != 0)) { - context = xmlOutputCallbackTable[i].opencallback(URI); + +#if ( defined( LIBXML_HTTP_ENABLED ) && defined( HAVE_ZLIB_H ) ) + /* Need to pass compression parameter into HTTP open calls */ + + if ( xmlOutputCallbackTable[i].matchcallback == xmlIOHTTPMatch ) + context = xmlIOHTTPOpenW( URI, compression ); + else +#endif + context = xmlOutputCallbackTable[i].opencallback(URI); + if (context != NULL) break; } } + if (context == NULL) { return(NULL); } @@ -1624,7 +2315,7 @@ xmlDefaultExternalEntityLoader(const char *URL, const char *ID, #ifdef DEBUG_EXTERNAL_ENTITIES xmlGenericError(xmlGenericErrorContext, - "xmlDefaultExternalEntityLoader(%s, %s)\n", URL, ID); + "xmlDefaultExternalEntityLoader(%s, xxx)\n", URL); #endif #ifdef LIBXML_CATALOG_ENABLED /*